]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #96107 - Gumichocopengin8:test/vec-deque, r=Mark-Simulacrum
authorMatthias Krüger <matthias.krueger@famsik.de>
Sun, 24 Apr 2022 22:11:00 +0000 (00:11 +0200)
committerGitHub <noreply@github.com>
Sun, 24 Apr 2022 22:11:00 +0000 (00:11 +0200)
[test] Add test cases for untested functions for VecDeque

Added test cases of the following functions
- get
- get_mut
- swap
- reserve_exact
- try_reserve_exact
- try_reserve
- contains
- rotate_left
- rotate_right
- binary_search
- binary_search_by
- binary_search_by_key

918 files changed:
.github/workflows/ci.yml
Cargo.lock
compiler/rustc_ast/src/ast.rs
compiler/rustc_ast/src/attr/mod.rs
compiler/rustc_ast/src/mut_visit.rs
compiler/rustc_ast/src/tokenstream.rs
compiler/rustc_ast/src/util/comments.rs
compiler/rustc_ast/src/visit.rs
compiler/rustc_ast_lowering/src/asm.rs
compiler/rustc_ast_lowering/src/index.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/src/ast_validation.rs
compiler/rustc_ast_passes/src/feature_gate.rs
compiler/rustc_ast_pretty/src/pprust/state.rs
compiler/rustc_ast_pretty/src/pprust/state/expr.rs
compiler/rustc_borrowck/src/constraints/graph.rs
compiler/rustc_borrowck/src/constraints/mod.rs
compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
compiler/rustc_borrowck/src/diagnostics/region_errors.rs
compiler/rustc_borrowck/src/diagnostics/region_name.rs
compiler/rustc_borrowck/src/region_infer/dump_mir.rs
compiler/rustc_borrowck/src/region_infer/mod.rs
compiler/rustc_borrowck/src/type_check/constraint_conversion.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/src/asm.rs
compiler/rustc_codegen_cranelift/Cargo.lock
compiler/rustc_codegen_cranelift/Cargo.toml
compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock
compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/example/mini_core.rs
compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
compiler/rustc_codegen_cranelift/example/std_example.rs
compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch
compiler/rustc_codegen_cranelift/rust-toolchain
compiler/rustc_codegen_cranelift/scripts/filter_profile.rs
compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
compiler/rustc_codegen_cranelift/scripts/tests.sh
compiler/rustc_codegen_cranelift/src/base.rs
compiler/rustc_codegen_cranelift/src/cast.rs
compiler/rustc_codegen_cranelift/src/config.rs
compiler/rustc_codegen_cranelift/src/discriminant.rs
compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
compiler/rustc_codegen_cranelift/src/lib.rs
compiler/rustc_codegen_cranelift/src/num.rs
compiler/rustc_codegen_gcc/src/asm.rs
compiler/rustc_codegen_gcc/src/back/write.rs
compiler/rustc_codegen_llvm/src/asm.rs
compiler/rustc_codegen_llvm/src/back/lto.rs
compiler/rustc_codegen_llvm/src/back/write.rs
compiler/rustc_codegen_llvm/src/base.rs
compiler/rustc_codegen_llvm/src/consts.rs
compiler/rustc_codegen_llvm/src/context.rs
compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
compiler/rustc_codegen_llvm/src/intrinsic.rs
compiler/rustc_codegen_llvm/src/llvm/ffi.rs
compiler/rustc_codegen_ssa/src/back/link.rs
compiler/rustc_codegen_ssa/src/back/symbol_export.rs
compiler/rustc_codegen_ssa/src/mir/place.rs
compiler/rustc_codegen_ssa/src/mono_item.rs
compiler/rustc_codegen_ssa/src/traits/asm.rs
compiler/rustc_codegen_ssa/src/traits/mod.rs
compiler/rustc_const_eval/src/const_eval/eval_queries.rs
compiler/rustc_const_eval/src/const_eval/mod.rs
compiler/rustc_const_eval/src/interpret/eval_context.rs
compiler/rustc_const_eval/src/interpret/machine.rs
compiler/rustc_const_eval/src/interpret/memory.rs
compiler/rustc_const_eval/src/interpret/place.rs
compiler/rustc_const_eval/src/interpret/step.rs
compiler/rustc_const_eval/src/interpret/validity.rs
compiler/rustc_const_eval/src/transform/validate.rs
compiler/rustc_data_structures/src/flock.rs
compiler/rustc_data_structures/src/flock/linux.rs [new file with mode: 0644]
compiler/rustc_data_structures/src/flock/unix.rs [new file with mode: 0644]
compiler/rustc_data_structures/src/flock/unsupported.rs [new file with mode: 0644]
compiler/rustc_data_structures/src/flock/windows.rs [new file with mode: 0644]
compiler/rustc_data_structures/src/lib.rs
compiler/rustc_data_structures/src/profiling.rs
compiler/rustc_data_structures/src/stable_hasher.rs
compiler/rustc_error_messages/src/lib.rs
compiler/rustc_errors/src/diagnostic.rs
compiler/rustc_errors/src/json.rs
compiler/rustc_errors/src/lib.rs
compiler/rustc_expand/src/mbe/macro_parser.rs
compiler/rustc_expand/src/proc_macro.rs
compiler/rustc_hir/src/def.rs
compiler/rustc_hir/src/definitions.rs
compiler/rustc_hir/src/hir.rs
compiler/rustc_hir/src/hir_id.rs
compiler/rustc_hir/src/intravisit.rs
compiler/rustc_hir/src/target.rs
compiler/rustc_hir_pretty/src/lib.rs
compiler/rustc_incremental/src/assert_dep_graph.rs
compiler/rustc_incremental/src/persist/dirty_clean.rs
compiler/rustc_infer/src/infer/combine.rs
compiler/rustc_infer/src/infer/equate.rs
compiler/rustc_infer/src/infer/error_reporting/mod.rs
compiler/rustc_infer/src/infer/mod.rs
compiler/rustc_interface/src/passes.rs
compiler/rustc_interface/src/proc_macro_decls.rs
compiler/rustc_interface/src/tests.rs
compiler/rustc_lint/Cargo.toml
compiler/rustc_lint/src/builtin.rs
compiler/rustc_lint/src/context.rs
compiler/rustc_lint/src/early.rs
compiler/rustc_lint/src/nonstandard_style.rs
compiler/rustc_lint_defs/src/builtin.rs
compiler/rustc_lint_defs/src/lib.rs
compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
compiler/rustc_macros/src/session_diagnostic.rs
compiler/rustc_metadata/src/creader.rs
compiler/rustc_metadata/src/foreign_modules.rs
compiler/rustc_metadata/src/lib.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/encoder.rs
compiler/rustc_metadata/src/rmeta/mod.rs
compiler/rustc_metadata/src/rmeta/table.rs
compiler/rustc_middle/src/dep_graph/dep_node.rs
compiler/rustc_middle/src/hir/map/mod.rs
compiler/rustc_middle/src/hir/mod.rs
compiler/rustc_middle/src/middle/stability.rs
compiler/rustc_middle/src/mir/interpret/allocation.rs
compiler/rustc_middle/src/mir/interpret/pointer.rs
compiler/rustc_middle/src/mir/mod.rs
compiler/rustc_middle/src/mir/pretty.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/thir.rs
compiler/rustc_middle/src/thir/visit.rs
compiler/rustc_middle/src/ty/consts.rs
compiler/rustc_middle/src/ty/consts/valtree.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_middle/src/ty/print/pretty.rs
compiler/rustc_middle/src/ty/query.rs
compiler/rustc_middle/src/ty/relate.rs
compiler/rustc_middle/src/ty/structural_impls.rs
compiler/rustc_mir_build/src/build/expr/into.rs
compiler/rustc_mir_build/src/build/mod.rs
compiler/rustc_mir_build/src/thir/cx/expr.rs
compiler/rustc_mir_build/src/thir/pattern/check_match.rs
compiler/rustc_mir_transform/src/const_prop.rs
compiler/rustc_mir_transform/src/const_prop_lint.rs
compiler/rustc_mir_transform/src/pass_manager.rs
compiler/rustc_monomorphize/src/collector.rs
compiler/rustc_monomorphize/src/partitioning/default.rs
compiler/rustc_parse/src/lexer/mod.rs
compiler/rustc_parse/src/parser/attr_wrapper.rs
compiler/rustc_parse/src/parser/mod.rs
compiler/rustc_parse/src/parser/nonterminal.rs
compiler/rustc_parse/src/parser/ty.rs
compiler/rustc_passes/src/check_attr.rs
compiler/rustc_passes/src/dead.rs
compiler/rustc_passes/src/entry.rs
compiler/rustc_passes/src/hir_id_validator.rs
compiler/rustc_passes/src/intrinsicck.rs
compiler/rustc_passes/src/lang_items.rs
compiler/rustc_passes/src/liveness.rs
compiler/rustc_passes/src/naked_functions.rs
compiler/rustc_passes/src/stability.rs
compiler/rustc_passes/src/weak_lang_items.rs
compiler/rustc_privacy/src/lib.rs
compiler/rustc_query_impl/src/profiling_support.rs
compiler/rustc_resolve/src/build_reduced_graph.rs
compiler/rustc_resolve/src/def_collector.rs
compiler/rustc_resolve/src/diagnostics.rs
compiler/rustc_resolve/src/ident.rs
compiler/rustc_resolve/src/imports.rs
compiler/rustc_resolve/src/late.rs
compiler/rustc_resolve/src/late/diagnostics.rs
compiler/rustc_resolve/src/late/lifetimes.rs
compiler/rustc_resolve/src/lib.rs
compiler/rustc_save_analysis/src/dump_visitor.rs
compiler/rustc_save_analysis/src/lib.rs
compiler/rustc_session/src/config.rs
compiler/rustc_session/src/options.rs
compiler/rustc_session/src/search_paths.rs
compiler/rustc_session/src/utils.rs
compiler/rustc_span/src/def_id.rs
compiler/rustc_span/src/hygiene.rs
compiler/rustc_span/src/lib.rs
compiler/rustc_span/src/profiling.rs [new file with mode: 0644]
compiler/rustc_span/src/symbol.rs
compiler/rustc_symbol_mangling/src/test.rs
compiler/rustc_target/src/asm/mod.rs
compiler/rustc_target/src/asm/x86.rs
compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
compiler/rustc_typeck/src/astconv/errors.rs
compiler/rustc_typeck/src/astconv/mod.rs
compiler/rustc_typeck/src/check/cast.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/arg_matrix.rs [new file with mode: 0644]
compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs
compiler/rustc_typeck/src/check/intrinsic.rs
compiler/rustc_typeck/src/check/mod.rs
compiler/rustc_typeck/src/check/pat.rs
compiler/rustc_typeck/src/check_unused.rs
compiler/rustc_typeck/src/coherence/orphan.rs
compiler/rustc_typeck/src/collect.rs
compiler/rustc_typeck/src/collect/type_of.rs
compiler/rustc_typeck/src/errors.rs
compiler/rustc_typeck/src/expr_use_visitor.rs
compiler/rustc_typeck/src/lib.rs
compiler/rustc_typeck/src/outlives/implicit_infer.rs
compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
config.toml.example
library/alloc/src/collections/btree/map/tests.rs
library/alloc/src/macros.rs
library/alloc/src/rc.rs
library/alloc/src/vec/mod.rs
library/core/benches/ascii/is_ascii.rs
library/core/src/char/methods.rs
library/core/src/intrinsics.rs
library/core/src/iter/traits/collect.rs
library/core/src/iter/traits/iterator.rs
library/core/src/lib.rs
library/core/src/mem/maybe_uninit.rs
library/core/src/num/f32.rs
library/core/src/num/f64.rs
library/core/src/num/mod.rs
library/core/src/ptr/const_ptr.rs
library/core/src/ptr/mut_ptr.rs
library/core/src/ptr/non_null.rs
library/core/src/ptr/unique.rs
library/core/src/slice/ascii.rs
library/core/src/slice/iter.rs
library/core/src/slice/memchr.rs
library/core/src/str/count.rs
library/core/src/str/validations.rs
library/core/tests/hash/sip.rs
library/core/tests/lib.rs
library/core/tests/slice.rs
library/portable-simd/crates/core_simd/src/intrinsics.rs
library/portable-simd/crates/core_simd/src/vector/ptr.rs
library/proc_macro/Cargo.toml
library/std/src/lib.rs
library/std/src/net/parser.rs
library/std/src/os/unix/process.rs
library/std/src/path.rs
library/std/src/path/tests.rs
library/std/src/sys/hermit/mutex.rs
library/std/src/sys/itron/mutex.rs
library/std/src/sys/sgx/mutex.rs
library/std/src/sys/unix/fd.rs
library/std/src/sys/unix/fs.rs
library/std/src/sys/unix/futex.rs
library/std/src/sys/unix/locks/futex.rs
library/std/src/sys/unix/locks/mod.rs
library/std/src/sys/unix/locks/pthread_remutex.rs [deleted file]
library/std/src/sys/unix/os.rs
library/std/src/sys/unix/process/process_common/tests.rs
library/std/src/sys/unix/process/process_unix.rs
library/std/src/sys/unix/weak.rs
library/std/src/sys/unsupported/locks/mod.rs
library/std/src/sys/unsupported/locks/mutex.rs
library/std/src/sys/wasm/atomics/condvar.rs [deleted file]
library/std/src/sys/wasm/atomics/futex.rs
library/std/src/sys/wasm/atomics/mutex.rs [deleted file]
library/std/src/sys/wasm/atomics/rwlock.rs [deleted file]
library/std/src/sys/wasm/atomics/thread.rs
library/std/src/sys/wasm/mod.rs
library/std/src/sys/windows/c.rs
library/std/src/sys/windows/locks/mod.rs
library/std/src/sys/windows/locks/mutex.rs
library/std/src/sys/windows/mod.rs
library/std/src/sys/windows/path.rs
library/std/src/sys/windows/path/tests.rs
library/std/src/sys_common/remutex.rs
library/std/src/thread/local.rs
src/bootstrap/bin/rustdoc.rs
src/bootstrap/bootstrap.py
src/bootstrap/builder.rs
src/bootstrap/builder/tests.rs
src/bootstrap/cc_detect.rs
src/bootstrap/check.rs
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/dist.rs
src/bootstrap/doc.rs
src/bootstrap/flags.rs
src/bootstrap/install.rs
src/bootstrap/native.rs
src/bootstrap/tarball.rs
src/bootstrap/test.rs
src/bootstrap/toolstate.rs
src/ci/github-actions/ci.yml
src/doc/book
src/doc/embedded-book
src/doc/nomicon
src/doc/reference
src/doc/rust-by-example
src/doc/rustc-dev-guide
src/doc/rustc/src/SUMMARY.md
src/doc/rustc/src/platform-support.md
src/doc/unstable-book/src/compiler-flags/extern-location.md [deleted file]
src/doc/unstable-book/src/language-features/doc-cfg.md
src/etc/gdb_providers.py
src/etc/htmldocck.py
src/etc/lldb_providers.py
src/etc/natvis/liballoc.natvis
src/etc/natvis/libcore.natvis
src/etc/natvis/libstd.natvis
src/librustdoc/Cargo.toml
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/blanket_impl.rs
src/librustdoc/clean/cfg.rs
src/librustdoc/clean/cfg/tests.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/clean/types/tests.rs [new file with mode: 0644]
src/librustdoc/clean/utils.rs
src/librustdoc/core.rs
src/librustdoc/doctest.rs
src/librustdoc/formats/cache.rs
src/librustdoc/formats/mod.rs
src/librustdoc/html/format.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/write_shared.rs
src/librustdoc/html/static/js/externs.js
src/librustdoc/html/static/js/search.js
src/librustdoc/json/conversions.rs
src/librustdoc/json/mod.rs
src/librustdoc/lib.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/check_doc_test_visibility.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/passes/collect_intra_doc_links/early.rs
src/librustdoc/passes/collect_trait_impls.rs
src/librustdoc/passes/html_tags.rs
src/librustdoc/passes/mod.rs
src/librustdoc/passes/strip_hidden.rs
src/librustdoc/passes/stripper.rs
src/librustdoc/passes/unindent_comments.rs [deleted file]
src/librustdoc/passes/unindent_comments/tests.rs [deleted file]
src/librustdoc/visit_lib.rs
src/llvm-project
src/test/assembly/asm/global_asm.rs
src/test/codegen/asm-clobber_abi.rs
src/test/codegen/set-discriminant-invalid.rs
src/test/codegen/simd_arith_offset.rs [new file with mode: 0644]
src/test/codegen/vec-clear.rs [deleted file]
src/test/codegen/vec-in-place.rs
src/test/debuginfo/unit-type.rs [new file with mode: 0644]
src/test/incremental/hashes/enum_defs.rs
src/test/incremental/hashes/inherent_impls.rs
src/test/incremental/hashes/statics.rs
src/test/incremental/hashes/struct_defs.rs
src/test/incremental/hashes/trait_defs.rs
src/test/mir-opt/combine_clone_of_primitives.rs
src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff
src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
src/test/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
src/test/mir-opt/early_otherwise_branch.rs
src/test/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
src/test/mir-opt/early_otherwise_branch_3_element_tuple.rs
src/test/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
src/test/mir-opt/early_otherwise_branch_noopt.rs
src/test/mir-opt/early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff
src/test/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff
src/test/mir-opt/early_otherwise_branch_soundness.rs
src/test/mir-opt/if-condition-int.rs
src/test/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff
src/test/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff
src/test/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff
src/test/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff
src/test/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff
src/test/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff
src/test/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff
src/test/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff
src/test/mir-opt/inline/inline_diverging.h.Inline.diff
src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff
src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff
src/test/mir-opt/issue_72181_1.main.mir_map.0.mir
src/test/mir-opt/lower_slice_len.rs
src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir
src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
src/test/mir-opt/nrvo-simple.rs
src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff
src/test/mir-opt/storage_ranges.main.nll.0.mir
src/test/pretty/hir-pretty-loop.pp
src/test/pretty/issue-4264.pp
src/test/pretty/stmt_expr_attributes.rs
src/test/run-make-fulldeps/hotplug_codegen_backend/Makefile
src/test/rustdoc-gui/item-info-overflow.goml
src/test/rustdoc-gui/item-info-width.goml
src/test/rustdoc-js-std/filter-crate.js
src/test/rustdoc-js-std/parser-errors.js [new file with mode: 0644]
src/test/rustdoc-js-std/parser-filter.js [new file with mode: 0644]
src/test/rustdoc-js-std/parser-generics.js [new file with mode: 0644]
src/test/rustdoc-js-std/parser-literal.js [new file with mode: 0644]
src/test/rustdoc-js-std/parser-paths.js [new file with mode: 0644]
src/test/rustdoc-js-std/parser-quote.js [new file with mode: 0644]
src/test/rustdoc-js-std/parser-returned.js [new file with mode: 0644]
src/test/rustdoc-js-std/parser-separators.js [new file with mode: 0644]
src/test/rustdoc-js-std/parser-weird-queries.js [new file with mode: 0644]
src/test/rustdoc-js-std/quoted.js
src/test/rustdoc-js-std/struct-vec.js
src/test/rustdoc-js-std/typed-query.js
src/test/rustdoc-js-std/vec-new.js
src/test/rustdoc-js/doc-alias-filter.js
src/test/rustdoc-js/doc-alias.js
src/test/rustdoc-js/generics.js
src/test/rustdoc-js/generics.rs
src/test/rustdoc-ui/intra-doc/email-address-localhost.rs
src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr [deleted file]
src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.rs [new file with mode: 0644]
src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr [new file with mode: 0644]
src/test/rustdoc-ui/issue-91713.stdout
src/test/rustdoc/doc-cfg.rs
src/test/rustdoc/duplicate-cfg.rs
src/test/rustdoc/duplicated_impl.rs [new file with mode: 0644]
src/test/rustdoc/early-unindent.rs [new file with mode: 0644]
src/test/rustdoc/where.SWhere_Simd_item-decl.html [new file with mode: 0644]
src/test/rustdoc/where.SWhere_TraitWhere_item-decl.html [new file with mode: 0644]
src/test/rustdoc/where.rs
src/test/ui/arg-count-mismatch.rs [deleted file]
src/test/ui/arg-count-mismatch.stderr [deleted file]
src/test/ui/arg-type-mismatch.rs [deleted file]
src/test/ui/arg-type-mismatch.stderr [deleted file]
src/test/ui/argument-suggestions/basic.rs [new file with mode: 0644]
src/test/ui/argument-suggestions/basic.stderr [new file with mode: 0644]
src/test/ui/argument-suggestions/complex.rs [new file with mode: 0644]
src/test/ui/argument-suggestions/complex.stderr [new file with mode: 0644]
src/test/ui/argument-suggestions/extra_arguments.rs [new file with mode: 0644]
src/test/ui/argument-suggestions/extra_arguments.stderr [new file with mode: 0644]
src/test/ui/argument-suggestions/invalid_arguments.rs [new file with mode: 0644]
src/test/ui/argument-suggestions/invalid_arguments.stderr [new file with mode: 0644]
src/test/ui/argument-suggestions/missing_arguments.rs [new file with mode: 0644]
src/test/ui/argument-suggestions/missing_arguments.stderr [new file with mode: 0644]
src/test/ui/argument-suggestions/mixed_cases.rs [new file with mode: 0644]
src/test/ui/argument-suggestions/mixed_cases.stderr [new file with mode: 0644]
src/test/ui/argument-suggestions/permuted_arguments.rs [new file with mode: 0644]
src/test/ui/argument-suggestions/permuted_arguments.stderr [new file with mode: 0644]
src/test/ui/argument-suggestions/swapped_arguments.rs [new file with mode: 0644]
src/test/ui/argument-suggestions/swapped_arguments.stderr [new file with mode: 0644]
src/test/ui/asm/aarch64/parse-error.rs
src/test/ui/asm/aarch64/parse-error.stderr
src/test/ui/asm/aarch64/type-check-2.rs
src/test/ui/asm/aarch64/type-check-2.stderr
src/test/ui/asm/type-check-1.rs
src/test/ui/asm/type-check-1.stderr
src/test/ui/asm/x86_64/bad-reg.rs
src/test/ui/asm/x86_64/bad-reg.stderr
src/test/ui/asm/x86_64/parse-error.rs
src/test/ui/asm/x86_64/parse-error.stderr
src/test/ui/asm/x86_64/type-check-2.rs
src/test/ui/asm/x86_64/type-check-2.stderr
src/test/ui/associated-types/associated-type-projection-from-supertrait.stderr
src/test/ui/associated-types/associated-types-path-2.stderr
src/test/ui/async-await/async-fn-path-elision.stderr
src/test/ui/async-await/dont-suggest-missing-await.stderr
src/test/ui/async-await/generator-desc.stderr
src/test/ui/async-await/issues/issue-67893.rs
src/test/ui/async-await/issues/issue-67893.stderr
src/test/ui/async-await/suggest-missing-await-closure.stderr
src/test/ui/async-await/suggest-missing-await.stderr
src/test/ui/binding/issue-53114-safety-checks.rs
src/test/ui/binding/issue-53114-safety-checks.stderr
src/test/ui/c-variadic/variadic-ffi-1.stderr
src/test/ui/cast/cast-int-to-char.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr
src/test/ui/closures/closure-reform-bad.stderr
src/test/ui/closures/issue-84128.stderr
src/test/ui/closures/issue-87461.stderr
src/test/ui/coercion/coerce-mut.stderr
src/test/ui/coercion/coerce-reborrow-multi-arg-fail.stderr
src/test/ui/coercion/coerce-to-bang.stderr
src/test/ui/coherence/coherence-cow.re_a.stderr
src/test/ui/coherence/coherence-cow.re_b.stderr
src/test/ui/coherence/coherence-cow.re_c.stderr
src/test/ui/coherence/coherence-impls-copy.stderr
src/test/ui/coherence/coherence-orphan.stderr
src/test/ui/coherence/coherence-overlapping-pairs.stderr
src/test/ui/coherence/coherence-pair-covered-uncovered-1.stderr
src/test/ui/coherence/coherence-pair-covered-uncovered.stderr
src/test/ui/coherence/coherence-vec-local-2.stderr
src/test/ui/coherence/coherence-vec-local.stderr
src/test/ui/coherence/coherence_local_err_struct.stderr
src/test/ui/coherence/impl-foreign-for-foreign.stderr
src/test/ui/coherence/impl-foreign-for-foreign[foreign].stderr
src/test/ui/coherence/impl-foreign-for-fundamental[foreign].stderr
src/test/ui/coherence/impl-foreign[foreign]-for-foreign.stderr
src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr
src/test/ui/coherence/impl[t]-foreign-for-foreign[t].stderr
src/test/ui/const-generics/const-argument-cross-crate-mismatch.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/const-argument-cross-crate-mismatch.stderr
src/test/ui/const-generics/generic_const_exprs/issue-62504.min.stderr
src/test/ui/const-generics/issues/issue-87493.stderr
src/test/ui/consts/const-eval/ub-enum.32bit.stderr
src/test/ui/consts/const-eval/ub-enum.64bit.stderr
src/test/ui/consts/const-eval/ub-enum.rs
src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs
src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs
src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr
src/test/ui/consts/const-float-bits-conv.rs
src/test/ui/consts/const-float-bits-reject-conv.rs [new file with mode: 0644]
src/test/ui/consts/const-float-bits-reject-conv.stderr [new file with mode: 0644]
src/test/ui/consts/const-fn-error.stderr
src/test/ui/consts/const-for.stderr
src/test/ui/derives/deriving-with-repr-packed.stderr
src/test/ui/did_you_mean/issue-42764.stderr
src/test/ui/did_you_mean/replace-impl-infer-ty-from-trait.fixed [new file with mode: 0644]
src/test/ui/did_you_mean/replace-impl-infer-ty-from-trait.rs [new file with mode: 0644]
src/test/ui/did_you_mean/replace-impl-infer-ty-from-trait.stderr [new file with mode: 0644]
src/test/ui/disambiguate-identical-names.stderr
src/test/ui/error-codes/E0057.stderr
src/test/ui/error-codes/E0060.rs
src/test/ui/error-codes/E0060.stderr
src/test/ui/error-codes/E0061.rs
src/test/ui/error-codes/E0061.stderr
src/test/ui/error-codes/E0107.rs
src/test/ui/error-codes/E0107.stderr
src/test/ui/error-codes/E0117.stderr
src/test/ui/estr-subtyping.rs [new file with mode: 0644]
src/test/ui/estr-subtyping.stderr [new file with mode: 0644]
src/test/ui/extern-flag/no-nounused.rs [new file with mode: 0644]
src/test/ui/extern-flag/no-nounused.stderr [new file with mode: 0644]
src/test/ui/extern-flag/nounused.rs [new file with mode: 0644]
src/test/ui/fmt/ifmt-bad-arg.stderr
src/test/ui/fn/fn-item-type.rs
src/test/ui/fn/fn-item-type.stderr
src/test/ui/generator/issue-93161.rs
src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr
src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr
src/test/ui/generic-associated-types/issue-67510.rs
src/test/ui/generic-associated-types/issue-67510.stderr
src/test/ui/generic-associated-types/issue-68648-2.stderr
src/test/ui/generic-associated-types/issue-70304.rs
src/test/ui/generic-associated-types/issue-70304.stderr
src/test/ui/generic-associated-types/missing-bounds.stderr
src/test/ui/generics/generic-extern-lifetime.stderr
src/test/ui/generics/issue-80512-param-reordering-with-defaults.rs [new file with mode: 0644]
src/test/ui/generics/issue-80512-param-reordering-with-defaults.stderr [new file with mode: 0644]
src/test/ui/hrtb/issue-58451.stderr
src/test/ui/impl-header-lifetime-elision/path-elided.stderr
src/test/ui/impl-header-lifetime-elision/trait-elided.rs
src/test/ui/impl-header-lifetime-elision/trait-elided.stderr
src/test/ui/impl-trait/issues/issue-74282.stderr
src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
src/test/ui/impl-trait/type_parameters_captured.nll.stderr
src/test/ui/indexing-requires-a-uint.stderr
src/test/ui/inference/deref-suggestion.stderr
src/test/ui/inference/tutorial-suffix-inference-test.stderr
src/test/ui/issues/issue-10412.rs
src/test/ui/issues/issue-10412.stderr
src/test/ui/issues/issue-10764.stderr
src/test/ui/issues/issue-11374.stderr
src/test/ui/issues/issue-12997-2.stderr
src/test/ui/issues/issue-13359.stderr
src/test/ui/issues/issue-13853.stderr
src/test/ui/issues/issue-1448-2.stderr
src/test/ui/issues/issue-15783.stderr
src/test/ui/issues/issue-16939.stderr
src/test/ui/issues/issue-17033.stderr
src/test/ui/issues/issue-1866.rs [deleted file]
src/test/ui/issues/issue-1866.stderr [deleted file]
src/test/ui/issues/issue-18819.stderr
src/test/ui/issues/issue-20343.rs [deleted file]
src/test/ui/issues/issue-24819.stderr
src/test/ui/issues/issue-26094.rs
src/test/ui/issues/issue-26094.stderr
src/test/ui/issues/issue-29488.rs [deleted file]
src/test/ui/issues/issue-3044.rs
src/test/ui/issues/issue-3044.stderr
src/test/ui/issues/issue-41776.rs [deleted file]
src/test/ui/issues/issue-41776.stderr [deleted file]
src/test/ui/issues/issue-43132.rs [deleted file]
src/test/ui/issues/issue-43420-no-over-suggest.stderr
src/test/ui/issues/issue-44127.rs [deleted file]
src/test/ui/issues/issue-4517.stderr
src/test/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.stderr
src/test/ui/issues/issue-48364.stderr
src/test/ui/issues/issue-4935.stderr
src/test/ui/issues/issue-51154.stderr
src/test/ui/issues/issue-5216.stderr
src/test/ui/issues/issue-53692.rs [deleted file]
src/test/ui/issues/issue-53692.stderr [deleted file]
src/test/ui/issues/issue-61106.stderr
src/test/ui/issues/issue-61858.rs [deleted file]
src/test/ui/issues/issue-61858.stderr [deleted file]
src/test/ui/issues/issue-69306.stderr
src/test/ui/issues/issue-71036.rs [deleted file]
src/test/ui/issues/issue-71036.stderr [deleted file]
src/test/ui/issues/issue-80512-param-reordering-with-defaults.rs [deleted file]
src/test/ui/issues/issue-80512-param-reordering-with-defaults.stderr [deleted file]
src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.rs [new file with mode: 0644]
src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr [new file with mode: 0644]
src/test/ui/lifetimes/issue-91763.stderr
src/test/ui/lifetimes/lifetime-errors/issue_74400.nll.stderr
src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr
src/test/ui/lint/force-warn/allowed-by-default-lint.stderr
src/test/ui/lint/issue-1866.rs [new file with mode: 0644]
src/test/ui/lint/issue-1866.stderr [new file with mode: 0644]
src/test/ui/lint/issue-20343.rs [new file with mode: 0644]
src/test/ui/lint/lint-ctypes-enum.rs
src/test/ui/lint/lint-ctypes-enum.stderr
src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr
src/test/ui/lint/lint-strict-provenance-lossy-casts.rs
src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr
src/test/ui/lint/reasons.rs
src/test/ui/lint/reasons.stderr
src/test/ui/lint/unaligned_references.stderr
src/test/ui/lint/unaligned_references_external_macro.stderr
src/test/ui/lint/unreachable_pub-pub_crate.rs
src/test/ui/lint/unreachable_pub-pub_crate.stderr
src/test/ui/lint/unreachable_pub.rs
src/test/ui/lint/unreachable_pub.stderr
src/test/ui/macros/issue-29084.stderr
src/test/ui/macros/issue-41776.rs [new file with mode: 0644]
src/test/ui/macros/issue-41776.stderr [new file with mode: 0644]
src/test/ui/macros/issue-44127.rs [new file with mode: 0644]
src/test/ui/match/issue-82392.stdout
src/test/ui/methods/issues/issue-90315.rs [new file with mode: 0644]
src/test/ui/methods/issues/issue-90315.stderr [new file with mode: 0644]
src/test/ui/methods/method-call-err-msg.stderr
src/test/ui/methods/method-call-lifetime-args-unresolved.rs
src/test/ui/methods/method-call-lifetime-args-unresolved.stderr
src/test/ui/methods/method-self-arg-1.stderr
src/test/ui/mir/issue-95978-validator-lifetime-comparison.rs [new file with mode: 0644]
src/test/ui/mismatched_types/issue-26480.stderr
src/test/ui/mismatched_types/issue-35030.stderr
src/test/ui/mismatched_types/numeric-literal-cast.stderr
src/test/ui/mismatched_types/overloaded-calls-bad.rs
src/test/ui/mismatched_types/overloaded-calls-bad.stderr
src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr
src/test/ui/mut/mut-cross-borrowing.stderr
src/test/ui/never_type/call-fn-never-arg-wrong-type.stderr
src/test/ui/never_type/issue-52443.stderr
src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr
src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr
src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr
src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.nll.stderr
src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.nll.stderr
src/test/ui/nll/ty-outlives/projection-where-clause-none.stderr
src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr
src/test/ui/nll/ty-outlives/ty-param-fn.stderr
src/test/ui/not-enough-arguments.stderr
src/test/ui/numeric/integer-literal-suffix-inference.stderr
src/test/ui/numeric/len.stderr
src/test/ui/numeric/numeric-cast-without-suggestion.stderr
src/test/ui/numeric/numeric-cast.stderr
src/test/ui/numeric/numeric-suffix.fixed [deleted file]
src/test/ui/numeric/numeric-suffix.rs [deleted file]
src/test/ui/numeric/numeric-suffix.stderr [deleted file]
src/test/ui/numeric/numeric-suffix/numeric-suffix-i32.fixed [new file with mode: 0644]
src/test/ui/numeric/numeric-suffix/numeric-suffix-i32.rs [new file with mode: 0644]
src/test/ui/numeric/numeric-suffix/numeric-suffix-i32.stderr [new file with mode: 0644]
src/test/ui/numeric/numeric-suffix/numeric-suffix-i64.fixed [new file with mode: 0644]
src/test/ui/numeric/numeric-suffix/numeric-suffix-i64.rs [new file with mode: 0644]
src/test/ui/numeric/numeric-suffix/numeric-suffix-i64.stderr [new file with mode: 0644]
src/test/ui/numeric/numeric-suffix/numeric-suffix-isize.fixed [new file with mode: 0644]
src/test/ui/numeric/numeric-suffix/numeric-suffix-isize.rs [new file with mode: 0644]
src/test/ui/numeric/numeric-suffix/numeric-suffix-isize.stderr [new file with mode: 0644]
src/test/ui/numeric/numeric-suffix/numeric-suffix-u32.fixed [new file with mode: 0644]
src/test/ui/numeric/numeric-suffix/numeric-suffix-u32.rs [new file with mode: 0644]
src/test/ui/numeric/numeric-suffix/numeric-suffix-u32.stderr [new file with mode: 0644]
src/test/ui/numeric/numeric-suffix/numeric-suffix-u64.fixed [new file with mode: 0644]
src/test/ui/numeric/numeric-suffix/numeric-suffix-u64.rs [new file with mode: 0644]
src/test/ui/numeric/numeric-suffix/numeric-suffix-u64.stderr [new file with mode: 0644]
src/test/ui/numeric/numeric-suffix/numeric-suffix-usize.fixed [new file with mode: 0644]
src/test/ui/numeric/numeric-suffix/numeric-suffix-usize.rs [new file with mode: 0644]
src/test/ui/numeric/numeric-suffix/numeric-suffix-usize.stderr [new file with mode: 0644]
src/test/ui/numeric/numeric-suffix/numeric-suffix.fixed [new file with mode: 0644]
src/test/ui/numeric/numeric-suffix/numeric-suffix.rs [new file with mode: 0644]
src/test/ui/numeric/numeric-suffix/numeric-suffix.stderr [new file with mode: 0644]
src/test/ui/packed/issue-27060-rpass.stderr [new file with mode: 0644]
src/test/ui/packed/issue-27060.rs
src/test/ui/packed/issue-27060.stderr
src/test/ui/packed/packed-struct-address-of-element.rs
src/test/ui/packed/packed-struct-borrow-element-64bit.rs
src/test/ui/packed/packed-struct-borrow-element-64bit.stderr
src/test/ui/packed/packed-struct-borrow-element.rs
src/test/ui/packed/packed-struct-borrow-element.stderr
src/test/ui/parser/fn-arg-doc-comment.rs
src/test/ui/parser/fn-arg-doc-comment.stderr
src/test/ui/parser/issue-61858.rs [new file with mode: 0644]
src/test/ui/parser/issue-61858.stderr [new file with mode: 0644]
src/test/ui/pattern/pattern-error-continue.stderr
src/test/ui/proc-macro/signature.stderr
src/test/ui/range/issue-54505-no-literals.stderr
src/test/ui/range/issue-54505-no-std.stderr
src/test/ui/range/issue-54505.stderr
src/test/ui/range/issue-73553-misinterp-range-literal.stderr
src/test/ui/regions/regions-close-associated-type-into-object.nll.stderr
src/test/ui/regions/regions-close-object-into-object-4.nll.stderr
src/test/ui/regions/regions-close-object-into-object-5.nll.stderr
src/test/ui/regions/regions-close-over-type-parameter-1.nll.stderr
src/test/ui/regions/regions-close-param-into-object.nll.stderr
src/test/ui/regions/regions-implied-bounds-projection-gap-1.nll.stderr
src/test/ui/regions/regions-infer-bound-from-trait-self.nll.stderr
src/test/ui/regions/regions-infer-bound-from-trait.nll.stderr
src/test/ui/regions/regions-name-static.rs
src/test/ui/regions/regions-name-undeclared.rs
src/test/ui/regions/regions-name-undeclared.stderr
src/test/ui/resolve/resolve-primitive-fallback.stderr
src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs
src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr
src/test/ui/rfc1623.base.stderr
src/test/ui/rfc1623.nll.stderr
src/test/ui/rfc1623.rs
src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.base.stderr [new file with mode: 0644]
src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr
src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs
src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr [deleted file]
src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.base.stderr [new file with mode: 0644]
src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr
src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs
src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr [deleted file]
src/test/ui/self/elision/lt-ref-self-async.base.stderr [new file with mode: 0644]
src/test/ui/self/elision/lt-ref-self-async.nll.stderr
src/test/ui/self/elision/lt-ref-self-async.rs
src/test/ui/self/elision/lt-ref-self-async.stderr [deleted file]
src/test/ui/self/elision/lt-ref-self.base.stderr [new file with mode: 0644]
src/test/ui/self/elision/lt-ref-self.nll.stderr
src/test/ui/self/elision/lt-ref-self.rs
src/test/ui/self/elision/lt-ref-self.stderr [deleted file]
src/test/ui/self/elision/ref-mut-self-async.base.stderr [new file with mode: 0644]
src/test/ui/self/elision/ref-mut-self-async.nll.stderr
src/test/ui/self/elision/ref-mut-self-async.rs
src/test/ui/self/elision/ref-mut-self-async.stderr [deleted file]
src/test/ui/self/elision/ref-mut-self.base.stderr [new file with mode: 0644]
src/test/ui/self/elision/ref-mut-self.nll.stderr
src/test/ui/self/elision/ref-mut-self.rs
src/test/ui/self/elision/ref-mut-self.stderr [deleted file]
src/test/ui/self/elision/ref-mut-struct-async.base.stderr [new file with mode: 0644]
src/test/ui/self/elision/ref-mut-struct-async.nll.stderr
src/test/ui/self/elision/ref-mut-struct-async.rs
src/test/ui/self/elision/ref-mut-struct-async.stderr [deleted file]
src/test/ui/self/elision/ref-mut-struct.base.stderr [new file with mode: 0644]
src/test/ui/self/elision/ref-mut-struct.nll.stderr
src/test/ui/self/elision/ref-mut-struct.rs
src/test/ui/self/elision/ref-mut-struct.stderr [deleted file]
src/test/ui/self/elision/ref-self-async.base.stderr [new file with mode: 0644]
src/test/ui/self/elision/ref-self-async.nll.stderr
src/test/ui/self/elision/ref-self-async.rs
src/test/ui/self/elision/ref-self-async.stderr [deleted file]
src/test/ui/self/elision/ref-self.base.stderr [new file with mode: 0644]
src/test/ui/self/elision/ref-self.nll.stderr
src/test/ui/self/elision/ref-self.rs
src/test/ui/self/elision/ref-self.stderr [deleted file]
src/test/ui/self/elision/ref-struct-async.base.stderr [new file with mode: 0644]
src/test/ui/self/elision/ref-struct-async.nll.stderr
src/test/ui/self/elision/ref-struct-async.rs
src/test/ui/self/elision/ref-struct-async.stderr [deleted file]
src/test/ui/self/elision/ref-struct.base.stderr [new file with mode: 0644]
src/test/ui/self/elision/ref-struct.nll.stderr
src/test/ui/self/elision/ref-struct.rs
src/test/ui/self/elision/ref-struct.stderr [deleted file]
src/test/ui/self/issue-61882.stderr
src/test/ui/span/E0057.rs [new file with mode: 0644]
src/test/ui/span/E0057.stderr [new file with mode: 0644]
src/test/ui/span/coerce-suggestions.stderr
src/test/ui/span/issue-34264.stderr
src/test/ui/span/missing-unit-argument.stderr
src/test/ui/statics/uninhabited-static.rs
src/test/ui/statics/uninhabited-static.stderr
src/test/ui/suggestions/args-instead-of-tuple-errors.stderr
src/test/ui/suggestions/args-instead-of-tuple.stderr
src/test/ui/suggestions/as-ref.stderr
src/test/ui/suggestions/boxed-variant-field.stderr
src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr
src/test/ui/suggestions/issue-53692.rs [new file with mode: 0644]
src/test/ui/suggestions/issue-53692.stderr [new file with mode: 0644]
src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr
src/test/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr
src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.nll.stderr
src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr [new file with mode: 0644]
src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs
src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
src/test/ui/suggestions/pattern-struct-with-slice-vec-field.rs [new file with mode: 0644]
src/test/ui/suggestions/pattern-struct-with-slice-vec-field.stderr [new file with mode: 0644]
src/test/ui/suggestions/recover-from-semicolon-trailing-item.stderr
src/test/ui/suggestions/suggest-impl-trait-lifetime.nll.stderr
src/test/ui/suggestions/suggest-ref-macro.stderr
src/test/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.stderr
src/test/ui/suggestions/trait-with-missing-associated-type-restriction.stderr
src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr
src/test/ui/terminal-width/flag-json.rs
src/test/ui/terr-in-field.stderr
src/test/ui/terr-sorts.stderr
src/test/ui/thread-local/non-static.rs [new file with mode: 0644]
src/test/ui/thread-local/non-static.stderr [new file with mode: 0644]
src/test/ui/threads-sendsync/issue-29488.rs [new file with mode: 0644]
src/test/ui/traits/bound/sugar.stderr
src/test/ui/traits/cycle-cache-err-60010.stderr
src/test/ui/traits/issue-43132.rs [new file with mode: 0644]
src/test/ui/traits/issue-52893.stderr
src/test/ui/traits/issue-71036.rs [new file with mode: 0644]
src/test/ui/traits/issue-71036.stderr [new file with mode: 0644]
src/test/ui/traits/multidispatch-bad.stderr
src/test/ui/tuple/tuple-arity-mismatch.stderr
src/test/ui/tuple/wrong_argument_ice-2.stderr
src/test/ui/tuple/wrong_argument_ice-3.stderr
src/test/ui/tuple/wrong_argument_ice-4.stderr
src/test/ui/tuple/wrong_argument_ice.stderr
src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr
src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr
src/test/ui/type-alias-impl-trait/issue-60662.stdout
src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs
src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr
src/test/ui/type/type-ascription-instead-of-initializer.stderr
src/test/ui/type/type-mismatch-same-crate-name.stderr
src/test/ui/type/type-mismatch.stderr
src/test/ui/typeck/issue-46112.stderr
src/test/ui/typeck/issue-84768.stderr
src/test/ui/typeck/issue-89856.stderr
src/test/ui/typeck/struct-enum-wrong-args.stderr
src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr
src/test/ui/typeck/typeck_type_placeholder_item.rs
src/test/ui/typeck/typeck_type_placeholder_item.stderr
src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr
src/test/ui/underscore-lifetime/in-binder.rs
src/test/ui/uninhabited/privately-uninhabited-mir-call.rs [new file with mode: 0644]
src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr [new file with mode: 0644]
src/test/ui/unsafe/issue-45087-unreachable-unsafe.mir.stderr
src/test/ui/unsafe/issue-45087-unreachable-unsafe.rs
src/test/ui/unsafe/issue-45087-unreachable-unsafe.thir.stderr
src/test/ui/unterminated-nested-comment.rs [new file with mode: 0644]
src/test/ui/unterminated-nested-comment.stderr [new file with mode: 0644]
src/test/ui/unused-crate-deps/extern-loc-bad-loctype.rs [deleted file]
src/test/ui/unused-crate-deps/extern-loc-bad-loctype.stderr [deleted file]
src/test/ui/unused-crate-deps/extern-loc-defl-json.rs [deleted file]
src/test/ui/unused-crate-deps/extern-loc-defl-json.stderr [deleted file]
src/test/ui/unused-crate-deps/extern-loc-json-bad-json.rs [deleted file]
src/test/ui/unused-crate-deps/extern-loc-json-bad-json.stderr [deleted file]
src/test/ui/unused-crate-deps/extern-loc-json-json.rs [deleted file]
src/test/ui/unused-crate-deps/extern-loc-json-json.stderr [deleted file]
src/test/ui/unused-crate-deps/extern-loc-json.rs [deleted file]
src/test/ui/unused-crate-deps/extern-loc-json.stderr [deleted file]
src/test/ui/unused-crate-deps/extern-loc-missing-loc.rs [deleted file]
src/test/ui/unused-crate-deps/extern-loc-missing-loc.stderr [deleted file]
src/test/ui/unused-crate-deps/extern-loc-missing-loctype.rs [deleted file]
src/test/ui/unused-crate-deps/extern-loc-missing-loctype.stderr [deleted file]
src/test/ui/unused-crate-deps/extern-loc-raw-json.rs [deleted file]
src/test/ui/unused-crate-deps/extern-loc-raw-json.stderr [deleted file]
src/test/ui/unused-crate-deps/extern-loc-raw-missing-loc.rs [deleted file]
src/test/ui/unused-crate-deps/extern-loc-raw-missing-loc.stderr [deleted file]
src/test/ui/unused-crate-deps/extern-loc-raw.rs [deleted file]
src/test/ui/unused-crate-deps/extern-loc-raw.stderr [deleted file]
src/test/ui/unused-crate-deps/libfib.stderr
src/test/ui/unused-crate-deps/unused-aliases.stderr
src/test/ui/unused-crate-deps/warn-attr.stderr
src/test/ui/unused-crate-deps/warn-cmdline-static.stderr
src/test/ui/unused-crate-deps/warn-cmdline.stderr
src/test/ui/use/use-super-global-path.rs
src/test/ui/use/use-super-global-path.stderr
src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr
src/test/ui/where-clauses/where-lifetime-resolution.stderr
src/tools/cargo
src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
src/tools/clippy/clippy_lints/src/enum_variants.rs
src/tools/clippy/clippy_lints/src/exhaustive_items.rs
src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
src/tools/clippy/clippy_lints/src/functions/too_many_arguments.rs
src/tools/clippy/clippy_lints/src/loops/never_loop.rs
src/tools/clippy/clippy_lints/src/missing_doc.rs
src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs
src/tools/clippy/clippy_lints/src/same_name_method.rs
src/tools/clippy/clippy_lints/src/unused_async.rs
src/tools/clippy/clippy_lints/src/utils/inspector.rs
src/tools/clippy/clippy_lints/src/wildcard_imports.rs
src/tools/clippy/clippy_utils/src/hir_utils.rs
src/tools/clippy/clippy_utils/src/lib.rs
src/tools/clippy/tests/ui/same_name_method.stderr
src/tools/clippy/tests/ui/unused_unit.stderr
src/tools/compiletest/src/common.rs
src/tools/compiletest/src/header.rs
src/tools/compiletest/src/header/tests.rs
src/tools/compiletest/src/main.rs
src/tools/compiletest/src/runtest.rs
src/tools/miri
src/tools/rust-analyzer
src/tools/rustbook/Cargo.toml
src/tools/rustdoc-js/tester.js
src/tools/rustfmt/src/items.rs
src/tools/rustfmt/src/visitor.rs
src/tools/tidy/src/deps.rs
src/tools/tidy/src/ui_tests.rs

index ff3a8326315309a2232a9b5a9f74971175ab3d81..451116f320d64ae1d7d8e04a010ce666c1117c9e 100644 (file)
@@ -56,7 +56,7 @@ jobs:
       - name: disable git crlf conversion
         run: git config --global core.autocrlf false
       - name: checkout the source code
-        uses: actions/checkout@v2
+        uses: actions/checkout@v3
         with:
           fetch-depth: 2
       - name: configure the PR in which the error message will be posted
@@ -454,7 +454,7 @@ jobs:
       - name: disable git crlf conversion
         run: git config --global core.autocrlf false
       - name: checkout the source code
-        uses: actions/checkout@v2
+        uses: actions/checkout@v3
         with:
           fetch-depth: 2
       - name: configure the PR in which the error message will be posted
@@ -567,7 +567,7 @@ jobs:
       - name: disable git crlf conversion
         run: git config --global core.autocrlf false
       - name: checkout the source code
-        uses: actions/checkout@v2
+        uses: actions/checkout@v3
         with:
           fetch-depth: 2
       - name: configure the PR in which the error message will be posted
@@ -670,7 +670,7 @@ jobs:
     if: "github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'rust-lang-ci/rust'"
     steps:
       - name: checkout the source code
-        uses: actions/checkout@v2
+        uses: actions/checkout@v3
         with:
           fetch-depth: 2
       - name: publish toolstate
index 9eba61f8d293b64253f12af8745b21b5e76d2f67..30175ae3561ab7b3ff6b9630855f1bc3b2e0759a 100644 (file)
@@ -337,6 +337,7 @@ dependencies = [
  "humantime 2.0.1",
  "ignore",
  "im-rc",
+ "indexmap",
  "itertools",
  "jobserver",
  "lazy_static",
@@ -358,6 +359,7 @@ dependencies = [
  "serde_ignored",
  "serde_json",
  "shell-escape",
+ "snapbox",
  "strip-ansi-escapes",
  "tar",
  "tempfile",
@@ -606,12 +608,22 @@ dependencies = [
  "atty",
  "bitflags",
  "indexmap",
+ "lazy_static",
  "os_str_bytes",
  "strsim 0.10.0",
  "termcolor",
  "textwrap 0.14.2",
 ]
 
+[[package]]
+name = "clap_complete"
+version = "3.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df6f3613c0a3cddfd78b41b10203eb322cb29b600cbdf808a7d3db95691b8e25"
+dependencies = [
+ "clap 3.1.1",
+]
+
 [[package]]
 name = "clippy"
 version = "0.1.62"
@@ -784,6 +796,32 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "concolor"
+version = "0.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "015267563b1df20adccdd00cb05257b1dfbea70a04928e9cf88ffb850c1a40af"
+dependencies = [
+ "atty",
+ "bitflags",
+ "concolor-query",
+]
+
+[[package]]
+name = "concolor-query"
+version = "0.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6417fe6fc03a8b533fd2177742eeb39a90c7233eedec7bac96d4d6b69a09449"
+
+[[package]]
+name = "content_inspector"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7bda66e858c683005a53a9a60c69a4aca7eeaa45d124526e389f7aec8e62f38"
+dependencies = [
+ "memchr",
+]
+
 [[package]]
 name = "core"
 version = "0.0.0"
@@ -1078,6 +1116,12 @@ dependencies = [
  "rustc-std-workspace-core",
 ]
 
+[[package]]
+name = "dunce"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "453440c271cf5577fd2a40e4942540cb7d0d2f85e27c8d07dd0023c925a67541"
+
 [[package]]
 name = "either"
 version = "1.6.0"
@@ -2240,14 +2284,15 @@ dependencies = [
 
 [[package]]
 name = "mdbook"
-version = "0.4.15"
+version = "0.4.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "241f10687eb3b4e0634b3b4e423f97c5f1efbd69dc9522e24a8b94583eeec3c6"
+checksum = "74612ae81a3e5ee509854049dfa4c7975ae033c06f5fc4735c7dfbe60ee2a39d"
 dependencies = [
  "ammonia",
  "anyhow",
  "chrono",
- "clap 2.34.0",
+ "clap 3.1.1",
+ "clap_complete",
  "elasticlunr-rs",
  "env_logger 0.7.1",
  "handlebars",
@@ -2406,6 +2451,12 @@ dependencies = [
  "version_check",
 ]
 
+[[package]]
+name = "normalize-line-endings"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
+
 [[package]]
 name = "ntapi"
 version = "0.3.6"
@@ -2480,9 +2531,9 @@ dependencies = [
 
 [[package]]
 name = "once_cell"
-version = "1.7.2"
+version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
+checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
 
 [[package]]
 name = "opaque-debug"
@@ -2502,9 +2553,9 @@ dependencies = [
 
 [[package]]
 name = "openssl"
-version = "0.10.35"
+version = "0.10.38"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "549430950c79ae24e6d02e0b7404534ecf311d94cc9f861e9e4020187d13d885"
+checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95"
 dependencies = [
  "bitflags",
  "cfg-if 1.0.0",
@@ -2531,9 +2582,9 @@ dependencies = [
 
 [[package]]
 name = "openssl-sys"
-version = "0.9.65"
+version = "0.9.72"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a7907e3bfa08bb85105209cdfcb6c63d109f8f6c1ed6ca318fff5c1853fbc1d"
+checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb"
 dependencies = [
  "autocfg",
  "cc",
@@ -2883,6 +2934,7 @@ dependencies = [
 name = "proc_macro"
 version = "0.0.0"
 dependencies = [
+ "core",
  "std",
 ]
 
@@ -2911,7 +2963,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "34f197a544b0c9ab3ae46c359a7ec9cbbb5c7bf97054266fecb7ead794a181d6"
 dependencies = [
  "bitflags",
- "getopts",
  "memchr",
  "unicase",
 ]
@@ -3129,9 +3180,9 @@ dependencies = [
 
 [[package]]
 name = "regex"
-version = "1.5.4"
+version = "1.5.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
+checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -3924,7 +3975,6 @@ dependencies = [
  "rustc_infer",
  "rustc_middle",
  "rustc_parse_format",
- "rustc_serialize",
  "rustc_session",
  "rustc_span",
  "rustc_target",
@@ -4486,6 +4536,7 @@ dependencies = [
  "expect-test",
  "itertools",
  "minifier",
+ "once_cell",
  "pulldown-cmark",
  "rayon",
  "regex",
@@ -4780,6 +4831,12 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "similar"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e24979f63a11545f5f2c60141afe249d4f19f84581ea2138065e400941d83d3"
+
 [[package]]
 name = "siphasher"
 version = "0.3.3"
@@ -4814,6 +4871,30 @@ version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "da73c8f77aebc0e40c300b93f0a5f1bece7a248a36eee287d4e095f35c7b7d6e"
 
+[[package]]
+name = "snapbox"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1f212b806d6f56d19838e36a0aaa7e79a0bc9ca177e873fb87651ad92f983e2"
+dependencies = [
+ "concolor",
+ "content_inspector",
+ "dunce",
+ "filetime",
+ "normalize-line-endings",
+ "similar",
+ "snapbox-macros",
+ "tempfile",
+ "walkdir",
+ "yansi",
+]
+
+[[package]]
+name = "snapbox-macros"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c01dea7e04cbb27ef4c86e9922184608185f7cd95c1763bc30d727cda4a5e930"
+
 [[package]]
 name = "socket2"
 version = "0.4.1"
@@ -5658,9 +5739,9 @@ dependencies = [
 
 [[package]]
 name = "walkdir"
-version = "2.3.1"
+version = "2.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
+checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
 dependencies = [
  "same-file",
  "winapi",
@@ -5771,6 +5852,12 @@ dependencies = [
  "linked-hash-map",
 ]
 
+[[package]]
+name = "yansi"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
+
 [[package]]
 name = "yansi-term"
 version = "0.1.2"
index 42ec206fc65b3ef1907e8fe4895454914d38f567..b7da276fc7e1dc431acd53a999524e3d4e05bb06 100644 (file)
@@ -107,11 +107,11 @@ fn eq(&self, symbol: &Symbol) -> bool {
     }
 }
 
-impl<CTX> HashStable<CTX> for Path {
+impl<CTX: rustc_span::HashStableContext> HashStable<CTX> for Path {
     fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
         self.segments.len().hash_stable(hcx, hasher);
         for segment in &self.segments {
-            segment.ident.name.hash_stable(hcx, hasher);
+            segment.ident.hash_stable(hcx, hasher);
         }
     }
 }
@@ -2061,6 +2061,20 @@ pub fn to_string(s: &[Self]) -> String {
     }
 }
 
+/// Inline assembly symbol operands get their own AST node that is somewhat
+/// similar to `AnonConst`.
+///
+/// The main difference is that we specifically don't assign it `DefId` in
+/// `DefCollector`. Instead this is deferred until AST lowering where we
+/// lower it to an `AnonConst` (for functions) or a `Path` (for statics)
+/// depending on what the path resolves to.
+#[derive(Clone, Encodable, Decodable, Debug)]
+pub struct InlineAsmSym {
+    pub id: NodeId,
+    pub qself: Option<QSelf>,
+    pub path: Path,
+}
+
 /// Inline assembly operand.
 ///
 /// E.g., `out("eax") result` as in `asm!("mov eax, 2", out("eax") result)`.
@@ -2090,7 +2104,7 @@ pub enum InlineAsmOperand {
         anon_const: AnonConst,
     },
     Sym {
-        expr: P<Expr>,
+        sym: InlineAsmSym,
     },
 }
 
index 80caf37d7099d67ddea64e0912cc44be3099483e..9a6d12faa605d62bcdf7540aeb1adf28a9dbb8b1 100644 (file)
@@ -9,6 +9,7 @@
 use crate::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree};
 use crate::tokenstream::{DelimSpan, Spacing, TokenTree, TreeAndSpacing};
 use crate::tokenstream::{LazyTokenStream, TokenStream};
+use crate::util::comments;
 
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_span::source_map::BytePos;
@@ -262,6 +263,10 @@ pub fn doc_str(&self) -> Option<Symbol> {
         }
     }
 
+    pub fn may_have_doc_links(&self) -> bool {
+        self.doc_str().map_or(false, |s| comments::may_have_doc_links(s.as_str()))
+    }
+
     pub fn get_normal_item(&self) -> &AttrItem {
         match self.kind {
             AttrKind::Normal(ref item, _) => item,
index 15f7aceb83d7ad0d9112a373a76e811ffb610eec..cba49835f69cb45efc0a6be4011ca764790f1b74 100644 (file)
@@ -280,6 +280,14 @@ fn visit_span(&mut self, _sp: &mut Span) {
     fn flat_map_pat_field(&mut self, fp: PatField) -> SmallVec<[PatField; 1]> {
         noop_flat_map_pat_field(fp, self)
     }
+
+    fn visit_inline_asm(&mut self, asm: &mut InlineAsm) {
+        noop_visit_inline_asm(asm, self)
+    }
+
+    fn visit_inline_asm_sym(&mut self, sym: &mut InlineAsmSym) {
+        noop_visit_inline_asm_sym(sym, self)
+    }
 }
 
 /// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
@@ -1019,7 +1027,7 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
             }
         }
         ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
-        ItemKind::GlobalAsm(asm) => noop_visit_inline_asm(asm, vis),
+        ItemKind::GlobalAsm(asm) => vis.visit_inline_asm(asm),
         ItemKind::TyAlias(box TyAlias {
             defaultness, generics, where_clauses, bounds, ty, ..
         }) => {
@@ -1237,13 +1245,12 @@ pub fn noop_visit_anon_const<T: MutVisitor>(AnonConst { id, value }: &mut AnonCo
     vis.visit_expr(value);
 }
 
-fn noop_visit_inline_asm<T: MutVisitor>(asm: &mut InlineAsm, vis: &mut T) {
+pub fn noop_visit_inline_asm<T: MutVisitor>(asm: &mut InlineAsm, vis: &mut T) {
     for (op, _) in &mut asm.operands {
         match op {
             InlineAsmOperand::In { expr, .. }
             | InlineAsmOperand::Out { expr: Some(expr), .. }
-            | InlineAsmOperand::InOut { expr, .. }
-            | InlineAsmOperand::Sym { expr, .. } => vis.visit_expr(expr),
+            | InlineAsmOperand::InOut { expr, .. } => vis.visit_expr(expr),
             InlineAsmOperand::Out { expr: None, .. } => {}
             InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
                 vis.visit_expr(in_expr);
@@ -1251,11 +1258,21 @@ fn noop_visit_inline_asm<T: MutVisitor>(asm: &mut InlineAsm, vis: &mut T) {
                     vis.visit_expr(out_expr);
                 }
             }
-            InlineAsmOperand::Const { anon_const, .. } => vis.visit_anon_const(anon_const),
+            InlineAsmOperand::Const { anon_const } => vis.visit_anon_const(anon_const),
+            InlineAsmOperand::Sym { sym } => vis.visit_inline_asm_sym(sym),
         }
     }
 }
 
+pub fn noop_visit_inline_asm_sym<T: MutVisitor>(
+    InlineAsmSym { id, qself, path }: &mut InlineAsmSym,
+    vis: &mut T,
+) {
+    vis.visit_id(id);
+    vis.visit_qself(qself);
+    vis.visit_path(path);
+}
+
 pub fn noop_visit_expr<T: MutVisitor>(
     Expr { kind, id, span, attrs, tokens }: &mut Expr,
     vis: &mut T,
@@ -1374,7 +1391,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
         ExprKind::Ret(expr) => {
             visit_opt(expr, |expr| vis.visit_expr(expr));
         }
-        ExprKind::InlineAsm(asm) => noop_visit_inline_asm(asm, vis),
+        ExprKind::InlineAsm(asm) => vis.visit_inline_asm(asm),
         ExprKind::MacCall(mac) => vis.visit_mac_call(mac),
         ExprKind::Struct(se) => {
             let StructExpr { qself, path, fields, rest } = se.deref_mut();
index affb4289cb1b5a4f229a79cdaba90b1d7008f7c3..d609fa6720502c5ca1b679ad2cd0b0c99c813be7 100644 (file)
@@ -94,16 +94,6 @@ pub fn token(kind: TokenKind, span: Span) -> TokenTree {
         TokenTree::Token(Token::new(kind, span))
     }
 
-    /// Returns the opening delimiter as a token tree.
-    pub fn open_tt(span: DelimSpan, delim: DelimToken) -> TokenTree {
-        TokenTree::token(token::OpenDelim(delim), span.open)
-    }
-
-    /// Returns the closing delimiter as a token tree.
-    pub fn close_tt(span: DelimSpan, delim: DelimToken) -> TokenTree {
-        TokenTree::token(token::CloseDelim(delim), span.close)
-    }
-
     pub fn uninterpolate(self) -> TokenTree {
         match self {
             TokenTree::Token(token) => TokenTree::Token(token.uninterpolate().into_owned()),
@@ -585,13 +575,20 @@ fn new(stream: TokenStream) -> Self {
         Cursor { stream, index: 0 }
     }
 
+    #[inline]
     pub fn next_with_spacing(&mut self) -> Option<TreeAndSpacing> {
-        if self.index < self.stream.len() {
+        self.stream.0.get(self.index).map(|tree| {
             self.index += 1;
-            Some(self.stream.0[self.index - 1].clone())
-        } else {
-            None
-        }
+            tree.clone()
+        })
+    }
+
+    #[inline]
+    pub fn next_with_spacing_ref(&mut self) -> Option<&TreeAndSpacing> {
+        self.stream.0.get(self.index).map(|tree| {
+            self.index += 1;
+            tree
+        })
     }
 
     pub fn index(&self) -> usize {
index 8730aeb0f3bffdf182cef918a75c06a4a44bd391..b4fff0022e29547e2cd17c2994ac09f528258456 100644 (file)
@@ -24,6 +24,14 @@ pub struct Comment {
     pub pos: BytePos,
 }
 
+/// A fast conservative estimate on whether the string can contain documentation links.
+/// A pair of square brackets `[]` must exist in the string, but we only search for the
+/// opening bracket because brackets always go in pairs in practice.
+#[inline]
+pub fn may_have_doc_links(s: &str) -> bool {
+    s.contains('[')
+}
+
 /// Makes a doc string more presentable to users.
 /// Used by rustdoc and perhaps other tools, but not by rustc.
 pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol {
index ed16c25d921e4872b7f02f528847e07d72f9b604..d925c6dd3549aa5da8b01d7a80858bd1dccaf8d1 100644 (file)
@@ -35,7 +35,7 @@ pub enum FnCtxt {
 #[derive(Copy, Clone, Debug)]
 pub enum FnKind<'a> {
     /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
-    Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, Option<&'a Block>),
+    Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, &'a Generics, Option<&'a Block>),
 
     /// E.g., `|x, y| body`.
     Closure(&'a FnDecl, &'a Expr),
@@ -44,7 +44,7 @@ pub enum FnKind<'a> {
 impl<'a> FnKind<'a> {
     pub fn header(&self) -> Option<&'a FnHeader> {
         match *self {
-            FnKind::Fn(_, _, sig, _, _) => Some(&sig.header),
+            FnKind::Fn(_, _, sig, _, _, _) => Some(&sig.header),
             FnKind::Closure(_, _) => None,
         }
     }
@@ -58,7 +58,7 @@ pub fn ident(&self) -> Option<&Ident> {
 
     pub fn decl(&self) -> &'a FnDecl {
         match self {
-            FnKind::Fn(_, _, sig, _, _) => &sig.decl,
+            FnKind::Fn(_, _, sig, _, _, _) => &sig.decl,
             FnKind::Closure(decl, _) => decl,
         }
     }
@@ -214,6 +214,12 @@ fn visit_pat_field(&mut self, fp: &'ast PatField) {
     fn visit_crate(&mut self, krate: &'ast Crate) {
         walk_crate(self, krate)
     }
+    fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) {
+        walk_inline_asm(self, asm)
+    }
+    fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) {
+        walk_inline_asm_sym(self, sym)
+    }
 }
 
 #[macro_export]
@@ -289,8 +295,8 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             walk_list!(visitor, visit_expr, expr);
         }
         ItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => {
-            visitor.visit_generics(generics);
-            let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref());
+            let kind =
+                FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, generics, body.as_deref());
             visitor.visit_fn(kind, item.span, item.id)
         }
         ItemKind::Mod(_unsafety, ref mod_kind) => match mod_kind {
@@ -555,8 +561,7 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI
             walk_list!(visitor, visit_expr, expr);
         }
         ForeignItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => {
-            visitor.visit_generics(generics);
-            let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, body.as_deref());
+            let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, generics, body.as_deref());
             visitor.visit_fn(kind, span, id);
         }
         ForeignItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
@@ -638,7 +643,8 @@ pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &
 
 pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>, _span: Span) {
     match kind {
-        FnKind::Fn(_, _, sig, _, body) => {
+        FnKind::Fn(_, _, sig, _, generics, body) => {
+            visitor.visit_generics(generics);
             visitor.visit_fn_header(&sig.header);
             walk_fn_decl(visitor, &sig.decl);
             walk_list!(visitor, visit_block, body);
@@ -661,8 +667,7 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
             walk_list!(visitor, visit_expr, expr);
         }
         AssocItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => {
-            visitor.visit_generics(generics);
-            let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, body.as_deref());
+            let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body.as_deref());
             visitor.visit_fn(kind, span, id);
         }
         AssocItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
@@ -717,13 +722,12 @@ pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonCo
     visitor.visit_expr(&constant.value);
 }
 
-fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) {
+pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) {
     for (op, _) in &asm.operands {
         match op {
             InlineAsmOperand::In { expr, .. }
             | InlineAsmOperand::Out { expr: Some(expr), .. }
-            | InlineAsmOperand::InOut { expr, .. }
-            | InlineAsmOperand::Sym { expr, .. } => visitor.visit_expr(expr),
+            | InlineAsmOperand::InOut { expr, .. } => visitor.visit_expr(expr),
             InlineAsmOperand::Out { expr: None, .. } => {}
             InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
                 visitor.visit_expr(in_expr);
@@ -732,10 +736,18 @@ fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) {
                 }
             }
             InlineAsmOperand::Const { anon_const, .. } => visitor.visit_anon_const(anon_const),
+            InlineAsmOperand::Sym { sym } => visitor.visit_inline_asm_sym(sym),
         }
     }
 }
 
+pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>(visitor: &mut V, sym: &'a InlineAsmSym) {
+    if let Some(ref qself) = sym.qself {
+        visitor.visit_ty(&qself.ty);
+    }
+    visitor.visit_path(&sym.path, sym.id);
+}
+
 pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
     walk_list!(visitor, visit_attribute, expression.attrs.iter());
 
index 171cc60dfd77c28b79dca802aa4c81d31b7543ea..ae3e367596258b16a37d4c66fd086fe2f2492f74 100644 (file)
@@ -1,12 +1,17 @@
+use crate::{ImplTraitContext, ImplTraitPosition, ParamMode};
+
 use super::LoweringContext;
 
+use rustc_ast::ptr::P;
 use rustc_ast::*;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_set::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::definitions::DefPathData;
 use rustc_session::parse::feature_err;
-use rustc_span::{sym, Span};
+use rustc_span::{sym, ExpnId, Span};
 use rustc_target::asm;
 use std::collections::hash_map::Entry;
 use std::fmt::Write;
@@ -188,7 +193,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             anon_const: self.lower_anon_const(anon_const),
                         }
                     }
-                    InlineAsmOperand::Sym { ref expr } => {
+                    InlineAsmOperand::Sym { ref sym } => {
                         if !self.sess.features_untracked().asm_sym {
                             feature_err(
                                 &self.sess.parse_sess,
@@ -198,7 +203,54 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             )
                             .emit();
                         }
-                        hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) }
+
+                        let static_def_id = self
+                            .resolver
+                            .get_partial_res(sym.id)
+                            .filter(|res| res.unresolved_segments() == 0)
+                            .and_then(|res| {
+                                if let Res::Def(DefKind::Static(_), def_id) = res.base_res() {
+                                    Some(def_id)
+                                } else {
+                                    None
+                                }
+                            });
+
+                        if let Some(def_id) = static_def_id {
+                            let path = self.lower_qpath(
+                                sym.id,
+                                &sym.qself,
+                                &sym.path,
+                                ParamMode::Optional,
+                                ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+                            );
+                            hir::InlineAsmOperand::SymStatic { path, def_id }
+                        } else {
+                            // Replace the InlineAsmSym AST node with an
+                            // Expr using the name node id.
+                            let expr = Expr {
+                                id: sym.id,
+                                kind: ExprKind::Path(sym.qself.clone(), sym.path.clone()),
+                                span: *op_sp,
+                                attrs: AttrVec::new(),
+                                tokens: None,
+                            };
+
+                            // Wrap the expression in an AnonConst.
+                            let parent_def_id = self.current_hir_id_owner;
+                            let node_id = self.resolver.next_node_id();
+                            self.resolver.create_def(
+                                parent_def_id,
+                                node_id,
+                                DefPathData::AnonConst,
+                                ExpnId::root(),
+                                *op_sp,
+                            );
+                            let anon_const = AnonConst { id: node_id, value: P(expr) };
+                            hir::InlineAsmOperand::SymFn {
+                                anon_const: self.lower_anon_const(&anon_const),
+                            }
+                        }
                     }
                 };
                 (op, self.lower_span(*op_sp))
@@ -260,7 +312,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         err.span_label(op_sp, "argument");
                         err.emit();
                     }
-                    hir::InlineAsmOperand::Sym { .. } => {
+                    hir::InlineAsmOperand::SymFn { .. }
+                    | hir::InlineAsmOperand::SymStatic { .. } => {
                         let mut err = sess.struct_span_err(
                             placeholder_span,
                             "asm template modifiers are not allowed for `sym` arguments",
@@ -308,7 +361,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         hir::InlineAsmOperand::InOut { .. }
                         | hir::InlineAsmOperand::SplitInOut { .. } => (true, true),
 
-                        hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::Sym { .. } => {
+                        hir::InlineAsmOperand::Const { .. }
+                        | hir::InlineAsmOperand::SymFn { .. }
+                        | hir::InlineAsmOperand::SymStatic { .. } => {
                             unreachable!()
                         }
                     };
index 5eab21bf79a90c9a95b57a41534df927793c3832..0f90239f4c8b39aa07822c2eed1c893bc733e997 100644 (file)
@@ -290,18 +290,6 @@ fn visit_lifetime(&mut self, lifetime: &'hir Lifetime) {
         self.insert(lifetime.span, lifetime.hir_id, Node::Lifetime(lifetime));
     }
 
-    fn visit_vis(&mut self, visibility: &'hir Visibility<'hir>) {
-        match visibility.node {
-            VisibilityKind::Public | VisibilityKind::Crate(_) | VisibilityKind::Inherited => {}
-            VisibilityKind::Restricted { hir_id, .. } => {
-                self.insert(visibility.span, hir_id, Node::Visibility(visibility));
-                self.with_parent(hir_id, |this| {
-                    intravisit::walk_vis(this, visibility);
-                });
-            }
-        }
-    }
-
     fn visit_variant(&mut self, v: &'hir Variant<'hir>, g: &'hir Generics<'hir>, item_id: HirId) {
         self.insert(v.span, v.id, Node::Variant(v));
         self.with_parent(v.id, |this| {
index a8bd8c92a41c47b54d45329720f092185260300f..29353d47b87e89ad36a2fed4666141b447332117 100644 (file)
@@ -14,7 +14,7 @@
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_session::utils::NtToTokenstream;
 use rustc_session::Session;
-use rustc_span::source_map::{respan, DesugaringKind};
+use rustc_span::source_map::DesugaringKind;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Span;
 use rustc_target::spec::abi;
@@ -230,15 +230,15 @@ fn lower_item_id_use_tree(
 
     fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> {
         let mut ident = i.ident;
-        let mut vis = self.lower_visibility(&i.vis);
+        let vis_span = self.lower_span(i.vis.span);
         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);
+        let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, vis_span, &i.kind);
         let item = hir::Item {
             def_id: hir_id.expect_owner(),
             ident: self.lower_ident(ident),
             kind,
-            vis,
+            vis_span,
             span: self.lower_span(i.span),
         };
         self.arena.alloc(item)
@@ -251,7 +251,7 @@ fn lower_item_kind(
         hir_id: hir::HirId,
         ident: &mut Ident,
         attrs: Option<&'hir [Attribute]>,
-        vis: &mut hir::Visibility<'hir>,
+        vis_span: Span,
         i: &ItemKind,
     ) -> hir::ItemKind<'hir> {
         match *i {
@@ -260,7 +260,7 @@ fn lower_item_kind(
                 // Start with an empty prefix.
                 let prefix = Path { segments: vec![], span: use_tree.span, tokens: None };
 
-                self.lower_use_tree(use_tree, &prefix, id, vis, ident, attrs)
+                self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs)
             }
             ItemKind::Static(ref t, m, ref e) => {
                 let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
@@ -527,12 +527,11 @@ fn lower_use_tree(
         tree: &UseTree,
         prefix: &Path,
         id: NodeId,
-        vis: &mut hir::Visibility<'hir>,
+        vis_span: Span,
         ident: &mut Ident,
         attrs: Option<&'hir [Attribute]>,
     ) -> hir::ItemKind<'hir> {
         debug!("lower_use_tree(tree={:?})", tree);
-        debug!("lower_use_tree: vis = {:?}", vis);
 
         let path = &tree.prefix;
         let segments = prefix.segments.iter().chain(path.segments.iter()).cloned().collect();
@@ -586,7 +585,6 @@ fn lower_use_tree(
                         let res = this.lower_res(res);
                         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(hir::ItemLocalId::new(0), attrs);
                         }
@@ -595,7 +593,7 @@ fn lower_use_tree(
                             def_id: new_id,
                             ident: this.lower_ident(ident),
                             kind,
-                            vis,
+                            vis_span,
                             span: this.lower_span(span),
                         };
                         hir::OwnerNode::Item(this.arena.alloc(item))
@@ -657,11 +655,10 @@ fn lower_use_tree(
                     // own its own names, we have to adjust the owner before
                     // lowering the rest of the import.
                     self.with_hir_id_owner(id, |this| {
-                        let mut vis = this.rebuild_vis(&vis);
                         let mut ident = *ident;
 
                         let kind =
-                            this.lower_use_tree(use_tree, &prefix, id, &mut vis, &mut ident, attrs);
+                            this.lower_use_tree(use_tree, &prefix, id, vis_span, &mut ident, attrs);
                         if let Some(attrs) = attrs {
                             this.attrs.insert(hir::ItemLocalId::new(0), attrs);
                         }
@@ -670,37 +667,13 @@ fn lower_use_tree(
                             def_id: new_hir_id,
                             ident: this.lower_ident(ident),
                             kind,
-                            vis,
+                            vis_span,
                             span: this.lower_span(use_tree.span),
                         };
                         hir::OwnerNode::Item(this.arena.alloc(item))
                     });
                 }
 
-                // Subtle and a bit hacky: we lower the privacy level
-                // of the list stem to "private" most of the time, but
-                // not for "restricted" paths. The key thing is that
-                // we don't want it to stay as `pub` (with no caveats)
-                // because that affects rustdoc and also the lints
-                // about `pub` items. But we can't *always* make it
-                // private -- particularly not for restricted paths --
-                // because it contains node-ids that would then be
-                // unused, failing the check that HirIds are "densely
-                // assigned".
-                match vis.node {
-                    hir::VisibilityKind::Public
-                    | hir::VisibilityKind::Crate(_)
-                    | hir::VisibilityKind::Inherited => {
-                        *vis = respan(
-                            self.lower_span(prefix.span.shrink_to_lo()),
-                            hir::VisibilityKind::Inherited,
-                        );
-                    }
-                    hir::VisibilityKind::Restricted { .. } => {
-                        // Do nothing here, as described in the comment on the match.
-                    }
-                }
-
                 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);
@@ -709,37 +682,6 @@ fn lower_use_tree(
         }
     }
 
-    /// Paths like the visibility path in `pub(super) use foo::{bar, baz}` are repeated
-    /// many times in the HIR tree; for each occurrence, we need to assign distinct
-    /// `NodeId`s. (See, e.g., #56128.)
-    fn rebuild_use_path(&mut self, path: &hir::Path<'hir>) -> &'hir hir::Path<'hir> {
-        debug!("rebuild_use_path(path = {:?})", path);
-        let segments =
-            self.arena.alloc_from_iter(path.segments.iter().map(|seg| hir::PathSegment {
-                ident: seg.ident,
-                hir_id: seg.hir_id.map(|_| self.next_id()),
-                res: seg.res,
-                args: None,
-                infer_args: seg.infer_args,
-            }));
-        self.arena.alloc(hir::Path { span: path.span, res: path.res, segments })
-    }
-
-    fn rebuild_vis(&mut self, vis: &hir::Visibility<'hir>) -> hir::Visibility<'hir> {
-        let vis_kind = match vis.node {
-            hir::VisibilityKind::Public => hir::VisibilityKind::Public,
-            hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
-            hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited,
-            hir::VisibilityKind::Restricted { ref path, hir_id: _ } => {
-                hir::VisibilityKind::Restricted {
-                    path: self.rebuild_use_path(path),
-                    hir_id: self.next_id(),
-                }
-            }
-        };
-        respan(self.lower_span(vis.span), vis_kind)
-    }
-
     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();
@@ -773,7 +715,7 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir
                 ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
                 ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
             },
-            vis: self.lower_visibility(&i.vis),
+            vis_span: self.lower_span(i.vis.span),
             span: self.lower_span(i.span),
         };
         self.arena.alloc(item)
@@ -851,7 +793,7 @@ fn lower_field_def(&mut self, (index, f): (usize, &FieldDef)) -> hir::FieldDef<'
                 // FIXME(jseyfried): positional field hygiene.
                 None => Ident::new(sym::integer(index), self.lower_span(f.span)),
             },
-            vis: self.lower_visibility(&f.vis),
+            vis_span: self.lower_span(f.vis.span),
             ty,
         }
     }
@@ -1016,8 +958,8 @@ fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
             def_id: hir_id.expect_owner(),
             ident: self.lower_ident(i.ident),
             generics,
-            vis: self.lower_visibility(&i.vis),
             kind,
+            vis_span: self.lower_span(i.vis.span),
             span: self.lower_span(i.span),
         };
         self.arena.alloc(item)
@@ -1044,28 +986,6 @@ fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
         }
     }
 
-    /// If an `explicit_owner` is given, this method allocates the `HirId` in
-    /// the address space of that item instead of the item currently being
-    /// 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) -> 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 = self.lower_node_id(id);
-                hir::VisibilityKind::Restricted {
-                    path: self.lower_path(id, path, ParamMode::Explicit),
-                    hir_id: lowered_id,
-                }
-            }
-            VisibilityKind::Inherited => hir::VisibilityKind::Inherited,
-        };
-        respan(self.lower_span(v.span), node)
-    }
-
     fn lower_defaultness(
         &self,
         d: Defaultness,
index e7e82e651bb09ae0f7dd5518eb76d9530ed46cea..b15f299b5f2cb9e5da02d6131f0a44d80d18a9c0 100644 (file)
@@ -61,7 +61,7 @@
 use rustc_session::utils::{FlattenNonterminals, NtToTokenstream};
 use rustc_session::Session;
 use rustc_span::hygiene::{ExpnId, MacroKind};
-use rustc_span::source_map::{respan, DesugaringKind};
+use rustc_span::source_map::DesugaringKind;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 
@@ -484,7 +484,7 @@ enum ParenthesizedGenericArgs {
 /// an "elided" or "underscore" lifetime name. In the future, we probably want to move
 /// everything into HIR lowering.
 #[derive(Copy, Clone, Debug)]
-enum AnonymousLifetimeMode {
+pub enum AnonymousLifetimeMode {
     /// For **Modern** cases, create a new anonymous region parameter
     /// and reference that.
     ///
@@ -1530,7 +1530,7 @@ fn generate_opaque_type(
             def_id: opaque_ty_id,
             ident: Ident::empty(),
             kind: opaque_ty_item_kind,
-            vis: respan(self.lower_span(span.shrink_to_lo()), hir::VisibilityKind::Inherited),
+            vis_span: self.lower_span(span.shrink_to_lo()),
             span: self.lower_span(opaque_ty_span),
         };
         hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item))
@@ -1835,7 +1835,7 @@ fn lower_async_fn_ret_ty(
             // Output lifetime like `'_`:
             for (span, node_id) in lifetimes_to_define {
                 let param = this.fresh_lifetime_to_generic_param(span, node_id);
-                lifetime_params.push((span, hir::LifetimeName::Implicit(false)));
+                lifetime_params.push((span, hir::LifetimeName::Implicit));
                 generic_params.push(param);
             }
             let generic_params = this.arena.alloc_from_iter(generic_params);
@@ -2017,16 +2017,16 @@ fn lower_generic_param(
                     });
                 let param_name = match lt.name {
                     hir::LifetimeName::Param(param_name) => param_name,
-                    hir::LifetimeName::Implicit(_)
-                    | hir::LifetimeName::Underscore
-                    | hir::LifetimeName::Static => hir::ParamName::Plain(lt.name.ident()),
+                    hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => {
+                        hir::ParamName::Plain(lt.name.ident())
+                    }
                     hir::LifetimeName::ImplicitObjectLifetimeDefault => {
                         self.sess.diagnostic().span_bug(
                             param.ident.span,
                             "object-lifetime-default should not occur here",
                         );
                     }
-                    hir::LifetimeName::Error => ParamName::Error,
+                    hir::LifetimeName::Static | hir::LifetimeName::Error => ParamName::Error,
                 };
 
                 let kind =
@@ -2397,27 +2397,14 @@ fn elided_ref_lifetime(&mut self, span: Span) -> hir::Lifetime {
 
             AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span),
 
-            AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span, false),
+            AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span),
         }
     }
 
     /// Report an error on illegal use of `'_` or a `&T` with no explicit lifetime;
     /// return an "error lifetime".
     fn new_error_lifetime(&mut self, id: Option<NodeId>, span: Span) -> hir::Lifetime {
-        let (id, msg, label) = match id {
-            Some(id) => (id, "`'_` cannot be used here", "`'_` is a reserved lifetime name"),
-
-            None => (
-                self.resolver.next_node_id(),
-                "`&` without an explicit lifetime name cannot be used here",
-                "explicit lifetime name needed here",
-            ),
-        };
-
-        let mut err = struct_span_err!(self.sess, span, E0637, "{}", msg,);
-        err.span_label(span, label);
-        err.emit();
-
+        let id = id.unwrap_or_else(|| self.resolver.next_node_id());
         self.new_named_lifetime(id, span, hir::LifetimeName::Error)
     }
 
@@ -2429,12 +2416,11 @@ fn elided_path_lifetimes<'s>(
         &'s mut self,
         span: Span,
         count: usize,
-        param_mode: ParamMode,
     ) -> impl Iterator<Item = hir::Lifetime> + Captures<'a> + Captures<'s> + Captures<'hir> {
-        (0..count).map(move |_| self.elided_path_lifetime(span, param_mode))
+        (0..count).map(move |_| self.elided_path_lifetime(span))
     }
 
-    fn elided_path_lifetime(&mut self, span: Span, param_mode: ParamMode) -> hir::Lifetime {
+    fn elided_path_lifetime(&mut self, span: Span) -> hir::Lifetime {
         match self.anonymous_lifetime_mode {
             AnonymousLifetimeMode::CreateParameter => {
                 // We should have emitted E0726 when processing this path above
@@ -2450,7 +2436,7 @@ fn elided_path_lifetime(&mut self, span: Span, param_mode: ParamMode) -> hir::Li
             // lifetime. Instead, we simply create an implicit lifetime, which will be checked
             // later, at which point a suitable error will be emitted.
             AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => {
-                self.new_implicit_lifetime(span, param_mode == ParamMode::Explicit)
+                self.new_implicit_lifetime(span)
             }
         }
     }
@@ -2493,11 +2479,11 @@ fn elided_dyn_bound(&mut self, span: Span) -> hir::Lifetime {
         r
     }
 
-    fn new_implicit_lifetime(&mut self, span: Span, missing: bool) -> hir::Lifetime {
+    fn new_implicit_lifetime(&mut self, span: Span) -> hir::Lifetime {
         hir::Lifetime {
             hir_id: self.next_id(),
             span: self.lower_span(span),
-            name: hir::LifetimeName::Implicit(missing),
+            name: hir::LifetimeName::Implicit,
         }
     }
 }
@@ -2600,7 +2586,7 @@ fn visit_generic_param(&mut self, param: &'v hir::GenericParam<'v>) {
 
         fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
             let name = match lifetime.name {
-                hir::LifetimeName::Implicit(_) | hir::LifetimeName::Underscore => {
+                hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => {
                     if self.collect_elided_lifetimes {
                         // Use `'_` for both implicit and underscore lifetimes in
                         // `type Foo<'_> = impl SomeTrait<'_>;`.
index b35e3a071619af307dfa7df01533a02d6c2487dd..8bf4b8fcc3975347c926a41373d56f359fb65b97 100644 (file)
@@ -290,47 +290,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo()
             };
             generic_args.args = self
-                .elided_path_lifetimes(elided_lifetime_span, expected_lifetimes, param_mode)
+                .elided_path_lifetimes(elided_lifetime_span, expected_lifetimes)
                 .map(GenericArg::Lifetime)
                 .chain(generic_args.args.into_iter())
                 .collect();
-            // In create-parameter mode we error here because we don't want to support
-            // deprecated impl elision in new features like impl elision and `async fn`,
-            // both of which work using the `CreateParameter` mode:
-            //
-            //     impl Foo for std::cell::Ref<u32> // note lack of '_
-            //     async fn foo(_: std::cell::Ref<u32>) { ... }
             if let (ParamMode::Explicit, AnonymousLifetimeMode::CreateParameter) =
                 (param_mode, self.anonymous_lifetime_mode)
             {
-                let anon_lt_suggestion = vec!["'_"; expected_lifetimes].join(", ");
-                let no_non_lt_args = generic_args.args.len() == expected_lifetimes;
-                let no_bindings = generic_args.bindings.is_empty();
-                let (incl_angl_brckt, suggestion) = if no_non_lt_args && no_bindings {
-                    // If there are no generic args, our suggestion can include the angle brackets.
-                    (true, format!("<{}>", anon_lt_suggestion))
-                } else {
-                    // Otherwise we'll insert a `'_, ` right after the opening bracket.
-                    (false, format!("{}, ", anon_lt_suggestion))
-                };
-                let insertion_sp = elided_lifetime_span.shrink_to_hi();
-                let mut err = struct_span_err!(
-                    self.sess,
-                    path_span,
-                    E0726,
-                    "implicit elided lifetime not allowed here"
-                );
-                rustc_errors::add_elided_lifetime_in_path_suggestion(
-                    &self.sess.source_map(),
-                    &mut err,
-                    expected_lifetimes,
-                    path_span,
-                    incl_angl_brckt,
-                    insertion_sp,
-                    suggestion,
-                );
-                err.note("assuming a `'static` lifetime...");
-                err.emit();
+                // Late resolver should have issued the error.
+                self.sess
+                    .delay_span_bug(elided_lifetime_span, "implicit lifetime not allowed here");
             }
         }
 
index 33727084ccf064f5d291934cc5bf062bcd0825fa..8d815e95528825a269a56f88619e9102631d5cc4 100644 (file)
@@ -91,16 +91,18 @@ fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
         self.is_impl_trait_banned = old;
     }
 
-    fn with_tilde_const_allowed(&mut self, f: impl FnOnce(&mut Self)) {
-        let old = mem::replace(&mut self.is_tilde_const_allowed, true);
+    fn with_tilde_const(&mut self, allowed: bool, f: impl FnOnce(&mut Self)) {
+        let old = mem::replace(&mut self.is_tilde_const_allowed, allowed);
         f(self);
         self.is_tilde_const_allowed = old;
     }
 
+    fn with_tilde_const_allowed(&mut self, f: impl FnOnce(&mut Self)) {
+        self.with_tilde_const(true, f)
+    }
+
     fn with_banned_tilde_const(&mut self, f: impl FnOnce(&mut Self)) {
-        let old = mem::replace(&mut self.is_tilde_const_allowed, false);
-        f(self);
-        self.is_tilde_const_allowed = old;
+        self.with_tilde_const(false, f)
     }
 
     fn with_let_management(
@@ -1202,12 +1204,8 @@ fn visit_item(&mut self, item: &'a Item) {
                 }
                 self.visit_vis(&item.vis);
                 self.visit_ident(item.ident);
-                if let Const::Yes(_) = sig.header.constness {
-                    self.with_tilde_const_allowed(|this| this.visit_generics(generics));
-                } else {
-                    self.visit_generics(generics);
-                }
-                let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref());
+                let kind =
+                    FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, generics, body.as_deref());
                 self.visit_fn(kind, item.span, item.id);
                 walk_list!(self, visit_attribute, &item.attrs);
                 return; // Avoid visiting again.
@@ -1555,13 +1553,14 @@ fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
             FnSig { span: sig_span, header: FnHeader { ext: Extern::Implicit, .. }, .. },
             _,
             _,
+            _,
         ) = fk
         {
             self.maybe_lint_missing_abi(*sig_span, id);
         }
 
         // Functions without bodies cannot have patterns.
-        if let FnKind::Fn(ctxt, _, sig, _, None) = fk {
+        if let FnKind::Fn(ctxt, _, sig, _, _, None) = fk {
             Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| {
                 let (code, msg, label) = match ctxt {
                     FnCtxt::Foreign => (
@@ -1596,7 +1595,11 @@ fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
             });
         }
 
-        visit::walk_fn(self, fk, span);
+        let tilde_const_allowed =
+            matches!(fk.header(), Some(FnHeader { constness: Const::Yes(_), .. }))
+                || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)));
+
+        self.with_tilde_const(tilde_const_allowed, |this| visit::walk_fn(this, fk, span));
     }
 
     fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
@@ -1670,9 +1673,14 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
             {
                 self.visit_vis(&item.vis);
                 self.visit_ident(item.ident);
-                self.with_tilde_const_allowed(|this| this.visit_generics(generics));
-                let kind =
-                    FnKind::Fn(FnCtxt::Assoc(ctxt), item.ident, sig, &item.vis, body.as_deref());
+                let kind = FnKind::Fn(
+                    FnCtxt::Assoc(ctxt),
+                    item.ident,
+                    sig,
+                    &item.vis,
+                    generics,
+                    body.as_deref(),
+                );
                 self.visit_fn(kind, item.span, item.id);
             }
             _ => self
index a778d8c54708459ab2325b922aba0973ce64773f..649af48e48adf624311ba4f4e37a6ef2c69c6783 100644 (file)
@@ -58,9 +58,22 @@ struct PostExpansionVisitor<'a> {
 }
 
 impl<'a> PostExpansionVisitor<'a> {
-    fn check_abi(&self, abi: ast::StrLit) {
+    fn check_abi(&self, abi: ast::StrLit, constness: ast::Const) {
         let ast::StrLit { symbol_unescaped, span, .. } = abi;
 
+        if let ast::Const::Yes(_) = constness {
+            match symbol_unescaped.as_str() {
+                // Stable
+                "Rust" | "C" => {}
+                abi => gate_feature_post!(
+                    &self,
+                    const_extern_fn,
+                    span,
+                    &format!("`{}` as a `const fn` ABI is unstable", abi)
+                ),
+            }
+        }
+
         match symbol_unescaped.as_str() {
             // Stable
             "Rust" | "C" | "cdecl" | "stdcall" | "fastcall" | "aapcs" | "win64" | "sysv64"
@@ -261,9 +274,9 @@ fn check_abi(&self, abi: ast::StrLit) {
         }
     }
 
-    fn check_extern(&self, ext: ast::Extern) {
+    fn check_extern(&self, ext: ast::Extern, constness: ast::Const) {
         if let ast::Extern::Explicit(abi) = ext {
-            self.check_abi(abi);
+            self.check_abi(abi, constness);
         }
     }
 
@@ -437,7 +450,7 @@ fn visit_item(&mut self, i: &'a ast::Item) {
         match i.kind {
             ast::ItemKind::ForeignMod(ref foreign_module) => {
                 if let Some(abi) = foreign_module.abi {
-                    self.check_abi(abi);
+                    self.check_abi(abi, ast::Const::No);
                 }
             }
 
@@ -560,7 +573,8 @@ fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
     fn visit_ty(&mut self, ty: &'a ast::Ty) {
         match ty.kind {
             ast::TyKind::BareFn(ref bare_fn_ty) => {
-                self.check_extern(bare_fn_ty.ext);
+                // Function pointers cannot be `const`
+                self.check_extern(bare_fn_ty.ext, ast::Const::No);
             }
             ast::TyKind::Never => {
                 gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental");
@@ -660,18 +674,7 @@ fn visit_pat(&mut self, pattern: &'a ast::Pat) {
     fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
         if let Some(header) = fn_kind.header() {
             // Stability of const fn methods are covered in `visit_assoc_item` below.
-            self.check_extern(header.ext);
-
-            if let (ast::Const::Yes(_), ast::Extern::Implicit)
-            | (ast::Const::Yes(_), ast::Extern::Explicit(_)) = (header.constness, header.ext)
-            {
-                gate_feature_post!(
-                    &self,
-                    const_extern_fn,
-                    span,
-                    "`const extern fn` definitions are unstable"
-                );
-            }
+            self.check_extern(header.ext, header.constness);
         }
 
         if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() {
index 719fd2710932185213c279573fa57ec3c98c339d..3c9bb81bedb1c64aec042148a23823b03ccd1ef0 100644 (file)
@@ -959,7 +959,7 @@ pub fn print_assoc_constraint(&mut self, constraint: &ast::AssocConstraint) {
                 self.word_space("=");
                 match term {
                     Term::Ty(ty) => self.print_type(ty),
-                    Term::Const(c) => self.print_expr_anon_const(c),
+                    Term::Const(c) => self.print_expr_anon_const(c, &[]),
                 }
             }
             ast::AssocConstraintKind::Bound { bounds } => self.print_type_bounds(":", &*bounds),
@@ -1266,10 +1266,14 @@ enum AsmArg<'a> {
                         s.space();
                         s.print_expr(&anon_const.value);
                     }
-                    InlineAsmOperand::Sym { expr } => {
+                    InlineAsmOperand::Sym { sym } => {
                         s.word("sym");
                         s.space();
-                        s.print_expr(expr);
+                        if let Some(qself) = &sym.qself {
+                            s.print_qpath(&sym.path, qself, true);
+                        } else {
+                            s.print_path(&sym.path, true, 0);
+                        }
                     }
                 }
             }
index 6435f1b6141e35a66c82211ab67a2b27883ad402..9de4cbbee13f068e483d0fa0ae26d055358f4e1a 100644 (file)
@@ -88,10 +88,21 @@ fn print_expr_vec(&mut self, exprs: &[P<ast::Expr>]) {
         self.end();
     }
 
-    pub(super) fn print_expr_anon_const(&mut self, expr: &ast::AnonConst) {
+    pub(super) fn print_expr_anon_const(
+        &mut self,
+        expr: &ast::AnonConst,
+        attrs: &[ast::Attribute],
+    ) {
         self.ibox(INDENT_UNIT);
         self.word("const");
-        self.print_expr(&expr.value);
+        self.nbsp();
+        if let ast::ExprKind::Block(block, None) = &expr.value.kind {
+            self.cbox(0);
+            self.ibox(0);
+            self.print_block_with_attrs(block, attrs);
+        } else {
+            self.print_expr(&expr.value);
+        }
         self.end();
     }
 
@@ -275,7 +286,7 @@ pub(super) fn print_expr_outer_attr_style(&mut self, expr: &ast::Expr, is_inline
                 self.print_expr_vec(exprs);
             }
             ast::ExprKind::ConstBlock(ref anon_const) => {
-                self.print_expr_anon_const(anon_const);
+                self.print_expr_anon_const(anon_const, attrs);
             }
             ast::ExprKind::Repeat(ref element, ref count) => {
                 self.print_expr_repeat(element, count);
index cb9e0234c49ffa5a5a7edc3e653817563f93ee5e..c19a39c393f799f3c926d4ac3aa8e5c6f0c447d1 100644 (file)
@@ -156,6 +156,7 @@ fn next(&mut self) -> Option<Self::Item> {
                 sup: self.static_region,
                 sub: next_static_idx.into(),
                 locations: Locations::All(DUMMY_SP),
+                span: DUMMY_SP,
                 category: ConstraintCategory::Internal,
                 variance_info: VarianceDiagInfo::default(),
             })
@@ -189,7 +190,7 @@ impl<'s, 'tcx, D: ConstraintGraphDirecton> RegionGraph<'s, 'tcx, D> {
 
     /// Given a region `R`, iterate over all regions `R1` such that
     /// there exists a constraint `R: R1`.
-    crate fn outgoing_regions(&self, region_sup: RegionVid) -> Successors<'_, 'tcx, D> {
+    crate fn outgoing_regions(&self, region_sup: RegionVid) -> Successors<'s, 'tcx, D> {
         Successors {
             edges: self.constraint_graph.outgoing_edges(region_sup, self.set, self.static_region),
         }
@@ -224,10 +225,7 @@ fn successors(&self, node: Self::Node) -> <Self as graph::GraphSuccessors<'_>>::
     }
 }
 
-impl<'s, 'graph, 'tcx, D: ConstraintGraphDirecton> graph::GraphSuccessors<'graph>
-    for RegionGraph<'s, 'tcx, D>
-{
+impl<'s, 'tcx, D: ConstraintGraphDirecton> graph::GraphSuccessors<'_> for RegionGraph<'s, 'tcx, D> {
     type Item = RegionVid;
-    // FIXME - why can't this be `'graph, 'tcx`
-    type Iter = Successors<'graph, 'graph, D>;
+    type Iter = Successors<'s, 'tcx, D>;
 }
index d41143ee763ad835709be88e3966595533913df5..14f0e5f620aeeab90d15b10d259eb735b64e5eb2 100644 (file)
@@ -2,6 +2,7 @@
 use rustc_index::vec::IndexVec;
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::{RegionVid, VarianceDiagInfo};
+use rustc_span::Span;
 use std::fmt;
 use std::ops::Index;
 
@@ -87,6 +88,12 @@ pub struct OutlivesConstraint<'tcx> {
     /// Where did this constraint arise?
     pub locations: Locations,
 
+    /// The `Span` associated with the creation of this constraint.
+    /// This should be used in preference to obtaining the span from
+    /// `locations`, since the `locations` may give a poor span
+    /// in some cases (e.g. converting a constraint from a promoted).
+    pub span: Span,
+
     /// What caused this constraint?
     pub category: ConstraintCategory,
 
index 9e5fb674772d5f0d7c9c525c40dbe886c13e784e..3b4e9e95b0e9108db5086f244888b4bce63e041b 100644 (file)
@@ -7,6 +7,7 @@
 use rustc_hir::{AsyncGeneratorKind, GeneratorKind};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::ObligationCause;
+use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::{
     self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory,
     FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
@@ -22,6 +23,7 @@
 use crate::borrow_set::TwoPhaseActivation;
 use crate::borrowck_errors;
 
+use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead;
 use crate::diagnostics::find_all_local_uses;
 use crate::{
     borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
@@ -1484,7 +1486,7 @@ fn try_report_cannot_return_reference_to_local(
                         err.span_suggestion_hidden(
                             return_span,
                             "use `.collect()` to allocate the iterator",
-                            format!("{}{}", snippet, ".collect::<Vec<_>>()"),
+                            format!("{snippet}.collect::<Vec<_>>()"),
                             Applicability::MaybeIncorrect,
                         );
                     }
@@ -1956,45 +1958,46 @@ pub(crate) fn report_illegal_reassignment(
 
     fn classify_drop_access_kind(&self, place: PlaceRef<'tcx>) -> StorageDeadOrDrop<'tcx> {
         let tcx = self.infcx.tcx;
-        match place.last_projection() {
-            None => StorageDeadOrDrop::LocalStorageDead,
-            Some((place_base, elem)) => {
-                // FIXME(spastorino) make this iterate
-                let base_access = self.classify_drop_access_kind(place_base);
-                match elem {
-                    ProjectionElem::Deref => match base_access {
-                        StorageDeadOrDrop::LocalStorageDead
-                        | StorageDeadOrDrop::BoxedStorageDead => {
-                            assert!(
-                                place_base.ty(self.body, tcx).ty.is_box(),
-                                "Drop of value behind a reference or raw pointer"
-                            );
-                            StorageDeadOrDrop::BoxedStorageDead
-                        }
-                        StorageDeadOrDrop::Destructor(_) => base_access,
-                    },
-                    ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
-                        let base_ty = place_base.ty(self.body, tcx).ty;
-                        match base_ty.kind() {
-                            ty::Adt(def, _) if def.has_dtor(tcx) => {
-                                // Report the outermost adt with a destructor
-                                match base_access {
-                                    StorageDeadOrDrop::Destructor(_) => base_access,
-                                    StorageDeadOrDrop::LocalStorageDead
-                                    | StorageDeadOrDrop::BoxedStorageDead => {
-                                        StorageDeadOrDrop::Destructor(base_ty)
+        let (kind, _place_ty) = place.projection.iter().fold(
+            (LocalStorageDead, PlaceTy::from_ty(self.body.local_decls[place.local].ty)),
+            |(kind, place_ty), &elem| {
+                (
+                    match elem {
+                        ProjectionElem::Deref => match kind {
+                            StorageDeadOrDrop::LocalStorageDead
+                            | StorageDeadOrDrop::BoxedStorageDead => {
+                                assert!(
+                                    place_ty.ty.is_box(),
+                                    "Drop of value behind a reference or raw pointer"
+                                );
+                                StorageDeadOrDrop::BoxedStorageDead
+                            }
+                            StorageDeadOrDrop::Destructor(_) => kind,
+                        },
+                        ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
+                            match place_ty.ty.kind() {
+                                ty::Adt(def, _) if def.has_dtor(tcx) => {
+                                    // Report the outermost adt with a destructor
+                                    match kind {
+                                        StorageDeadOrDrop::Destructor(_) => kind,
+                                        StorageDeadOrDrop::LocalStorageDead
+                                        | StorageDeadOrDrop::BoxedStorageDead => {
+                                            StorageDeadOrDrop::Destructor(place_ty.ty)
+                                        }
                                     }
                                 }
+                                _ => kind,
                             }
-                            _ => base_access,
                         }
-                    }
-                    ProjectionElem::ConstantIndex { .. }
-                    | ProjectionElem::Subslice { .. }
-                    | ProjectionElem::Index(_) => base_access,
-                }
-            }
-        }
+                        ProjectionElem::ConstantIndex { .. }
+                        | ProjectionElem::Subslice { .. }
+                        | ProjectionElem::Index(_) => kind,
+                    },
+                    place_ty.projection_ty(tcx, elem),
+                )
+            },
+        );
+        kind
     }
 
     /// Describe the reason for the fake borrow that was assigned to `place`.
index 5fd9ecf4513661c4301705d5d0db35c7950a122d..fd78b483b75f25c24af7bcd60c5130591cdde612 100644 (file)
@@ -4,6 +4,7 @@
 use rustc_infer::infer::{
     error_reporting::nice_region_error::NiceRegionError,
     error_reporting::unexpected_hidden_region_diagnostic, NllRegionVariableOrigin,
+    RelateParamBound,
 };
 use rustc_middle::hir::place::PlaceBase;
 use rustc_middle::mir::{ConstraintCategory, ReturnConstraint};
@@ -166,11 +167,14 @@ pub(crate) fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) {
                     let type_test_span = type_test.locations.span(&self.body);
 
                     if let Some(lower_bound_region) = lower_bound_region {
+                        let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx);
+                        let origin = RelateParamBound(type_test_span, generic_ty, None);
                         self.buffer_error(self.infcx.construct_generic_bound_failure(
                             type_test_span,
-                            None,
+                            Some(origin),
                             type_test.generic_kind,
                             lower_bound_region,
+                            self.body.source.def_id().as_local(),
                         ));
                     } else {
                         // FIXME. We should handle this case better. It
index 7742813888e535848e185b5404e6d85992aec197..459d4a783e40f06042bbd4f5660e5e35c53622a7 100644 (file)
@@ -575,7 +575,7 @@ fn match_adt_and_segment<'hir>(
                 Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime_span))
             }
 
-            hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Implicit(_) => {
+            hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Implicit => {
                 // In this case, the user left off the lifetime; so
                 // they wrote something like:
                 //
index 97233b930c395f839abe07d86a4b64640fc5ded7..fe5193102f958de004aa6b1fbcbd59fa9d00bfab 100644 (file)
@@ -74,14 +74,18 @@ fn for_each_constraint(
         let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
         constraints.sort_by_key(|c| (c.sup, c.sub));
         for constraint in &constraints {
-            let OutlivesConstraint { sup, sub, locations, category, variance_info: _ } = constraint;
+            let OutlivesConstraint { sup, sub, locations, category, span, variance_info: _ } =
+                constraint;
             let (name, arg) = match locations {
                 Locations::All(span) => {
                     ("All", tcx.sess.source_map().span_to_embeddable_string(*span))
                 }
                 Locations::Single(loc) => ("Single", format!("{:?}", loc)),
             };
-            with_msg(&format!("{:?}: {:?} due to {:?} at {}({})", sup, sub, category, name, arg))?;
+            with_msg(&format!(
+                "{:?}: {:?} due to {:?} at {}({}) ({:?}",
+                sup, sub, category, name, arg, span
+            ))?;
         }
 
         Ok(())
index dabf61715ce58fb78bb4239dd40ab501932c061e..cf03f34a4ec5fbb03b2a76e6e8434ea49dbdc832 100644 (file)
@@ -1733,7 +1733,7 @@ fn check_member_constraints(
 
     crate fn retrieve_closure_constraint_info(
         &self,
-        body: &Body<'tcx>,
+        _body: &Body<'tcx>,
         constraint: &OutlivesConstraint<'tcx>,
     ) -> BlameConstraint<'tcx> {
         let loc = match constraint.locations {
@@ -1760,7 +1760,7 @@ fn check_member_constraints(
             .unwrap_or(BlameConstraint {
                 category: constraint.category,
                 from_closure: false,
-                cause: ObligationCause::dummy_with_span(body.source_info(loc).span),
+                cause: ObligationCause::dummy_with_span(constraint.span),
                 variance_info: constraint.variance_info,
             })
     }
@@ -1869,6 +1869,7 @@ fn check_member_constraints(
                     sup: r,
                     sub: constraint.min_choice,
                     locations: Locations::All(p_c.definition_span),
+                    span: p_c.definition_span,
                     category: ConstraintCategory::OpaqueType,
                     variance_info: ty::VarianceDiagInfo::default(),
                 };
@@ -2017,7 +2018,7 @@ fn check_member_constraints(
                         category: constraint.category,
                         from_closure: false,
                         cause: ObligationCause::new(
-                            constraint.locations.span(body),
+                            constraint.span,
                             CRATE_HIR_ID,
                             cause_code.clone(),
                         ),
index 5022cb98b821d0786565e1a81cbc76e60d0f6396..21190a850b7b1eb33d8129fa3c85022ca4c3e112 100644 (file)
@@ -8,7 +8,7 @@
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::TypeFoldable;
 use rustc_middle::ty::{self, TyCtxt};
-use rustc_span::DUMMY_SP;
+use rustc_span::{Span, DUMMY_SP};
 
 use crate::{
     constraints::OutlivesConstraint,
@@ -26,6 +26,7 @@
     implicit_region_bound: Option<ty::Region<'tcx>>,
     param_env: ty::ParamEnv<'tcx>,
     locations: Locations,
+    span: Span,
     category: ConstraintCategory,
     constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
 }
@@ -38,6 +39,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
         implicit_region_bound: Option<ty::Region<'tcx>>,
         param_env: ty::ParamEnv<'tcx>,
         locations: Locations,
+        span: Span,
         category: ConstraintCategory,
         constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
     ) -> Self {
@@ -49,6 +51,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
             implicit_region_bound,
             param_env,
             locations,
+            span,
             category,
             constraints,
         }
@@ -153,6 +156,7 @@ fn add_outlives(&mut self, sup: ty::RegionVid, sub: ty::RegionVid) {
         self.constraints.outlives_constraints.push(OutlivesConstraint {
             locations: self.locations,
             category: self.category,
+            span: self.span,
             sub,
             sup,
             variance_info: ty::VarianceDiagInfo::default(),
index f8439d2e163559f5c51faa2364f18c15b2dc1aed..f08f2e1b12da6439fc574adcafe272119e481c33 100644 (file)
@@ -316,6 +316,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
                 self.implicit_region_bound,
                 self.param_env,
                 Locations::All(DUMMY_SP),
+                DUMMY_SP,
                 ConstraintCategory::Internal,
                 &mut self.constraints,
             )
index 83c8ecba1f17aa78d86d2af0a8a8c76dbc69bf06..e6f996491a41b7031b2420d00fc2e9b4266c52e8 100644 (file)
@@ -235,6 +235,7 @@ pub(crate) fn normalize_and_add_constraints(&mut self, t: Ty<'tcx>) -> Fallible<
                 Some(self.implicit_region_bound),
                 self.param_env,
                 Locations::All(DUMMY_SP),
+                DUMMY_SP,
                 ConstraintCategory::Internal,
                 &mut self.borrowck_context.constraints,
             )
index ece801716b2dbacc6715dc87e2d37113304fce63..6dcdd46816e0dbea5a284ec8a88ffa306cbde90a 100644 (file)
@@ -1141,6 +1141,7 @@ fn push_region_constraints(
             Some(self.implicit_region_bound),
             self.param_env,
             locations,
+            locations.span(self.body),
             category,
             &mut self.borrowck_context.constraints,
         )
@@ -2401,6 +2402,7 @@ fn add_reborrow_constraint(
                                 sup: ref_region.to_region_vid(),
                                 sub: borrow_region.to_region_vid(),
                                 locations: location.to_locations(),
+                                span: location.to_locations().span(body),
                                 category,
                                 variance_info: ty::VarianceDiagInfo::default(),
                             });
index f0106630797d33d91f4cf771d22759a272c80d77..f98d2c3128c524ed7f27c20ce13719c7284009db 100644 (file)
@@ -116,6 +116,7 @@ fn push_outlives(
                 sup,
                 sub,
                 locations: self.locations,
+                span: self.locations.span(self.type_checker.body),
                 category: self.category,
                 variance_info: info,
             },
index 57ef46475ddd860e3f4423bf37cba037b0f04596..030295d3d8dc382e296c1b01dc7f7ecfeeb35c2e 100644 (file)
@@ -154,17 +154,19 @@ pub fn parse_asm_args<'a>(
         } else if p.eat_keyword(kw::Const) {
             let anon_const = p.parse_anon_const_expr()?;
             ast::InlineAsmOperand::Const { anon_const }
-        } else if !is_global_asm && p.eat_keyword(sym::sym) {
+        } else if p.eat_keyword(sym::sym) {
             let expr = p.parse_expr()?;
-            match expr.kind {
-                ast::ExprKind::Path(..) => {}
-                _ => {
-                    let err = diag
-                        .struct_span_err(expr.span, "argument to `sym` must be a path expression");
-                    return Err(err);
-                }
-            }
-            ast::InlineAsmOperand::Sym { expr }
+            let ast::ExprKind::Path(qself, path) = &expr.kind else {
+                let err = diag
+                    .struct_span_err(expr.span, "expected a path for argument to `sym`");
+                return Err(err);
+            };
+            let sym = ast::InlineAsmSym {
+                id: ast::DUMMY_NODE_ID,
+                qself: qself.clone(),
+                path: path.clone(),
+            };
+            ast::InlineAsmOperand::Sym { sym }
         } else if allow_templates {
             let template = p.parse_expr()?;
             // If it can't possibly expand to a string, provide diagnostics here to include other
index 30e9627c48d749f17324ba2dab559af13ba4e956..7b8e43b639f993f97aec41c1da60d8775fdb613a 100644 (file)
@@ -33,18 +33,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "cranelift-bforest"
-version = "0.82.1"
+version = "0.83.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d16922317bd7dd104d509a373887822caa0242fc1def00de66abb538db221db4"
+checksum = "ed44413e7e2fe3260d0ed73e6956ab188b69c10ee92b892e401e0f4f6808c68b"
 dependencies = [
  "cranelift-entity",
 ]
 
 [[package]]
 name = "cranelift-codegen"
-version = "0.82.1"
+version = "0.83.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b80bf40380256307b68a3dcbe1b91cac92a533e212b5b635abc3e4525781a0a"
+checksum = "0b5d83f0f26bf213f971f45589d17e5b65e4861f9ed22392b0cbb6eaa5bd329c"
 dependencies = [
  "cranelift-bforest",
  "cranelift-codegen-meta",
@@ -59,30 +59,30 @@ dependencies = [
 
 [[package]]
 name = "cranelift-codegen-meta"
-version = "0.82.1"
+version = "0.83.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "703d0ed7d3bc6c7a814ca12858175bf4e93167a3584127858c686e4b5dd6e432"
+checksum = "6800dc386177df6ecc5a32680607ed8ba1fa0d31a2a59c8c61fbf44826b8191d"
 dependencies = [
  "cranelift-codegen-shared",
 ]
 
 [[package]]
 name = "cranelift-codegen-shared"
-version = "0.82.1"
+version = "0.83.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80f52311e1c90de12dcf8c4b9999c6ebfd1ed360373e88c357160936844511f6"
+checksum = "c961f85070985ebc8fcdb81b838a5cf842294d1e6ed4852446161c7e246fd455"
 
 [[package]]
 name = "cranelift-entity"
-version = "0.82.1"
+version = "0.83.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66bc82ef522c1f643baf7d4d40b7c52643ee4549d8960b0e6a047daacb83f897"
+checksum = "2347b2b8d1d5429213668f2a8e36c85ee3c73984a2f6a79007e365d3e575e7ed"
 
 [[package]]
 name = "cranelift-frontend"
-version = "0.82.1"
+version = "0.83.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3cc35e4251864b17515845ba47447bca88fec9ca1a4186b19fe42526e36140e8"
+checksum = "4cbcdbf7bed29e363568b778649b69dabc3d727256d5d25236096ef693757654"
 dependencies = [
  "cranelift-codegen",
  "log",
@@ -92,9 +92,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-jit"
-version = "0.82.1"
+version = "0.83.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93c66d594ad3bfe4e58b1fbd8d17877a7c6564a5f2d6f78cbbf4b0182af1927f"
+checksum = "7c769d4e0d76f59c8b2a3bf0477d89ee149bb0731b53fbb245ee081d49063095"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -110,9 +110,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-module"
-version = "0.82.1"
+version = "0.83.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf356697c40232aa09e1e3fb8a350ee894e849ccecc4eac56ff0570a4575c325"
+checksum = "0ab57d399a2401074bb0cc40b3031e420f3d66d46ec0cf21eeae53ac04bd73e2"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -120,9 +120,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-native"
-version = "0.82.1"
+version = "0.83.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b882b2251c9845d509d92aebfdb6c8bb3b3b48e207ac951f21fbd20cfe7f90b3"
+checksum = "8f4cdf93552e5ceb2e3c042829ebb4de4378492705f769eadc6a7c6c5251624c"
 dependencies = [
  "cranelift-codegen",
  "libc",
@@ -131,9 +131,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-object"
-version = "0.82.1"
+version = "0.83.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d3f1a88e654e567d2591169239ed157ab290811a729a6468f53999c01001263"
+checksum = "cf8e65f4839c26e6237fc0744911d79b0a2ac5e76b4e4eebd14db2b8d849fd31"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
index 70c03da3f29fa9808169e415ae6417cb99e3eefd..74f50808a980a7de298a943e74ac3c4301f07473 100644 (file)
@@ -8,12 +8,12 @@ crate-type = ["dylib"]
 
 [dependencies]
 # These have to be in sync with each other
-cranelift-codegen = { version = "0.82.1", features = ["unwind", "all-arch"] }
-cranelift-frontend = "0.82.1"
-cranelift-module = "0.82.1"
-cranelift-native = "0.82.1"
-cranelift-jit = { version = "0.82.1", optional = true }
-cranelift-object = "0.82.1"
+cranelift-codegen = { version = "0.83.0", features = ["unwind", "all-arch"] }
+cranelift-frontend = "0.83.0"
+cranelift-module = "0.83.0"
+cranelift-native = "0.83.0"
+cranelift-jit = { version = "0.83.0", optional = true }
+cranelift-object = "0.83.0"
 target-lexicon = "0.12.0"
 gimli = { version = "0.26.0", default-features = false, features = ["write"]}
 object = { version = "0.27.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
index f584f54e106ac060900e01924f65d5e0a17804df..51ba0dbfcc7920e2868531cc897bd70c48a9909b 100644 (file)
@@ -56,9 +56,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.71"
+version = "0.1.72"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "163437f05ca8f29d7e9128ea728dedf5eb620e445fbca273641d3a3050305f23"
+checksum = "afdbb35d279238cf77f0c9e8d90ad50d6c7bff476ab342baafa29440f0f10bff"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -134,9 +134,9 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.121"
+version = "0.2.124"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f"
+checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -203,6 +203,7 @@ dependencies = [
 name = "proc_macro"
 version = "0.0.0"
 dependencies = [
+ "core",
  "std",
 ]
 
diff --git a/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs b/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs
new file mode 100644 (file)
index 0000000..b8f901d
--- /dev/null
@@ -0,0 +1,53 @@
+// Copied from https://github.com/rust-lang/rust/blob/3fe3b89cd57229343eeca753fdd8c63d9b03c65c/src/test/ui/simd/intrinsic/float-minmax-pass.rs
+// run-pass
+// ignore-emscripten
+
+// Test that the simd_f{min,max} intrinsics produce the correct results.
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+    fn simd_fmin<T>(x: T, y: T) -> T;
+    fn simd_fmax<T>(x: T, y: T) -> T;
+}
+
+fn main() {
+    let x = f32x4(1.0, 2.0, 3.0, 4.0);
+    let y = f32x4(2.0, 1.0, 4.0, 3.0);
+
+    #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))]
+    let nan = f32::NAN;
+    // MIPS hardware treats f32::NAN as SNAN. Clear the signaling bit.
+    // See https://github.com/rust-lang/rust/issues/52746.
+    #[cfg(any(target_arch = "mips", target_arch = "mips64"))]
+    let nan = f32::from_bits(f32::NAN.to_bits() - 1);
+
+    let n = f32x4(nan, nan, nan, nan);
+
+    unsafe {
+        let min0 = simd_fmin(x, y);
+        let min1 = simd_fmin(y, x);
+        assert_eq!(min0, min1);
+        let e = f32x4(1.0, 1.0, 3.0, 3.0);
+        assert_eq!(min0, e);
+        let minn = simd_fmin(x, n);
+        assert_eq!(minn, x);
+        let minn = simd_fmin(y, n);
+        assert_eq!(minn, y);
+
+        let max0 = simd_fmax(x, y);
+        let max1 = simd_fmax(y, x);
+        assert_eq!(max0, max1);
+        let e = f32x4(2.0, 2.0, 4.0, 4.0);
+        assert_eq!(max0, e);
+        let maxn = simd_fmax(x, n);
+        assert_eq!(maxn, x);
+        let maxn = simd_fmax(y, n);
+        assert_eq!(maxn, y);
+    }
+}
index 7efc8dc785a1912476b3d6e93e9f3f5896d6e39c..8da705e0cb06dbf7f0232bdad8e9ab6f899636d8 100644 (file)
@@ -16,6 +16,9 @@
 #[lang = "sized"]
 pub trait Sized {}
 
+#[lang = "destruct"]
+pub trait Destruct {}
+
 #[lang = "unsize"]
 pub trait Unsize<T: ?Sized> {}
 
@@ -491,13 +494,20 @@ pub trait Deref {
     fn deref(&self) -> &Self::Target;
 }
 
+#[repr(transparent)]
+#[rustc_layout_scalar_valid_range_start(1)]
+#[rustc_nonnull_optimization_guaranteed]
+pub struct NonNull<T: ?Sized>(pub *mut T);
+
+impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
+
 pub struct Unique<T: ?Sized> {
-    pub pointer: *const T,
+    pub pointer: NonNull<T>,
     pub _marker: PhantomData<T>,
 }
 
 impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> {}
-
 impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> {}
 
 #[lang = "owned_box"]
@@ -526,7 +536,7 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
 
 #[lang = "box_free"]
 unsafe fn box_free<T: ?Sized>(ptr: Unique<T>, alloc: ()) {
-    libc::free(ptr.pointer as *mut u8);
+    libc::free(ptr.pointer.0 as *mut u8);
 }
 
 #[lang = "drop"]
index c4730581335ecbffa29d3c58fc1cfc187b052b86..85ca908d0a266f2e1012ea4d166d1068d7e538dc 100644 (file)
@@ -122,7 +122,7 @@ fn call_return_u128_pair() {
 #[allow(unreachable_code)] // FIXME false positive
 fn main() {
     take_unique(Unique {
-        pointer: 0 as *const (),
+        pointer: unsafe { NonNull(1 as *mut ()) },
         _marker: PhantomData,
     });
     take_f32(0.1);
@@ -173,7 +173,7 @@ fn main() {
         assert!(intrinsics::needs_drop::<NoisyDrop>());
 
         Unique {
-            pointer: 0 as *const &str,
+            pointer: NonNull(1 as *mut &str),
             _marker: PhantomData,
         } as Unique<dyn SomeTrait>;
 
index 5bc51a541b58c7d63b0939976ab2d8869983d24b..0a2bce2621d963f1e6d68e173c5f65522c108a89 100644 (file)
@@ -1,7 +1,8 @@
-#![feature(core_intrinsics, generators, generator_trait, is_sorted)]
+#![feature(core_intrinsics, generators, generator_trait, is_sorted, bench_black_box)]
 
 #[cfg(target_arch = "x86_64")]
 use std::arch::x86_64::*;
+use std::hint::black_box;
 use std::io::Write;
 use std::ops::Generator;
 
@@ -86,6 +87,9 @@ fn main() {
     assert_eq!(houndred_f64 as i128, 100);
     assert_eq!(1u128.rotate_left(2), 4);
 
+    assert_eq!(black_box(f32::NAN) as i128, 0);
+    assert_eq!(black_box(f32::NAN) as u128, 0);
+
     // Test signed 128bit comparing
     let max = usize::MAX as i128;
     if 100i128 < 0i128 || 100i128 > max {
index c13259086917b9c8e996dd8b88d7a142137a0bc5..54e13b090abda43a8d66147207b16c09c27dae64 100644 (file)
@@ -102,42 +102,6 @@ index 6a8ecd3..68fcb49 100644
          }
      }
  }
-diff --git a/crates/core_simd/tests/ops_macros.rs b/crates/core_simd/tests/ops_macros.rs
-index 31b7ee2..bd04b3c 100644
---- a/crates/core_simd/tests/ops_macros.rs
-+++ b/crates/core_simd/tests/ops_macros.rs
-@@ -567,6 +567,7 @@ macro_rules! impl_float_tests {
-                     });
-                 }
-+                /*
-                 fn horizontal_max<const LANES: usize>() {
-                     test_helpers::test_1(&|x| {
-                         let vmax = Vector::<LANES>::from_array(x).horizontal_max();
-@@ -590,6 +591,7 @@ macro_rules! impl_float_tests {
-                         Ok(())
-                     });
-                 }
-+                */
-             }
-             #[cfg(feature = "std")]
-@@ -604,6 +606,7 @@ macro_rules! impl_float_tests {
-                         )
-                     }
-+                    /*
-                     fn mul_add<const LANES: usize>() {
-                         test_helpers::test_ternary_elementwise(
-                             &Vector::<LANES>::mul_add,
-@@ -611,6 +614,7 @@ macro_rules! impl_float_tests {
-                             &|_, _, _| true,
-                         )
-                     }
-+                    */
-                 }
-             }
-         }
 -- 
 2.26.2.7.g19db9cfb68
 
index 84d90e5db02539c3edcc72c5fed578f41368e06c..966097c248b6f6c98d6d250a369f5df0b8d797c9 100644 (file)
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2022-03-19"
+channel = "nightly-2022-04-21"
 components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
index a0e99267c2b705771b9c9cfee2e11a41c12a5cf1..f4e863e5494b51f34154bfc0730cd9758e73b999 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 #![forbid(unsafe_code)]/* This line is ignored by bash
 # This block is ignored by rustc
 pushd $(dirname "$0")/../
index 85c0109c6f61eb6932889a6cd667e0c31cd4f352..cabbaaa8922517351dc70eeb3bb0730f752b0c17 100644 (file)
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 set -e
 
 ./y.rs build --no-unstable-features
index a32e6df220832847efaef3e86f5dd1b402dc3d5f..4cf24c02235df731a81e36def7900d4c9e390afd 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 set -e
 
 cd $(dirname "$0")/../
@@ -11,7 +11,7 @@ pushd rust
 command -v rg >/dev/null 2>&1 || cargo install ripgrep
 
 rm -r src/test/ui/{extern/,unsized-locals/,lto/,linkage*} || true
-for test in $(rg --files-with-matches "asm!|lto|// needs-asm-support|// needs-unwind" src/test/{ui,incremental}); do
+for test in $(rg --files-with-matches "lto|// needs-asm-support|// needs-unwind" src/test/{ui,incremental}); do
   rm $test
 done
 
@@ -25,14 +25,8 @@ git checkout -- src/test/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR
 # ================
 
 # requires stack unwinding
-rm src/test/ui/backtrace.rs
-rm src/test/ui/process/multi-panic.rs
-rm src/test/ui/numbers-arithmetic/issue-8460.rs
 rm src/test/incremental/change_crate_dep_kind.rs
 rm src/test/incremental/issue-80691-bad-eval-cache.rs # -Cpanic=abort causes abort instead of exit(101)
-rm src/test/ui/panic-while-printing.rs
-rm src/test/ui/test-attrs/test-panic-while-printing.rs
-rm src/test/ui/test-attrs/test-type.rs
 
 # requires compiling with -Cpanic=unwind
 rm src/test/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs # "Cannot run dynamic test fn out-of-process"
@@ -85,8 +79,6 @@ rm src/test/ui/abi/stack-protector.rs # requires stack protector support
 
 # giving different but possibly correct results
 # =============================================
-rm src/test/ui/numbers-arithmetic/saturating-float-casts.rs # intrinsic gives different but valid result
-rm src/test/ui/simd/intrinsic/float-minmax-pass.rs # same
 rm src/test/ui/mir/mir_misc_casts.rs # depends on deduplication of constants
 rm src/test/ui/mir/mir_raw_fat_ptr.rs # same
 rm src/test/ui/consts/issue-33537.rs # same
@@ -112,9 +104,14 @@ rm src/test/ui/mir/ssa-analysis-regression-50041.rs # produces ICE
 
 rm src/test/ui/simd/intrinsic/generic-reduction-pass.rs # simd_reduce_add_unordered doesn't accept an accumulator for integer vectors
 
+rm src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs # wrong result from `Location::caller()`
+
 # bugs in the test suite
 # ======================
-rm src/test/ui/unsafe/union.rs # has UB caught by cg_clif. see rust-lang/rust#95075
+rm src/test/ui/backtrace.rs # TODO warning
+rm src/test/ui/empty_global_asm.rs # TODO add needs-asm-support
+rm src/test/ui/simple_global_asm.rs # TODO add needs-asm-support
+rm src/test/ui/test-attrs/test-type.rs # TODO panic message on stderr. correct stdout
 
 echo "[TEST] rustc test suite"
 RUST_TEST_NOCAPTURE=1 COMPILETEST_FORCE_STAGE0=1 ./x.py test --stage 0 src/test/{codegen-units,run-make,run-pass-valgrind,ui,incremental}
index fee1012c8f1dc4196df3f6e8293c75f24faa315d..aae626081f62be5c93b3e7d92c08c811105c4d8f 100755 (executable)
@@ -72,6 +72,10 @@ function base_sysroot_tests() {
     $MY_RUSTC example/track-caller-attribute.rs --crate-type bin -Cpanic=abort --target "$TARGET_TRIPLE"
     $RUN_WRAPPER ./target/out/track-caller-attribute
 
+    echo "[AOT] float-minmax-pass"
+    $MY_RUSTC example/float-minmax-pass.rs --crate-type bin -Cpanic=abort --target "$TARGET_TRIPLE"
+    $RUN_WRAPPER ./target/out/float-minmax-pass
+
     echo "[AOT] mod_bench"
     $MY_RUSTC example/mod_bench.rs --crate-type bin --target "$TARGET_TRIPLE"
     $RUN_WRAPPER ./target/out/mod_bench
index 8c45993a8b76bf7e4a171be65c81def5e6e6025c..65346cb39622aa0e7bc2a7de747820af62b3d519 100644 (file)
@@ -821,7 +821,8 @@ pub(crate) fn codegen_place<'tcx>(
                 if cplace.layout().ty.is_box() {
                     cplace = cplace
                         .place_field(fx, Field::new(0)) // Box<T> -> Unique<T>
-                        .place_field(fx, Field::new(0)) // Unique<T> -> *const T
+                        .place_field(fx, Field::new(0)) // Unique<T> -> NonNull<T>
+                        .place_field(fx, Field::new(0)) // NonNull<T> -> *mut T
                         .place_deref(fx);
                 } else {
                     cplace = cplace.place_deref(fx);
index e7e6afeb865bb005bf436b7ec6e2802930dc7fe2..e19070774c6e0c246662f55ed06e4cf5a53f17e0 100644 (file)
@@ -84,7 +84,7 @@ pub(crate) fn clif_int_or_float_cast(
             fx.bcx.ins().fcvt_from_uint(to_ty, from)
         }
     } else if from_ty.is_float() && to_ty.is_int() {
-        if to_ty == types::I128 {
+        let val = if to_ty == types::I128 {
             // _____sssf___
             // __fix   sfti: f32 -> i128
             // __fix   dfti: f64 -> i128
@@ -109,13 +109,9 @@ pub(crate) fn clif_int_or_float_cast(
 
             let to_rust_ty = if to_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 };
 
-            return fx
-                .easy_call(&name, &[CValue::by_val(from, fx.layout_of(from_rust_ty))], to_rust_ty)
-                .load_scalar(fx);
-        }
-
-        // float -> int-like
-        if to_ty == types::I8 || to_ty == types::I16 {
+            fx.easy_call(&name, &[CValue::by_val(from, fx.layout_of(from_rust_ty))], to_rust_ty)
+                .load_scalar(fx)
+        } else if to_ty == types::I8 || to_ty == types::I16 {
             // FIXME implement fcvt_to_*int_sat.i8/i16
             let val = if to_signed {
                 fx.bcx.ins().fcvt_to_sint_sat(types::I32, from)
@@ -146,6 +142,23 @@ pub(crate) fn clif_int_or_float_cast(
             fx.bcx.ins().fcvt_to_sint_sat(to_ty, from)
         } else {
             fx.bcx.ins().fcvt_to_uint_sat(to_ty, from)
+        };
+
+        if let Some(false) = fx.tcx.sess.opts.debugging_opts.saturating_float_casts {
+            return val;
+        }
+
+        let is_not_nan = fx.bcx.ins().fcmp(FloatCC::Equal, from, from);
+        if to_ty == types::I128 {
+            // FIXME(bytecodealliance/wasmtime#3963): select.i128 on fcmp eq miscompiles
+            let (lsb, msb) = fx.bcx.ins().isplit(val);
+            let zero = fx.bcx.ins().iconst(types::I64, 0);
+            let lsb = fx.bcx.ins().select(is_not_nan, lsb, zero);
+            let msb = fx.bcx.ins().select(is_not_nan, msb, zero);
+            fx.bcx.ins().iconcat(lsb, msb)
+        } else {
+            let zero = fx.bcx.ins().iconst(to_ty, 0);
+            fx.bcx.ins().select(is_not_nan, val, zero)
         }
     } else if from_ty.is_float() && to_ty.is_float() {
         // float -> float
index eef3c8c8d6e2b38170209854f34c5c441ad59b5b..e59a0cb0a23237bfe0b4fd0164909db4d8a98e49 100644 (file)
@@ -48,12 +48,6 @@ pub struct BackendConfig {
     /// Can be set using `-Cllvm-args=display_cg_time=...`.
     pub display_cg_time: bool,
 
-    /// The register allocator to use.
-    ///
-    /// Defaults to the value of `CG_CLIF_REGALLOC` or `backtracking` otherwise. Can be set using
-    /// `-Cllvm-args=regalloc=...`.
-    pub regalloc: String,
-
     /// Enable the Cranelift ir verifier for all compilation passes. If not set it will only run
     /// once before passing the clif ir to Cranelift for compilation.
     ///
@@ -80,8 +74,6 @@ fn default() -> Self {
                 args.split(' ').map(|arg| arg.to_string()).collect()
             },
             display_cg_time: bool_env_var("CG_CLIF_DISPLAY_CG_TIME"),
-            regalloc: std::env::var("CG_CLIF_REGALLOC")
-                .unwrap_or_else(|_| "backtracking".to_string()),
             enable_verifier: cfg!(debug_assertions) || bool_env_var("CG_CLIF_ENABLE_VERIFIER"),
             disable_incr_cache: bool_env_var("CG_CLIF_DISABLE_INCR_CACHE"),
         }
@@ -101,7 +93,6 @@ fn parse_bool(name: &str, value: &str) -> Result<bool, String> {
                 match name {
                     "mode" => config.codegen_mode = value.parse()?,
                     "display_cg_time" => config.display_cg_time = parse_bool(name, value)?,
-                    "regalloc" => config.regalloc = value.to_string(),
                     "enable_verifier" => config.enable_verifier = parse_bool(name, value)?,
                     "disable_incr_cache" => config.disable_incr_cache = parse_bool(name, value)?,
                     _ => return Err(format!("Unknown option `{}`", name)),
index 357cb4a6d246fa451a1b42ff3413df5455ef3f81..f619bb5ed5e586ae33f5b7711095613bdad14472 100644 (file)
@@ -128,8 +128,16 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
             let relative_discr = if niche_start == 0 {
                 tag
             } else {
-                // FIXME handle niche_start > i64::MAX
-                fx.bcx.ins().iadd_imm(tag, -i64::try_from(niche_start).unwrap())
+                let niche_start = match fx.bcx.func.dfg.value_type(tag) {
+                    types::I128 => {
+                        let lsb = fx.bcx.ins().iconst(types::I64, niche_start as u64 as i64);
+                        let msb =
+                            fx.bcx.ins().iconst(types::I64, (niche_start >> 64) as u64 as i64);
+                        fx.bcx.ins().iconcat(lsb, msb)
+                    }
+                    ty => fx.bcx.ins().iconst(ty, niche_start as i64),
+                };
+                fx.bcx.ins().isub(tag, niche_start)
             };
             let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
             let is_niche = {
index 310d27c6decf6c87e66bd21a5148912eb0c9f070..d76dfca7960c4a220871c57b8fc1f020f5cab588 100644 (file)
@@ -1019,39 +1019,23 @@ fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value {
             ret.write_cvalue(fx, old);
         };
 
-        // In Rust floating point min and max don't propagate NaN. In Cranelift they do however.
-        // For this reason it is necessary to use `a.is_nan() ? b : (a >= b ? b : a)` for `minnumf*`
-        // and `a.is_nan() ? b : (a <= b ? b : a)` for `maxnumf*`. NaN checks are done by comparing
-        // a float against itself. Only in case of NaN is it not equal to itself.
         minnumf32, (v a, v b) {
-            let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a);
-            let a_ge_b = fx.bcx.ins().fcmp(FloatCC::GreaterThanOrEqual, a, b);
-            let temp = fx.bcx.ins().select(a_ge_b, b, a);
-            let val = fx.bcx.ins().select(a_is_nan, b, temp);
+            let val = crate::num::codegen_float_min(fx, a, b);
             let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32));
             ret.write_cvalue(fx, val);
         };
         minnumf64, (v a, v b) {
-            let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a);
-            let a_ge_b = fx.bcx.ins().fcmp(FloatCC::GreaterThanOrEqual, a, b);
-            let temp = fx.bcx.ins().select(a_ge_b, b, a);
-            let val = fx.bcx.ins().select(a_is_nan, b, temp);
+            let val = crate::num::codegen_float_min(fx, a, b);
             let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64));
             ret.write_cvalue(fx, val);
         };
         maxnumf32, (v a, v b) {
-            let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a);
-            let a_le_b = fx.bcx.ins().fcmp(FloatCC::LessThanOrEqual, a, b);
-            let temp = fx.bcx.ins().select(a_le_b, b, a);
-            let val = fx.bcx.ins().select(a_is_nan, b, temp);
+            let val = crate::num::codegen_float_max(fx, a, b);
             let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32));
             ret.write_cvalue(fx, val);
         };
         maxnumf64, (v a, v b) {
-            let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a);
-            let a_le_b = fx.bcx.ins().fcmp(FloatCC::LessThanOrEqual, a, b);
-            let temp = fx.bcx.ins().select(a_le_b, b, a);
-            let val = fx.bcx.ins().select(a_is_nan, b, temp);
+            let val = crate::num::codegen_float_max(fx, a, b);
             let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64));
             ret.write_cvalue(fx, val);
         };
index bc21d736166277ce3f664fe926b17adb34841578..d1ca9edf2e0f1bb578889566bc8384c5bf5bfc1c 100644 (file)
@@ -322,20 +322,21 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
             }
             assert_eq!(a.layout(), b.layout());
             assert_eq!(a.layout(), c.layout());
-            let layout = a.layout();
+            assert_eq!(a.layout(), ret.layout());
 
-            let (lane_count, _lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
-            let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
-            assert_eq!(lane_count, ret_lane_count);
-            let ret_lane_layout = fx.layout_of(ret_lane_ty);
+            let layout = a.layout();
+            let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
 
             for lane in 0..lane_count {
-                let a_lane = a.value_lane(fx, lane).load_scalar(fx);
-                let b_lane = b.value_lane(fx, lane).load_scalar(fx);
-                let c_lane = c.value_lane(fx, lane).load_scalar(fx);
+                let a_lane = a.value_lane(fx, lane);
+                let b_lane = b.value_lane(fx, lane);
+                let c_lane = c.value_lane(fx, lane);
 
-                let mul_lane = fx.bcx.ins().fmul(a_lane, b_lane);
-                let res_lane = CValue::by_val(fx.bcx.ins().fadd(mul_lane, c_lane), ret_lane_layout);
+                let res_lane = match lane_ty.kind() {
+                    ty::Float(FloatTy::F32) => fx.easy_call("fmaf", &[a_lane, b_lane, c_lane], lane_ty),
+                    ty::Float(FloatTy::F64) => fx.easy_call("fma", &[a_lane, b_lane, c_lane], lane_ty),
+                    _ => unreachable!(),
+                };
 
                 ret.place_lane(fx, lane).write_cvalue(fx, res_lane);
             }
@@ -354,8 +355,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
                     _ => unreachable!("{:?}", lane_ty),
                 }
                 match intrinsic {
-                    sym::simd_fmin => fx.bcx.ins().fmin(x_lane, y_lane),
-                    sym::simd_fmax => fx.bcx.ins().fmax(x_lane, y_lane),
+                    sym::simd_fmin => crate::num::codegen_float_min(fx, x_lane, y_lane),
+                    sym::simd_fmax => crate::num::codegen_float_max(fx, x_lane, y_lane),
                     _ => unreachable!(),
                 }
             });
@@ -495,7 +496,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
                 let lt = match ty.kind() {
                     ty::Int(_) => fx.bcx.ins().icmp(IntCC::SignedLessThan, a, b),
                     ty::Uint(_) => fx.bcx.ins().icmp(IntCC::UnsignedLessThan, a, b),
-                    ty::Float(_) => fx.bcx.ins().fcmp(FloatCC::LessThan, a, b),
+                    ty::Float(_) => return crate::num::codegen_float_min(fx, a, b),
                     _ => unreachable!(),
                 };
                 fx.bcx.ins().select(lt, a, b)
@@ -512,7 +513,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
                 let gt = match ty.kind() {
                     ty::Int(_) => fx.bcx.ins().icmp(IntCC::SignedGreaterThan, a, b),
                     ty::Uint(_) => fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, a, b),
-                    ty::Float(_) => fx.bcx.ins().fcmp(FloatCC::GreaterThan, a, b),
+                    ty::Float(_) => return crate::num::codegen_float_max(fx, a, b),
                     _ => unreachable!(),
                 };
                 fx.bcx.ins().select(gt, a, b)
index 878b9390e1318c6c650cf56fb0ed6a3b1c132682..9d2e12f98984ae366b37472015543a0adcee4559 100644 (file)
@@ -256,8 +256,6 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::Tar
 
     flags_builder.set("enable_llvm_abi_extensions", "true").unwrap();
 
-    flags_builder.set("regalloc", &backend_config.regalloc).unwrap();
-
     use rustc_session::config::OptLevel;
     match sess.opts.optimize {
         OptLevel::No => {
index 545d390e269957f1ef94c48b83d2c1e10b5f953f..4ce8adb182e0fab68756d06f3fad196f1bf5a770 100644 (file)
@@ -420,3 +420,21 @@ pub(crate) fn codegen_ptr_binop<'tcx>(
         CValue::by_val(fx.bcx.ins().bint(types::I8, res), fx.layout_of(fx.tcx.types.bool))
     }
 }
+
+// In Rust floating point min and max don't propagate NaN. In Cranelift they do however.
+// For this reason it is necessary to use `a.is_nan() ? b : (a >= b ? b : a)` for `minnumf*`
+// and `a.is_nan() ? b : (a <= b ? b : a)` for `maxnumf*`. NaN checks are done by comparing
+// a float against itself. Only in case of NaN is it not equal to itself.
+pub(crate) fn codegen_float_min(fx: &mut FunctionCx<'_, '_, '_>, a: Value, b: Value) -> Value {
+    let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a);
+    let a_ge_b = fx.bcx.ins().fcmp(FloatCC::GreaterThanOrEqual, a, b);
+    let temp = fx.bcx.ins().select(a_ge_b, b, a);
+    fx.bcx.ins().select(a_is_nan, b, temp)
+}
+
+pub(crate) fn codegen_float_max(fx: &mut FunctionCx<'_, '_, '_>, a: Value, b: Value) -> Value {
+    let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a);
+    let a_le_b = fx.bcx.ins().fcmp(FloatCC::LessThanOrEqual, a, b);
+    let temp = fx.bcx.ins().select(a_le_b, b, a);
+    fx.bcx.ins().select(a_is_nan, b, temp)
+}
index 8a74c4c07e0cf2ba331aec30a9839942b7ce0d99..2e8cd934eb2986fb22f6633618722ec912ab8f44 100644 (file)
@@ -258,9 +258,14 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
                 }
 
                 InlineAsmOperandRef::SymFn { instance } => {
+                    // TODO(@Amanieu): Additional mangling is needed on
+                    // some targets to add a leading underscore (Mach-O)
+                    // or byte count suffixes (x86 Windows).
                     constants_len += self.tcx.symbol_name(instance).name.len();
                 }
                 InlineAsmOperandRef::SymStatic { def_id } => {
+                    // TODO(@Amanieu): Additional mangling is needed on
+                    // some targets to add a leading underscore (Mach-O).
                     constants_len += self.tcx.symbol_name(Instance::mono(self.tcx, def_id)).name.len();
                 }
             }
@@ -412,13 +417,16 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
                         }
 
                         InlineAsmOperandRef::SymFn { instance } => {
+                            // TODO(@Amanieu): Additional mangling is needed on
+                            // some targets to add a leading underscore (Mach-O)
+                            // or byte count suffixes (x86 Windows).
                             let name = self.tcx.symbol_name(instance).name;
                             template_str.push_str(name);
                         }
 
                         InlineAsmOperandRef::SymStatic { def_id } => {
-                            // TODO(@Commeownist): This may not be sufficient for all kinds of statics.
-                            // Some statics may need the `@plt` suffix, like thread-local vars.
+                            // TODO(@Amanieu): Additional mangling is needed on
+                            // some targets to add a leading underscore (Mach-O).
                             let instance = Instance::mono(self.tcx, def_id);
                             let name = self.tcx.symbol_name(instance).name;
                             template_str.push_str(name);
@@ -581,6 +589,7 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
             | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x",
             InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
             InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => unimplemented!(),
+            InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg0) => unimplemented!(),
             InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => unimplemented!(),
             InlineAsmRegClass::X86(
                 X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg,
@@ -646,6 +655,7 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
         | InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(),
         InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg) => unimplemented!(),
         InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(),
+        InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg0) => cx.type_i16(),
         InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(),
         InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
             bug!("LLVM backend does not support SPIR-V")
@@ -656,8 +666,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
     }
 }
 
-impl<'gcc, 'tcx> AsmMethods for CodegenCx<'gcc, 'tcx> {
-    fn codegen_global_asm(&self, template: &[InlineAsmTemplatePiece], operands: &[GlobalAsmOperandRef], options: InlineAsmOptions, _line_spans: &[Span]) {
+impl<'gcc, 'tcx> AsmMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
+    fn codegen_global_asm(&self, template: &[InlineAsmTemplatePiece], operands: &[GlobalAsmOperandRef<'tcx>], options: InlineAsmOptions, _line_spans: &[Span]) {
         let asm_arch = self.tcx.sess.asm_arch.unwrap();
 
         // Default to Intel syntax on x86
@@ -690,6 +700,22 @@ fn codegen_global_asm(&self, template: &[InlineAsmTemplatePiece], operands: &[Gl
                             // here unlike normal inline assembly.
                             template_str.push_str(string);
                         }
+
+                        GlobalAsmOperandRef::SymFn { instance } => {
+                            // TODO(@Amanieu): Additional mangling is needed on
+                            // some targets to add a leading underscore (Mach-O)
+                            // or byte count suffixes (x86 Windows).
+                            let name = self.tcx.symbol_name(instance).name;
+                            template_str.push_str(name);
+                        }
+
+                        GlobalAsmOperandRef::SymStatic { def_id } => {
+                            // TODO(@Amanieu): Additional mangling is needed on
+                            // some targets to add a leading underscore (Mach-O).
+                            let instance = Instance::mono(self.tcx, def_id);
+                            let name = self.tcx.symbol_name(instance).name;
+                            template_str.push_str(name);
+                        }
                     }
                 }
             }
@@ -760,6 +786,7 @@ fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option
             _ => unreachable!(),
         },
         InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None,
+        InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg0) => None,
         InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg) => {
             unreachable!("clobber-only")
         }
index b503bd020f6bb87a24267ca96edeb177fc06df43..efcf18d31eb09a69d345f94f5081b16b3612a20c 100644 (file)
@@ -11,7 +11,7 @@
 use crate::{GccCodegenBackend, GccContext};
 
 pub(crate) unsafe fn codegen(cgcx: &CodegenContext<GccCodegenBackend>, _diag_handler: &Handler, module: ModuleCodegen<GccContext>, config: &ModuleConfig) -> Result<CompiledModule, FatalError> {
-    let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen", &module.name[..]);
+    let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen", &*module.name);
     {
         let context = &module.module_llvm.context;
 
index 91d132eb34350d762d8cd688fa2d8d78e6b7a302..e994001f96fd9b47cd6fa2e3c550c9ee1351b04d 100644 (file)
@@ -312,11 +312,11 @@ fn codegen_inline_asm(
     }
 }
 
-impl AsmMethods for CodegenCx<'_, '_> {
+impl<'tcx> AsmMethods<'tcx> for CodegenCx<'_, 'tcx> {
     fn codegen_global_asm(
         &self,
         template: &[InlineAsmTemplatePiece],
-        operands: &[GlobalAsmOperandRef],
+        operands: &[GlobalAsmOperandRef<'tcx>],
         options: InlineAsmOptions,
         _line_spans: &[Span],
     ) {
@@ -342,6 +342,29 @@ fn codegen_global_asm(
                             // here unlike normal inline assembly.
                             template_str.push_str(string);
                         }
+                        GlobalAsmOperandRef::SymFn { instance } => {
+                            let llval = self.get_fn(instance);
+                            self.add_compiler_used_global(llval);
+                            let symbol = llvm::build_string(|s| unsafe {
+                                llvm::LLVMRustGetMangledName(llval, s);
+                            })
+                            .expect("symbol is not valid UTF-8");
+                            template_str.push_str(&symbol);
+                        }
+                        GlobalAsmOperandRef::SymStatic { def_id } => {
+                            let llval = self
+                                .renamed_statics
+                                .borrow()
+                                .get(&def_id)
+                                .copied()
+                                .unwrap_or_else(|| self.get_static(def_id));
+                            self.add_compiler_used_global(llval);
+                            let symbol = llvm::build_string(|s| unsafe {
+                                llvm::LLVMRustGetMangledName(llval, s);
+                            })
+                            .expect("symbol is not valid UTF-8");
+                            template_str.push_str(&symbol);
+                        }
                     }
                 }
             }
@@ -579,7 +602,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
             InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
             InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "^Yk",
             InlineAsmRegClass::X86(
-                X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg,
+                X86InlineAsmRegClass::x87_reg
+                | X86InlineAsmRegClass::mmx_reg
+                | X86InlineAsmRegClass::kreg0,
             ) => unreachable!("clobber-only"),
             InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
             InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
@@ -664,7 +689,11 @@ fn modifier_to_llvm(
             _ => unreachable!(),
         },
         InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None,
-        InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg) => {
+        InlineAsmRegClass::X86(
+            X86InlineAsmRegClass::x87_reg
+            | X86InlineAsmRegClass::mmx_reg
+            | X86InlineAsmRegClass::kreg0,
+        ) => {
             unreachable!("clobber-only")
         }
         InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None,
@@ -734,7 +763,11 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'
         | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg)
         | InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(),
         InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(),
-        InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg) => {
+        InlineAsmRegClass::X86(
+            X86InlineAsmRegClass::x87_reg
+            | X86InlineAsmRegClass::mmx_reg
+            | X86InlineAsmRegClass::kreg0,
+        ) => {
             unreachable!("clobber-only")
         }
         InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(),
index 0f5b1c08ec2dc707920b85ec45c08aac2bde8193..7a747a9cdee4ead49b6894f5dc730a0ac94e729e 100644 (file)
@@ -313,7 +313,9 @@ fn fat_lto(
         for (bc_decoded, name) in serialized_modules {
             let _timer = cgcx
                 .prof
-                .generic_activity_with_arg("LLVM_fat_lto_link_module", format!("{:?}", name));
+                .generic_activity_with_arg_recorder("LLVM_fat_lto_link_module", |recorder| {
+                    recorder.record_arg(format!("{:?}", name))
+                });
             info!("linking {:?}", name);
             let data = bc_decoded.data();
             linker.add(data).map_err(|()| {
index c18719d4ad7391c7aa52c7ee129df4f4f0638729..7ef3b12cd08dab5c5a2b7f71ca1ceb70668c388d 100644 (file)
@@ -721,8 +721,7 @@ pub(crate) fn link(
 
     let mut linker = Linker::new(first.module_llvm.llmod());
     for module in elements {
-        let _timer =
-            cgcx.prof.generic_activity_with_arg("LLVM_link_module", format!("{:?}", module.name));
+        let _timer = cgcx.prof.generic_activity_with_arg("LLVM_link_module", &*module.name);
         let buffer = ModuleBuffer::new(module.module_llvm.llmod());
         linker.add(buffer.data()).map_err(|()| {
             let msg = format!("failed to serialize module {:?}", module.name);
index dd3ada443895fabef4c4389167ebda493c66cea7..86f92dc02399f95e3bb34b83d311030919afaf98 100644 (file)
@@ -74,10 +74,11 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen
 
     fn module_codegen(tcx: TyCtxt<'_>, cgu_name: Symbol) -> ModuleCodegen<ModuleLlvm> {
         let cgu = tcx.codegen_unit(cgu_name);
-        let _prof_timer = tcx.prof.generic_activity_with_args(
-            "codegen_module",
-            &[cgu_name.to_string(), cgu.size_estimate().to_string()],
-        );
+        let _prof_timer =
+            tcx.prof.generic_activity_with_arg_recorder("codegen_module", |recorder| {
+                recorder.record_arg(cgu_name.to_string());
+                recorder.record_arg(cgu.size_estimate().to_string());
+            });
         // Instantiate monomorphizations without filling out definitions yet...
         let llvm_module = ModuleLlvm::new(tcx, cgu_name.as_str());
         {
@@ -99,15 +100,6 @@ fn module_codegen(tcx: TyCtxt<'_>, cgu_name: Symbol) -> ModuleCodegen<ModuleLlvm
                 attributes::apply_to_llfn(entry, llvm::AttributePlace::Function, &attrs);
             }
 
-            // Run replace-all-uses-with for statics that need it
-            for &(old_g, new_g) in cx.statics_to_rauw().borrow().iter() {
-                unsafe {
-                    let bitcast = llvm::LLVMConstPointerCast(new_g, cx.val_ty(old_g));
-                    llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
-                    llvm::LLVMDeleteGlobal(old_g);
-                }
-            }
-
             // Finalize code coverage by injecting the coverage map. Note, the coverage map will
             // also be added to the `llvm.compiler.used` variable, created next.
             if cx.sess().instrument_coverage() {
@@ -122,6 +114,16 @@ fn module_codegen(tcx: TyCtxt<'_>, cgu_name: Symbol) -> ModuleCodegen<ModuleLlvm
                 cx.create_compiler_used_variable()
             }
 
+            // Run replace-all-uses-with for statics that need it. This must
+            // happen after the llvm.used variables are created.
+            for &(old_g, new_g) in cx.statics_to_rauw().borrow().iter() {
+                unsafe {
+                    let bitcast = llvm::LLVMConstPointerCast(new_g, cx.val_ty(old_g));
+                    llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
+                    llvm::LLVMDeleteGlobal(old_g);
+                }
+            }
+
             // Finalize debuginfo
             if cx.sess().opts.debuginfo != DebugInfo::None {
                 cx.debuginfo_finalize();
index cb4073528e10a0affbfd4d5d7e75183236c9b75c..4d3f3f318b80c7aa8d884ec9b93e1a686f9eb02e 100644 (file)
@@ -412,6 +412,13 @@ fn codegen_static(&self, def_id: DefId, is_mutable: bool) {
                 llvm::LLVMRustSetLinkage(new_g, linkage);
                 llvm::LLVMRustSetVisibility(new_g, visibility);
 
+                // The old global has had its name removed but is returned by
+                // get_static since it is in the instance cache. Provide an
+                // alternative lookup that points to the new global so that
+                // global_asm! can compute the correct mangled symbol name
+                // for the global.
+                self.renamed_statics.borrow_mut().insert(def_id, new_g);
+
                 // To avoid breaking any invariants, we leave around the old
                 // global for the moment; we'll replace all references to it
                 // with the new global later. (See base::codegen_backend.)
index 98cf873ebbdc3e7d8efd43aee7aa46b38c5929fc..d296ee3b42ce1cfe4f5c738a87c325dca1ade669 100644 (file)
@@ -14,6 +14,7 @@
 use rustc_data_structures::base_n;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::small_c_str::SmallCStr;
+use rustc_hir::def_id::DefId;
 use rustc_middle::mir::mono::CodegenUnit;
 use rustc_middle::ty::layout::{
     FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers,
@@ -105,6 +106,12 @@ pub struct CodegenCx<'ll, 'tcx> {
 
     /// A counter that is used for generating local symbol names
     local_gen_sym_counter: Cell<usize>,
+
+    /// `codegen_static` will sometimes create a second global variable with a
+    /// different type and clear the symbol name of the original global.
+    /// `global_asm!` needs to be able to find this new global so that it can
+    /// compute the correct mangled symbol name to insert into the asm.
+    pub renamed_statics: RefCell<FxHashMap<DefId, &'ll Value>>,
 }
 
 pub struct TypeLowering<'ll> {
@@ -436,6 +443,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
             rust_try_fn: Cell::new(None),
             intrinsics: Default::default(),
             local_gen_sym_counter: Cell::new(0),
+            renamed_statics: Default::default(),
         }
     }
 
index 74e194750faddffe269347358d223140586a3bfc..f2cf3b1ef5c1eea396fdd208024118f7a9b7deb6 100644 (file)
@@ -437,11 +437,9 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D
 
     let DINodeCreationResult { di_node, already_stored_in_typemap } = match *t.kind() {
         ty::Never | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => {
-            DINodeCreationResult::new(build_basic_type_di_node(cx, t), false)
-        }
-        ty::Tuple(elements) if elements.is_empty() => {
-            DINodeCreationResult::new(build_basic_type_di_node(cx, t), false)
+            build_basic_type_di_node(cx, t)
         }
+        ty::Tuple(elements) if elements.is_empty() => build_basic_type_di_node(cx, t),
         ty::Array(..) => build_fixed_size_array_di_node(cx, unique_type_id, t),
         ty::Slice(_) | ty::Str => build_slice_type_di_node(cx, t, unique_type_id),
         ty::Dynamic(..) => build_dyn_type_di_node(cx, t, unique_type_id),
@@ -640,7 +638,10 @@ fn msvc_basic_name(self) -> &'static str {
     }
 }
 
-fn build_basic_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
+fn build_basic_type_di_node<'ll, 'tcx>(
+    cx: &CodegenCx<'ll, 'tcx>,
+    t: Ty<'tcx>,
+) -> DINodeCreationResult<'ll> {
     debug!("build_basic_type_di_node: {:?}", t);
 
     // When targeting MSVC, emit MSVC style type names for compatibility with
@@ -649,7 +650,13 @@ fn build_basic_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -
 
     let (name, encoding) = match t.kind() {
         ty::Never => ("!", DW_ATE_unsigned),
-        ty::Tuple(elements) if elements.is_empty() => ("()", DW_ATE_unsigned),
+        ty::Tuple(elements) if elements.is_empty() => {
+            if cpp_like_debuginfo {
+                return build_tuple_type_di_node(cx, UniqueTypeId::for_ty(cx.tcx, t));
+            } else {
+                ("()", DW_ATE_unsigned)
+            }
+        }
         ty::Bool => ("bool", DW_ATE_boolean),
         ty::Char => ("char", DW_ATE_UTF),
         ty::Int(int_ty) if cpp_like_debuginfo => (int_ty.msvc_basic_name(), DW_ATE_signed),
@@ -672,14 +679,14 @@ fn build_basic_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -
     };
 
     if !cpp_like_debuginfo {
-        return ty_di_node;
+        return DINodeCreationResult::new(ty_di_node, false);
     }
 
     let typedef_name = match t.kind() {
         ty::Int(int_ty) => int_ty.name_str(),
         ty::Uint(uint_ty) => uint_ty.name_str(),
         ty::Float(float_ty) => float_ty.name_str(),
-        _ => return ty_di_node,
+        _ => return DINodeCreationResult::new(ty_di_node, false),
     };
 
     let typedef_di_node = unsafe {
@@ -694,7 +701,7 @@ fn build_basic_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -
         )
     };
 
-    typedef_di_node
+    DINodeCreationResult::new(typedef_di_node, false)
 }
 
 fn build_foreign_type_di_node<'ll, 'tcx>(
index 31bb9ed318589441885a41f3d265bccb06e8895b..d6e2c8ccdf44a2344cbf74004c0dec9f0f0b85db 100644 (file)
@@ -372,7 +372,6 @@ fn build_union_fields_for_direct_tag_generator<'ll, 'tcx>(
 
     // Build the type node for each field.
     let variant_field_infos: SmallVec<VariantFieldInfo<'ll>> = variant_range
-        .clone()
         .map(|variant_index| {
             let variant_struct_type_di_node = super::build_generator_variant_struct_type_di_node(
                 cx,
index 48840c76cac8b05c4d312e60af84d5e85d5af1ba..cf9cf1b70aaa7b4f672cc973b13554fe3f84ba0d 100644 (file)
@@ -1839,6 +1839,27 @@ macro_rules! arith_unary {
         simd_neg: Int => neg, Float => fneg;
     }
 
+    if name == sym::simd_arith_offset {
+        // This also checks that the first operand is a ptr type.
+        let pointee = in_elem.builtin_deref(true).unwrap_or_else(|| {
+            span_bug!(span, "must be called with a vector of pointer types as first argument")
+        });
+        let layout = bx.layout_of(pointee.ty);
+        let ptrs = args[0].immediate();
+        // The second argument must be a ptr-sized integer.
+        // (We don't care about the signedness, this is wrapping anyway.)
+        let (_offsets_len, offsets_elem) = arg_tys[1].simd_size_and_type(bx.tcx());
+        if !matches!(offsets_elem.kind(), ty::Int(ty::IntTy::Isize) | ty::Uint(ty::UintTy::Usize)) {
+            span_bug!(
+                span,
+                "must be called with a vector of pointer-sized integers as second argument"
+            );
+        }
+        let offsets = args[1].immediate();
+
+        return Ok(bx.gep(bx.backend_type(layout), ptrs, &[offsets]));
+    }
+
     if name == sym::simd_saturating_add || name == sym::simd_saturating_sub {
         let lhs = args[0].immediate();
         let rhs = args[1].immediate();
index 375b9927c867219579c4cf15d9ad6cf19a7ec792..7f533b0552a5de2d884be0b1a312a66faca174f5 100644 (file)
@@ -2537,4 +2537,6 @@ pub fn LLVMRustContextConfigureDiagnosticHandler(
         remark_passes_len: usize,
     );
 
+    #[allow(improper_ctypes)]
+    pub fn LLVMRustGetMangledName(V: &Value, out: &RustString);
 }
index cf32d558d4a5190bd495cc15d7b894ece75fe712..4d20ed841d47c502bd0b17d39c9f557ac91904b2 100644 (file)
@@ -987,7 +987,7 @@ fn is_illegal_instruction(_status: &ExitStatus) -> bool {
 
         // On MSVC packed debug information is produced by the linker itself so
         // there's no need to do anything else here.
-        SplitDebuginfo::Packed if sess.target.is_like_msvc => {}
+        SplitDebuginfo::Packed if sess.target.is_like_windows => {}
 
         // ... and otherwise we're processing a `*.dwp` packed dwarf file.
         //
index 765bd877db1697dfde390b89604cd455e83b4a29..7b7c676c26cd12b7f487a99982c8154930b4589b 100644 (file)
@@ -1,12 +1,10 @@
 use std::collections::hash_map::Entry::*;
 
 use rustc_ast::expand::allocator::ALLOCATOR_METHODS;
-use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
 use rustc_hir::Node;
-use rustc_index::vec::IndexVec;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::middle::exported_symbols::{
     metadata_symbol_name, ExportedSymbol, SymbolExportLevel,
@@ -277,17 +275,6 @@ fn upstream_monomorphizations_provider(
 
     let mut instances: DefIdMap<FxHashMap<_, _>> = Default::default();
 
-    let cnum_stable_ids: IndexVec<CrateNum, Fingerprint> = {
-        let mut cnum_stable_ids = IndexVec::from_elem_n(Fingerprint::ZERO, cnums.len() + 1);
-
-        for &cnum in cnums.iter() {
-            cnum_stable_ids[cnum] =
-                tcx.def_path_hash(DefId { krate: cnum, index: CRATE_DEF_INDEX }).0;
-        }
-
-        cnum_stable_ids
-    };
-
     let drop_in_place_fn_def_id = tcx.lang_items().drop_in_place_fn();
 
     for &cnum in cnums.iter() {
@@ -316,7 +303,7 @@ fn upstream_monomorphizations_provider(
                     // If there are multiple monomorphizations available,
                     // we select one deterministically.
                     let other_cnum = *e.get();
-                    if cnum_stable_ids[other_cnum] > cnum_stable_ids[cnum] {
+                    if tcx.stable_crate_id(other_cnum) > tcx.stable_crate_id(cnum) {
                         e.insert(cnum);
                     }
                 }
index cf69c8fd8fda940784522c89ecff24d71ea516d5..b6a7bcae9328450d1c38dcc4c5cf4032ab7951a0 100644 (file)
@@ -448,7 +448,9 @@ pub fn codegen_place(
 
                     // a box with a non-zst allocator should not be directly dereferenced
                     if cg_base.layout.ty.is_box() && !cg_base.layout.field(cx, 1).is_zst() {
-                        let ptr = cg_base.extract_field(bx, 0).extract_field(bx, 0);
+                        // Extract `Box<T>` -> `Unique<T>` -> `NonNull<T>` -> `*const T`
+                        let ptr =
+                            cg_base.extract_field(bx, 0).extract_field(bx, 0).extract_field(bx, 0);
 
                         ptr.deref(bx.cx())
                     } else {
@@ -464,7 +466,9 @@ pub fn codegen_place(
                 mir::ProjectionElem::Deref => {
                     // a box with a non-zst allocator should not be directly dereferenced
                     if cg_base.layout.ty.is_box() && !cg_base.layout.field(cx, 1).is_zst() {
-                        let ptr = cg_base.project_field(bx, 0).project_field(bx, 0);
+                        // Project `Box<T>` -> `Unique<T>` -> `NonNull<T>` -> `*const T`
+                        let ptr =
+                            cg_base.project_field(bx, 0).project_field(bx, 0).project_field(bx, 0);
 
                         bx.load_operand(ptr).deref(bx.cx())
                     } else {
index 5414c619dcbcaabd2354aaf8ed722664612a87fe..5006a2157fcae6e801dcf763bfcbd84415fad9eb 100644 (file)
@@ -4,7 +4,9 @@
 use rustc_hir as hir;
 use rustc_middle::mir::mono::MonoItem;
 use rustc_middle::mir::mono::{Linkage, Visibility};
+use rustc_middle::ty;
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
+use rustc_middle::ty::Instance;
 
 pub trait MonoItemExt<'a, 'tcx> {
     fn define<Bx: BuilderMethods<'a, 'tcx>>(&self, cx: &'a Bx::CodegenCx);
@@ -56,7 +58,27 @@ fn define<Bx: BuilderMethods<'a, 'tcx>>(&self, cx: &'a Bx::CodegenCx) {
                                 );
                                 GlobalAsmOperandRef::Const { string }
                             }
-                            _ => span_bug!(*op_sp, "invalid operand type for global_asm!"),
+                            hir::InlineAsmOperand::SymFn { ref anon_const } => {
+                                let ty = cx
+                                    .tcx()
+                                    .typeck_body(anon_const.body)
+                                    .node_type(anon_const.hir_id);
+                                let instance = match ty.kind() {
+                                    &ty::FnDef(def_id, substs) => Instance::new(def_id, substs),
+                                    _ => span_bug!(*op_sp, "asm sym is not a function"),
+                                };
+
+                                GlobalAsmOperandRef::SymFn { instance }
+                            }
+                            hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
+                                GlobalAsmOperandRef::SymStatic { def_id }
+                            }
+                            hir::InlineAsmOperand::In { .. }
+                            | hir::InlineAsmOperand::Out { .. }
+                            | hir::InlineAsmOperand::InOut { .. }
+                            | hir::InlineAsmOperand::SplitInOut { .. } => {
+                                span_bug!(*op_sp, "invalid operand type for global_asm!")
+                            }
                         })
                         .collect();
 
index 11111a7974410f1d9ab2ebe377bf7a6ade571c1d..c2ae74b18d81ee17473dc3cfc68c792561fc09ba 100644 (file)
@@ -36,8 +36,10 @@ pub enum InlineAsmOperandRef<'tcx, B: BackendTypes + ?Sized> {
 }
 
 #[derive(Debug)]
-pub enum GlobalAsmOperandRef {
+pub enum GlobalAsmOperandRef<'tcx> {
     Const { string: String },
+    SymFn { instance: Instance<'tcx> },
+    SymStatic { def_id: DefId },
 }
 
 pub trait AsmBuilderMethods<'tcx>: BackendTypes {
@@ -53,11 +55,11 @@ fn codegen_inline_asm(
     );
 }
 
-pub trait AsmMethods {
+pub trait AsmMethods<'tcx> {
     fn codegen_global_asm(
         &self,
         template: &[InlineAsmTemplatePiece],
-        operands: &[GlobalAsmOperandRef],
+        operands: &[GlobalAsmOperandRef<'tcx>],
         options: InlineAsmOptions,
         line_spans: &[Span],
     );
index c529fbbf518b667a9ed02953f9bf67cfcff6b61b..396768e0a42d0a2e17203ebfe01c7b1475a6eaaf 100644 (file)
@@ -60,7 +60,7 @@ pub trait CodegenMethods<'tcx>:
     + StaticMethods
     + CoverageInfoMethods<'tcx>
     + DebugInfoMethods<'tcx>
-    + AsmMethods
+    + AsmMethods<'tcx>
     + PreDefineMethods<'tcx>
     + HasParamEnv<'tcx>
     + HasTyCtxt<'tcx>
@@ -76,7 +76,7 @@ impl<'tcx, T> CodegenMethods<'tcx> for T where
         + StaticMethods
         + CoverageInfoMethods<'tcx>
         + DebugInfoMethods<'tcx>
-        + AsmMethods
+        + AsmMethods<'tcx>
         + PreDefineMethods<'tcx>
         + HasParamEnv<'tcx>
         + HasTyCtxt<'tcx>
index 498b2f1b081b3308dd65720a419537a7db89f7dc..7cca6178ab25727c989962d841deec9e17267bda 100644 (file)
@@ -188,6 +188,7 @@ pub(super) fn op_to_const<'tcx>(
     }
 }
 
+#[instrument(skip(tcx), level = "debug")]
 fn turn_into_const_value<'tcx>(
     tcx: TyCtxt<'tcx>,
     constant: ConstAlloc<'tcx>,
@@ -206,6 +207,7 @@ fn turn_into_const_value<'tcx>(
         !is_static || cid.promoted.is_some(),
         "the `eval_to_const_value_raw` query should not be used for statics, use `eval_to_allocation` instead"
     );
+
     // Turn this into a proper constant.
     op_to_const(&ecx, &mplace.into())
 }
index 6fd7f707e7e5d4813805e892f394e16a33cc73be..68f9bee593f65ea0f8b04da55f60ef657b0670f8 100644 (file)
@@ -3,12 +3,14 @@
 use std::convert::TryFrom;
 
 use rustc_hir::Mutability;
+use rustc_middle::ty::layout::HasTyCtxt;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_middle::{
     mir::{self, interpret::ConstAlloc},
     ty::ScalarInt,
 };
 use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
+use rustc_target::abi::VariantIdx;
 
 use crate::interpret::{
     intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, MPlaceTy,
@@ -36,7 +38,7 @@ pub(crate) fn const_caller_location(
     if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() {
         bug!("intern_const_alloc_recursive should not error in this case")
     }
-    ConstValue::Scalar(Scalar::from_pointer(loc_place.ptr.into_pointer_or_addr().unwrap(), &tcx))
+    ConstValue::Scalar(Scalar::from_maybe_pointer(loc_place.ptr, &tcx))
 }
 
 /// Convert an evaluated constant to a type level constant
@@ -55,28 +57,48 @@ pub(crate) fn const_to_valtree<'tcx>(
     const_to_valtree_inner(&ecx, &place)
 }
 
-fn const_to_valtree_inner<'tcx>(
+#[instrument(skip(ecx), level = "debug")]
+fn branches<'tcx>(
     ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
     place: &MPlaceTy<'tcx>,
+    n: usize,
+    variant: Option<VariantIdx>,
 ) -> Option<ty::ValTree<'tcx>> {
-    let branches = |n, variant| {
-        let place = match variant {
-            Some(variant) => ecx.mplace_downcast(&place, variant).unwrap(),
-            None => *place,
-        };
-        let variant =
-            variant.map(|variant| Some(ty::ValTree::Leaf(ScalarInt::from(variant.as_u32()))));
-        let fields = (0..n).map(|i| {
-            let field = ecx.mplace_field(&place, i).unwrap();
-            const_to_valtree_inner(ecx, &field)
-        });
-        // For enums, we preped their variant index before the variant's fields so we can figure out
-        // the variant again when just seeing a valtree.
-        let branches = variant.into_iter().chain(fields);
-        Some(ty::ValTree::Branch(
-            ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?),
-        ))
+    let place = match variant {
+        Some(variant) => ecx.mplace_downcast(&place, variant).unwrap(),
+        None => *place,
     };
+    let variant = variant.map(|variant| Some(ty::ValTree::Leaf(ScalarInt::from(variant.as_u32()))));
+    debug!(?place, ?variant);
+
+    let fields = (0..n).map(|i| {
+        let field = ecx.mplace_field(&place, i).unwrap();
+        const_to_valtree_inner(ecx, &field)
+    });
+    // For enums, we prepend their variant index before the variant's fields so we can figure out
+    // the variant again when just seeing a valtree.
+    let branches = variant.into_iter().chain(fields);
+    Some(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?)))
+}
+
+fn slice_branches<'tcx>(
+    ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
+    place: &MPlaceTy<'tcx>,
+) -> Option<ty::ValTree<'tcx>> {
+    let n = place.len(&ecx.tcx()).expect(&format!("expected to use len of place {:?}", place));
+    let branches = (0..n).map(|i| {
+        let place_elem = ecx.mplace_index(place, i).unwrap();
+        const_to_valtree_inner(ecx, &place_elem)
+    });
+
+    Some(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?)))
+}
+
+#[instrument(skip(ecx), level = "debug")]
+fn const_to_valtree_inner<'tcx>(
+    ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
+    place: &MPlaceTy<'tcx>,
+) -> Option<ty::ValTree<'tcx>> {
     match place.layout.ty.kind() {
         ty::FnDef(..) => Some(ty::ValTree::zst()),
         ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => {
@@ -90,19 +112,27 @@ fn const_to_valtree_inner<'tcx>(
         // Technically we could allow function pointers (represented as `ty::Instance`), but this is not guaranteed to
         // agree with runtime equality tests.
         ty::FnPtr(_) | ty::RawPtr(_) => None,
-        ty::Ref(..) => unimplemented!("need to use deref_const"),
 
+        ty::Ref(_, _, _)  => {
+            let derefd_place = ecx.deref_operand(&place.into()).unwrap_or_else(|e| bug!("couldn't deref {:?}, error: {:?}", place, e));
+            debug!(?derefd_place);
+
+            const_to_valtree_inner(ecx, &derefd_place)
+        }
+
+        ty::Str | ty::Slice(_) | ty::Array(_, _) => {
+            let valtree = slice_branches(ecx, place);
+            debug!(?valtree);
+
+            valtree
+        }
         // Trait objects are not allowed in type level constants, as we have no concept for
         // resolving their backing type, even if we can do that at const eval time. We may
         // hypothetically be able to allow `dyn StructuralEq` trait objects in the future,
         // but it is unclear if this is useful.
         ty::Dynamic(..) => None,
 
-        ty::Slice(_) | ty::Str => {
-            unimplemented!("need to find the backing data of the slice/str and recurse on that")
-        }
-        ty::Tuple(substs) => branches(substs.len(), None),
-        ty::Array(_, len) => branches(usize::try_from(len.eval_usize(ecx.tcx.tcx, ecx.param_env)).unwrap(), None),
+        ty::Tuple(substs) => branches(ecx, place, substs.len(), None),
 
         ty::Adt(def, _) => {
             if def.variants().is_empty() {
@@ -111,7 +141,7 @@ fn const_to_valtree_inner<'tcx>(
 
             let variant = ecx.read_discriminant(&place.into()).unwrap().1;
 
-            branches(def.variant(variant).fields.len(), def.is_enum().then_some(variant))
+            branches(ecx, place, def.variant(variant).fields.len(), def.is_enum().then_some(variant))
         }
 
         ty::Never
index f0fff602fe4cfbf8a647c415035898a04eaa8e6f..827959113b90734ce321673ab5c56bbc359469d7 100644 (file)
@@ -679,7 +679,7 @@ pub fn push_stack_frame(
         return_place: Option<&PlaceTy<'tcx, M::PointerTag>>,
         return_to_block: StackPopCleanup,
     ) -> InterpResult<'tcx> {
-        debug!("body: {:#?}", body);
+        trace!("body: {:#?}", body);
         // first push a stack frame so we have access to the local substs
         let pre_frame = Frame {
             body,
@@ -836,7 +836,7 @@ pub(super) fn pop_stack_frame(&mut self, unwinding: bool) -> InterpResult<'tcx>
             return Ok(());
         }
 
-        debug!("locals: {:#?}", frame.locals);
+        trace!("locals: {:#?}", frame.locals);
 
         // Cleanup: deallocate all locals that are backed by an allocation.
         for local in &frame.locals {
index ddfbcbdd22e162495e2621d8ab67184c11ed4d68..7721485771b3b0a121ea08e321b326889869d982 100644 (file)
@@ -88,6 +88,10 @@ pub trait Machine<'mir, 'tcx>: Sized {
     /// Pointers are "tagged" with provenance information; typically the `AllocId` they belong to.
     type PointerTag: Provenance + Eq + Hash + 'static;
 
+    /// When getting the AllocId of a pointer, some extra data is also obtained from the tag
+    /// that is passed to memory access hooks so they can do things with it.
+    type TagExtra: Copy + 'static;
+
     /// Machines can define extra (non-instance) things that represent values of function pointers.
     /// For example, Miri uses this to return a function pointer from `dlsym`
     /// that can later be called to execute the right thing.
@@ -122,6 +126,8 @@ pub trait Machine<'mir, 'tcx>: Sized {
 
     /// Whether, when checking alignment, we should `force_int` and thus support
     /// custom alignment logic based on whatever the integer address happens to be.
+    ///
+    /// Requires PointerTag::OFFSET_IS_ADDR to be true.
     fn force_int_for_alignment_check(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
 
     /// Whether to enforce the validity invariant
@@ -285,11 +291,14 @@ fn ptr_from_addr(
         addr: u64,
     ) -> Pointer<Option<Self::PointerTag>>;
 
-    /// Convert a pointer with provenance into an allocation-offset pair.
+    /// Convert a pointer with provenance into an allocation-offset pair
+    /// and extra provenance info.
+    ///
+    /// The returned `AllocId` must be the same as `ptr.provenance.get_alloc_id()`.
     fn ptr_get_alloc(
         ecx: &InterpCx<'mir, 'tcx, Self>,
         ptr: Pointer<Self::PointerTag>,
-    ) -> (AllocId, Size);
+    ) -> (AllocId, Size, Self::TagExtra);
 
     /// Called to initialize the "extra" state of an allocation and make the pointers
     /// it contains (in relocations) tagged.  The way we construct allocations is
@@ -321,7 +330,7 @@ fn memory_read(
         _tcx: TyCtxt<'tcx>,
         _machine: &Self,
         _alloc_extra: &Self::AllocExtra,
-        _tag: Self::PointerTag,
+        _tag: (AllocId, Self::TagExtra),
         _range: AllocRange,
     ) -> InterpResult<'tcx> {
         Ok(())
@@ -333,7 +342,7 @@ fn memory_written(
         _tcx: TyCtxt<'tcx>,
         _machine: &mut Self,
         _alloc_extra: &mut Self::AllocExtra,
-        _tag: Self::PointerTag,
+        _tag: (AllocId, Self::TagExtra),
         _range: AllocRange,
     ) -> InterpResult<'tcx> {
         Ok(())
@@ -345,7 +354,7 @@ fn memory_deallocated(
         _tcx: TyCtxt<'tcx>,
         _machine: &mut Self,
         _alloc_extra: &mut Self::AllocExtra,
-        _tag: Self::PointerTag,
+        _tag: (AllocId, Self::TagExtra),
         _range: AllocRange,
     ) -> InterpResult<'tcx> {
         Ok(())
@@ -397,6 +406,8 @@ fn after_stack_pop(
 // (CTFE and ConstProp) use the same instance.  Here, we share that code.
 pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
     type PointerTag = AllocId;
+    type TagExtra = ();
+
     type ExtraFnVal = !;
 
     type MemoryMap =
@@ -474,9 +485,12 @@ fn ptr_from_addr(_ecx: &InterpCx<$mir, $tcx, Self>, addr: u64) -> Pointer<Option
     }
 
     #[inline(always)]
-    fn ptr_get_alloc(_ecx: &InterpCx<$mir, $tcx, Self>, ptr: Pointer<AllocId>) -> (AllocId, Size) {
+    fn ptr_get_alloc(
+        _ecx: &InterpCx<$mir, $tcx, Self>,
+        ptr: Pointer<AllocId>,
+    ) -> (AllocId, Size, Self::TagExtra) {
         // We know `offset` is relative to the allocation, so we can use `into_parts`.
         let (alloc_id, offset) = ptr.into_parts();
-        (alloc_id, offset)
+        (alloc_id, offset, ())
     }
 }
index a165fa23f30acf5e40af7a2a4d4171ba84ada542..b1d7ab6a098beccc7954322739b348f6551678d1 100644 (file)
@@ -158,8 +158,7 @@ pub fn global_base_pointer(
         &self,
         ptr: Pointer<AllocId>,
     ) -> InterpResult<'tcx, Pointer<M::PointerTag>> {
-        // We know `offset` is relative to the allocation, so we can use `into_parts`.
-        let (alloc_id, offset) = ptr.into_parts();
+        let alloc_id = ptr.provenance;
         // We need to handle `extern static`.
         match self.tcx.get_global_alloc(alloc_id) {
             Some(GlobalAlloc::Static(def_id)) if self.tcx.is_thread_local_static(def_id) => {
@@ -171,7 +170,7 @@ pub fn global_base_pointer(
             _ => {}
         }
         // And we need to get the tag.
-        Ok(M::tag_alloc_base_pointer(self, Pointer::new(alloc_id, offset)))
+        Ok(M::tag_alloc_base_pointer(self, ptr))
     }
 
     pub fn create_fn_alloc_ptr(
@@ -238,7 +237,7 @@ pub fn reallocate_ptr(
         new_align: Align,
         kind: MemoryKind<M::MemoryKind>,
     ) -> InterpResult<'tcx, Pointer<M::PointerTag>> {
-        let (alloc_id, offset, ptr) = self.ptr_get_alloc_id(ptr)?;
+        let (alloc_id, offset, _tag) = self.ptr_get_alloc_id(ptr)?;
         if offset.bytes() != 0 {
             throw_ub_format!(
                 "reallocating {:?} which does not point to the beginning of an object",
@@ -255,14 +254,14 @@ pub fn reallocate_ptr(
         };
         // This will also call the access hooks.
         self.mem_copy(
-            ptr.into(),
+            ptr,
             Align::ONE,
             new_ptr.into(),
             Align::ONE,
             old_size.min(new_size),
             /*nonoverlapping*/ true,
         )?;
-        self.deallocate_ptr(ptr.into(), old_size_and_align, kind)?;
+        self.deallocate_ptr(ptr, old_size_and_align, kind)?;
 
         Ok(new_ptr)
     }
@@ -274,7 +273,7 @@ pub fn deallocate_ptr(
         old_size_and_align: Option<(Size, Align)>,
         kind: MemoryKind<M::MemoryKind>,
     ) -> InterpResult<'tcx> {
-        let (alloc_id, offset, ptr) = self.ptr_get_alloc_id(ptr)?;
+        let (alloc_id, offset, tag) = self.ptr_get_alloc_id(ptr)?;
         trace!("deallocating: {}", alloc_id);
 
         if offset.bytes() != 0 {
@@ -330,7 +329,7 @@ pub fn deallocate_ptr(
             *self.tcx,
             &mut self.machine,
             &mut alloc.extra,
-            ptr.provenance,
+            (alloc_id, tag),
             alloc_range(Size::ZERO, size),
         )?;
 
@@ -350,17 +349,17 @@ fn get_ptr_access(
         ptr: Pointer<Option<M::PointerTag>>,
         size: Size,
         align: Align,
-    ) -> InterpResult<'tcx, Option<(AllocId, Size, Pointer<M::PointerTag>)>> {
+    ) -> InterpResult<'tcx, Option<(AllocId, Size, M::TagExtra)>> {
         let align = M::enforce_alignment(&self).then_some(align);
         self.check_and_deref_ptr(
             ptr,
             size,
             align,
             CheckInAllocMsg::MemoryAccessTest,
-            |alloc_id, offset, ptr| {
+            |alloc_id, offset, tag| {
                 let (size, align) =
                     self.get_alloc_size_and_align(alloc_id, AllocCheck::Dereferenceable)?;
-                Ok((size, align, (alloc_id, offset, ptr)))
+                Ok((size, align, (alloc_id, offset, tag)))
             },
         )
     }
@@ -401,11 +400,7 @@ fn check_and_deref_ptr<T>(
         size: Size,
         align: Option<Align>,
         msg: CheckInAllocMsg,
-        alloc_size: impl FnOnce(
-            AllocId,
-            Size,
-            Pointer<M::PointerTag>,
-        ) -> InterpResult<'tcx, (Size, Align, T)>,
+        alloc_size: impl FnOnce(AllocId, Size, M::TagExtra) -> InterpResult<'tcx, (Size, Align, T)>,
     ) -> InterpResult<'tcx, Option<T>> {
         fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> {
             if offset % align.bytes() == 0 {
@@ -433,8 +428,8 @@ fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> {
                 }
                 None
             }
-            Ok((alloc_id, offset, ptr)) => {
-                let (alloc_size, alloc_align, ret_val) = alloc_size(alloc_id, offset, ptr)?;
+            Ok((alloc_id, offset, tag)) => {
+                let (alloc_size, alloc_align, ret_val) = alloc_size(alloc_id, offset, tag)?;
                 // Test bounds. This also ensures non-null.
                 // It is sufficient to check this for the end pointer. Also check for overflow!
                 if offset.checked_add(size, &self.tcx).map_or(true, |end| end > alloc_size) {
@@ -450,10 +445,8 @@ fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> {
                 // we want the error to be about the bounds.
                 if let Some(align) = align {
                     if M::force_int_for_alignment_check(self) {
-                        let addr = Scalar::from_pointer(ptr, &self.tcx)
-                            .to_machine_usize(&self.tcx)
-                            .expect("ptr-to-int cast for align check should never fail");
-                        check_offset_align(addr, align)?;
+                        // `force_int_for_alignment_check` can only be true if `OFFSET_IS_ADDR` is true.
+                        check_offset_align(ptr.addr().bytes(), align)?;
                     } else {
                         // Check allocation alignment and offset alignment.
                         if alloc_align.bytes() < align.bytes() {
@@ -569,14 +562,14 @@ pub fn get_ptr_alloc<'a>(
             size,
             align,
             CheckInAllocMsg::MemoryAccessTest,
-            |alloc_id, offset, ptr| {
+            |alloc_id, offset, tag| {
                 let alloc = self.get_alloc_raw(alloc_id)?;
-                Ok((alloc.size(), alloc.align, (alloc_id, offset, ptr, alloc)))
+                Ok((alloc.size(), alloc.align, (alloc_id, offset, tag, alloc)))
             },
         )?;
-        if let Some((alloc_id, offset, ptr, alloc)) = ptr_and_alloc {
+        if let Some((alloc_id, offset, tag, alloc)) = ptr_and_alloc {
             let range = alloc_range(offset, size);
-            M::memory_read(*self.tcx, &self.machine, &alloc.extra, ptr.provenance, range)?;
+            M::memory_read(*self.tcx, &self.machine, &alloc.extra, (alloc_id, tag), range)?;
             Ok(Some(AllocRef { alloc, range, tcx: *self.tcx, alloc_id }))
         } else {
             // Even in this branch we have to be sure that we actually access the allocation, in
@@ -631,13 +624,13 @@ pub fn get_ptr_alloc_mut<'a>(
         align: Align,
     ) -> InterpResult<'tcx, Option<AllocRefMut<'a, 'tcx, M::PointerTag, M::AllocExtra>>> {
         let parts = self.get_ptr_access(ptr, size, align)?;
-        if let Some((alloc_id, offset, ptr)) = parts {
+        if let Some((alloc_id, offset, tag)) = parts {
             let tcx = *self.tcx;
             // FIXME: can we somehow avoid looking up the allocation twice here?
             // We cannot call `get_raw_mut` inside `check_and_deref_ptr` as that would duplicate `&mut self`.
             let (alloc, machine) = self.get_alloc_raw_mut(alloc_id)?;
             let range = alloc_range(offset, size);
-            M::memory_written(tcx, machine, &mut alloc.extra, ptr.provenance, range)?;
+            M::memory_written(tcx, machine, &mut alloc.extra, (alloc_id, tag), range)?;
             Ok(Some(AllocRefMut { alloc, range, tcx, alloc_id }))
         } else {
             Ok(None)
@@ -732,7 +725,7 @@ pub fn get_ptr_fn(
         ptr: Pointer<Option<M::PointerTag>>,
     ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> {
         trace!("get_fn({:?})", ptr);
-        let (alloc_id, offset, _ptr) = self.ptr_get_alloc_id(ptr)?;
+        let (alloc_id, offset, _tag) = self.ptr_get_alloc_id(ptr)?;
         if offset.bytes() != 0 {
             throw_ub!(InvalidFunctionPointer(Pointer::new(alloc_id, offset)))
         }
@@ -877,9 +870,17 @@ pub fn write_scalar(
         range: AllocRange,
         val: ScalarMaybeUninit<Tag>,
     ) -> InterpResult<'tcx> {
+        let range = self.range.subrange(range);
+        debug!(
+            "write_scalar in {} at {:#x}, size {}: {:?}",
+            self.alloc_id,
+            range.start.bytes(),
+            range.size.bytes(),
+            val
+        );
         Ok(self
             .alloc
-            .write_scalar(&self.tcx, self.range.subrange(range), val)
+            .write_scalar(&self.tcx, range, val)
             .map_err(|e| e.to_interp_error(self.alloc_id))?)
     }
 
@@ -892,17 +893,29 @@ pub fn write_ptr_sized(
     }
 
     /// Mark the entire referenced range as uninitalized
-    pub fn write_uninit(&mut self) {
-        self.alloc.mark_init(self.range, false);
+    pub fn write_uninit(&mut self) -> InterpResult<'tcx> {
+        Ok(self
+            .alloc
+            .write_uninit(&self.tcx, self.range)
+            .map_err(|e| e.to_interp_error(self.alloc_id))?)
     }
 }
 
 impl<'tcx, 'a, Tag: Provenance, Extra> AllocRef<'a, 'tcx, Tag, Extra> {
     pub fn read_scalar(&self, range: AllocRange) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
-        Ok(self
+        let range = self.range.subrange(range);
+        let res = self
             .alloc
-            .read_scalar(&self.tcx, self.range.subrange(range))
-            .map_err(|e| e.to_interp_error(self.alloc_id))?)
+            .read_scalar(&self.tcx, range)
+            .map_err(|e| e.to_interp_error(self.alloc_id))?;
+        debug!(
+            "read_scalar in {} at {:#x}, size {}: {:?}",
+            self.alloc_id,
+            range.start.bytes(),
+            range.size.bytes(),
+            res
+        );
+        Ok(res)
     }
 
     pub fn read_ptr_sized(&self, offset: Size) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
@@ -1009,16 +1022,16 @@ pub fn mem_copy_repeatedly(
         // and once below to get the underlying `&[mut] Allocation`.
 
         // Source alloc preparations and access hooks.
-        let Some((src_alloc_id, src_offset, src)) = src_parts else {
+        let Some((src_alloc_id, src_offset, src_tag)) = src_parts else {
             // Zero-sized *source*, that means dst is also zero-sized and we have nothing to do.
             return Ok(());
         };
         let src_alloc = self.get_alloc_raw(src_alloc_id)?;
         let src_range = alloc_range(src_offset, size);
-        M::memory_read(*tcx, &self.machine, &src_alloc.extra, src.provenance, src_range)?;
+        M::memory_read(*tcx, &self.machine, &src_alloc.extra, (src_alloc_id, src_tag), src_range)?;
         // We need the `dest` ptr for the next operation, so we get it now.
         // We already did the source checks and called the hooks so we are good to return early.
-        let Some((dest_alloc_id, dest_offset, dest)) = dest_parts else {
+        let Some((dest_alloc_id, dest_offset, dest_tag)) = dest_parts else {
             // Zero-sized *destination*.
             return Ok(());
         };
@@ -1040,7 +1053,13 @@ pub fn mem_copy_repeatedly(
         // Destination alloc preparations and access hooks.
         let (dest_alloc, extra) = self.get_alloc_raw_mut(dest_alloc_id)?;
         let dest_range = alloc_range(dest_offset, size * num_copies);
-        M::memory_written(*tcx, extra, &mut dest_alloc.extra, dest.provenance, dest_range)?;
+        M::memory_written(
+            *tcx,
+            extra,
+            &mut dest_alloc.extra,
+            (dest_alloc_id, dest_tag),
+            dest_range,
+        )?;
         let dest_bytes = dest_alloc
             .get_bytes_mut_ptr(&tcx, dest_range)
             .map_err(|e| e.to_interp_error(dest_alloc_id))?
@@ -1053,8 +1072,10 @@ pub fn mem_copy_repeatedly(
             // This also avoids writing to the target bytes so that the backing allocation is never
             // touched if the bytes stay uninitialized for the whole interpreter execution. On contemporary
             // operating system this can avoid physically allocating the page.
-            dest_alloc.mark_init(dest_range, false); // `Size` multiplication
-            dest_alloc.mark_relocation_range(relocations);
+            dest_alloc
+                .write_uninit(&tcx, dest_range)
+                .map_err(|e| e.to_interp_error(dest_alloc_id))?;
+            // We can forget about the relocations, this is all not initialized anyway.
             return Ok(());
         }
 
@@ -1159,11 +1180,11 @@ pub fn scalar_may_be_null(&self, scalar: Scalar<M::PointerTag>) -> InterpResult<
     pub fn ptr_try_get_alloc_id(
         &self,
         ptr: Pointer<Option<M::PointerTag>>,
-    ) -> Result<(AllocId, Size, Pointer<M::PointerTag>), u64> {
+    ) -> Result<(AllocId, Size, M::TagExtra), u64> {
         match ptr.into_pointer_or_addr() {
             Ok(ptr) => {
-                let (alloc_id, offset) = M::ptr_get_alloc(self, ptr);
-                Ok((alloc_id, offset, ptr))
+                let (alloc_id, offset, extra) = M::ptr_get_alloc(self, ptr);
+                Ok((alloc_id, offset, extra))
             }
             Err(addr) => Err(addr.bytes()),
         }
@@ -1174,7 +1195,7 @@ pub fn ptr_try_get_alloc_id(
     pub fn ptr_get_alloc_id(
         &self,
         ptr: Pointer<Option<M::PointerTag>>,
-    ) -> InterpResult<'tcx, (AllocId, Size, Pointer<M::PointerTag>)> {
+    ) -> InterpResult<'tcx, (AllocId, Size, M::TagExtra)> {
         self.ptr_try_get_alloc_id(ptr).map_err(|offset| {
             err_ub!(DanglingIntPointer(offset, CheckInAllocMsg::InboundsTest)).into()
         })
index 8dc74035d61d009b0ec59dbd2ec4c69b4e694e66..e4660fe090ce5fb4900d9c350908103866906a1d 100644 (file)
@@ -191,7 +191,7 @@ pub fn from_aligned_ptr(ptr: Pointer<Option<Tag>>, layout: TyAndLayout<'tcx>) ->
     }
 
     #[inline]
-    pub(super) fn len(&self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> {
+    pub(crate) fn len(&self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> {
         if self.layout.is_unsized() {
             // We need to consult `meta` metadata
             match self.layout.ty.kind() {
@@ -823,7 +823,7 @@ pub fn write_uninit(&mut self, dest: &PlaceTy<'tcx, M::PointerTag>) -> InterpRes
             // Zero-sized access
             return Ok(());
         };
-        alloc.write_uninit();
+        alloc.write_uninit()?;
         Ok(())
     }
 
index eb1a184bf9b219139c00b16fa4431cf8735d4b18..e6dfdf54a32d136c7dbf70edb52ba4c9bbeb9ab3 100644 (file)
@@ -196,27 +196,11 @@ pub fn eval_rvalue_into_place(
                 self.write_immediate(*val, &dest)?;
             }
 
-            Aggregate(ref kind, ref operands) => {
-                // active_field_index is for union initialization.
-                let (dest, active_field_index) = match **kind {
-                    mir::AggregateKind::Adt(adt_did, variant_index, _, _, active_field_index) => {
-                        self.write_discriminant(variant_index, &dest)?;
-                        if self.tcx.adt_def(adt_did).is_enum() {
-                            assert!(active_field_index.is_none());
-                            (self.place_downcast(&dest, variant_index)?, None)
-                        } else {
-                            if active_field_index.is_some() {
-                                assert_eq!(operands.len(), 1);
-                            }
-                            (dest, active_field_index)
-                        }
-                    }
-                    _ => (dest, None),
-                };
+            Aggregate(box ref kind, ref operands) => {
+                assert!(matches!(kind, mir::AggregateKind::Array(..)));
 
-                for (i, operand) in operands.iter().enumerate() {
+                for (field_index, operand) in operands.iter().enumerate() {
                     let op = self.eval_operand(operand, None)?;
-                    let field_index = active_field_index.unwrap_or(i);
                     let field_dest = self.place_field(&dest, field_index)?;
                     self.copy_op(&op, &field_dest)?;
                 }
index 4a0aa41de739b3caa13f0ed80fa3170fc8c3d331..71d29be97d5ec38e99b544bee0532d2c58ad4400 100644 (file)
@@ -432,7 +432,7 @@ fn check_safe_pointer(
         if let Some(ref mut ref_tracking) = self.ref_tracking {
             // Proceed recursively even for ZST, no reason to skip them!
             // `!` is a ZST and we want to validate it.
-            if let Ok((alloc_id, _offset, _ptr)) = self.ecx.ptr_try_get_alloc_id(place.ptr) {
+            if let Ok((alloc_id, _offset, _tag)) = self.ecx.ptr_try_get_alloc_id(place.ptr) {
                 // Special handling for pointers to statics (irrespective of their type).
                 let alloc_kind = self.ecx.tcx.get_global_alloc(alloc_id);
                 if let Some(GlobalAlloc::Static(did)) = alloc_kind {
index 01af95851357e481da64e819bfc32bb2e785ca08..f71bc586b4847e3d92b2ac6f7a35123ed0ba3ee3 100644 (file)
@@ -214,7 +214,8 @@ fn visit_local(&mut self, local: &Local, context: PlaceContext, location: Locati
 
     fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
         // This check is somewhat expensive, so only run it when -Zvalidate-mir is passed.
-        if self.tcx.sess.opts.debugging_opts.validate_mir {
+        if self.tcx.sess.opts.debugging_opts.validate_mir && self.mir_phase < MirPhase::DropsLowered
+        {
             // `Operand::Copy` is only supposed to be used with `Copy` types.
             if let Operand::Copy(place) = operand {
                 let ty = place.ty(&self.body.local_decls, self.tcx).ty;
@@ -315,9 +316,8 @@ macro_rules! check_kinds {
                                     | ty::FnPtr(..)
                             )
                         }
-                        // None of the possible types have lifetimes, so we can just compare
-                        // directly
-                        if a != b {
+                        // The function pointer types can have lifetimes
+                        if !self.mir_assign_valid_types(a, b) {
                             self.fail(
                                 location,
                                 format!("Cannot compare unequal types {:?} and {:?}", a, b),
@@ -464,7 +464,7 @@ fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
                 };
                 // since CopyNonOverlapping is parametrized by 1 type,
                 // we only need to check that they are equal and not keep an extra parameter.
-                if op_src_ty != op_dst_ty {
+                if !self.mir_assign_valid_types(op_src_ty, op_dst_ty) {
                     self.fail(location, format!("bad arg ({:?} != {:?})", op_src_ty, op_dst_ty));
                 }
 
index 293ef4caac4007ad1e74bf1b6404f3a6c0d370e6..e395d8dbbbf8b2dea18c1f29a3cfdab2d21ffcd5 100644 (file)
 #![allow(non_camel_case_types)]
 #![allow(nonstandard_style)]
 
-use std::fs::{File, OpenOptions};
-use std::io;
-use std::path::Path;
-
 cfg_if! {
-    // We use `flock` rather than `fcntl` on Linux, because WSL1 does not support
-    // `fcntl`-style advisory locks properly (rust-lang/rust#72157).
-    //
-    // For other Unix targets we still use `fcntl` because it's more portable than
-    // `flock`.
     if #[cfg(target_os = "linux")] {
-        use std::os::unix::prelude::*;
-
-        #[derive(Debug)]
-        pub struct Lock {
-            _file: File,
-        }
-
-        impl Lock {
-            pub fn new(p: &Path,
-                       wait: bool,
-                       create: bool,
-                       exclusive: bool)
-                       -> io::Result<Lock> {
-                let file = OpenOptions::new()
-                    .read(true)
-                    .write(true)
-                    .create(create)
-                    .mode(libc::S_IRWXU as u32)
-                    .open(p)?;
-
-                let mut operation = if exclusive {
-                    libc::LOCK_EX
-                } else {
-                    libc::LOCK_SH
-                };
-                if !wait {
-                    operation |= libc::LOCK_NB
-                }
-
-                let ret = unsafe { libc::flock(file.as_raw_fd(), operation) };
-                if ret == -1 {
-                    Err(io::Error::last_os_error())
-                } else {
-                    Ok(Lock { _file: file })
-                }
-            }
-
-            pub fn error_unsupported(err: &io::Error) -> bool {
-                matches!(err.raw_os_error(), Some(libc::ENOTSUP) | Some(libc::ENOSYS))
-            }
-        }
-
-        // Note that we don't need a Drop impl to execute `flock(fd, LOCK_UN)`. Lock acquired by
-        // `flock` is associated with the file descriptor and closing the file release it
-        // automatically.
+        mod linux;
+        use linux as imp;
     } else if #[cfg(unix)] {
-        use std::mem;
-        use std::os::unix::prelude::*;
-
-        #[derive(Debug)]
-        pub struct Lock {
-            file: File,
-        }
-
-        impl Lock {
-            pub fn new(p: &Path,
-                       wait: bool,
-                       create: bool,
-                       exclusive: bool)
-                       -> io::Result<Lock> {
-                let file = OpenOptions::new()
-                    .read(true)
-                    .write(true)
-                    .create(create)
-                    .mode(libc::S_IRWXU as u32)
-                    .open(p)?;
-
-                let lock_type = if exclusive {
-                    libc::F_WRLCK
-                } else {
-                    libc::F_RDLCK
-                };
-
-                let mut flock: libc::flock = unsafe { mem::zeroed() };
-                flock.l_type = lock_type as libc::c_short;
-                flock.l_whence = libc::SEEK_SET as libc::c_short;
-                flock.l_start = 0;
-                flock.l_len = 0;
-
-                let cmd = if wait { libc::F_SETLKW } else { libc::F_SETLK };
-                let ret = unsafe {
-                    libc::fcntl(file.as_raw_fd(), cmd, &flock)
-                };
-                if ret == -1 {
-                    Err(io::Error::last_os_error())
-                } else {
-                    Ok(Lock { file })
-                }
-            }
-
-            pub fn error_unsupported(err: &io::Error) -> bool {
-                matches!(err.raw_os_error(), Some(libc::ENOTSUP) | Some(libc::ENOSYS))
-            }
-        }
-
-        impl Drop for Lock {
-            fn drop(&mut self) {
-                let mut flock: libc::flock = unsafe { mem::zeroed() };
-                flock.l_type = libc::F_UNLCK as libc::c_short;
-                flock.l_whence = libc::SEEK_SET as libc::c_short;
-                flock.l_start = 0;
-                flock.l_len = 0;
-
-                unsafe {
-                    libc::fcntl(self.file.as_raw_fd(), libc::F_SETLK, &flock);
-                }
-            }
-        }
+        mod unix;
+        use unix as imp;
     } else if #[cfg(windows)] {
-        use std::mem;
-        use std::os::windows::prelude::*;
-
-        use winapi::shared::winerror::ERROR_INVALID_FUNCTION;
-        use winapi::um::minwinbase::{OVERLAPPED, LOCKFILE_FAIL_IMMEDIATELY, LOCKFILE_EXCLUSIVE_LOCK};
-        use winapi::um::fileapi::LockFileEx;
-        use winapi::um::winnt::{FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE};
-
-        #[derive(Debug)]
-        pub struct Lock {
-            _file: File,
-        }
-
-        impl Lock {
-            pub fn new(p: &Path,
-                       wait: bool,
-                       create: bool,
-                       exclusive: bool)
-                       -> io::Result<Lock> {
-                assert!(p.parent().unwrap().exists(),
-                    "Parent directory of lock-file must exist: {}",
-                    p.display());
-
-                let share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
-
-                let mut open_options = OpenOptions::new();
-                open_options.read(true)
-                            .share_mode(share_mode);
-
-                if create {
-                    open_options.create(true)
-                                .write(true);
-                }
-
-                debug!("attempting to open lock file `{}`", p.display());
-                let file = match open_options.open(p) {
-                    Ok(file) => {
-                        debug!("lock file opened successfully");
-                        file
-                    }
-                    Err(err) => {
-                        debug!("error opening lock file: {}", err);
-                        return Err(err)
-                    }
-                };
-
-                let ret = unsafe {
-                    let mut overlapped: OVERLAPPED = mem::zeroed();
-
-                    let mut dwFlags = 0;
-                    if !wait {
-                        dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
-                    }
-
-                    if exclusive {
-                        dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
-                    }
-
-                    debug!("attempting to acquire lock on lock file `{}`",
-                           p.display());
-                    LockFileEx(file.as_raw_handle(),
-                               dwFlags,
-                               0,
-                               0xFFFF_FFFF,
-                               0xFFFF_FFFF,
-                               &mut overlapped)
-                };
-                if ret == 0 {
-                    let err = io::Error::last_os_error();
-                    debug!("failed acquiring file lock: {}", err);
-                    Err(err)
-                } else {
-                    debug!("successfully acquired lock");
-                    Ok(Lock { _file: file })
-                }
-            }
-
-            pub fn error_unsupported(err: &io::Error) -> bool {
-                err.raw_os_error() == Some(ERROR_INVALID_FUNCTION as i32)
-            }
-        }
-
-        // Note that we don't need a Drop impl on the Windows: The file is unlocked
-        // automatically when it's closed.
+        mod windows;
+        use windows as imp;
     } else {
-        #[derive(Debug)]
-        pub struct Lock(());
-
-        impl Lock {
-            pub fn new(_p: &Path, _wait: bool, _create: bool, _exclusive: bool)
-                -> io::Result<Lock>
-            {
-                let msg = "file locks not supported on this platform";
-                Err(io::Error::new(io::ErrorKind::Other, msg))
-            }
-
-            pub fn error_unsupported(_err: &io::Error) -> bool {
-                true
-            }
-        }
+        mod unsupported;
+        use unsupported as imp;
     }
 }
+
+pub use imp::Lock;
diff --git a/compiler/rustc_data_structures/src/flock/linux.rs b/compiler/rustc_data_structures/src/flock/linux.rs
new file mode 100644 (file)
index 0000000..bb3ecfb
--- /dev/null
@@ -0,0 +1,40 @@
+//! We use `flock` rather than `fcntl` on Linux, because WSL1 does not support
+//! `fcntl`-style advisory locks properly (rust-lang/rust#72157). For other Unix
+//! targets we still use `fcntl` because it's more portable than `flock`.
+
+use std::fs::{File, OpenOptions};
+use std::io;
+use std::os::unix::prelude::*;
+use std::path::Path;
+
+#[derive(Debug)]
+pub struct Lock {
+    _file: File,
+}
+
+impl Lock {
+    pub fn new(p: &Path, wait: bool, create: bool, exclusive: bool) -> io::Result<Lock> {
+        let file = OpenOptions::new()
+            .read(true)
+            .write(true)
+            .create(create)
+            .mode(libc::S_IRWXU as u32)
+            .open(p)?;
+
+        let mut operation = if exclusive { libc::LOCK_EX } else { libc::LOCK_SH };
+        if !wait {
+            operation |= libc::LOCK_NB
+        }
+
+        let ret = unsafe { libc::flock(file.as_raw_fd(), operation) };
+        if ret == -1 { Err(io::Error::last_os_error()) } else { Ok(Lock { _file: file }) }
+    }
+
+    pub fn error_unsupported(err: &io::Error) -> bool {
+        matches!(err.raw_os_error(), Some(libc::ENOTSUP) | Some(libc::ENOSYS))
+    }
+}
+
+// Note that we don't need a Drop impl to execute `flock(fd, LOCK_UN)`. A lock acquired by
+// `flock` is associated with the file descriptor and closing the file releases it
+// automatically.
diff --git a/compiler/rustc_data_structures/src/flock/unix.rs b/compiler/rustc_data_structures/src/flock/unix.rs
new file mode 100644 (file)
index 0000000..4e5297d
--- /dev/null
@@ -0,0 +1,51 @@
+use std::fs::{File, OpenOptions};
+use std::io;
+use std::mem;
+use std::os::unix::prelude::*;
+use std::path::Path;
+
+#[derive(Debug)]
+pub struct Lock {
+    file: File,
+}
+
+impl Lock {
+    pub fn new(p: &Path, wait: bool, create: bool, exclusive: bool) -> io::Result<Lock> {
+        let file = OpenOptions::new()
+            .read(true)
+            .write(true)
+            .create(create)
+            .mode(libc::S_IRWXU as u32)
+            .open(p)?;
+
+        let lock_type = if exclusive { libc::F_WRLCK } else { libc::F_RDLCK };
+
+        let mut flock: libc::flock = unsafe { mem::zeroed() };
+        flock.l_type = lock_type as libc::c_short;
+        flock.l_whence = libc::SEEK_SET as libc::c_short;
+        flock.l_start = 0;
+        flock.l_len = 0;
+
+        let cmd = if wait { libc::F_SETLKW } else { libc::F_SETLK };
+        let ret = unsafe { libc::fcntl(file.as_raw_fd(), cmd, &flock) };
+        if ret == -1 { Err(io::Error::last_os_error()) } else { Ok(Lock { file }) }
+    }
+
+    pub fn error_unsupported(err: &io::Error) -> bool {
+        matches!(err.raw_os_error(), Some(libc::ENOTSUP) | Some(libc::ENOSYS))
+    }
+}
+
+impl Drop for Lock {
+    fn drop(&mut self) {
+        let mut flock: libc::flock = unsafe { mem::zeroed() };
+        flock.l_type = libc::F_UNLCK as libc::c_short;
+        flock.l_whence = libc::SEEK_SET as libc::c_short;
+        flock.l_start = 0;
+        flock.l_len = 0;
+
+        unsafe {
+            libc::fcntl(self.file.as_raw_fd(), libc::F_SETLK, &flock);
+        }
+    }
+}
diff --git a/compiler/rustc_data_structures/src/flock/unsupported.rs b/compiler/rustc_data_structures/src/flock/unsupported.rs
new file mode 100644 (file)
index 0000000..9245fca
--- /dev/null
@@ -0,0 +1,16 @@
+use std::io;
+use std::path::Path;
+
+#[derive(Debug)]
+pub struct Lock(());
+
+impl Lock {
+    pub fn new(_p: &Path, _wait: bool, _create: bool, _exclusive: bool) -> io::Result<Lock> {
+        let msg = "file locks not supported on this platform";
+        Err(io::Error::new(io::ErrorKind::Other, msg))
+    }
+
+    pub fn error_unsupported(_err: &io::Error) -> bool {
+        true
+    }
+}
diff --git a/compiler/rustc_data_structures/src/flock/windows.rs b/compiler/rustc_data_structures/src/flock/windows.rs
new file mode 100644 (file)
index 0000000..43e6caa
--- /dev/null
@@ -0,0 +1,77 @@
+use std::fs::{File, OpenOptions};
+use std::io;
+use std::mem;
+use std::os::windows::prelude::*;
+use std::path::Path;
+
+use winapi::shared::winerror::ERROR_INVALID_FUNCTION;
+use winapi::um::fileapi::LockFileEx;
+use winapi::um::minwinbase::{LOCKFILE_EXCLUSIVE_LOCK, LOCKFILE_FAIL_IMMEDIATELY, OVERLAPPED};
+use winapi::um::winnt::{FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE};
+
+#[derive(Debug)]
+pub struct Lock {
+    _file: File,
+}
+
+impl Lock {
+    pub fn new(p: &Path, wait: bool, create: bool, exclusive: bool) -> io::Result<Lock> {
+        assert!(
+            p.parent().unwrap().exists(),
+            "Parent directory of lock-file must exist: {}",
+            p.display()
+        );
+
+        let share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
+
+        let mut open_options = OpenOptions::new();
+        open_options.read(true).share_mode(share_mode);
+
+        if create {
+            open_options.create(true).write(true);
+        }
+
+        debug!("attempting to open lock file `{}`", p.display());
+        let file = match open_options.open(p) {
+            Ok(file) => {
+                debug!("lock file opened successfully");
+                file
+            }
+            Err(err) => {
+                debug!("error opening lock file: {}", err);
+                return Err(err);
+            }
+        };
+
+        let ret = unsafe {
+            let mut overlapped: OVERLAPPED = mem::zeroed();
+
+            let mut dwFlags = 0;
+            if !wait {
+                dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
+            }
+
+            if exclusive {
+                dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
+            }
+
+            debug!("attempting to acquire lock on lock file `{}`", p.display());
+            LockFileEx(file.as_raw_handle(), dwFlags, 0, 0xFFFF_FFFF, 0xFFFF_FFFF, &mut overlapped)
+        };
+        if ret == 0 {
+            let err = io::Error::last_os_error();
+            debug!("failed acquiring file lock: {}", err);
+            Err(err)
+        } else {
+            debug!("successfully acquired lock");
+            Ok(Lock { _file: file })
+        }
+    }
+
+    pub fn error_unsupported(err: &io::Error) -> bool {
+        err.raw_os_error() == Some(ERROR_INVALID_FUNCTION as i32)
+    }
+}
+
+// Note that we don't need a Drop impl on Windows: The file is unlocked
+// automatically when it's closed.
index 1a3fe652521567d839b359fdffa81ae0fd70c9b2..30a3ddc6003035e417b74db88c7fd4864211af4d 100644 (file)
@@ -14,6 +14,8 @@
 #![feature(control_flow_enum)]
 #![feature(core_intrinsics)]
 #![feature(extend_one)]
+#![feature(generator_trait)]
+#![feature(generators)]
 #![feature(let_else)]
 #![feature(hash_raw_entry)]
 #![feature(maybe_uninit_uninit_array)]
@@ -27,7 +29,6 @@
 #![feature(thread_id_value)]
 #![feature(vec_into_raw_parts)]
 #![allow(rustc::default_hash_types)]
-#![deny(unaligned_references)]
 #![allow(rustc::potential_query_instability)]
 
 #[macro_use]
@@ -113,6 +114,9 @@ macro_rules! unlikely {
 pub use ena::undo_log;
 pub use ena::unify;
 
+use std::ops::{Generator, GeneratorState};
+use std::pin::Pin;
+
 pub struct OnDrop<F: Fn()>(pub F);
 
 impl<F: Fn()> OnDrop<F> {
@@ -131,6 +135,26 @@ fn drop(&mut self) {
     }
 }
 
+struct IterFromGenerator<G>(G);
+
+impl<G: Generator<Return = ()> + Unpin> Iterator for IterFromGenerator<G> {
+    type Item = G::Yield;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match Pin::new(&mut self.0).resume(()) {
+            GeneratorState::Yielded(n) => Some(n),
+            GeneratorState::Complete(_) => None,
+        }
+    }
+}
+
+/// An adapter for turning a generator closure into an iterator, similar to `iter::from_fn`.
+pub fn iter_from_generator<G: Generator<Return = ()> + Unpin>(
+    generator: G,
+) -> impl Iterator<Item = G::Yield> {
+    IterFromGenerator(generator)
+}
+
 // See comments in src/librustc_middle/lib.rs
 #[doc(hidden)]
 pub fn __noop_fix_for_27438() {}
index fd6ff086b08cd1f735a7160f54fd0294dbf9573c..3f7a90a8467b85b3ac91983e9e51a729d2f6b358 100644 (file)
@@ -97,6 +97,7 @@
 pub use measureme::EventId;
 use measureme::{EventIdBuilder, Profiler, SerializableString, StringId};
 use parking_lot::RwLock;
+use smallvec::SmallVec;
 
 bitflags::bitflags! {
     struct EventFilter: u32 {
@@ -183,11 +184,11 @@ pub fn new(
         }
     }
 
-    // This shim makes sure that calls only get executed if the filter mask
-    // lets them pass. It also contains some trickery to make sure that
-    // code is optimized for non-profiling compilation sessions, i.e. anything
-    // past the filter check is never inlined so it doesn't clutter the fast
-    // path.
+    /// This shim makes sure that calls only get executed if the filter mask
+    /// lets them pass. It also contains some trickery to make sure that
+    /// code is optimized for non-profiling compilation sessions, i.e. anything
+    /// past the filter check is never inlined so it doesn't clutter the fast
+    /// path.
     #[inline(always)]
     fn exec<F>(&self, event_filter: EventFilter, f: F) -> TimingGuard<'_>
     where
@@ -288,6 +289,66 @@ pub fn generic_activity_with_arg<A>(
         })
     }
 
+    /// Start profiling a generic activity, allowing costly arguments to be recorded. Profiling
+    /// continues until the `TimingGuard` returned from this call is dropped.
+    ///
+    /// If the arguments to a generic activity are cheap to create, use `generic_activity_with_arg`
+    /// or `generic_activity_with_args` for their simpler API. However, if they are costly or
+    /// require allocation in sufficiently hot contexts, then this allows for a closure to be called
+    /// only when arguments were asked to be recorded via `-Z self-profile-events=args`.
+    ///
+    /// In this case, the closure will be passed a `&mut EventArgRecorder`, to help with recording
+    /// one or many arguments within the generic activity being profiled, by calling its
+    /// `record_arg` method for example.
+    ///
+    /// This `EventArgRecorder` may implement more specific traits from other rustc crates, e.g. for
+    /// richer handling of rustc-specific argument types, while keeping this single entry-point API
+    /// for recording arguments.
+    ///
+    /// Note: recording at least one argument is *required* for the self-profiler to create the
+    /// `TimingGuard`. A panic will be triggered if that doesn't happen. This function exists
+    /// explicitly to record arguments, so it fails loudly when there are none to record.
+    ///
+    #[inline(always)]
+    pub fn generic_activity_with_arg_recorder<F>(
+        &self,
+        event_label: &'static str,
+        mut f: F,
+    ) -> TimingGuard<'_>
+    where
+        F: FnMut(&mut EventArgRecorder<'_>),
+    {
+        // Ensure this event will only be recorded when self-profiling is turned on.
+        self.exec(EventFilter::GENERIC_ACTIVITIES, |profiler| {
+            let builder = EventIdBuilder::new(&profiler.profiler);
+            let event_label = profiler.get_or_alloc_cached_string(event_label);
+
+            // Ensure the closure to create event arguments will only be called when argument
+            // recording is turned on.
+            let event_id = if profiler.event_filter_mask.contains(EventFilter::FUNCTION_ARGS) {
+                // Set up the builder and call the user-provided closure to record potentially
+                // costly event arguments.
+                let mut recorder = EventArgRecorder { profiler, args: SmallVec::new() };
+                f(&mut recorder);
+
+                // It is expected that the closure will record at least one argument. If that
+                // doesn't happen, it's a bug: we've been explicitly called in order to record
+                // arguments, so we fail loudly when there are none to record.
+                if recorder.args.is_empty() {
+                    panic!(
+                        "The closure passed to `generic_activity_with_arg_recorder` needs to \
+                         record at least one argument"
+                    );
+                }
+
+                builder.from_label_and_args(event_label, &recorder.args)
+            } else {
+                builder.from_label(event_label)
+            };
+            TimingGuard::start(profiler, profiler.generic_activity_event_kind, event_id)
+        })
+    }
+
     /// Record the size of an artifact that the compiler produces
     ///
     /// `artifact_kind` is the class of artifact (e.g., query_cache, object_file, etc.)
@@ -443,6 +504,33 @@ pub fn get_self_profiler(&self) -> Option<Arc<SelfProfiler>> {
     }
 }
 
+/// A helper for recording costly arguments to self-profiling events. Used with
+/// `SelfProfilerRef::generic_activity_with_arg_recorder`.
+pub struct EventArgRecorder<'p> {
+    /// The `SelfProfiler` used to intern the event arguments that users will ask to record.
+    profiler: &'p SelfProfiler,
+
+    /// The interned event arguments to be recorded in the generic activity event.
+    ///
+    /// The most common case, when actually recording event arguments, is to have one argument. Then
+    /// followed by recording two, in a couple places.
+    args: SmallVec<[StringId; 2]>,
+}
+
+impl EventArgRecorder<'_> {
+    /// Records a single argument within the current generic activity being profiled.
+    ///
+    /// Note: when self-profiling with costly event arguments, at least one argument
+    /// needs to be recorded. A panic will be triggered if that doesn't happen.
+    pub fn record_arg<A>(&mut self, event_arg: A)
+    where
+        A: Borrow<str> + Into<String>,
+    {
+        let event_arg = self.profiler.get_or_alloc_cached_string(event_arg);
+        self.args.push(event_arg);
+    }
+}
+
 pub struct SelfProfiler {
     profiler: Profiler,
     event_filter_mask: EventFilter,
index 85ad0f2f7f5ce5aca99f2f8ddc601ce1f7f45f6b..25353290fd50c4943c018554102791388342163d 100644 (file)
@@ -207,9 +207,14 @@ pub trait ToStableHashKey<HCX> {
     fn to_stable_hash_key(&self, hcx: &HCX) -> Self::KeyType;
 }
 
-// Implement HashStable by just calling `Hash::hash()`. This works fine for
-// self-contained values that don't depend on the hashing context `CTX`.
-#[macro_export]
+/// Implement HashStable by just calling `Hash::hash()`.
+///
+/// **WARNING** This is only valid for types that *really* don't need any context for fingerprinting.
+/// But it is easy to misuse this macro (see [#96013](https://github.com/rust-lang/rust/issues/96013)
+/// for examples). Therefore this macro is not exported and should only be used in the limited cases
+/// here in this module.
+///
+/// Use `#[derive(HashStable_Generic)]` instead.
 macro_rules! impl_stable_hash_via_hash {
     ($t:ty) => {
         impl<CTX> $crate::stable_hasher::HashStable<CTX> for $t {
@@ -246,12 +251,14 @@ fn hash_stable(&self, _ctx: &mut CTX, _hasher: &mut StableHasher) {
 }
 
 impl<CTX> HashStable<CTX> for ::std::num::NonZeroU32 {
+    #[inline]
     fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
         self.get().hash_stable(ctx, hasher)
     }
 }
 
 impl<CTX> HashStable<CTX> for ::std::num::NonZeroUsize {
+    #[inline]
     fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
         self.get().hash_stable(ctx, hasher)
     }
@@ -272,12 +279,14 @@ fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
 }
 
 impl<CTX> HashStable<CTX> for ::std::cmp::Ordering {
+    #[inline]
     fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
         (*self as i8).hash_stable(ctx, hasher);
     }
 }
 
 impl<T1: HashStable<CTX>, CTX> HashStable<CTX> for (T1,) {
+    #[inline]
     fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
         let (ref _0,) = *self;
         _0.hash_stable(ctx, hasher);
index de0dd18cc6ec5402283997b1adcb2581aa34c343..e1e0ed7222d55fb39265197de0f449e32bf5d32d 100644 (file)
@@ -338,18 +338,12 @@ pub fn primary_spans(&self) -> &[Span] {
 
     /// Returns `true` if any of the primary spans are displayable.
     pub fn has_primary_spans(&self) -> bool {
-        self.primary_spans.iter().any(|sp| !sp.is_dummy())
+        !self.is_dummy()
     }
 
     /// Returns `true` if this contains only a dummy primary span with any hygienic context.
     pub fn is_dummy(&self) -> bool {
-        let mut is_dummy = true;
-        for span in &self.primary_spans {
-            if !span.is_dummy() {
-                is_dummy = false;
-            }
-        }
-        is_dummy
+        self.primary_spans.iter().all(|sp| sp.is_dummy())
     }
 
     /// Replaces all occurrences of one Span with another. Used to move `Span`s in areas that don't
index 9cd072c8b4cdf38af332c504b226cea1996edb3f..cd17726c78588dae3ac87503de5ba14dd192a8c1 100644 (file)
@@ -1,12 +1,11 @@
 use crate::snippet::Style;
 use crate::{
     CodeSuggestion, DiagnosticMessage, Level, MultiSpan, Substitution, SubstitutionPart,
-    SuggestionStyle, ToolMetadata,
+    SuggestionStyle,
 };
 use rustc_data_structures::stable_map::FxHashMap;
 use rustc_error_messages::FluentValue;
 use rustc_lint_defs::{Applicability, LintExpectationId};
-use rustc_serialize::json::Json;
 use rustc_span::edition::LATEST_STABLE_EDITION;
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -554,7 +553,6 @@ pub fn multipart_suggestion_with_style(
             msg: msg.into(),
             style,
             applicability,
-            tool_metadata: Default::default(),
         });
         self
     }
@@ -582,7 +580,6 @@ pub fn tool_only_multipart_suggestion(
             msg: msg.into(),
             style: SuggestionStyle::CompletelyHidden,
             applicability,
-            tool_metadata: Default::default(),
         });
         self
     }
@@ -637,7 +634,6 @@ pub fn span_suggestion_with_style(
             msg: msg.into(),
             style,
             applicability,
-            tool_metadata: Default::default(),
         });
         self
     }
@@ -680,7 +676,6 @@ pub fn span_suggestions(
             msg: msg.into(),
             style: SuggestionStyle::ShowCode,
             applicability,
-            tool_metadata: Default::default(),
         });
         self
     }
@@ -705,7 +700,6 @@ pub fn multipart_suggestions(
             msg: msg.into(),
             style: SuggestionStyle::ShowCode,
             applicability,
-            tool_metadata: Default::default(),
         });
         self
     }
@@ -774,23 +768,6 @@ pub fn tool_only_span_suggestion(
         self
     }
 
-    /// Adds a suggestion intended only for a tool. The intent is that the metadata encodes
-    /// the suggestion in a tool-specific way, as it may not even directly involve Rust code.
-    pub fn tool_only_suggestion_with_metadata(
-        &mut self,
-        msg: impl Into<DiagnosticMessage>,
-        applicability: Applicability,
-        tool_metadata: Json,
-    ) {
-        self.push_suggestion(CodeSuggestion {
-            substitutions: vec![],
-            msg: msg.into(),
-            style: SuggestionStyle::CompletelyHidden,
-            applicability,
-            tool_metadata: ToolMetadata::new(tool_metadata),
-        })
-    }
-
     pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self {
         self.span = sp.into();
         if let Some(span) = self.span.primary_span() {
index 0139007da4261222d7b565c72da23e59bca2b586..d680e7fab704763917a2361f2c67b2100b33e915 100644 (file)
@@ -14,7 +14,6 @@
 use crate::emitter::{Emitter, HumanReadableErrorType};
 use crate::registry::Registry;
 use crate::DiagnosticId;
-use crate::ToolMetadata;
 use crate::{
     CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, SubDiagnostic,
 };
@@ -30,7 +29,6 @@
 use std::vec;
 
 use rustc_serialize::json::{as_json, as_pretty_json};
-use rustc_serialize::{Encodable, Encoder};
 
 #[cfg(test)]
 mod tests;
@@ -205,8 +203,7 @@ fn should_show_explain(&self) -> bool {
 
 // The following data types are provided just for serialisation.
 
-// NOTE: this has a manual implementation of Encodable which needs to be updated in
-// parallel.
+#[derive(Encodable)]
 struct Diagnostic {
     /// The primary error message.
     message: String,
@@ -218,65 +215,6 @@ struct Diagnostic {
     children: Vec<Diagnostic>,
     /// The message as rustc would render it.
     rendered: Option<String>,
-    /// Extra tool metadata
-    tool_metadata: ToolMetadata,
-}
-
-macro_rules! encode_fields {
-    (
-        $enc:expr,                  // encoder
-        $idx:expr,                  // starting field index
-        $struct:expr,               // struct we're serializing
-        $struct_name:ident,         // struct name
-        [ $($name:ident),+$(,)? ],  // fields to encode
-        [ $($ignore:ident),+$(,)? ] // fields we're skipping
-    ) => {
-        {
-            // Pattern match to make sure all fields are accounted for
-            let $struct_name { $($name,)+ $($ignore: _,)+ } = $struct;
-            let mut idx = $idx;
-            $(
-                $enc.emit_struct_field(
-                    stringify!($name),
-                    idx == 0,
-                    |enc| $name.encode(enc),
-                )?;
-                idx += 1;
-            )+
-            idx
-        }
-    };
-}
-
-// Special-case encoder to skip tool_metadata if not set
-impl<E: Encoder> Encodable<E> for Diagnostic {
-    fn encode(&self, s: &mut E) -> Result<(), E::Error> {
-        s.emit_struct(false, |s| {
-            let mut idx = 0;
-
-            idx = encode_fields!(
-                s,
-                idx,
-                self,
-                Self,
-                [message, code, level, spans, children, rendered],
-                [tool_metadata]
-            );
-            if self.tool_metadata.is_set() {
-                idx = encode_fields!(
-                    s,
-                    idx,
-                    self,
-                    Self,
-                    [tool_metadata],
-                    [message, code, level, spans, children, rendered]
-                );
-            }
-
-            let _ = idx;
-            Ok(())
-        })
-    }
 }
 
 #[derive(Encodable)]
@@ -380,7 +318,6 @@ fn from_errors_diagnostic(diag: &crate::Diagnostic, je: &JsonEmitter) -> Diagnos
                 spans: DiagnosticSpan::from_suggestion(sugg, &args, je),
                 children: vec![],
                 rendered: None,
-                tool_metadata: sugg.tool_metadata.clone(),
             }
         });
 
@@ -428,7 +365,6 @@ fn flush(&mut self) -> io::Result<()> {
                 .chain(sugg)
                 .collect(),
             rendered: Some(output),
-            tool_metadata: ToolMetadata::default(),
         }
     }
 
@@ -449,7 +385,6 @@ fn from_sub_diagnostic(
                 .unwrap_or_else(|| DiagnosticSpan::from_multispan(&diag.span, args, je)),
             children: vec![],
             rendered: None,
-            tool_metadata: ToolMetadata::default(),
         }
     }
 }
index cfad1fc01abb01a279345f9c8a72212f3fec29c2..4e6ab0edf6666377c97b16e433619dd6c785f2c2 100644 (file)
     LazyFallbackBundle, MultiSpan, SpanLabel, DEFAULT_LOCALE_RESOURCES,
 };
 pub use rustc_lint_defs::{pluralize, Applicability};
-use rustc_serialize::json::Json;
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use rustc_span::source_map::SourceMap;
+use rustc_span::HashStableContext;
 use rustc_span::{Loc, Span};
 
 use std::borrow::Cow;
-use std::hash::{Hash, Hasher};
+use std::hash::Hash;
 use std::num::NonZeroUsize;
 use std::panic;
 use std::path::Path;
@@ -93,39 +92,6 @@ fn hide_inline(&self) -> bool {
     }
 }
 
-#[derive(Clone, Debug, PartialEq, Default)]
-pub struct ToolMetadata(pub Option<Json>);
-
-impl ToolMetadata {
-    fn new(json: Json) -> Self {
-        ToolMetadata(Some(json))
-    }
-
-    fn is_set(&self) -> bool {
-        self.0.is_some()
-    }
-}
-
-impl Hash for ToolMetadata {
-    fn hash<H: Hasher>(&self, _state: &mut H) {}
-}
-
-// Doesn't really need to round-trip
-impl<D: Decoder> Decodable<D> for ToolMetadata {
-    fn decode(_d: &mut D) -> Self {
-        ToolMetadata(None)
-    }
-}
-
-impl<S: Encoder> Encodable<S> for ToolMetadata {
-    fn encode(&self, e: &mut S) -> Result<(), S::Error> {
-        match &self.0 {
-            None => e.emit_unit(),
-            Some(json) => json.encode(e),
-        }
-    }
-}
-
 #[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
 pub struct CodeSuggestion {
     /// Each substitute can have multiple variants due to multiple
@@ -159,8 +125,6 @@ pub struct CodeSuggestion {
     /// which are useful for users but not useful for
     /// tools like rustfix
     pub applicability: Applicability,
-    /// Tool-specific metadata
-    pub tool_metadata: ToolMetadata,
 }
 
 #[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
@@ -1208,7 +1172,7 @@ fn print_error_count(&mut self, registry: &Registry) {
             (0, 0) => return,
             (0, _) => self.emitter.emit_diagnostic(&Diagnostic::new(
                 Level::Warning,
-                DiagnosticMessage::Str(warnings.to_owned()),
+                DiagnosticMessage::Str(warnings),
             )),
             (_, 0) => {
                 let _ = self.fatal(&errors);
@@ -1511,35 +1475,17 @@ pub fn add_elided_lifetime_in_path_suggestion(
     path_span: Span,
     incl_angl_brckt: bool,
     insertion_span: Span,
-    anon_lts: String,
 ) {
-    let (replace_span, suggestion) = if incl_angl_brckt {
-        (insertion_span, anon_lts)
-    } else {
-        // When possible, prefer a suggestion that replaces the whole
-        // `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, `
-        // at a point (which makes for an ugly/confusing label)
-        if let Ok(snippet) = source_map.span_to_snippet(path_span) {
-            // But our spans can get out of whack due to macros; if the place we think
-            // we want to insert `'_` isn't even within the path expression's span, we
-            // should bail out of making any suggestion rather than panicking on a
-            // subtract-with-overflow or string-slice-out-out-bounds (!)
-            // FIXME: can we do better?
-            if insertion_span.lo().0 < path_span.lo().0 {
-                return;
-            }
-            let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize;
-            if insertion_index > snippet.len() {
-                return;
-            }
-            let (before, after) = snippet.split_at(insertion_index);
-            (path_span, format!("{}{}{}", before, anon_lts, after))
-        } else {
-            (insertion_span, anon_lts)
-        }
-    };
-    diag.span_suggestion(
-        replace_span,
+    diag.span_label(path_span, format!("expected lifetime parameter{}", pluralize!(n)));
+    if source_map.span_to_snippet(insertion_span).is_err() {
+        // Do not try to suggest anything if generated by a proc-macro.
+        return;
+    }
+    let anon_lts = vec!["'_"; n].join(", ");
+    let suggestion =
+        if incl_angl_brckt { format!("<{}>", anon_lts) } else { format!("{}, ", anon_lts) };
+    diag.span_suggestion_verbose(
+        insertion_span.shrink_to_hi(),
         &format!("indicate the anonymous lifetime{}", pluralize!(n)),
         suggestion,
         Applicability::MachineApplicable,
@@ -1549,6 +1495,7 @@ pub fn add_elided_lifetime_in_path_suggestion(
 /// Useful type to use with `Result<>` indicate that an error has already
 /// been reported to the user, so no need to continue checking.
 #[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(HashStable_Generic)]
 pub struct ErrorGuaranteed(());
 
 impl ErrorGuaranteed {
@@ -1558,5 +1505,3 @@ pub fn unchecked_claim_error_was_emitted() -> Self {
         ErrorGuaranteed(())
     }
 }
-
-rustc_data_structures::impl_stable_hash_via_hash!(ErrorGuaranteed);
index 63aac64989dfaa4d4712bbade80c1cc4eee67b8c..8f260e1cdb5c8c04296792a237238a0b980fd6cf 100644 (file)
@@ -590,7 +590,7 @@ pub(super) fn parse_tt(
                 (_, 0) => {
                     // Dump all possible `next_mps` into `cur_mps` for the next iteration. Then
                     // process the next token.
-                    self.cur_mps.extend(self.next_mps.drain(..));
+                    self.cur_mps.append(&mut self.next_mps);
                     parser.to_mut().bump();
                 }
 
index aec401a041ca35d51e29d92266c933f53ba88dda..8e1966a0711d6c6087b0dc540f34f5e34ae3a0bd 100644 (file)
@@ -9,6 +9,7 @@
 use rustc_errors::ErrorGuaranteed;
 use rustc_parse::nt_to_tokenstream;
 use rustc_parse::parser::ForceCollect;
+use rustc_span::profiling::SpannedEventArgRecorder;
 use rustc_span::{Span, DUMMY_SP};
 
 const EXEC_STRATEGY: pm::bridge::server::SameThread = pm::bridge::server::SameThread;
@@ -25,7 +26,10 @@ fn expand<'cx>(
         input: TokenStream,
     ) -> Result<TokenStream, ErrorGuaranteed> {
         let _timer =
-            ecx.sess.prof.generic_activity_with_arg("expand_proc_macro", ecx.expansion_descr());
+            ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
+                recorder.record_arg_with_span(ecx.expansion_descr(), span);
+            });
+
         let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
         let server = proc_macro_server::Rustc::new(ecx);
         self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace).map_err(|e| {
@@ -51,7 +55,10 @@ fn expand<'cx>(
         annotated: TokenStream,
     ) -> Result<TokenStream, ErrorGuaranteed> {
         let _timer =
-            ecx.sess.prof.generic_activity_with_arg("expand_proc_macro", ecx.expansion_descr());
+            ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
+                recorder.record_arg_with_span(ecx.expansion_descr(), span);
+            });
+
         let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
         let server = proc_macro_server::Rustc::new(ecx);
         self.client
@@ -103,7 +110,9 @@ fn expand(
 
         let stream = {
             let _timer =
-                ecx.sess.prof.generic_activity_with_arg("expand_proc_macro", ecx.expansion_descr());
+                ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
+                    recorder.record_arg_with_span(ecx.expansion_descr(), span);
+                });
             let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
             let server = proc_macro_server::Rustc::new(ecx);
             match self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace) {
index 53d60d280c001dcf3179d0488facd869e828a5dc..324e110005717ac6517f4f357e4b4dc7c08cc1a2 100644 (file)
@@ -1,4 +1,4 @@
-use crate::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use crate::def_id::DefId;
 use crate::hir;
 
 use rustc_ast as ast;
@@ -124,9 +124,7 @@ impl DefKind {
     pub fn descr(self, def_id: DefId) -> &'static str {
         match self {
             DefKind::Fn => "function",
-            DefKind::Mod if def_id.index == CRATE_DEF_INDEX && def_id.krate != LOCAL_CRATE => {
-                "crate"
-            }
+            DefKind::Mod if def_id.is_crate_root() && !def_id.is_local() => "crate",
             DefKind::Mod => "module",
             DefKind::Static(..) => "static",
             DefKind::Enum => "enum",
index 4908992085a6e12de70bf3f25fc513d71c4f0ff2..bce9ba12ac0c424045e391a05f420f714307d4f7 100644 (file)
@@ -353,11 +353,6 @@ pub fn new(stable_crate_id: StableCrateId, crate_span: Span) -> Definitions {
         }
     }
 
-    /// Retrieves the root definition.
-    pub fn get_root_def(&self) -> LocalDefId {
-        LocalDefId { local_def_index: CRATE_DEF_INDEX }
-    }
-
     /// Adds a definition with a parent definition.
     pub fn create_def(
         &mut self,
index 68ae2441af7979d185e1db47dbdf7908e82b0cd5..ef56093bed8d9f6dbe0979d47013fe03ae65290c 100644 (file)
@@ -4,8 +4,8 @@
 use crate::intravisit::FnKind;
 use crate::LangItem;
 
+use rustc_ast as ast;
 use rustc_ast::util::parser::ExprPrecedence;
-use rustc_ast::{self as ast, CrateSugar};
 use rustc_ast::{Attribute, FloatTy, IntTy, Label, LitKind, TraitObjectSyntax, UintTy};
 pub use rustc_ast::{BorrowKind, ImplPolarity, IsAuto};
 pub use rustc_ast::{CaptureBy, Movability, Mutability};
@@ -95,7 +95,7 @@ pub enum LifetimeName {
     /// User wrote nothing (e.g., the lifetime in `&u32`).
     ///
     /// The bool indicates whether the user should have written something.
-    Implicit(bool),
+    Implicit,
 
     /// Implicit lifetime in a context like `dyn Foo`. This is
     /// distinguished from implicit lifetimes elsewhere because the
@@ -125,7 +125,7 @@ impl LifetimeName {
     pub fn ident(&self) -> Ident {
         match *self {
             LifetimeName::ImplicitObjectLifetimeDefault
-            | LifetimeName::Implicit(_)
+            | LifetimeName::Implicit
             | LifetimeName::Error => Ident::empty(),
             LifetimeName::Underscore => Ident::with_dummy_span(kw::UnderscoreLifetime),
             LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime),
@@ -136,7 +136,7 @@ pub fn ident(&self) -> Ident {
     pub fn is_elided(&self) -> bool {
         match self {
             LifetimeName::ImplicitObjectLifetimeDefault
-            | LifetimeName::Implicit(_)
+            | LifetimeName::Implicit
             | LifetimeName::Underscore => true,
 
             // It might seem surprising that `Fresh(_)` counts as
@@ -2140,10 +2140,10 @@ pub fn hir_id(&self) -> HirId {
 pub struct ImplItem<'hir> {
     pub ident: Ident,
     pub def_id: LocalDefId,
-    pub vis: Visibility<'hir>,
     pub generics: Generics<'hir>,
     pub kind: ImplItemKind<'hir>,
     pub span: Span,
+    pub vis_span: Span,
 }
 
 impl ImplItem<'_> {
@@ -2425,8 +2425,12 @@ pub enum InlineAsmOperand<'hir> {
     Const {
         anon_const: AnonConst,
     },
-    Sym {
-        expr: Expr<'hir>,
+    SymFn {
+        anon_const: AnonConst,
+    },
+    SymStatic {
+        path: QPath<'hir>,
+        def_id: DefId,
     },
 }
 
@@ -2437,7 +2441,7 @@ pub fn reg(&self) -> Option<InlineAsmRegOrRegClass> {
             | Self::Out { reg, .. }
             | Self::InOut { reg, .. }
             | Self::SplitInOut { reg, .. } => Some(reg),
-            Self::Const { .. } | Self::Sym { .. } => None,
+            Self::Const { .. } | Self::SymFn { .. } | Self::SymStatic { .. } => None,
         }
     }
 
@@ -2641,34 +2645,11 @@ pub struct PolyTraitRef<'hir> {
     pub span: Span,
 }
 
-pub type Visibility<'hir> = Spanned<VisibilityKind<'hir>>;
-
-#[derive(Copy, Clone, Debug, HashStable_Generic)]
-pub enum VisibilityKind<'hir> {
-    Public,
-    Crate(CrateSugar),
-    Restricted { path: &'hir Path<'hir>, hir_id: HirId },
-    Inherited,
-}
-
-impl VisibilityKind<'_> {
-    pub fn is_pub(&self) -> bool {
-        matches!(*self, VisibilityKind::Public)
-    }
-
-    pub fn is_pub_restricted(&self) -> bool {
-        match *self {
-            VisibilityKind::Public | VisibilityKind::Inherited => false,
-            VisibilityKind::Crate(..) | VisibilityKind::Restricted { .. } => true,
-        }
-    }
-}
-
 #[derive(Debug, HashStable_Generic)]
 pub struct FieldDef<'hir> {
     pub span: Span,
+    pub vis_span: Span,
     pub ident: Ident,
-    pub vis: Visibility<'hir>,
     pub hir_id: HirId,
     pub ty: &'hir Ty<'hir>,
 }
@@ -2740,8 +2721,8 @@ pub struct Item<'hir> {
     pub ident: Ident,
     pub def_id: LocalDefId,
     pub kind: ItemKind<'hir>,
-    pub vis: Visibility<'hir>,
     pub span: Span,
+    pub vis_span: Span,
 }
 
 impl Item<'_> {
@@ -2998,7 +2979,7 @@ pub struct ForeignItem<'hir> {
     pub kind: ForeignItemKind<'hir>,
     pub def_id: LocalDefId,
     pub span: Span,
-    pub vis: Visibility<'hir>,
+    pub vis_span: Span,
 }
 
 impl ForeignItem<'_> {
@@ -3206,7 +3187,6 @@ pub enum Node<'hir> {
 
     Lifetime(&'hir Lifetime),
     GenericParam(&'hir GenericParam<'hir>),
-    Visibility(&'hir Visibility<'hir>),
 
     Crate(&'hir Mod<'hir>),
 
@@ -3249,7 +3229,6 @@ pub fn ident(&self) -> Option<Ident> {
             | Node::Binding(..)
             | Node::Arm(..)
             | Node::Local(..)
-            | Node::Visibility(..)
             | Node::Crate(..)
             | Node::Ty(..)
             | Node::TraitRef(..)
@@ -3314,18 +3293,18 @@ pub fn fn_kind(self) -> Option<FnKind<'hir>> {
         match self {
             Node::Item(i) => match i.kind {
                 ItemKind::Fn(ref sig, ref generics, _) => {
-                    Some(FnKind::ItemFn(i.ident, generics, sig.header, &i.vis))
+                    Some(FnKind::ItemFn(i.ident, generics, sig.header))
                 }
                 _ => None,
             },
             Node::TraitItem(ti) => match ti.kind {
                 TraitItemKind::Fn(ref sig, TraitFn::Provided(_)) => {
-                    Some(FnKind::Method(ti.ident, sig, None))
+                    Some(FnKind::Method(ti.ident, sig))
                 }
                 _ => None,
             },
             Node::ImplItem(ii) => match ii.kind {
-                ImplItemKind::Fn(ref sig, _) => Some(FnKind::Method(ii.ident, sig, Some(&ii.vis))),
+                ImplItemKind::Fn(ref sig, _) => Some(FnKind::Method(ii.ident, sig)),
                 _ => None,
             },
             Node::Expr(e) => match e.kind {
@@ -3346,8 +3325,8 @@ mod size_asserts {
     rustc_data_structures::static_assert_size!(super::QPath<'static>, 24);
     rustc_data_structures::static_assert_size!(super::Ty<'static>, 72);
 
-    rustc_data_structures::static_assert_size!(super::Item<'static>, 184);
+    rustc_data_structures::static_assert_size!(super::Item<'static>, 160);
     rustc_data_structures::static_assert_size!(super::TraitItem<'static>, 128);
-    rustc_data_structures::static_assert_size!(super::ImplItem<'static>, 144);
-    rustc_data_structures::static_assert_size!(super::ForeignItem<'static>, 136);
+    rustc_data_structures::static_assert_size!(super::ImplItem<'static>, 120);
+    rustc_data_structures::static_assert_size!(super::ForeignItem<'static>, 112);
 }
index 3b5e4dcf5e01188db28d3edfcab62cc43167b28f..346ac9e96440abfb1eae0ec9932bf40d5b6fdd91 100644 (file)
@@ -1,4 +1,4 @@
-use crate::def_id::{LocalDefId, CRATE_DEF_INDEX};
+use crate::def_id::{LocalDefId, CRATE_DEF_ID};
 use std::fmt;
 
 /// Uniquely identifies a node in the HIR of the current crate. It is
@@ -76,16 +76,14 @@ fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
     /// integers starting at zero, so a mapping that maps all or most nodes within
     /// an "item-like" to something else can be implemented by a `Vec` instead of a
     /// tree or hash map.
+    #[derive(HashStable_Generic)]
     pub struct ItemLocalId { .. }
 }
-rustc_data_structures::impl_stable_hash_via_hash!(ItemLocalId);
+
 impl ItemLocalId {
     /// Signal local id which should never be used.
     pub const INVALID: ItemLocalId = ItemLocalId::MAX;
 }
 
-/// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_INDEX`.
-pub const CRATE_HIR_ID: HirId = HirId {
-    owner: LocalDefId { local_def_index: CRATE_DEF_INDEX },
-    local_id: ItemLocalId::from_u32(0),
-};
+/// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_ID`.
+pub const CRATE_HIR_ID: HirId = HirId { owner: CRATE_DEF_ID, local_id: ItemLocalId::from_u32(0) };
index 1b40f3d390ee59dedaaa266035821931afb96594..59bd46ae353b2f23611d087d0ba11de57ec68614 100644 (file)
@@ -100,10 +100,10 @@ fn visit_foreign_item(&self, foreign_item: &'hir ForeignItem<'hir>) {
 #[derive(Copy, Clone, Debug)]
 pub enum FnKind<'a> {
     /// `#[xxx] pub async/const/extern "Abi" fn foo()`
-    ItemFn(Ident, &'a Generics<'a>, FnHeader, &'a Visibility<'a>),
+    ItemFn(Ident, &'a Generics<'a>, FnHeader),
 
     /// `fn foo(&self)`
-    Method(Ident, &'a FnSig<'a>, Option<&'a Visibility<'a>>),
+    Method(Ident, &'a FnSig<'a>),
 
     /// `|x, y| {}`
     Closure,
@@ -112,8 +112,8 @@ pub enum FnKind<'a> {
 impl<'a> FnKind<'a> {
     pub fn header(&self) -> Option<&FnHeader> {
         match *self {
-            FnKind::ItemFn(_, _, ref header, _) => Some(header),
-            FnKind::Method(_, ref sig, _) => Some(&sig.header),
+            FnKind::ItemFn(_, _, ref header) => Some(header),
+            FnKind::Method(_, ref sig) => Some(&sig.header),
             FnKind::Closure => None,
         }
     }
@@ -475,15 +475,15 @@ fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding<'v>) {
         walk_assoc_type_binding(self, type_binding)
     }
     fn visit_attribute(&mut self, _id: HirId, _attr: &'v Attribute) {}
-    fn visit_vis(&mut self, vis: &'v Visibility<'v>) {
-        walk_vis(self, vis)
-    }
     fn visit_associated_item_kind(&mut self, kind: &'v AssocItemKind) {
         walk_associated_item_kind(self, kind);
     }
     fn visit_defaultness(&mut self, defaultness: &'v Defaultness) {
         walk_defaultness(self, defaultness);
     }
+    fn visit_inline_asm(&mut self, asm: &'v InlineAsm<'v>, id: HirId) {
+        walk_inline_asm(self, asm, id);
+    }
 }
 
 pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod<'v>, mod_hir_id: HirId) {
@@ -525,7 +525,7 @@ pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime
         | LifetimeName::Param(ParamName::Error)
         | LifetimeName::Static
         | LifetimeName::Error
-        | LifetimeName::Implicit(_)
+        | LifetimeName::Implicit
         | LifetimeName::ImplicitObjectLifetimeDefault
         | LifetimeName::Underscore => {}
     }
@@ -551,7 +551,6 @@ pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) {
 }
 
 pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
-    visitor.visit_vis(&item.vis);
     visitor.visit_ident(item.ident);
     match item.kind {
         ItemKind::ExternCrate(orig_name) => {
@@ -569,7 +568,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
             visitor.visit_nested_body(body);
         }
         ItemKind::Fn(ref sig, ref generics, body_id) => visitor.visit_fn(
-            FnKind::ItemFn(item.ident, generics, sig.header, &item.vis),
+            FnKind::ItemFn(item.ident, generics, sig.header),
             &sig.decl,
             body_id,
             item.span,
@@ -588,7 +587,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
         }
         ItemKind::GlobalAsm(asm) => {
             visitor.visit_id(item.hir_id());
-            walk_inline_asm(visitor, asm);
+            visitor.visit_inline_asm(asm, item.hir_id());
         }
         ItemKind::TyAlias(ref ty, ref generics) => {
             visitor.visit_id(item.hir_id());
@@ -648,12 +647,12 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
     }
 }
 
-fn walk_inline_asm<'v, V: Visitor<'v>>(visitor: &mut V, asm: &'v InlineAsm<'v>) {
-    for (op, _op_sp) in asm.operands {
+pub fn walk_inline_asm<'v, V: Visitor<'v>>(visitor: &mut V, asm: &'v InlineAsm<'v>, id: HirId) {
+    for (op, op_sp) in asm.operands {
         match op {
-            InlineAsmOperand::In { expr, .. }
-            | InlineAsmOperand::InOut { expr, .. }
-            | InlineAsmOperand::Sym { expr, .. } => visitor.visit_expr(expr),
+            InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => {
+                visitor.visit_expr(expr)
+            }
             InlineAsmOperand::Out { expr, .. } => {
                 if let Some(expr) = expr {
                     visitor.visit_expr(expr);
@@ -665,7 +664,9 @@ fn walk_inline_asm<'v, V: Visitor<'v>>(visitor: &mut V, asm: &'v InlineAsm<'v>)
                     visitor.visit_expr(out_expr);
                 }
             }
-            InlineAsmOperand::Const { anon_const } => visitor.visit_anon_const(anon_const),
+            InlineAsmOperand::Const { anon_const, .. }
+            | InlineAsmOperand::SymFn { anon_const, .. } => visitor.visit_anon_const(anon_const),
+            InlineAsmOperand::SymStatic { path, .. } => visitor.visit_qpath(path, id, *op_sp),
         }
     }
 }
@@ -854,7 +855,6 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) {
 
 pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem<'v>) {
     visitor.visit_id(foreign_item.hir_id());
-    visitor.visit_vis(&foreign_item.vis);
     visitor.visit_ident(foreign_item.ident);
 
     match foreign_item.kind {
@@ -994,7 +994,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
         }
         TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => {
             visitor.visit_fn(
-                FnKind::Method(trait_item.ident, sig, None),
+                FnKind::Method(trait_item.ident, sig),
                 &sig.decl,
                 body_id,
                 trait_item.span,
@@ -1020,10 +1020,9 @@ pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref:
 
 pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem<'v>) {
     // N.B., deliberately force a compilation error if/when new fields are added.
-    let ImplItem { def_id: _, ident, ref vis, ref generics, ref kind, span: _ } = *impl_item;
+    let ImplItem { def_id: _, ident, ref generics, ref kind, span: _, vis_span: _ } = *impl_item;
 
     visitor.visit_ident(ident);
-    visitor.visit_vis(vis);
     visitor.visit_generics(generics);
     match *kind {
         ImplItemKind::Const(ref ty, body) => {
@@ -1033,7 +1032,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
         }
         ImplItemKind::Fn(ref sig, body_id) => {
             visitor.visit_fn(
-                FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis)),
+                FnKind::Method(impl_item.ident, sig),
                 &sig.decl,
                 body_id,
                 impl_item.span,
@@ -1077,7 +1076,6 @@ pub fn walk_struct_def<'v, V: Visitor<'v>>(
 
 pub fn walk_field_def<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v FieldDef<'v>) {
     visitor.visit_id(field.hir_id);
-    visitor.visit_vis(&field.vis);
     visitor.visit_ident(field.ident);
     visitor.visit_ty(&field.ty);
 }
@@ -1221,7 +1219,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
             walk_list!(visitor, visit_expr, optional_expression);
         }
         ExprKind::InlineAsm(ref asm) => {
-            walk_inline_asm(visitor, asm);
+            visitor.visit_inline_asm(asm, expression.hir_id);
         }
         ExprKind::Yield(ref subexpression, _) => {
             visitor.visit_expr(subexpression);
@@ -1245,13 +1243,6 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) {
     visitor.visit_expr(&arm.body);
 }
 
-pub fn walk_vis<'v, V: Visitor<'v>>(visitor: &mut V, vis: &'v Visibility<'v>) {
-    if let VisibilityKind::Restricted { ref path, hir_id } = vis.node {
-        visitor.visit_id(hir_id);
-        visitor.visit_path(path, hir_id)
-    }
-}
-
 pub fn walk_associated_item_kind<'v, V: Visitor<'v>>(_: &mut V, _: &'v AssocItemKind) {
     // No visitable content here: this fn exists so you can call it if
     // the right thing to do, should content be added in the future,
index 70d9db4a84ba1e2910a0b8ff2c6ebfc9710fd8ba..96dd00ec5cff193210506e64b99e8a60fb285981 100644 (file)
@@ -7,6 +7,7 @@
 use crate::hir;
 use crate::{Item, ItemKind, TraitItem, TraitItemKind};
 
+use crate::def::DefKind;
 use std::fmt::{self, Display};
 
 #[derive(Copy, Clone, PartialEq, Debug)]
@@ -130,6 +131,30 @@ pub fn from_item(item: &Item<'_>) -> Target {
         }
     }
 
+    // FIXME: For now, should only be used with def_kinds from ItemIds
+    pub fn from_def_kind(def_kind: DefKind) -> Target {
+        match def_kind {
+            DefKind::ExternCrate => Target::ExternCrate,
+            DefKind::Use => Target::Use,
+            DefKind::Static(..) => Target::Static,
+            DefKind::Const => Target::Const,
+            DefKind::Fn => Target::Fn,
+            DefKind::Macro(..) => Target::MacroDef,
+            DefKind::Mod => Target::Mod,
+            DefKind::ForeignMod => Target::ForeignMod,
+            DefKind::GlobalAsm => Target::GlobalAsm,
+            DefKind::TyAlias => Target::TyAlias,
+            DefKind::OpaqueTy => Target::OpaqueTy,
+            DefKind::Enum => Target::Enum,
+            DefKind::Struct => Target::Struct,
+            DefKind::Union => Target::Union,
+            DefKind::Trait => Target::Trait,
+            DefKind::TraitAlias => Target::TraitAlias,
+            DefKind::Impl => Target::Impl,
+            _ => panic!("impossible case reached"),
+        }
+    }
+
     pub fn from_trait_item(trait_item: &TraitItem<'_>) -> Target {
         match trait_item.kind {
             TraitItemKind::Const(..) => Target::AssocConst,
index b3042c61002c4fae7f129ea618ece77c66bffea3..87ff94577836cfcccd89d382c2eb98bc252356b9 100644 (file)
@@ -8,12 +8,11 @@
 use rustc_hir as hir;
 use rustc_hir::{GenericArg, GenericParam, GenericParamKind, Node, Term};
 use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier};
-use rustc_span::source_map::{SourceMap, Spanned};
+use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, Ident, IdentPrinter, Symbol};
 use rustc_span::{self, FileName};
 use rustc_target::spec::abi::Abi;
 
-use std::borrow::Cow;
 use std::cell::Cell;
 use std::vec;
 
@@ -98,7 +97,6 @@ pub fn print_node(&mut self, node: Node<'_>) {
                 self.print_block(&a)
             }
             Node::Lifetime(a) => self.print_lifetime(&a),
-            Node::Visibility(a) => self.print_visibility(&a),
             Node::GenericParam(_) => panic!("cannot print Node::GenericParam"),
             Node::Field(_) => panic!("cannot print Node::Field"),
             // These cases do not carry enough information in the
@@ -191,13 +189,6 @@ pub fn to_string<F>(ann: &dyn PpAnn, f: F) -> String
     printer.s.eof()
 }
 
-pub fn visibility_qualified<S: Into<Cow<'static, str>>>(vis: &hir::Visibility<'_>, w: S) -> String {
-    to_string(NO_ANN, |s| {
-        s.print_visibility(vis);
-        s.word(w)
-    })
-}
-
 pub fn generic_params_to_string(generic_params: &[GenericParam<'_>]) -> String {
     to_string(NO_ANN, |s| s.print_generic_params(generic_params))
 }
@@ -223,11 +214,10 @@ pub fn fn_to_string(
     header: hir::FnHeader,
     name: Option<Symbol>,
     generics: &hir::Generics<'_>,
-    vis: &hir::Visibility<'_>,
     arg_names: &[Ident],
     body_id: Option<hir::BodyId>,
 ) -> String {
-    to_string(NO_ANN, |s| s.print_fn(decl, header, name, generics, vis, arg_names, body_id))
+    to_string(NO_ANN, |s| s.print_fn(decl, header, name, generics, arg_names, body_id))
 }
 
 pub fn enum_def_to_string(
@@ -235,9 +225,8 @@ pub fn enum_def_to_string(
     generics: &hir::Generics<'_>,
     name: Symbol,
     span: rustc_span::Span,
-    visibility: &hir::Visibility<'_>,
 ) -> String {
-    to_string(NO_ANN, |s| s.print_enum_def(enum_definition, generics, name, span, visibility))
+    to_string(NO_ANN, |s| s.print_enum_def(enum_definition, generics, name, span))
 }
 
 impl<'a> State<'a> {
@@ -395,7 +384,6 @@ pub fn print_foreign_item(&mut self, item: &hir::ForeignItem<'_>) {
                     },
                     Some(item.ident.name),
                     generics,
-                    &item.vis,
                     arg_names,
                     None,
                 );
@@ -404,7 +392,7 @@ pub fn print_foreign_item(&mut self, item: &hir::ForeignItem<'_>) {
                 self.end() // end the outer fn box
             }
             hir::ForeignItemKind::Static(ref t, m) => {
-                self.head(visibility_qualified(&item.vis, "static"));
+                self.head("static");
                 if m == hir::Mutability::Mut {
                     self.word_space("mut");
                 }
@@ -416,7 +404,7 @@ pub fn print_foreign_item(&mut self, item: &hir::ForeignItem<'_>) {
                 self.end() // end the outer cbox
             }
             hir::ForeignItemKind::Type => {
-                self.head(visibility_qualified(&item.vis, "type"));
+                self.head("type");
                 self.print_ident(item.ident);
                 self.word(";");
                 self.end(); // end the head-ibox
@@ -430,9 +418,8 @@ fn print_associated_const(
         ident: Ident,
         ty: &hir::Ty<'_>,
         default: Option<hir::BodyId>,
-        vis: &hir::Visibility<'_>,
     ) {
-        self.word(visibility_qualified(vis, ""));
+        self.head("");
         self.word_space("const");
         self.print_ident(ident);
         self.word_space(":");
@@ -473,7 +460,7 @@ fn print_item_type(
         generics: &hir::Generics<'_>,
         inner: impl Fn(&mut Self),
     ) {
-        self.head(visibility_qualified(&item.vis, "type"));
+        self.head("type");
         self.print_ident(item.ident);
         self.print_generic_params(&generics.params);
         self.end(); // end the inner ibox
@@ -494,7 +481,7 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
         self.ann.pre(self, AnnNode::Item(item));
         match item.kind {
             hir::ItemKind::ExternCrate(orig_name) => {
-                self.head(visibility_qualified(&item.vis, "extern crate"));
+                self.head("extern crate");
                 if let Some(orig_name) = orig_name {
                     self.print_name(orig_name);
                     self.space();
@@ -507,7 +494,7 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
                 self.end(); // end outer head-block
             }
             hir::ItemKind::Use(ref path, kind) => {
-                self.head(visibility_qualified(&item.vis, "use"));
+                self.head("use");
                 self.print_path(path, false);
 
                 match kind {
@@ -526,7 +513,7 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
                 self.end(); // end outer head-block
             }
             hir::ItemKind::Static(ref ty, m, expr) => {
-                self.head(visibility_qualified(&item.vis, "static"));
+                self.head("static");
                 if m == hir::Mutability::Mut {
                     self.word_space("mut");
                 }
@@ -542,7 +529,7 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
                 self.end(); // end the outer cbox
             }
             hir::ItemKind::Const(ref ty, expr) => {
-                self.head(visibility_qualified(&item.vis, "const"));
+                self.head("const");
                 self.print_ident(item.ident);
                 self.word_space(":");
                 self.print_type(&ty);
@@ -561,7 +548,6 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
                     sig.header,
                     Some(item.ident.name),
                     param_names,
-                    &item.vis,
                     &[],
                     Some(body),
                 );
@@ -571,12 +557,10 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
                 self.ann.nested(self, Nested::Body(body));
             }
             hir::ItemKind::Macro(ref macro_def, _) => {
-                self.print_mac_def(macro_def, &item.ident, item.span, |state| {
-                    state.print_visibility(&item.vis)
-                });
+                self.print_mac_def(macro_def, &item.ident, item.span, |_| {});
             }
             hir::ItemKind::Mod(ref _mod) => {
-                self.head(visibility_qualified(&item.vis, "mod"));
+                self.head("mod");
                 self.print_ident(item.ident);
                 self.nbsp();
                 self.bopen();
@@ -594,7 +578,7 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
                 self.bclose(item.span);
             }
             hir::ItemKind::GlobalAsm(ref asm) => {
-                self.head(visibility_qualified(&item.vis, "global_asm!"));
+                self.head("global_asm!");
                 self.print_inline_asm(asm);
                 self.end()
             }
@@ -620,14 +604,14 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
                 });
             }
             hir::ItemKind::Enum(ref enum_definition, ref params) => {
-                self.print_enum_def(enum_definition, params, item.ident.name, item.span, &item.vis);
+                self.print_enum_def(enum_definition, params, item.ident.name, item.span);
             }
             hir::ItemKind::Struct(ref struct_def, ref generics) => {
-                self.head(visibility_qualified(&item.vis, "struct"));
+                self.head("struct");
                 self.print_struct(struct_def, generics, item.ident.name, item.span, true);
             }
             hir::ItemKind::Union(ref struct_def, ref generics) => {
-                self.head(visibility_qualified(&item.vis, "union"));
+                self.head("union");
                 self.print_struct(struct_def, generics, item.ident.name, item.span, true);
             }
             hir::ItemKind::Impl(hir::Impl {
@@ -642,7 +626,6 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
                 items,
             }) => {
                 self.head("");
-                self.print_visibility(&item.vis);
                 self.print_defaultness(defaultness);
                 self.print_unsafety(unsafety);
                 self.word_nbsp("impl");
@@ -679,7 +662,6 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
             }
             hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, trait_items) => {
                 self.head("");
-                self.print_visibility(&item.vis);
                 self.print_is_auto(is_auto);
                 self.print_unsafety(unsafety);
                 self.word_nbsp("trait");
@@ -705,7 +687,7 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
                 self.bclose(item.span);
             }
             hir::ItemKind::TraitAlias(ref generics, ref bounds) => {
-                self.head(visibility_qualified(&item.vis, "trait"));
+                self.head("trait");
                 self.print_ident(item.ident);
                 self.print_generic_params(&generics.params);
                 let mut real_bounds = Vec::with_capacity(bounds.len());
@@ -753,9 +735,8 @@ pub fn print_enum_def(
         generics: &hir::Generics<'_>,
         name: Symbol,
         span: rustc_span::Span,
-        visibility: &hir::Visibility<'_>,
     ) {
-        self.head(visibility_qualified(visibility, "enum"));
+        self.head("enum");
         self.print_name(name);
         self.print_generic_params(&generics.params);
         self.print_where_clause(&generics.where_clause);
@@ -778,27 +759,6 @@ pub fn print_variants(&mut self, variants: &[hir::Variant<'_>], span: rustc_span
         self.bclose(span)
     }
 
-    pub fn print_visibility(&mut self, vis: &hir::Visibility<'_>) {
-        match vis.node {
-            hir::VisibilityKind::Public => self.word_nbsp("pub"),
-            hir::VisibilityKind::Crate(ast::CrateSugar::JustCrate) => self.word_nbsp("crate"),
-            hir::VisibilityKind::Crate(ast::CrateSugar::PubCrate) => self.word_nbsp("pub(crate)"),
-            hir::VisibilityKind::Restricted { ref path, .. } => {
-                self.word("pub(");
-                if path.segments.len() == 1 && path.segments[0].ident.name == kw::Super {
-                    // Special case: `super` can print like `pub(super)`.
-                    self.word("super");
-                } else {
-                    // Everything else requires `in` at present.
-                    self.word_nbsp("in");
-                    self.print_path(path, false);
-                }
-                self.word_nbsp(")");
-            }
-            hir::VisibilityKind::Inherited => (),
-        }
-    }
-
     pub fn print_defaultness(&mut self, defaultness: hir::Defaultness) {
         match defaultness {
             hir::Defaultness::Default { .. } => self.word_nbsp("default"),
@@ -823,7 +783,6 @@ pub fn print_struct(
                     self.commasep(Inconsistent, struct_def.fields(), |s, field| {
                         s.maybe_print_comment(field.span.lo());
                         s.print_outer_attributes(s.attrs(field.hir_id));
-                        s.print_visibility(&field.vis);
                         s.print_type(&field.ty)
                     });
                     self.pclose();
@@ -845,7 +804,6 @@ pub fn print_struct(
                     self.hardbreak_if_not_bol();
                     self.maybe_print_comment(field.span.lo());
                     self.print_outer_attributes(self.attrs(field.hir_id));
-                    self.print_visibility(&field.vis);
                     self.print_ident(field.ident);
                     self.word_nbsp(":");
                     self.print_type(&field.ty);
@@ -872,11 +830,10 @@ pub fn print_method_sig(
         ident: Ident,
         m: &hir::FnSig<'_>,
         generics: &hir::Generics<'_>,
-        vis: &hir::Visibility<'_>,
         arg_names: &[Ident],
         body_id: Option<hir::BodyId>,
     ) {
-        self.print_fn(&m.decl, m.header, Some(ident.name), generics, vis, arg_names, body_id)
+        self.print_fn(&m.decl, m.header, Some(ident.name), generics, arg_names, body_id)
     }
 
     pub fn print_trait_item(&mut self, ti: &hir::TraitItem<'_>) {
@@ -886,21 +843,15 @@ pub fn print_trait_item(&mut self, ti: &hir::TraitItem<'_>) {
         self.print_outer_attributes(self.attrs(ti.hir_id()));
         match ti.kind {
             hir::TraitItemKind::Const(ref ty, default) => {
-                let vis =
-                    Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited };
-                self.print_associated_const(ti.ident, &ty, default, &vis);
+                self.print_associated_const(ti.ident, &ty, default);
             }
             hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref arg_names)) => {
-                let vis =
-                    Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited };
-                self.print_method_sig(ti.ident, sig, &ti.generics, &vis, arg_names, None);
+                self.print_method_sig(ti.ident, sig, &ti.generics, arg_names, None);
                 self.word(";");
             }
             hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
-                let vis =
-                    Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited };
                 self.head("");
-                self.print_method_sig(ti.ident, sig, &ti.generics, &vis, &[], Some(body));
+                self.print_method_sig(ti.ident, sig, &ti.generics, &[], Some(body));
                 self.nbsp();
                 self.end(); // need to close a box
                 self.end(); // need to close a box
@@ -926,11 +877,11 @@ pub fn print_impl_item(&mut self, ii: &hir::ImplItem<'_>) {
 
         match ii.kind {
             hir::ImplItemKind::Const(ref ty, expr) => {
-                self.print_associated_const(ii.ident, &ty, Some(expr), &ii.vis);
+                self.print_associated_const(ii.ident, &ty, Some(expr));
             }
             hir::ImplItemKind::Fn(ref sig, body) => {
                 self.head("");
-                self.print_method_sig(ii.ident, sig, &ii.generics, &ii.vis, &[], Some(body));
+                self.print_method_sig(ii.ident, sig, &ii.generics, &[], Some(body));
                 self.nbsp();
                 self.end(); // need to close a box
                 self.end(); // need to close a box
@@ -1352,10 +1303,15 @@ enum AsmArg<'a> {
                     s.space();
                     s.print_anon_const(anon_const);
                 }
-                hir::InlineAsmOperand::Sym { expr } => {
-                    s.word("sym");
+                hir::InlineAsmOperand::SymFn { anon_const } => {
+                    s.word("sym_fn");
                     s.space();
-                    s.print_expr(expr);
+                    s.print_anon_const(anon_const);
+                }
+                hir::InlineAsmOperand::SymStatic { path, def_id: _ } => {
+                    s.word("sym_static");
+                    s.space();
+                    s.print_qpath(path, true);
                 }
             },
             AsmArg::Options(opts) => {
@@ -2003,11 +1959,10 @@ pub fn print_fn(
         header: hir::FnHeader,
         name: Option<Symbol>,
         generics: &hir::Generics<'_>,
-        vis: &hir::Visibility<'_>,
         arg_names: &[Ident],
         body_id: Option<hir::BodyId>,
     ) {
-        self.print_fn_header_info(header, vis);
+        self.print_fn_header_info(header);
 
         if let Some(name) = name {
             self.nbsp();
@@ -2296,16 +2251,13 @@ pub fn print_ty_fn(
             },
             name,
             &generics,
-            &Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited },
             arg_names,
             None,
         );
         self.end();
     }
 
-    pub fn print_fn_header_info(&mut self, header: hir::FnHeader, vis: &hir::Visibility<'_>) {
-        self.word(visibility_qualified(vis, ""));
-
+    pub fn print_fn_header_info(&mut self, header: hir::FnHeader) {
         match header.constness {
             hir::Constness::NotConst => {}
             hir::Constness::Const => self.word_nbsp("const"),
index 60b48e9bc8a0124d1b2fc793121ba42e901fb173..2d06c9d8ec92c60d8f6cb3d56820d56d7c0d29d7 100644 (file)
@@ -241,7 +241,7 @@ fn dump_graph(query: &DepGraphQuery) {
             let targets = node_set(&query, &edge_filter.target);
             filter_nodes(&query, &sources, &targets)
         }
-        Err(_) => query.nodes().into_iter().collect(),
+        Err(_) => query.nodes().into_iter().map(|n| n.kind).collect(),
     };
     let edges = filter_edges(&query, &nodes);
 
@@ -264,33 +264,33 @@ fn dump_graph(query: &DepGraphQuery) {
 }
 
 #[allow(missing_docs)]
-pub struct GraphvizDepGraph<'q>(FxHashSet<&'q DepNode>, Vec<(&'q DepNode, &'q DepNode)>);
+pub struct GraphvizDepGraph(FxHashSet<DepKind>, Vec<(DepKind, DepKind)>);
 
-impl<'a, 'q> dot::GraphWalk<'a> for GraphvizDepGraph<'q> {
-    type Node = &'q DepNode;
-    type Edge = (&'q DepNode, &'q DepNode);
-    fn nodes(&self) -> dot::Nodes<'_, &'q DepNode> {
+impl<'a> dot::GraphWalk<'a> for GraphvizDepGraph {
+    type Node = DepKind;
+    type Edge = (DepKind, DepKind);
+    fn nodes(&self) -> dot::Nodes<'_, DepKind> {
         let nodes: Vec<_> = self.0.iter().cloned().collect();
         nodes.into()
     }
-    fn edges(&self) -> dot::Edges<'_, (&'q DepNode, &'q DepNode)> {
+    fn edges(&self) -> dot::Edges<'_, (DepKind, DepKind)> {
         self.1[..].into()
     }
-    fn source(&self, edge: &(&'q DepNode, &'q DepNode)) -> &'q DepNode {
+    fn source(&self, edge: &(DepKind, DepKind)) -> DepKind {
         edge.0
     }
-    fn target(&self, edge: &(&'q DepNode, &'q DepNode)) -> &'q DepNode {
+    fn target(&self, edge: &(DepKind, DepKind)) -> DepKind {
         edge.1
     }
 }
 
-impl<'a, 'q> dot::Labeller<'a> for GraphvizDepGraph<'q> {
-    type Node = &'q DepNode;
-    type Edge = (&'q DepNode, &'q DepNode);
+impl<'a> dot::Labeller<'a> for GraphvizDepGraph {
+    type Node = DepKind;
+    type Edge = (DepKind, DepKind);
     fn graph_id(&self) -> dot::Id<'_> {
         dot::Id::new("DependencyGraph").unwrap()
     }
-    fn node_id(&self, n: &&'q DepNode) -> dot::Id<'_> {
+    fn node_id(&self, n: &DepKind) -> dot::Id<'_> {
         let s: String = format!("{:?}", n)
             .chars()
             .map(|c| if c == '_' || c.is_alphanumeric() { c } else { '_' })
@@ -298,7 +298,7 @@ fn node_id(&self, n: &&'q DepNode) -> dot::Id<'_> {
         debug!("n={:?} s={:?}", n, s);
         dot::Id::new(s).unwrap()
     }
-    fn node_label(&self, n: &&'q DepNode) -> dot::LabelText<'_> {
+    fn node_label(&self, n: &DepKind) -> dot::LabelText<'_> {
         dot::LabelText::label(format!("{:?}", n))
     }
 }
@@ -323,7 +323,7 @@ fn filter_nodes<'q>(
     query: &'q DepGraphQuery,
     sources: &Option<FxHashSet<&'q DepNode>>,
     targets: &Option<FxHashSet<&'q DepNode>>,
-) -> FxHashSet<&'q DepNode> {
+) -> FxHashSet<DepKind> {
     if let Some(sources) = sources {
         if let Some(targets) = targets {
             walk_between(query, sources, targets)
@@ -333,7 +333,7 @@ fn filter_nodes<'q>(
     } else if let Some(targets) = targets {
         walk_nodes(query, targets, INCOMING)
     } else {
-        query.nodes().into_iter().collect()
+        query.nodes().into_iter().map(|n| n.kind).collect()
     }
 }
 
@@ -341,17 +341,17 @@ fn walk_nodes<'q>(
     query: &'q DepGraphQuery,
     starts: &FxHashSet<&'q DepNode>,
     direction: Direction,
-) -> FxHashSet<&'q DepNode> {
+) -> FxHashSet<DepKind> {
     let mut set = FxHashSet::default();
     for &start in starts {
         debug!("walk_nodes: start={:?} outgoing?={:?}", start, direction == OUTGOING);
-        if set.insert(start) {
+        if set.insert(start.kind) {
             let mut stack = vec![query.indices[start]];
             while let Some(index) = stack.pop() {
                 for (_, edge) in query.graph.adjacent_edges(index, direction) {
                     let neighbor_index = edge.source_or_target(direction);
                     let neighbor = query.graph.node_data(neighbor_index);
-                    if set.insert(neighbor) {
+                    if set.insert(neighbor.kind) {
                         stack.push(neighbor_index);
                     }
                 }
@@ -365,7 +365,7 @@ fn walk_between<'q>(
     query: &'q DepGraphQuery,
     sources: &FxHashSet<&'q DepNode>,
     targets: &FxHashSet<&'q DepNode>,
-) -> FxHashSet<&'q DepNode> {
+) -> FxHashSet<DepKind> {
     // This is a bit tricky. We want to include a node only if it is:
     // (a) reachable from a source and (b) will reach a target. And we
     // have to be careful about cycles etc.  Luckily efficiency is not
@@ -396,6 +396,7 @@ enum State {
             let index = query.indices[n];
             node_states[index.0] == State::Included
         })
+        .map(|n| n.kind)
         .collect();
 
     fn recurse(query: &DepGraphQuery, node_states: &mut [State], node: NodeIndex) -> bool {
@@ -433,11 +434,13 @@ fn recurse(query: &DepGraphQuery, node_states: &mut [State], node: NodeIndex) ->
 
 fn filter_edges<'q>(
     query: &'q DepGraphQuery,
-    nodes: &FxHashSet<&'q DepNode>,
-) -> Vec<(&'q DepNode, &'q DepNode)> {
-    query
+    nodes: &FxHashSet<DepKind>,
+) -> Vec<(DepKind, DepKind)> {
+    let uniq: FxHashSet<_> = query
         .edges()
         .into_iter()
-        .filter(|&(source, target)| nodes.contains(source) && nodes.contains(target))
-        .collect()
+        .map(|(s, t)| (s.kind, t.kind))
+        .filter(|(source, target)| nodes.contains(source) && nodes.contains(target))
+        .collect();
+    uniq.into_iter().collect()
 }
index 8a4ed02f6aea16220601c3f4af2759cec8dbd966..aaf24636598b9c98a95574ee7def5b42fd869768 100644 (file)
@@ -24,7 +24,6 @@
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::Node as HirNode;
 use rustc_hir::{ImplItemKind, ItemKind as HirItem, TraitItemKind};
 use rustc_middle::dep_graph::{label_strs, DepNode, DepNodeExt};
@@ -147,7 +146,24 @@ pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) {
 
     tcx.dep_graph.with_ignore(|| {
         let mut dirty_clean_visitor = DirtyCleanVisitor { tcx, checked_attrs: Default::default() };
-        tcx.hir().visit_all_item_likes(&mut dirty_clean_visitor);
+
+        let crate_items = tcx.hir_crate_items(());
+
+        for id in crate_items.items() {
+            dirty_clean_visitor.check_item(id.def_id);
+        }
+
+        for id in crate_items.trait_items() {
+            dirty_clean_visitor.check_item(id.def_id);
+        }
+
+        for id in crate_items.impl_items() {
+            dirty_clean_visitor.check_item(id.def_id);
+        }
+
+        for id in crate_items.foreign_items() {
+            dirty_clean_visitor.check_item(id.def_id);
+        }
 
         let mut all_attrs = FindAllAttrs { tcx, found_attrs: vec![] };
         tcx.hir().walk_attributes(&mut all_attrs);
@@ -365,7 +381,8 @@ fn assert_loaded_from_disk(&self, item_span: Span, dep_node: DepNode) {
         }
     }
 
-    fn check_item(&mut self, item_id: LocalDefId, item_span: Span) {
+    fn check_item(&mut self, item_id: LocalDefId) {
+        let item_span = self.tcx.def_span(item_id.to_def_id());
         let def_path_hash = self.tcx.def_path_hash(item_id.to_def_id());
         for attr in self.tcx.get_attrs(item_id.to_def_id()).iter() {
             let Some(assertion) = self.assertion_maybe(item_id, attr) else {
@@ -388,24 +405,6 @@ fn check_item(&mut self, item_id: LocalDefId, item_span: Span) {
     }
 }
 
-impl<'tcx> ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'tcx> {
-    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        self.check_item(item.def_id, item.span);
-    }
-
-    fn visit_trait_item(&mut self, item: &hir::TraitItem<'_>) {
-        self.check_item(item.def_id, item.span);
-    }
-
-    fn visit_impl_item(&mut self, item: &hir::ImplItem<'_>) {
-        self.check_item(item.def_id, item.span);
-    }
-
-    fn visit_foreign_item(&mut self, item: &hir::ForeignItem<'_>) {
-        self.check_item(item.def_id, item.span);
-    }
-}
-
 /// Given a `#[rustc_clean]` attribute, scan for a `cfg="foo"` attribute and check whether we have
 /// a cfg flag called `foo`.
 fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool {
index 86229dbfad746a51b528e1de9fff6d256cf7baff..0ca0fe33614f826600589d69fd0edfcea9b14d9e 100644 (file)
@@ -567,11 +567,17 @@ fn relate_item_substs(
             // Avoid fetching the variance if we are in an invariant
             // context; no need, and it can induce dependency cycles
             // (e.g., #41849).
-            relate::relate_substs(self, None, a_subst, b_subst)
+            relate::relate_substs(self, a_subst, b_subst)
         } else {
             let tcx = self.tcx();
             let opt_variances = tcx.variances_of(item_def_id);
-            relate::relate_substs(self, Some((item_def_id, &opt_variances)), a_subst, b_subst)
+            relate::relate_substs_with_variances(
+                self,
+                item_def_id,
+                &opt_variances,
+                a_subst,
+                b_subst,
+            )
         }
     }
 
index 65c0eba4b3d5c791aa254269c389c3c26460e5f4..ef6d464d3c6f101bad711e81647aa88450a4857b 100644 (file)
@@ -53,7 +53,7 @@ fn relate_item_substs(
         // performing trait matching (which then performs equality
         // unification).
 
-        relate::relate_substs(self, None, a_subst, b_subst)
+        relate::relate_substs(self, a_subst, b_subst)
     }
 
     fn relate_with_variance<T: Relate<'tcx>>(
index f25215fe813d6d10b0856d2c697c771934d74aee..f9273cc50b70a2b6a44b6c1630afb6e618170035 100644 (file)
@@ -61,7 +61,7 @@
 use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed};
 use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan};
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{Item, ItemKind, Node};
 use rustc_middle::dep_graph::DepContext;
@@ -1448,6 +1448,7 @@ pub fn note_type_err(
         mut values: Option<ValuePairs<'tcx>>,
         terr: &TypeError<'tcx>,
         swap_secondary_and_primary: bool,
+        force_label: bool,
     ) {
         let span = cause.span(self.tcx);
         debug!("note_type_err cause={:?} values={:?}, terr={:?}", cause, values, terr);
@@ -1623,7 +1624,7 @@ enum Mismatch<'a> {
             TypeError::ObjectUnsafeCoercion(_) => {}
             _ => {
                 let mut label_or_note = |span: Span, msg: &str| {
-                    if &[span] == diag.span.primary_spans() {
+                    if force_label || &[span] == diag.span.primary_spans() {
                         diag.span_label(span, msg);
                     } else {
                         diag.span_note(span, msg);
@@ -2171,7 +2172,7 @@ pub fn report_and_explain_type_error(
                 struct_span_err!(self.tcx.sess, span, E0644, "{}", failure_str)
             }
         };
-        self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr, false);
+        self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr, false, false);
         diag
     }
 
@@ -2284,7 +2285,9 @@ pub fn report_generic_bound_failure(
         bound_kind: GenericKind<'tcx>,
         sub: Region<'tcx>,
     ) {
-        self.construct_generic_bound_failure(span, origin, bound_kind, sub).emit();
+        let owner =
+            self.in_progress_typeck_results.map(|typeck_results| typeck_results.borrow().hir_owner);
+        self.construct_generic_bound_failure(span, origin, bound_kind, sub, owner).emit();
     }
 
     pub fn construct_generic_bound_failure(
@@ -2293,31 +2296,29 @@ pub fn construct_generic_bound_failure(
         origin: Option<SubregionOrigin<'tcx>>,
         bound_kind: GenericKind<'tcx>,
         sub: Region<'tcx>,
+        owner: Option<LocalDefId>,
     ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
         let hir = self.tcx.hir();
         // Attempt to obtain the span of the parameter so we can
         // suggest adding an explicit lifetime bound to it.
-        let generics = self
-            .in_progress_typeck_results
-            .map(|typeck_results| typeck_results.borrow().hir_owner)
-            .map(|owner| {
-                let hir_id = hir.local_def_id_to_hir_id(owner);
-                let parent_id = hir.get_parent_item(hir_id);
-                (
-                    // Parent item could be a `mod`, so we check the HIR before calling:
-                    if let Some(Node::Item(Item {
-                        kind: ItemKind::Trait(..) | ItemKind::Impl { .. },
-                        ..
-                    })) = hir.find_by_def_id(parent_id)
-                    {
-                        Some(self.tcx.generics_of(parent_id))
-                    } else {
-                        None
-                    },
-                    self.tcx.generics_of(owner.to_def_id()),
-                    hir.span(hir_id),
-                )
-            });
+        let generics = owner.map(|owner| {
+            let hir_id = hir.local_def_id_to_hir_id(owner);
+            let parent_id = hir.get_parent_item(hir_id);
+            (
+                // Parent item could be a `mod`, so we check the HIR before calling:
+                if let Some(Node::Item(Item {
+                    kind: ItemKind::Trait(..) | ItemKind::Impl { .. },
+                    ..
+                })) = hir.find_by_def_id(parent_id)
+                {
+                    Some(self.tcx.generics_of(parent_id))
+                } else {
+                    None
+                },
+                self.tcx.generics_of(owner.to_def_id()),
+                hir.span(hir_id),
+            )
+        });
 
         let span = match generics {
             // This is to get around the trait identity obligation, that has a `DUMMY_SP` as signal
@@ -2605,11 +2606,8 @@ enum SubOrigin<'hir> {
                     None,
                 );
                 if let Some(infer::RelateParamBound(_, t, _)) = origin {
-                    let return_impl_trait = self
-                        .in_progress_typeck_results
-                        .map(|typeck_results| typeck_results.borrow().hir_owner)
-                        .and_then(|owner| self.tcx.return_type_impl_trait(owner))
-                        .is_some();
+                    let return_impl_trait =
+                        owner.and_then(|owner| self.tcx.return_type_impl_trait(owner)).is_some();
                     let t = self.resolve_vars_if_possible(t);
                     match t.kind() {
                         // We've got:
@@ -2765,7 +2763,7 @@ fn report_inference_failure(
     }
 }
 
-enum FailureCode {
+pub enum FailureCode {
     Error0038(DefId),
     Error0317(&'static str),
     Error0580(&'static str),
@@ -2773,7 +2771,7 @@ enum FailureCode {
     Error0644(&'static str),
 }
 
-trait ObligationCauseExt<'tcx> {
+pub trait ObligationCauseExt<'tcx> {
     fn as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode;
     fn as_requirement_str(&self) -> &'static str;
 }
index 2524bd78355a118c3701d1dedc371df28db90d1b..6ec929f98950e6a64901cb84620a2f7dd41b88dd 100644 (file)
@@ -385,8 +385,8 @@ pub fn ty(&self) -> Option<(Ty<'tcx>, Ty<'tcx>)> {
 /// See the `error_reporting` module for more details.
 #[derive(Clone, Debug)]
 pub struct TypeTrace<'tcx> {
-    cause: ObligationCause<'tcx>,
-    values: ValuePairs<'tcx>,
+    pub cause: ObligationCause<'tcx>,
+    pub values: ValuePairs<'tcx>,
 }
 
 /// The origin of a `r1 <= r2` constraint.
@@ -1659,49 +1659,6 @@ pub fn const_eval_resolve(
         self.tcx.const_eval_resolve(param_env_erased, unevaluated, span)
     }
 
-    /// If `typ` is a type variable of some kind, resolve it one level
-    /// (but do not resolve types found in the result). If `typ` is
-    /// not a type variable, just return it unmodified.
-    // FIXME(eddyb) inline into `ShallowResolver::visit_ty`.
-    fn shallow_resolve_ty(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
-        match *typ.kind() {
-            ty::Infer(ty::TyVar(v)) => {
-                // Not entirely obvious: if `typ` is a type variable,
-                // it can be resolved to an int/float variable, which
-                // can then be recursively resolved, hence the
-                // recursion. Note though that we prevent type
-                // variables from unifying to other type variables
-                // directly (though they may be embedded
-                // structurally), and we prevent cycles in any case,
-                // so this recursion should always be of very limited
-                // depth.
-                //
-                // Note: if these two lines are combined into one we get
-                // dynamic borrow errors on `self.inner`.
-                let known = self.inner.borrow_mut().type_variables().probe(v).known();
-                known.map_or(typ, |t| self.shallow_resolve_ty(t))
-            }
-
-            ty::Infer(ty::IntVar(v)) => self
-                .inner
-                .borrow_mut()
-                .int_unification_table()
-                .probe_value(v)
-                .map(|v| v.to_type(self.tcx))
-                .unwrap_or(typ),
-
-            ty::Infer(ty::FloatVar(v)) => self
-                .inner
-                .borrow_mut()
-                .float_unification_table()
-                .probe_value(v)
-                .map(|v| v.to_type(self.tcx))
-                .unwrap_or(typ),
-
-            _ => typ,
-        }
-    }
-
     /// `ty_or_const_infer_var_changed` is equivalent to one of these two:
     ///   * `shallow_resolve(ty) != ty` (where `ty.kind = ty::Infer(_)`)
     ///   * `shallow_resolve(ct) != ct` (where `ct.kind = ty::ConstKind::Infer(_)`)
@@ -1831,8 +1788,46 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
 
+    /// If `ty` is a type variable of some kind, resolve it one level
+    /// (but do not resolve types found in the result). If `typ` is
+    /// not a type variable, just return it unmodified.
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.infcx.shallow_resolve_ty(ty)
+        match *ty.kind() {
+            ty::Infer(ty::TyVar(v)) => {
+                // Not entirely obvious: if `typ` is a type variable,
+                // it can be resolved to an int/float variable, which
+                // can then be recursively resolved, hence the
+                // recursion. Note though that we prevent type
+                // variables from unifying to other type variables
+                // directly (though they may be embedded
+                // structurally), and we prevent cycles in any case,
+                // so this recursion should always be of very limited
+                // depth.
+                //
+                // Note: if these two lines are combined into one we get
+                // dynamic borrow errors on `self.inner`.
+                let known = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
+                known.map_or(ty, |t| self.fold_ty(t))
+            }
+
+            ty::Infer(ty::IntVar(v)) => self
+                .infcx
+                .inner
+                .borrow_mut()
+                .int_unification_table()
+                .probe_value(v)
+                .map_or(ty, |v| v.to_type(self.infcx.tcx)),
+
+            ty::Infer(ty::FloatVar(v)) => self
+                .infcx
+                .inner
+                .borrow_mut()
+                .float_unification_table()
+                .probe_value(v)
+                .map_or(ty, |v| v.to_type(self.infcx.tcx)),
+
+            _ => ty,
+        }
     }
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
index 2a01b677e33bf7e47cd4ec5e4b1a4c387bbe0666..08987dff660a4d78391280df384aa6a6430375f7 100644 (file)
@@ -629,11 +629,15 @@ fn write_out_deps(
         });
         files.extend(extra_tracked_files);
 
-        if let Some(ref backend) = sess.opts.debugging_opts.codegen_backend {
-            files.push(backend.to_string());
-        }
-
         if sess.binary_dep_depinfo() {
+            if let Some(ref backend) = sess.opts.debugging_opts.codegen_backend {
+                if backend.contains('.') {
+                    // If the backend name contain a `.`, it is the path to an external dynamic
+                    // library. If not, it is not a path.
+                    files.push(backend.to_string());
+                }
+            }
+
             boxed_resolver.borrow_mut().access(|resolver| {
                 for cnum in resolver.cstore().crates_untracked() {
                     let source = resolver.cstore().crate_source_untracked(cnum);
index c0316ce58d26e7ea12e9f93fb864ac83b0760886..5371c513d29819102df2d4cb9af3e6d8e6238024 100644 (file)
@@ -1,35 +1,25 @@
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::sym;
 
 fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> {
     let mut finder = Finder { tcx, decls: None };
-    tcx.hir().visit_all_item_likes(&mut finder);
 
-    finder.decls.map(|id| tcx.hir().local_def_id(id))
-}
-
-struct Finder<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    decls: Option<hir::HirId>,
-}
-
-impl<'v> ItemLikeVisitor<'v> for Finder<'_> {
-    fn visit_item(&mut self, item: &hir::Item<'_>) {
-        let attrs = self.tcx.hir().attrs(item.hir_id());
-        if self.tcx.sess.contains_name(attrs, sym::rustc_proc_macro_decls) {
-            self.decls = Some(item.hir_id());
+    for id in tcx.hir().items() {
+        let attrs = finder.tcx.hir().attrs(id.hir_id());
+        if finder.tcx.sess.contains_name(attrs, sym::rustc_proc_macro_decls) {
+            finder.decls = Some(id.def_id);
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
-
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
+    finder.decls
+}
 
-    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
+struct Finder<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    decls: Option<hir::def_id::LocalDefId>,
 }
 
 pub(crate) fn provide(providers: &mut Providers) {
index fe75ee8b37b8d06fd748bebed146d452ce4e00a9..1327bf6fcd427a9523213875f9ae02fec1fce78d 100644 (file)
@@ -66,6 +66,7 @@ fn new_public_extern_entry<S, I>(locations: I) -> ExternEntry
         location: ExternLocation::ExactPaths(locations),
         is_private_dep: false,
         add_prelude: true,
+        nounused_dep: false,
     }
 }
 
@@ -751,6 +752,7 @@ macro_rules! tracked {
     tracked!(location_detail, LocationDetail { file: true, line: false, column: false });
     tracked!(merge_functions, Some(MergeFunctions::Disabled));
     tracked!(mir_emit_retag, true);
+    tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]);
     tracked!(mir_opt_level, Some(4));
     tracked!(move_size_limit, Some(4096));
     tracked!(mutable_noalias, Some(true));
index 8ea47dda928f5f0cc8af8c4ab83299c95ee021e1..02f747eeccc3e1eb21f72d4f6395c4f0112bb58b 100644 (file)
@@ -18,7 +18,6 @@ rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_feature = { path = "../rustc_feature" }
 rustc_index = { path = "../rustc_index" }
 rustc_session = { path = "../rustc_session" }
-rustc_serialize = { path = "../rustc_serialize" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
 rustc_parse_format = { path = "../rustc_parse_format" }
 rustc_infer = { path = "../rustc_infer" }
index e6f9246d73242f4b1c2ebe200a15075b2f30db0d..68658e2616e9b76c697e1166374a1ebbbc09f05f 100644 (file)
@@ -36,8 +36,7 @@
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
-use rustc_hir::{ForeignItemKind, GenericParamKind, PatKind};
-use rustc_hir::{HirId, Node};
+use rustc_hir::{ForeignItemKind, GenericParamKind, HirId, PatKind};
 use rustc_index::vec::Idx;
 use rustc_middle::lint::LintDiagnosticBuilder;
 use rustc_middle::ty::layout::{LayoutError, LayoutOf};
@@ -441,6 +440,7 @@ fn check_fn(&mut self, cx: &EarlyContext<'_>, fk: FnKind<'_>, span: Span, _: ast
             _,
             ast::FnSig { header: ast::FnHeader { unsafety: ast::Unsafe::Yes(_), .. }, .. },
             _,
+            _,
             body,
         ) = fk
         {
@@ -486,9 +486,6 @@ fn check_fn(&mut self, cx: &EarlyContext<'_>, fk: FnKind<'_>, span: Span, _: ast
 pub struct MissingDoc {
     /// Stack of whether `#[doc(hidden)]` is set at each level which has lint attributes.
     doc_hidden_stack: Vec<bool>,
-
-    /// Private traits or trait items that leaked through. Don't check their methods.
-    private_traits: FxHashSet<hir::HirId>,
 }
 
 impl_lint_pass!(MissingDoc => [MISSING_DOCS]);
@@ -519,7 +516,7 @@ fn has_doc(attr: &ast::Attribute) -> bool {
 
 impl MissingDoc {
     pub fn new() -> MissingDoc {
-        MissingDoc { doc_hidden_stack: vec![false], private_traits: FxHashSet::default() }
+        MissingDoc { doc_hidden_stack: vec![false] }
     }
 
     fn doc_hidden(&self) -> bool {
@@ -597,30 +594,16 @@ fn check_crate(&mut self, cx: &LateContext<'_>) {
 
     fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
         match it.kind {
-            hir::ItemKind::Trait(.., trait_item_refs) => {
+            hir::ItemKind::Trait(..) => {
                 // Issue #11592: traits are always considered exported, even when private.
-                if let hir::VisibilityKind::Inherited = it.vis.node {
-                    self.private_traits.insert(it.hir_id());
-                    for trait_item_ref in trait_item_refs {
-                        self.private_traits.insert(trait_item_ref.id.hir_id());
-                    }
+                if cx.tcx.visibility(it.def_id)
+                    == ty::Visibility::Restricted(
+                        cx.tcx.parent_module_from_def_id(it.def_id).to_def_id(),
+                    )
+                {
                     return;
                 }
             }
-            hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref trait_ref), items, .. }) => {
-                // If the trait is private, add the impl items to `private_traits` so they don't get
-                // reported for missing docs.
-                let real_trait = trait_ref.path.res.def_id();
-                let Some(def_id) = real_trait.as_local() else { return };
-                let Some(Node::Item(item)) = cx.tcx.hir().find_by_def_id(def_id) else { return };
-                if let hir::VisibilityKind::Inherited = item.vis.node {
-                    for impl_item_ref in items {
-                        self.private_traits.insert(impl_item_ref.id.hir_id());
-                    }
-                }
-                return;
-            }
-
             hir::ItemKind::TyAlias(..)
             | hir::ItemKind::Fn(..)
             | hir::ItemKind::Macro(..)
@@ -640,10 +623,6 @@ fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
     }
 
     fn check_trait_item(&mut self, cx: &LateContext<'_>, trait_item: &hir::TraitItem<'_>) {
-        if self.private_traits.contains(&trait_item.hir_id()) {
-            return;
-        }
-
         let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id());
 
         self.check_missing_docs_attrs(cx, trait_item.def_id, trait_item.span, article, desc);
@@ -1383,46 +1362,47 @@ fn perform_lint(
         cx: &LateContext<'_>,
         what: &str,
         def_id: LocalDefId,
-        vis: &hir::Visibility<'_>,
         span: Span,
+        vis_span: Span,
         exportable: bool,
     ) {
         let mut applicability = Applicability::MachineApplicable;
-        match vis.node {
-            hir::VisibilityKind::Public if !cx.access_levels.is_reachable(def_id) => {
-                if span.from_expansion() {
-                    applicability = Applicability::MaybeIncorrect;
+        if cx.tcx.visibility(def_id).is_public() && !cx.access_levels.is_reachable(def_id) {
+            if vis_span.from_expansion() {
+                applicability = Applicability::MaybeIncorrect;
+            }
+            let def_span = cx.tcx.sess.source_map().guess_head_span(span);
+            cx.struct_span_lint(UNREACHABLE_PUB, def_span, |lint| {
+                let mut err = lint.build(&format!("unreachable `pub` {}", what));
+                let replacement = if cx.tcx.features().crate_visibility_modifier {
+                    "crate"
+                } else {
+                    "pub(crate)"
                 }
-                let def_span = cx.tcx.sess.source_map().guess_head_span(span);
-                cx.struct_span_lint(UNREACHABLE_PUB, def_span, |lint| {
-                    let mut err = lint.build(&format!("unreachable `pub` {}", what));
-                    let replacement = if cx.tcx.features().crate_visibility_modifier {
-                        "crate"
-                    } else {
-                        "pub(crate)"
-                    }
-                    .to_owned();
+                .to_owned();
 
-                    err.span_suggestion(
-                        vis.span,
-                        "consider restricting its visibility",
-                        replacement,
-                        applicability,
-                    );
-                    if exportable {
-                        err.help("or consider exporting it for use by other crates");
-                    }
-                    err.emit();
-                });
-            }
-            _ => {}
+                err.span_suggestion(
+                    vis_span,
+                    "consider restricting its visibility",
+                    replacement,
+                    applicability,
+                );
+                if exportable {
+                    err.help("or consider exporting it for use by other crates");
+                }
+                err.emit();
+            });
         }
     }
 }
 
 impl<'tcx> LateLintPass<'tcx> for UnreachablePub {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
-        self.perform_lint(cx, "item", item.def_id, &item.vis, item.span, true);
+        // Do not warn for fake `use` statements.
+        if let hir::ItemKind::Use(_, hir::UseKind::ListStem) = &item.kind {
+            return;
+        }
+        self.perform_lint(cx, "item", item.def_id, item.span, item.vis_span, true);
     }
 
     fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'tcx>) {
@@ -1430,19 +1410,29 @@ fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::Forei
             cx,
             "item",
             foreign_item.def_id,
-            &foreign_item.vis,
             foreign_item.span,
+            foreign_item.vis_span,
             true,
         );
     }
 
     fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
         let def_id = cx.tcx.hir().local_def_id(field.hir_id);
-        self.perform_lint(cx, "field", def_id, &field.vis, field.span, false);
+        self.perform_lint(cx, "field", def_id, field.span, field.vis_span, false);
     }
 
     fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
-        self.perform_lint(cx, "item", impl_item.def_id, &impl_item.vis, impl_item.span, false);
+        // Only lint inherent impl items.
+        if cx.tcx.associated_item(impl_item.def_id).trait_item_def_id.is_none() {
+            self.perform_lint(
+                cx,
+                "item",
+                impl_item.def_id,
+                impl_item.span,
+                impl_item.vis_span,
+                false,
+            );
+        }
     }
 }
 
index 3600b6ad212036da44e05b0625f6e7859695b8b4..0ffa65b79b584a5070e06bc93b2bcd717a6f91cb 100644 (file)
@@ -21,7 +21,8 @@
 use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync;
-use rustc_errors::{struct_span_err, Applicability, MultiSpan, SuggestionStyle};
+use rustc_errors::{add_elided_lifetime_in_path_suggestion, struct_span_err};
+use rustc_errors::{Applicability, MultiSpan, SuggestionStyle};
 use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::{CrateNum, DefId};
@@ -32,8 +33,7 @@
 use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, print::Printer, subst::GenericArg, RegisteredTools, Ty, TyCtxt};
-use rustc_serialize::json::Json;
-use rustc_session::lint::{BuiltinLintDiagnostics, ExternDepSpec};
+use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
 use rustc_session::Session;
 use rustc_span::lev_distance::find_best_match_for_name;
@@ -665,6 +665,21 @@ fn lookup_with_diagnostics(
                 ) => {
                     db.span_note(span_def, "the macro is defined here");
                 }
+                BuiltinLintDiagnostics::ElidedLifetimesInPaths(
+                    n,
+                    path_span,
+                    incl_angl_brckt,
+                    insertion_span,
+                ) => {
+                    add_elided_lifetime_in_path_suggestion(
+                        sess.source_map(),
+                        &mut db,
+                        n,
+                        path_span,
+                        incl_angl_brckt,
+                        insertion_span,
+                    );
+                }
                 BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => {
                     db.span_suggestion(span, &note, sugg, Applicability::MaybeIncorrect);
                 }
@@ -712,30 +727,6 @@ fn lookup_with_diagnostics(
                 BuiltinLintDiagnostics::LegacyDeriveHelpers(span) => {
                     db.span_label(span, "the attribute is introduced here");
                 }
-                BuiltinLintDiagnostics::ExternDepSpec(krate, loc) => {
-                    let json = match loc {
-                        ExternDepSpec::Json(json) => {
-                            db.help(&format!("remove unnecessary dependency `{}`", krate));
-                            json
-                        }
-                        ExternDepSpec::Raw(raw) => {
-                            db.help(&format!("remove unnecessary dependency `{}` at `{}`", krate, raw));
-                            db.span_suggestion_with_style(
-                                DUMMY_SP,
-                                "raw extern location",
-                                raw.clone(),
-                                Applicability::Unspecified,
-                                SuggestionStyle::CompletelyHidden,
-                            );
-                            Json::String(raw)
-                        }
-                    };
-                    db.tool_only_suggestion_with_metadata(
-                        "json extern location",
-                        Applicability::Unspecified,
-                        json
-                    );
-                }
                 BuiltinLintDiagnostics::ProcMacroBackCompat(note) => {
                     db.note(&note);
                 }
index 7447f9f64b7b100f9a8aec19c883ef6d0a2a2145..b4262f184c8c43bc294cdfab261af6dd83872976 100644 (file)
@@ -158,7 +158,7 @@ fn visit_fn(&mut self, fk: ast_visit::FnKind<'a>, span: Span, id: ast::NodeId) {
 
         // Explicitly check for lints associated with 'closure_id', since
         // it does not have a corresponding AST node
-        if let ast_visit::FnKind::Fn(_, _, sig, _, _) = fk {
+        if let ast_visit::FnKind::Fn(_, _, sig, _, _, _) = fk {
             if let ast::Async::Yes { closure_id, .. } = sig.header.asyncness {
                 self.check_id(closure_id);
             }
@@ -284,6 +284,11 @@ fn visit_path(&mut self, p: &'a ast::Path, id: ast::NodeId) {
         ast_visit::walk_path(self, p);
     }
 
+    fn visit_path_segment(&mut self, path_span: Span, s: &'a ast::PathSegment) {
+        self.check_id(s.id);
+        ast_visit::walk_path_segment(self, path_span, s);
+    }
+
     fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
         run_early_pass!(self, check_attribute, attr);
     }
index f73388c675ee2a25dcc178ffe013976a6daa534d..e1507d0fbb48ff0525d7f68f08c44008e84dae33 100644 (file)
@@ -406,7 +406,7 @@ fn check_fn(
                 }
                 _ => (),
             },
-            FnKind::ItemFn(ident, _, header, _) => {
+            FnKind::ItemFn(ident, _, header) => {
                 // Skip foreign-ABI #[no_mangle] functions (Issue #31924)
                 if header.abi != Abi::Rust && cx.sess().contains_name(attrs, sym::no_mangle) {
                     return;
index 89ce307d12cd707f0bc6bc550bf64baf0aea5add..a42e3d5d9578502a216ce6624e676498139ac99c 100644 (file)
     /// ### Example
     ///
     /// ```rust,compile_fail
-    /// #![deny(unaligned_references)]
-    ///
     /// #[repr(packed)]
     /// pub struct Foo {
     ///     field1: u64,
     /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
     /// [issue #82523]: https://github.com/rust-lang/rust/issues/82523
     pub UNALIGNED_REFERENCES,
-    Warn,
+    Deny,
     "detects unaligned references to fields of packed structs",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #82523 <https://github.com/rust-lang/rust/issues/82523>",
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
     };
     report_in_external_macro
 }
index 031b01af5dd95e44056b25920d7d3e3b5960d67f..f590172af4f9ccf8c2b33e456b6be0fd4dec2ea6 100644 (file)
@@ -8,8 +8,8 @@
 use rustc_ast::{AttrId, Attribute};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
 use rustc_error_messages::MultiSpan;
+use rustc_hir::HashStableContext;
 use rustc_hir::HirId;
-use rustc_serialize::json::Json;
 use rustc_span::edition::Edition;
 use rustc_span::{sym, symbol::Ident, Span, Symbol};
 use rustc_target::spec::abi::Abi;
@@ -147,7 +147,7 @@ fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType {
 /// Setting for how to handle a lint.
 ///
 /// See: <https://doc.rust-lang.org/rustc/lints/levels.html>
-#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
+#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash, HashStable_Generic)]
 pub enum Level {
     /// The `allow` level will not issue any message.
     Allow,
@@ -175,8 +175,6 @@ pub enum Level {
     Forbid,
 }
 
-rustc_data_structures::impl_stable_hash_via_hash!(Level);
-
 impl Level {
     /// Converts a level to a lower-case string.
     pub fn as_str(self) -> &'static str {
@@ -403,13 +401,6 @@ fn to_stable_hash_key(&self, _: &HCX) -> &'static str {
     }
 }
 
-// Duplicated from rustc_session::config::ExternDepSpec to avoid cyclic dependency
-#[derive(PartialEq, Debug)]
-pub enum ExternDepSpec {
-    Json(Json),
-    Raw(String),
-}
-
 // This could be a closure, but then implementing derive trait
 // becomes hacky (and it gets allocated).
 #[derive(Debug)]
@@ -418,6 +409,7 @@ pub enum BuiltinLintDiagnostics {
     AbsPathWithModule(Span),
     ProcMacroDeriveResolutionFallback(Span),
     MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
+    ElidedLifetimesInPaths(usize, Span, bool, Span),
     UnknownCrateTypes(Span, String, String),
     UnusedImports(String, Vec<(Span, String)>, Option<Span>),
     RedundantImport(Vec<(Span, bool)>, Ident),
@@ -427,7 +419,6 @@ pub enum BuiltinLintDiagnostics {
     UnusedBuiltinAttribute { attr_name: Symbol, macro_name: String, invoc_span: Span },
     PatternsInFnsWithoutBody(Span, Ident),
     LegacyDeriveHelpers(Span),
-    ExternDepSpec(String, ExternDepSpec),
     ProcMacroBackCompat(String),
     OrPatternsBackCompat(Span, String),
     ReservedPrefix(Span),
index 51739df067f9da03718f914fb92a291132a03fbd..3ed4396d1e955c2bc531f69d323a1a6deb7e0e18 100644 (file)
@@ -1835,3 +1835,9 @@ extern "C" void LLVMRustContextConfigureDiagnosticHandler(
   unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
       DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));
 }
+
+extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) {
+  RawRustStringOstream OS(Str);
+  GlobalValue *GV = unwrap<GlobalValue>(V);
+  Mangler().getNameWithPrefix(OS, GV, true);
+}
index 46f698f6f9b819ef793934c319031b6e2bab8372..ff7506979fc3445c9ed78c834ebad5b35246aa34 100644 (file)
 /// # extern crate rust_middle;
 /// # use rustc_middle::ty::Ty;
 /// #[derive(SessionDiagnostic)]
-/// #[error(code = "E0505", slug = "move-out-of-borrow-error")]
+/// #[error(code = "E0505", slug = "borrowck-move-out-of-borrow")]
 /// pub struct MoveOutOfBorrowError<'tcx> {
 ///     pub name: Ident,
 ///     pub ty: Ty<'tcx>,
 ///     #[primary_span]
-///     #[label = "cannot move out of borrow"]
+///     #[label]
 ///     pub span: Span,
-///     #[label = "`{ty}` first borrowed here"]
-///     pub other_span: Span,
-///     #[suggestion(message = "consider cloning here", code = "{name}.clone()")]
-///     pub opt_sugg: Option<(Span, Applicability)>
+///     #[label = "first-borrow-label"]
+///     pub first_borrow_span: Span,
+///     #[suggestion(code = "{name}.clone()")]
+///     pub clone_sugg: Option<(Span, Applicability)>
 /// }
 /// ```
 ///
+/// ```fluent
+/// move-out-of-borrow = cannot move out of {$name} because it is borrowed
+///     .label = cannot move out of borrow
+///     .first-borrow-label = `{$ty}` first borrowed here
+///     .suggestion = consider cloning here
+/// ```
+///
 /// Then, later, to emit the error:
 ///
 /// ```ignore (pseudo-rust)
 ///     expected,
 ///     actual,
 ///     span,
-///     other_span,
-///     opt_sugg: Some(suggestion, Applicability::MachineApplicable),
+///     first_borrow_span,
+///     clone_sugg: Some(suggestion, Applicability::MachineApplicable),
 /// });
 /// ```
+///
+/// See rustc dev guide for more examples on using the `#[derive(SessionDiagnostic)]`:
+/// <https://rustc-dev-guide.rust-lang.org/diagnostics/sessiondiagnostic.html>
 pub fn session_diagnostic_derive(s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
     // Names for the diagnostic we build and the session we build it from.
     let diag = format_ident!("diag");
index 566d27212d08dcbfee7b44a6f50553222b1b69d5..e8cdae7fd25ceb742492882fac8360b08774931a 100644 (file)
 use rustc_hir::definitions::Definitions;
 use rustc_index::vec::IndexVec;
 use rustc_middle::ty::TyCtxt;
-use rustc_serialize::json::ToJson;
 use rustc_session::config::{self, CrateType, ExternLocation};
 use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate};
 use rustc_session::cstore::{ExternCrateSource, MetadataLoaderDyn};
-use rustc_session::lint::{self, BuiltinLintDiagnostics, ExternDepSpec};
+use rustc_session::lint;
 use rustc_session::output::validate_crate_name;
 use rustc_session::search_paths::PathKind;
 use rustc_session::Session;
@@ -27,7 +26,6 @@
 use rustc_target::spec::{PanicStrategy, TargetTriple};
 
 use proc_macro::bridge::client::ProcMacro;
-use std::collections::BTreeMap;
 use std::ops::Fn;
 use std::path::Path;
 use std::{cmp, env};
@@ -909,6 +907,10 @@ fn report_unused_deps(&mut self, krate: &ast::Crate) {
                 // Don't worry about pathless `--extern foo` sysroot references
                 continue;
             }
+            if entry.nounused_dep {
+                // We're not worried about this one
+                continue;
+            }
             let name_interned = Symbol::intern(name);
             if self.used_extern_options.contains(&name_interned) {
                 continue;
@@ -920,20 +922,7 @@ fn report_unused_deps(&mut self, krate: &ast::Crate) {
                 continue;
             }
 
-            let diag = match self.sess.opts.extern_dep_specs.get(name) {
-                Some(loc) => BuiltinLintDiagnostics::ExternDepSpec(name.clone(), loc.into()),
-                None => {
-                    // If we don't have a specific location, provide a json encoding of the `--extern`
-                    // option.
-                    let meta: BTreeMap<String, String> =
-                        std::iter::once(("name".to_string(), name.to_string())).collect();
-                    BuiltinLintDiagnostics::ExternDepSpec(
-                        name.clone(),
-                        ExternDepSpec::Json(meta.to_json()),
-                    )
-                }
-            };
-            self.sess.parse_sess.buffer_lint_with_diagnostic(
+            self.sess.parse_sess.buffer_lint(
                     lint::builtin::UNUSED_CRATE_DEPENDENCIES,
                     span,
                     ast::CRATE_NODE_ID,
@@ -942,7 +931,6 @@ fn report_unused_deps(&mut self, krate: &ast::Crate) {
                         name,
                         self.local_crate_name,
                         name),
-                    diag,
                 );
         }
     }
index c4ee1e191286d4aae12211f20aadd072578b0ee0..97fcbeb4ccc59962f6517c9da9973a4023b66835 100644 (file)
@@ -1,29 +1,19 @@
 use rustc_hir as hir;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_hir::def::DefKind;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::cstore::ForeignModule;
 
 crate fn collect(tcx: TyCtxt<'_>) -> Vec<ForeignModule> {
-    let mut collector = Collector { modules: Vec::new() };
-    tcx.hir().visit_all_item_likes(&mut collector);
-    collector.modules
-}
-
-struct Collector {
-    modules: Vec<ForeignModule>,
-}
-
-impl<'tcx> ItemLikeVisitor<'tcx> for Collector {
-    fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
-        let hir::ItemKind::ForeignMod { items, .. } = it.kind else {
-            return;
-        };
-
-        let foreign_items = items.iter().map(|it| it.id.def_id.to_def_id()).collect();
-        self.modules.push(ForeignModule { foreign_items, def_id: it.def_id.to_def_id() });
+    let mut modules = Vec::new();
+    for id in tcx.hir().items() {
+        if !matches!(tcx.hir().def_kind(id.def_id), DefKind::ForeignMod) {
+            continue;
+        }
+        let item = tcx.hir().item(id);
+        if let hir::ItemKind::ForeignMod { items, .. } = item.kind {
+            let foreign_items = items.iter().map(|it| it.id.def_id.to_def_id()).collect();
+            modules.push(ForeignModule { foreign_items, def_id: id.def_id.to_def_id() });
+        }
     }
-
-    fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem<'tcx>) {}
-    fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem<'tcx>) {}
-    fn visit_foreign_item(&mut self, _it: &'tcx hir::ForeignItem<'tcx>) {}
+    modules
 }
index aebd293f6c211976ada0edc86622a1fed6239cee..dfed9dd15a72173acddb6304ff87350393dd4974 100644 (file)
@@ -1,6 +1,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(crate_visibility_modifier)]
 #![feature(drain_filter)]
+#![feature(generators)]
 #![feature(let_else)]
 #![feature(nll)]
 #![feature(once_cell)]
index 1cbfb0bd5546b4e7416dd5ce2dee05b00fbfa7b1..43b6ecee794cd73cfca5a74488638e72f085616b 100644 (file)
@@ -3,7 +3,7 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_hir::def::DefKind;
 use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
 use rustc_session::cstore::{DllCallingConvention, DllImport, NativeLib};
 use rustc_session::parse::feature_err;
@@ -15,7 +15,9 @@
 
 crate fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLib> {
     let mut collector = Collector { tcx, libs: Vec::new() };
-    tcx.hir().visit_all_item_likes(&mut collector);
+    for id in tcx.hir().items() {
+        collector.process_item(id);
+    }
     collector.process_command_line();
     collector.libs
 }
@@ -32,8 +34,13 @@ struct Collector<'tcx> {
     libs: Vec<NativeLib>,
 }
 
-impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
-    fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
+impl<'tcx> Collector<'tcx> {
+    fn process_item(&mut self, id: rustc_hir::ItemId) {
+        if !matches!(self.tcx.hir().def_kind(id.def_id), DefKind::ForeignMod) {
+            return;
+        }
+
+        let it = self.tcx.hir().item(id);
         let hir::ItemKind::ForeignMod { abi, items: foreign_mod_items } = it.kind else {
             return;
         };
@@ -252,12 +259,6 @@ fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
         }
     }
 
-    fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem<'tcx>) {}
-    fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem<'tcx>) {}
-    fn visit_foreign_item(&mut self, _it: &'tcx hir::ForeignItem<'tcx>) {}
-}
-
-impl Collector<'_> {
     fn register_native_lib(&mut self, span: Option<Span>, lib: NativeLib) {
         if lib.name.as_ref().map_or(false, |&s| s == kw::Empty) {
             match span {
index 8d0e8467404cae2939cdc0be9dd816f4605e3e72..77afa7b4a5cf0a7f1d94b90c17d47046c37caf97 100644 (file)
@@ -28,6 +28,7 @@
 use rustc_middle::thir;
 use rustc_middle::ty::codec::TyDecoder;
 use rustc_middle::ty::fast_reject::SimplifiedType;
+use rustc_middle::ty::GeneratorDiagnosticData;
 use rustc_middle::ty::{self, Ty, TyCtxt, Visibility};
 use rustc_serialize::{opaque, Decodable, Decoder};
 use rustc_session::cstore::{
@@ -1089,63 +1090,32 @@ fn for_each_module_child(
         // Iterate over all children.
         if let Some(children) = self.root.tables.children.get(self, id) {
             for child_index in children.decode((self, sess)) {
-                if let Some(ident) = self.opt_item_ident(child_index, sess) {
-                    let kind = self.def_kind(child_index);
-                    let def_id = self.local_def_id(child_index);
-                    let res = Res::Def(kind, def_id);
-                    let vis = self.get_visibility(child_index);
-                    let span = self.get_span(child_index, sess);
-                    let macro_rules = match kind {
-                        DefKind::Macro(..) => match self.kind(child_index) {
-                            EntryKind::MacroDef(_, macro_rules) => macro_rules,
-                            _ => unreachable!(),
-                        },
-                        _ => false,
-                    };
-
-                    callback(ModChild { ident, res, vis, span, macro_rules });
-
-                    // For non-re-export structs and variants add their constructors to children.
-                    // Re-export lists automatically contain constructors when necessary.
-                    match kind {
-                        DefKind::Struct => {
-                            if let Some((ctor_def_id, ctor_kind)) =
-                                self.get_ctor_def_id_and_kind(child_index)
-                            {
-                                let ctor_res =
-                                    Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
-                                let vis = self.get_visibility(ctor_def_id.index);
-                                callback(ModChild {
-                                    ident,
-                                    res: ctor_res,
-                                    vis,
-                                    span,
-                                    macro_rules: false,
-                                });
-                            }
-                        }
-                        DefKind::Variant => {
-                            // Braced variants, unlike structs, generate unusable names in
-                            // value namespace, they are reserved for possible future use.
-                            // It's ok to use the variant's id as a ctor id since an
-                            // error will be reported on any use of such resolution anyway.
-                            let (ctor_def_id, ctor_kind) = self
-                                .get_ctor_def_id_and_kind(child_index)
-                                .unwrap_or((def_id, CtorKind::Fictive));
+                let ident = self.item_ident(child_index, sess);
+                let kind = self.def_kind(child_index);
+                let def_id = self.local_def_id(child_index);
+                let res = Res::Def(kind, def_id);
+                let vis = self.get_visibility(child_index);
+                let span = self.get_span(child_index, sess);
+                let macro_rules = match kind {
+                    DefKind::Macro(..) => match self.kind(child_index) {
+                        EntryKind::MacroDef(_, macro_rules) => macro_rules,
+                        _ => unreachable!(),
+                    },
+                    _ => false,
+                };
+
+                callback(ModChild { ident, res, vis, span, macro_rules });
+
+                // For non-re-export structs and variants add their constructors to children.
+                // Re-export lists automatically contain constructors when necessary.
+                match kind {
+                    DefKind::Struct => {
+                        if let Some((ctor_def_id, ctor_kind)) =
+                            self.get_ctor_def_id_and_kind(child_index)
+                        {
                             let ctor_res =
-                                Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id);
-                            let mut vis = self.get_visibility(ctor_def_id.index);
-                            if ctor_def_id == def_id && vis.is_public() {
-                                // For non-exhaustive variants lower the constructor visibility to
-                                // within the crate. We only need this for fictive constructors,
-                                // for other constructors correct visibilities
-                                // were already encoded in metadata.
-                                let mut attrs = self.get_item_attrs(def_id.index, sess);
-                                if attrs.any(|item| item.has_name(sym::non_exhaustive)) {
-                                    let crate_def_id = self.local_def_id(CRATE_DEF_INDEX);
-                                    vis = ty::Visibility::Restricted(crate_def_id);
-                                }
-                            }
+                                Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
+                            let vis = self.get_visibility(ctor_def_id.index);
                             callback(ModChild {
                                 ident,
                                 res: ctor_res,
@@ -1154,8 +1124,32 @@ fn for_each_module_child(
                                 macro_rules: false,
                             });
                         }
-                        _ => {}
                     }
+                    DefKind::Variant => {
+                        // Braced variants, unlike structs, generate unusable names in
+                        // value namespace, they are reserved for possible future use.
+                        // It's ok to use the variant's id as a ctor id since an
+                        // error will be reported on any use of such resolution anyway.
+                        let (ctor_def_id, ctor_kind) = self
+                            .get_ctor_def_id_and_kind(child_index)
+                            .unwrap_or((def_id, CtorKind::Fictive));
+                        let ctor_res =
+                            Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id);
+                        let mut vis = self.get_visibility(ctor_def_id.index);
+                        if ctor_def_id == def_id && vis.is_public() {
+                            // For non-exhaustive variants lower the constructor visibility to
+                            // within the crate. We only need this for fictive constructors,
+                            // for other constructors correct visibilities
+                            // were already encoded in metadata.
+                            let mut attrs = self.get_item_attrs(def_id.index, sess);
+                            if attrs.any(|item| item.has_name(sym::non_exhaustive)) {
+                                let crate_def_id = self.local_def_id(CRATE_DEF_INDEX);
+                                vis = ty::Visibility::Restricted(crate_def_id);
+                            }
+                        }
+                        callback(ModChild { ident, res: ctor_res, vis, span, macro_rules: false });
+                    }
+                    _ => {}
                 }
             }
         }
@@ -1732,6 +1726,28 @@ fn imported_source_files(self, sess: &Session) -> &'a [ImportedSourceFile] {
                 .collect()
         })
     }
+
+    fn get_generator_diagnostic_data(
+        self,
+        tcx: TyCtxt<'tcx>,
+        id: DefIndex,
+    ) -> Option<GeneratorDiagnosticData<'tcx>> {
+        self.root
+            .tables
+            .generator_diagnostic_data
+            .get(self, id)
+            .map(|param| param.decode((self, tcx)))
+            .map(|generator_data| GeneratorDiagnosticData {
+                generator_interior_types: generator_data.generator_interior_types,
+                hir_owner: generator_data.hir_owner,
+                nodes_types: generator_data.nodes_types,
+                adjustments: generator_data.adjustments,
+            })
+    }
+
+    fn get_may_have_doc_links(self, index: DefIndex) -> bool {
+        self.root.tables.may_have_doc_links.get(self, index).is_some()
+    }
 }
 
 impl CrateMetadata {
index 63bf929fb86393a7bc4b102dcd54dca606bb9865..1156a78e8a94afb4adfd64de62744ad15ce0b3b7 100644 (file)
@@ -5,7 +5,7 @@
 
 use rustc_ast as ast;
 use rustc_hir::def::{CtorKind, DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
 use rustc_middle::metadata::ModChild;
 use rustc_middle::middle::exported_symbols::ExportedSymbol;
@@ -246,6 +246,7 @@ fn into_args(self) -> (DefId, SimplifiedType) {
 
     crate_extern_paths => { cdata.source().paths().cloned().collect() }
     expn_that_defined => { cdata.get_expn_that_defined(def_id.index, tcx.sess) }
+    generator_diagnostic_data => { cdata.get_generator_diagnostic_data(tcx, def_id.index) }
 }
 
 pub(in crate::rmeta) fn provide(providers: &mut Providers) {
@@ -324,7 +325,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
                     continue;
                 }
 
-                bfs_queue.push_back(DefId { krate: cnum, index: CRATE_DEF_INDEX });
+                bfs_queue.push_back(cnum.as_def_id());
             }
 
             let mut add_child = |bfs_queue: &mut VecDeque<_>, child: &ModChild, parent: DefId| {
@@ -530,6 +531,18 @@ pub fn incoherent_impls_in_crate_untracked(
     ) -> impl Iterator<Item = DefId> + '_ {
         self.get_crate_data(cnum).get_all_incoherent_impls()
     }
+
+    pub fn associated_item_def_ids_untracked<'a>(
+        &'a self,
+        def_id: DefId,
+        sess: &'a Session,
+    ) -> impl Iterator<Item = DefId> + 'a {
+        self.get_crate_data(def_id.krate).get_associated_item_def_ids(def_id.index, sess)
+    }
+
+    pub fn may_have_doc_links_untracked(&self, def_id: DefId) -> bool {
+        self.get_crate_data(def_id.krate).get_may_have_doc_links(def_id.index)
+    }
 }
 
 impl CrateStore for CStore {
index e967750aebb522c15473b75bd4b035d024b76ab6..f485e09913e9d0d054179c1fab53db12167bd4e0 100644 (file)
@@ -4,6 +4,7 @@
 
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
+use rustc_data_structures::iter_from_generator;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator};
 use rustc_hir as hir;
@@ -976,6 +977,14 @@ fn should_encode_generics(def_kind: DefKind) -> bool {
 }
 
 impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
+    fn encode_attrs(&mut self, def_id: DefId) {
+        let attrs = self.tcx.get_attrs(def_id);
+        record!(self.tables.attributes[def_id] <- attrs);
+        if attrs.iter().any(|attr| attr.may_have_doc_links()) {
+            self.tables.may_have_doc_links.set(def_id.index, ());
+        }
+    }
+
     fn encode_def_ids(&mut self) {
         if self.is_proc_macro {
             return;
@@ -988,7 +997,7 @@ fn encode_def_ids(&mut self) {
             let Some(def_kind) = def_kind else { continue };
             self.tables.opt_def_kind.set(def_id.index, def_kind);
             record!(self.tables.def_span[def_id] <- tcx.def_span(def_id));
-            record!(self.tables.attributes[def_id] <- tcx.get_attrs(def_id));
+            self.encode_attrs(def_id);
             record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id));
             if should_encode_visibility(def_kind) {
                 record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id));
@@ -1107,21 +1116,26 @@ fn encode_info_for_mod(&mut self, local_def_id: LocalDefId, md: &hir::Mod<'_>) {
             // Encode this here because we don't do it in encode_def_ids.
             record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id));
         } else {
-            let direct_children = md.item_ids.iter().map(|item_id| item_id.def_id.local_def_index);
-            // Foreign items are planted into their parent modules from name resolution point of view.
-            let tcx = self.tcx;
-            let foreign_item_children = md
-                .item_ids
-                .iter()
-                .filter_map(|item_id| match tcx.hir().item(*item_id).kind {
-                    hir::ItemKind::ForeignMod { items, .. } => {
-                        Some(items.iter().map(|fi_ref| fi_ref.id.def_id.local_def_index))
+            record!(self.tables.children[def_id] <- iter_from_generator(|| {
+                for item_id in md.item_ids {
+                    match tcx.hir().item(*item_id).kind {
+                        // Foreign items are planted into their parent modules
+                        // from name resolution point of view.
+                        hir::ItemKind::ForeignMod { items, .. } => {
+                            for foreign_item in items {
+                                yield foreign_item.id.def_id.local_def_index;
+                            }
+                        }
+                        // Only encode named non-reexport children, reexports are encoded
+                        // separately and unnamed items are not used by name resolution.
+                        hir::ItemKind::ExternCrate(..) => continue,
+                        _ if tcx.def_key(item_id.def_id.to_def_id()).get_opt_name().is_some() => {
+                            yield item_id.def_id.local_def_index;
+                        }
+                        _ => continue,
                     }
-                    _ => None,
-                })
-                .flatten();
-
-            record!(self.tables.children[def_id] <- direct_children.chain(foreign_item_children));
+                }
+            }));
         }
     }
 
@@ -1550,16 +1564,17 @@ fn encode_info_for_generic_param(&mut self, def_id: DefId, kind: EntryKind, enco
     fn encode_info_for_closure(&mut self, hir_id: hir::HirId) {
         let def_id = self.tcx.hir().local_def_id(hir_id);
         debug!("EncodeContext::encode_info_for_closure({:?})", def_id);
-
         // NOTE(eddyb) `tcx.type_of(def_id)` isn't used because it's fully generic,
         // including on the signature, which is inferred in `typeck.
-        let ty = self.tcx.typeck(def_id).node_type(hir_id);
-
+        let typeck_result: &'tcx ty::TypeckResults<'tcx> = self.tcx.typeck(def_id);
+        let ty = typeck_result.node_type(hir_id);
         match ty.kind() {
             ty::Generator(..) => {
                 let data = self.tcx.generator_kind(def_id).unwrap();
+                let generator_diagnostic_data = typeck_result.get_generator_diagnostic_data();
                 record!(self.tables.kind[def_id.to_def_id()] <- EntryKind::Generator);
                 record!(self.tables.generator_kind[def_id.to_def_id()] <- data);
+                record!(self.tables.generator_diagnostic_data[def_id.to_def_id()]  <- generator_diagnostic_data);
             }
 
             ty::Closure(..) => {
@@ -1633,7 +1648,7 @@ fn encode_proc_macros(&mut self) -> Option<ProcMacroData> {
             let hir = tcx.hir();
 
             let proc_macro_decls_static = tcx.proc_macro_decls_static(()).unwrap().local_def_index;
-            let stability = tcx.lookup_stability(DefId::local(CRATE_DEF_INDEX));
+            let stability = tcx.lookup_stability(CRATE_DEF_ID);
             let macros =
                 self.lazy(tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index));
             let spans = self.tcx.sess.parse_sess.proc_macro_quoted_spans();
@@ -1644,7 +1659,7 @@ fn encode_proc_macros(&mut self) -> Option<ProcMacroData> {
 
             self.tables.opt_def_kind.set(LOCAL_CRATE.as_def_id().index, DefKind::Mod);
             record!(self.tables.def_span[LOCAL_CRATE.as_def_id()] <- tcx.def_span(LOCAL_CRATE.as_def_id()));
-            record!(self.tables.attributes[LOCAL_CRATE.as_def_id()] <- tcx.get_attrs(LOCAL_CRATE.as_def_id()));
+            self.encode_attrs(LOCAL_CRATE.as_def_id());
             record!(self.tables.visibility[LOCAL_CRATE.as_def_id()] <- tcx.visibility(LOCAL_CRATE.as_def_id()));
             if let Some(stability) = stability {
                 record!(self.tables.lookup_stability[LOCAL_CRATE.as_def_id()] <- stability);
@@ -1685,7 +1700,7 @@ fn encode_proc_macros(&mut self) -> Option<ProcMacroData> {
                 let def_id = id.to_def_id();
                 self.tables.opt_def_kind.set(def_id.index, DefKind::Macro(macro_kind));
                 record!(self.tables.kind[def_id] <- EntryKind::ProcMacro(macro_kind));
-                record!(self.tables.attributes[def_id] <- attrs);
+                self.encode_attrs(def_id);
                 record!(self.tables.def_keys[def_id] <- def_key);
                 record!(self.tables.def_ident_span[def_id] <- span);
                 record!(self.tables.def_span[def_id] <- span);
@@ -1781,10 +1796,27 @@ fn encode_impls(&mut self) -> Lazy<[TraitImpls]> {
         debug!("EncodeContext::encode_traits_and_impls()");
         empty_proc_macro!(self);
         let tcx = self.tcx;
-        let mut visitor = ImplsVisitor { tcx, impls: FxHashMap::default() };
-        tcx.hir().visit_all_item_likes(&mut visitor);
+        let mut fx_hash_map: FxHashMap<DefId, Vec<(DefIndex, Option<SimplifiedType>)>> =
+            FxHashMap::default();
+
+        for id in tcx.hir().items() {
+            if matches!(tcx.hir().def_kind(id.def_id), DefKind::Impl) {
+                if let Some(trait_ref) = tcx.impl_trait_ref(id.def_id.to_def_id()) {
+                    let simplified_self_ty = fast_reject::simplify_type(
+                        self.tcx,
+                        trait_ref.self_ty(),
+                        TreatParams::AsPlaceholders,
+                    );
 
-        let mut all_impls: Vec<_> = visitor.impls.into_iter().collect();
+                    fx_hash_map
+                        .entry(trait_ref.def_id)
+                        .or_default()
+                        .push((id.def_id.local_def_index, simplified_self_ty));
+                }
+            }
+        }
+
+        let mut all_impls: Vec<_> = fx_hash_map.into_iter().collect();
 
         // Bring everything into deterministic order for hashing
         all_impls.sort_by_cached_key(|&(trait_def_id, _)| tcx.def_path_hash(trait_def_id));
@@ -2047,41 +2079,6 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item<'_>) {
     }
 }
 
-struct ImplsVisitor<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    impls: FxHashMap<DefId, Vec<(DefIndex, Option<SimplifiedType>)>>,
-}
-
-impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplsVisitor<'tcx> {
-    fn visit_item(&mut self, item: &hir::Item<'_>) {
-        match item.kind {
-            hir::ItemKind::Impl(..) => {
-                if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id.to_def_id()) {
-                    let simplified_self_ty = fast_reject::simplify_type(
-                        self.tcx,
-                        trait_ref.self_ty(),
-                        TreatParams::AsPlaceholders,
-                    );
-
-                    self.impls
-                        .entry(trait_ref.def_id)
-                        .or_default()
-                        .push((item.def_id.local_def_index, simplified_self_ty));
-                }
-            }
-            _ => {}
-        }
-    }
-
-    fn visit_trait_item(&mut self, _trait_item: &'v hir::TraitItem<'v>) {}
-
-    fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem<'v>) {
-        // handled in `visit_item` above
-    }
-
-    fn visit_foreign_item(&mut self, _foreign_item: &'v hir::ForeignItem<'v>) {}
-}
-
 /// Used to prefetch queries which will be needed later by metadata encoding.
 /// Only a subset of the queries are actually prefetched to keep this code smaller.
 fn prefetch_mir(tcx: TyCtxt<'_>) {
index 43ccfc64e0563978adf8f7c7b6dfd7a083ff3c2a..f1498665ff3853bcf92b7dde96f58a46dce7905a 100644 (file)
@@ -19,6 +19,7 @@
 use rustc_middle::thir;
 use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::GeneratorDiagnosticData;
 use rustc_middle::ty::{self, ReprOptions, Ty};
 use rustc_serialize::opaque::Encoder;
 use rustc_session::config::SymbolManglingVersion;
@@ -358,6 +359,8 @@ fn encode(&self, buf: &mut Encoder) -> LazyTables<'tcx> {
     def_keys: Table<DefIndex, Lazy<DefKey>>,
     def_path_hashes: Table<DefIndex, DefPathHash>,
     proc_macro_quoted_spans: Table<usize, Lazy<Span>>,
+    generator_diagnostic_data: Table<DefIndex, Lazy<GeneratorDiagnosticData<'tcx>>>,
+    may_have_doc_links: Table<DefIndex, ()>,
 }
 
 #[derive(Copy, Clone, MetadataEncodable, MetadataDecodable)]
index 7a23cba536a0a18bfdfbc69b4fb3cda5333aacad..53fc2efe00bb79c230515dd319c9246ddca47c99 100644 (file)
@@ -186,6 +186,20 @@ impl FixedSizeEncoding for Option<RawDefId> {
     }
 }
 
+impl FixedSizeEncoding for Option<()> {
+    type ByteArray = [u8; 1];
+
+    #[inline]
+    fn from_bytes(b: &[u8; 1]) -> Self {
+        (b[0] != 0).then(|| ())
+    }
+
+    #[inline]
+    fn write_to_bytes(self, b: &mut [u8; 1]) {
+        b[0] = self.is_some() as u8
+    }
+}
+
 // NOTE(eddyb) there could be an impl for `usize`, which would enable a more
 // generic `Lazy<T>` impl, but in the general case we might not need / want to
 // fit every `usize` in `u32`.
index d20be0a34d2d5f525f456c9c604d3426678e8d2f..8402ca3028cce500665ac2091c230f8cdf91183d 100644 (file)
@@ -60,7 +60,7 @@
 use crate::ty::TyCtxt;
 
 use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
 use rustc_hir::definitions::DefPathHash;
 use rustc_hir::HirId;
 use rustc_query_system::dep_graph::FingerprintStyle;
@@ -366,7 +366,7 @@ fn fingerprint_style() -> FingerprintStyle {
 
     #[inline(always)]
     fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
-        let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX };
+        let def_id = self.as_def_id();
         def_id.to_fingerprint(tcx)
     }
 
index 08cd40f38efcede73570b5bede8fef5fc9de1949..e0ed402283904a1bf99a1a9f0dbf7df8cf73bb6d 100644 (file)
 use rustc_index::vec::Idx;
 use rustc_middle::hir::nested_filter;
 use rustc_span::def_id::StableCrateId;
-use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
-use std::collections::VecDeque;
 
 fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> {
     match node {
@@ -159,12 +157,12 @@ pub fn root_module(self) -> &'hir Mod<'hir> {
         }
     }
 
-    pub fn items(self) -> impl Iterator<Item = &'hir Item<'hir>> + 'hir {
-        let krate = self.krate();
-        krate.owners.iter().filter_map(|owner| match owner.as_owner()?.node() {
-            OwnerNode::Item(item) => Some(item),
-            _ => None,
-        })
+    pub fn items(self) -> impl Iterator<Item = ItemId> + 'hir {
+        self.tcx.hir_crate_items(()).items.iter().copied()
+    }
+
+    pub fn par_for_each_item(self, f: impl Fn(ItemId) + Sync + Send) {
+        par_for_each_in(&self.tcx.hir_crate_items(()).items[..], |id| f(*id));
     }
 
     pub fn def_key(self, def_id: LocalDefId) -> DefKey {
@@ -305,7 +303,6 @@ pub fn opt_def_kind(self, local_def_id: LocalDefId) -> Option<DefKind> {
             | Node::Param(_)
             | Node::Arm(_)
             | Node::Lifetime(_)
-            | Node::Visibility(_)
             | Node::Block(_) => return None,
         };
         Some(def_kind)
@@ -675,13 +672,9 @@ pub fn visit_item_likes_in_module<V>(self, module: LocalDefId, visitor: &mut V)
     }
 
     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())
+        let crate_items = self.tcx.hir_crate_items(());
+        for module in crate_items.submodules.iter() {
+            f(*module)
         }
     }
 
@@ -1005,12 +998,7 @@ pub fn opt_span(self, hir_id: HirId) -> Option<Span> {
             },
             Node::Lifetime(lifetime) => lifetime.span,
             Node::GenericParam(param) => param.span,
-            Node::Visibility(&Spanned {
-                node: VisibilityKind::Restricted { ref path, .. },
-                ..
-            }) => path.span,
             Node::Infer(i) => i.span,
-            Node::Visibility(v) => bug!("unexpected Visibility {:?}", v),
             Node::Local(local) => local.span,
             Node::Crate(item) => item.spans.inner_span,
         };
@@ -1133,6 +1121,10 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
     }
     tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher);
     tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher);
+    // Hash visibility information since it does not appear in HIR.
+    let resolutions = tcx.resolutions(());
+    resolutions.visibilities.hash_stable(&mut hcx, &mut stable_hasher);
+    resolutions.has_pub_restricted.hash_stable(&mut hcx, &mut stable_hasher);
 
     let crate_hash: Fingerprint = stable_hasher.finish();
     Svh::new(crate_hash.to_smaller_hash())
@@ -1237,7 +1229,6 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
         Some(Node::Ctor(..)) => format!("ctor {}{}", path_str(), id_str),
         Some(Node::Lifetime(_)) => node_str("lifetime"),
         Some(Node::GenericParam(ref param)) => format!("generic_param {:?}{}", param, id_str),
-        Some(Node::Visibility(ref vis)) => format!("visibility {:?}{}", vis, id_str),
         Some(Node::Crate(..)) => String::from("root_crate"),
         None => format!("unknown node{}", id_str),
     }
@@ -1308,3 +1299,69 @@ fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) {
         }
     }
 }
+
+pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems {
+    let mut collector = CrateCollector {
+        tcx,
+        submodules: Vec::default(),
+        items: Vec::default(),
+        trait_items: Vec::default(),
+        impl_items: Vec::default(),
+        foreign_items: Vec::default(),
+    };
+
+    tcx.hir().walk_toplevel_module(&mut collector);
+
+    let CrateCollector { 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 CrateCollector<'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 CrateCollector<'hir> {
+        type NestedFilter = nested_filter::All;
+
+        fn nested_visit_map(&mut self) -> Self::Map {
+            self.tcx.hir()
+        }
+
+        fn visit_item(&mut self, item: &'hir Item<'hir>) {
+            self.items.push(item.item_id());
+            intravisit::walk_item(self, item)
+        }
+
+        fn visit_mod(&mut self, m: &'hir Mod<'hir>, _s: Span, n: HirId) {
+            self.submodules.push(n.owner);
+            intravisit::walk_mod(self, m, n);
+        }
+
+        fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) {
+            self.foreign_items.push(item.foreign_item_id());
+            intravisit::walk_foreign_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)
+        }
+    }
+}
index a9e22d16ee0506de64f6f8c1dde4883e00403458..f18067145dd4a377a2aefd64f88d51b83fdcbded 100644 (file)
@@ -45,6 +45,24 @@ pub struct ModuleItems {
     foreign_items: Box<[ForeignItemId]>,
 }
 
+impl ModuleItems {
+    pub fn items(&self) -> impl Iterator<Item = ItemId> + '_ {
+        self.items.iter().copied()
+    }
+
+    pub fn trait_items(&self) -> impl Iterator<Item = TraitItemId> + '_ {
+        self.trait_items.iter().copied()
+    }
+
+    pub fn impl_items(&self) -> impl Iterator<Item = ImplItemId> + '_ {
+        self.impl_items.iter().copied()
+    }
+
+    pub fn foreign_items(&self) -> impl Iterator<Item = ForeignItemId> + '_ {
+        self.foreign_items.iter().copied()
+    }
+}
+
 impl<'tcx> TyCtxt<'tcx> {
     #[inline(always)]
     pub fn hir(self) -> map::Map<'tcx> {
@@ -68,6 +86,7 @@ pub fn provide(providers: &mut Providers) {
         hir.get_module_parent_node(hir.local_def_id_to_hir_id(id))
     };
     providers.hir_crate = |tcx, ()| tcx.untracked_crate;
+    providers.hir_crate_items = map::hir_crate_items;
     providers.crate_hash = map::crate_hash;
     providers.hir_module_items = map::hir_module_items;
     providers.hir_owner = |tcx, id| {
index fd6e241346db8e9aeddada8789c59fac6736f03d..758658c3d8c941c8f07081001c9493590f28b955 100644 (file)
@@ -11,7 +11,7 @@
 use rustc_feature::GateIssue;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::{self, HirId};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE};
@@ -370,8 +370,7 @@ pub fn eval_stability(
             };
         }
 
-        let is_staged_api =
-            self.lookup_stability(DefId { index: CRATE_DEF_INDEX, ..def_id }).is_some();
+        let is_staged_api = self.lookup_stability(def_id.krate.as_def_id()).is_some();
         if !is_staged_api {
             return EvalResult::Allow;
         }
index 438f356f072c6d863e093668d022327785efb3d9..c628406064fb63e4703bf503d75519a680c07534 100644 (file)
@@ -269,7 +269,7 @@ impl<Tag: Provenance, Extra> Allocation<Tag, Extra> {
     /// `get_bytes_with_uninit_and_ptr` instead,
     ///
     /// This function also guarantees that the resulting pointer will remain stable
-    /// even when new allocations are pushed to the `HashMap`. `copy_repeatedly` relies
+    /// even when new allocations are pushed to the `HashMap`. `mem_copy_repeatedly` relies
     /// on that.
     ///
     /// It is the caller's responsibility to check bounds and alignment beforehand.
@@ -429,8 +429,7 @@ pub fn write_scalar(
         let val = match val {
             ScalarMaybeUninit::Scalar(scalar) => scalar,
             ScalarMaybeUninit::Uninit => {
-                self.mark_init(range, false);
-                return Ok(());
+                return self.write_uninit(cx, range);
             }
         };
 
@@ -455,6 +454,13 @@ pub fn write_scalar(
 
         Ok(())
     }
+
+    /// Write "uninit" to the given memory range.
+    pub fn write_uninit(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult {
+        self.mark_init(range, false);
+        self.clear_relocations(cx, range)?;
+        return Ok(());
+    }
 }
 
 /// Relocations.
@@ -509,6 +515,9 @@ fn clear_relocations(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> A
             if Tag::ERR_ON_PARTIAL_PTR_OVERWRITE {
                 return Err(AllocError::PartialPointerOverwrite(first));
             }
+            warn!(
+                "Partial pointer overwrite! De-initializing memory at offsets {first:?}..{start:?}."
+            );
             self.init_mask.set_range(first, start, false);
         }
         if last > end {
@@ -517,10 +526,15 @@ fn clear_relocations(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> A
                     last - cx.data_layout().pointer_size,
                 ));
             }
+            warn!(
+                "Partial pointer overwrite! De-initializing memory at offsets {end:?}..{last:?}."
+            );
             self.init_mask.set_range(end, last, false);
         }
 
         // Forget all the relocations.
+        // Since relocations do not overlap, we know that removing until `last` (exclusive) is fine,
+        // i.e., this will not remove any other relocations just after the ones we care about.
         self.relocations.0.remove_range(first..last);
 
         Ok(())
@@ -561,8 +575,10 @@ fn deref(&self) -> &Self::Target {
 }
 
 /// A partial, owned list of relocations to transfer into another allocation.
+///
+/// Offsets are already adjusted to the destination allocation.
 pub struct AllocationRelocations<Tag> {
-    relative_relocations: Vec<(Size, Tag)>,
+    dest_relocations: Vec<(Size, Tag)>,
 }
 
 impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
@@ -575,12 +591,17 @@ pub fn prepare_relocation_copy(
     ) -> AllocationRelocations<Tag> {
         let relocations = self.get_relocations(cx, src);
         if relocations.is_empty() {
-            return AllocationRelocations { relative_relocations: Vec::new() };
+            return AllocationRelocations { dest_relocations: Vec::new() };
         }
 
         let size = src.size;
         let mut new_relocations = Vec::with_capacity(relocations.len() * (count as usize));
 
+        // If `count` is large, this is rather wasteful -- we are allocating a big array here, which
+        // is mostly filled with redundant information since it's just N copies of the same `Tag`s
+        // at slightly adjusted offsets. The reason we do this is so that in `mark_relocation_range`
+        // we can use `insert_presorted`. That wouldn't work with an `Iterator` that just produces
+        // the right sequence of relocations for all N copies.
         for i in 0..count {
             new_relocations.extend(relocations.iter().map(|&(offset, reloc)| {
                 // compute offset for current repetition
@@ -593,14 +614,17 @@ pub fn prepare_relocation_copy(
             }));
         }
 
-        AllocationRelocations { relative_relocations: new_relocations }
+        AllocationRelocations { dest_relocations: new_relocations }
     }
 
     /// Applies a relocation copy.
     /// The affected range, as defined in the parameters to `prepare_relocation_copy` is expected
     /// to be clear of relocations.
+    ///
+    /// This is dangerous to use as it can violate internal `Allocation` invariants!
+    /// It only exists to support an efficient implementation of `mem_copy_repeatedly`.
     pub fn mark_relocation_range(&mut self, relocations: AllocationRelocations<Tag>) {
-        self.relocations.0.insert_presorted(relocations.relative_relocations);
+        self.relocations.0.insert_presorted(relocations.dest_relocations);
     }
 }
 
@@ -1056,7 +1080,7 @@ fn check_init(&self, range: AllocRange) -> AllocResult {
         })
     }
 
-    pub fn mark_init(&mut self, range: AllocRange, is_init: bool) {
+    fn mark_init(&mut self, range: AllocRange, is_init: bool) {
         if range.size.bytes() == 0 {
             return;
         }
@@ -1118,6 +1142,9 @@ pub fn compress_uninit_range(&self, range: AllocRange) -> InitMaskCompressed {
     }
 
     /// Applies multiple instances of the run-length encoding to the initialization mask.
+    ///
+    /// This is dangerous to use as it can violate internal `Allocation` invariants!
+    /// It only exists to support an efficient implementation of `mem_copy_repeatedly`.
     pub fn mark_compressed_init_range(
         &mut self,
         defined: &InitMaskCompressed,
index 813c0912f539679db80f57d1ec455580c0ccb1de..c71aea417eca0143279c565a813ed0da9203dabc 100644 (file)
@@ -163,6 +163,9 @@ pub struct Pointer<Tag = AllocId> {
 }
 
 static_assert_size!(Pointer, 16);
+// `Option<Tag>` pointers are also passed around quite a bit
+// (but not stored in permanent machine state).
+static_assert_size!(Pointer<Option<AllocId>>, 16);
 
 // We want the `Debug` output to be readable as it is used by `derive(Debug)` for
 // all the Miri types.
@@ -198,12 +201,26 @@ fn from(ptr: Pointer<Tag>) -> Self {
 }
 
 impl<Tag> Pointer<Option<Tag>> {
+    /// Convert this pointer that *might* have a tag into a pointer that *definitely* has a tag, or
+    /// an absolute address.
+    ///
+    /// This is rarely what you want; call `ptr_try_get_alloc_id` instead.
     pub fn into_pointer_or_addr(self) -> Result<Pointer<Tag>, Size> {
         match self.provenance {
             Some(tag) => Ok(Pointer::new(tag, self.offset)),
             None => Err(self.offset),
         }
     }
+
+    /// Returns the absolute address the pointer points to.
+    /// Only works if Tag::OFFSET_IS_ADDR is true!
+    pub fn addr(self) -> Size
+    where
+        Tag: Provenance,
+    {
+        assert!(Tag::OFFSET_IS_ADDR);
+        self.offset
+    }
 }
 
 impl<Tag> Pointer<Option<Tag>> {
index db7e973fb62234f45dff13466d6e616fbc3b4b10..881f59ae464c93ababca1442fe0a67e7f2909d7b 100644 (file)
@@ -15,7 +15,7 @@
 
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def::{CtorKind, Namespace};
-use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
 use rustc_hir::{self, GeneratorKind};
 use rustc_hir::{self as hir, HirId};
 use rustc_session::Session;
@@ -166,7 +166,8 @@ pub enum MirPhase {
     /// * [`StatementKind::Retag`]
     ///
     /// Furthermore, `Drop` now uses explicit drop flags visible in the MIR and reaching a `Drop`
-    /// terminator means that the auto-generated drop glue will be invoked.
+    /// terminator means that the auto-generated drop glue will be invoked. Also, `Copy` operands
+    /// are allowed for non-`Copy` types.
     DropsLowered = 3,
     /// Beginning with this phase, the following variant is disallowed:
     /// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array`
@@ -385,7 +386,7 @@ pub fn new(
     pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
         let mut body = Body {
             phase: MirPhase::Built,
-            source: MirSource::item(DefId::local(CRATE_DEF_INDEX)),
+            source: MirSource::item(CRATE_DEF_ID.to_def_id()),
             basic_blocks,
             source_scopes: IndexVec::new(),
             generator: None,
@@ -2330,7 +2331,10 @@ pub struct SourceScopeLocalData {
 /// validator.
 #[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
 pub enum Operand<'tcx> {
-    /// Creates a value by loading the given place. The type of the place must be `Copy`
+    /// Creates a value by loading the given place.
+    ///
+    /// Before drop elaboration, the type of the place must be `Copy`. After drop elaboration there
+    /// is no such requirement.
     Copy(Place<'tcx>),
 
     /// Creates a value by performing loading the place, just like the `Copy` operand.
@@ -2518,7 +2522,8 @@ pub enum Rvalue<'tcx> {
     /// * `Offset` has the same semantics as [`offset`](pointer::offset), except that the second
     ///   parameter may be a `usize` as well.
     /// * The comparison operations accept `bool`s, `char`s, signed or unsigned integers, floats,
-    ///   raw pointers, or function pointers of matching types and return a `bool`.
+    ///   raw pointers, or function pointers and return a `bool`. The types of the operands must be
+    ///   matching, up to the usual caveat of the lifetimes in function pointers.
     /// * Left and right shift operations accept signed or unsigned integers not necessarily of the
     ///   same type and return a value of the same type as their LHS. Like in Rust, the RHS is
     ///   truncated as needed.
index 69dac03883940de4d24ea32afa0a04f5bc3b9255..b7f695da544f1db26a260a1c26d2e3a63cf42b64 100644 (file)
@@ -851,6 +851,7 @@ fn write_allocation_bytes<'tcx, Tag: Provenance, Extra>(
         }
         if let Some(&tag) = alloc.relocations().get(&i) {
             // Memory with a relocation must be defined
+            assert!(alloc.init_mask().is_range_initialized(i, i + ptr_size).is_ok());
             let j = i.bytes_usize();
             let offset = alloc
                 .inspect_with_uninit_and_ptr_outside_interpreter(j..j + ptr_size.bytes_usize());
index f38ade1076eac3481682cd48e189df9577d68eed..78a3383243306b42187e2cf48fab7dea0867e254 100644 (file)
         desc { "get the crate HIR" }
     }
 
+    /// All items in the crate.
+    query hir_crate_items(_: ()) -> rustc_middle::hir::ModuleItems {
+        storage(ArenaCacheSelector<'tcx>)
+        eval_always
+        desc { "get HIR crate items" }
+    }
+
     /// The items in a module.
     ///
     /// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`.
         eval_always
         desc { "computing the backend features for CLI flags" }
     }
+
+    query generator_diagnostic_data(key: DefId) -> Option<GeneratorDiagnosticData<'tcx>> {
+        storage(ArenaCacheSelector<'tcx>)
+        desc { |tcx| "looking up generator diagnostic data of `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
+    }
 }
index b17343d7692f6644e7e3ad776157fc1e9576c8e9..fdf5ecfdaf7ef25f599a228886b759f19d11f918 100644 (file)
@@ -66,7 +66,7 @@ macro_rules! thir_with_elements {
         /// A container for a THIR body.
         ///
         /// This can be indexed directly by any THIR index (e.g. [`ExprId`]).
-        #[derive(Debug, HashStable)]
+        #[derive(Debug, HashStable, Clone)]
         pub struct Thir<'tcx> {
             $(
                 pub $name: IndexVec<$id, $value>,
@@ -106,7 +106,7 @@ pub enum LintLevel {
     Explicit(hir::HirId),
 }
 
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
 pub struct Block {
     /// Whether the block itself has a label. Used by `label: {}`
     /// and `try` blocks.
@@ -125,7 +125,7 @@ pub struct Block {
     pub safety_mode: BlockSafety,
 }
 
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
 pub struct Adt<'tcx> {
     /// The ADT we're constructing.
     pub adt_def: AdtDef<'tcx>,
@@ -151,13 +151,13 @@ pub enum BlockSafety {
     ExplicitUnsafe(hir::HirId),
 }
 
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
 pub struct Stmt<'tcx> {
     pub kind: StmtKind<'tcx>,
     pub opt_destruction_scope: Option<region::Scope>,
 }
 
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
 pub enum StmtKind<'tcx> {
     /// An expression with a trailing semicolon.
     Expr {
@@ -196,7 +196,7 @@ pub enum StmtKind<'tcx> {
 rustc_data_structures::static_assert_size!(Expr<'_>, 104);
 
 /// A THIR expression.
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
 pub struct Expr<'tcx> {
     /// The type of this expression
     pub ty: Ty<'tcx>,
@@ -212,7 +212,7 @@ pub struct Expr<'tcx> {
     pub kind: ExprKind<'tcx>,
 }
 
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
 pub enum ExprKind<'tcx> {
     /// `Scope`s are used to explicitly mark destruction scopes,
     /// and to track the `HirId` of the expressions within the scope.
@@ -461,20 +461,20 @@ pub fn zero_sized_literal(user_ty: Option<Canonical<'tcx, UserType<'tcx>>>) -> S
 /// Represents the association of a field identifier and an expression.
 ///
 /// This is used in struct constructors.
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
 pub struct FieldExpr {
     pub name: Field,
     pub expr: ExprId,
 }
 
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
 pub struct FruInfo<'tcx> {
     pub base: ExprId,
     pub field_types: Box<[Ty<'tcx>]>,
 }
 
 /// A `match` arm.
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
 pub struct Arm<'tcx> {
     pub pattern: Pat<'tcx>,
     pub guard: Option<Guard<'tcx>>,
@@ -485,7 +485,7 @@ pub struct Arm<'tcx> {
 }
 
 /// A `match` guard.
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
 pub enum Guard<'tcx> {
     If(ExprId),
     IfLet(Pat<'tcx>, ExprId),
@@ -499,7 +499,7 @@ pub enum LogicalOp {
     Or,
 }
 
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
 pub enum InlineAsmOperand<'tcx> {
     In {
         reg: InlineAsmRegOrRegClass,
@@ -526,7 +526,8 @@ pub enum InlineAsmOperand<'tcx> {
         span: Span,
     },
     SymFn {
-        expr: ExprId,
+        value: mir::ConstantKind<'tcx>,
+        span: Span,
     },
     SymStatic {
         def_id: DefId,
index ef7becde69a6673c4dbc6acbdf7be5143ccbe647..f57569522d58d3c65e1e0bd9522c0cff0d4d67fa 100644 (file)
@@ -138,8 +138,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
                 match op {
                     In { expr, reg: _ }
                     | Out { expr: Some(expr), reg: _, late: _ }
-                    | InOut { expr, reg: _, late: _ }
-                    | SymFn { expr } => visitor.visit_expr(&visitor.thir()[*expr]),
+                    | InOut { expr, reg: _, late: _ } => 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 {
@@ -148,6 +147,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
                     }
                     Out { expr: None, reg: _, late: _ }
                     | Const { value: _, span: _ }
+                    | SymFn { value: _, span: _ }
                     | SymStatic { def_id: _ } => {}
                 }
             }
index 4b7c1d44cea29f6c6a531fd8519720e9e9eb836d..7af7eb4f5ecfd868ebf1408ac90aed3027c08b93 100644 (file)
@@ -44,10 +44,12 @@ pub struct ConstS<'tcx> {
 static_assert_size!(ConstS<'_>, 48);
 
 impl<'tcx> Const<'tcx> {
+    #[inline]
     pub fn ty(self) -> Ty<'tcx> {
         self.0.ty
     }
 
+    #[inline]
     pub fn val(self) -> ConstKind<'tcx> {
         self.0.val
     }
index fae22c28628f86f35ba023fce19625a4caeb5b88..195760c059081bf607e54c26a33dfec44e4dbb77 100644 (file)
@@ -1,5 +1,5 @@
 use super::ScalarInt;
-use rustc_macros::HashStable;
+use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 
 #[derive(Copy, Clone, Debug, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)]
 #[derive(HashStable)]
index 4e6be84ad7f8ff6f990a155de5be959c7d6d0772..30fe3ffa7e3c46c0b438269ebf430942b85397c8 100644 (file)
@@ -367,6 +367,16 @@ pub struct GeneratorInteriorTypeCause<'tcx> {
     pub expr: Option<hir::HirId>,
 }
 
+// This type holds diagnostic information on generators and async functions across crate boundaries
+// and is used to provide better error messages
+#[derive(TyEncodable, TyDecodable, Clone, Debug, HashStable)]
+pub struct GeneratorDiagnosticData<'tcx> {
+    pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
+    pub hir_owner: DefId,
+    pub nodes_types: ItemLocalMap<Ty<'tcx>>,
+    pub adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
+}
+
 #[derive(TyEncodable, TyDecodable, Debug, HashStable)]
 pub struct TypeckResults<'tcx> {
     /// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
@@ -623,6 +633,28 @@ pub fn node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>> {
         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types }
     }
 
+    pub fn get_generator_diagnostic_data(&self) -> GeneratorDiagnosticData<'tcx> {
+        let generator_interior_type = self.generator_interior_types.map_bound_ref(|vec| {
+            vec.iter()
+                .map(|item| {
+                    GeneratorInteriorTypeCause {
+                        ty: item.ty,
+                        span: item.span,
+                        scope_span: item.scope_span,
+                        yield_span: item.yield_span,
+                        expr: None, //FIXME: Passing expression over crate boundaries is impossible at the moment
+                    }
+                })
+                .collect::<Vec<_>>()
+        });
+        GeneratorDiagnosticData {
+            generator_interior_types: generator_interior_type,
+            hir_owner: self.hir_owner.to_def_id(),
+            nodes_types: self.node_types.clone(),
+            adjustments: self.adjustments.clone(),
+        }
+    }
+
     pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
         self.node_type_opt(id).unwrap_or_else(|| {
             bug!("node_type: no type for node `{}`", tls::with(|tcx| tcx.hir().node_to_string(id)))
index f6d139fe59d3cf5b7f98173a75829d124539cae1..7cf2984a63f90609b10f30ed2d85d393792a656c 100644 (file)
@@ -1120,21 +1120,12 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<'
                                 match st[i].abi() {
                                     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.
+                                        // Only the niche is guaranteed to be initialised,
+                                        // so use union layout for the other primitive.
                                         if offset.bytes() == 0 {
-                                            Abi::ScalarPair(
-                                                niche_scalar,
-                                                scalar_unit(second.primitive()),
-                                            )
+                                            Abi::ScalarPair(niche_scalar, second.to_union())
                                         } else {
-                                            Abi::ScalarPair(
-                                                scalar_unit(first.primitive()),
-                                                niche_scalar,
-                                            )
+                                            Abi::ScalarPair(first.to_union(), niche_scalar)
                                         }
                                     }
                                     _ => Abi::Aggregate { sized: true },
@@ -1329,6 +1320,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<'
                 } else {
                     // Try to use a ScalarPair for all tagged enums.
                     let mut common_prim = None;
+                    let mut common_prim_initialized_in_all_variants = true;
                     for (field_layouts, layout_variant) in iter::zip(&variants, &layout_variants) {
                         let FieldsShape::Arbitrary { ref offsets, .. } = layout_variant.fields else {
                             bug!();
@@ -1336,7 +1328,10 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<'
                         let mut fields =
                             iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst());
                         let (field, offset) = match (fields.next(), fields.next()) {
-                            (None, None) => continue,
+                            (None, None) => {
+                                common_prim_initialized_in_all_variants = false;
+                                continue;
+                            }
                             (Some(pair), None) => pair,
                             _ => {
                                 common_prim = None;
@@ -1344,7 +1339,11 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<'
                             }
                         };
                         let prim = match field.abi {
-                            Abi::Scalar(scalar) => scalar.primitive(),
+                            Abi::Scalar(scalar) => {
+                                common_prim_initialized_in_all_variants &=
+                                    matches!(scalar, Scalar::Initialized { .. });
+                                scalar.primitive()
+                            }
                             _ => {
                                 common_prim = None;
                                 break;
@@ -1364,7 +1363,13 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<'
                         }
                     }
                     if let Some((prim, offset)) = common_prim {
-                        let pair = self.scalar_pair(tag, scalar_unit(prim));
+                        let prim_scalar = if common_prim_initialized_in_all_variants {
+                            scalar_unit(prim)
+                        } else {
+                            // Common prim might be uninit.
+                            Scalar::Union { value: prim }
+                        };
+                        let pair = self.scalar_pair(tag, prim_scalar);
                         let pair_offsets = match pair.fields {
                             FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
                                 assert_eq!(memory_index, &[0, 1]);
index c2accea11ba2aee2bb6604ba30d8b7e7e2f768ee..ec416722c214e6018bc9f566c7e2aa065292b4c4 100644 (file)
@@ -36,7 +36,7 @@
 use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap};
 use rustc_hir::Node;
 use rustc_macros::HashStable;
 use rustc_query_system::ich::StableHashingContext;
@@ -67,8 +67,9 @@
 };
 pub use self::context::{
     tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
-    CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorInteriorTypeCause, GlobalCtxt,
-    Lift, OnDiskCache, TyCtxt, TypeckResults, UserType, UserTypeAnnotationIndex,
+    CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorDiagnosticData,
+    GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TypeckResults, UserType,
+    UserTypeAnnotationIndex,
 };
 pub use self::instance::{Instance, InstanceDef};
 pub use self::list::List;
@@ -130,6 +131,8 @@ pub struct ResolverOutputs {
     pub definitions: rustc_hir::definitions::Definitions,
     pub cstore: Box<CrateStoreDyn>,
     pub visibilities: FxHashMap<LocalDefId, Visibility>,
+    /// This field is used to decide whether we should make `PRIVATE_IN_PUBLIC` a hard error.
+    pub has_pub_restricted: bool,
     pub access_levels: AccessLevels,
     pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
     pub maybe_unused_trait_imports: FxHashSet<LocalDefId>,
@@ -316,22 +319,6 @@ fn parent(self, id: DefId) -> Option<DefId> {
 }
 
 impl Visibility {
-    pub fn from_hir(visibility: &hir::Visibility<'_>, id: hir::HirId, tcx: TyCtxt<'_>) -> Self {
-        match visibility.node {
-            hir::VisibilityKind::Public => Visibility::Public,
-            hir::VisibilityKind::Crate(_) => Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)),
-            hir::VisibilityKind::Restricted { ref path, .. } => match path.res {
-                // If there is no resolution, `resolve` will have already reported an error, so
-                // assume that the visibility is public to avoid reporting more privacy errors.
-                Res::Err => Visibility::Public,
-                def => Visibility::Restricted(def.def_id()),
-            },
-            hir::VisibilityKind::Inherited => {
-                Visibility::Restricted(tcx.parent_module(id).to_def_id())
-            }
-        }
-    }
-
     /// Returns `true` if an item with this visibility is accessible from the given block.
     pub fn is_accessible_from<T: DefIdTree>(self, module: DefId, tree: T) -> bool {
         let restriction = match self {
@@ -1992,8 +1979,8 @@ pub fn provided_trait_methods(self, id: DefId) -> impl 'tcx + Iterator<Item = &'
     }
 
     fn opt_item_name(self, def_id: DefId) -> Option<Symbol> {
-        if def_id.index == CRATE_DEF_INDEX {
-            Some(self.crate_name(def_id.krate))
+        if let Some(cnum) = def_id.as_crate_root() {
+            Some(self.crate_name(cnum))
         } else {
             let def_key = self.def_key(def_id);
             match def_key.disambiguated_data.data {
index 4379adb604e1f29e9d1e24e79413ef2460eedecb..38362a4cbb92529a8a164ba137096bd1cda4e70a 100644 (file)
@@ -6,9 +6,8 @@
 use rustc_data_structures::sso::SsoHashSet;
 use rustc_hir as hir;
 use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
-use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
-use rustc_hir::ItemKind;
 use rustc_session::config::TrimmedDefPaths;
 use rustc_session::cstore::{ExternCrate, ExternCrateSource};
 use rustc_span::symbol::{kw, Ident, Symbol};
@@ -336,9 +335,7 @@ fn try_print_visible_def_path_recur(
 
         // If `def_id` is a direct or injected extern crate, return the
         // path to the crate followed by the path to the item within the crate.
-        if def_id.index == CRATE_DEF_INDEX {
-            let cnum = def_id.krate;
-
+        if let Some(cnum) = def_id.as_crate_root() {
             if cnum == LOCAL_CRATE {
                 return Ok((self.path_crate(cnum)?, true));
             }
@@ -2228,11 +2225,11 @@ fn name_by_region_index(index: usize) -> Symbol {
                     ty::BrNamed(_, _) => br.kind,
                     ty::BrAnon(i) => {
                         let name = region_map[&(i + 1)];
-                        ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
+                        ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)
                     }
                     ty::BrEnv => {
                         let name = region_map[&0];
-                        ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
+                        ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)
                     }
                 };
                 self.tcx.mk_region(ty::ReLateBound(
@@ -2258,7 +2255,7 @@ fn name_by_region_index(index: usize) -> Symbol {
                             }
                         };
                         do_continue(&mut self, name);
-                        ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
+                        ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)
                     }
                 };
                 tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind }))
@@ -2678,8 +2675,13 @@ pub fn print_modifiers_and_trait_path(
 fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, Namespace, DefId)) {
     // Iterate all local crate items no matter where they are defined.
     let hir = tcx.hir();
-    for item in hir.items() {
-        if item.ident.name.as_str().is_empty() || matches!(item.kind, ItemKind::Use(_, _)) {
+    for id in hir.items() {
+        if matches!(hir.def_kind(id.def_id), DefKind::Use) {
+            continue;
+        }
+
+        let item = hir.item(id);
+        if item.ident.name == kw::Empty {
             continue;
         }
 
@@ -2693,7 +2695,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
     let mut seen_defs: DefIdSet = Default::default();
 
     for &cnum in tcx.crates(()).iter() {
-        let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
+        let def_id = cnum.as_def_id();
 
         // Ignore crates that are not direct dependencies.
         match tcx.extern_crate(def_id) {
index 9e48c569c253a593f1bb0dd5dd1bd3003eb87578..7629d7a8259b8b841598e95c2c70519f186a04cc 100644 (file)
 use crate::ty::fast_reject::SimplifiedType;
 use crate::ty::subst::{GenericArg, SubstsRef};
 use crate::ty::util::AlwaysRequiresDrop;
+use crate::ty::GeneratorDiagnosticData;
 use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
+use rustc_ast as ast;
 use rustc_ast::expand::allocator::AllocatorKind;
+use rustc_attr as attr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_data_structures::steal::Steal;
 use rustc_data_structures::svh::Svh;
 use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
 use rustc_session::utils::NativeLibKind;
 use rustc_session::Limits;
-use rustc_target::abi;
-use rustc_target::spec::PanicStrategy;
-
-use rustc_ast as ast;
-use rustc_attr as attr;
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
+use rustc_target::abi;
+use rustc_target::spec::PanicStrategy;
 use std::ops::Deref;
 use std::path::PathBuf;
 use std::sync::Arc;
index d9b55563996bab580d050db2d2d9d4d517e244ed..4c1160e21fec2bf715d8257f46082faba65f2916 100644 (file)
@@ -61,7 +61,7 @@ fn relate_item_substs(
 
         let tcx = self.tcx();
         let opt_variances = tcx.variances_of(item_def_id);
-        relate_substs(self, Some((item_def_id, opt_variances)), a_subst, b_subst)
+        relate_substs_with_variances(self, item_def_id, opt_variances, a_subst, b_subst)
     }
 
     /// Switch variance for the purpose of relating `a` and `b`.
@@ -135,29 +135,34 @@ pub fn relate_type_and_mut<'tcx, R: TypeRelation<'tcx>>(
     }
 }
 
+#[inline]
 pub fn relate_substs<'tcx, R: TypeRelation<'tcx>>(
     relation: &mut R,
-    variances: Option<(DefId, &[ty::Variance])>,
+    a_subst: SubstsRef<'tcx>,
+    b_subst: SubstsRef<'tcx>,
+) -> RelateResult<'tcx, SubstsRef<'tcx>> {
+    relation.tcx().mk_substs(iter::zip(a_subst, b_subst).map(|(a, b)| {
+        relation.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)
+    }))
+}
+
+pub fn relate_substs_with_variances<'tcx, R: TypeRelation<'tcx>>(
+    relation: &mut R,
+    ty_def_id: DefId,
+    variances: &[ty::Variance],
     a_subst: SubstsRef<'tcx>,
     b_subst: SubstsRef<'tcx>,
 ) -> RelateResult<'tcx, SubstsRef<'tcx>> {
     let tcx = relation.tcx();
-    let mut cached_ty = None;
 
+    let mut cached_ty = None;
     let params = iter::zip(a_subst, b_subst).enumerate().map(|(i, (a, b))| {
-        let (variance, variance_info) = match variances {
-            Some((ty_def_id, variances)) => {
-                let variance = variances[i];
-                let variance_info = if variance == ty::Invariant {
-                    let ty = *cached_ty
-                        .get_or_insert_with(|| tcx.type_of(ty_def_id).subst(tcx, a_subst));
-                    ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() }
-                } else {
-                    ty::VarianceDiagInfo::default()
-                };
-                (variance, variance_info)
-            }
-            None => (ty::Invariant, ty::VarianceDiagInfo::default()),
+        let variance = variances[i];
+        let variance_info = if variance == ty::Invariant {
+            let ty = *cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).subst(tcx, a_subst));
+            ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() }
+        } else {
+            ty::VarianceDiagInfo::default()
         };
         relation.relate_with_variance(variance, variance_info, a, b)
     });
@@ -318,7 +323,7 @@ fn relate<R: TypeRelation<'tcx>>(
         if a.def_id != b.def_id {
             Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id)))
         } else {
-            let substs = relate_substs(relation, None, a.substs, b.substs)?;
+            let substs = relate_substs(relation, a.substs, b.substs)?;
             Ok(ty::TraitRef { def_id: a.def_id, substs })
         }
     }
@@ -334,7 +339,7 @@ fn relate<R: TypeRelation<'tcx>>(
         if a.def_id != b.def_id {
             Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id)))
         } else {
-            let substs = relate_substs(relation, None, a.substs, b.substs)?;
+            let substs = relate_substs(relation, a.substs, b.substs)?;
             Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs })
         }
     }
@@ -554,7 +559,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
         (&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs))
             if a_def_id == b_def_id =>
         {
-            let substs = relate_substs(relation, None, a_substs, b_substs)?;
+            let substs = relate_substs(relation, a_substs, b_substs)?;
             Ok(tcx.mk_opaque(a_def_id, substs))
         }
 
@@ -742,7 +747,7 @@ fn relate<R: TypeRelation<'tcx>>(
         a: ty::ClosureSubsts<'tcx>,
         b: ty::ClosureSubsts<'tcx>,
     ) -> RelateResult<'tcx, ty::ClosureSubsts<'tcx>> {
-        let substs = relate_substs(relation, None, a.substs, b.substs)?;
+        let substs = relate_substs(relation, a.substs, b.substs)?;
         Ok(ty::ClosureSubsts { substs })
     }
 }
@@ -753,7 +758,7 @@ fn relate<R: TypeRelation<'tcx>>(
         a: ty::GeneratorSubsts<'tcx>,
         b: ty::GeneratorSubsts<'tcx>,
     ) -> RelateResult<'tcx, ty::GeneratorSubsts<'tcx>> {
-        let substs = relate_substs(relation, None, a.substs, b.substs)?;
+        let substs = relate_substs(relation, a.substs, b.substs)?;
         Ok(ty::GeneratorSubsts { substs })
     }
 }
@@ -764,7 +769,7 @@ fn relate<R: TypeRelation<'tcx>>(
         a: SubstsRef<'tcx>,
         b: SubstsRef<'tcx>,
     ) -> RelateResult<'tcx, SubstsRef<'tcx>> {
-        relate_substs(relation, None, a, b)
+        relate_substs(relation, a, b)
     }
 }
 
index 5c7910db362d290c2257e04daf031bdebffb8436..4ef6ff1835ffd022ccddc0a098c3c2496aec2640 100644 (file)
@@ -10,7 +10,6 @@
 use rustc_data_structures::functor::IdFunctor;
 use rustc_hir as hir;
 use rustc_hir::def::Namespace;
-use rustc_hir::def_id::CRATE_DEF_INDEX;
 use rustc_index::vec::{Idx, IndexVec};
 
 use std::fmt;
@@ -71,7 +70,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
             ty::BrAnon(n) => write!(f, "BrAnon({:?})", n),
             ty::BrNamed(did, name) => {
-                if did.index == CRATE_DEF_INDEX {
+                if did.is_crate_root() {
                     write!(f, "BrNamed({})", name)
                 } else {
                     write!(f, "BrNamed({:?}, {})", did, name)
index 823f5f4cf12c460f74c79946e47e658050c76a2a..cee657e9da244fdc39f5358f463d5cf1f8fa024c 100644 (file)
@@ -255,10 +255,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         func: fun,
                         args,
                         cleanup: None,
-                        // FIXME(varkor): replace this with an uninhabitedness-based check.
-                        // This requires getting access to the current module to call
-                        // `tcx.is_ty_uninhabited_from`, which is currently tricky to do.
-                        destination: if expr.ty.is_never() {
+                        // The presence or absence of a return edge affects control-flow sensitive
+                        // MIR checks and ultimately whether code is accepted or not. We can only
+                        // omit the return edge if a return type is visibly uninhabited to a module
+                        // that makes the call.
+                        destination: if this.tcx.is_ty_uninhabited_from(
+                            this.parent_module,
+                            expr.ty,
+                            this.param_env,
+                        ) {
                             None
                         } else {
                             Some((destination, success))
@@ -426,9 +431,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                 value: Box::new(Constant { span, user_ty: None, literal: value }),
                             }
                         }
-                        thir::InlineAsmOperand::SymFn { expr } => mir::InlineAsmOperand::SymFn {
-                            value: Box::new(this.as_constant(&this.thir[expr])),
-                        },
+                        thir::InlineAsmOperand::SymFn { value, span } => {
+                            mir::InlineAsmOperand::SymFn {
+                                value: Box::new(Constant {
+                                    span,
+                                    user_ty: None,
+                                    literal: value.into(),
+                                }),
+                            }
+                        }
                         thir::InlineAsmOperand::SymStatic { def_id } => {
                             mir::InlineAsmOperand::SymStatic { def_id }
                         }
index 901635dc488a7c42fa99f9c472a3b900fc0fd94d..3c51f7918627437bcd9b8f3d479941abed490f4c 100644 (file)
@@ -350,6 +350,7 @@ struct Builder<'a, 'tcx> {
 
     def_id: DefId,
     hir_id: hir::HirId,
+    parent_module: DefId,
     check_overflow: bool,
     fn_span: Span,
     arg_count: usize,
@@ -807,15 +808,17 @@ fn new(
         );
 
         let lint_level = LintLevel::Explicit(hir_id);
+        let param_env = tcx.param_env(def.did);
         let mut builder = Builder {
             thir,
             tcx,
             infcx,
             typeck_results: tcx.typeck_opt_const_arg(def),
             region_scope_tree: tcx.region_scope_tree(def.did),
-            param_env: tcx.param_env(def.did),
+            param_env,
             def_id: def.did.to_def_id(),
             hir_id,
+            parent_module: tcx.parent_module(hir_id).to_def_id(),
             check_overflow,
             cfg: CFG { basic_blocks: IndexVec::new() },
             fn_span: span,
index 7ef33011234fc4ff87cd426682c0b660e7769ef7..f382f79af29dbf1291c3efe6a2678d3c7a7d1498 100644 (file)
@@ -462,95 +462,56 @@ fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx>
                 operands: asm
                     .operands
                     .iter()
-                    .map(|(op, _op_sp)| {
-                        match *op {
-                            hir::InlineAsmOperand::In { reg, ref expr } => {
-                                InlineAsmOperand::In { reg, expr: self.mirror_expr(expr) }
-                            }
-                            hir::InlineAsmOperand::Out { reg, late, ref expr } => {
-                                InlineAsmOperand::Out {
-                                    reg,
-                                    late,
-                                    expr: expr.as_ref().map(|expr| self.mirror_expr(expr)),
-                                }
-                            }
-                            hir::InlineAsmOperand::InOut { reg, late, ref expr } => {
-                                InlineAsmOperand::InOut { reg, late, expr: self.mirror_expr(expr) }
-                            }
-                            hir::InlineAsmOperand::SplitInOut {
-                                reg,
-                                late,
-                                ref in_expr,
-                                ref out_expr,
-                            } => InlineAsmOperand::SplitInOut {
+                    .map(|(op, _op_sp)| match *op {
+                        hir::InlineAsmOperand::In { reg, ref expr } => {
+                            InlineAsmOperand::In { reg, expr: self.mirror_expr(expr) }
+                        }
+                        hir::InlineAsmOperand::Out { reg, late, ref expr } => {
+                            InlineAsmOperand::Out {
                                 reg,
                                 late,
-                                in_expr: self.mirror_expr(in_expr),
-                                out_expr: out_expr.as_ref().map(|expr| self.mirror_expr(expr)),
-                            },
-                            hir::InlineAsmOperand::Const { ref anon_const } => {
-                                let anon_const_def_id =
-                                    self.tcx.hir().local_def_id(anon_const.hir_id);
-                                let value = mir::ConstantKind::from_anon_const(
-                                    self.tcx,
-                                    anon_const_def_id,
-                                    self.param_env,
-                                );
-                                let span = self.tcx.hir().span(anon_const.hir_id);
-
-                                InlineAsmOperand::Const { value, span }
-                            }
-                            hir::InlineAsmOperand::Sym { ref expr } => {
-                                let hir::ExprKind::Path(ref qpath) = expr.kind else {
-                                    span_bug!(
-                                        expr.span,
-                                        "asm `sym` operand should be a path, found {:?}",
-                                        expr.kind
-                                    );
-                                };
-                                let temp_lifetime =
-                                    self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
-                                let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
-                                let ty;
-                                match res {
-                                    Res::Def(DefKind::Fn, _) | Res::Def(DefKind::AssocFn, _) => {
-                                        ty = self.typeck_results().node_type(expr.hir_id);
-                                        let user_ty =
-                                            self.user_substs_applied_to_res(expr.hir_id, res);
-                                        InlineAsmOperand::SymFn {
-                                            expr: self.thir.exprs.push(Expr {
-                                                ty,
-                                                temp_lifetime,
-                                                span: expr.span,
-                                                kind: ExprKind::zero_sized_literal(user_ty),
-                                            }),
-                                        }
-                                    }
-
-                                    Res::Def(DefKind::Static(_), def_id) => {
-                                        InlineAsmOperand::SymStatic { def_id }
-                                    }
-
-                                    _ => {
-                                        self.tcx.sess.span_err(
-                                            expr.span,
-                                            "asm `sym` operand must point to a fn or static",
-                                        );
-
-                                        // Not a real fn, but we're not reaching codegen anyways...
-                                        ty = self.tcx.ty_error();
-                                        InlineAsmOperand::SymFn {
-                                            expr: self.thir.exprs.push(Expr {
-                                                ty,
-                                                temp_lifetime,
-                                                span: expr.span,
-                                                kind: ExprKind::zero_sized_literal(None),
-                                            }),
-                                        }
-                                    }
-                                }
+                                expr: expr.as_ref().map(|expr| self.mirror_expr(expr)),
                             }
                         }
+                        hir::InlineAsmOperand::InOut { reg, late, ref expr } => {
+                            InlineAsmOperand::InOut { reg, late, expr: self.mirror_expr(expr) }
+                        }
+                        hir::InlineAsmOperand::SplitInOut {
+                            reg,
+                            late,
+                            ref in_expr,
+                            ref out_expr,
+                        } => InlineAsmOperand::SplitInOut {
+                            reg,
+                            late,
+                            in_expr: self.mirror_expr(in_expr),
+                            out_expr: out_expr.as_ref().map(|expr| self.mirror_expr(expr)),
+                        },
+                        hir::InlineAsmOperand::Const { ref anon_const } => {
+                            let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
+                            let value = mir::ConstantKind::from_anon_const(
+                                self.tcx,
+                                anon_const_def_id,
+                                self.param_env,
+                            );
+                            let span = self.tcx.hir().span(anon_const.hir_id);
+
+                            InlineAsmOperand::Const { value, span }
+                        }
+                        hir::InlineAsmOperand::SymFn { ref anon_const } => {
+                            let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
+                            let value = mir::ConstantKind::from_anon_const(
+                                self.tcx,
+                                anon_const_def_id,
+                                self.param_env,
+                            );
+                            let span = self.tcx.hir().span(anon_const.hir_id);
+
+                            InlineAsmOperand::SymFn { value, span }
+                        }
+                        hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
+                            InlineAsmOperand::SymStatic { def_id }
+                        }
                     })
                     .collect(),
                 options: asm.options,
index 44caa2ac076f23f9de6bf3e5451284d08a982208..58e484e413dab4d5a1a4d4ca14f40479ec059328 100644 (file)
@@ -844,7 +844,7 @@ fn non_exhaustive_match<'p, 'tcx>(
                     format!(
                         "{}{}{} => todo!()",
                         comma,
-                        snippet.strip_prefix(",").unwrap_or(&snippet),
+                        snippet.strip_prefix(',').unwrap_or(&snippet),
                         pattern
                     ),
                 ));
index 13b49256d488a8f1b25c0c5168e00f0db8acd72e..691f4fb0e54259a29e5532a8f154274d76e59cc8 100644 (file)
@@ -313,9 +313,7 @@ struct ConstPropagator<'mir, 'tcx> {
     ecx: InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>,
     tcx: TyCtxt<'tcx>,
     param_env: ParamEnv<'tcx>,
-    // FIXME(eddyb) avoid cloning this field more than once,
-    // by accessing it through `ecx` instead.
-    local_decls: IndexVec<Local, LocalDecl<'tcx>>,
+    local_decls: &'mir IndexVec<Local, LocalDecl<'tcx>>,
     // Because we have `MutVisitor` we can't obtain the `SourceInfo` from a `Location`. So we store
     // the last known `SourceInfo` here and just keep revisiting it.
     source_info: Option<SourceInfo>,
@@ -361,10 +359,6 @@ fn new(
         let substs = &InternalSubsts::identity_for_item(tcx, def_id);
         let param_env = tcx.param_env_reveal_all_normalized(def_id);
 
-        let span = tcx.def_span(def_id);
-        // FIXME: `CanConstProp::check` computes the layout of all locals, return those layouts
-        // so we can write them to `ecx.frame_mut().locals.layout, reducing the duplication in
-        // `layout_of` query invocations.
         let can_const_prop = CanConstProp::check(tcx, param_env, body);
         let mut only_propagate_inside_block_locals = BitSet::new_empty(can_const_prop.len());
         for (l, mode) in can_const_prop.iter_enumerated() {
@@ -374,7 +368,7 @@ fn new(
         }
         let mut ecx = InterpCx::new(
             tcx,
-            span,
+            tcx.def_span(def_id),
             param_env,
             ConstPropMachine::new(only_propagate_inside_block_locals, can_const_prop),
         );
@@ -405,10 +399,7 @@ fn new(
             ecx,
             tcx,
             param_env,
-            // FIXME(eddyb) avoid cloning this field more than once,
-            // by accessing it through `ecx` instead.
-            //FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it
-            local_decls: body.local_decls.clone(),
+            local_decls: &dummy_body.local_decls,
             source_info: None,
         }
     }
@@ -511,7 +502,7 @@ fn check_binary_op(
             let r = r?;
             // We need the type of the LHS. We cannot use `place_layout` as that is the type
             // of the result, which for checked binops is not the same!
-            let left_ty = left.ty(&self.local_decls, self.tcx);
+            let left_ty = left.ty(self.local_decls, self.tcx);
             let left_size = self.ecx.layout_of(left_ty).ok()?.size;
             let right_size = r.layout.size;
             let r_bits = r.to_scalar().ok();
index d6331a88c5b7da31a7d4e3679a3afe37f8c92066..4945c10c9aaa900aa35f826435a2dd7f083ebd85 100644 (file)
@@ -308,10 +308,8 @@ struct ConstPropagator<'mir, 'tcx> {
     ecx: InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>,
     tcx: TyCtxt<'tcx>,
     param_env: ParamEnv<'tcx>,
-    // FIXME(eddyb) avoid cloning these two fields more than once,
-    // by accessing them through `ecx` instead.
-    source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
-    local_decls: IndexVec<Local, LocalDecl<'tcx>>,
+    source_scopes: &'mir IndexVec<SourceScope, SourceScopeData<'tcx>>,
+    local_decls: &'mir IndexVec<Local, LocalDecl<'tcx>>,
     // Because we have `MutVisitor` we can't obtain the `SourceInfo` from a `Location`. So we store
     // the last known `SourceInfo` here and just keep revisiting it.
     source_info: Option<SourceInfo>,
@@ -357,10 +355,6 @@ fn new(
         let substs = &InternalSubsts::identity_for_item(tcx, def_id);
         let param_env = tcx.param_env_reveal_all_normalized(def_id);
 
-        let span = tcx.def_span(def_id);
-        // FIXME: `CanConstProp::check` computes the layout of all locals, return those layouts
-        // so we can write them to `ecx.frame_mut().locals.layout, reducing the duplication in
-        // `layout_of` query invocations.
         let can_const_prop = CanConstProp::check(tcx, param_env, body);
         let mut only_propagate_inside_block_locals = BitSet::new_empty(can_const_prop.len());
         for (l, mode) in can_const_prop.iter_enumerated() {
@@ -370,7 +364,7 @@ fn new(
         }
         let mut ecx = InterpCx::new(
             tcx,
-            span,
+            tcx.def_span(def_id),
             param_env,
             ConstPropMachine::new(only_propagate_inside_block_locals, can_const_prop),
         );
@@ -401,11 +395,8 @@ fn new(
             ecx,
             tcx,
             param_env,
-            // FIXME(eddyb) avoid cloning these two fields more than once,
-            // by accessing them through `ecx` instead.
-            source_scopes: body.source_scopes.clone(),
-            //FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it
-            local_decls: body.local_decls.clone(),
+            source_scopes: &dummy_body.source_scopes,
+            local_decls: &dummy_body.local_decls,
             source_info: None,
         }
     }
@@ -435,7 +426,7 @@ fn remove_const(ecx: &mut InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>, lo
     }
 
     fn lint_root(&self, source_info: SourceInfo) -> Option<HirId> {
-        source_info.scope.lint_root(&self.source_scopes)
+        source_info.scope.lint_root(self.source_scopes)
     }
 
     fn use_ecx<F, T>(&mut self, f: F) -> Option<T>
@@ -572,7 +563,7 @@ fn check_binary_op(
             let r = r?;
             // We need the type of the LHS. We cannot use `place_layout` as that is the type
             // of the result, which for checked binops is not the same!
-            let left_ty = left.ty(&self.local_decls, self.tcx);
+            let left_ty = left.ty(self.local_decls, self.tcx);
             let left_size = self.ecx.layout_of(left_ty).ok()?.size;
             let right_size = r.layout.size;
             let r_bits = r.to_scalar().ok();
index 740a2168b41cc52865c92782309d41f5beeb2331..2380391d09a914042e3b83e77c740543c1077175 100644 (file)
@@ -77,17 +77,30 @@ pub fn run_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, passes: &[&dyn
     let mut cnt = 0;
 
     let validate = tcx.sess.opts.debugging_opts.validate_mir;
+    let overridden_passes = &tcx.sess.opts.debugging_opts.mir_enable_passes;
+    trace!(?overridden_passes);
 
     if validate {
         validate_body(tcx, body, format!("start of phase transition from {:?}", start_phase));
     }
 
     for pass in passes {
-        if !pass.is_enabled(&tcx.sess) {
-            continue;
-        }
-
         let name = pass.name();
+
+        if let Some((_, polarity)) = overridden_passes.iter().rev().find(|(s, _)| s == &*name) {
+            trace!(
+                pass = %name,
+                "{} as requested by flag",
+                if *polarity { "Running" } else { "Not running" },
+            );
+            if !polarity {
+                continue;
+            }
+        } else {
+            if !pass.is_enabled(&tcx.sess) {
+                continue;
+            }
+        }
         let dump_enabled = pass.is_mir_dump_enabled();
 
         if dump_enabled {
index 2a659a97db5f9cbf759d4b2129e0b6721a357ea2..0e0a4fbc2155641b87a080983c72fae181044db1 100644 (file)
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
 use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_middle::mir::interpret::{AllocId, ConstValue};
@@ -327,11 +327,19 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
 
         debug!("collect_roots: entry_fn = {:?}", entry_fn);
 
-        let mut visitor = RootCollector { tcx, mode, entry_fn, output: &mut roots };
+        let mut collector = RootCollector { tcx, mode, entry_fn, output: &mut roots };
 
-        tcx.hir().visit_all_item_likes(&mut visitor);
+        let crate_items = tcx.hir_crate_items(());
 
-        visitor.push_extra_entry_roots();
+        for id in crate_items.items() {
+            collector.process_item(id);
+        }
+
+        for id in crate_items.impl_items() {
+            collector.process_impl_item(id);
+        }
+
+        collector.push_extra_entry_roots();
     }
 
     // We can only codegen items that are instantiable - items all of
@@ -435,7 +443,27 @@ fn collect_items_rec<'tcx>(
                             // are supported. Therefore the value should not
                             // depend on any other items.
                         }
-                        _ => span_bug!(*op_sp, "invalid operand type for global_asm!"),
+                        hir::InlineAsmOperand::SymFn { anon_const } => {
+                            let def_id = tcx.hir().body_owner_def_id(anon_const.body).to_def_id();
+                            if let Ok(val) = tcx.const_eval_poly(def_id) {
+                                rustc_data_structures::stack::ensure_sufficient_stack(|| {
+                                    collect_const_value(tcx, val, &mut neighbors);
+                                });
+                            }
+                        }
+                        hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
+                            let instance = Instance::mono(tcx, *def_id);
+                            if should_codegen_locally(tcx, &instance) {
+                                trace!("collecting static {:?}", def_id);
+                                neighbors.push(dummy_spanned(MonoItem::Static(*def_id)));
+                            }
+                        }
+                        hir::InlineAsmOperand::In { .. }
+                        | hir::InlineAsmOperand::Out { .. }
+                        | hir::InlineAsmOperand::InOut { .. }
+                        | hir::InlineAsmOperand::SplitInOut { .. } => {
+                            span_bug!(*op_sp, "invalid operand type for global_asm!")
+                        }
                     }
                 }
             } else {
@@ -1139,87 +1167,74 @@ struct RootCollector<'a, 'tcx> {
     entry_fn: Option<(DefId, EntryFnType)>,
 }
 
-impl<'v> ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
-    fn visit_item(&mut self, item: &'v hir::Item<'v>) {
-        match item.kind {
-            hir::ItemKind::ExternCrate(..)
-            | hir::ItemKind::Use(..)
-            | hir::ItemKind::Macro(..)
-            | hir::ItemKind::ForeignMod { .. }
-            | hir::ItemKind::TyAlias(..)
-            | hir::ItemKind::Trait(..)
-            | hir::ItemKind::TraitAlias(..)
-            | hir::ItemKind::OpaqueTy(..)
-            | hir::ItemKind::Mod(..) => {
-                // Nothing to do, just keep recursing.
-            }
-
-            hir::ItemKind::Impl { .. } => {
-                if self.mode == MonoItemCollectionMode::Eager {
-                    create_mono_items_for_default_impls(self.tcx, item, self.output);
-                }
-            }
-
-            hir::ItemKind::Enum(_, ref generics)
-            | hir::ItemKind::Struct(_, ref generics)
-            | hir::ItemKind::Union(_, ref generics) => {
-                if generics.params.is_empty() {
-                    if self.mode == MonoItemCollectionMode::Eager {
-                        debug!(
-                            "RootCollector: ADT drop-glue for {}",
-                            self.tcx.def_path_str(item.def_id.to_def_id())
-                        );
-
-                        let ty = Instance::new(item.def_id.to_def_id(), InternalSubsts::empty())
-                            .ty(self.tcx, ty::ParamEnv::reveal_all());
-                        visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output);
+impl<'v> RootCollector<'_, 'v> {
+    fn process_item(&mut self, id: hir::ItemId) {
+        match self.tcx.hir().def_kind(id.def_id) {
+            DefKind::Enum | DefKind::Struct | DefKind::Union => {
+                let item = self.tcx.hir().item(id);
+                match item.kind {
+                    hir::ItemKind::Enum(_, ref generics)
+                    | hir::ItemKind::Struct(_, ref generics)
+                    | hir::ItemKind::Union(_, ref generics) => {
+                        if generics.params.is_empty() {
+                            if self.mode == MonoItemCollectionMode::Eager {
+                                debug!(
+                                    "RootCollector: ADT drop-glue for {}",
+                                    self.tcx.def_path_str(item.def_id.to_def_id())
+                                );
+
+                                let ty =
+                                    Instance::new(item.def_id.to_def_id(), InternalSubsts::empty())
+                                        .ty(self.tcx, ty::ParamEnv::reveal_all());
+                                visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output);
+                            }
+                        }
                     }
+                    _ => bug!(),
                 }
             }
-            hir::ItemKind::GlobalAsm(..) => {
+            DefKind::GlobalAsm => {
                 debug!(
                     "RootCollector: ItemKind::GlobalAsm({})",
-                    self.tcx.def_path_str(item.def_id.to_def_id())
+                    self.tcx.def_path_str(id.def_id.to_def_id())
                 );
-                self.output.push(dummy_spanned(MonoItem::GlobalAsm(item.item_id())));
+                self.output.push(dummy_spanned(MonoItem::GlobalAsm(id)));
             }
-            hir::ItemKind::Static(..) => {
+            DefKind::Static(..) => {
                 debug!(
                     "RootCollector: ItemKind::Static({})",
-                    self.tcx.def_path_str(item.def_id.to_def_id())
+                    self.tcx.def_path_str(id.def_id.to_def_id())
                 );
-                self.output.push(dummy_spanned(MonoItem::Static(item.def_id.to_def_id())));
+                self.output.push(dummy_spanned(MonoItem::Static(id.def_id.to_def_id())));
             }
-            hir::ItemKind::Const(..) => {
+            DefKind::Const => {
                 // const items only generate mono items if they are
                 // actually used somewhere. Just declaring them is insufficient.
 
                 // but even just declaring them must collect the items they refer to
-                if let Ok(val) = self.tcx.const_eval_poly(item.def_id.to_def_id()) {
+                if let Ok(val) = self.tcx.const_eval_poly(id.def_id.to_def_id()) {
                     collect_const_value(self.tcx, val, &mut self.output);
                 }
             }
-            hir::ItemKind::Fn(..) => {
-                self.push_if_root(item.def_id);
+            DefKind::Impl => {
+                if self.mode == MonoItemCollectionMode::Eager {
+                    let item = self.tcx.hir().item(id);
+                    create_mono_items_for_default_impls(self.tcx, item, self.output);
+                }
+            }
+            DefKind::Fn => {
+                self.push_if_root(id.def_id);
             }
+            _ => {}
         }
     }
 
-    fn visit_trait_item(&mut self, _: &'v hir::TraitItem<'v>) {
-        // Even if there's a default body with no explicit generics,
-        // it's still generic over some `Self: Trait`, so not a root.
-    }
-
-    fn visit_impl_item(&mut self, ii: &'v hir::ImplItem<'v>) {
-        if let hir::ImplItemKind::Fn(hir::FnSig { .. }, _) = ii.kind {
-            self.push_if_root(ii.def_id);
+    fn process_impl_item(&mut self, id: hir::ImplItemId) {
+        if matches!(self.tcx.hir().def_kind(id.def_id), DefKind::AssocFn) {
+            self.push_if_root(id.def_id);
         }
     }
 
-    fn visit_foreign_item(&mut self, _foreign_item: &'v hir::ForeignItem<'v>) {}
-}
-
-impl<'v> RootCollector<'_, 'v> {
     fn is_root(&self, def_id: LocalDefId) -> bool {
         !item_requires_monomorphization(self.tcx, def_id)
             && match self.mode {
index c4ffb19f87a91a6595a193c858b0c4fdbd47496b..167741988798862b79e05f008190fa65b38f46ae 100644 (file)
@@ -2,7 +2,7 @@
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathDataName;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::middle::exported_symbols::SymbolExportLevel;
@@ -335,10 +335,10 @@ fn compute_codegen_unit_name(
     let mut cgu_def_id = None;
     // Walk backwards from the item we want to find the module for.
     loop {
-        if current_def_id.index == CRATE_DEF_INDEX {
+        if current_def_id.is_crate_root() {
             if cgu_def_id.is_none() {
                 // If we have not found a module yet, take the crate root.
-                cgu_def_id = Some(DefId { krate: def_id.krate, index: CRATE_DEF_INDEX });
+                cgu_def_id = Some(def_id.krate.as_def_id());
             }
             break;
         } else if tcx.def_kind(current_def_id) == DefKind::Mod {
index 79f0237fd9b7478f4128c70465c92f0a1246915e..bfa13ce79bab47c99c376d857ea671ffbbb90d3c 100644 (file)
@@ -182,16 +182,7 @@ fn cook_lexer_token(&self, token: rustc_lexer::TokenKind, start: BytePos) -> Opt
             }
             rustc_lexer::TokenKind::BlockComment { doc_style, terminated } => {
                 if !terminated {
-                    let msg = match doc_style {
-                        Some(_) => "unterminated block doc-comment",
-                        None => "unterminated block comment",
-                    };
-                    let last_bpos = self.pos;
-                    self.sess.span_diagnostic.span_fatal_with_code(
-                        self.mk_sp(start, last_bpos),
-                        msg,
-                        error_code!(E0758),
-                    );
+                    self.report_unterminated_block_comment(start, doc_style);
                 }
 
                 // Skip non-doc comments
@@ -553,6 +544,55 @@ fn report_unterminated_raw_string(
         err.emit()
     }
 
+    fn report_unterminated_block_comment(&self, start: BytePos, doc_style: Option<DocStyle>) {
+        let msg = match doc_style {
+            Some(_) => "unterminated block doc-comment",
+            None => "unterminated block comment",
+        };
+        let last_bpos = self.pos;
+        let mut err = self.sess.span_diagnostic.struct_span_fatal_with_code(
+            self.mk_sp(start, last_bpos),
+            msg,
+            error_code!(E0758),
+        );
+        let mut nested_block_comment_open_idxs = vec![];
+        let mut last_nested_block_comment_idxs = None;
+        let mut content_chars = self.str_from(start).char_indices().peekable();
+
+        while let Some((idx, current_char)) = content_chars.next() {
+            match content_chars.peek() {
+                Some((_, '*')) if current_char == '/' => {
+                    nested_block_comment_open_idxs.push(idx);
+                }
+                Some((_, '/')) if current_char == '*' => {
+                    last_nested_block_comment_idxs =
+                        nested_block_comment_open_idxs.pop().map(|open_idx| (open_idx, idx));
+                }
+                _ => {}
+            };
+        }
+
+        if let Some((nested_open_idx, nested_close_idx)) = last_nested_block_comment_idxs {
+            err.span_label(self.mk_sp(start, start + BytePos(2)), msg)
+                .span_label(
+                    self.mk_sp(
+                        start + BytePos(nested_open_idx as u32),
+                        start + BytePos(nested_open_idx as u32 + 2),
+                    ),
+                    "...as last nested comment starts here, maybe you want to close this instead?",
+                )
+                .span_label(
+                    self.mk_sp(
+                        start + BytePos(nested_close_idx as u32),
+                        start + BytePos(nested_close_idx as u32 + 2),
+                    ),
+                    "...and last nested comment terminates here.",
+                );
+        }
+
+        err.emit();
+    }
+
     // RFC 3101 introduced the idea of (reserved) prefixes. As of Rust 2021,
     // using a (unknown) prefix is an error. In earlier editions, however, they
     // only result in a (allowed by default) lint, and are treated as regular
index 5ee9c339bb7aa9067c5d24726f65110b2a78fd8b..02749088c3139e50e9745dee12243021de5a73ac 100644 (file)
@@ -100,21 +100,16 @@ struct LazyTokenStreamImpl {
 
 impl CreateTokenStream for LazyTokenStreamImpl {
     fn create_token_stream(&self) -> AttrAnnotatedTokenStream {
-        // The token produced by the final call to `{,inlined_}next` or
-        // `{,inlined_}next_desugared` was not actually consumed by the
-        // callback. The combination of chaining the initial token and using
-        // `take` produces the desired result - we produce an empty
-        // `TokenStream` if no calls were made, and omit the final token
-        // otherwise.
+        // The token produced by the final call to `{,inlined_}next` was not
+        // actually consumed by the callback. The combination of chaining the
+        // initial token and using `take` produces the desired result - we
+        // produce an empty `TokenStream` if no calls were made, and omit the
+        // final token otherwise.
         let mut cursor_snapshot = self.cursor_snapshot.clone();
         let tokens =
             std::iter::once((FlatToken::Token(self.start_token.0.clone()), self.start_token.1))
                 .chain((0..self.num_calls).map(|_| {
-                    let token = if cursor_snapshot.desugar_doc_comments {
-                        cursor_snapshot.next_desugared()
-                    } else {
-                        cursor_snapshot.next()
-                    };
+                    let token = cursor_snapshot.next(cursor_snapshot.desugar_doc_comments);
                     (FlatToken::Token(token.0), token.1)
                 }))
                 .take(self.num_calls);
index f1956fb695bf7ef4c46b738fff61ddd5dd107541..1686c5873e1833f4b5627fd627300aad055e950d 100644 (file)
@@ -123,8 +123,8 @@ pub struct Parser<'a> {
     pub capture_cfg: bool,
     restrictions: Restrictions,
     expected_tokens: Vec<TokenType>,
-    // Important: This must only be advanced from `next_tok`
-    // to ensure that `token_cursor.num_next_calls` is updated properly
+    // Important: This must only be advanced from `bump` to ensure that
+    // `token_cursor.num_next_calls` is updated properly.
     token_cursor: TokenCursor,
     desugar_doc_comments: bool,
     /// This field is used to keep track of how many left angle brackets we have seen. This is
@@ -150,6 +150,11 @@ pub struct Parser<'a> {
     pub current_closure: Option<ClosureSpans>,
 }
 
+// This type is used a lot, e.g. it's cloned when matching many declarative macro rules. Make sure
+// it doesn't unintentionally get bigger.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+rustc_data_structures::static_assert_size!(Parser<'_>, 328);
+
 /// Stores span information about a closure.
 #[derive(Clone)]
 pub struct ClosureSpans {
@@ -203,12 +208,15 @@ fn drop(&mut self) {
 
 #[derive(Clone)]
 struct TokenCursor {
+    // The current (innermost) frame. `frame` and `stack` could be combined,
+    // but it's faster to have them separately to access `frame` directly
+    // rather than via something like `stack.last().unwrap()` or
+    // `stack[stack.len() - 1]`.
     frame: TokenCursorFrame,
+    // Additional frames that enclose `frame`.
     stack: Vec<TokenCursorFrame>,
     desugar_doc_comments: bool,
-    // Counts the number of calls to `{,inlined_}next` or
-    // `{,inlined_}next_desugared`, depending on whether
-    // `desugar_doc_comments` is set.
+    // Counts the number of calls to `{,inlined_}next`.
     num_next_calls: usize,
     // During parsing, we may sometimes need to 'unglue' a
     // glued token into two component tokens
@@ -238,73 +246,60 @@ struct TokenCursor {
 struct TokenCursorFrame {
     delim: token::DelimToken,
     span: DelimSpan,
-    open_delim: bool,
     tree_cursor: tokenstream::Cursor,
-    close_delim: bool,
 }
 
 impl TokenCursorFrame {
     fn new(span: DelimSpan, delim: DelimToken, tts: TokenStream) -> Self {
-        TokenCursorFrame {
-            delim,
-            span,
-            open_delim: false,
-            tree_cursor: tts.into_trees(),
-            close_delim: false,
-        }
+        TokenCursorFrame { delim, span, tree_cursor: tts.into_trees() }
     }
 }
 
 impl TokenCursor {
-    fn next(&mut self) -> (Token, Spacing) {
-        self.inlined_next()
+    fn next(&mut self, desugar_doc_comments: bool) -> (Token, Spacing) {
+        self.inlined_next(desugar_doc_comments)
     }
 
     /// This always-inlined version should only be used on hot code paths.
     #[inline(always)]
-    fn inlined_next(&mut self) -> (Token, Spacing) {
+    fn inlined_next(&mut self, desugar_doc_comments: bool) -> (Token, Spacing) {
         loop {
-            let (tree, spacing) = if !self.frame.open_delim {
-                self.frame.open_delim = true;
-                TokenTree::open_tt(self.frame.span, self.frame.delim).into()
-            } else if let Some(tree) = self.frame.tree_cursor.next_with_spacing() {
-                tree
-            } else if !self.frame.close_delim {
-                self.frame.close_delim = true;
-                TokenTree::close_tt(self.frame.span, self.frame.delim).into()
+            // FIXME: we currently don't return `NoDelim` open/close delims. To fix #67062 we will
+            // need to, whereupon the `delim != DelimToken::NoDelim` conditions below can be
+            // removed, as well as the loop.
+            if let Some((tree, spacing)) = self.frame.tree_cursor.next_with_spacing_ref() {
+                match tree {
+                    &TokenTree::Token(ref token) => match (desugar_doc_comments, token) {
+                        (true, &Token { kind: token::DocComment(_, attr_style, data), span }) => {
+                            return self.desugar(attr_style, data, span);
+                        }
+                        _ => return (token.clone(), *spacing),
+                    },
+                    &TokenTree::Delimited(sp, delim, ref tts) => {
+                        // Set `open_delim` to true here because we deal with it immediately.
+                        let frame = TokenCursorFrame::new(sp, delim, tts.clone());
+                        self.stack.push(mem::replace(&mut self.frame, frame));
+                        if delim != DelimToken::NoDelim {
+                            return (Token::new(token::OpenDelim(delim), sp.open), Spacing::Alone);
+                        }
+                        // No open delimeter to return; continue on to the next iteration.
+                    }
+                };
             } else if let Some(frame) = self.stack.pop() {
+                let delim = self.frame.delim;
+                let span = self.frame.span;
                 self.frame = frame;
-                continue;
-            } else {
-                (TokenTree::Token(Token::new(token::Eof, DUMMY_SP)), Spacing::Alone)
-            };
-
-            match tree {
-                TokenTree::Token(token) => {
-                    return (token, spacing);
-                }
-                TokenTree::Delimited(sp, delim, tts) => {
-                    let frame = TokenCursorFrame::new(sp, delim, tts);
-                    self.stack.push(mem::replace(&mut self.frame, frame));
+                if delim != DelimToken::NoDelim {
+                    return (Token::new(token::CloseDelim(delim), span.close), Spacing::Alone);
                 }
+                // No close delimiter to return; continue on to the next iteration.
+            } else {
+                return (Token::new(token::Eof, DUMMY_SP), Spacing::Alone);
             }
         }
     }
 
-    fn next_desugared(&mut self) -> (Token, Spacing) {
-        self.inlined_next_desugared()
-    }
-
-    /// This always-inlined version should only be used on hot code paths.
-    #[inline(always)]
-    fn inlined_next_desugared(&mut self) -> (Token, Spacing) {
-        let (data, attr_style, sp) = match self.inlined_next() {
-            (Token { kind: token::DocComment(_, attr_style, data), span }, _) => {
-                (data, attr_style, span)
-            }
-            tok => return tok,
-        };
-
+    fn desugar(&mut self, attr_style: AttrStyle, data: Symbol, span: Span) -> (Token, Spacing) {
         // Searches for the occurrences of `"#*` and returns the minimum number of `#`s
         // required to wrap the text.
         let mut num_of_hashes = 0;
@@ -318,14 +313,14 @@ fn inlined_next_desugared(&mut self) -> (Token, Spacing) {
             num_of_hashes = cmp::max(num_of_hashes, count);
         }
 
-        let delim_span = DelimSpan::from_single(sp);
+        let delim_span = DelimSpan::from_single(span);
         let body = TokenTree::Delimited(
             delim_span,
             token::Bracket,
             [
-                TokenTree::token(token::Ident(sym::doc, false), sp),
-                TokenTree::token(token::Eq, sp),
-                TokenTree::token(TokenKind::lit(token::StrRaw(num_of_hashes), data, None), sp),
+                TokenTree::token(token::Ident(sym::doc, false), span),
+                TokenTree::token(token::Eq, span),
+                TokenTree::token(TokenKind::lit(token::StrRaw(num_of_hashes), data, None), span),
             ]
             .iter()
             .cloned()
@@ -338,12 +333,12 @@ fn inlined_next_desugared(&mut self) -> (Token, Spacing) {
                 delim_span,
                 token::NoDelim,
                 if attr_style == AttrStyle::Inner {
-                    [TokenTree::token(token::Pound, sp), TokenTree::token(token::Not, sp), body]
+                    [TokenTree::token(token::Pound, span), TokenTree::token(token::Not, span), body]
                         .iter()
                         .cloned()
                         .collect::<TokenStream>()
                 } else {
-                    [TokenTree::token(token::Pound, sp), body]
+                    [TokenTree::token(token::Pound, span), body]
                         .iter()
                         .cloned()
                         .collect::<TokenStream>()
@@ -351,7 +346,7 @@ fn inlined_next_desugared(&mut self) -> (Token, Spacing) {
             ),
         ));
 
-        self.next()
+        self.next(/* desugar_doc_comments */ false)
     }
 }
 
@@ -436,9 +431,9 @@ pub fn new(
         desugar_doc_comments: bool,
         subparser_name: Option<&'static str>,
     ) -> Self {
-        let mut start_frame = TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, tokens);
-        start_frame.open_delim = true;
-        start_frame.close_delim = true;
+        // Note: because of the way `TokenCursor::inlined_next` is structured, the `span` and
+        // `delim` arguments here are never used.
+        let start_frame = TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, tokens);
 
         let mut parser = Parser {
             sess,
@@ -476,33 +471,6 @@ pub fn new(
         parser
     }
 
-    #[inline]
-    fn next_tok(&mut self, fallback_span: Span) -> (Token, Spacing) {
-        loop {
-            let (mut next, spacing) = if self.desugar_doc_comments {
-                self.token_cursor.inlined_next_desugared()
-            } else {
-                self.token_cursor.inlined_next()
-            };
-            self.token_cursor.num_next_calls += 1;
-            // We've retrieved an token from the underlying
-            // cursor, so we no longer need to worry about
-            // an unglued token. See `break_and_eat` for more details
-            self.token_cursor.break_last_token = false;
-            if next.span.is_dummy() {
-                // Tweak the location for better diagnostics, but keep syntactic context intact.
-                next.span = fallback_span.with_ctxt(next.span.ctxt());
-            }
-            if matches!(
-                next.kind,
-                token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim)
-            ) {
-                continue;
-            }
-            return (next, spacing);
-        }
-    }
-
     pub fn unexpected<T>(&mut self) -> PResult<'a, T> {
         match self.expect_one_of(&[], &[]) {
             Err(e) => Err(e),
@@ -697,7 +665,7 @@ fn break_and_eat(&mut self, expected: TokenKind) -> bool {
                 //
                 // If we consume any additional tokens, then this token
                 // is not needed (we'll capture the entire 'glued' token),
-                // and `next_tok` will set this field to `None`
+                // and `bump` will set this field to `None`
                 self.token_cursor.break_last_token = true;
                 // Use the spacing of the glued token as the spacing
                 // of the unglued second token.
@@ -1019,12 +987,6 @@ fn bump_with(&mut self, next: (Token, Spacing)) {
     /// This always-inlined version should only be used on hot code paths.
     #[inline(always)]
     fn inlined_bump_with(&mut self, (next_token, next_spacing): (Token, Spacing)) {
-        // Bumping after EOF is a bad sign, usually an infinite loop.
-        if self.prev_token.kind == TokenKind::Eof {
-            let msg = "attempted to bump the parser past EOF (may be stuck in a loop)";
-            self.span_bug(self.token.span, msg);
-        }
-
         // Update the current and previous tokens.
         self.prev_token = mem::replace(&mut self.token, next_token);
         self.token_spacing = next_spacing;
@@ -1035,8 +997,24 @@ fn inlined_bump_with(&mut self, (next_token, next_spacing): (Token, Spacing)) {
 
     /// Advance the parser by one token.
     pub fn bump(&mut self) {
-        let next_token = self.next_tok(self.token.span);
-        self.inlined_bump_with(next_token);
+        // Note: destructuring here would give nicer code, but it was found in #96210 to be slower
+        // than `.0`/`.1` access.
+        let mut next = self.token_cursor.inlined_next(self.desugar_doc_comments);
+        self.token_cursor.num_next_calls += 1;
+        // We've retrieved an token from the underlying
+        // cursor, so we no longer need to worry about
+        // an unglued token. See `break_and_eat` for more details
+        self.token_cursor.break_last_token = false;
+        if next.0.span.is_dummy() {
+            // Tweak the location for better diagnostics, but keep syntactic context intact.
+            let fallback_span = self.token.span;
+            next.0.span = fallback_span.with_ctxt(next.0.span.ctxt());
+        }
+        debug_assert!(!matches!(
+            next.0.kind,
+            token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim)
+        ));
+        self.inlined_bump_with(next)
     }
 
     /// Look-ahead `dist` tokens of `self.token` and get access to that token there.
@@ -1069,7 +1047,7 @@ pub fn look_ahead<R>(&self, dist: usize, looker: impl FnOnce(&Token) -> R) -> R
         let mut i = 0;
         let mut token = Token::dummy();
         while i < dist {
-            token = cursor.next().0;
+            token = cursor.next(/* desugar_doc_comments */ false).0;
             if matches!(
                 token.kind,
                 token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim)
@@ -1125,13 +1103,13 @@ fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, P<Expr>> {
             self.sess.gated_spans.gate(sym::inline_const, span);
         }
         self.eat_keyword(kw::Const);
-        let blk = self.parse_block()?;
+        let (attrs, blk) = self.parse_inner_attrs_and_block()?;
         let anon_const = AnonConst {
             id: DUMMY_NODE_ID,
             value: self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new()),
         };
         let blk_span = anon_const.value.span;
-        Ok(self.mk_expr(span.to(blk_span), ExprKind::ConstBlock(anon_const), AttrVec::new()))
+        Ok(self.mk_expr(span.to(blk_span), ExprKind::ConstBlock(anon_const), AttrVec::from(attrs)))
     }
 
     /// Parses mutability (`mut` or nothing).
@@ -1217,24 +1195,28 @@ fn parse_or_use_outer_attributes(
     pub(crate) fn parse_token_tree(&mut self) -> TokenTree {
         match self.token.kind {
             token::OpenDelim(..) => {
-                let depth = self.token_cursor.stack.len();
+                // Grab the tokens from this frame.
+                let frame = &self.token_cursor.frame;
+                let stream = frame.tree_cursor.stream.clone();
+                let span = frame.span;
+                let delim = frame.delim;
 
-                // We keep advancing the token cursor until we hit
-                // the matching `CloseDelim` token.
-                while !(depth == self.token_cursor.stack.len()
-                    && matches!(self.token.kind, token::CloseDelim(_)))
-                {
+                // Advance the token cursor through the entire delimited
+                // sequence. After getting the `OpenDelim` we are *within* the
+                // delimited sequence, i.e. at depth `d`. After getting the
+                // matching `CloseDelim` we are *after* the delimited sequence,
+                // i.e. at depth `d - 1`.
+                let target_depth = self.token_cursor.stack.len() - 1;
+                loop {
                     // Advance one token at a time, so `TokenCursor::next()`
                     // can capture these tokens if necessary.
                     self.bump();
+                    if self.token_cursor.stack.len() == target_depth {
+                        debug_assert!(matches!(self.token.kind, token::CloseDelim(_)));
+                        break;
+                    }
                 }
-                // We are still inside the frame corresponding
-                // to the delimited stream we captured, so grab
-                // the tokens from this frame.
-                let frame = &self.token_cursor.frame;
-                let stream = frame.tree_cursor.stream.clone();
-                let span = frame.span;
-                let delim = frame.delim;
+
                 // Consume close delimiter
                 self.bump();
                 TokenTree::Delimited(span, delim, stream)
index b45bca3d2e024acf169d5a34411a32d9430b07d7..691bfdb01a43ebfef224e141869c992c1f0ce57a 100644 (file)
 impl<'a> Parser<'a> {
     /// Checks whether a non-terminal may begin with a particular token.
     ///
-    /// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with that
-    /// token. Be conservative (return true) if not sure.
+    /// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with
+    /// that token. Be conservative (return true) if not sure. Inlined because it has a single call
+    /// site.
+    #[inline]
     pub fn nonterminal_may_begin_with(kind: NonterminalKind, token: &Token) -> bool {
         /// Checks whether the non-terminal may contain a single (non-keyword) identifier.
         fn may_be_ident(nt: &token::Nonterminal) -> bool {
@@ -95,7 +97,9 @@ fn may_be_ident(nt: &token::Nonterminal) -> bool {
         }
     }
 
-    /// Parse a non-terminal (e.g. MBE `:pat` or `:ident`).
+    /// Parse a non-terminal (e.g. MBE `:pat` or `:ident`). Inlined because there is only one call
+    /// site.
+    #[inline]
     pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, NtOrTt> {
         // Any `Nonterminal` which stores its tokens (currently `NtItem` and `NtExpr`)
         // needs to have them force-captured here.
index 436c5bd4fcac23fc7b62f5f305d0442530613c21..bb387064e27fe0e583c16f63a565cf8e96d94383 100644 (file)
@@ -523,6 +523,9 @@ fn parse_ty_bare_fn(
         let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?;
         let whole_span = lo.to(self.prev_token.span);
         if let ast::Const::Yes(span) = constness {
+            // If we ever start to allow `const fn()`, then update
+            // feature gating for `#![feature(const_extern_fn)]` to
+            // cover it.
             self.error_fn_ptr_bad_qualifier(whole_span, span, "const");
         }
         if let ast::Async::Yes { span, .. } = asyncness {
index c45326e1e6e6c483ea820894a472228e89c44363..a9444972130a85a0bef02baaf23bffb0189ef75b 100644 (file)
@@ -80,6 +80,7 @@ fn check_attributes(
                     self.check_rustc_must_implement_one_of(attr, span, target)
                 }
                 sym::target_feature => self.check_target_feature(hir_id, attr, span, target),
+                sym::thread_local => self.check_thread_local(attr, span, target),
                 sym::track_caller => {
                     self.check_track_caller(hir_id, attr.span, attrs, span, target)
                 }
@@ -523,6 +524,21 @@ fn check_target_feature(
         }
     }
 
+    /// Checks if the `#[thread_local]` attribute on `item` is valid. Returns `true` if valid.
+    fn check_thread_local(&self, attr: &Attribute, span: Span, target: Target) -> bool {
+        match target {
+            Target::ForeignStatic | Target::Static => true,
+            _ => {
+                self.tcx
+                    .sess
+                    .struct_span_err(attr.span, "attribute should be applied to a static")
+                    .span_label(span, "not a static")
+                    .emit();
+                false
+            }
+        }
+    }
+
     fn doc_attr_str_error(&self, meta: &NestedMetaItem, attr_name: &str) {
         self.tcx
             .sess
index 8c979a124667c015e860de514c343cd14c913e49..b661f6f9d729eaa31020189d6d53e01dfa971924 100644 (file)
@@ -45,8 +45,6 @@ struct MarkSymbolVisitor<'tcx> {
     live_symbols: FxHashSet<LocalDefId>,
     repr_has_repr_c: bool,
     in_pat: bool,
-    inherited_pub_visibility: bool,
-    pub_visibility: bool,
     ignore_variant_stack: Vec<DefId>,
     // maps from tuple struct constructors to tuple struct items
     struct_constructors: FxHashMap<LocalDefId, LocalDefId>,
@@ -284,33 +282,23 @@ fn visit_node(&mut self, node: Node<'tcx>) {
         }
 
         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;
         self.repr_has_repr_c = false;
-        self.inherited_pub_visibility = false;
-        self.pub_visibility = false;
         match node {
-            Node::Item(item) => {
-                self.pub_visibility = item.vis.node.is_pub();
+            Node::Item(item) => match item.kind {
+                hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
+                    let def = self.tcx.adt_def(item.def_id);
+                    self.repr_has_repr_c = def.repr().c();
 
-                match item.kind {
-                    hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
-                        let def = self.tcx.adt_def(item.def_id);
-                        self.repr_has_repr_c = def.repr().c();
-
-                        intravisit::walk_item(self, &item);
-                    }
-                    hir::ItemKind::Enum(..) => {
-                        self.inherited_pub_visibility = self.pub_visibility;
-
-                        intravisit::walk_item(self, &item);
-                    }
-                    hir::ItemKind::ForeignMod { .. } => {}
-                    _ => {
-                        intravisit::walk_item(self, &item);
-                    }
+                    intravisit::walk_item(self, &item);
                 }
-            }
+                hir::ItemKind::Enum(..) => {
+                    intravisit::walk_item(self, &item);
+                }
+                hir::ItemKind::ForeignMod { .. } => {}
+                _ => {
+                    intravisit::walk_item(self, &item);
+                }
+            },
             Node::TraitItem(trait_item) => {
                 intravisit::walk_trait_item(self, trait_item);
             }
@@ -322,8 +310,6 @@ fn visit_node(&mut self, node: Node<'tcx>) {
             }
             _ => {}
         }
-        self.pub_visibility = had_pub_visibility;
-        self.inherited_pub_visibility = had_inherited_pub_visibility;
         self.repr_has_repr_c = had_repr_c;
     }
 
@@ -354,14 +340,19 @@ fn visit_variant_data(
         _: hir::HirId,
         _: rustc_span::Span,
     ) {
+        let tcx = self.tcx;
         let has_repr_c = self.repr_has_repr_c;
-        let inherited_pub_visibility = self.inherited_pub_visibility;
-        let pub_visibility = self.pub_visibility;
-        let live_fields = def.fields().iter().filter(|f| {
-            has_repr_c || (pub_visibility && (inherited_pub_visibility || f.vis.node.is_pub()))
+        let live_fields = def.fields().iter().filter_map(|f| {
+            let def_id = tcx.hir().local_def_id(f.hir_id);
+            if has_repr_c {
+                return Some(def_id);
+            }
+            if !tcx.visibility(f.hir_id.owner).is_public() {
+                return None;
+            }
+            if tcx.visibility(def_id).is_public() { Some(def_id) } else { None }
         });
-        let hir = self.tcx.hir();
-        self.live_symbols.extend(live_fields.map(|f| hir.local_def_id(f.hir_id)));
+        self.live_symbols.extend(live_fields);
 
         intravisit::walk_struct_def(self, def);
     }
@@ -536,6 +527,10 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                         .insert(self.tcx.hir().local_def_id(ctor_hir_id), item.def_id);
                 }
             }
+            hir::ItemKind::GlobalAsm(_) => {
+                // global_asm! is always live.
+                self.worklist.push(item.def_id);
+            }
             _ => (),
         }
     }
@@ -598,8 +593,6 @@ fn live_symbols_and_ignored_derived_traits<'tcx>(
         live_symbols: Default::default(),
         repr_has_repr_c: false,
         in_pat: false,
-        inherited_pub_visibility: false,
-        pub_visibility: false,
         ignore_variant_stack: vec![],
         struct_constructors,
         ignored_derived_traits: FxHashMap::default(),
index 5a1373ad1a218dc94c0987cc3a6b2023ca0e4811..db083d0453bc05d7cc9a6924a3a3e3ca845eca8c 100644 (file)
@@ -1,21 +1,18 @@
 use rustc_ast::entry::EntryPointType;
 use rustc_errors::struct_span_err;
-use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{ForeignItem, ImplItem, Item, ItemKind, Node, TraitItem, CRATE_HIR_ID};
-use rustc_middle::hir::map::Map;
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{DefIdTree, TyCtxt};
 use rustc_session::config::{CrateType, EntryFnType};
 use rustc_session::parse::feature_err;
 use rustc_session::Session;
 use rustc_span::symbol::sym;
 use rustc_span::{Span, DUMMY_SP};
 
-struct EntryContext<'a, 'tcx> {
-    session: &'a Session,
-
-    map: Map<'tcx>,
+struct EntryContext<'tcx> {
+    tcx: TyCtxt<'tcx>,
 
     /// The function that has attribute named `main`.
     attr_main_fn: Option<(LocalDefId, Span)>,
@@ -28,10 +25,9 @@ struct EntryContext<'a, 'tcx> {
     non_main_fns: Vec<Span>,
 }
 
-impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> {
+impl<'tcx> ItemLikeVisitor<'tcx> for EntryContext<'tcx> {
     fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
-        let def_key = self.map.def_key(item.def_id);
-        let at_root = def_key.parent == Some(CRATE_DEF_INDEX);
+        let at_root = self.tcx.local_parent(item.def_id) == Some(CRATE_DEF_ID);
         find_item(item, self, at_root);
     }
 
@@ -60,13 +56,8 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
         return None;
     }
 
-    let mut ctxt = EntryContext {
-        session: tcx.sess,
-        map: tcx.hir(),
-        attr_main_fn: None,
-        start_fn: None,
-        non_main_fns: Vec::new(),
-    };
+    let mut ctxt =
+        EntryContext { tcx, attr_main_fn: None, start_fn: None, non_main_fns: Vec::new() };
 
     tcx.hir().visit_all_item_likes(&mut ctxt);
 
@@ -75,11 +66,11 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
 
 // Beware, this is duplicated in `librustc_builtin_macros/test_harness.rs`
 // (with `ast::Item`), so make sure to keep them in sync.
-fn entry_point_type(ctxt: &EntryContext<'_, '_>, item: &Item<'_>, at_root: bool) -> EntryPointType {
-    let attrs = ctxt.map.attrs(item.hir_id());
-    if ctxt.session.contains_name(attrs, sym::start) {
+fn entry_point_type(ctxt: &EntryContext<'_>, item: &Item<'_>, at_root: bool) -> EntryPointType {
+    let attrs = ctxt.tcx.hir().attrs(item.hir_id());
+    if ctxt.tcx.sess.contains_name(attrs, sym::start) {
         EntryPointType::Start
-    } else if ctxt.session.contains_name(attrs, sym::rustc_main) {
+    } else if ctxt.tcx.sess.contains_name(attrs, sym::rustc_main) {
         EntryPointType::MainAttr
     } else if item.ident.name == sym::main {
         if at_root {
@@ -98,16 +89,16 @@ fn throw_attr_err(sess: &Session, span: Span, attr: &str) {
         .emit();
 }
 
-fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
+fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_>, at_root: bool) {
     match entry_point_type(ctxt, item, at_root) {
         EntryPointType::None => (),
         _ if !matches!(item.kind, ItemKind::Fn(..)) => {
-            let attrs = ctxt.map.attrs(item.hir_id());
-            if let Some(attr) = ctxt.session.find_by_name(attrs, sym::start) {
-                throw_attr_err(&ctxt.session, attr.span, "start");
+            let attrs = ctxt.tcx.hir().attrs(item.hir_id());
+            if let Some(attr) = ctxt.tcx.sess.find_by_name(attrs, sym::start) {
+                throw_attr_err(&ctxt.tcx.sess, attr.span, "start");
             }
-            if let Some(attr) = ctxt.session.find_by_name(attrs, sym::rustc_main) {
-                throw_attr_err(&ctxt.session, attr.span, "rustc_main");
+            if let Some(attr) = ctxt.tcx.sess.find_by_name(attrs, sym::rustc_main) {
+                throw_attr_err(&ctxt.tcx.sess, attr.span, "rustc_main");
             }
         }
         EntryPointType::MainNamed => (),
@@ -119,7 +110,7 @@ fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
                 ctxt.attr_main_fn = Some((item.def_id, item.span));
             } else {
                 struct_span_err!(
-                    ctxt.session,
+                    ctxt.tcx.sess,
                     item.span,
                     E0137,
                     "multiple functions with a `#[main]` attribute"
@@ -133,7 +124,7 @@ fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
             if ctxt.start_fn.is_none() {
                 ctxt.start_fn = Some((item.def_id, item.span));
             } else {
-                struct_span_err!(ctxt.session, item.span, E0138, "multiple `start` functions")
+                struct_span_err!(ctxt.tcx.sess, item.span, E0138, "multiple `start` functions")
                     .span_label(ctxt.start_fn.unwrap().1, "previous `#[start]` function here")
                     .span_label(item.span, "multiple `start` functions")
                     .emit();
@@ -142,7 +133,7 @@ fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
     }
 }
 
-fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(DefId, EntryFnType)> {
+fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, EntryFnType)> {
     if let Some((def_id, _)) = visitor.start_fn {
         Some((def_id.to_def_id(), EntryFnType::Start))
     } else if let Some((def_id, _)) = visitor.attr_main_fn {
@@ -177,7 +168,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(De
     }
 }
 
-fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) {
+fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) {
     let sp = tcx.def_span(CRATE_DEF_ID);
     if *tcx.sess.parse_sess.reached_eof.borrow() {
         // There's an unclosed brace that made the parser reach `Eof`, we shouldn't complain about
index 56755d68686e3d27b4c70df96de00d5ef82db02d..379a6827c8aac5d3d41075a5aa1998ee7d4cec24 100644 (file)
@@ -1,7 +1,7 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lock;
 use rustc_hir as hir;
-use rustc_hir::def_id::{LocalDefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
 use rustc_hir::intravisit;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{HirId, ItemLocalId};
@@ -89,7 +89,7 @@ fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(&mut self, owner: LocalDefId,
         self.owner = Some(owner);
         walk(self);
 
-        if owner.local_def_index == CRATE_DEF_INDEX {
+        if owner == CRATE_DEF_ID {
             return;
         }
 
index 027eac16bad305d5629bf6a1ce6ce6ee2c96603d..7028fc4412648832b09dc57e90ae1aa1b8e35a29 100644 (file)
@@ -1,3 +1,4 @@
+use hir::intravisit::walk_inline_asm;
 use rustc_ast::InlineAsmTemplatePiece;
 use rustc_data_structures::stable_set::FxHashSet;
 use rustc_errors::struct_span_err;
@@ -483,7 +484,10 @@ fn check_asm(&self, asm: &hir::InlineAsm<'tcx>, hir_id: hir::HirId) {
                         );
                     }
                 }
-                hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::Sym { .. } => {}
+                // These are checked in ItemVisitor.
+                hir::InlineAsmOperand::Const { .. }
+                | hir::InlineAsmOperand::SymFn { .. }
+                | hir::InlineAsmOperand::SymStatic { .. } => {}
             }
         }
     }
@@ -498,6 +502,42 @@ fn visit_nested_body(&mut self, body_id: hir::BodyId) {
         ExprVisitor { tcx: self.tcx, param_env, typeck_results }.visit_body(body);
         self.visit_body(body);
     }
+
+    fn visit_inline_asm(&mut self, asm: &'tcx hir::InlineAsm<'tcx>, id: hir::HirId) {
+        for (op, op_sp) in asm.operands.iter() {
+            match *op {
+                // These are checked in ExprVisitor.
+                hir::InlineAsmOperand::In { .. }
+                | hir::InlineAsmOperand::Out { .. }
+                | hir::InlineAsmOperand::InOut { .. }
+                | hir::InlineAsmOperand::SplitInOut { .. } => {}
+                // No special checking is needed for these:
+                // - Typeck has checked that Const operands are integers.
+                // - AST lowering guarantees that SymStatic points to a static.
+                hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymStatic { .. } => {}
+                // Check that sym actually points to a function. Later passes
+                // depend on this.
+                hir::InlineAsmOperand::SymFn { anon_const } => {
+                    let ty = self.tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
+                    match ty.kind() {
+                        ty::Never | ty::Error(_) => {}
+                        ty::FnDef(..) => {}
+                        _ => {
+                            let mut err =
+                                self.tcx.sess.struct_span_err(*op_sp, "invalid `sym` operand");
+                            err.span_label(
+                                self.tcx.hir().span(anon_const.body.hir_id),
+                                &format!("is {} `{}`", ty.kind().article(), ty),
+                            );
+                            err.help("`sym` operands must refer to either a function or a static");
+                            err.emit();
+                        }
+                    };
+                }
+            }
+        }
+        walk_inline_asm(self, asm, id);
+    }
 }
 
 impl<'tcx> Visitor<'tcx> for ExprVisitor<'tcx> {
index 0c934ecc91376b121e4b7f648280c51cbbcc1b69..18d9bdf8e1792d7b86d6442bbc9e72fc07b6e954 100644 (file)
@@ -12,8 +12,8 @@
 
 use rustc_errors::{pluralize, struct_span_err};
 use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::lang_items::{extract, GenericRequirement, ITEM_REFS};
 use rustc_hir::{HirId, LangItem, LanguageItems, Target};
 use rustc_middle::ty::TyCtxt;
@@ -27,28 +27,6 @@ struct LanguageItemCollector<'tcx> {
     tcx: TyCtxt<'tcx>,
 }
 
-impl<'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> {
-    fn visit_item(&mut self, item: &hir::Item<'_>) {
-        self.check_for_lang(Target::from_item(item), item.hir_id());
-
-        if let hir::ItemKind::Enum(def, ..) = &item.kind {
-            for variant in def.variants {
-                self.check_for_lang(Target::Variant, variant.id);
-            }
-        }
-    }
-
-    fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
-        self.check_for_lang(Target::from_trait_item(trait_item), trait_item.hir_id())
-    }
-
-    fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
-        self.check_for_lang(target_from_impl_item(self.tcx, impl_item), impl_item.hir_id())
-    }
-
-    fn visit_foreign_item(&mut self, _: &hir::ForeignItem<'_>) {}
-}
-
 impl<'tcx> LanguageItemCollector<'tcx> {
     fn new(tcx: TyCtxt<'tcx>) -> LanguageItemCollector<'tcx> {
         LanguageItemCollector { tcx, items: LanguageItems::new() }
@@ -259,7 +237,32 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems {
     }
 
     // Collect lang items in this crate.
-    tcx.hir().visit_all_item_likes(&mut collector);
+    let crate_items = tcx.hir_crate_items(());
+
+    for id in crate_items.items() {
+        collector.check_for_lang(Target::from_def_kind(tcx.hir().def_kind(id.def_id)), id.hir_id());
+
+        if matches!(tcx.hir().def_kind(id.def_id), DefKind::Enum) {
+            let item = tcx.hir().item(id);
+            if let hir::ItemKind::Enum(def, ..) = &item.kind {
+                for variant in def.variants {
+                    collector.check_for_lang(Target::Variant, variant.id);
+                }
+            }
+        }
+    }
+
+    // FIXME: avoid calling trait_item() when possible
+    for id in crate_items.trait_items() {
+        let item = tcx.hir().trait_item(id);
+        collector.check_for_lang(Target::from_trait_item(item), item.hir_id())
+    }
+
+    // FIXME: avoid calling impl_item() when possible
+    for id in crate_items.impl_items() {
+        let item = tcx.hir().impl_item(id);
+        collector.check_for_lang(target_from_impl_item(tcx, item), item.hir_id())
+    }
 
     // Extract out the found lang items.
     let LanguageItemCollector { mut items, .. } = collector;
index 7298aba7e8763ddf4be9295dacf8e8fafd430f8e..99ea73fe2fe10bdb9304dbf8e2f60a13d8f8b464 100644 (file)
@@ -1043,7 +1043,8 @@ fn propagate_through_expr(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNod
                     match op {
                         hir::InlineAsmOperand::In { .. }
                         | hir::InlineAsmOperand::Const { .. }
-                        | hir::InlineAsmOperand::Sym { .. } => {}
+                        | hir::InlineAsmOperand::SymFn { .. }
+                        | hir::InlineAsmOperand::SymStatic { .. } => {}
                         hir::InlineAsmOperand::Out { expr, .. } => {
                             if let Some(expr) = expr {
                                 succ = self.write_place(expr, succ, ACC_WRITE);
@@ -1064,8 +1065,7 @@ fn propagate_through_expr(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNod
                 let mut succ = succ;
                 for (op, _op_sp) in asm.operands.iter().rev() {
                     match op {
-                        hir::InlineAsmOperand::In { expr, .. }
-                        | hir::InlineAsmOperand::Sym { expr, .. } => {
+                        hir::InlineAsmOperand::In { expr, .. } => {
                             succ = self.propagate_through_expr(expr, succ)
                         }
                         hir::InlineAsmOperand::Out { expr, .. } => {
@@ -1082,7 +1082,9 @@ fn propagate_through_expr(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNod
                             }
                             succ = self.propagate_through_expr(in_expr, succ);
                         }
-                        hir::InlineAsmOperand::Const { .. } => {}
+                        hir::InlineAsmOperand::Const { .. }
+                        | hir::InlineAsmOperand::SymFn { .. }
+                        | hir::InlineAsmOperand::SymStatic { .. } => {}
                     }
                 }
                 succ
index af78fd5a6f2120b435f428dc755d8698eedbfabb..e85720952da7a4dc81616ff3b19de86995708da4 100644 (file)
@@ -252,7 +252,9 @@ fn check_inline_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>, span: Span) {
             .operands
             .iter()
             .filter_map(|&(ref op, op_sp)| match op {
-                InlineAsmOperand::Const { .. } | InlineAsmOperand::Sym { .. } => None,
+                InlineAsmOperand::Const { .. }
+                | InlineAsmOperand::SymFn { .. }
+                | InlineAsmOperand::SymStatic { .. } => None,
                 InlineAsmOperand::In { .. }
                 | InlineAsmOperand::Out { .. }
                 | InlineAsmOperand::InOut { .. }
index 01ba9e35c24dc65c22e1ba4d79e9ef381214cfbc..35a858cb86c3f1851f40e4b266c2571bf0fc5342 100644 (file)
@@ -6,7 +6,7 @@
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
 use rustc_hir::hir_id::CRATE_HIR_ID;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{FieldDef, Generics, HirId, Item, TraitRef, Ty, TyKind, Variant};
@@ -703,7 +703,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                 let Some(cnum) = self.tcx.extern_mod_stmt_cnum(item.def_id) else {
                     return;
                 };
-                let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
+                let def_id = cnum.as_def_id();
                 self.tcx.check_stability(def_id, Some(item.hir_id()), item.span, None);
             }
 
index 6b73c95011940a1cc0c3883574ab46d33420d44e..5411946343b74c7d2cc4f2f9e7a0761a09650cd8 100644 (file)
@@ -2,20 +2,11 @@
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
-use rustc_hir as hir;
-use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::lang_items::{self, LangItem};
 use rustc_hir::weak_lang_items::WEAK_ITEMS_REFS;
 use rustc_middle::middle::lang_items::required;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::CrateType;
-use rustc_span::symbol::Symbol;
-use rustc_span::Span;
-
-struct Context<'a, 'tcx> {
-    tcx: TyCtxt<'tcx>,
-    items: &'a mut lang_items::LanguageItems,
-}
 
 /// Checks the crate for usage of weak lang items, returning a vector of all the
 /// language items required by this crate, but not defined yet.
@@ -30,10 +21,28 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem
         items.missing.push(LangItem::EhCatchTypeinfo);
     }
 
-    {
-        let mut cx = Context { tcx, items };
-        tcx.hir().visit_all_item_likes(&mut cx.as_deep_visitor());
+    let crate_items = tcx.hir_crate_items(());
+    for id in crate_items.foreign_items() {
+        let attrs = tcx.hir().attrs(id.hir_id());
+        if let Some((lang_item, _)) = lang_items::extract(attrs) {
+            if let Some(&item) = WEAK_ITEMS_REFS.get(&lang_item) {
+                if items.require(item).is_err() {
+                    items.missing.push(item);
+                }
+            } else {
+                let span = tcx.def_span(id.def_id);
+                struct_span_err!(
+                    tcx.sess,
+                    span,
+                    E0264,
+                    "unknown external lang item: `{}`",
+                    lang_item
+                )
+                .emit();
+            }
+        }
     }
+
     verify(tcx, items);
 }
 
@@ -80,26 +89,3 @@ fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) {
         }
     }
 }
-
-impl<'a, 'tcx> Context<'a, 'tcx> {
-    fn register(&mut self, name: Symbol, span: Span) {
-        if let Some(&item) = WEAK_ITEMS_REFS.get(&name) {
-            if self.items.require(item).is_err() {
-                self.items.missing.push(item);
-            }
-        } else {
-            struct_span_err!(self.tcx.sess, span, E0264, "unknown external lang item: `{}`", name)
-                .emit();
-        }
-    }
-}
-
-impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
-    fn visit_foreign_item(&mut self, i: &hir::ForeignItem<'_>) {
-        let attrs = self.tcx.hir().attrs(i.hir_id());
-        if let Some((lang_item, _)) = lang_items::extract(attrs) {
-            self.register(lang_item, i.span);
-        }
-        intravisit::walk_foreign_item(self, i)
-    }
-}
index 0ce97de413496db7146557dd8e4681183a3acbb6..5f9a03575575c6ad9767be7764e4ce6d82899083 100644 (file)
@@ -295,28 +295,6 @@ fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visib
     if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 }
 }
 
-////////////////////////////////////////////////////////////////////////////////
-/// Visitor used to determine if pub(restricted) is used anywhere in the crate.
-///
-/// This is done so that `private_in_public` warnings can be turned into hard errors
-/// in crates that have been updated to use pub(restricted).
-////////////////////////////////////////////////////////////////////////////////
-struct PubRestrictedVisitor<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    has_pub_restricted: bool,
-}
-
-impl<'tcx> Visitor<'tcx> for PubRestrictedVisitor<'tcx> {
-    type NestedFilter = nested_filter::All;
-
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
-    }
-    fn visit_vis(&mut self, vis: &'tcx hir::Visibility<'tcx>) {
-        self.has_pub_restricted = self.has_pub_restricted || vis.node.is_pub_restricted();
-    }
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 /// Visitor used to determine impl visibility and reachability.
 ////////////////////////////////////////////////////////////////////////////////
@@ -682,7 +660,9 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                     self.update_with_hir_id(ctor_hir_id, item_level);
                 }
                 for field in def.fields() {
-                    if field.vis.node.is_pub() {
+                    let def_id = self.tcx.hir().local_def_id(field.hir_id);
+                    let vis = self.tcx.visibility(def_id);
+                    if vis.is_public() {
                         self.update_with_hir_id(field.hir_id, item_level);
                     }
                 }
@@ -1361,7 +1341,7 @@ fn path_is_private_type(&self, path: &hir::Path<'_>) -> bool {
             // .. and it corresponds to a private type in the AST (this returns
             // `None` for type parameters).
             match self.tcx.hir().find(self.tcx.hir().local_def_id_to_hir_id(did)) {
-                Some(Node::Item(item)) => !item.vis.node.is_pub(),
+                Some(Node::Item(_)) => !self.tcx.visibility(did).is_public(),
                 Some(_) | None => false,
             }
         } else {
@@ -1383,8 +1363,8 @@ fn check_generic_bound(&mut self, bound: &hir::GenericBound<'_>) {
         }
     }
 
-    fn item_is_public(&self, def_id: LocalDefId, vis: &hir::Visibility<'_>) -> bool {
-        self.access_levels.is_reachable(def_id) || vis.node.is_pub()
+    fn item_is_public(&self, def_id: LocalDefId) -> bool {
+        self.access_levels.is_reachable(def_id) || self.tcx.visibility(def_id).is_public()
     }
 }
 
@@ -1519,8 +1499,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                                 let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
                                 match impl_item.kind {
                                     hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..)
-                                        if self
-                                            .item_is_public(impl_item.def_id, &impl_item.vis) =>
+                                        if self.item_is_public(impl_item.def_id) =>
                                     {
                                         intravisit::walk_impl_item(self, impl_item)
                                     }
@@ -1591,7 +1570,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
             hir::ItemKind::TyAlias(..) => return,
 
             // Not at all public, so we don't care.
-            _ if !self.item_is_public(item.def_id, &item.vis) => {
+            _ if !self.item_is_public(item.def_id) => {
                 return;
             }
 
@@ -1655,7 +1634,9 @@ fn visit_variant(
     }
 
     fn visit_field_def(&mut self, s: &'tcx hir::FieldDef<'tcx>) {
-        if s.vis.node.is_pub() || self.in_variant {
+        let def_id = self.tcx.hir().local_def_id(s.hir_id);
+        let vis = self.tcx.visibility(def_id);
+        if vis.is_public() || self.in_variant {
             intravisit::walk_field_def(self, s);
         }
     }
@@ -1680,7 +1661,6 @@ struct SearchInterfaceForPrivateItemsVisitor<'tcx> {
     item_def_id: LocalDefId,
     /// The visitor checks that each component type is at least this visible.
     required_visibility: ty::Visibility,
-    has_pub_restricted: bool,
     has_old_errors: bool,
     in_assoc_ty: bool,
 }
@@ -1769,7 +1749,10 @@ fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display)
             };
             let make_msg = || format!("{} {} `{}` in public interface", vis_descr, kind, descr);
             let span = self.tcx.def_span(self.item_def_id.to_def_id());
-            if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty {
+            if self.has_old_errors
+                || self.in_assoc_ty
+                || self.tcx.resolutions(()).has_pub_restricted
+            {
                 let mut err = if kind == "trait" {
                     struct_span_err!(self.tcx.sess, span, E0445, "{}", make_msg())
                 } else {
@@ -1828,7 +1811,6 @@ fn visit_def_id(
 
 struct PrivateItemsInPublicInterfacesVisitor<'tcx> {
     tcx: TyCtxt<'tcx>,
-    has_pub_restricted: bool,
     old_error_set_ancestry: LocalDefIdSet,
 }
 
@@ -1842,7 +1824,6 @@ fn check(
             tcx: self.tcx,
             item_def_id: def_id,
             required_visibility,
-            has_pub_restricted: self.has_pub_restricted,
             has_old_errors: self.old_error_set_ancestry.contains(&def_id),
             in_assoc_ty: false,
         }
@@ -1994,19 +1975,16 @@ fn visibility(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Visibility {
             match tcx.hir().get(hir_id) {
                 // Unique types created for closures participate in type privacy checking.
                 // They have visibilities inherited from the module they are defined in.
-                Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => {
-                    ty::Visibility::Restricted(tcx.parent_module(hir_id).to_def_id())
-                }
-                // - AST lowering may clone `use` items and the clones don't
+                Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. })
+                // - AST lowering creates dummy `use` items which don't
                 //   get their entries in the resolver's visibility table.
                 // - AST lowering also creates opaque type items with inherited visibilities.
                 //   Visibility on them should have no effect, but to avoid the visibility
                 //   query failing on some items, we provide it for opaque types as well.
-                Node::Item(hir::Item {
-                    vis,
-                    kind: hir::ItemKind::Use(..) | hir::ItemKind::OpaqueTy(..),
+                | Node::Item(hir::Item {
+                    kind: hir::ItemKind::Use(_, hir::UseKind::ListStem) | hir::ItemKind::OpaqueTy(..),
                     ..
-                }) => ty::Visibility::from_hir(vis, hir_id, tcx),
+                }) => ty::Visibility::Restricted(tcx.parent_module(hir_id).to_def_id()),
                 // Visibilities of trait impl items are inherited from their traits
                 // and are not filled in resolve.
                 Node::ImplItem(impl_item) => {
@@ -2083,12 +2061,6 @@ fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) {
     };
     tcx.hir().walk_toplevel_module(&mut visitor);
 
-    let has_pub_restricted = {
-        let mut pub_restricted_visitor = PubRestrictedVisitor { tcx, has_pub_restricted: false };
-        tcx.hir().walk_toplevel_module(&mut pub_restricted_visitor);
-        pub_restricted_visitor.has_pub_restricted
-    };
-
     let mut old_error_set_ancestry = HirIdSet::default();
     for mut id in visitor.old_error_set.iter().copied() {
         loop {
@@ -2106,7 +2078,6 @@ fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) {
     // Check for private types and traits in public interfaces.
     let mut visitor = PrivateItemsInPublicInterfacesVisitor {
         tcx,
-        has_pub_restricted,
         // Only definition IDs are ever searched in `old_error_set_ancestry`,
         // so we can filter away all non-definition IDs at this point.
         old_error_set_ancestry: old_error_set_ancestry
index acccf43f06285f59b8421227b0373d47bbbfac26..b20aa7b53468aa0f329071cde63314849288ccc1 100644 (file)
@@ -1,7 +1,7 @@
 use measureme::{StringComponent, StringId};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::profiling::SelfProfiler;
-use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathData;
 use rustc_middle::ty::{TyCtxt, WithOptConstParam};
 use rustc_query_system::query::QueryCache;
@@ -143,7 +143,7 @@ fn spec_to_self_profile_string(
         &self,
         builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
     ) -> StringId {
-        builder.def_id_to_string_id(DefId { krate: *self, index: CRATE_DEF_INDEX })
+        builder.def_id_to_string_id(self.as_def_id())
     }
 }
 
index 54e8c03156d558448b64e58721c885d99457b7bd..291b6645d9aa6d00a185cf9364e83f2908a46e22 100644 (file)
@@ -23,7 +23,7 @@
 use rustc_expand::base::SyntaxExtension;
 use rustc_expand::expand::AstFragment;
 use rustc_hir::def::{self, *};
-use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
 use rustc_metadata::creader::LoadedMacro;
 use rustc_middle::bug;
 use rustc_middle::metadata::ModChild;
@@ -140,8 +140,8 @@ pub fn expect_module(&mut self, def_id: DefId) -> Module<'a> {
                     let parent = def_key.parent.map(|index| {
                         self.get_nearest_non_block_module(DefId { index, krate: def_id.krate })
                     });
-                    let name = if def_id.index == CRATE_DEF_INDEX {
-                        self.cstore().crate_name(def_id.krate)
+                    let name = if let Some(cnum) = def_id.as_crate_root() {
+                        self.cstore().crate_name(cnum)
                     } else {
                         def_key.disambiguated_data.data.get_opt_name().expect("module without name")
                     };
@@ -250,7 +250,7 @@ fn try_resolve_visibility<'ast>(
         match vis.kind {
             ast::VisibilityKind::Public => Ok(ty::Visibility::Public),
             ast::VisibilityKind::Crate(..) => {
-                Ok(ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)))
+                Ok(ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id()))
             }
             ast::VisibilityKind::Inherited => {
                 Ok(match self.parent_scope.module.kind {
@@ -265,6 +265,8 @@ fn try_resolve_visibility<'ast>(
                 })
             }
             ast::VisibilityKind::Restricted { ref path, id, .. } => {
+                // Make `PRIVATE_IN_PUBLIC` lint a hard error.
+                self.r.has_pub_restricted = true;
                 // For visibilities we are not ready to provide correct implementation of "uniform
                 // paths" right now, so on 2018 edition we only allow module-relative paths for now.
                 // On 2015 edition visibilities are resolved as crate-relative by default,
@@ -458,6 +460,14 @@ fn build_reduced_graph_for_use_tree(
                 let mut source = module_path.pop().unwrap();
                 let mut type_ns_only = false;
 
+                self.r.visibilities.insert(self.r.local_def_id(id), vis);
+                if id1 != ast::DUMMY_NODE_ID {
+                    self.r.visibilities.insert(self.r.local_def_id(id1), vis);
+                }
+                if id2 != ast::DUMMY_NODE_ID {
+                    self.r.visibilities.insert(self.r.local_def_id(id2), vis);
+                }
+
                 if nested {
                     // Correctly handle `self`
                     if source.ident.name == kw::SelfLower {
@@ -521,11 +531,10 @@ fn build_reduced_graph_for_use_tree(
                         // while the current crate doesn't have a valid `crate_name`.
                         if crate_name != kw::Empty {
                             // `crate_name` should not be interpreted as relative.
-                            module_path.push(Segment {
-                                ident: Ident { name: kw::PathRoot, span: source.ident.span },
-                                id: Some(self.r.next_node_id()),
-                                has_generic_args: false,
-                            });
+                            module_path.push(Segment::from_ident_and_id(
+                                Ident { name: kw::PathRoot, span: source.ident.span },
+                                self.r.next_node_id(),
+                            ));
                             source.ident.name = crate_name;
                         }
                         if rename.is_none() {
@@ -581,6 +590,7 @@ fn build_reduced_graph_for_use_tree(
                     is_prelude: self.r.session.contains_name(&item.attrs, sym::prelude_import),
                     max_vis: Cell::new(ty::Visibility::Invisible),
                 };
+                self.r.visibilities.insert(self.r.local_def_id(id), vis);
                 self.add_import(prefix, kind, use_tree.span, id, item, root_span, item.id, vis);
             }
             ast::UseTreeKind::Nested(ref items) => {
@@ -759,7 +769,7 @@ fn build_reduced_graph_for_item(&mut self, item: &'b Item) {
                     let mut ctor_vis = if vis == ty::Visibility::Public
                         && self.r.session.contains_name(&item.attrs, sym::non_exhaustive)
                     {
-                        ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
+                        ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id())
                     } else {
                         vis
                     };
@@ -1108,7 +1118,7 @@ fn process_macro_use_imports(&mut self, item: &Item, module: Module<'a>) -> bool
                 root_span: span,
                 span,
                 module_path: Vec::new(),
-                vis: Cell::new(ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))),
+                vis: Cell::new(ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id())),
                 used: Cell::new(false),
             })
         };
@@ -1244,7 +1254,7 @@ fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'a> {
             let vis = if is_macro_export {
                 ty::Visibility::Public
             } else {
-                ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
+                ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id())
             };
             let binding = (res, vis, span, expansion).to_name_binding(self.r.arenas);
             self.r.set_binding_parent_module(binding, parent_scope.module);
@@ -1490,7 +1500,7 @@ fn visit_variant(&mut self, variant: &'b ast::Variant) {
         let ctor_vis = if vis == ty::Visibility::Public
             && self.r.session.contains_name(&variant.attrs, sym::non_exhaustive)
         {
-            ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
+            ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id())
         } else {
             vis
         };
index 8ea5dca6f108a64ae7a5cabe661fc66059c1a2f6..1e8cca6122c4c58724bad81648e96417624a6073 100644 (file)
@@ -133,8 +133,10 @@ fn visit_item(&mut self, i: &'a Item) {
     }
 
     fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
-        if let FnKind::Fn(_, _, sig, _, body) = fn_kind {
+        if let FnKind::Fn(_, _, sig, _, generics, body) = fn_kind {
             if let Async::Yes { closure_id, return_impl_trait_id, .. } = sig.header.asyncness {
+                self.visit_generics(generics);
+
                 let return_impl_trait_id =
                     self.create_def(return_impl_trait_id, DefPathData::ImplTrait, span);
 
index d979311171be66c657192e895dc88a8e3a442dd4..9bbecf104e55e897964cc1838e9e31bb3a39154a 100644 (file)
@@ -10,7 +10,7 @@
 use rustc_feature::BUILTIN_ATTRIBUTES;
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PerNS};
-use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::PrimTy;
 use rustc_middle::bug;
 use rustc_middle::ty::DefIdTree;
@@ -1012,6 +1012,12 @@ fn add_suggestion_for_duplicate_nested_use(
                 err.span_label(trait_item_span, "item in trait");
                 err
             }
+            ResolutionError::InvalidAsmSym => {
+                let mut err = self.session.struct_span_err(span, "invalid `sym` operand");
+                err.span_label(span, "is a local variable");
+                err.help("`sym` operands must refer to either a function or a static");
+                err
+            }
         }
     }
 
@@ -1161,7 +1167,7 @@ fn early_lookup_typo_candidate(
                 }
                 Scope::ExternPrelude => {
                     suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, _)| {
-                        let res = Res::Def(DefKind::Mod, DefId::local(CRATE_DEF_INDEX));
+                        let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
                         filter_fn(res).then_some(TypoSuggestion::typo_from_res(ident.name, res))
                     }));
                 }
index 25ab3f7dacf905aa7bf48680616d1ee19cd55620..84fe0ec83d26c3c075dc332a7b7982f03d8e655a 100644 (file)
@@ -1182,6 +1182,12 @@ fn validate_res_from_ribs(
                             }
                             return Res::Err;
                         }
+                        InlineAsmSymRibKind => {
+                            if let Some(span) = finalize {
+                                self.report_error(span, InvalidAsmSym);
+                            }
+                            return Res::Err;
+                        }
                     }
                 }
                 if let Some((span, res_err)) = res_err {
@@ -1242,6 +1248,22 @@ fn validate_res_from_ribs(
                             }
                             return Res::Err;
                         }
+                        InlineAsmSymRibKind => {
+                            let features = self.session.features_untracked();
+                            if !features.generic_const_exprs {
+                                if let Some(span) = finalize {
+                                    self.report_error(
+                                        span,
+                                        ResolutionError::ParamInNonTrivialAnonConst {
+                                            name: rib_ident.name,
+                                            is_type: true,
+                                        },
+                                    );
+                                }
+                                return Res::Err;
+                            }
+                            continue;
+                        }
                     };
 
                     if let Some(span) = finalize {
@@ -1306,6 +1328,22 @@ fn validate_res_from_ribs(
                             }
                             return Res::Err;
                         }
+                        InlineAsmSymRibKind => {
+                            let features = self.session.features_untracked();
+                            if !features.generic_const_exprs {
+                                if let Some(span) = finalize {
+                                    self.report_error(
+                                        span,
+                                        ResolutionError::ParamInNonTrivialAnonConst {
+                                            name: rib_ident.name,
+                                            is_type: false,
+                                        },
+                                    );
+                                }
+                                return Res::Err;
+                            }
+                            continue;
+                        }
                     };
 
                     // This was an attempt to use a const parameter outside its scope.
@@ -1364,7 +1402,7 @@ fn validate_res_from_ribs(
         let mut allow_super = true;
         let mut second_binding = None;
 
-        for (i, &Segment { ident, id, has_generic_args: _ }) in path.iter().enumerate() {
+        for (i, &Segment { ident, id, .. }) in path.iter().enumerate() {
             debug!("resolve_path ident {} {:?} {:?}", i, ident, id);
             let record_segment_res = |this: &mut Self, res| {
                 if finalize.is_some() {
index aab0c1f97717c79b6fe3117c2543838181858dbf..01dc727737a5a53e2c0891b11b2aa19ae2da5978 100644 (file)
@@ -310,18 +310,23 @@ fn update_resolution<T, F>(&mut self, module: Module<'a>, key: BindingKey, f: F)
         t
     }
 
-    // Define a "dummy" resolution containing a Res::Err as a placeholder for a
-    // failed resolution
+    // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed resolution,
+    // also mark such failed imports as used to avoid duplicate diagnostics.
     fn import_dummy_binding(&mut self, import: &'a Import<'a>) {
-        if let ImportKind::Single { target, .. } = import.kind {
+        if let ImportKind::Single { target, ref target_bindings, .. } = import.kind {
+            if target_bindings.iter().any(|binding| binding.get().is_some()) {
+                return; // Has resolution, do not create the dummy binding
+            }
             let dummy_binding = self.dummy_binding;
             let dummy_binding = self.import(dummy_binding, import);
             self.per_ns(|this, ns| {
                 let key = this.new_key(target, ns);
                 let _ = this.try_define(import.parent_scope.module, key, dummy_binding);
             });
-            // Consider erroneous imports used to avoid duplicate diagnostics.
             self.record_use(target, dummy_binding, false);
+        } else if import.imported_module.get().is_none() {
+            import.used.set(true);
+            self.used_imports.insert(import.id);
         }
     }
 }
@@ -386,7 +391,13 @@ pub fn finalize_imports(&mut self) {
             .map(|i| (false, i))
             .chain(indeterminate_imports.into_iter().map(|i| (true, i)))
         {
-            if let Some(err) = self.finalize_import(import) {
+            let unresolved_import_error = self.finalize_import(import);
+
+            // If this import is unresolved then create a dummy import
+            // resolution for it so that later resolve stages won't complain.
+            self.r.import_dummy_binding(import);
+
+            if let Some(err) = unresolved_import_error {
                 if let ImportKind::Single { source, ref source_bindings, .. } = import.kind {
                     if source.name == kw::SelfLower {
                         // Silence `unresolved import` error if E0429 is already emitted
@@ -396,9 +407,6 @@ pub fn finalize_imports(&mut self) {
                     }
                 }
 
-                // If the error is a single failed import then create a "fake" import
-                // resolution for it so that later resolve stages won't complain.
-                self.r.import_dummy_binding(import);
                 if prev_root_id.as_u32() != 0
                     && prev_root_id.as_u32() != import.root_id.as_u32()
                     && !errors.is_empty()
@@ -418,8 +426,6 @@ pub fn finalize_imports(&mut self) {
                     prev_root_id = import.root_id;
                 }
             } else if is_indeterminate {
-                // Consider erroneous imports used to avoid duplicate diagnostics.
-                self.r.used_imports.insert(import.id);
                 let path = import_path_to_string(
                     &import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
                     &import.kind,
@@ -553,26 +559,23 @@ fn resolve_import(&mut self, import: &'b Import<'b>) -> bool {
                     Err(Undetermined) => indeterminate = true,
                     // Don't update the resolution, because it was never added.
                     Err(Determined) if target.name == kw::Underscore => {}
-                    Err(Determined) => {
+                    Ok(binding) if binding.is_importable() => {
+                        let imported_binding = this.import(binding, import);
+                        target_bindings[ns].set(Some(imported_binding));
+                        this.define(parent, target, ns, imported_binding);
+                    }
+                    source_binding @ (Ok(..) | Err(Determined)) => {
+                        if source_binding.is_ok() {
+                            let msg = format!("`{}` is not directly importable", target);
+                            struct_span_err!(this.session, import.span, E0253, "{}", &msg)
+                                .span_label(import.span, "cannot be imported directly")
+                                .emit();
+                        }
                         let key = this.new_key(target, ns);
                         this.update_resolution(parent, key, |_, resolution| {
                             resolution.single_imports.remove(&Interned::new_unchecked(import));
                         });
                     }
-                    Ok(binding) if !binding.is_importable() => {
-                        let msg = format!("`{}` is not directly importable", target);
-                        struct_span_err!(this.session, import.span, E0253, "{}", &msg)
-                            .span_label(import.span, "cannot be imported directly")
-                            .emit();
-                        // Do not import this illegal binding. Import a dummy binding and pretend
-                        // everything is fine
-                        this.import_dummy_binding(import);
-                    }
-                    Ok(binding) => {
-                        let imported_binding = this.import(binding, import);
-                        target_bindings[ns].set(Some(imported_binding));
-                        this.define(parent, target, ns, imported_binding);
-                    }
                 }
             }
         });
@@ -605,10 +608,6 @@ fn finalize_import(&mut self, import: &'b Import<'b>) -> Option<UnresolvedImport
         );
         let no_ambiguity = self.r.ambiguity_errors.len() == prev_ambiguity_errors_len;
         import.vis.set(orig_vis);
-        if let PathResult::Failed { .. } | PathResult::NonModule(..) = path_res {
-            // Consider erroneous imports used to avoid duplicate diagnostics.
-            self.r.used_imports.insert(import.id);
-        }
         let module = match path_res {
             PathResult::Module(module) => {
                 // Consistency checks, analogous to `finalize_macro_resolutions`.
@@ -872,7 +871,6 @@ fn finalize_import(&mut self, import: &'b Import<'b>) -> Option<UnresolvedImport
                 })
             } else {
                 // `resolve_ident_in_module` reported a privacy error.
-                self.r.import_dummy_binding(import);
                 None
             };
         }
index f27b60e889f6b9c10154ccfc2806569cedd524f5..7635ad9bd87bf145a752cf87c004b0e74f723115 100644 (file)
 use rustc_errors::DiagnosticId;
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS};
-use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
 use rustc_hir::{PrimTy, TraitCandidate};
+use rustc_middle::ty::DefIdTree;
 use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::Span;
+use rustc_span::{BytePos, Span};
 use smallvec::{smallvec, SmallVec};
 
 use rustc_span::source_map::{respan, Spanned};
@@ -140,6 +141,10 @@ enum PatBoundCtx {
     /// We are inside of the type of a const parameter. Can't refer to any
     /// parameters.
     ConstParamTyRibKind,
+
+    /// We are inside a `sym` inline assembly operand. Can only refer to
+    /// globals.
+    InlineAsmSymRibKind,
 }
 
 impl RibKind<'_> {
@@ -153,7 +158,8 @@ impl RibKind<'_> {
             | ConstantItemRibKind(..)
             | ModuleRibKind(_)
             | MacroDefinition(_)
-            | ConstParamTyRibKind => false,
+            | ConstParamTyRibKind
+            | InlineAsmSymRibKind => false,
             AssocItemRibKind | ItemRibKind(_) | ForwardGenericParamBanRibKind => true,
         }
     }
@@ -183,6 +189,68 @@ fn new(kind: RibKind<'a>) -> Rib<'a, R> {
     }
 }
 
+#[derive(Copy, Clone, Debug)]
+enum LifetimeRibKind {
+    /// This rib acts as a barrier to forbid reference to lifetimes of a parent item.
+    Item,
+
+    /// This rib declares generic parameters.
+    Generics { span: Span, kind: LifetimeBinderKind },
+
+    /// For **Modern** cases, create a new anonymous region parameter
+    /// and reference that.
+    ///
+    /// For **Dyn Bound** cases, pass responsibility to
+    /// `resolve_lifetime` code.
+    ///
+    /// For **Deprecated** cases, report an error.
+    AnonymousCreateParameter,
+
+    /// Give a hard error when either `&` or `'_` is written. Used to
+    /// rule out things like `where T: Foo<'_>`. Does not imply an
+    /// error on default object bounds (e.g., `Box<dyn Foo>`).
+    AnonymousReportError,
+
+    /// Pass responsibility to `resolve_lifetime` code for all cases.
+    AnonymousPassThrough,
+}
+
+#[derive(Copy, Clone, Debug)]
+enum LifetimeBinderKind {
+    BareFnType,
+    PolyTrait,
+    WhereBound,
+    Item,
+    Function,
+    ImplBlock,
+}
+
+impl LifetimeBinderKind {
+    fn descr(self) -> &'static str {
+        use LifetimeBinderKind::*;
+        match self {
+            BareFnType => "type",
+            PolyTrait => "bound",
+            WhereBound => "bound",
+            Item => "item",
+            ImplBlock => "impl block",
+            Function => "function",
+        }
+    }
+}
+
+#[derive(Debug)]
+struct LifetimeRib {
+    kind: LifetimeRibKind,
+    bindings: IdentMap<()>,
+}
+
+impl LifetimeRib {
+    fn new(kind: LifetimeRibKind) -> LifetimeRib {
+        LifetimeRib { bindings: Default::default(), kind }
+    }
+}
+
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 crate enum AliasPossibility {
     No,
@@ -417,6 +485,9 @@ struct LateResolutionVisitor<'a, 'b, 'ast> {
     /// The current set of local scopes, for labels.
     label_ribs: Vec<Rib<'a, NodeId>>,
 
+    /// The current set of local scopes for lifetimes.
+    lifetime_ribs: Vec<LifetimeRib>,
+
     /// The trait that the current context can refer to.
     current_trait_ref: Option<(Module<'a>, TraitRef)>,
 
@@ -441,7 +512,7 @@ fn visit_item(&mut self, item: &'ast Item) {
         let prev = replace(&mut self.diagnostic_metadata.current_item, Some(item));
         // Always report errors in items we just entered.
         let old_ignore = replace(&mut self.in_func_body, false);
-        self.resolve_item(item);
+        self.with_lifetime_rib(LifetimeRibKind::Item, |this| this.resolve_item(item));
         self.in_func_body = old_ignore;
         self.diagnostic_metadata.current_item = prev;
     }
@@ -476,6 +547,12 @@ fn visit_ty(&mut self, ty: &'ast Ty) {
         let prev = self.diagnostic_metadata.current_trait_object;
         let prev_ty = self.diagnostic_metadata.current_type_path;
         match ty.kind {
+            TyKind::Rptr(None, _) => {
+                // Elided lifetime in reference: we resolve as if there was some lifetime `'_` with
+                // NodeId `ty.id`.
+                let span = self.r.session.source_map().next_point(ty.span.shrink_to_lo());
+                self.resolve_elided_lifetime(ty.id, span);
+            }
             TyKind::Path(ref qself, ref path) => {
                 self.diagnostic_metadata.current_type_path = Some(ty);
                 self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type);
@@ -495,36 +572,86 @@ fn visit_ty(&mut self, ty: &'ast Ty) {
             TyKind::TraitObject(ref bounds, ..) => {
                 self.diagnostic_metadata.current_trait_object = Some(&bounds[..]);
             }
+            TyKind::BareFn(ref bare_fn) => {
+                let span = if bare_fn.generic_params.is_empty() {
+                    ty.span.shrink_to_lo()
+                } else {
+                    ty.span
+                };
+                self.with_generic_param_rib(
+                    &bare_fn.generic_params,
+                    NormalRibKind,
+                    LifetimeRibKind::Generics { kind: LifetimeBinderKind::BareFnType, span },
+                    |this| {
+                        this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| {
+                            this.visit_generic_param_vec(&bare_fn.generic_params, false);
+                            visit::walk_fn_decl(this, &bare_fn.decl);
+                        });
+                    },
+                );
+                self.diagnostic_metadata.current_trait_object = prev;
+                return;
+            }
             _ => (),
         }
         visit::walk_ty(self, ty);
         self.diagnostic_metadata.current_trait_object = prev;
         self.diagnostic_metadata.current_type_path = prev_ty;
     }
-    fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) {
-        self.smart_resolve_path(
-            tref.trait_ref.ref_id,
-            None,
-            &tref.trait_ref.path,
-            PathSource::Trait(AliasPossibility::Maybe),
+    fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef, _: &'ast TraitBoundModifier) {
+        let span =
+            if tref.bound_generic_params.is_empty() { tref.span.shrink_to_lo() } else { tref.span };
+        self.with_generic_param_rib(
+            &tref.bound_generic_params,
+            NormalRibKind,
+            LifetimeRibKind::Generics { kind: LifetimeBinderKind::PolyTrait, span },
+            |this| {
+                this.visit_generic_param_vec(&tref.bound_generic_params, false);
+                this.smart_resolve_path(
+                    tref.trait_ref.ref_id,
+                    None,
+                    &tref.trait_ref.path,
+                    PathSource::Trait(AliasPossibility::Maybe),
+                );
+                this.visit_trait_ref(&tref.trait_ref);
+            },
         );
-        visit::walk_poly_trait_ref(self, tref, m);
     }
     fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
         match foreign_item.kind {
-            ForeignItemKind::Fn(box Fn { ref generics, .. })
-            | ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
-                self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
-                    visit::walk_foreign_item(this, foreign_item);
+            ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
+                self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
+                    this.with_generic_param_rib(
+                        &generics.params,
+                        ItemRibKind(HasGenericParams::Yes),
+                        LifetimeRibKind::Generics {
+                            kind: LifetimeBinderKind::Item,
+                            span: generics.span,
+                        },
+                        |this| visit::walk_foreign_item(this, foreign_item),
+                    )
+                });
+            }
+            ForeignItemKind::Fn(box Fn { ref generics, .. }) => {
+                self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
+                    this.with_generic_param_rib(
+                        &generics.params,
+                        ItemRibKind(HasGenericParams::Yes),
+                        LifetimeRibKind::Generics {
+                            kind: LifetimeBinderKind::Function,
+                            span: generics.span,
+                        },
+                        |this| visit::walk_foreign_item(this, foreign_item),
+                    )
                 });
             }
             ForeignItemKind::Static(..) => {
-                self.with_item_rib(HasGenericParams::No, |this| {
+                self.with_item_rib(|this| {
                     visit::walk_foreign_item(this, foreign_item);
                 });
             }
             ForeignItemKind::MacCall(..) => {
-                visit::walk_foreign_item(self, foreign_item);
+                panic!("unexpanded macro in resolve!")
             }
         }
     }
@@ -532,11 +659,15 @@ fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, _: NodeId) {
         let rib_kind = match fn_kind {
             // Bail if the function is foreign, and thus cannot validly have
             // a body, or if there's no body for some other reason.
-            FnKind::Fn(FnCtxt::Foreign, _, sig, ..) | FnKind::Fn(_, _, sig, .., None) => {
-                // We don't need to deal with patterns in parameters, because
-                // they are not possible for foreign or bodiless functions.
-                self.visit_fn_header(&sig.header);
-                visit::walk_fn_decl(self, &sig.decl);
+            FnKind::Fn(FnCtxt::Foreign, _, sig, _, generics, _)
+            | FnKind::Fn(_, _, sig, _, generics, None) => {
+                self.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| {
+                    // We don't need to deal with patterns in parameters, because
+                    // they are not possible for foreign or bodiless functions.
+                    this.visit_fn_header(&sig.header);
+                    this.visit_generics(generics);
+                    visit::walk_fn_decl(this, &sig.decl);
+                });
                 return;
             }
             FnKind::Fn(FnCtxt::Free, ..) => FnItemRibKind,
@@ -554,19 +685,44 @@ fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, _: NodeId) {
         self.with_rib(ValueNS, rib_kind, |this| {
             // Create a label rib for the function.
             this.with_label_rib(rib_kind, |this| {
-                // Add each argument to the rib.
-                this.resolve_params(&declaration.inputs);
+                let async_node_id = fn_kind.header().and_then(|h| h.asyncness.opt_return_id());
 
-                visit::walk_fn_ret_ty(this, &declaration.output);
+                if let FnKind::Fn(_, _, _, _, generics, _) = fn_kind {
+                    this.visit_generics(generics);
+                }
+
+                if async_node_id.is_some() {
+                    // In `async fn`, argument-position elided lifetimes
+                    // must be transformed into fresh generic parameters so that
+                    // they can be applied to the opaque `impl Trait` return type.
+                    this.with_lifetime_rib(LifetimeRibKind::AnonymousCreateParameter, |this| {
+                        // Add each argument to the rib.
+                        this.resolve_params(&declaration.inputs)
+                    });
+
+                    this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| {
+                        visit::walk_fn_ret_ty(this, &declaration.output)
+                    });
+                } else {
+                    this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| {
+                        // Add each argument to the rib.
+                        this.resolve_params(&declaration.inputs);
+
+                        visit::walk_fn_ret_ty(this, &declaration.output);
+                    });
+                };
 
                 // Ignore errors in function bodies if this is rustdoc
                 // Be sure not to set this until the function signature has been resolved.
                 let previous_state = replace(&mut this.in_func_body, true);
                 // Resolve the function body, potentially inside the body of an async closure
-                match fn_kind {
-                    FnKind::Fn(.., body) => walk_list!(this, visit_block, body),
-                    FnKind::Closure(_, body) => this.visit_expr(body),
-                };
+                this.with_lifetime_rib(
+                    LifetimeRibKind::AnonymousPassThrough,
+                    |this| match fn_kind {
+                        FnKind::Fn(.., body) => walk_list!(this, visit_block, body),
+                        FnKind::Closure(_, body) => this.visit_expr(body),
+                    },
+                );
 
                 debug!("(resolving function) leaving function");
                 this.in_func_body = previous_state;
@@ -574,89 +730,15 @@ fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, _: NodeId) {
         });
         self.diagnostic_metadata.current_function = previous_value;
     }
+    fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
+        self.resolve_lifetime(lifetime)
+    }
 
     fn visit_generics(&mut self, generics: &'ast Generics) {
-        // For type parameter defaults, we have to ban access
-        // to following type parameters, as the InternalSubsts can only
-        // provide previous type parameters as they're built. We
-        // put all the parameters on the ban list and then remove
-        // them one by one as they are processed and become available.
-        let mut forward_ty_ban_rib = Rib::new(ForwardGenericParamBanRibKind);
-        let mut forward_const_ban_rib = Rib::new(ForwardGenericParamBanRibKind);
-        for param in generics.params.iter() {
-            match param.kind {
-                GenericParamKind::Type { .. } => {
-                    forward_ty_ban_rib
-                        .bindings
-                        .insert(Ident::with_dummy_span(param.ident.name), Res::Err);
-                }
-                GenericParamKind::Const { .. } => {
-                    forward_const_ban_rib
-                        .bindings
-                        .insert(Ident::with_dummy_span(param.ident.name), Res::Err);
-                }
-                GenericParamKind::Lifetime => {}
-            }
-        }
-
-        // rust-lang/rust#61631: The type `Self` is essentially
-        // another type parameter. For ADTs, we consider it
-        // well-defined only after all of the ADT type parameters have
-        // been provided. Therefore, we do not allow use of `Self`
-        // anywhere in ADT type parameter defaults.
-        //
-        // (We however cannot ban `Self` for defaults on *all* generic
-        // lists; e.g. trait generics can usefully refer to `Self`,
-        // such as in the case of `trait Add<Rhs = Self>`.)
-        if self.diagnostic_metadata.current_self_item.is_some() {
-            // (`Some` if + only if we are in ADT's generics.)
-            forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
-        }
-
-        for param in &generics.params {
-            match param.kind {
-                GenericParamKind::Lifetime => self.visit_generic_param(param),
-                GenericParamKind::Type { ref default } => {
-                    for bound in &param.bounds {
-                        self.visit_param_bound(bound);
-                    }
-
-                    if let Some(ref ty) = default {
-                        self.ribs[TypeNS].push(forward_ty_ban_rib);
-                        self.ribs[ValueNS].push(forward_const_ban_rib);
-                        self.visit_ty(ty);
-                        forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap();
-                        forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap();
-                    }
-
-                    // Allow all following defaults to refer to this type parameter.
-                    forward_ty_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name));
-                }
-                GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
-                    // Const parameters can't have param bounds.
-                    assert!(param.bounds.is_empty());
-
-                    self.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind));
-                    self.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind));
-                    self.visit_ty(ty);
-                    self.ribs[TypeNS].pop().unwrap();
-                    self.ribs[ValueNS].pop().unwrap();
-
-                    if let Some(ref expr) = default {
-                        self.ribs[TypeNS].push(forward_ty_ban_rib);
-                        self.ribs[ValueNS].push(forward_const_ban_rib);
-                        self.visit_anon_const(expr);
-                        forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap();
-                        forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap();
-                    }
-
-                    // Allow all following defaults to refer to this const parameter.
-                    forward_const_ban_rib
-                        .bindings
-                        .remove(&Ident::with_dummy_span(param.ident.name));
-                }
-            }
-        }
+        self.visit_generic_param_vec(
+            &generics.params,
+            self.diagnostic_metadata.current_self_item.is_some(),
+        );
         for p in &generics.where_clause.predicates {
             self.visit_where_predicate(p);
         }
@@ -715,13 +797,71 @@ fn visit_generic_arg(&mut self, arg: &'ast GenericArg) {
         self.diagnostic_metadata.currently_processing_generics = prev;
     }
 
+    fn visit_path_segment(&mut self, path_span: Span, path_segment: &'ast PathSegment) {
+        if let Some(ref args) = path_segment.args {
+            match &**args {
+                GenericArgs::AngleBracketed(..) => visit::walk_generic_args(self, path_span, args),
+                GenericArgs::Parenthesized(..) => self
+                    .with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| {
+                        visit::walk_generic_args(this, path_span, args)
+                    }),
+            }
+        }
+    }
+
     fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
         debug!("visit_where_predicate {:?}", p);
         let previous_value =
             replace(&mut self.diagnostic_metadata.current_where_predicate, Some(p));
-        visit::walk_where_predicate(self, p);
+        self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
+            if let WherePredicate::BoundPredicate(WhereBoundPredicate {
+                ref bounded_ty,
+                ref bounds,
+                ref bound_generic_params,
+                span: predicate_span,
+                ..
+            }) = p
+            {
+                let span = if bound_generic_params.is_empty() {
+                    predicate_span.shrink_to_lo()
+                } else {
+                    *predicate_span
+                };
+                this.with_generic_param_rib(
+                    &bound_generic_params,
+                    NormalRibKind,
+                    LifetimeRibKind::Generics { kind: LifetimeBinderKind::WhereBound, span },
+                    |this| {
+                        this.visit_generic_param_vec(&bound_generic_params, false);
+                        this.visit_ty(bounded_ty);
+                        for bound in bounds {
+                            this.visit_param_bound(bound)
+                        }
+                    },
+                );
+            } else {
+                visit::walk_where_predicate(this, p);
+            }
+        });
         self.diagnostic_metadata.current_where_predicate = previous_value;
     }
+
+    fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) {
+        // This is similar to the code for AnonConst.
+        self.with_rib(ValueNS, InlineAsmSymRibKind, |this| {
+            this.with_rib(TypeNS, InlineAsmSymRibKind, |this| {
+                this.with_label_rib(InlineAsmSymRibKind, |this| {
+                    this.smart_resolve_path(
+                        sym.id,
+                        sym.qself.as_ref(),
+                        &sym.path,
+                        PathSource::Expr(None),
+                    );
+                    visit::walk_inline_asm_sym(this, sym);
+                });
+            })
+        });
+    }
 }
 
 impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
@@ -740,6 +880,7 @@ fn new(resolver: &'b mut Resolver<'a>) -> LateResolutionVisitor<'a, 'b, 'ast> {
                 macro_ns: vec![Rib::new(start_rib_kind)],
             },
             label_ribs: Vec::new(),
+            lifetime_ribs: Vec::new(),
             current_trait_ref: None,
             diagnostic_metadata: DiagnosticMetadata::default(),
             // errors at module scope should always be reported
@@ -842,6 +983,319 @@ fn with_scope<T>(&mut self, id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
         }
     }
 
+    fn visit_generic_param_vec(&mut self, params: &'ast Vec<GenericParam>, add_self_upper: bool) {
+        // For type parameter defaults, we have to ban access
+        // to following type parameters, as the InternalSubsts can only
+        // provide previous type parameters as they're built. We
+        // put all the parameters on the ban list and then remove
+        // them one by one as they are processed and become available.
+        let mut forward_ty_ban_rib = Rib::new(ForwardGenericParamBanRibKind);
+        let mut forward_const_ban_rib = Rib::new(ForwardGenericParamBanRibKind);
+        for param in params.iter() {
+            match param.kind {
+                GenericParamKind::Type { .. } => {
+                    forward_ty_ban_rib
+                        .bindings
+                        .insert(Ident::with_dummy_span(param.ident.name), Res::Err);
+                }
+                GenericParamKind::Const { .. } => {
+                    forward_const_ban_rib
+                        .bindings
+                        .insert(Ident::with_dummy_span(param.ident.name), Res::Err);
+                }
+                GenericParamKind::Lifetime => {}
+            }
+        }
+
+        // rust-lang/rust#61631: The type `Self` is essentially
+        // another type parameter. For ADTs, we consider it
+        // well-defined only after all of the ADT type parameters have
+        // been provided. Therefore, we do not allow use of `Self`
+        // anywhere in ADT type parameter defaults.
+        //
+        // (We however cannot ban `Self` for defaults on *all* generic
+        // lists; e.g. trait generics can usefully refer to `Self`,
+        // such as in the case of `trait Add<Rhs = Self>`.)
+        if add_self_upper {
+            // (`Some` if + only if we are in ADT's generics.)
+            forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
+        }
+
+        self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
+            for param in params {
+                match param.kind {
+                    GenericParamKind::Lifetime => {
+                        for bound in &param.bounds {
+                            this.visit_param_bound(bound);
+                        }
+                    }
+                    GenericParamKind::Type { ref default } => {
+                        for bound in &param.bounds {
+                            this.visit_param_bound(bound);
+                        }
+
+                        if let Some(ref ty) = default {
+                            this.ribs[TypeNS].push(forward_ty_ban_rib);
+                            this.ribs[ValueNS].push(forward_const_ban_rib);
+                            this.visit_ty(ty);
+                            forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap();
+                            forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap();
+                        }
+
+                        // Allow all following defaults to refer to this type parameter.
+                        forward_ty_ban_rib
+                            .bindings
+                            .remove(&Ident::with_dummy_span(param.ident.name));
+                    }
+                    GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
+                        // Const parameters can't have param bounds.
+                        assert!(param.bounds.is_empty());
+
+                        this.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind));
+                        this.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind));
+                        this.visit_ty(ty);
+                        this.ribs[TypeNS].pop().unwrap();
+                        this.ribs[ValueNS].pop().unwrap();
+
+                        if let Some(ref expr) = default {
+                            this.ribs[TypeNS].push(forward_ty_ban_rib);
+                            this.ribs[ValueNS].push(forward_const_ban_rib);
+                            this.visit_anon_const(expr);
+                            forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap();
+                            forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap();
+                        }
+
+                        // Allow all following defaults to refer to this const parameter.
+                        forward_const_ban_rib
+                            .bindings
+                            .remove(&Ident::with_dummy_span(param.ident.name));
+                    }
+                }
+            }
+        })
+    }
+
+    #[tracing::instrument(level = "debug", skip(self, work))]
+    fn with_lifetime_rib<T>(
+        &mut self,
+        kind: LifetimeRibKind,
+        work: impl FnOnce(&mut Self) -> T,
+    ) -> T {
+        self.lifetime_ribs.push(LifetimeRib::new(kind));
+        let ret = work(self);
+        self.lifetime_ribs.pop();
+        ret
+    }
+
+    #[tracing::instrument(level = "debug", skip(self))]
+    fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime) {
+        let ident = lifetime.ident;
+
+        if ident.name == kw::StaticLifetime {
+            return;
+        }
+
+        if ident.name == kw::UnderscoreLifetime {
+            return self.resolve_anonymous_lifetime(lifetime, false);
+        }
+
+        let mut indices = (0..self.lifetime_ribs.len()).rev();
+        for i in &mut indices {
+            let rib = &self.lifetime_ribs[i];
+            let normalized_ident = ident.normalize_to_macros_2_0();
+            if let Some(_) = rib.bindings.get_key_value(&normalized_ident) {
+                return;
+            }
+
+            if let LifetimeRibKind::Item = rib.kind {
+                break;
+            }
+        }
+
+        let mut outer_res = None;
+        for i in indices {
+            let rib = &self.lifetime_ribs[i];
+            let normalized_ident = ident.normalize_to_macros_2_0();
+            if let Some((&outer, _)) = rib.bindings.get_key_value(&normalized_ident) {
+                outer_res = Some(outer);
+                break;
+            }
+        }
+
+        self.emit_undeclared_lifetime_error(lifetime, outer_res);
+    }
+
+    #[tracing::instrument(level = "debug", skip(self))]
+    fn resolve_anonymous_lifetime(&mut self, lifetime: &Lifetime, elided: bool) {
+        debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime);
+
+        for i in (0..self.lifetime_ribs.len()).rev() {
+            let rib = &mut self.lifetime_ribs[i];
+            match rib.kind {
+                LifetimeRibKind::AnonymousReportError => {
+                    let (msg, note) = if elided {
+                        (
+                            "`&` without an explicit lifetime name cannot be used here",
+                            "explicit lifetime name needed here",
+                        )
+                    } else {
+                        ("`'_` cannot be used here", "`'_` is a reserved lifetime name")
+                    };
+                    rustc_errors::struct_span_err!(
+                        self.r.session,
+                        lifetime.ident.span,
+                        E0637,
+                        "{}",
+                        msg,
+                    )
+                    .span_label(lifetime.ident.span, note)
+                    .emit();
+
+                    return;
+                }
+                LifetimeRibKind::AnonymousCreateParameter
+                | LifetimeRibKind::AnonymousPassThrough
+                | LifetimeRibKind::Item => return,
+                _ => {}
+            }
+        }
+    }
+
+    #[tracing::instrument(level = "debug", skip(self))]
+    fn resolve_elided_lifetime(&mut self, anchor_id: NodeId, span: Span) {
+        let id = self.r.next_node_id();
+        let lt = Lifetime { id, ident: Ident::new(kw::UnderscoreLifetime, span) };
+        self.resolve_anonymous_lifetime(&lt, true);
+    }
+
+    #[tracing::instrument(level = "debug", skip(self))]
+    fn resolve_elided_lifetimes_in_path(
+        &mut self,
+        path_id: NodeId,
+        partial_res: PartialRes,
+        path: &[Segment],
+        source: PathSource<'_>,
+        finalize: Finalize,
+    ) {
+        let Some(path_span) = finalize.path_span() else {
+            return;
+        };
+        let proj_start = path.len() - partial_res.unresolved_segments();
+        for (i, segment) in path.iter().enumerate() {
+            if segment.has_lifetime_args {
+                continue;
+            }
+            let Some(segment_id) = segment.id else {
+                continue;
+            };
+
+            // Figure out if this is a type/trait segment,
+            // which may need lifetime elision performed.
+            let type_def_id = match partial_res.base_res() {
+                Res::Def(DefKind::AssocTy, def_id) if i + 2 == proj_start => {
+                    self.r.parent(def_id).unwrap()
+                }
+                Res::Def(DefKind::Variant, def_id) if i + 1 == proj_start => {
+                    self.r.parent(def_id).unwrap()
+                }
+                Res::Def(DefKind::Struct, def_id)
+                | Res::Def(DefKind::Union, def_id)
+                | Res::Def(DefKind::Enum, def_id)
+                | Res::Def(DefKind::TyAlias, def_id)
+                | Res::Def(DefKind::Trait, def_id)
+                    if i + 1 == proj_start =>
+                {
+                    def_id
+                }
+                _ => continue,
+            };
+
+            let expected_lifetimes = self.r.item_generics_num_lifetimes(type_def_id);
+            if expected_lifetimes == 0 {
+                continue;
+            }
+
+            let missing = match source {
+                PathSource::Trait(..) | PathSource::TraitItem(..) | PathSource::Type => true,
+                PathSource::Expr(..)
+                | PathSource::Pat
+                | PathSource::Struct
+                | PathSource::TupleStruct(..) => false,
+            };
+            let mut error = false;
+            for rib in self.lifetime_ribs.iter().rev() {
+                match rib.kind {
+                    // In create-parameter mode we error here because we don't want to support
+                    // deprecated impl elision in new features like impl elision and `async fn`,
+                    // both of which work using the `CreateParameter` mode:
+                    //
+                    //     impl Foo for std::cell::Ref<u32> // note lack of '_
+                    //     async fn foo(_: std::cell::Ref<u32>) { ... }
+                    LifetimeRibKind::AnonymousCreateParameter => {
+                        error = true;
+                        break;
+                    }
+                    // `PassThrough` is the normal case.
+                    // `new_error_lifetime`, which would usually be used in the case of `ReportError`,
+                    // is unsuitable here, as these can occur from missing lifetime parameters in a
+                    // `PathSegment`, for which there is no associated `'_` or `&T` with no explicit
+                    // lifetime. Instead, we simply create an implicit lifetime, which will be checked
+                    // later, at which point a suitable error will be emitted.
+                    LifetimeRibKind::AnonymousPassThrough
+                    | LifetimeRibKind::AnonymousReportError
+                    | LifetimeRibKind::Item => break,
+                    _ => {}
+                }
+            }
+
+            if !missing {
+                continue;
+            }
+
+            let elided_lifetime_span = if segment.has_generic_args {
+                // If there are brackets, but not generic arguments, then use the opening bracket
+                segment.args_span.with_hi(segment.args_span.lo() + BytePos(1))
+            } else {
+                // If there are no brackets, use the identifier span.
+                // HACK: we use find_ancestor_inside to properly suggest elided spans in paths
+                // originating from macros, since the segment's span might be from a macro arg.
+                segment.ident.span.find_ancestor_inside(path_span).unwrap_or(path_span)
+            };
+            if error {
+                let sess = self.r.session;
+                let mut err = rustc_errors::struct_span_err!(
+                    sess,
+                    path_span,
+                    E0726,
+                    "implicit elided lifetime not allowed here"
+                );
+                rustc_errors::add_elided_lifetime_in_path_suggestion(
+                    sess.source_map(),
+                    &mut err,
+                    expected_lifetimes,
+                    path_span,
+                    !segment.has_generic_args,
+                    elided_lifetime_span,
+                );
+                err.note("assuming a `'static` lifetime...");
+                err.emit();
+            } else {
+                self.r.lint_buffer.buffer_lint_with_diagnostic(
+                    lint::builtin::ELIDED_LIFETIMES_IN_PATHS,
+                    segment_id,
+                    elided_lifetime_span,
+                    "hidden lifetime parameters in types are deprecated",
+                    lint::BuiltinLintDiagnostics::ElidedLifetimesInPaths(
+                        expected_lifetimes,
+                        path_span,
+                        !segment.has_generic_args,
+                        elided_lifetime_span,
+                    ),
+                );
+            }
+        }
+    }
+
     /// Searches the current set of local scopes for labels. Returns the `NodeId` of the resolved
     /// label and reports an error if the label is not found or is unreachable.
     fn resolve_label(&self, mut label: Ident) -> Option<NodeId> {
@@ -909,7 +1363,8 @@ fn is_label_valid_from_rib(&self, rib_index: usize) -> bool {
                 | ConstantItemRibKind(..)
                 | ModuleRibKind(..)
                 | ForwardGenericParamBanRibKind
-                | ConstParamTyRibKind => {
+                | ConstParamTyRibKind
+                | InlineAsmSymRibKind => {
                     return false;
                 }
             }
@@ -921,15 +1376,20 @@ fn is_label_valid_from_rib(&self, rib_index: usize) -> bool {
     fn resolve_adt(&mut self, item: &'ast Item, generics: &'ast Generics) {
         debug!("resolve_adt");
         self.with_current_self_item(item, |this| {
-            this.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
-                let item_def_id = this.r.local_def_id(item.id).to_def_id();
-                this.with_self_rib(
-                    Res::SelfTy { trait_: None, alias_to: Some((item_def_id, false)) },
-                    |this| {
-                        visit::walk_item(this, item);
-                    },
-                );
-            });
+            this.with_generic_param_rib(
+                &generics.params,
+                ItemRibKind(HasGenericParams::Yes),
+                LifetimeRibKind::Generics { kind: LifetimeBinderKind::Item, span: generics.span },
+                |this| {
+                    let item_def_id = this.r.local_def_id(item.id).to_def_id();
+                    this.with_self_rib(
+                        Res::SelfTy { trait_: None, alias_to: Some((item_def_id, false)) },
+                        |this| {
+                            visit::walk_item(this, item);
+                        },
+                    );
+                },
+            );
         });
     }
 
@@ -981,18 +1441,33 @@ fn resolve_item(&mut self, item: &'ast Item) {
         debug!("(resolving item) resolving {} ({:?})", name, item.kind);
 
         match item.kind {
-            ItemKind::TyAlias(box TyAlias { ref generics, .. })
-            | ItemKind::Fn(box Fn { ref generics, .. }) => {
-                self.compute_num_lifetime_params(item.id, generics);
-                self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
-                    visit::walk_item(this, item)
-                });
+            ItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
+                self.with_generic_param_rib(
+                    &generics.params,
+                    ItemRibKind(HasGenericParams::Yes),
+                    LifetimeRibKind::Generics {
+                        kind: LifetimeBinderKind::Item,
+                        span: generics.span,
+                    },
+                    |this| visit::walk_item(this, item),
+                );
+            }
+
+            ItemKind::Fn(box Fn { ref generics, .. }) => {
+                self.with_generic_param_rib(
+                    &generics.params,
+                    ItemRibKind(HasGenericParams::Yes),
+                    LifetimeRibKind::Generics {
+                        kind: LifetimeBinderKind::Function,
+                        span: generics.span,
+                    },
+                    |this| visit::walk_item(this, item),
+                );
             }
 
             ItemKind::Enum(_, ref generics)
             | ItemKind::Struct(_, ref generics)
             | ItemKind::Union(_, ref generics) => {
-                self.compute_num_lifetime_params(item.id, generics);
                 self.resolve_adt(item, generics);
             }
 
@@ -1003,72 +1478,113 @@ fn resolve_item(&mut self, item: &'ast Item) {
                 items: ref impl_items,
                 ..
             }) => {
-                self.compute_num_lifetime_params(item.id, generics);
                 self.resolve_implementation(generics, of_trait, &self_ty, item.id, impl_items);
             }
 
             ItemKind::Trait(box Trait { ref generics, ref bounds, ref items, .. }) => {
-                self.compute_num_lifetime_params(item.id, generics);
                 // Create a new rib for the trait-wide type parameters.
-                self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
-                    let def = this.r.local_def_id(item.id).to_def_id();
-                    this.with_self_rib(Res::SelfTy { trait_: Some(def), alias_to: None }, |this| {
-                        this.visit_generics(generics);
-                        walk_list!(this, visit_param_bound, bounds);
-
-                        let walk_assoc_item = |this: &mut Self, generics, item| {
-                            this.with_generic_param_rib(generics, AssocItemRibKind, |this| {
-                                visit::walk_assoc_item(this, item, AssocCtxt::Trait)
-                            });
-                        };
-
-                        this.with_trait_items(items, |this| {
-                            for item in items {
-                                match &item.kind {
-                                    AssocItemKind::Const(_, ty, default) => {
-                                        this.visit_ty(ty);
-                                        // Only impose the restrictions of `ConstRibKind` for an
-                                        // actual constant expression in a provided default.
-                                        if let Some(expr) = default {
-                                            // We allow arbitrary const expressions inside of associated consts,
-                                            // even if they are potentially not const evaluatable.
-                                            //
-                                            // Type parameters can already be used and as associated consts are
-                                            // not used as part of the type system, this is far less surprising.
-                                            this.with_constant_rib(
-                                                IsRepeatExpr::No,
-                                                true,
-                                                None,
-                                                |this| this.visit_expr(expr),
-                                            );
-                                        }
-                                    }
-                                    AssocItemKind::Fn(box Fn { generics, .. }) => {
-                                        walk_assoc_item(this, generics, item);
-                                    }
-                                    AssocItemKind::TyAlias(box TyAlias { generics, .. }) => {
-                                        walk_assoc_item(this, generics, item);
-                                    }
-                                    AssocItemKind::MacCall(_) => {
-                                        panic!("unexpanded macro in resolve!")
+                self.with_generic_param_rib(
+                    &generics.params,
+                    ItemRibKind(HasGenericParams::Yes),
+                    LifetimeRibKind::Generics {
+                        kind: LifetimeBinderKind::Item,
+                        span: generics.span,
+                    },
+                    |this| {
+                        let local_def_id = this.r.local_def_id(item.id).to_def_id();
+                        this.with_self_rib(
+                            Res::SelfTy { trait_: Some(local_def_id), alias_to: None },
+                            |this| {
+                                this.visit_generics(generics);
+                                walk_list!(this, visit_param_bound, bounds);
+
+                                let walk_assoc_item =
+                                    |this: &mut Self,
+                                     generics: &Generics,
+                                     kind,
+                                     item: &'ast AssocItem| {
+                                        this.with_generic_param_rib(
+                                            &generics.params,
+                                            AssocItemRibKind,
+                                            LifetimeRibKind::Generics { span: generics.span, kind },
+                                            |this| {
+                                                visit::walk_assoc_item(this, item, AssocCtxt::Trait)
+                                            },
+                                        );
+                                    };
+
+                                this.with_trait_items(items, |this| {
+                                    for item in items {
+                                        match &item.kind {
+                                            AssocItemKind::Const(_, ty, default) => {
+                                                this.visit_ty(ty);
+                                                // Only impose the restrictions of `ConstRibKind` for an
+                                                // actual constant expression in a provided default.
+                                                if let Some(expr) = default {
+                                                    // We allow arbitrary const expressions inside of associated consts,
+                                                    // even if they are potentially not const evaluatable.
+                                                    //
+                                                    // Type parameters can already be used and as associated consts are
+                                                    // not used as part of the type system, this is far less surprising.
+                                                    this.with_constant_rib(
+                                                        IsRepeatExpr::No,
+                                                        true,
+                                                        None,
+                                                        |this| this.visit_expr(expr),
+                                                    );
+                                                }
+                                            }
+                                            AssocItemKind::Fn(box Fn { generics, .. }) => {
+                                                walk_assoc_item(
+                                                    this,
+                                                    generics,
+                                                    LifetimeBinderKind::Function,
+                                                    item,
+                                                );
+                                            }
+                                            AssocItemKind::TyAlias(box TyAlias {
+                                                generics,
+                                                ..
+                                            }) => {
+                                                walk_assoc_item(
+                                                    this,
+                                                    generics,
+                                                    LifetimeBinderKind::Item,
+                                                    item,
+                                                );
+                                            }
+                                            AssocItemKind::MacCall(_) => {
+                                                panic!("unexpanded macro in resolve!")
+                                            }
+                                        };
                                     }
-                                };
-                            }
-                        });
-                    });
-                });
+                                });
+                            },
+                        );
+                    },
+                );
             }
 
             ItemKind::TraitAlias(ref generics, ref bounds) => {
-                self.compute_num_lifetime_params(item.id, generics);
                 // Create a new rib for the trait-wide type parameters.
-                self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
-                    let def = this.r.local_def_id(item.id).to_def_id();
-                    this.with_self_rib(Res::SelfTy { trait_: Some(def), alias_to: None }, |this| {
-                        this.visit_generics(generics);
-                        walk_list!(this, visit_param_bound, bounds);
-                    });
-                });
+                self.with_generic_param_rib(
+                    &generics.params,
+                    ItemRibKind(HasGenericParams::Yes),
+                    LifetimeRibKind::Generics {
+                        kind: LifetimeBinderKind::Item,
+                        span: generics.span,
+                    },
+                    |this| {
+                        let local_def_id = this.r.local_def_id(item.id).to_def_id();
+                        this.with_self_rib(
+                            Res::SelfTy { trait_: Some(local_def_id), alias_to: None },
+                            |this| {
+                                this.visit_generics(generics);
+                                walk_list!(this, visit_param_bound, bounds);
+                            },
+                        );
+                    },
+                );
             }
 
             ItemKind::Mod(..) | ItemKind::ForeignMod(_) => {
@@ -1078,7 +1594,7 @@ fn resolve_item(&mut self, item: &'ast Item) {
             }
 
             ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(_, ref ty, ref expr) => {
-                self.with_item_rib(HasGenericParams::No, |this| {
+                self.with_item_rib(|this| {
                     this.visit_ty(ty);
                     if let Some(expr) = expr {
                         let constant_item_kind = match item.kind {
@@ -1114,13 +1630,19 @@ fn resolve_item(&mut self, item: &'ast Item) {
         }
     }
 
-    fn with_generic_param_rib<'c, F>(&'c mut self, generics: &'c Generics, kind: RibKind<'a>, f: F)
-    where
+    fn with_generic_param_rib<'c, F>(
+        &'c mut self,
+        params: &'c Vec<GenericParam>,
+        kind: RibKind<'a>,
+        lifetime_kind: LifetimeRibKind,
+        f: F,
+    ) where
         F: FnOnce(&mut Self),
     {
         debug!("with_generic_param_rib");
         let mut function_type_rib = Rib::new(kind);
         let mut function_value_rib = Rib::new(kind);
+        let mut function_lifetime_rib = LifetimeRib::new(lifetime_kind);
         let mut seen_bindings = FxHashMap::default();
 
         // We also can't shadow bindings from the parent item
@@ -1137,11 +1659,7 @@ fn with_generic_param_rib<'c, F>(&'c mut self, generics: &'c Generics, kind: Rib
             add_bindings_for_ns(TypeNS);
         }
 
-        for param in &generics.params {
-            if let GenericParamKind::Lifetime = param.kind {
-                continue;
-            }
-
+        for param in params {
             let ident = param.ident.normalize_to_macros_2_0();
             debug!("with_generic_param_rib: {}", param.id);
 
@@ -1149,24 +1667,57 @@ fn with_generic_param_rib<'c, F>(&'c mut self, generics: &'c Generics, kind: Rib
                 Entry::Occupied(entry) => {
                     let span = *entry.get();
                     let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, span);
-                    self.report_error(param.ident.span, err);
+                    if !matches!(param.kind, GenericParamKind::Lifetime) {
+                        self.report_error(param.ident.span, err);
+                    }
                 }
                 Entry::Vacant(entry) => {
                     entry.insert(param.ident.span);
                 }
             }
 
+            if param.ident.name == kw::UnderscoreLifetime {
+                rustc_errors::struct_span_err!(
+                    self.r.session,
+                    param.ident.span,
+                    E0637,
+                    "`'_` cannot be used here"
+                )
+                .span_label(param.ident.span, "`'_` is a reserved lifetime name")
+                .emit();
+                continue;
+            }
+
+            if param.ident.name == kw::StaticLifetime {
+                rustc_errors::struct_span_err!(
+                    self.r.session,
+                    param.ident.span,
+                    E0262,
+                    "invalid lifetime parameter name: `{}`",
+                    param.ident,
+                )
+                .span_label(param.ident.span, "'static is a reserved lifetime name")
+                .emit();
+                continue;
+            }
+
+            let def_id = self.r.local_def_id(param.id);
+
             // Plain insert (no renaming).
             let (rib, def_kind) = match param.kind {
                 GenericParamKind::Type { .. } => (&mut function_type_rib, DefKind::TyParam),
                 GenericParamKind::Const { .. } => (&mut function_value_rib, DefKind::ConstParam),
-                _ => unreachable!(),
+                GenericParamKind::Lifetime => {
+                    function_lifetime_rib.bindings.insert(ident, ());
+                    continue;
+                }
             };
-            let res = Res::Def(def_kind, self.r.local_def_id(param.id).to_def_id());
+            let res = Res::Def(def_kind, def_id.to_def_id());
             self.r.record_partial_res(param.id, PartialRes::new(res));
             rib.bindings.insert(ident, res);
         }
 
+        self.lifetime_ribs.push(function_lifetime_rib);
         self.ribs[ValueNS].push(function_value_rib);
         self.ribs[TypeNS].push(function_type_rib);
 
@@ -1174,6 +1725,7 @@ fn with_generic_param_rib<'c, F>(&'c mut self, generics: &'c Generics, kind: Rib
 
         self.ribs[TypeNS].pop();
         self.ribs[ValueNS].pop();
+        self.lifetime_ribs.pop();
     }
 
     fn with_label_rib(&mut self, kind: RibKind<'a>, f: impl FnOnce(&mut Self)) {
@@ -1182,9 +1734,11 @@ fn with_label_rib(&mut self, kind: RibKind<'a>, f: impl FnOnce(&mut Self)) {
         self.label_ribs.pop();
     }
 
-    fn with_item_rib(&mut self, has_generic_params: HasGenericParams, f: impl FnOnce(&mut Self)) {
-        let kind = ItemRibKind(has_generic_params);
-        self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
+    fn with_item_rib(&mut self, f: impl FnOnce(&mut Self)) {
+        let kind = ItemRibKind(HasGenericParams::No);
+        self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
+            this.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
+        })
     }
 
     // HACK(min_const_generics,const_evaluatable_unchecked): We
@@ -1295,128 +1849,137 @@ fn resolve_implementation(
     ) {
         debug!("resolve_implementation");
         // If applicable, create a rib for the type parameters.
-        self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
+        self.with_generic_param_rib(&generics.params, ItemRibKind(HasGenericParams::Yes), LifetimeRibKind::Generics { span: generics.span, kind: LifetimeBinderKind::ImplBlock }, |this| {
             // Dummy self type for better errors if `Self` is used in the trait path.
             this.with_self_rib(Res::SelfTy { trait_: None, alias_to: None }, |this| {
-                // Resolve the trait reference, if necessary.
-                this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| {
-                    let item_def_id = this.r.local_def_id(item_id);
-
-                    // Register the trait definitions from here.
-                    if let Some(trait_id) = trait_id {
-                        this.r.trait_impls.entry(trait_id).or_default().push(item_def_id);
-                    }
-
-                    let item_def_id = item_def_id.to_def_id();
-                    let res =
-                        Res::SelfTy { trait_: trait_id, alias_to: Some((item_def_id, false)) };
-                    this.with_self_rib(res, |this| {
-                        if let Some(trait_ref) = opt_trait_reference.as_ref() {
-                            // Resolve type arguments in the trait path.
-                            visit::walk_trait_ref(this, trait_ref);
+                this.with_lifetime_rib(LifetimeRibKind::AnonymousCreateParameter, |this| {
+                    // Resolve the trait reference, if necessary.
+                    this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| {
+                        let item_def_id = this.r.local_def_id(item_id);
+
+                        // Register the trait definitions from here.
+                        if let Some(trait_id) = trait_id {
+                            this.r.trait_impls.entry(trait_id).or_default().push(item_def_id);
                         }
-                        // Resolve the self type.
-                        this.visit_ty(self_type);
-                        // Resolve the generic parameters.
-                        this.visit_generics(generics);
-                        // Resolve the items within the impl.
-                        this.with_current_self_type(self_type, |this| {
-                            this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| {
-                                debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)");
-                                for item in impl_items {
-                                    use crate::ResolutionError::*;
-                                    match &item.kind {
-                                        AssocItemKind::Const(_default, _ty, _expr) => {
-                                            debug!("resolve_implementation AssocItemKind::Const");
-                                            // If this is a trait impl, ensure the const
-                                            // exists in trait
-                                            this.check_trait_item(
-                                                item.id,
-                                                item.ident,
-                                                &item.kind,
-                                                ValueNS,
-                                                item.span,
-                                                |i, s, c| ConstNotMemberOfTrait(i, s, c),
-                                            );
-
-                                            // We allow arbitrary const expressions inside of associated consts,
-                                            // even if they are potentially not const evaluatable.
-                                            //
-                                            // Type parameters can already be used and as associated consts are
-                                            // not used as part of the type system, this is far less surprising.
-                                            this.with_constant_rib(
-                                                IsRepeatExpr::No,
-                                                true,
-                                                None,
-                                                |this| {
-                                                    visit::walk_assoc_item(
-                                                        this,
-                                                        item,
-                                                        AssocCtxt::Impl,
-                                                    )
-                                                },
-                                            );
-                                        }
-                                        AssocItemKind::Fn(box Fn { generics, .. }) => {
-                                            debug!("resolve_implementation AssocItemKind::Fn");
-                                            // We also need a new scope for the impl item type parameters.
-                                            this.with_generic_param_rib(
-                                                generics,
-                                                AssocItemRibKind,
-                                                |this| {
-                                                    // If this is a trait impl, ensure the method
-                                                    // exists in trait
-                                                    this.check_trait_item(
-                                                        item.id,
-                                                        item.ident,
-                                                        &item.kind,
-                                                        ValueNS,
-                                                        item.span,
-                                                        |i, s, c| MethodNotMemberOfTrait(i, s, c),
-                                                    );
 
-                                                    visit::walk_assoc_item(
-                                                        this,
-                                                        item,
-                                                        AssocCtxt::Impl,
-                                                    )
-                                                },
-                                            );
-                                        }
-                                        AssocItemKind::TyAlias(box TyAlias {
-                                            generics, ..
-                                        }) => {
-                                            debug!("resolve_implementation AssocItemKind::TyAlias");
-                                            // We also need a new scope for the impl item type parameters.
-                                            this.with_generic_param_rib(
-                                                generics,
-                                                AssocItemRibKind,
-                                                |this| {
-                                                    // If this is a trait impl, ensure the type
-                                                    // exists in trait
-                                                    this.check_trait_item(
-                                                        item.id,
-                                                        item.ident,
-                                                        &item.kind,
-                                                        TypeNS,
-                                                        item.span,
-                                                        |i, s, c| TypeNotMemberOfTrait(i, s, c),
-                                                    );
-
-                                                    visit::walk_assoc_item(
-                                                        this,
-                                                        item,
-                                                        AssocCtxt::Impl,
-                                                    )
-                                                },
-                                            );
-                                        }
-                                        AssocItemKind::MacCall(_) => {
-                                            panic!("unexpanded macro in resolve!")
-                                        }
-                                    }
-                                }
-                            });
+                        let item_def_id = item_def_id.to_def_id();
+                        let res =
+                            Res::SelfTy { trait_: trait_id, alias_to: Some((item_def_id, false)) };
+                        this.with_self_rib(res, |this| {
+                            if let Some(trait_ref) = opt_trait_reference.as_ref() {
+                                // Resolve type arguments in the trait path.
+                                visit::walk_trait_ref(this, trait_ref);
+                            }
+                            // Resolve the self type.
+                            this.visit_ty(self_type);
+                            // Resolve the generic parameters.
+                            this.visit_generics(generics);
+
+                            // Resolve the items within the impl.
+                            this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough,
+                                |this| {
+                                    this.with_current_self_type(self_type, |this| {
+                                        this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| {
+                                            debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)");
+                                            for item in impl_items {
+                                                use crate::ResolutionError::*;
+                                                match &item.kind {
+                                                    AssocItemKind::Const(_default, _ty, _expr) => {
+                                                        debug!("resolve_implementation AssocItemKind::Const");
+                                                        // If this is a trait impl, ensure the const
+                                                        // exists in trait
+                                                        this.check_trait_item(
+                                                            item.id,
+                                                            item.ident,
+                                                            &item.kind,
+                                                            ValueNS,
+                                                            item.span,
+                                                            |i, s, c| ConstNotMemberOfTrait(i, s, c),
+                                                        );
+
+                                                        // We allow arbitrary const expressions inside of associated consts,
+                                                        // even if they are potentially not const evaluatable.
+                                                        //
+                                                        // Type parameters can already be used and as associated consts are
+                                                        // not used as part of the type system, this is far less surprising.
+                                                        this.with_constant_rib(
+                                                            IsRepeatExpr::No,
+                                                            true,
+                                                            None,
+                                                            |this| {
+                                                                visit::walk_assoc_item(
+                                                                    this,
+                                                                    item,
+                                                                    AssocCtxt::Impl,
+                                                                )
+                                                            },
+                                                        );
+                                                    }
+                                                    AssocItemKind::Fn(box Fn { generics, .. }) => {
+                                                        debug!("resolve_implementation AssocItemKind::Fn");
+                                                        // We also need a new scope for the impl item type parameters.
+                                                        this.with_generic_param_rib(
+                                                            &generics.params,
+                                                            AssocItemRibKind,
+                                                            LifetimeRibKind::Generics { span: generics.span, kind: LifetimeBinderKind::Function },
+                                                            |this| {
+                                                                // If this is a trait impl, ensure the method
+                                                                // exists in trait
+                                                                this.check_trait_item(
+                                                                    item.id,
+                                                                    item.ident,
+                                                                    &item.kind,
+                                                                    ValueNS,
+                                                                    item.span,
+                                                                    |i, s, c| MethodNotMemberOfTrait(i, s, c),
+                                                                );
+
+                                                                visit::walk_assoc_item(
+                                                                    this,
+                                                                    item,
+                                                                    AssocCtxt::Impl,
+                                                                )
+                                                            },
+                                                        );
+                                                    }
+                                                    AssocItemKind::TyAlias(box TyAlias {
+                                                        generics, ..
+                                                    }) => {
+                                                        debug!("resolve_implementation AssocItemKind::TyAlias");
+                                                        // We also need a new scope for the impl item type parameters.
+                                                        this.with_generic_param_rib(
+                                                            &generics.params,
+                                                            AssocItemRibKind,
+                                                            LifetimeRibKind::Generics { span: generics.span, kind: LifetimeBinderKind::Item },
+                                                            |this| {
+                                                                // If this is a trait impl, ensure the type
+                                                                // exists in trait
+                                                                this.check_trait_item(
+                                                                    item.id,
+                                                                    item.ident,
+                                                                    &item.kind,
+                                                                    TypeNS,
+                                                                    item.span,
+                                                                    |i, s, c| TypeNotMemberOfTrait(i, s, c),
+                                                                );
+
+                                                                visit::walk_assoc_item(
+                                                                    this,
+                                                                    item,
+                                                                    AssocCtxt::Impl,
+                                                                )
+                                                            },
+                                                        );
+                                                    }
+                                                    AssocItemKind::MacCall(_) => {
+                                                        panic!("unexpanded macro in resolve!")
+                                                    }
+                                                }
+                                            }
+                                        });
+                                    });
+                                },
+                            );
                         });
                     });
                 });
@@ -2094,6 +2657,7 @@ fn smart_resolve_path_fragment(
             self.r.record_partial_res(id, partial_res);
         }
 
+        self.resolve_elided_lifetimes_in_path(id, partial_res, path, source, finalize);
         partial_res
     }
 
@@ -2187,7 +2751,7 @@ fn resolve_qpath(
                 // trait to resolve.  In that case, we leave the `B`
                 // segment to be resolved by type-check.
                 return Ok(Some(PartialRes::with_unresolved_segments(
-                    Res::Def(DefKind::Mod, DefId::local(CRATE_DEF_INDEX)),
+                    Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id()),
                     path.len(),
                 )));
             }
@@ -2553,20 +3117,51 @@ fn traits_in_scope(&mut self, ident: Ident, ns: Namespace) -> Vec<TraitCandidate
             Some((ident.name, ns)),
         )
     }
+}
+
+struct LifetimeCountVisitor<'a, 'b> {
+    r: &'b mut Resolver<'a>,
+}
 
-    fn compute_num_lifetime_params(&mut self, id: NodeId, generics: &Generics) {
-        let def_id = self.r.local_def_id(id);
-        let count = generics
-            .params
-            .iter()
-            .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime { .. }))
-            .count();
-        self.r.item_generics_num_lifetimes.insert(def_id, count);
+/// Walks the whole crate in DFS order, visiting each item, counting the declared number of
+/// lifetime generic parameters.
+impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_> {
+    fn visit_item(&mut self, item: &'ast Item) {
+        match &item.kind {
+            ItemKind::TyAlias(box TyAlias { ref generics, .. })
+            | ItemKind::Fn(box Fn { ref generics, .. })
+            | ItemKind::Enum(_, ref generics)
+            | ItemKind::Struct(_, ref generics)
+            | ItemKind::Union(_, ref generics)
+            | ItemKind::Impl(box Impl { ref generics, .. })
+            | ItemKind::Trait(box Trait { ref generics, .. })
+            | ItemKind::TraitAlias(ref generics, _) => {
+                let def_id = self.r.local_def_id(item.id);
+                let count = generics
+                    .params
+                    .iter()
+                    .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime { .. }))
+                    .count();
+                self.r.item_generics_num_lifetimes.insert(def_id, count);
+            }
+
+            ItemKind::Mod(..)
+            | ItemKind::ForeignMod(..)
+            | ItemKind::Static(..)
+            | ItemKind::Const(..)
+            | ItemKind::Use(..)
+            | ItemKind::ExternCrate(..)
+            | ItemKind::MacroDef(..)
+            | ItemKind::GlobalAsm(..)
+            | ItemKind::MacCall(..) => {}
+        }
+        visit::walk_item(self, item)
     }
 }
 
 impl<'a> Resolver<'a> {
     pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
+        visit::walk_crate(&mut LifetimeCountVisitor { r: self }, krate);
         let mut late_resolution_visitor = LateResolutionVisitor::new(self);
         visit::walk_crate(&mut late_resolution_visitor, krate);
         for (id, span) in late_resolution_visitor.diagnostic_metadata.unused_labels.iter() {
index 0926f24ae70efb44f497a1a654e1d72c1d597423..d77cc917e2f9a2035c05fd4d3b7b303c4c19db7c 100644 (file)
@@ -1,6 +1,7 @@
 use crate::diagnostics::{ImportSuggestion, LabelSuggestion, TypoSuggestion};
 use crate::late::lifetimes::{ElisionFailureInfo, LifetimeContext};
 use crate::late::{AliasPossibility, LateResolutionVisitor, RibKind};
+use crate::late::{LifetimeBinderKind, LifetimeRibKind};
 use crate::path_names_to_string;
 use crate::{Finalize, Module, ModuleKind, ModuleOrUniformRoot};
 use crate::{PathResult, PathSource, Segment};
@@ -19,7 +20,7 @@
 use rustc_hir as hir;
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, CtorOf, DefKind};
-use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::PrimTy;
 use rustc_session::parse::feature_err;
 use rustc_span::edition::Edition;
@@ -351,7 +352,7 @@ pub(crate) fn smart_resolve_report_errors(
                 }
             })
             .collect::<Vec<_>>();
-        let crate_def_id = DefId::local(CRATE_DEF_INDEX);
+        let crate_def_id = CRATE_DEF_ID.to_def_id();
         if candidates.is_empty() && is_expected(Res::Def(DefKind::Enum, crate_def_id)) {
             let mut enum_candidates: Vec<_> = self
                 .r
@@ -1331,10 +1332,8 @@ fn lookup_typo_candidate(
                             names.extend(extern_prelude.iter().flat_map(|(ident, _)| {
                                 self.r.crate_loader.maybe_process_path_extern(ident.name).and_then(
                                     |crate_id| {
-                                        let crate_mod = Res::Def(
-                                            DefKind::Mod,
-                                            DefId { krate: crate_id, index: CRATE_DEF_INDEX },
-                                        );
+                                        let crate_mod =
+                                            Res::Def(DefKind::Mod, crate_id.as_def_id());
 
                                         if filter_fn(crate_mod) {
                                             Some(TypoSuggestion::typo_from_res(
@@ -1793,83 +1792,118 @@ fn suggest_using_enum_variant(
             (*ident, within_scope)
         })
     }
-}
 
-impl<'tcx> LifetimeContext<'_, 'tcx> {
-    crate fn report_missing_lifetime_specifiers(
+    crate fn emit_undeclared_lifetime_error(
         &self,
-        spans: Vec<Span>,
-        count: usize,
-    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-        struct_span_err!(
-            self.tcx.sess,
-            spans,
-            E0106,
-            "missing lifetime specifier{}",
-            pluralize!(count)
-        )
-    }
+        lifetime_ref: &ast::Lifetime,
+        outer_lifetime_ref: Option<Ident>,
+    ) {
+        debug_assert_ne!(lifetime_ref.ident.name, kw::UnderscoreLifetime);
+        let mut err = if let Some(outer) = outer_lifetime_ref {
+            let mut err = struct_span_err!(
+                self.r.session,
+                lifetime_ref.ident.span,
+                E0401,
+                "can't use generic parameters from outer item",
+            );
+            err.span_label(lifetime_ref.ident.span, "use of generic parameter from outer item");
+            err.span_label(outer.span, "lifetime parameter from outer item");
+            err
+        } else {
+            let mut err = struct_span_err!(
+                self.r.session,
+                lifetime_ref.ident.span,
+                E0261,
+                "use of undeclared lifetime name `{}`",
+                lifetime_ref.ident
+            );
+            err.span_label(lifetime_ref.ident.span, "undeclared lifetime");
+            err
+        };
+        let mut suggest_note = true;
 
-    crate fn emit_undeclared_lifetime_error(&self, lifetime_ref: &hir::Lifetime) {
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            lifetime_ref.span,
-            E0261,
-            "use of undeclared lifetime name `{}`",
-            lifetime_ref
-        );
-        err.span_label(lifetime_ref.span, "undeclared lifetime");
-        let mut suggested_spans = vec![];
-        for missing in &self.missing_named_lifetime_spots {
-            match missing {
-                MissingLifetimeSpot::Generics(generics) => {
-                    let (span, sugg) = if let Some(param) = generics.params.iter().find(|p| {
-                        !matches!(
-                            p.kind,
-                            hir::GenericParamKind::Type { synthetic: true, .. }
-                                | hir::GenericParamKind::Lifetime {
-                                    kind: hir::LifetimeParamKind::Elided,
-                                }
-                        )
-                    }) {
-                        (param.span.shrink_to_lo(), format!("{}, ", lifetime_ref))
-                    } else {
-                        (generics.span, format!("<{}>", lifetime_ref))
-                    };
-                    if suggested_spans.contains(&span) {
+        for rib in self.lifetime_ribs.iter().rev() {
+            match rib.kind {
+                LifetimeRibKind::Generics { span, kind } => {
+                    if !span.can_be_used_for_suggestions() && suggest_note {
+                        suggest_note = false; // Avoid displaying the same help multiple times.
+                        err.span_label(
+                            span,
+                            &format!(
+                                "lifetime `{}` is missing in item created through this procedural macro",
+                                lifetime_ref.ident,
+                            ),
+                        );
                         continue;
                     }
-                    suggested_spans.push(span);
-                    if span.can_be_used_for_suggestions() {
+
+                    let higher_ranked = matches!(
+                        kind,
+                        LifetimeBinderKind::BareFnType
+                            | LifetimeBinderKind::PolyTrait
+                            | LifetimeBinderKind::WhereBound
+                    );
+                    let (span, sugg) = if span.is_empty() {
+                        let sugg = format!(
+                            "{}<{}>{}",
+                            if higher_ranked { "for" } else { "" },
+                            lifetime_ref.ident,
+                            if higher_ranked { " " } else { "" },
+                        );
+                        (span, sugg)
+                    } else {
+                        let span =
+                            self.r.session.source_map().span_through_char(span, '<').shrink_to_hi();
+                        let sugg = format!("{}, ", lifetime_ref.ident);
+                        (span, sugg)
+                    };
+                    if higher_ranked {
+                        err.span_suggestion(
+                            span,
+                            &format!(
+                                "consider making the {} lifetime-generic with a new `{}` lifetime",
+                                kind.descr(),
+                                lifetime_ref
+                            ),
+                            sugg,
+                            Applicability::MaybeIncorrect,
+                        );
+                        err.note_once(
+                            "for more information on higher-ranked polymorphism, visit \
+                             https://doc.rust-lang.org/nomicon/hrtb.html",
+                        );
+                    } else {
                         err.span_suggestion(
                             span,
-                            &format!("consider introducing lifetime `{}` here", lifetime_ref),
+                            &format!("consider introducing lifetime `{}` here", lifetime_ref.ident),
                             sugg,
                             Applicability::MaybeIncorrect,
                         );
                     }
                 }
-                MissingLifetimeSpot::HigherRanked { span, span_type } => {
-                    err.span_suggestion(
-                        *span,
-                        &format!(
-                            "consider making the {} lifetime-generic with a new `{}` lifetime",
-                            span_type.descr(),
-                            lifetime_ref
-                        ),
-                        span_type.suggestion(&lifetime_ref.to_string()),
-                        Applicability::MaybeIncorrect,
-                    );
-                    err.note(
-                        "for more information on higher-ranked polymorphism, visit \
-                         https://doc.rust-lang.org/nomicon/hrtb.html",
-                    );
-                }
+                LifetimeRibKind::Item => break,
                 _ => {}
             }
         }
+
         err.emit();
     }
+}
+
+impl<'tcx> LifetimeContext<'_, 'tcx> {
+    crate fn report_missing_lifetime_specifiers(
+        &self,
+        spans: Vec<Span>,
+        count: usize,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+        struct_span_err!(
+            self.tcx.sess,
+            spans,
+            E0106,
+            "missing lifetime specifier{}",
+            pluralize!(count)
+        )
+    }
 
     /// Returns whether to add `'static` lifetime to the suggested lifetime list.
     crate fn report_elision_failure(
@@ -1950,38 +1984,6 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
         }
     }
 
-    crate fn report_elided_lifetime_in_ty(&self, lifetime_refs: &[&hir::Lifetime]) {
-        let Some(missing_lifetime) = lifetime_refs.iter().find(|lt| {
-            lt.name == hir::LifetimeName::Implicit(true)
-        }) else { return };
-
-        let mut spans: Vec<_> = lifetime_refs.iter().map(|lt| lt.span).collect();
-        spans.sort();
-        let mut spans_dedup = spans.clone();
-        spans_dedup.dedup();
-        let spans_with_counts: Vec<_> = spans_dedup
-            .into_iter()
-            .map(|sp| (sp, spans.iter().filter(|nsp| *nsp == &sp).count()))
-            .collect();
-
-        self.tcx.struct_span_lint_hir(
-            rustc_session::lint::builtin::ELIDED_LIFETIMES_IN_PATHS,
-            missing_lifetime.hir_id,
-            spans,
-            |lint| {
-                let mut db = lint.build("hidden lifetime parameters in types are deprecated");
-                self.add_missing_lifetime_specifiers_label(
-                    &mut db,
-                    spans_with_counts,
-                    &FxHashSet::from_iter([kw::UnderscoreLifetime]),
-                    Vec::new(),
-                    &[],
-                );
-                db.emit();
-            },
-        );
-    }
-
     // FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const
     // generics. We are disallowing this until we can decide on how we want to handle non-'static
     // lifetimes in const generics. See issue #74052 for discussion.
@@ -2416,9 +2418,7 @@ fn span_underscore_borrow(&self) -> Span {
         );
         let is_allowed_lifetime = matches!(
             lifetime_ref.name,
-            hir::LifetimeName::Implicit(_)
-                | hir::LifetimeName::Static
-                | hir::LifetimeName::Underscore
+            hir::LifetimeName::Implicit | hir::LifetimeName::Static | hir::LifetimeName::Underscore
         );
 
         if !self.tcx.lazy_normalization() && is_anon_const && !is_allowed_lifetime {
index 2bf01146fae027709d33c1af365940c4859eeb0d..ce3069265d0206381b1c29dda43f0258a8af8428 100644 (file)
@@ -164,9 +164,6 @@ struct NamedRegionMap {
     map: &'a mut NamedRegionMap,
     scope: ScopeRef<'a>,
 
-    /// Used to disallow the use of in-band lifetimes in `fn` or `Fn` syntax.
-    is_in_fn_syntax: bool,
-
     is_in_const_generic: bool,
 
     /// Indicates that we only care about the definition of a trait. This should
@@ -455,7 +452,6 @@ fn do_resolve(
         tcx,
         map: &mut named_region_map,
         scope: ROOT_SCOPE,
-        is_in_fn_syntax: false,
         is_in_const_generic: false,
         trait_definition_only,
         labels_in_fn: vec![],
@@ -689,8 +685,8 @@ fn visit_fn(
         hir_id: hir::HirId,
     ) {
         let name = match fk {
-            intravisit::FnKind::ItemFn(id, _, _, _) => id.name,
-            intravisit::FnKind::Method(id, _, _) => id.name,
+            intravisit::FnKind::ItemFn(id, _, _) => id.name,
+            intravisit::FnKind::Method(id, _) => id.name,
             intravisit::FnKind::Closure => sym::closure,
         };
         let name = name.as_str();
@@ -874,8 +870,6 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
         match ty.kind {
             hir::TyKind::BareFn(ref c) => {
                 let next_early_index = self.next_early_index();
-                let was_in_fn_syntax = self.is_in_fn_syntax;
-                self.is_in_fn_syntax = true;
                 let lifetime_span: Option<Span> =
                     c.generic_params.iter().rev().find_map(|param| match param.kind {
                         GenericParamKind::Lifetime { .. } => Some(param.span),
@@ -917,7 +911,6 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
                     intravisit::walk_ty(this, ty);
                 });
                 self.missing_named_lifetime_spots.pop();
-                self.is_in_fn_syntax = was_in_fn_syntax;
             }
             hir::TyKind::TraitObject(bounds, ref lifetime, _) => {
                 debug!(?bounds, ?lifetime, "TraitObject");
@@ -928,7 +921,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
                     }
                 });
                 match lifetime.name {
-                    LifetimeName::Implicit(_) => {
+                    LifetimeName::Implicit => {
                         // For types like `dyn Foo`, we should
                         // generate a special form of elided.
                         span_bug!(ty.span, "object-lifetime-default expected, not implicit",);
@@ -1805,7 +1798,6 @@ fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
             tcx: *tcx,
             map,
             scope: &wrap_scope,
-            is_in_fn_syntax: self.is_in_fn_syntax,
             is_in_const_generic: self.is_in_const_generic,
             trait_definition_only: self.trait_definition_only,
             labels_in_fn,
@@ -2320,7 +2312,10 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
 
             self.insert_lifetime(lifetime_ref, def);
         } else {
-            self.emit_undeclared_lifetime_error(lifetime_ref);
+            self.tcx.sess.delay_span_bug(
+                lifetime_ref.span,
+                &format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,),
+            );
         }
     }
 
@@ -2336,10 +2331,7 @@ fn visit_segment_args(
         );
 
         if generic_args.parenthesized {
-            let was_in_fn_syntax = self.is_in_fn_syntax;
-            self.is_in_fn_syntax = true;
             self.visit_fn_like_elision(generic_args.inputs(), Some(generic_args.bindings[0].ty()));
-            self.is_in_fn_syntax = was_in_fn_syntax;
             return;
         }
 
@@ -2963,9 +2955,9 @@ fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[&'tcx hir::Lifetime]) {
         let error = loop {
             match *scope {
                 // Do not assign any resolution, it will be inferred.
-                Scope::Body { .. } => break Ok(()),
+                Scope::Body { .. } => return,
 
-                Scope::Root => break Err(None),
+                Scope::Root => break None,
 
                 Scope::Binder { s, ref lifetimes, scope_type, .. } => {
                     // collect named lifetimes for suggestions
@@ -2992,7 +2984,7 @@ fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[&'tcx hir::Lifetime]) {
 
                         self.insert_lifetime(lifetime_ref, lifetime);
                     }
-                    break Ok(());
+                    return;
                 }
 
                 Scope::Elision { elide: Elide::Exact(l), .. } => {
@@ -3000,7 +2992,7 @@ fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[&'tcx hir::Lifetime]) {
                     for lifetime_ref in lifetime_refs {
                         self.insert_lifetime(lifetime_ref, lifetime);
                     }
-                    break Ok(());
+                    return;
                 }
 
                 Scope::Elision { elide: Elide::Error(ref e), ref s, .. } => {
@@ -3025,10 +3017,10 @@ fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[&'tcx hir::Lifetime]) {
                             _ => break,
                         }
                     }
-                    break Err(Some(&e[..]));
+                    break Some(&e[..]);
                 }
 
-                Scope::Elision { elide: Elide::Forbid, .. } => break Err(None),
+                Scope::Elision { elide: Elide::Forbid, .. } => break None,
 
                 Scope::ObjectLifetimeDefault { s, .. }
                 | Scope::Supertrait { s, .. }
@@ -3038,14 +3030,6 @@ fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[&'tcx hir::Lifetime]) {
             }
         };
 
-        let error = match error {
-            Ok(()) => {
-                self.report_elided_lifetime_in_ty(lifetime_refs);
-                return;
-            }
-            Err(error) => error,
-        };
-
         // If we specifically need the `scope_for_path` map, then we're in the
         // diagnostic pass and we don't want to emit more errors.
         if self.map.scope_for_path.is_some() {
@@ -3130,18 +3114,10 @@ fn check_lifetime_params(
             if let hir::ParamName::Plain(_) = lifetime_i_name {
                 let name = lifetime_i_name.ident().name;
                 if name == kw::UnderscoreLifetime || name == kw::StaticLifetime {
-                    let mut err = struct_span_err!(
-                        self.tcx.sess,
-                        lifetime_i.span,
-                        E0262,
-                        "invalid lifetime parameter name: `{}`",
-                        lifetime_i.name.ident(),
-                    );
-                    err.span_label(
+                    self.tcx.sess.delay_span_bug(
                         lifetime_i.span,
-                        format!("{} is a reserved lifetime name", name),
+                        &format!("invalid lifetime parameter name: `{}`", lifetime_i.name.ident()),
                     );
-                    err.emit();
                 }
             }
 
@@ -3190,7 +3166,7 @@ fn check_lifetime_params(
                                 ))
                                 .emit();
                         }
-                        hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit(_) => {
+                        hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit => {
                             self.resolve_lifetime_ref(lt);
                         }
                         hir::LifetimeName::ImplicitObjectLifetimeDefault => {
index b2c7a4d18de386c42a18ce55e126ee724c5bbd5e..cca1f1025866863465fae0b73fd465019ac6bfef 100644 (file)
@@ -11,6 +11,7 @@
 #![feature(drain_filter)]
 #![feature(bool_to_option)]
 #![feature(crate_visibility_modifier)]
+#![feature(if_let_guard)]
 #![feature(let_chains)]
 #![feature(let_else)]
 #![feature(never_type)]
@@ -27,7 +28,7 @@
 use rustc_arena::{DroplessArena, TypedArena};
 use rustc_ast::node_id::NodeMap;
 use rustc_ast::{self as ast, NodeId, CRATE_NODE_ID};
-use rustc_ast::{Crate, Expr, ExprKind, LitKind, Path};
+use rustc_ast::{AngleBracketedArg, Crate, Expr, ExprKind, GenericArg, GenericArgs, LitKind, Path};
 use rustc_ast_lowering::ResolverAstLowering;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_data_structures::intern::Interned;
@@ -37,7 +38,7 @@
 use rustc_hir::def::Namespace::*;
 use rustc_hir::def::{self, CtorOf, DefKind, PartialRes};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefPathHash, LocalDefId};
-use rustc_hir::def_id::{CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPathData, Definitions};
 use rustc_hir::TraitCandidate;
 use rustc_index::vec::IndexVec;
@@ -260,6 +261,8 @@ enum ResolutionError<'a> {
         trait_item_span: Span,
         code: rustc_errors::DiagnosticId,
     },
+    /// Inline asm `sym` operand must refer to a `fn` or `static`.
+    InvalidAsmSym,
 }
 
 enum VisResolutionError<'a> {
@@ -280,6 +283,9 @@ pub struct Segment {
     /// Signals whether this `PathSegment` has generic arguments. Used to avoid providing
     /// nonsensical suggestions.
     has_generic_args: bool,
+    /// Signals whether this `PathSegment` has lifetime arguments.
+    has_lifetime_args: bool,
+    args_span: Span,
 }
 
 impl Segment {
@@ -288,7 +294,23 @@ fn from_path(path: &Path) -> Vec<Segment> {
     }
 
     fn from_ident(ident: Ident) -> Segment {
-        Segment { ident, id: None, has_generic_args: false }
+        Segment {
+            ident,
+            id: None,
+            has_generic_args: false,
+            has_lifetime_args: false,
+            args_span: DUMMY_SP,
+        }
+    }
+
+    fn from_ident_and_id(ident: Ident, id: NodeId) -> Segment {
+        Segment {
+            ident,
+            id: Some(id),
+            has_generic_args: false,
+            has_lifetime_args: false,
+            args_span: DUMMY_SP,
+        }
     }
 
     fn names_to_string(segments: &[Segment]) -> String {
@@ -298,7 +320,28 @@ fn names_to_string(segments: &[Segment]) -> String {
 
 impl<'a> From<&'a ast::PathSegment> for Segment {
     fn from(seg: &'a ast::PathSegment) -> Segment {
-        Segment { ident: seg.ident, id: Some(seg.id), has_generic_args: seg.args.is_some() }
+        let has_generic_args = seg.args.is_some();
+        let (args_span, has_lifetime_args) = if let Some(args) = seg.args.as_deref() {
+            match args {
+                GenericArgs::AngleBracketed(args) => {
+                    let found_lifetimes = args
+                        .args
+                        .iter()
+                        .any(|arg| matches!(arg, AngleBracketedArg::Arg(GenericArg::Lifetime(_))));
+                    (args.span, found_lifetimes)
+                }
+                GenericArgs::Parenthesized(args) => (args.span, true),
+            }
+        } else {
+            (DUMMY_SP, false)
+        };
+        Segment {
+            ident: seg.ident,
+            id: Some(seg.id),
+            has_generic_args,
+            has_lifetime_args,
+            args_span,
+        }
     }
 }
 
@@ -753,7 +796,7 @@ fn is_extern_crate(&self) -> bool {
             NameBindingKind::Module(&ModuleData {
                 kind: ModuleKind::Def(DefKind::Mod, def_id, _),
                 ..
-            }) => def_id.index == CRATE_DEF_INDEX,
+            }) => def_id.is_crate_root(),
             _ => false,
         }
     }
@@ -891,6 +934,7 @@ pub struct Resolver<'a> {
     glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
     /// Visibilities in "lowered" form, for all entities that have them.
     visibilities: FxHashMap<LocalDefId, ty::Visibility>,
+    has_pub_restricted: bool,
     used_imports: FxHashSet<NodeId>,
     maybe_unused_trait_imports: FxHashSet<LocalDefId>,
     maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,
@@ -1205,18 +1249,17 @@ pub fn new(
         );
 
         let definitions = Definitions::new(session.local_stable_crate_id(), krate.spans.inner_span);
-        let root = definitions.get_root_def();
 
         let mut visibilities = FxHashMap::default();
         visibilities.insert(CRATE_DEF_ID, ty::Visibility::Public);
 
         let mut def_id_to_node_id = IndexVec::default();
-        assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), root);
+        assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), CRATE_DEF_ID);
         let mut node_id_to_def_id = FxHashMap::default();
-        node_id_to_def_id.insert(CRATE_NODE_ID, root);
+        node_id_to_def_id.insert(CRATE_NODE_ID, CRATE_DEF_ID);
 
         let mut invocation_parents = FxHashMap::default();
-        invocation_parents.insert(LocalExpnId::ROOT, (root, ImplTraitContext::Existential));
+        invocation_parents.insert(LocalExpnId::ROOT, (CRATE_DEF_ID, ImplTraitContext::Existential));
 
         let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'_>> = session
             .opts
@@ -1271,6 +1314,7 @@ pub fn new(
 
             glob_map: Default::default(),
             visibilities,
+            has_pub_restricted: false,
             used_imports: FxHashSet::default(),
             maybe_unused_trait_imports: Default::default(),
             maybe_unused_extern_crates: Vec::new(),
@@ -1356,9 +1400,17 @@ fn new_module(
     }
 
     pub fn next_node_id(&mut self) -> NodeId {
-        let next =
-            self.next_node_id.as_u32().checked_add(1).expect("input too large; ran out of NodeIds");
-        mem::replace(&mut self.next_node_id, ast::NodeId::from_u32(next))
+        let start = self.next_node_id;
+        let next = start.as_u32().checked_add(1).expect("input too large; ran out of NodeIds");
+        self.next_node_id = ast::NodeId::from_u32(next);
+        start
+    }
+
+    pub fn next_node_ids(&mut self, count: usize) -> std::ops::Range<NodeId> {
+        let start = self.next_node_id;
+        let end = start.as_usize().checked_add(count).expect("input too large; ran out of NodeIds");
+        self.next_node_id = ast::NodeId::from_usize(end);
+        start..self.next_node_id
     }
 
     pub fn lint_buffer(&mut self) -> &mut LintBuffer {
@@ -1373,6 +1425,7 @@ pub fn into_outputs(self) -> ResolverOutputs {
         let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect();
         let definitions = self.definitions;
         let visibilities = self.visibilities;
+        let has_pub_restricted = self.has_pub_restricted;
         let extern_crate_map = self.extern_crate_map;
         let reexport_map = self.reexport_map;
         let maybe_unused_trait_imports = self.maybe_unused_trait_imports;
@@ -1385,6 +1438,7 @@ pub fn into_outputs(self) -> ResolverOutputs {
             definitions,
             cstore: Box::new(self.crate_loader.into_cstore()),
             visibilities,
+            has_pub_restricted,
             access_levels,
             extern_crate_map,
             reexport_map,
@@ -1411,6 +1465,7 @@ pub fn clone_outputs(&self) -> ResolverOutputs {
             access_levels: self.access_levels.clone(),
             cstore: Box::new(self.cstore().clone()),
             visibilities: self.visibilities.clone(),
+            has_pub_restricted: self.has_pub_restricted,
             extern_crate_map: self.extern_crate_map.clone(),
             reexport_map: self.reexport_map.clone(),
             glob_map: self.glob_map.clone(),
index 22d0a20395ec7d77b62a9811f14049940e55f1a2..6681ea9d299cf057c69b0090b03de10541a45f4a 100644 (file)
@@ -25,7 +25,6 @@
 use rustc_middle::span_bug;
 use rustc_middle::ty::{self, DefIdTree, TyCtxt};
 use rustc_session::config::Input;
-use rustc_span::source_map::respan;
 use rustc_span::symbol::Ident;
 use rustc_span::*;
 
@@ -57,20 +56,14 @@ macro_rules! down_cast_data {
 }
 
 macro_rules! access_from {
-    ($save_ctxt:expr, $item:expr, $id:expr) => {
+    ($save_ctxt:expr, $id:expr) => {
         Access {
-            public: $item.vis.node.is_pub(),
+            public: $save_ctxt.tcx.visibility($id).is_public(),
             reachable: $save_ctxt.access_levels.is_reachable($id),
         }
     };
 }
 
-macro_rules! access_from_vis {
-    ($save_ctxt:expr, $vis:expr, $id:expr) => {
-        Access { public: $vis.node.is_pub(), reachable: $save_ctxt.access_levels.is_reachable($id) }
-    };
-}
-
 pub struct DumpVisitor<'tcx> {
     pub save_ctxt: SaveContext<'tcx>,
     tcx: TyCtxt<'tcx>,
@@ -257,7 +250,6 @@ fn process_method(
         def_id: LocalDefId,
         ident: Ident,
         generics: &'tcx hir::Generics<'tcx>,
-        vis: &hir::Visibility<'tcx>,
         span: Span,
     ) {
         debug!("process_method: {:?}:{}", def_id, ident);
@@ -272,10 +264,10 @@ fn process_method(
                 v.process_generic_params(&generics, &method_data.qualname, hir_id);
 
                 method_data.value =
-                    fn_to_string(sig.decl, sig.header, Some(ident.name), generics, vis, &[], None);
+                    fn_to_string(sig.decl, sig.header, Some(ident.name), generics, &[], None);
                 method_data.sig = sig::method_signature(hir_id, ident, generics, sig, &v.save_ctxt);
 
-                v.dumper.dump_def(&access_from_vis!(v.save_ctxt, vis, def_id), method_data);
+                v.dumper.dump_def(&access_from!(v.save_ctxt, def_id), method_data);
             }
 
             // walk arg and return types
@@ -302,7 +294,7 @@ fn process_struct_field_def(
         let field_data = self.save_ctxt.get_field_data(field, parent_id);
         if let Some(field_data) = field_data {
             self.dumper.dump_def(
-                &access_from!(self.save_ctxt, field, self.tcx.hir().local_def_id(field.hir_id)),
+                &access_from!(self.save_ctxt, self.tcx.hir().local_def_id(field.hir_id)),
                 field_data,
             );
         }
@@ -369,7 +361,7 @@ fn process_fn(
                 v.process_formals(body.params, &fn_data.qualname);
                 v.process_generic_params(ty_params, &fn_data.qualname, item.hir_id());
 
-                v.dumper.dump_def(&access_from!(v.save_ctxt, item, item.def_id), fn_data);
+                v.dumper.dump_def(&access_from!(v.save_ctxt, item.def_id), fn_data);
             }
 
             for arg in decl.inputs {
@@ -393,7 +385,7 @@ fn process_static_or_const_item(
         self.nest_typeck_results(item.def_id, |v| {
             if let Some(var_data) = v.save_ctxt.get_item_data(item) {
                 down_cast_data!(var_data, DefData, item.span);
-                v.dumper.dump_def(&access_from!(v.save_ctxt, item, item.def_id), var_data);
+                v.dumper.dump_def(&access_from!(v.save_ctxt, item.def_id), var_data);
             }
             v.visit_ty(&typ);
             v.visit_expr(expr);
@@ -407,7 +399,6 @@ fn process_assoc_const(
         typ: &'tcx hir::Ty<'tcx>,
         expr: Option<&'tcx hir::Expr<'tcx>>,
         parent_id: DefId,
-        vis: &hir::Visibility<'tcx>,
         attrs: &'tcx [ast::Attribute],
     ) {
         let qualname = format!("::{}", self.tcx.def_path_str(def_id.to_def_id()));
@@ -418,7 +409,7 @@ fn process_assoc_const(
             let span = self.span_from_span(ident.span);
 
             self.dumper.dump_def(
-                &access_from_vis!(self.save_ctxt, vis, def_id),
+                &access_from!(self.save_ctxt, def_id),
                 Def {
                     kind: DefKind::Const,
                     id: id_from_hir_id(hir_id, &self.save_ctxt),
@@ -469,7 +460,11 @@ fn process_struct(
                 let fields_str = fields
                     .iter()
                     .filter_map(|f| {
-                        if include_priv_fields || f.vis.node.is_pub() {
+                        if include_priv_fields {
+                            return Some(f.ident.to_string());
+                        }
+                        let def_id = self.save_ctxt.tcx.hir().local_def_id(f.hir_id);
+                        if self.save_ctxt.tcx.visibility(def_id).is_public() {
                             Some(f.ident.to_string())
                         } else {
                             None
@@ -487,7 +482,7 @@ fn process_struct(
             let span = self.span_from_span(item.ident.span);
             let attrs = self.tcx.hir().attrs(item.hir_id());
             self.dumper.dump_def(
-                &access_from!(self.save_ctxt, item, item.def_id),
+                &access_from!(self.save_ctxt, item.def_id),
                 Def {
                     kind,
                     id: id_from_def_id(item.def_id.to_def_id()),
@@ -527,7 +522,7 @@ fn process_enum(
         };
         down_cast_data!(enum_data, DefData, item.span);
 
-        let access = access_from!(self.save_ctxt, item, item.def_id);
+        let access = access_from!(self.save_ctxt, item.def_id);
 
         for variant in enum_definition.variants {
             let name = variant.ident.name.to_string();
@@ -662,7 +657,7 @@ fn process_trait(
                 methods.iter().map(|i| id_from_def_id(i.id.def_id.to_def_id())).collect();
             let attrs = self.tcx.hir().attrs(item.hir_id());
             self.dumper.dump_def(
-                &access_from!(self.save_ctxt, item, item.def_id),
+                &access_from!(self.save_ctxt, item.def_id),
                 Def {
                     kind: DefKind::Trait,
                     id,
@@ -724,7 +719,7 @@ fn process_trait(
     fn process_mod(&mut self, item: &'tcx hir::Item<'tcx>) {
         if let Some(mod_data) = self.save_ctxt.get_item_data(item) {
             down_cast_data!(mod_data, DefData, item.span);
-            self.dumper.dump_def(&access_from!(self.save_ctxt, item, item.def_id), mod_data);
+            self.dumper.dump_def(&access_from!(self.save_ctxt, item.def_id), mod_data);
         }
     }
 
@@ -979,11 +974,9 @@ fn process_macro_use(&mut self, _span: Span) {
 
     fn process_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>, trait_id: DefId) {
         self.process_macro_use(trait_item.span);
-        let vis_span = trait_item.span.shrink_to_lo();
         match trait_item.kind {
             hir::TraitItemKind::Const(ref ty, body) => {
                 let body = body.map(|b| &self.tcx.hir().body(b).value);
-                let respan = respan(vis_span, hir::VisibilityKind::Public);
                 let attrs = self.tcx.hir().attrs(trait_item.hir_id());
                 self.process_assoc_const(
                     trait_item.def_id,
@@ -991,21 +984,18 @@ fn process_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>, trait_i
                     &ty,
                     body,
                     trait_id,
-                    &respan,
                     attrs,
                 );
             }
             hir::TraitItemKind::Fn(ref sig, ref trait_fn) => {
                 let body =
                     if let hir::TraitFn::Provided(body) = trait_fn { Some(*body) } else { None };
-                let respan = respan(vis_span, hir::VisibilityKind::Public);
                 self.process_method(
                     sig,
                     body,
                     trait_item.def_id,
                     trait_item.ident,
                     &trait_item.generics,
-                    &respan,
                     trait_item.span,
                 );
             }
@@ -1064,7 +1054,6 @@ fn process_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>, impl_id: D
                     &ty,
                     Some(&body.value),
                     impl_id,
-                    &impl_item.vis,
                     attrs,
                 );
             }
@@ -1075,7 +1064,6 @@ fn process_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>, impl_id: D
                     impl_item.def_id,
                     impl_item.ident,
                     &impl_item.generics,
-                    &impl_item.vis,
                     impl_item.span,
                 );
             }
@@ -1147,7 +1135,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
             hir::ItemKind::Use(path, hir::UseKind::Single) => {
                 let sub_span = path.segments.last().unwrap().ident.span;
                 if !self.span.filter_generated(sub_span) {
-                    let access = access_from!(self.save_ctxt, item, item.def_id);
+                    let access = access_from!(self.save_ctxt, item.def_id);
                     let ref_id = self.lookup_def_id(item.hir_id()).map(id_from_def_id);
                     let span = self.span_from_span(sub_span);
                     let parent =
@@ -1176,7 +1164,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                 // we don't want to track anyway, since it's probably macro-internal `use`
                 if let Some(sub_span) = self.span.sub_span_of_star(item.span) {
                     if !self.span.filter_generated(item.span) {
-                        let access = access_from!(self.save_ctxt, item, item.def_id);
+                        let access = access_from!(self.save_ctxt, item.def_id);
                         let span = self.span_from_span(sub_span);
                         let parent =
                             self.save_ctxt.tcx.parent(item.def_id.to_def_id()).map(id_from_def_id);
@@ -1249,7 +1237,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                     let attrs = self.tcx.hir().attrs(item.hir_id());
 
                     self.dumper.dump_def(
-                        &access_from!(self.save_ctxt, item, item.def_id),
+                        &access_from!(self.save_ctxt, item.def_id),
                         Def {
                             kind: DefKind::Type,
                             id,
@@ -1443,7 +1431,7 @@ fn visit_local(&mut self, l: &'tcx hir::Local<'tcx>) {
     }
 
     fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
-        let access = access_from!(self.save_ctxt, item, item.def_id);
+        let access = access_from!(self.save_ctxt, item.def_id);
 
         match item.kind {
             hir::ForeignItemKind::Fn(decl, _, ref generics) => {
index 102268c6ca3524b1b7e39c51bb02217f6925f148..582186cbd1fe7221c30c5655bc4c9b7fe97b1421 100644 (file)
@@ -27,7 +27,6 @@
 use rustc_session::config::{CrateType, Input, OutputType};
 use rustc_session::cstore::ExternCrate;
 use rustc_session::output::{filename_for_metadata, out_filename};
-use rustc_span::source_map::Spanned;
 use rustc_span::symbol::Ident;
 use rustc_span::*;
 
@@ -165,7 +164,6 @@ pub fn get_extern_item_data(&self, item: &hir::ForeignItem<'_>) -> Option<Data>
                         },
                         Some(item.ident.name),
                         generics,
-                        &item.vis,
                         arg_names,
                         None,
                     ),
@@ -221,7 +219,6 @@ pub fn get_item_data(&self, item: &hir::Item<'_>) -> Option<Data> {
                         sig.header,
                         Some(item.ident.name),
                         generics,
-                        &item.vis,
                         &[],
                         None,
                     ),
@@ -310,7 +307,7 @@ pub fn get_item_data(&self, item: &hir::Item<'_>) -> Option<Data> {
                 let qualname = format!("::{}", self.tcx.def_path_str(def_id));
                 filter!(self.span_utils, item.ident.span);
                 let value =
-                    enum_def_to_string(def, generics, item.ident.name, item.span, &item.vis);
+                    enum_def_to_string(def, generics, item.ident.name, item.span);
                 Some(Data::DefData(Def {
                     kind: DefKind::Enum,
                     id: id_from_def_id(def_id),
@@ -595,11 +592,6 @@ pub fn get_path_res(&self, hir_id: hir::HirId) -> Res {
             Node::TraitRef(tr) => tr.path.res,
 
             Node::Item(&hir::Item { kind: hir::ItemKind::Use(path, _), .. }) => path.res,
-            Node::Visibility(&Spanned {
-                node: hir::VisibilityKind::Restricted { ref path, .. },
-                ..
-            }) => path.res,
-
             Node::PathSegment(seg) => match seg.res {
                 Some(res) if res != Res::Err => res,
                 _ => {
index 5a447aa6237345f2e6c608666f90bf0fecc34a8f..925f6bfd93d3cdf90f80671e2087fe1354175e0e 100644 (file)
@@ -3,20 +3,18 @@
 
 pub use crate::options::*;
 
-use crate::lint;
 use crate::search_paths::SearchPath;
 use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
 use crate::{early_error, early_warn, Session};
+use crate::{lint, HashStableContext};
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::impl_stable_hash_via_hash;
 
+use rustc_data_structures::stable_hasher::ToStableHashKey;
 use rustc_target::abi::{Align, TargetDataLayout};
 use rustc_target::spec::{LinkerFlavor, SplitDebuginfo, Target, TargetTriple, TargetWarnings};
 use rustc_target::spec::{PanicStrategy, SanitizerSet, TARGETS};
 
-use rustc_serialize::json;
-
 use crate::parse::{CrateCheckConfig, CrateConfig};
 use rustc_feature::UnstableFeatures;
 use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION};
@@ -80,7 +78,7 @@ pub enum CFProtection {
     Full,
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Hash)]
+#[derive(Clone, Copy, Debug, PartialEq, Hash, HashStable_Generic)]
 pub enum OptLevel {
     No,         // -O0
     Less,       // -O1
@@ -90,8 +88,6 @@ pub enum OptLevel {
     SizeMin,    // -Oz
 }
 
-impl_stable_hash_via_hash!(OptLevel);
-
 /// This is what the `LtoCli` values get mapped to after resolving defaults and
 /// and taking other command line options into account.
 ///
@@ -232,15 +228,13 @@ pub fn enabled(&self) -> bool {
     }
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable_Generic)]
 #[derive(Encodable, Decodable)]
 pub enum SymbolManglingVersion {
     Legacy,
     V0,
 }
 
-impl_stable_hash_via_hash!(SymbolManglingVersion);
-
 #[derive(Clone, Copy, Debug, PartialEq, Hash)]
 pub enum DebugInfo {
     None,
@@ -279,7 +273,7 @@ fn from_str(s: &str) -> Result<Self, ()> {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, HashStable_Generic)]
 #[derive(Encodable, Decodable)]
 pub enum OutputType {
     Bitcode,
@@ -292,7 +286,13 @@ pub enum OutputType {
     DepInfo,
 }
 
-impl_stable_hash_via_hash!(OutputType);
+impl<HCX: HashStableContext> ToStableHashKey<HCX> for OutputType {
+    type KeyType = Self;
+
+    fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType {
+        *self
+    }
+}
 
 impl OutputType {
     fn is_compatible_with_codegen_units_and_single_output_file(&self) -> bool {
@@ -398,7 +398,7 @@ pub enum TrimmedDefPaths {
 /// *Do not* switch `BTreeMap` out for an unsorted container type! That would break
 /// dependency tracking for command-line arguments. Also only hash keys, since tracking
 /// should only depend on the output types, not the paths they're written to.
-#[derive(Clone, Debug, Hash)]
+#[derive(Clone, Debug, Hash, HashStable_Generic)]
 pub struct OutputTypes(BTreeMap<OutputType, Option<PathBuf>>);
 
 impl OutputTypes {
@@ -460,9 +460,6 @@ pub fn should_link(&self) -> bool {
 #[derive(Clone)]
 pub struct Externs(BTreeMap<String, ExternEntry>);
 
-#[derive(Clone)]
-pub struct ExternDepSpecs(BTreeMap<String, ExternDepSpec>);
-
 #[derive(Clone, Debug)]
 pub struct ExternEntry {
     pub location: ExternLocation,
@@ -477,6 +474,11 @@ pub struct ExternEntry {
     /// This can be disabled with the `noprelude` option like
     /// `--extern noprelude:name`.
     pub add_prelude: bool,
+    /// The extern entry shouldn't be considered for unused dependency warnings.
+    ///
+    /// `--extern nounused:std=/path/to/lib/libstd.rlib`. This is used to
+    /// suppress `unused-crate-dependencies` warnings.
+    pub nounused_dep: bool,
 }
 
 #[derive(Clone, Debug)]
@@ -494,27 +496,6 @@ pub enum ExternLocation {
     ExactPaths(BTreeSet<CanonicalizedPath>),
 }
 
-/// Supplied source location of a dependency - for example in a build specification
-/// file like Cargo.toml. We support several syntaxes: if it makes sense to reference
-/// a file and line, then the build system can specify that. On the other hand, it may
-/// make more sense to have an arbitrary raw string.
-#[derive(Clone, PartialEq)]
-pub enum ExternDepSpec {
-    /// Raw string
-    Raw(String),
-    /// Raw data in json format
-    Json(json::Json),
-}
-
-impl<'a> From<&'a ExternDepSpec> for rustc_lint_defs::ExternDepSpec {
-    fn from(from: &'a ExternDepSpec) -> Self {
-        match from {
-            ExternDepSpec::Raw(s) => rustc_lint_defs::ExternDepSpec::Raw(s.clone()),
-            ExternDepSpec::Json(json) => rustc_lint_defs::ExternDepSpec::Json(json.clone()),
-        }
-    }
-}
-
 impl Externs {
     /// Used for testing.
     pub fn new(data: BTreeMap<String, ExternEntry>) -> Externs {
@@ -536,7 +517,7 @@ pub fn len(&self) -> usize {
 
 impl ExternEntry {
     fn new(location: ExternLocation) -> ExternEntry {
-        ExternEntry { location, is_private_dep: false, add_prelude: false }
+        ExternEntry { location, is_private_dep: false, add_prelude: false, nounused_dep: false }
     }
 
     pub fn files(&self) -> Option<impl Iterator<Item = &CanonicalizedPath>> {
@@ -547,25 +528,6 @@ pub fn files(&self) -> Option<impl Iterator<Item = &CanonicalizedPath>> {
     }
 }
 
-impl ExternDepSpecs {
-    pub fn new(data: BTreeMap<String, ExternDepSpec>) -> ExternDepSpecs {
-        ExternDepSpecs(data)
-    }
-
-    pub fn get(&self, key: &str) -> Option<&ExternDepSpec> {
-        self.0.get(key)
-    }
-}
-
-impl fmt::Display for ExternDepSpec {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            ExternDepSpec::Raw(raw) => fmt.write_str(raw),
-            ExternDepSpec::Json(json) => json::as_json(json).fmt(fmt),
-        }
-    }
-}
-
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum PrintRequest {
     FileNames,
@@ -630,7 +592,7 @@ pub fn source_name(&self) -> FileName {
     }
 }
 
-#[derive(Clone, Hash, Debug)]
+#[derive(Clone, Hash, Debug, HashStable_Generic)]
 pub struct OutputFilenames {
     pub out_directory: PathBuf,
     filestem: String,
@@ -639,8 +601,6 @@ pub struct OutputFilenames {
     pub outputs: OutputTypes,
 }
 
-impl_stable_hash_via_hash!(OutputFilenames);
-
 pub const RLINK_EXT: &str = "rlink";
 pub const RUST_CGU_EXT: &str = "rcgu";
 pub const DWARF_OBJECT_EXT: &str = "dwo";
@@ -785,7 +745,6 @@ fn default() -> Options {
             cg: Default::default(),
             error_format: ErrorOutputType::default(),
             externs: Externs(BTreeMap::new()),
-            extern_dep_specs: ExternDepSpecs(BTreeMap::new()),
             crate_name: None,
             libs: Vec::new(),
             unstable_features: UnstableFeatures::Disallow,
@@ -854,15 +813,14 @@ pub fn diagnostic_handler_flags(&self, can_emit_warnings: bool) -> HandlerFlags
 }
 
 // The type of entry function, so users can have their own entry functions
-#[derive(Copy, Clone, PartialEq, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Hash, Debug, HashStable_Generic)]
 pub enum EntryFnType {
     Main,
     Start,
 }
 
-impl_stable_hash_via_hash!(EntryFnType);
-
 #[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)]
+#[derive(HashStable_Generic)]
 pub enum CrateType {
     Executable,
     Dylib,
@@ -872,8 +830,6 @@ pub enum CrateType {
     ProcMacro,
 }
 
-impl_stable_hash_via_hash!(CrateType);
-
 impl CrateType {
     /// When generated, is this crate type an archive?
     pub fn is_archive(&self) -> bool {
@@ -1454,12 +1410,6 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
             "Specify where an external rust library is located",
             "NAME[=PATH]",
         ),
-        opt::multi_s(
-            "",
-            "extern-location",
-            "Location where an external crate dependency is specified",
-            "NAME=LOCATION",
-        ),
         opt::opt_s("", "sysroot", "Override the system root", "PATH"),
         opt::multi("Z", "", "Set internal debugging options", "FLAG"),
         opt::opt_s(
@@ -2186,6 +2136,7 @@ pub fn parse_externs(
 
         let mut is_private_dep = false;
         let mut add_prelude = true;
+        let mut nounused_dep = false;
         if let Some(opts) = options {
             if !is_unstable_enabled {
                 early_error(
@@ -2207,6 +2158,7 @@ pub fn parse_externs(
                             );
                         }
                     }
+                    "nounused" => nounused_dep = true,
                     _ => early_error(error_format, &format!("unknown --extern option `{opt}`")),
                 }
             }
@@ -2215,74 +2167,14 @@ pub fn parse_externs(
         // Crates start out being not private, and go to being private `priv`
         // is specified.
         entry.is_private_dep |= is_private_dep;
+        // likewise `nounused`
+        entry.nounused_dep |= nounused_dep;
         // If any flag is missing `noprelude`, then add to the prelude.
         entry.add_prelude |= add_prelude;
     }
     Externs(externs)
 }
 
-fn parse_extern_dep_specs(
-    matches: &getopts::Matches,
-    debugging_opts: &DebuggingOptions,
-    error_format: ErrorOutputType,
-) -> ExternDepSpecs {
-    let is_unstable_enabled = debugging_opts.unstable_options;
-    let mut map = BTreeMap::new();
-
-    for arg in matches.opt_strs("extern-location") {
-        if !is_unstable_enabled {
-            early_error(
-                error_format,
-                "`--extern-location` option is unstable: set `-Z unstable-options`",
-            );
-        }
-
-        let mut parts = arg.splitn(2, '=');
-        let name = parts.next().unwrap_or_else(|| {
-            early_error(error_format, "`--extern-location` value must not be empty")
-        });
-        let loc = parts.next().unwrap_or_else(|| {
-            early_error(
-                error_format,
-                &format!("`--extern-location`: specify location for extern crate `{name}`"),
-            )
-        });
-
-        let locparts: Vec<_> = loc.split(':').collect();
-        let spec = match &locparts[..] {
-            ["raw", ..] => {
-                // Don't want `:` split string
-                let raw = loc.splitn(2, ':').nth(1).unwrap_or_else(|| {
-                    early_error(error_format, "`--extern-location`: missing `raw` location")
-                });
-                ExternDepSpec::Raw(raw.to_string())
-            }
-            ["json", ..] => {
-                // Don't want `:` split string
-                let raw = loc.splitn(2, ':').nth(1).unwrap_or_else(|| {
-                    early_error(error_format, "`--extern-location`: missing `json` location")
-                });
-                let json = json::from_str(raw).unwrap_or_else(|_| {
-                    early_error(
-                        error_format,
-                        &format!("`--extern-location`: malformed json location `{raw}`"),
-                    )
-                });
-                ExternDepSpec::Json(json)
-            }
-            [bad, ..] => early_error(
-                error_format,
-                &format!("unknown location type `{bad}`: use `raw` or `json`"),
-            ),
-            [] => early_error(error_format, "missing location specification"),
-        };
-
-        map.insert(name.to_string(), spec);
-    }
-
-    ExternDepSpecs::new(map)
-}
-
 fn parse_remap_path_prefix(
     matches: &getopts::Matches,
     debugging_opts: &DebuggingOptions,
@@ -2525,7 +2417,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
     }
 
     let externs = parse_externs(matches, &debugging_opts, error_format);
-    let extern_dep_specs = parse_extern_dep_specs(matches, &debugging_opts, error_format);
 
     let crate_name = matches.opt_str("crate-name");
 
@@ -2601,7 +2492,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         error_format,
         externs,
         unstable_features: UnstableFeatures::from_environment(crate_name.as_deref()),
-        extern_dep_specs,
         crate_name,
         libs,
         debug_assertions,
index 4994f8eaeb2dcaae287369413334f0710c10c62b..96f50e57ac4d0efe779ec63c14fc44a3a1c1c2f0 100644 (file)
@@ -183,7 +183,6 @@ pub struct Options {
         borrowck_mode: BorrowckMode [UNTRACKED],
         cg: CodegenOptions [SUBSTRUCT],
         externs: Externs [UNTRACKED],
-        extern_dep_specs: ExternDepSpecs [UNTRACKED],
         crate_name: Option<String> [TRACKED],
         /// Indicates how the compiler should treat unstable features.
         unstable_features: UnstableFeatures [TRACKED],
@@ -369,6 +368,8 @@ mod desc {
     pub const parse_opt_langid: &str = "a language identifier";
     pub const parse_opt_pathbuf: &str = "a path";
     pub const parse_list: &str = "a space-separated list of strings";
+    pub const parse_list_with_polarity: &str =
+        "a comma-separated list of strings, with elements beginning with + or -";
     pub const parse_opt_comma_list: &str = "a comma-separated list of strings";
     pub const parse_number: &str = "a number";
     pub const parse_opt_number: &str = parse_number;
@@ -530,6 +531,19 @@ mod parse {
         }
     }
 
+    crate fn parse_list_with_polarity(slot: &mut Vec<(String, bool)>, v: Option<&str>) -> bool {
+        match v {
+            Some(s) => {
+                for s in s.split(",") {
+                    let Some(pass_name) = s.strip_prefix(&['+', '-'][..]) else { return false };
+                    slot.push((pass_name.to_string(), &s[..1] == "+"));
+                }
+                true
+            }
+            None => false,
+        }
+    }
+
     crate fn parse_location_detail(ld: &mut LocationDetail, v: Option<&str>) -> bool {
         if let Some(v) = v {
             ld.line = false;
@@ -1319,6 +1333,10 @@ mod parse {
     mir_emit_retag: bool = (false, parse_bool, [TRACKED],
         "emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \
         (default: no)"),
+    mir_enable_passes: Vec<(String, bool)> = (Vec::new(), parse_list_with_polarity, [TRACKED],
+        "use like `-Zmir-enable-passes=+DestProp,-InstCombine`. Forces the specified passes to be \
+        enabled, overriding all other checks. Passes that are not specified are enabled or \
+        disabled by other flags as usual."),
     mir_opt_level: Option<usize> = (None, parse_opt_number, [TRACKED],
         "MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"),
     move_size_limit: Option<usize> = (None, parse_opt_number, [TRACKED],
index b6bde28233d243bc2ad86c0e5619111f3bc1d6d7..56a6b6f3b03efe6d18c98fd80ad69e1fa6c5af2c 100644 (file)
@@ -26,7 +26,7 @@ pub struct SearchPathFile {
     pub file_name_str: String,
 }
 
-#[derive(PartialEq, Clone, Copy, Debug, Hash, Eq, Encodable, Decodable)]
+#[derive(PartialEq, Clone, Copy, Debug, Hash, Eq, Encodable, Decodable, HashStable_Generic)]
 pub enum PathKind {
     Native,
     Crate,
@@ -36,8 +36,6 @@ pub enum PathKind {
     All,
 }
 
-rustc_data_structures::impl_stable_hash_via_hash!(PathKind);
-
 impl PathKind {
     pub fn matches(&self, kind: PathKind) -> bool {
         match (self, kind) {
index 9a286d94ab89da3aa65042e8d9b14fba2e268acd..8064c217457bb561bc66185b27d75822f0fbce1e 100644 (file)
@@ -18,6 +18,7 @@ pub fn time<R>(&self, what: &'static str, f: impl FnOnce() -> R) -> R {
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
+#[derive(HashStable_Generic)]
 pub enum NativeLibKind {
     /// Static library (e.g. `libfoo.a` on Linux or `foo.lib` on Windows/MSVC)
     Static {
@@ -57,9 +58,8 @@ pub fn has_modifiers(&self) -> bool {
     }
 }
 
-rustc_data_structures::impl_stable_hash_via_hash!(NativeLibKind);
-
 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
+#[derive(HashStable_Generic)]
 pub struct NativeLib {
     pub name: String,
     pub new_name: Option<String>,
@@ -73,8 +73,6 @@ pub fn has_modifiers(&self) -> bool {
     }
 }
 
-rustc_data_structures::impl_stable_hash_via_hash!(NativeLib);
-
 /// A path that has been canonicalized along with its original, non-canonicalized form
 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
 pub struct CanonicalizedPath {
index 6d1b36796d869fec88463521d022bc76dea66489..d5f806308cf41bbca3b16ea67cd7f1fe77278fd5 100644 (file)
@@ -283,8 +283,19 @@ pub fn expect_local(self) -> LocalDefId {
         self.as_local().unwrap_or_else(|| panic!("DefId::expect_local: `{:?}` isn't local", self))
     }
 
+    #[inline]
+    pub fn is_crate_root(self) -> bool {
+        self.index == CRATE_DEF_INDEX
+    }
+
+    #[inline]
+    pub fn as_crate_root(self) -> Option<CrateNum> {
+        if self.is_crate_root() { Some(self.krate) } else { None }
+    }
+
+    #[inline]
     pub fn is_top_level_module(self) -> bool {
-        self.is_local() && self.index == CRATE_DEF_INDEX
+        self.is_local() && self.is_crate_root()
     }
 }
 
@@ -357,7 +368,7 @@ pub fn to_def_id(self) -> DefId {
 
     #[inline]
     pub fn is_top_level_module(self) -> bool {
-        self.local_def_index == CRATE_DEF_INDEX
+        self == CRATE_DEF_ID
     }
 }
 
index 7ebf323e20d8889dacd9dc4c2aab2399c67ca9e8..3889639b50f454bf232b430c17bbf9ff86397db1 100644 (file)
@@ -103,16 +103,6 @@ impl !PartialOrd for LocalExpnId {}
 /// of `HashingControls` settings.
 fn assert_default_hashing_controls<CTX: HashStableContext>(ctx: &CTX, msg: &str) {
     match ctx.hashing_controls() {
-        // Ideally, we would also check that `node_id_hashing_mode` was always
-        // `NodeIdHashingMode::HashDefPath`. However, we currently end up hashing
-        // `Span`s in this mode, and there's not an easy way to change that.
-        // All of the span-related data that we hash is pretty self-contained
-        // (in particular, we don't hash any `HirId`s), so this shouldn't result
-        // in any caching problems.
-        // FIXME: Enforce that we don't end up transitively hashing any `HirId`s,
-        // or ensure that this method is always invoked with the same
-        // `NodeIdHashingMode`
-        //
         // Note that we require that `hash_spans` be set according to the global
         // `-Z incremental-ignore-spans` option. Normally, this option is disabled,
         // which will cause us to require that this method always be called with `Span` hashing
index b132c0a2132b724b0077f3019432112d4a1ba55e..f22faef2580a56c6482570ba083e44fc790eb548 100644 (file)
@@ -59,6 +59,8 @@
 mod analyze_source_file;
 pub mod fatal_error;
 
+pub mod profiling;
+
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{Lock, Lrc};
 
@@ -1130,6 +1132,7 @@ pub fn get_source(&self) -> Option<&Lrc<String>> {
 pub struct OffsetOverflowError;
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
+#[derive(HashStable_Generic)]
 pub enum SourceFileHashAlgorithm {
     Md5,
     Sha1,
@@ -1149,8 +1152,6 @@ fn from_str(s: &str) -> Result<SourceFileHashAlgorithm, ()> {
     }
 }
 
-rustc_data_structures::impl_stable_hash_via_hash!(SourceFileHashAlgorithm);
-
 /// The hash of the on-disk source file used for debug info.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 #[derive(HashStable_Generic, Encodable, Decodable)]
diff --git a/compiler/rustc_span/src/profiling.rs b/compiler/rustc_span/src/profiling.rs
new file mode 100644 (file)
index 0000000..f169007
--- /dev/null
@@ -0,0 +1,35 @@
+use std::borrow::Borrow;
+
+use rustc_data_structures::profiling::EventArgRecorder;
+
+/// Extension trait for self-profiling purposes: allows to record spans within a generic activity's
+/// event arguments.
+pub trait SpannedEventArgRecorder {
+    /// Records the following event arguments within the current generic activity being profiled:
+    /// - the provided `event_arg`
+    /// - a string representation of the provided `span`
+    ///
+    /// Note: when self-profiling with costly event arguments, at least one argument
+    /// needs to be recorded. A panic will be triggered if that doesn't happen.
+    fn record_arg_with_span<A>(&mut self, event_arg: A, span: crate::Span)
+    where
+        A: Borrow<str> + Into<String>;
+}
+
+impl SpannedEventArgRecorder for EventArgRecorder<'_> {
+    fn record_arg_with_span<A>(&mut self, event_arg: A, span: crate::Span)
+    where
+        A: Borrow<str> + Into<String>,
+    {
+        self.record_arg(event_arg);
+
+        let span_arg = crate::with_session_globals(|session_globals| {
+            if let Some(source_map) = &*session_globals.source_map.borrow() {
+                source_map.span_to_embeddable_string(span)
+            } else {
+                format!("{:?}", span)
+            }
+        });
+        self.record_arg(span_arg);
+    }
+}
index f6acb3c76fe588f6a455fca793157fd5cab8a095..e3ce8105a8b47a825ccb5499944993015f4bea92 100644 (file)
         keyword,
         kind,
         kreg,
+        kreg0,
         label,
         label_break_value,
         lang,
         simd,
         simd_add,
         simd_and,
+        simd_arith_offset,
         simd_as,
         simd_bitmask,
         simd_cast,
index 611943652a6a151abe17c7b6ca35960829735dab..37d1cffa2a52b9e1f6cc482a1208df1c52a53b4f 100644 (file)
@@ -4,7 +4,6 @@
 //! def-path. This is used for unit testing the code that generates
 //! paths etc in all kinds of annoying scenarios.
 
-use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{subst::InternalSubsts, Instance, TyCtxt};
@@ -22,8 +21,24 @@ pub fn report_symbol_names(tcx: TyCtxt<'_>) {
     }
 
     tcx.dep_graph.with_ignore(|| {
-        let mut visitor = SymbolNamesTest { tcx };
-        tcx.hir().visit_all_item_likes(&mut visitor);
+        let mut symbol_names = SymbolNamesTest { tcx };
+        let crate_items = tcx.hir_crate_items(());
+
+        for id in crate_items.items() {
+            symbol_names.process_attrs(id.def_id);
+        }
+
+        for id in crate_items.trait_items() {
+            symbol_names.process_attrs(id.def_id);
+        }
+
+        for id in crate_items.impl_items() {
+            symbol_names.process_attrs(id.def_id);
+        }
+
+        for id in crate_items.foreign_items() {
+            symbol_names.process_attrs(id.def_id);
+        }
     })
 }
 
@@ -58,21 +73,3 @@ fn process_attrs(&mut self, def_id: LocalDefId) {
         }
     }
 }
-
-impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for SymbolNamesTest<'tcx> {
-    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        self.process_attrs(item.def_id);
-    }
-
-    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
-        self.process_attrs(trait_item.def_id);
-    }
-
-    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
-        self.process_attrs(impl_item.def_id);
-    }
-
-    fn visit_foreign_item(&mut self, foreign_item: &'tcx hir::ForeignItem<'tcx>) {
-        self.process_attrs(foreign_item.def_id);
-    }
-}
index 5bc4b566daf67f86a241082c544ba75b90a6444d..6bc807c7c4421649f89e81867da730d26a88b733 100644 (file)
@@ -893,7 +893,7 @@ macro_rules! clobbered_regs {
 
                     xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
 
-                    k1, k2, k3, k4, k5, k6, k7,
+                    k0, k1, k2, k3, k4, k5, k6, k7,
 
                     mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7,
                     st0, st1, st2, st3, st4, st5, st6, st7,
@@ -908,7 +908,7 @@ macro_rules! clobbered_regs {
                     zmm16, zmm17, zmm18, zmm19, zmm20, zmm21, zmm22, zmm23,
                     zmm24, zmm25, zmm26, zmm27, zmm28, zmm29, zmm30, zmm31,
 
-                    k1, k2, k3, k4, k5, k6, k7,
+                    k0, k1, k2, k3, k4, k5, k6, k7,
 
                     mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7,
                     st0, st1, st2, st3, st4, st5, st6, st7,
@@ -927,7 +927,7 @@ macro_rules! clobbered_regs {
                     zmm16, zmm17, zmm18, zmm19, zmm20, zmm21, zmm22, zmm23,
                     zmm24, zmm25, zmm26, zmm27, zmm28, zmm29, zmm30, zmm31,
 
-                    k1, k2, k3, k4, k5, k6, k7,
+                    k0, k1, k2, k3, k4, k5, k6, k7,
 
                     mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7,
                     st0, st1, st2, st3, st4, st5, st6, st7,
index 7c136a475486b63eb835a2e3bdac065f6204f54a..854674c7f2fa7c98804c4ce6cc28bc9d5c483a9b 100644 (file)
@@ -14,6 +14,7 @@
         ymm_reg,
         zmm_reg,
         kreg,
+        kreg0,
         mmx_reg,
         x87_reg,
     }
@@ -38,7 +39,7 @@ pub fn valid_modifiers(self, arch: super::InlineAsmArch) -> &'static [char] {
             }
             Self::reg_byte => &[],
             Self::xmm_reg | Self::ymm_reg | Self::zmm_reg => &['x', 'y', 'z'],
-            Self::kreg => &[],
+            Self::kreg | Self::kreg0 => &[],
             Self::mmx_reg | Self::x87_reg => &[],
         }
     }
@@ -77,7 +78,7 @@ pub fn suggest_modifier(
                 256 => Some(('y', "ymm0")),
                 _ => Some(('x', "xmm0")),
             },
-            Self::kreg => None,
+            Self::kreg | Self::kreg0 => None,
             Self::mmx_reg | Self::x87_reg => None,
         }
     }
@@ -95,7 +96,7 @@ pub fn default_modifier(self, arch: InlineAsmArch) -> Option<(char, &'static str
             Self::xmm_reg => Some(('x', "xmm0")),
             Self::ymm_reg => Some(('y', "ymm0")),
             Self::zmm_reg => Some(('z', "zmm0")),
-            Self::kreg => None,
+            Self::kreg | Self::kreg0 => None,
             Self::mmx_reg | Self::x87_reg => None,
         }
     }
@@ -132,6 +133,7 @@ pub fn supported_types(
                 avx512f: I8, I16;
                 avx512bw: I32, I64;
             },
+            Self::kreg0 => &[],
             Self::mmx_reg | Self::x87_reg => &[],
         }
     }
@@ -294,6 +296,7 @@ fn esi_reserved(
         zmm29: zmm_reg = ["zmm29", "xmm29", "ymm29"] % x86_64_only,
         zmm30: zmm_reg = ["zmm30", "xmm30", "ymm30"] % x86_64_only,
         zmm31: zmm_reg = ["zmm31", "xmm31", "ymm31"] % x86_64_only,
+        k0: kreg0 = ["k0"],
         k1: kreg = ["k1"],
         k2: kreg = ["k2"],
         k3: kreg = ["k3"],
@@ -323,8 +326,6 @@ fn esi_reserved(
             "the stack pointer cannot be used as an operand for inline asm",
         #error = ["ip", "eip", "rip"] =>
             "the instruction pointer cannot be used as an operand for inline asm",
-        #error = ["k0"] =>
-            "the k0 AVX mask register cannot be used as an operand for inline asm",
     }
 }
 
index 0cb70de241596080f181260637f8fac47d3e6246..50e4fafdd6c829c44fe8212e244993f5689a0b3b 100644 (file)
@@ -1654,7 +1654,15 @@ fn report_projection_error(
                     }),
                 _ => None,
             };
-            self.note_type_err(&mut diag, &obligation.cause, secondary_span, values, err, true);
+            self.note_type_err(
+                &mut diag,
+                &obligation.cause,
+                secondary_span,
+                values,
+                err,
+                true,
+                false,
+            );
             self.note_obligation_cause(&mut diag, obligation);
             diag.emit();
         });
index ead1f0126c465a37c5ebac944dc2caee60075500..0c1ca65c48f6adb9230785eb5e494973c04cc70c 100644 (file)
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node};
+use rustc_middle::hir::map;
 use rustc_middle::ty::{
     self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree,
-    Infer, InferTy, ToPredicate, Ty, TyCtxt, TypeFoldable,
+    GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, ToPredicate, Ty, TyCtxt,
+    TypeFoldable,
 };
 use rustc_middle::ty::{TypeAndMut, TypeckResults};
 use rustc_session::Limit;
@@ -44,6 +46,123 @@ pub enum GeneratorInteriorOrUpvar {
     Upvar(Span),
 }
 
+// This type provides a uniform interface to retrieve data on generators, whether it originated from
+// the local crate being compiled or from a foreign crate.
+#[derive(Debug)]
+pub enum GeneratorData<'tcx, 'a> {
+    Local(&'a TypeckResults<'tcx>),
+    Foreign(&'tcx GeneratorDiagnosticData<'tcx>),
+}
+
+impl<'tcx, 'a> GeneratorData<'tcx, 'a> {
+    // Try to get information about variables captured by the generator that matches a type we are
+    // looking for with `ty_matches` function. We uses it to find upvar which causes a failure to
+    // meet an obligation
+    fn try_get_upvar_span<F>(
+        &self,
+        infer_context: &InferCtxt<'a, 'tcx>,
+        generator_did: DefId,
+        ty_matches: F,
+    ) -> Option<GeneratorInteriorOrUpvar>
+    where
+        F: Fn(ty::Binder<'tcx, Ty<'tcx>>) -> bool,
+    {
+        match self {
+            GeneratorData::Local(typeck_results) => {
+                infer_context.tcx.upvars_mentioned(generator_did).and_then(|upvars| {
+                    upvars.iter().find_map(|(upvar_id, upvar)| {
+                        let upvar_ty = typeck_results.node_type(*upvar_id);
+                        let upvar_ty = infer_context.resolve_vars_if_possible(upvar_ty);
+                        if ty_matches(ty::Binder::dummy(upvar_ty)) {
+                            Some(GeneratorInteriorOrUpvar::Upvar(upvar.span))
+                        } else {
+                            None
+                        }
+                    })
+                })
+            }
+            GeneratorData::Foreign(_) => None,
+        }
+    }
+
+    // Try to get the span of a type being awaited on that matches the type we are looking with the
+    // `ty_matches` function. We uses it to find awaited type which causes a failure to meet an
+    // obligation
+    fn get_from_await_ty<F>(
+        &self,
+        visitor: AwaitsVisitor,
+        hir: map::Map<'tcx>,
+        ty_matches: F,
+    ) -> Option<Span>
+    where
+        F: Fn(ty::Binder<'tcx, Ty<'tcx>>) -> bool,
+    {
+        match self {
+            GeneratorData::Local(typeck_results) => visitor
+                .awaits
+                .into_iter()
+                .map(|id| hir.expect_expr(id))
+                .find(|await_expr| {
+                    ty_matches(ty::Binder::dummy(typeck_results.expr_ty_adjusted(&await_expr)))
+                })
+                .map(|expr| expr.span),
+            GeneratorData::Foreign(generator_diagnostic_data) => visitor
+                .awaits
+                .into_iter()
+                .map(|id| hir.expect_expr(id))
+                .find(|await_expr| {
+                    ty_matches(ty::Binder::dummy(
+                        generator_diagnostic_data
+                            .adjustments
+                            .get(&await_expr.hir_id.local_id)
+                            .map_or::<&[ty::adjustment::Adjustment<'tcx>], _>(&[], |a| &a[..])
+                            .last()
+                            .map_or_else::<Ty<'tcx>, _, _>(
+                                || {
+                                    generator_diagnostic_data
+                                        .nodes_types
+                                        .get(&await_expr.hir_id.local_id)
+                                        .cloned()
+                                        .unwrap_or_else(|| {
+                                            bug!(
+                                                "node_type: no type for node `{}`",
+                                                ty::tls::with(|tcx| tcx
+                                                    .hir()
+                                                    .node_to_string(await_expr.hir_id))
+                                            )
+                                        })
+                                },
+                                |adj| adj.target,
+                            ),
+                    ))
+                })
+                .map(|expr| expr.span),
+        }
+    }
+
+    /// Get the type, expression, span and optional scope span of all types
+    /// that are live across the yield of this generator
+    fn get_generator_interior_types(
+        &self,
+    ) -> ty::Binder<'tcx, &Vec<GeneratorInteriorTypeCause<'tcx>>> {
+        match self {
+            GeneratorData::Local(typeck_result) => typeck_result.generator_interior_types.as_ref(),
+            GeneratorData::Foreign(generator_diagnostic_data) => {
+                generator_diagnostic_data.generator_interior_types.as_ref()
+            }
+        }
+    }
+
+    // Used to get the source of the data, note we don't have as much information for generators
+    // originated from foreign crates
+    fn is_foreign(&self) -> bool {
+        match self {
+            GeneratorData::Local(_) => false,
+            GeneratorData::Foreign(_) => true,
+        }
+    }
+}
+
 // This trait is public to expose the diagnostics methods to clippy.
 pub trait InferCtxtExt<'tcx> {
     fn suggest_restricting_param_bound(
@@ -152,7 +271,7 @@ fn note_obligation_cause_for_async_await(
         err: &mut Diagnostic,
         interior_or_upvar_span: GeneratorInteriorOrUpvar,
         interior_extra_info: Option<(Option<Span>, Span, Option<hir::HirId>, Option<Span>)>,
-        inner_generator_body: Option<&hir::Body<'tcx>>,
+        is_async: bool,
         outer_generator: Option<DefId>,
         trait_pred: ty::TraitPredicate<'tcx>,
         target_ty: Ty<'tcx>,
@@ -1642,6 +1761,17 @@ fn maybe_note_obligation_cause_for_async_await(
             .map(|def_id| hir.local_def_id_to_hir_id(def_id))
             .and_then(|hir_id| hir.maybe_body_owned_by(hir_id))
             .map(|body_id| hir.body(body_id));
+        let is_async = match generator_did.as_local() {
+            Some(_) => generator_body
+                .and_then(|body| body.generator_kind())
+                .map(|generator_kind| matches!(generator_kind, hir::GeneratorKind::Async(..)))
+                .unwrap_or(false),
+            None => self
+                .tcx
+                .generator_kind(generator_did)
+                .map(|generator_kind| matches!(generator_kind, hir::GeneratorKind::Async(..)))
+                .unwrap_or(false),
+        };
         let mut visitor = AwaitsVisitor::default();
         if let Some(body) = generator_body {
             visitor.visit_body(body);
@@ -1682,61 +1812,55 @@ fn maybe_note_obligation_cause_for_async_await(
         // type-checking; otherwise, get them by performing a query.  This is needed to avoid
         // cycles. If we can't use resolved types because the generator comes from another crate,
         // we still provide a targeted error but without all the relevant spans.
-        let query_typeck_results;
-        let typeck_results: Option<&TypeckResults<'tcx>> = match &in_progress_typeck_results {
-            Some(t) if t.hir_owner.to_def_id() == generator_did_root => Some(&t),
+        let generator_data: Option<GeneratorData<'tcx, '_>> = match &in_progress_typeck_results {
+            Some(t) if t.hir_owner.to_def_id() == generator_did_root => {
+                Some(GeneratorData::Local(&t))
+            }
             _ if generator_did.is_local() => {
-                query_typeck_results = self.tcx.typeck(generator_did.expect_local());
-                Some(&query_typeck_results)
+                Some(GeneratorData::Local(self.tcx.typeck(generator_did.expect_local())))
             }
-            _ => None, // Do not ICE on closure typeck (#66868).
+            _ => self
+                .tcx
+                .generator_diagnostic_data(generator_did)
+                .as_ref()
+                .map(|generator_diag_data| GeneratorData::Foreign(generator_diag_data)),
         };
-        if let Some(typeck_results) = typeck_results {
-            if let Some(upvars) = self.tcx.upvars_mentioned(generator_did) {
-                interior_or_upvar_span = upvars.iter().find_map(|(upvar_id, upvar)| {
-                    let upvar_ty = typeck_results.node_type(*upvar_id);
-                    let upvar_ty = self.resolve_vars_if_possible(upvar_ty);
-                    if ty_matches(ty::Binder::dummy(upvar_ty)) {
-                        Some(GeneratorInteriorOrUpvar::Upvar(upvar.span))
-                    } else {
-                        None
-                    }
-                });
-            };
+
+        if let Some(generator_data) = generator_data.as_ref() {
+            interior_or_upvar_span =
+                generator_data.try_get_upvar_span(&self, generator_did, ty_matches);
 
             // The generator interior types share the same binders
             if let Some(cause) =
-                typeck_results.generator_interior_types.as_ref().skip_binder().iter().find(
+                generator_data.get_generator_interior_types().skip_binder().iter().find(
                     |ty::GeneratorInteriorTypeCause { ty, .. }| {
-                        ty_matches(typeck_results.generator_interior_types.rebind(*ty))
+                        ty_matches(generator_data.get_generator_interior_types().rebind(*ty))
                     },
                 )
             {
-                // Check to see if any awaited expressions have the target type.
-                let from_awaited_ty = visitor
-                    .awaits
-                    .into_iter()
-                    .map(|id| hir.expect_expr(id))
-                    .find(|await_expr| {
-                        ty_matches(ty::Binder::dummy(typeck_results.expr_ty_adjusted(&await_expr)))
-                    })
-                    .map(|expr| expr.span);
+                let from_awaited_ty = generator_data.get_from_await_ty(visitor, hir, ty_matches);
                 let ty::GeneratorInteriorTypeCause { span, scope_span, yield_span, expr, .. } =
                     cause;
 
                 interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(*span));
                 interior_extra_info = Some((*scope_span, *yield_span, *expr, from_awaited_ty));
-            };
-        } else {
-            interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(span));
+            }
+
+            if interior_or_upvar_span.is_none() && generator_data.is_foreign() {
+                interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(span));
+            }
         }
 
         if let Some(interior_or_upvar_span) = interior_or_upvar_span {
+            let typeck_results = generator_data.and_then(|generator_data| match generator_data {
+                GeneratorData::Local(typeck_results) => Some(typeck_results),
+                GeneratorData::Foreign(_) => None,
+            });
             self.note_obligation_cause_for_async_await(
                 err,
                 interior_or_upvar_span,
                 interior_extra_info,
-                generator_body,
+                is_async,
                 outer_generator,
                 trait_ref,
                 target_ty,
@@ -1757,7 +1881,7 @@ fn note_obligation_cause_for_async_await(
         err: &mut Diagnostic,
         interior_or_upvar_span: GeneratorInteriorOrUpvar,
         interior_extra_info: Option<(Option<Span>, Span, Option<hir::HirId>, Option<Span>)>,
-        inner_generator_body: Option<&hir::Body<'tcx>>,
+        is_async: bool,
         outer_generator: Option<DefId>,
         trait_pred: ty::TraitPredicate<'tcx>,
         target_ty: Ty<'tcx>,
@@ -1767,10 +1891,6 @@ fn note_obligation_cause_for_async_await(
     ) {
         let source_map = self.tcx.sess.source_map();
 
-        let is_async = inner_generator_body
-            .and_then(|body| body.generator_kind())
-            .map(|generator_kind| matches!(generator_kind, hir::GeneratorKind::Async(..)))
-            .unwrap_or(false);
         let (await_or_yield, an_await_or_yield) =
             if is_async { ("await", "an await") } else { ("yield", "a yield") };
         let future_or_generator = if is_async { "future" } else { "generator" };
@@ -2724,9 +2844,9 @@ fn suggest_derive(
                 &format!(
                     "consider annotating `{}` with `#[derive({})]`",
                     trait_pred.skip_binder().self_ty(),
-                    diagnostic_name.to_string(),
+                    diagnostic_name,
                 ),
-                format!("#[derive({})]\n", diagnostic_name.to_string()),
+                format!("#[derive({})]\n", diagnostic_name),
                 Applicability::MaybeIncorrect,
             );
         }
index 1a10b07cc2706fa28038dc04960ebfab847c212c..38cc74a5e37348ccca400456140e43b9650d210b 100644 (file)
@@ -10,7 +10,6 @@
 use rustc_span::{Span, DUMMY_SP};
 
 use std::collections::BTreeSet;
-use std::iter;
 
 impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     /// On missing type parameters, emit an E0393 error and provide a structured suggestion using
@@ -323,6 +322,7 @@ pub(crate) fn complain_about_missing_associated_types(
         let mut suggestions = vec![];
         let mut types_count = 0;
         let mut where_constraints = vec![];
+        let mut already_has_generics_args_suggestion = false;
         for (span, assoc_items) in &associated_types {
             let mut names: FxHashMap<_, usize> = FxHashMap::default();
             for item in assoc_items {
@@ -343,16 +343,10 @@ pub(crate) fn complain_about_missing_associated_types(
                 }
             }
             if potential_assoc_types.len() == assoc_items.len() {
-                // Only suggest when the amount of missing associated types equals the number of
-                // extra type arguments present, as that gives us a relatively high confidence
-                // that the user forgot to give the associated type's name. The canonical
-                // example would be trying to use `Iterator<isize>` instead of
-                // `Iterator<Item = isize>`.
-                for (potential, item) in iter::zip(&potential_assoc_types, assoc_items) {
-                    if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*potential) {
-                        suggestions.push((*potential, format!("{} = {}", item.name, snippet)));
-                    }
-                }
+                // When the amount of missing associated types equals the number of
+                // extra type arguments present.  A suggesting to replace the generic args with
+                // associated types is already emitted.
+                already_has_generics_args_suggestion = true;
             } else if let (Ok(snippet), false) =
                 (tcx.sess.source_map().span_to_snippet(*span), dupes)
             {
@@ -382,7 +376,7 @@ pub(crate) fn complain_about_missing_associated_types(
             // the same associated type name.
             err.help(where_msg);
         }
-        if suggestions.len() != 1 {
+        if suggestions.len() != 1 || already_has_generics_args_suggestion {
             // We don't need this label if there's an inline suggestion, show otherwise.
             for (span, assoc_items) in &associated_types {
                 let mut names: FxHashMap<_, usize> = FxHashMap::default();
index 6bae0f2eac9545b5cb1c92d4a6bf84f4526d2e9e..1cd0ace8adb052ab23d242516c85198138156f60 100644 (file)
@@ -2563,40 +2563,77 @@ pub fn ty_of_fn(
 
         // We proactively collect all the inferred type params to emit a single error per fn def.
         let mut visitor = HirPlaceholderCollector::default();
-        for ty in decl.inputs {
-            visitor.visit_ty(ty);
-        }
+        let mut infer_replacements = vec![];
+
         walk_generics(&mut visitor, generics);
 
-        let input_tys = decl.inputs.iter().map(|a| self.ty_of_arg(a, None));
+        let input_tys: Vec<_> = decl
+            .inputs
+            .iter()
+            .enumerate()
+            .map(|(i, a)| {
+                if let hir::TyKind::Infer = a.kind && !self.allow_ty_infer() {
+                    if let Some(suggested_ty) =
+                        self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i))
+                    {
+                        infer_replacements.push((a.span, suggested_ty.to_string()));
+                        return suggested_ty;
+                    }
+                }
+
+                // Only visit the type looking for `_` if we didn't fix the type above
+                visitor.visit_ty(a);
+                self.ty_of_arg(a, None)
+            })
+            .collect();
+
         let output_ty = match decl.output {
             hir::FnRetTy::Return(output) => {
-                visitor.visit_ty(output);
-                self.ast_ty_to_ty(output)
+                if let hir::TyKind::Infer = output.kind
+                    && !self.allow_ty_infer()
+                    && let Some(suggested_ty) =
+                        self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
+                {
+                    infer_replacements.push((output.span, suggested_ty.to_string()));
+                    suggested_ty
+                } else {
+                    visitor.visit_ty(output);
+                    self.ast_ty_to_ty(output)
+                }
             }
             hir::FnRetTy::DefaultReturn(..) => tcx.mk_unit(),
         };
 
         debug!("ty_of_fn: output_ty={:?}", output_ty);
 
-        let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi);
+        let fn_ty = tcx.mk_fn_sig(input_tys.into_iter(), output_ty, decl.c_variadic, unsafety, abi);
         let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars);
 
-        if !self.allow_ty_infer() {
+        if !self.allow_ty_infer() && !(visitor.0.is_empty() && infer_replacements.is_empty()) {
             // We always collect the spans for placeholder types when evaluating `fn`s, but we
             // only want to emit an error complaining about them if infer types (`_`) are not
             // allowed. `allow_ty_infer` gates this behavior. We check for the presence of
             // `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`.
 
-            crate::collect::placeholder_type_error(
+            let mut diag = crate::collect::placeholder_type_error_diag(
                 tcx,
                 ident_span.map(|sp| sp.shrink_to_hi()),
                 generics.params,
                 visitor.0,
+                infer_replacements.iter().map(|(s, _)| *s).collect(),
                 true,
                 hir_ty,
                 "function",
             );
+
+            if !infer_replacements.is_empty() {
+                diag.multipart_suggestion(&format!(
+                    "try replacing `_` with the type{} in the corresponding trait method signature",
+                    rustc_errors::pluralize!(infer_replacements.len()),
+                ), infer_replacements, Applicability::MachineApplicable);
+            }
+
+            diag.emit();
         }
 
         // Find any late-bound regions declared in return type that do
@@ -2624,6 +2661,43 @@ pub fn ty_of_fn(
         bare_fn_ty
     }
 
+    /// Given a fn_hir_id for a impl function, suggest the type that is found on the
+    /// corresponding function in the trait that the impl implements, if it exists.
+    /// If arg_idx is Some, then it corresponds to an input type index, otherwise it
+    /// corresponds to the return type.
+    fn suggest_trait_fn_ty_for_impl_fn_infer(
+        &self,
+        fn_hir_id: hir::HirId,
+        arg_idx: Option<usize>,
+    ) -> Option<Ty<'tcx>> {
+        let tcx = self.tcx();
+        let hir = tcx.hir();
+
+        let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), ident, .. }) =
+            hir.get(fn_hir_id) else { return None };
+        let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(i), .. }) =
+                hir.get(hir.get_parent_node(fn_hir_id)) else { bug!("ImplItem should have Impl parent") };
+
+        let trait_ref =
+            self.instantiate_mono_trait_ref(i.of_trait.as_ref()?, self.ast_ty_to_ty(i.self_ty));
+
+        let x: &ty::AssocItem = tcx.associated_items(trait_ref.def_id).find_by_name_and_kind(
+            tcx,
+            *ident,
+            ty::AssocKind::Fn,
+            trait_ref.def_id,
+        )?;
+
+        let fn_sig = tcx.fn_sig(x.def_id).subst(
+            tcx,
+            trait_ref.substs.extend_to(tcx, x.def_id, |param, _| tcx.mk_param_from_def(param)),
+        );
+
+        let ty = if let Some(arg_idx) = arg_idx { fn_sig.input(arg_idx) } else { fn_sig.output() };
+
+        Some(tcx.erase_late_bound_regions(ty))
+    }
+
     fn validate_late_bound_regions(
         &self,
         constrained_regions: FxHashSet<ty::BoundRegionKind>,
index 049940d19a651b3622f278c0b829c3097abe27c2..a153997599aba5dafb5822172b1bc1ffbd1c8ccd 100644 (file)
@@ -993,20 +993,33 @@ fn lossy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_c: ty::cast::I
                 ));
 
                 let msg = "use `.addr()` to obtain the address of a pointer";
-                if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
-                    let scalar_cast = match t_c {
-                        ty::cast::IntTy::U(ty::UintTy::Usize) => String::new(),
-                        _ => format!(" as {}", self.cast_ty),
-                    };
+
+                let expr_prec = self.expr.precedence().order();
+                let needs_parens = expr_prec < rustc_ast::util::parser::PREC_POSTFIX;
+
+                let scalar_cast = match t_c {
+                    ty::cast::IntTy::U(ty::UintTy::Usize) => String::new(),
+                    _ => format!(" as {}", self.cast_ty),
+                };
+
+                let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span);
+
+                if needs_parens {
+                    let suggestions = vec![
+                        (self.expr_span.shrink_to_lo(), String::from("(")),
+                        (cast_span, format!(").addr(){scalar_cast}")),
+                    ];
+
+                    err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
+                } else {
                     err.span_suggestion(
-                        self.span,
+                        cast_span,
                         msg,
-                        format!("({snippet}).addr(){scalar_cast}"),
-                        Applicability::MaybeIncorrect
+                        format!(".addr(){scalar_cast}"),
+                        Applicability::MaybeIncorrect,
                     );
-                } else {
-                    err.help(msg);
                 }
+
                 err.help(
                     "if you can't comply with strict provenance and need to expose the pointer \
                     provenance you can use `.expose_addr()` instead"
@@ -1028,16 +1041,12 @@ fn fuzzy_provenance_int2ptr_lint(&self, fcx: &FnCtxt<'a, 'tcx>) {
                     self.expr_ty, self.cast_ty
                 ));
                 let msg = "use `.with_addr()` to adjust a valid pointer in the same allocation, to this address";
-                if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
-                    err.span_suggestion(
-                        self.span,
-                        msg,
-                        format!("(...).with_addr({snippet})"),
-                        Applicability::HasPlaceholders,
-                    );
-                } else {
-                    err.help(msg);
-                }
+                let suggestions = vec![
+                    (self.expr_span.shrink_to_lo(), String::from("(...).with_addr(")),
+                    (self.expr_span.shrink_to_hi().to(self.cast_span), String::from(")")),
+                ];
+
+                err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
                 err.help(
                     "if you can't comply with strict provenance and don't have a pointer with \
                     the correct provenance you can use `std::ptr::from_exposed_addr()` instead"
index 3162de38aaea1ca7e0afca8911d43373d1522eb4..b44baf83cbe1e61fecbf61c6e31debf86eb6f6c7 100644 (file)
@@ -1499,7 +1499,7 @@ pub fn coerce_forced_unit<'a>(
                         found,
                         expected,
                         None,
-                        coercion_error,
+                        Some(coercion_error),
                     );
                 }
 
index 4aa46c21fce91313288e77f433de1eaee71c9b23..4ab6f2cdafbc7ee7140b29442a81bd03a7069c02 100644 (file)
@@ -384,6 +384,7 @@ fn compare_predicate_entailment<'tcx>(
                 })),
                 &terr,
                 false,
+                false,
             );
 
             return Err(diag.emit());
@@ -1072,6 +1073,7 @@ fn compare_const_param_types<'tcx>(
                 })),
                 &terr,
                 false,
+                false,
             );
             diag.emit();
         }
index 7c5a312c40e628589b6529b0ef9e25ef827b98c5..f377cf3678e40e7a3e0e92d39cd0c2b15869e848 100644 (file)
@@ -28,7 +28,7 @@ pub fn emit_coerce_suggestions(
         expr_ty: Ty<'tcx>,
         expected: Ty<'tcx>,
         expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
-        error: TypeError<'tcx>,
+        error: Option<TypeError<'tcx>>,
     ) {
         self.annotate_expected_due_to_let_ty(err, expr, error);
         self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr);
@@ -150,7 +150,7 @@ pub fn demand_coerce_diag(
         let expr_ty = self.resolve_vars_with_obligations(checked_ty);
         let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e.clone());
 
-        self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, e);
+        self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, Some(e));
 
         (expected, Some(err))
     }
@@ -159,7 +159,7 @@ fn annotate_expected_due_to_let_ty(
         &self,
         err: &mut Diagnostic,
         expr: &hir::Expr<'_>,
-        error: TypeError<'_>,
+        error: Option<TypeError<'_>>,
     ) {
         let parent = self.tcx.hir().get_parent_node(expr.hir_id);
         match (self.tcx.hir().find(parent), error) {
@@ -173,7 +173,7 @@ fn annotate_expected_due_to_let_ty(
                 Some(hir::Node::Expr(hir::Expr {
                     kind: hir::ExprKind::Assign(lhs, rhs, _), ..
                 })),
-                TypeError::Sorts(ExpectedFound { expected, .. }),
+                Some(TypeError::Sorts(ExpectedFound { expected, .. })),
             ) if rhs.hir_id == expr.hir_id && !expected.is_closure() => {
                 // We ignore closures explicitly because we already point at them elsewhere.
                 // Point at the assigned-to binding.
index 4d15dd715f1fcf61b8ea8ade03cd4f1395a9c06c..e88082dbb9744e36c57a8b3c7f558c0a37333a16 100644 (file)
@@ -259,7 +259,7 @@ pub(super) fn check_expr_with_expectation_and_args(
     }
 
     #[instrument(skip(self, expr), level = "debug")]
-    fn check_expr_kind(
+    pub(super) fn check_expr_kind(
         &self,
         expr: &'tcx hir::Expr<'tcx>,
         expected: Expectation<'tcx>,
@@ -1366,11 +1366,13 @@ fn check_expr_struct_fields(
     ) {
         let tcx = self.tcx;
 
-        let adt_ty_hint = self
-            .expected_inputs_for_expected_output(span, expected, adt_ty, &[adt_ty])
-            .get(0)
-            .cloned()
-            .unwrap_or(adt_ty);
+        let expected_inputs =
+            self.expected_inputs_for_expected_output(span, expected, adt_ty, &[adt_ty]);
+        let adt_ty_hint = if let Some(expected_inputs) = expected_inputs {
+            expected_inputs.get(0).cloned().unwrap_or(adt_ty)
+        } else {
+            adt_ty
+        };
         // re-link the regions that EIfEO can erase.
         self.demand_eqtype(span, adt_ty_hint, adt_ty);
 
@@ -2520,12 +2522,11 @@ fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx> {
                         self.check_expr_asm_operand(out_expr, false);
                     }
                 }
-                hir::InlineAsmOperand::Const { anon_const } => {
+                hir::InlineAsmOperand::Const { anon_const }
+                | hir::InlineAsmOperand::SymFn { anon_const } => {
                     self.to_const(anon_const);
                 }
-                hir::InlineAsmOperand::Sym { expr } => {
-                    self.check_expr(expr);
-                }
+                hir::InlineAsmOperand::SymStatic { .. } => {}
             }
         }
         if asm.options.contains(ast::InlineAsmOptions::NORETURN) {
index d403d6e3f33828ccd16d4021e994b6df18dc9e55..152be4bd5382906b728fb6d67fa9eb2f606bd640 100644 (file)
@@ -755,9 +755,9 @@ pub(in super::super) fn expected_inputs_for_expected_output(
         expected_ret: Expectation<'tcx>,
         formal_ret: Ty<'tcx>,
         formal_args: &[Ty<'tcx>],
-    ) -> Vec<Ty<'tcx>> {
+    ) -> Option<Vec<Ty<'tcx>>> {
         let formal_ret = self.resolve_vars_with_obligations(formal_ret);
-        let Some(ret_ty) = expected_ret.only_has_type(self) else { return Vec::new() };
+        let Some(ret_ty) = expected_ret.only_has_type(self) else { return None };
 
         // HACK(oli-obk): This is a hack to keep RPIT and TAIT in sync wrt their behaviour.
         // Without it, the inference
@@ -779,7 +779,7 @@ pub(in super::super) fn expected_inputs_for_expected_output(
                 if let ty::subst::GenericArgKind::Type(ty) = ty.unpack() {
                     if let ty::Opaque(def_id, _) = *ty.kind() {
                         if self.infcx.opaque_type_origin(def_id, DUMMY_SP).is_some() {
-                            return Vec::new();
+                            return None;
                         }
                     }
                 }
@@ -820,7 +820,7 @@ pub(in super::super) fn expected_inputs_for_expected_output(
 
                 // Record all the argument types, with the substitutions
                 // produced from the above subtyping unification.
-                Ok(formal_args.iter().map(|&ty| self.resolve_vars_if_possible(ty)).collect())
+                Ok(Some(formal_args.iter().map(|&ty| self.resolve_vars_if_possible(ty)).collect()))
             })
             .unwrap_or_default();
         debug!(?formal_args, ?formal_ret, ?expect_args, ?expected_ret);
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/arg_matrix.rs b/compiler/rustc_typeck/src/check/fn_ctxt/arg_matrix.rs
new file mode 100644 (file)
index 0000000..48a66e8
--- /dev/null
@@ -0,0 +1,343 @@
+use std::cmp;
+
+use rustc_middle::ty::error::TypeError;
+
+// An issue that might be found in the compatibility matrix
+enum Issue {
+    /// The given argument is the invalid type for the input
+    Invalid(usize),
+    /// There is a missing input
+    Missing(usize),
+    /// There's a superfluous argument
+    Extra(usize),
+    /// Two arguments should be swapped
+    Swap(usize, usize),
+    /// Several arguments should be reordered
+    Permutation(Vec<Option<usize>>),
+}
+
+#[derive(Clone, Debug)]
+pub(crate) enum Compatibility<'tcx> {
+    Compatible,
+    Incompatible(Option<TypeError<'tcx>>),
+}
+
+/// Similar to `Issue`, but contains some extra information
+pub(crate) enum Error<'tcx> {
+    /// The given argument is the invalid type for the input
+    Invalid(usize, Compatibility<'tcx>),
+    /// There is a missing input
+    Missing(usize),
+    /// There's a superfluous argument
+    Extra(usize),
+    /// Two arguments should be swapped
+    Swap(usize, usize, usize, usize),
+    /// Several arguments should be reordered
+    Permutation(Vec<(usize, usize)>), // dest_arg, dest_input
+}
+
+pub(crate) struct ArgMatrix<'tcx> {
+    input_indexes: Vec<usize>,
+    arg_indexes: Vec<usize>,
+    compatibility_matrix: Vec<Vec<Compatibility<'tcx>>>,
+}
+
+impl<'tcx> ArgMatrix<'tcx> {
+    pub(crate) fn new<F: FnMut(usize, usize) -> Compatibility<'tcx>>(
+        minimum_input_count: usize,
+        provided_arg_count: usize,
+        mut is_compatible: F,
+    ) -> Self {
+        let compatibility_matrix = (0..provided_arg_count)
+            .map(|i| (0..minimum_input_count).map(|j| is_compatible(i, j)).collect())
+            .collect();
+        ArgMatrix {
+            input_indexes: (0..minimum_input_count).collect(),
+            arg_indexes: (0..provided_arg_count).collect(),
+            compatibility_matrix,
+        }
+    }
+
+    /// Remove a given input from consideration
+    fn eliminate_input(&mut self, idx: usize) {
+        self.input_indexes.remove(idx);
+        for row in &mut self.compatibility_matrix {
+            row.remove(idx);
+        }
+    }
+
+    /// Remove a given argument from consideration
+    fn eliminate_arg(&mut self, idx: usize) {
+        self.arg_indexes.remove(idx);
+        self.compatibility_matrix.remove(idx);
+    }
+
+    /// "satisfy" an input with a given arg, removing both from consideration
+    fn satisfy_input(&mut self, input_idx: usize, arg_idx: usize) {
+        self.eliminate_input(input_idx);
+        self.eliminate_arg(arg_idx);
+    }
+
+    fn eliminate_satisfied(&mut self) -> Vec<(usize, usize)> {
+        let mut i = cmp::min(self.input_indexes.len(), self.arg_indexes.len());
+        let mut eliminated = vec![];
+        while i > 0 {
+            let idx = i - 1;
+            if matches!(self.compatibility_matrix[idx][idx], Compatibility::Compatible) {
+                eliminated.push((self.arg_indexes[idx], self.input_indexes[idx]));
+                self.satisfy_input(idx, idx);
+            }
+            i -= 1;
+        }
+        return eliminated;
+    }
+
+    // Check for the above mismatch cases
+    fn find_issue(&self) -> Option<Issue> {
+        let mat = &self.compatibility_matrix;
+        let ai = &self.arg_indexes;
+        let ii = &self.input_indexes;
+
+        for i in 0..cmp::max(ai.len(), ii.len()) {
+            // If we eliminate the last row, any left-over inputs are considered missing
+            if i >= mat.len() {
+                return Some(Issue::Missing(i));
+            }
+            // If we eliminate the last column, any left-over arguments are extra
+            if mat[i].len() == 0 {
+                return Some(Issue::Extra(i));
+            }
+
+            // Make sure we don't pass the bounds of our matrix
+            let is_arg = i < ai.len();
+            let is_input = i < ii.len();
+            if is_arg && is_input && matches!(mat[i][i], Compatibility::Compatible) {
+                // This is a satisfied input, so move along
+                continue;
+            }
+
+            let mut useless = true;
+            let mut unsatisfiable = true;
+            if is_arg {
+                for j in 0..ii.len() {
+                    // If we find at least one input this argument could satisfy
+                    // this argument isn't completely useless
+                    if matches!(mat[i][j], Compatibility::Compatible) {
+                        useless = false;
+                        break;
+                    }
+                }
+            }
+            if is_input {
+                for j in 0..ai.len() {
+                    // If we find at least one argument that could satisfy this input
+                    // this argument isn't unsatisfiable
+                    if matches!(mat[j][i], Compatibility::Compatible) {
+                        unsatisfiable = false;
+                        break;
+                    }
+                }
+            }
+
+            match (is_arg, is_input, useless, unsatisfiable) {
+                // If an input is unsatisfied, and the argument in its position is useless
+                // then the most likely explanation is that we just got the types wrong
+                (true, true, true, true) => return Some(Issue::Invalid(i)),
+                // Otherwise, if an input is useless, then indicate that this is an extra argument
+                (true, _, true, _) => return Some(Issue::Extra(i)),
+                // Otherwise, if an argument is unsatisfiable, indicate that it's missing
+                (_, true, _, true) => return Some(Issue::Missing(i)),
+                (true, true, _, _) => {
+                    // The argument isn't useless, and the input isn't unsatisfied,
+                    // so look for a parameter we might swap it with
+                    // We look for swaps explicitly, instead of just falling back on permutations
+                    // so that cases like (A,B,C,D) given (B,A,D,C) show up as two swaps,
+                    // instead of a large permutation of 4 elements.
+                    for j in 0..cmp::min(ai.len(), ii.len()) {
+                        if i == j || matches!(mat[j][j], Compatibility::Compatible) {
+                            continue;
+                        }
+                        if matches!(mat[i][j], Compatibility::Compatible)
+                            && matches!(mat[j][i], Compatibility::Compatible)
+                        {
+                            return Some(Issue::Swap(i, j));
+                        }
+                    }
+                }
+                _ => {
+                    continue;
+                }
+            };
+        }
+
+        // We didn't find any of the individual issues above, but
+        // there might be a larger permutation of parameters, so we now check for that
+        // by checking for cycles
+        // We use a double option at position i in this vec to represent:
+        // - None: We haven't computed anything about this argument yet
+        // - Some(None): This argument definitely doesn't participate in a cycle
+        // - Some(Some(x)): the i-th argument could permute to the x-th position
+        let mut permutation: Vec<Option<Option<usize>>> = vec![None; mat.len()];
+        let mut permutation_found = false;
+        for i in 0..mat.len() {
+            if permutation[i].is_some() {
+                // We've already decided whether this argument is or is not in a loop
+                continue;
+            }
+
+            let mut stack = vec![];
+            let mut j = i;
+            let mut last = i;
+            let mut is_cycle = true;
+            loop {
+                stack.push(j);
+                // Look for params this one could slot into
+                let compat: Vec<_> =
+                    mat[j]
+                        .iter()
+                        .enumerate()
+                        .filter_map(|(i, c)| {
+                            if matches!(c, Compatibility::Compatible) { Some(i) } else { None }
+                        })
+                        .collect();
+                if compat.len() != 1 {
+                    // this could go into multiple slots, don't bother exploring both
+                    is_cycle = false;
+                    break;
+                }
+                j = compat[0];
+                if stack.contains(&j) {
+                    last = j;
+                    break;
+                }
+            }
+            if stack.len() <= 2 {
+                // If we encounter a cycle of 1 or 2 elements, we'll let the
+                // "satisfy" and "swap" code above handle those
+                is_cycle = false;
+            }
+            // We've built up some chain, some of which might be a cycle
+            // ex: [1,2,3,4]; last = 2; j = 2;
+            // So, we want to mark 4, 3, and 2 as part of a permutation
+            permutation_found = is_cycle;
+            while let Some(x) = stack.pop() {
+                if is_cycle {
+                    permutation[x] = Some(Some(j));
+                    j = x;
+                    if j == last {
+                        // From here on out, we're a tail leading into a cycle,
+                        // not the cycle itself
+                        is_cycle = false;
+                    }
+                } else {
+                    // Some(None) ensures we save time by skipping this argument again
+                    permutation[x] = Some(None);
+                }
+            }
+        }
+
+        if permutation_found {
+            // Map unwrap to remove the first layer of Some
+            let final_permutation: Vec<Option<usize>> =
+                permutation.into_iter().map(|x| x.unwrap()).collect();
+            return Some(Issue::Permutation(final_permutation));
+        }
+        return None;
+    }
+
+    // Obviously, detecting exact user intention is impossible, so the goal here is to
+    // come up with as likely of a story as we can to be helpful.
+    //
+    // We'll iteratively removed "satisfied" input/argument pairs,
+    // then check for the cases above, until we've eliminated the entire grid
+    //
+    // We'll want to know which arguments and inputs these rows and columns correspond to
+    // even after we delete them.
+    pub(crate) fn find_errors(mut self) -> (Vec<Error<'tcx>>, Vec<Option<usize>>) {
+        let provided_arg_count = self.arg_indexes.len();
+
+        let mut errors: Vec<Error<'tcx>> = vec![];
+        // For each expected argument, the matched *actual* input
+        let mut matched_inputs: Vec<Option<usize>> = vec![None; self.input_indexes.len()];
+
+        // Before we start looking for issues, eliminate any arguments that are already satisfied,
+        // so that an argument which is already spoken for by the input it's in doesn't
+        // spill over into another similarly typed input
+        // ex:
+        //   fn some_func(_a: i32, _b: i32) {}
+        //   some_func(1, "");
+        // Without this elimination, the first argument causes the second argument
+        // to show up as both a missing input and extra argument, rather than
+        // just an invalid type.
+        for (arg, inp) in self.eliminate_satisfied() {
+            matched_inputs[inp] = Some(arg);
+        }
+
+        while self.input_indexes.len() > 0 || self.arg_indexes.len() > 0 {
+            // Check for the first relevant issue
+            match self.find_issue() {
+                Some(Issue::Invalid(idx)) => {
+                    let compatibility = self.compatibility_matrix[idx][idx].clone();
+                    let input_idx = self.input_indexes[idx];
+                    self.satisfy_input(idx, idx);
+                    errors.push(Error::Invalid(input_idx, compatibility));
+                }
+                Some(Issue::Extra(idx)) => {
+                    let arg_idx = self.arg_indexes[idx];
+                    self.eliminate_arg(idx);
+                    errors.push(Error::Extra(arg_idx));
+                }
+                Some(Issue::Missing(idx)) => {
+                    let input_idx = self.input_indexes[idx];
+                    self.eliminate_input(idx);
+                    errors.push(Error::Missing(input_idx));
+                }
+                Some(Issue::Swap(idx, other)) => {
+                    let input_idx = self.input_indexes[idx];
+                    let other_input_idx = self.input_indexes[other];
+                    let arg_idx = self.arg_indexes[idx];
+                    let other_arg_idx = self.arg_indexes[other];
+                    let (min, max) = (cmp::min(idx, other), cmp::max(idx, other));
+                    self.satisfy_input(min, max);
+                    // Subtract 1 because we already removed the "min" row
+                    self.satisfy_input(max - 1, min);
+                    errors.push(Error::Swap(input_idx, other_input_idx, arg_idx, other_arg_idx));
+                    matched_inputs[input_idx] = Some(other_arg_idx);
+                    matched_inputs[other_input_idx] = Some(arg_idx);
+                }
+                Some(Issue::Permutation(args)) => {
+                    // FIXME: If satisfy_input ever did anything non-trivial (emit obligations to help type checking, for example)
+                    // we'd want to call this function with the correct arg/input pairs, but for now, we just throw them in a bucket.
+                    // This works because they force a cycle, so each row is guaranteed to also be a column
+                    let mut idxs: Vec<usize> = args.iter().filter_map(|&a| a).collect();
+
+                    let mut real_idxs = vec![None; provided_arg_count];
+                    for (src, dst) in
+                        args.iter().enumerate().filter_map(|(src, dst)| dst.map(|dst| (src, dst)))
+                    {
+                        let src_arg = self.arg_indexes[src];
+                        let dst_arg = self.arg_indexes[dst];
+                        let dest_input = self.input_indexes[dst];
+                        real_idxs[src_arg] = Some((dst_arg, dest_input));
+                        matched_inputs[dest_input] = Some(src_arg);
+                    }
+                    idxs.sort();
+                    idxs.reverse();
+                    for i in idxs {
+                        self.satisfy_input(i, i);
+                    }
+                    errors.push(Error::Permutation(real_idxs.into_iter().flatten().collect()));
+                }
+                None => {
+                    // We didn't find any issues, so we need to push the algorithm forward
+                    // First, eliminate any arguments that currently satisfy their inputs
+                    for (arg, inp) in self.eliminate_satisfied() {
+                        matched_inputs[inp] = Some(arg);
+                    }
+                }
+            };
+        }
+
+        return (errors, matched_inputs);
+    }
+}
index 9c702610888807edf93db00027866e1abda7f622..616aa11f00a6b638870cfa61e6f9bf4c7463ee9f 100644 (file)
@@ -1,5 +1,6 @@
 use crate::astconv::AstConv;
 use crate::check::coercion::CoerceMany;
+use crate::check::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error};
 use crate::check::gather_locals::Declaration;
 use crate::check::method::MethodCallee;
 use crate::check::Expectation::*;
@@ -8,6 +9,7 @@
     potentially_plural_count, struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt,
     LocalTy, Needs, TupleArgumentsFlag,
 };
+use crate::structured_errors::StructuredDiagnostic;
 
 use rustc_ast as ast;
 use rustc_data_structures::sync::Lrc;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{ExprKind, Node, QPath};
+use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt};
+use rustc_infer::infer::InferOk;
+use rustc_infer::infer::TypeTrace;
 use rustc_middle::ty::adjustment::AllowTwoPhase;
+use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::Session;
 use rustc_span::{self, Span};
 use rustc_trait_selection::traits::{self, ObligationCauseCode, StatementAsExpression};
 
-use crate::structured_errors::StructuredDiagnostic;
 use std::iter;
 use std::slice;
 
-struct FnArgsAsTuple<'hir> {
-    first: &'hir hir::Expr<'hir>,
-    last: &'hir hir::Expr<'hir>,
+enum TupleMatchFound {
+    None,
+    Single,
+    /// Beginning and end Span
+    Multiple(Span, Span),
 }
-
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(in super::super) fn check_casts(&self) {
         let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
@@ -67,7 +73,7 @@ pub(in super::super) fn check_method_argument_types(
                 sp,
                 expr,
                 &err_inputs,
-                vec![],
+                None,
                 args_no_rcvr,
                 false,
                 tuple_arguments,
@@ -108,7 +114,7 @@ pub(in super::super) fn check_argument_types(
         // Types (as defined in the *signature* of the target function)
         formal_input_tys: &[Ty<'tcx>],
         // More specific expected types, after unifying with caller output types
-        expected_input_tys: Vec<Ty<'tcx>>,
+        expected_input_tys: Option<Vec<Ty<'tcx>>>,
         // The expressions for each provided argument
         provided_args: &'tcx [hir::Expr<'tcx>],
         // Whether the function is variadic, for example when imported from C
@@ -119,10 +125,18 @@ pub(in super::super) fn check_argument_types(
         fn_def_id: Option<DefId>,
     ) {
         let tcx = self.tcx;
-        // Grab the argument types, supplying fresh type variables
-        // if the wrong number of arguments were supplied
-        let supplied_arg_count =
-            if tuple_arguments == DontTupleArguments { provided_args.len() } else { 1 };
+
+        // Conceptually, we've got some number of expected inputs, and some number of provided aguments
+        // and we can form a grid of whether each argument could satisfy a given input:
+        //      in1 | in2 | in3 | ...
+        // arg1  ?  |     |     |
+        // arg2     |  ?  |     |
+        // arg3     |     |  ?  |
+        // ...
+        // Initially, we just check the diagonal, because in the case of correct code
+        // these are the only checks that matter
+        // However, in the unhappy path, we'll fill in this whole grid to attempt to provide
+        // better error messages about invalid method calls.
 
         // All the input types from the fn signature must outlive the call
         // so as to validate implied bounds.
@@ -130,11 +144,7 @@ pub(in super::super) fn check_argument_types(
             self.register_wf_obligation(fn_input_ty.into(), arg_expr.span, traits::MiscObligation);
         }
 
-        let expected_arg_count = formal_input_tys.len();
-
-        // expected_count, arg_count, error_code, sugg_unit, sugg_tuple_wrap_args
-        let mut arg_count_error: Option<(usize, usize, &str, bool, Option<FnArgsAsTuple<'_>>)> =
-            None;
+        let mut err_code = "E0061";
 
         // If the arguments should be wrapped in a tuple (ex: closures), unwrap them here
         let (formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments {
@@ -144,15 +154,17 @@ pub(in super::super) fn check_argument_types(
                 ty::Tuple(arg_types) => {
                     // Argument length differs
                     if arg_types.len() != provided_args.len() {
-                        arg_count_error =
-                            Some((arg_types.len(), provided_args.len(), "E0057", false, None));
+                        err_code = "E0057";
                     }
-                    let expected_input_tys = match expected_input_tys.get(0) {
-                        Some(&ty) => match ty.kind() {
-                            ty::Tuple(tys) => tys.iter().collect(),
-                            _ => vec![],
+                    let expected_input_tys = match expected_input_tys {
+                        Some(expected_input_tys) => match expected_input_tys.get(0) {
+                            Some(ty) => match ty.kind() {
+                                ty::Tuple(tys) => Some(tys.iter().collect()),
+                                _ => None,
+                            },
+                            None => None,
                         },
-                        None => vec![],
+                        None => None,
                     };
                     (arg_types.iter().collect(), expected_input_tys)
                 }
@@ -167,67 +179,25 @@ pub(in super::super) fn check_argument_types(
                          for the function trait is neither a tuple nor unit"
                     )
                     .emit();
-                    (self.err_args(provided_args.len()), vec![])
+                    (self.err_args(provided_args.len()), None)
                 }
             }
-        } else if expected_arg_count == supplied_arg_count {
-            (formal_input_tys.to_vec(), expected_input_tys)
-        } else if c_variadic {
-            if supplied_arg_count >= expected_arg_count {
-                (formal_input_tys.to_vec(), expected_input_tys)
-            } else {
-                arg_count_error =
-                    Some((expected_arg_count, supplied_arg_count, "E0060", false, None));
-                (self.err_args(supplied_arg_count), vec![])
-            }
         } else {
-            // is the missing argument of type `()`?
-            let sugg_unit = if expected_input_tys.len() == 1 && supplied_arg_count == 0 {
-                self.resolve_vars_if_possible(expected_input_tys[0]).is_unit()
-            } else if formal_input_tys.len() == 1 && supplied_arg_count == 0 {
-                self.resolve_vars_if_possible(formal_input_tys[0]).is_unit()
-            } else {
-                false
-            };
-
-            // are we passing elements of a tuple without the tuple parentheses?
-            let expected_input_tys = if expected_input_tys.is_empty() {
-                // In most cases we can use expected_input_tys, but some callers won't have the type
-                // information, in which case we fall back to the types from the input expressions.
-                formal_input_tys
-            } else {
-                &*expected_input_tys
-            };
-
-            let sugg_tuple_wrap_args = self.suggested_tuple_wrap(expected_input_tys, provided_args);
-
-            arg_count_error = Some((
-                expected_arg_count,
-                supplied_arg_count,
-                "E0061",
-                sugg_unit,
-                sugg_tuple_wrap_args,
-            ));
-            (self.err_args(supplied_arg_count), vec![])
+            (formal_input_tys.to_vec(), expected_input_tys)
         };
 
-        debug!(
-            "check_argument_types: formal_input_tys={:?}",
-            formal_input_tys.iter().map(|t| self.ty_to_string(*t)).collect::<Vec<String>>()
-        );
-
-        // If there is no expectation, expect formal_input_tys.
-        let expected_input_tys = if !expected_input_tys.is_empty() {
+        // If there are no external expectations at the call site, just use the types from the function defn
+        let expected_input_tys = if let Some(expected_input_tys) = expected_input_tys {
+            assert_eq!(expected_input_tys.len(), formal_input_tys.len());
             expected_input_tys
         } else {
             formal_input_tys.clone()
         };
 
-        assert_eq!(expected_input_tys.len(), formal_input_tys.len());
-
-        let provided_arg_count: usize = provided_args.len();
+        let minimum_input_count = expected_input_tys.len();
+        let provided_arg_count = provided_args.len();
 
-        // Keep track of the fully coerced argument types
+        // We'll also want to keep track of the fully coerced argument types, for an awkward hack near the end
         let mut final_arg_types: Vec<Option<(Ty<'_>, Ty<'_>)>> = vec![None; provided_arg_count];
 
         // We introduce a helper function to demand that a given argument satisfy a given input
@@ -240,8 +210,9 @@ pub(in super::super) fn check_argument_types(
 
             debug!("checking argument {}: {:?} = {:?}", idx, provided_arg, formal_input_ty);
 
-            // The special-cased logic below has three functions:
-            // 1. Provide as good of an expected type as possible.
+            // We're on the happy path here, so we'll do a more involved check and write back types
+            // To check compatibility, we'll do 3 things:
+            // 1. Unify the provided argument with the expected type
             let expectation = Expectation::rvalue_hint(self, expected_input_ty);
 
             let checked_ty = self.check_expr_with_expectation(provided_arg, expectation);
@@ -255,8 +226,7 @@ pub(in super::super) fn check_argument_types(
             final_arg_types[idx] = Some((checked_ty, coerced_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
+            // argument and not the call. This lets us customize the span pointed to in the
             // fulfillment error to be more accurate.
             let coerced_ty =
                 self.resolve_vars_with_obligations_and_mutate_fulfillment(coerced_ty, |errors| {
@@ -270,18 +240,95 @@ pub(in super::super) fn check_argument_types(
                     );
                 });
 
+            // Make sure we store the resolved type
             final_arg_types[idx] = Some((checked_ty, coerced_ty));
 
-            // We're processing function arguments so we definitely want to use
-            // two-phase borrows.
-            self.demand_coerce(&provided_arg, checked_ty, coerced_ty, None, AllowTwoPhase::Yes);
+            let coerce_error = self
+                .try_coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None)
+                .err();
+
+            if coerce_error.is_some() {
+                return Compatibility::Incompatible(coerce_error);
+            }
+
+            // 3. Check if the formal type is a supertype of the checked one
+            //    and register any such obligations for future type checks
+            let supertype_error = self
+                .at(&self.misc(provided_arg.span), self.param_env)
+                .sup(formal_input_ty, coerced_ty);
+            let subtyping_error = match supertype_error {
+                Ok(InferOk { obligations, value: () }) => {
+                    self.register_predicates(obligations);
+                    None
+                }
+                Err(err) => Some(err),
+            };
 
-            // 3. Relate the expected type and the formal one,
-            //    if the expected type was used for the coercion.
-            self.demand_suptype(provided_arg.span, formal_input_ty, coerced_ty);
+            // If neither check failed, the types are compatible
+            match subtyping_error {
+                None => Compatibility::Compatible,
+                Some(_) => Compatibility::Incompatible(subtyping_error),
+            }
         };
 
-        let minimum_input_count = formal_input_tys.len();
+        // A "softer" version of the helper above, which checks types without persisting them,
+        // and treats error types differently
+        // This will allow us to "probe" for other argument orders that would likely have been correct
+        let check_compatible = |arg_idx, input_idx| {
+            let formal_input_ty: Ty<'tcx> = formal_input_tys[input_idx];
+            let expected_input_ty: Ty<'tcx> = expected_input_tys[input_idx];
+
+            // If either is an error type, we defy the usual convention and consider them to *not* be
+            // coercible.  This prevents our error message heuristic from trying to pass errors into
+            // every argument.
+            if formal_input_ty.references_error() || expected_input_ty.references_error() {
+                return Compatibility::Incompatible(None);
+            }
+
+            let provided_arg: &hir::Expr<'tcx> = &provided_args[arg_idx];
+            let expectation = Expectation::rvalue_hint(self, expected_input_ty);
+            // FIXME: check that this is safe; I don't believe this commits any of the obligations, but I can't be sure.
+            //
+            //   I had another method of "soft" type checking before,
+            //   but it was failing to find the type of some expressions (like "")
+            //   so I prodded this method and made it pub(super) so I could call it, and it seems to work well.
+            let checked_ty = self.check_expr_kind(provided_arg, expectation);
+
+            let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
+            let can_coerce = self.can_coerce(checked_ty, coerced_ty);
+
+            if !can_coerce {
+                return Compatibility::Incompatible(None);
+            }
+
+            let subtyping_result = self
+                .at(&self.misc(provided_arg.span), self.param_env)
+                .sup(formal_input_ty, coerced_ty);
+
+            // Same as above: if either the coerce type or the checked type is an error type,
+            // consider them *not* compatible.
+            let coercible =
+                !coerced_ty.references_error() && !checked_ty.references_error() && can_coerce;
+
+            match (coercible, &subtyping_result) {
+                (true, Ok(_)) => Compatibility::Compatible,
+                _ => Compatibility::Incompatible(subtyping_result.err()),
+            }
+        };
+
+        // To start, we only care "along the diagonal", where we expect every
+        // provided arg to be in the right spot
+        let mut compatibility = vec![Compatibility::Incompatible(None); provided_args.len()];
+
+        // Keep track of whether we *could possibly* be satisfied, i.e. whether we're on the happy path
+        // if the wrong number of arguments were supplied, we CAN'T be satisfied,
+        // and if we're c_variadic, the supplied arguments must be >= the minimum count from the function
+        // otherwise, they need to be identical, because rust doesn't currently support variadic functions
+        let mut call_appears_satisfied = if c_variadic {
+            provided_arg_count >= minimum_input_count
+        } else {
+            provided_arg_count == minimum_input_count
+        };
 
         // Check the arguments.
         // We do this in a pretty awful way: first we type-check any arguments
@@ -305,6 +352,8 @@ pub(in super::super) fn check_argument_types(
                 })
             }
 
+            // Check each argument, to satisfy the input it was provided for
+            // Visually, we're traveling down the diagonal of the compatibility matrix
             for (idx, arg) in provided_args.iter().enumerate() {
                 // Warn only for the first loop (the "no closures" one).
                 // Closure arguments themselves can't be diverging, but
@@ -327,15 +376,82 @@ pub(in super::super) fn check_argument_types(
                     continue;
                 }
 
-                demand_compatible(idx, &mut final_arg_types);
+                let compatible = demand_compatible(idx, &mut final_arg_types);
+                let is_compatible = matches!(compatible, Compatibility::Compatible);
+                compatibility[idx] = compatible;
+
+                if !is_compatible {
+                    call_appears_satisfied = false;
+                }
             }
         }
 
-        // If there was an error in parameter count, emit that here
-        if let Some((expected_count, arg_count, err_code, sugg_unit, sugg_tuple_wrap_args)) =
-            arg_count_error
-        {
-            let (span, start_span, args, ctor_of) = match &call_expr.kind {
+        // Logic here is a bit hairy
+        'errors: {
+            // If something above didn't typecheck, we've fallen off the happy path
+            // and we should make some effort to provide better error messages
+            if call_appears_satisfied {
+                break 'errors;
+            }
+
+            // The algorithm here is inspired by levenshtein distance and longest common subsequence.
+            // We'll try to detect 4 different types of mistakes:
+            // - An extra parameter has been provided that doesn't satisfy *any* of the other inputs
+            // - An input is missing, which isn't satisfied by *any* of the other arguments
+            // - Some number of arguments have been provided in the wrong order
+            // - A type is straight up invalid
+
+            // First, let's find the errors
+            let mut compatibility: Vec<_> = compatibility.into_iter().map(Some).collect();
+            let (mut errors, matched_inputs) =
+                ArgMatrix::new(minimum_input_count, provided_arg_count, |i, j| {
+                    if i == j { compatibility[i].take().unwrap() } else { check_compatible(i, j) }
+                })
+                .find_errors();
+
+            // Okay, so here's where it gets complicated in regards to what errors
+            // we emit and how.
+            // There are 3 different "types" of errors we might encounter.
+            //   1) Missing/extra/swapped arguments
+            //   2) Valid but incorrect arguments
+            //   3) Invalid arguments
+            //      - Currently I think this only comes up with `CyclicTy`
+            //
+            // We first need to go through, remove those from (3) and emit those
+            // as their own error, particularly since they're error code and
+            // message is special. From what I can tell, we *must* emit these
+            // here (vs somewhere prior to this function) since the arguments
+            // become invalid *because* of how they get used in the function.
+            // It is what it is.
+
+            let found_errors = !errors.is_empty();
+
+            errors.drain_filter(|error| {
+                let Error::Invalid(input_idx, Compatibility::Incompatible(error)) = error else { return false };
+                let expected_ty = expected_input_tys[*input_idx];
+                let provided_ty = final_arg_types[*input_idx].map(|ty| ty.0).unwrap();
+                let cause = &self.misc(provided_args[*input_idx].span);
+                let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
+                if let Some(e) = error {
+                    if !matches!(trace.cause.as_failure_code(e), FailureCode::Error0308(_)) {
+                        self.report_and_explain_type_error(trace, e).emit();
+                        return true;
+                    }
+                }
+                false
+            });
+
+            // We're done if we found errors, but we already emitted them.
+            // I don't think we *should* be able to enter this bit of code
+            // (`!call_appears_satisfied`) without *also* finding errors, but we
+            // don't want to accidentally not emit an error if there is some
+            // logic bug in the `ArgMatrix` code.
+            if found_errors && errors.is_empty() {
+                break 'errors;
+            }
+
+            // Next, let's construct the error
+            let (error_span, full_call_span, ctor_of) = match &call_expr.kind {
                 hir::ExprKind::Call(
                     hir::Expr {
                         span,
@@ -346,67 +462,484 @@ pub(in super::super) fn check_argument_types(
                             )),
                         ..
                     },
-                    args,
-                ) => (*span, *span, &args[..], Some(of)),
-                hir::ExprKind::Call(hir::Expr { span, .. }, args) => {
-                    (*span, *span, &args[..], None)
+                    _,
+                ) => (call_span, *span, Some(of)),
+                hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, None),
+                hir::ExprKind::MethodCall(path_segment, _, span) => {
+                    let ident_span = path_segment.ident.span;
+                    let ident_span = if let Some(args) = path_segment.args {
+                        ident_span.with_hi(args.span_ext.hi())
+                    } else {
+                        ident_span
+                    };
+                    (
+                        *span, ident_span, None, // methods are never ctors
+                    )
                 }
-                hir::ExprKind::MethodCall(path_segment, args, _) => (
-                    path_segment.ident.span,
-                    // `sp` doesn't point at the whole `foo.bar()`, only at `bar`.
-                    path_segment
-                        .args
-                        .and_then(|args| args.args.iter().last())
-                        // Account for `foo.bar::<T>()`.
-                        .map(|arg| {
-                            // Skip the closing `>`.
-                            tcx.sess
-                                .source_map()
-                                .next_point(tcx.sess.source_map().next_point(arg.span()))
-                        })
-                        .unwrap_or(path_segment.ident.span),
-                    &args[1..], // Skip the receiver.
-                    None,       // methods are never ctors
-                ),
                 k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k),
             };
-            let arg_spans = if provided_args.is_empty() {
-                // foo()
-                // ^^^-- supplied 0 arguments
-                // |
-                // expected 2 arguments
-                vec![tcx.sess.source_map().next_point(start_span).with_hi(call_span.hi())]
-            } else {
-                // foo(1, 2, 3)
-                // ^^^ -  -  - supplied 3 arguments
-                // |
-                // expected 2 arguments
-                args.iter().map(|arg| arg.span).collect::<Vec<Span>>()
-            };
+            let args_span = error_span.trim_start(full_call_span).unwrap_or(error_span);
             let call_name = match ctor_of {
                 Some(CtorOf::Struct) => "struct",
                 Some(CtorOf::Variant) => "enum variant",
                 None => "function",
             };
-            let mut err = tcx.sess.struct_span_err_with_code(
-                span,
-                &format!(
-                    "this {} takes {}{} but {} {} supplied",
+            if c_variadic && provided_arg_count < minimum_input_count {
+                err_code = "E0060";
+            }
+
+            // Next special case: The case where we expect a single tuple and
+            // wrapping all the args in parentheses (or adding a comma to
+            // already existing parentheses) will result in a tuple that
+            // satisfies the call.
+            // This isn't super ideal code, because we copy code from elsewhere
+            // and somewhat duplicate this. We also delegate to the general type
+            // mismatch suggestions for the single arg case.
+            let sugg_tuple_wrap_args =
+                self.suggested_tuple_wrap(&expected_input_tys, provided_args);
+            match sugg_tuple_wrap_args {
+                TupleMatchFound::None => {}
+                TupleMatchFound::Single => {
+                    let expected_ty = expected_input_tys[0];
+                    let provided_ty = final_arg_types[0].map(|ty| ty.0).unwrap();
+                    let cause = &self.misc(provided_args[0].span);
+                    let compatibility = demand_compatible(0, &mut final_arg_types);
+                    let type_error = match compatibility {
+                        Compatibility::Incompatible(Some(error)) => error,
+                        _ => TypeError::Mismatch,
+                    };
+                    let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
+                    let mut err = self.report_and_explain_type_error(trace, &type_error);
+                    self.emit_coerce_suggestions(
+                        &mut err,
+                        &provided_args[0],
+                        final_arg_types[0].map(|ty| ty.0).unwrap(),
+                        final_arg_types[0].map(|ty| ty.1).unwrap(),
+                        None,
+                        None,
+                    );
+                    err.span_label(
+                        full_call_span,
+                        format!("arguments to this {} are incorrect", call_name),
+                    );
+                    // Call out where the function is defined
+                    if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
+                        let mut spans: MultiSpan = def_span.into();
+
+                        let params = tcx
+                            .hir()
+                            .get_if_local(def_id)
+                            .and_then(|node| node.body_id())
+                            .into_iter()
+                            .map(|id| tcx.hir().body(id).params)
+                            .flatten();
+
+                        for param in params {
+                            spans.push_span_label(param.span, String::new());
+                        }
+
+                        let def_kind = tcx.def_kind(def_id);
+                        err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
+                    }
+                    err.emit();
+                    break 'errors;
+                }
+                TupleMatchFound::Multiple(start, end) => {
+                    let mut err = tcx.sess.struct_span_err_with_code(
+                        full_call_span,
+                        &format!(
+                            "this {} takes {}{} but {} {} supplied",
+                            call_name,
+                            if c_variadic { "at least " } else { "" },
+                            potentially_plural_count(minimum_input_count, "argument"),
+                            potentially_plural_count(provided_arg_count, "argument"),
+                            if provided_arg_count == 1 { "was" } else { "were" }
+                        ),
+                        DiagnosticId::Error(err_code.to_owned()),
+                    );
+                    // Call out where the function is defined
+                    if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
+                        let mut spans: MultiSpan = def_span.into();
+
+                        let params = tcx
+                            .hir()
+                            .get_if_local(def_id)
+                            .and_then(|node| node.body_id())
+                            .into_iter()
+                            .map(|id| tcx.hir().body(id).params)
+                            .flatten();
+
+                        for param in params {
+                            spans.push_span_label(param.span, String::new());
+                        }
+
+                        let def_kind = tcx.def_kind(def_id);
+                        err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
+                    }
+                    err.multipart_suggestion(
+                        "use parentheses to construct a tuple",
+                        vec![(start, '('.to_string()), (end, ')'.to_string())],
+                        Applicability::MachineApplicable,
+                    );
+                    err.emit();
+                    break 'errors;
+                }
+            }
+
+            // Okay, now that we've emitted the special errors separately, we
+            // are only left missing/extra/swapped and mismatched arguments, both
+            // can be collated pretty easily if needed.
+
+            // Next special case: if there is only one "Incompatible" error, just emit that
+            if errors.len() == 1 {
+                if let Some(Error::Invalid(input_idx, Compatibility::Incompatible(Some(error)))) =
+                    errors.iter().next()
+                {
+                    let expected_ty = expected_input_tys[*input_idx];
+                    let provided_ty = final_arg_types[*input_idx].map(|ty| ty.0).unwrap();
+                    let cause = &self.misc(provided_args[*input_idx].span);
+                    let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
+                    let mut err = self.report_and_explain_type_error(trace, error);
+                    self.emit_coerce_suggestions(
+                        &mut err,
+                        &provided_args[*input_idx],
+                        final_arg_types[*input_idx].map(|ty| ty.0).unwrap(),
+                        final_arg_types[*input_idx].map(|ty| ty.1).unwrap(),
+                        None,
+                        None,
+                    );
+                    err.span_label(
+                        full_call_span,
+                        format!("arguments to this {} are incorrect", call_name),
+                    );
+                    // Call out where the function is defined
+                    if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
+                        let mut spans: MultiSpan = def_span.into();
+
+                        let params = tcx
+                            .hir()
+                            .get_if_local(def_id)
+                            .and_then(|node| node.body_id())
+                            .into_iter()
+                            .map(|id| tcx.hir().body(id).params)
+                            .flatten();
+
+                        for param in params {
+                            spans.push_span_label(param.span, String::new());
+                        }
+
+                        let def_kind = tcx.def_kind(def_id);
+                        err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
+                    }
+                    err.emit();
+                    break 'errors;
+                }
+            }
+
+            let mut err = if minimum_input_count == provided_arg_count {
+                struct_span_err!(
+                    tcx.sess,
+                    full_call_span,
+                    E0308,
+                    "arguments to this {} are incorrect",
                     call_name,
-                    if c_variadic { "at least " } else { "" },
-                    potentially_plural_count(expected_count, "argument"),
-                    potentially_plural_count(arg_count, "argument"),
-                    if arg_count == 1 { "was" } else { "were" }
-                ),
-                DiagnosticId::Error(err_code.to_owned()),
-            );
-            let label = format!("supplied {}", potentially_plural_count(arg_count, "argument"));
-            for (i, span) in arg_spans.into_iter().enumerate() {
-                err.span_label(
-                    span,
-                    if arg_count == 0 || i + 1 == arg_count { &label } else { "" },
-                );
+                )
+            } else {
+                tcx.sess.struct_span_err_with_code(
+                    full_call_span,
+                    &format!(
+                        "this {} takes {}{} but {} {} supplied",
+                        call_name,
+                        if c_variadic { "at least " } else { "" },
+                        potentially_plural_count(minimum_input_count, "argument"),
+                        potentially_plural_count(provided_arg_count, "argument"),
+                        if provided_arg_count == 1 { "was" } else { "were" }
+                    ),
+                    DiagnosticId::Error(err_code.to_owned()),
+                )
+            };
+
+            // As we encounter issues, keep track of what we want to provide for the suggestion
+            let mut labels = vec![];
+            // If there is a single error, we give a specific suggestion; otherwise, we change to
+            // "did you mean" with the suggested function call
+            enum SuggestionText {
+                None,
+                Provide(bool),
+                Remove(bool),
+                Swap,
+                Reorder,
+                DidYouMean,
             }
+            let mut suggestion_text = SuggestionText::None;
+
+            let mut errors = errors.into_iter().peekable();
+            while let Some(error) = errors.next() {
+                match error {
+                    Error::Invalid(input_idx, compatibility) => {
+                        let expected_ty = expected_input_tys[input_idx];
+                        if let Compatibility::Incompatible(error) = &compatibility {
+                            let provided_ty = final_arg_types[input_idx].map(|ty| ty.0).unwrap();
+                            let cause = &self.misc(provided_args[input_idx].span);
+                            let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
+                            if let Some(e) = error {
+                                self.note_type_err(
+                                    &mut err,
+                                    &trace.cause,
+                                    None,
+                                    Some(trace.values),
+                                    e,
+                                    false,
+                                    true,
+                                );
+                            }
+                        }
+
+                        self.emit_coerce_suggestions(
+                            &mut err,
+                            &provided_args[input_idx],
+                            final_arg_types[input_idx].map(|ty| ty.0).unwrap(),
+                            final_arg_types[input_idx].map(|ty| ty.1).unwrap(),
+                            None,
+                            None,
+                        );
+                    }
+                    Error::Extra(arg_idx) => {
+                        let arg_type = if let Some((_, ty)) = final_arg_types[arg_idx] {
+                            if ty.references_error() || ty.has_infer_types() {
+                                "".into()
+                            } else {
+                                format!(" of type `{}`", ty)
+                            }
+                        } else {
+                            "".into()
+                        };
+                        labels.push((
+                            provided_args[arg_idx].span,
+                            format!("argument{} unexpected", arg_type),
+                        ));
+                        suggestion_text = match suggestion_text {
+                            SuggestionText::None => SuggestionText::Remove(false),
+                            SuggestionText::Remove(_) => SuggestionText::Remove(true),
+                            _ => SuggestionText::DidYouMean,
+                        };
+                    }
+                    Error::Missing(input_idx) => {
+                        // If there are multiple missing arguments adjacent to each other,
+                        // then we can provide a single error.
+
+                        let mut missing_idxs = vec![input_idx];
+                        while let Some(e) = errors.next_if(|e| matches!(e, Error::Missing(input_idx) if *input_idx == (missing_idxs.last().unwrap() + 1))) {
+                            match e {
+                                Error::Missing(input_idx) => missing_idxs.push(input_idx),
+                                _ => unreachable!(),
+                            }
+                        }
+
+                        // NOTE: Because we might be re-arranging arguments, might have extra
+                        // arguments, etc. it's hard to *really* know where we should provide
+                        // this error label, so as a heuristic, we point to the provided arg, or
+                        // to the call if the missing inputs pass the provided args.
+                        match &missing_idxs[..] {
+                            &[input_idx] => {
+                                let expected_ty = expected_input_tys[input_idx];
+                                let input_ty = self.resolve_vars_if_possible(expected_ty);
+                                let span = if input_idx < provided_arg_count {
+                                    let arg_span = provided_args[input_idx].span;
+                                    Span::new(arg_span.lo(), arg_span.hi(), arg_span.ctxt(), None)
+                                } else {
+                                    args_span
+                                };
+                                let arg_type =
+                                    if input_ty.references_error() || input_ty.has_infer_types() {
+                                        "".into()
+                                    } else {
+                                        format!(" of type `{}`", input_ty)
+                                    };
+                                labels.push((span, format!("an argument{} is missing", arg_type)));
+                                suggestion_text = match suggestion_text {
+                                    SuggestionText::None => SuggestionText::Provide(false),
+                                    SuggestionText::Provide(_) => SuggestionText::Provide(true),
+                                    _ => SuggestionText::DidYouMean,
+                                };
+                            }
+                            &[first_idx, second_idx] => {
+                                let first_input_ty =
+                                    self.resolve_vars_if_possible(expected_input_tys[first_idx]);
+                                let second_input_ty =
+                                    self.resolve_vars_if_possible(expected_input_tys[second_idx]);
+
+                                let span = if second_idx < provided_arg_count {
+                                    let first_arg_span = provided_args[first_idx].span;
+                                    let second_arg_span = provided_args[second_idx].span;
+                                    Span::new(
+                                        first_arg_span.lo(),
+                                        second_arg_span.hi(),
+                                        first_arg_span.ctxt(),
+                                        None,
+                                    )
+                                } else {
+                                    args_span
+                                };
+                                let any_unnameable = false
+                                    || first_input_ty.references_error()
+                                    || first_input_ty.has_infer_types()
+                                    || second_input_ty.references_error()
+                                    || second_input_ty.has_infer_types();
+                                let arg_type = if any_unnameable {
+                                    "".into()
+                                } else {
+                                    format!(
+                                        " of type `{}` and `{}`",
+                                        first_input_ty, second_input_ty
+                                    )
+                                };
+                                labels
+                                    .push((span, format!("two arguments{} are missing", arg_type)));
+                                suggestion_text = match suggestion_text {
+                                    SuggestionText::None | SuggestionText::Provide(_) => {
+                                        SuggestionText::Provide(true)
+                                    }
+                                    _ => SuggestionText::DidYouMean,
+                                };
+                            }
+                            &[first_idx, second_idx, third_idx] => {
+                                let first_input_ty =
+                                    self.resolve_vars_if_possible(expected_input_tys[first_idx]);
+                                let second_input_ty =
+                                    self.resolve_vars_if_possible(expected_input_tys[second_idx]);
+                                let third_input_ty =
+                                    self.resolve_vars_if_possible(expected_input_tys[second_idx]);
+                                let span = if third_idx < provided_arg_count {
+                                    let first_arg_span = provided_args[first_idx].span;
+                                    let third_arg_span = provided_args[third_idx].span;
+                                    Span::new(
+                                        first_arg_span.lo(),
+                                        third_arg_span.hi(),
+                                        first_arg_span.ctxt(),
+                                        None,
+                                    )
+                                } else {
+                                    args_span
+                                };
+                                let any_unnameable = false
+                                    || first_input_ty.references_error()
+                                    || first_input_ty.has_infer_types()
+                                    || second_input_ty.references_error()
+                                    || second_input_ty.has_infer_types()
+                                    || third_input_ty.references_error()
+                                    || third_input_ty.has_infer_types();
+                                let arg_type = if any_unnameable {
+                                    "".into()
+                                } else {
+                                    format!(
+                                        " of type `{}`, `{}`, and `{}`",
+                                        first_input_ty, second_input_ty, third_input_ty
+                                    )
+                                };
+                                labels.push((
+                                    span,
+                                    format!("three arguments{} are missing", arg_type),
+                                ));
+                                suggestion_text = match suggestion_text {
+                                    SuggestionText::None | SuggestionText::Provide(_) => {
+                                        SuggestionText::Provide(true)
+                                    }
+                                    _ => SuggestionText::DidYouMean,
+                                };
+                            }
+                            missing_idxs => {
+                                let first_idx = *missing_idxs.first().unwrap();
+                                let second_idx = *missing_idxs.last().unwrap();
+                                // NOTE: Because we might be re-arranging arguments, might have extra arguments, etc.
+                                // It's hard to *really* know where we should provide this error label, so this is a
+                                // decent heuristic
+                                let span = if first_idx < provided_arg_count {
+                                    let first_arg_span = provided_args[first_idx].span;
+                                    let second_arg_span = provided_args[second_idx].span;
+                                    Span::new(
+                                        first_arg_span.lo(),
+                                        second_arg_span.hi(),
+                                        first_arg_span.ctxt(),
+                                        None,
+                                    )
+                                } else {
+                                    // Otherwise just label the whole function
+                                    args_span
+                                };
+                                labels.push((span, format!("multiple arguments are missing")));
+                                suggestion_text = match suggestion_text {
+                                    SuggestionText::None | SuggestionText::Provide(_) => {
+                                        SuggestionText::Provide(true)
+                                    }
+                                    _ => SuggestionText::DidYouMean,
+                                };
+                            }
+                        }
+                    }
+                    Error::Swap(input_idx, other_input_idx, arg_idx, other_arg_idx) => {
+                        let first_span = provided_args[arg_idx].span;
+                        let second_span = provided_args[other_arg_idx].span;
+
+                        let first_expected_ty =
+                            self.resolve_vars_if_possible(expected_input_tys[input_idx]);
+                        let first_provided_ty = if let Some((ty, _)) = final_arg_types[arg_idx] {
+                            format!(",found `{}`", ty)
+                        } else {
+                            "".into()
+                        };
+                        labels.push((
+                            first_span,
+                            format!("expected `{}`{}", first_expected_ty, first_provided_ty),
+                        ));
+                        let other_expected_ty =
+                            self.resolve_vars_if_possible(expected_input_tys[other_input_idx]);
+                        let other_provided_ty =
+                            if let Some((ty, _)) = final_arg_types[other_arg_idx] {
+                                format!(",found `{}`", ty)
+                            } else {
+                                "".into()
+                            };
+                        labels.push((
+                            second_span,
+                            format!("expected `{}`{}", other_expected_ty, other_provided_ty),
+                        ));
+                        suggestion_text = match suggestion_text {
+                            SuggestionText::None => SuggestionText::Swap,
+                            _ => SuggestionText::DidYouMean,
+                        };
+                    }
+                    Error::Permutation(args) => {
+                        for (dst_arg, dest_input) in args {
+                            let expected_ty =
+                                self.resolve_vars_if_possible(expected_input_tys[dest_input]);
+                            let provided_ty = if let Some((ty, _)) = final_arg_types[dst_arg] {
+                                format!(",found `{}`", ty)
+                            } else {
+                                "".into()
+                            };
+                            labels.push((
+                                provided_args[dst_arg].span,
+                                format!("expected `{}`{}", expected_ty, provided_ty),
+                            ));
+                        }
+
+                        suggestion_text = match suggestion_text {
+                            SuggestionText::None => SuggestionText::Reorder,
+                            _ => SuggestionText::DidYouMean,
+                        };
+                    }
+                }
+            }
+
+            // If we have less than 5 things to say, it would be useful to call out exactly what's wrong
+            if labels.len() <= 5 {
+                for (span, label) in labels {
+                    err.span_label(span, label);
+                }
+            }
+
+            // Call out where the function is defined
             if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
                 let mut spans: MultiSpan = def_span.into();
 
@@ -425,33 +958,52 @@ pub(in super::super) fn check_argument_types(
                 let def_kind = tcx.def_kind(def_id);
                 err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
             }
-            if sugg_unit {
-                let sugg_span = tcx.sess.source_map().end_point(call_expr.span);
-                // remove closing `)` from the span
-                let sugg_span = sugg_span.shrink_to_lo();
-                err.span_suggestion(
-                    sugg_span,
-                    "expected the unit value `()`; create it with empty parentheses",
-                    String::from("()"),
-                    Applicability::MachineApplicable,
-                );
-            } else if let Some(FnArgsAsTuple { first, last }) = sugg_tuple_wrap_args {
-                err.multipart_suggestion(
-                    "use parentheses to construct a tuple",
-                    vec![
-                        (first.span.shrink_to_lo(), '('.to_string()),
-                        (last.span.shrink_to_hi(), ')'.to_string()),
-                    ],
-                    Applicability::MachineApplicable,
+
+            // And add a suggestion block for all of the parameters
+            let suggestion_text = match suggestion_text {
+                SuggestionText::None => None,
+                SuggestionText::Provide(plural) => {
+                    Some(format!("provide the argument{}", if plural { "s" } else { "" }))
+                }
+                SuggestionText::Remove(plural) => {
+                    Some(format!("remove the extra argument{}", if plural { "s" } else { "" }))
+                }
+                SuggestionText::Swap => Some("swap these arguments".to_string()),
+                SuggestionText::Reorder => Some("reorder these arguments".to_string()),
+                SuggestionText::DidYouMean => Some("did you mean".to_string()),
+            };
+            if let Some(suggestion_text) = suggestion_text {
+                let source_map = self.sess().source_map();
+                let mut suggestion = format!(
+                    "{}(",
+                    source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| String::new())
                 );
-            } else {
-                err.span_label(
-                    span,
-                    format!(
-                        "expected {}{}",
-                        if c_variadic { "at least " } else { "" },
-                        potentially_plural_count(expected_count, "argument")
-                    ),
+                for (idx, arg) in matched_inputs.iter().enumerate() {
+                    let suggestion_text = if let Some(arg) = arg {
+                        let arg_span = provided_args[*arg].span;
+                        let arg_text = source_map.span_to_snippet(arg_span).unwrap();
+                        arg_text
+                    } else {
+                        // Propose a placeholder of the correct type
+                        let expected_ty = expected_input_tys[idx];
+                        let input_ty = self.resolve_vars_if_possible(expected_ty);
+                        if input_ty.is_unit() {
+                            "()".to_string()
+                        } else {
+                            format!("{{{}}}", input_ty)
+                        }
+                    };
+                    suggestion += &suggestion_text;
+                    if idx < minimum_input_count - 1 {
+                        suggestion += ", ";
+                    }
+                }
+                suggestion += ")";
+                err.span_suggestion_verbose(
+                    error_span,
+                    &suggestion_text,
+                    suggestion,
+                    Applicability::HasPlaceholders,
                 );
             }
             err.emit();
@@ -460,10 +1012,11 @@ pub(in super::super) fn check_argument_types(
         for arg in provided_args.iter().skip(minimum_input_count) {
             let arg_ty = self.check_expr(&arg);
 
+            // If the function is c-style variadic, we skipped a bunch of arguments
+            // so we need to check those, and write out the types
+            // Ideally this would be folded into the above, for uniform style
+            // but c-variadic is already a corner case
             if c_variadic {
-                // We also need to make sure we at least write the ty of the other
-                // arguments which we skipped above, either because they were additional
-                // c_variadic args, or because we had an argument count mismatch.
                 fn variadic_error<'tcx>(sess: &Session, span: Span, ty: Ty<'tcx>, cast_ty: &str) {
                     use crate::structured_errors::MissingCastForVariadicArg;
 
@@ -498,27 +1051,31 @@ fn suggested_tuple_wrap(
         &self,
         expected_input_tys: &[Ty<'tcx>],
         provided_args: &'tcx [hir::Expr<'tcx>],
-    ) -> Option<FnArgsAsTuple<'_>> {
-        let [expected_arg_type] = expected_input_tys[..] else { return None };
-
+    ) -> TupleMatchFound {
+        // Only handle the case where we expect only one tuple arg
+        let [expected_arg_type] = expected_input_tys[..] else { return TupleMatchFound::None };
         let &ty::Tuple(expected_types) = self.resolve_vars_if_possible(expected_arg_type).kind()
-            else { return None };
+            else { return TupleMatchFound::None };
+
+        // First check that there are the same number of types.
+        if expected_types.len() != provided_args.len() {
+            return TupleMatchFound::None;
+        }
 
         let supplied_types: Vec<_> = provided_args.iter().map(|arg| self.check_expr(arg)).collect();
 
         let all_match = iter::zip(expected_types, supplied_types)
             .all(|(expected, supplied)| self.can_eq(self.param_env, expected, supplied).is_ok());
 
-        if all_match {
-            match provided_args {
-                [] => None,
-                [_] => unreachable!(
-                    "shouldn't reach here - need count mismatch between 1-tuple and 1-argument"
-                ),
-                [first, .., last] => Some(FnArgsAsTuple { first, last }),
+        if !all_match {
+            return TupleMatchFound::None;
+        }
+        match provided_args {
+            [] => TupleMatchFound::None,
+            [_] => TupleMatchFound::Single,
+            [first, .., last] => {
+                TupleMatchFound::Multiple(first.span.shrink_to_lo(), last.span.shrink_to_hi())
             }
-        } else {
-            None
         }
     }
 
index 77cba1c22c408cca0c99f173f089b170641b0b35..ce9ff61bd9e6f0ada69ba401eab3e39265cbcc9f 100644 (file)
@@ -1,9 +1,9 @@
 mod _impl;
+mod arg_matrix;
 mod checks;
 mod suggestions;
 
 pub use _impl::*;
-pub use checks::*;
 pub use suggestions::*;
 
 use crate::astconv::AstConv;
index 75a8ad8a159b52c658f829c03ab4030a11316e10..721f251650f54656a68497be907d8abfa01561b0 100644 (file)
@@ -257,7 +257,6 @@ fn find_target_expression_from_destination(
                 | hir::Node::Ctor(..)
                 | hir::Node::Lifetime(..)
                 | hir::Node::GenericParam(..)
-                | hir::Node::Visibility(..)
                 | hir::Node::Crate(..)
                 | hir::Node::Infer(..) => bug!("Unsupported branch target: {:?}", node),
             }
index 78e7758067942c3f16a45c11b5cafd39daa71b6a..0dd8ee88ca2ad772b67b5500d84f20a4ec015aeb 100644 (file)
@@ -437,6 +437,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
         | sym::simd_fpow
         | sym::simd_saturating_add
         | sym::simd_saturating_sub => (1, vec![param(0), param(0)], param(0)),
+        sym::simd_arith_offset => (2, vec![param(0), param(1)], param(0)),
         sym::simd_neg
         | sym::simd_fsqrt
         | sym::simd_fsin
index 043472e37f5f4ee6f5df89818bdb52493f0281dc..0d5e7b28a4e65e942c8e2c975f448a3b21a5e0d2 100644 (file)
@@ -427,16 +427,29 @@ fn typeck_with_fallback<'tcx>(
                             span,
                         }),
                         Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. })
-                        | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. })
-                            if asm.operands.iter().any(|(op, _op_sp)| match op {
-                                hir::InlineAsmOperand::Const { anon_const } => {
-                                    anon_const.hir_id == id
-                                }
-                                _ => false,
-                            }) =>
-                        {
-                            // Inline assembly constants must be integers.
-                            fcx.next_int_var()
+                        | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. }) => {
+                            let operand_ty = asm
+                                .operands
+                                .iter()
+                                .filter_map(|(op, _op_sp)| match op {
+                                    hir::InlineAsmOperand::Const { anon_const }
+                                        if anon_const.hir_id == id =>
+                                    {
+                                        // Inline assembly constants must be integers.
+                                        Some(fcx.next_int_var())
+                                    }
+                                    hir::InlineAsmOperand::SymFn { anon_const }
+                                        if anon_const.hir_id == id =>
+                                    {
+                                        Some(fcx.next_ty_var(TypeVariableOrigin {
+                                            kind: TypeVariableOriginKind::MiscVariable,
+                                            span,
+                                        }))
+                                    }
+                                    _ => None,
+                                })
+                                .next();
+                            operand_ty.unwrap_or_else(fallback)
                         }
                         _ => fallback(),
                     },
index f3dcf5fff74cc39bd4562826d12b1263616f6d73..cf0c5703cd0ee7c724ff760b13ef9987ac79bab1 100644 (file)
@@ -2042,63 +2042,60 @@ fn error_expected_array_or_slice(&self, span: Span, expected_ty: Ty<'tcx>, ti: T
             self.tcx.sess,
             span,
             E0529,
-            "expected an array or slice, found `{}`",
-            expected_ty
+            "expected an array or slice, found `{expected_ty}`"
         );
-        if let ty::Ref(_, ty, _) = expected_ty.kind() {
-            if let ty::Array(..) | ty::Slice(..) = ty.kind() {
-                err.help("the semantics of slice patterns changed recently; see issue #62254");
-            }
+        if let ty::Ref(_, ty, _) = expected_ty.kind()
+            && let ty::Array(..) | ty::Slice(..) = ty.kind()
+        {
+            err.help("the semantics of slice patterns changed recently; see issue #62254");
         } else if Autoderef::new(&self.infcx, self.param_env, self.body_id, span, expected_ty, span)
             .any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
+            && let (Some(span), true) = (ti.span, ti.origin_expr)
+            && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
         {
-            if let (Some(span), true) = (ti.span, ti.origin_expr) {
-                if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-                    let applicability = Autoderef::new(
-                        &self.infcx,
-                        self.param_env,
-                        self.body_id,
-                        span,
-                        self.resolve_vars_if_possible(ti.expected),
+            let ty = self.resolve_vars_if_possible(ti.expected);
+            let is_slice_or_array_or_vector = self.is_slice_or_array_or_vector(&mut err, snippet.clone(), ty);
+            match is_slice_or_array_or_vector.1.kind() {
+                ty::Adt(adt_def, _)
+                    if self.tcx.is_diagnostic_item(sym::Option, adt_def.did())
+                        || self.tcx.is_diagnostic_item(sym::Result, adt_def.did()) =>
+                {
+                    // Slicing won't work here, but `.as_deref()` might (issue #91328).
+                    err.span_suggestion(
                         span,
-                    )
-                    .find_map(|(ty, _)| {
-                        match ty.kind() {
-                            ty::Adt(adt_def, _)
-                                if self.tcx.is_diagnostic_item(sym::Option, adt_def.did())
-                                    || self.tcx.is_diagnostic_item(sym::Result, adt_def.did()) =>
-                            {
-                                // Slicing won't work here, but `.as_deref()` might (issue #91328).
-                                err.span_suggestion(
-                                    span,
-                                    "consider using `as_deref` here",
-                                    format!("{}.as_deref()", snippet),
-                                    Applicability::MaybeIncorrect,
-                                );
-                                Some(None)
-                            }
-
-                            ty::Slice(..) | ty::Array(..) => {
-                                Some(Some(Applicability::MachineApplicable))
-                            }
-
-                            _ => None,
-                        }
-                    })
-                    .unwrap_or(Some(Applicability::MaybeIncorrect));
-
-                    if let Some(applicability) = applicability {
-                        err.span_suggestion(
-                            span,
-                            "consider slicing here",
-                            format!("{}[..]", snippet),
-                            applicability,
-                        );
-                    }
+                        "consider using `as_deref` here",
+                        format!("{snippet}.as_deref()"),
+                        Applicability::MaybeIncorrect,
+                    );
                 }
+                _ => ()
+            }
+            if is_slice_or_array_or_vector.0 {
+                err.span_suggestion(
+                    span,
+                    "consider slicing here",
+                    format!("{snippet}[..]"),
+                    Applicability::MachineApplicable,
+                );
             }
         }
-        err.span_label(span, format!("pattern cannot match with input type `{}`", expected_ty));
+        err.span_label(span, format!("pattern cannot match with input type `{expected_ty}`"));
         err.emit();
     }
+
+    fn is_slice_or_array_or_vector(
+        &self,
+        err: &mut Diagnostic,
+        snippet: String,
+        ty: Ty<'tcx>,
+    ) -> (bool, Ty<'tcx>) {
+        match ty.kind() {
+            ty::Adt(adt_def, _) if self.tcx.is_diagnostic_item(sym::Vec, adt_def.did()) => {
+                (true, ty)
+            }
+            ty::Ref(_, ty, _) => self.is_slice_or_array_or_vector(err, snippet, *ty),
+            ty::Slice(..) | ty::Array(..) => (true, ty),
+            _ => (false, ty),
+        }
+    }
 }
index 1826c3f5f7fa506ea806d7546b90b3c881b7b35f..d52886a09bd958d5485dd8764ca75b0e9cd17f84 100644 (file)
@@ -1,72 +1,61 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::lint;
 use rustc_span::{Span, Symbol};
 
 pub fn check_crate(tcx: TyCtxt<'_>) {
-    let mut used_trait_imports = FxHashSet::default();
+    let mut used_trait_imports: FxHashSet<LocalDefId> = FxHashSet::default();
+
     for item_def_id in tcx.hir().body_owners() {
         let imports = tcx.used_trait_imports(item_def_id);
         debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
         used_trait_imports.extend(imports.iter());
     }
 
-    let mut visitor = CheckVisitor { tcx, used_trait_imports };
-    tcx.hir().visit_all_item_likes(&mut visitor);
-
-    unused_crates_lint(tcx);
-}
-
-impl<'tcx> ItemLikeVisitor<'_> for CheckVisitor<'tcx> {
-    fn visit_item(&mut self, item: &hir::Item<'_>) {
-        if item.vis.node.is_pub() || item.span.is_dummy() {
-            return;
-        }
-        if let hir::ItemKind::Use(path, _) = item.kind {
-            self.check_import(item.item_id(), path.span);
+    for id in tcx.hir().items() {
+        if matches!(tcx.hir().def_kind(id.def_id), DefKind::Use) {
+            if tcx.visibility(id.def_id).is_public() {
+                continue;
+            }
+            let item = tcx.hir().item(id);
+            if item.span.is_dummy() {
+                continue;
+            }
+            if let hir::ItemKind::Use(path, _) = item.kind {
+                check_import(tcx, &mut used_trait_imports, item.item_id(), path.span);
+            }
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
-
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
-
-    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
+    unused_crates_lint(tcx);
 }
 
-struct CheckVisitor<'tcx> {
+fn check_import<'tcx>(
     tcx: TyCtxt<'tcx>,
-    used_trait_imports: FxHashSet<LocalDefId>,
-}
-
-impl<'tcx> CheckVisitor<'tcx> {
-    fn check_import(&self, item_id: hir::ItemId, span: Span) {
-        if !self.tcx.maybe_unused_trait_import(item_id.def_id) {
-            return;
-        }
-
-        if self.used_trait_imports.contains(&item_id.def_id) {
-            return;
-        }
+    used_trait_imports: &mut FxHashSet<LocalDefId>,
+    item_id: hir::ItemId,
+    span: Span,
+) {
+    if !tcx.maybe_unused_trait_import(item_id.def_id) {
+        return;
+    }
 
-        self.tcx.struct_span_lint_hir(
-            lint::builtin::UNUSED_IMPORTS,
-            item_id.hir_id(),
-            span,
-            |lint| {
-                let msg = if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-                    format!("unused import: `{}`", snippet)
-                } else {
-                    "unused import".to_owned()
-                };
-                lint.build(&msg).emit();
-            },
-        );
+    if used_trait_imports.contains(&item_id.def_id) {
+        return;
     }
+
+    tcx.struct_span_lint_hir(lint::builtin::UNUSED_IMPORTS, item_id.hir_id(), span, |lint| {
+        let msg = if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(span) {
+            format!("unused import: `{}`", snippet)
+        } else {
+            "unused import".to_owned()
+        };
+        lint.build(&msg).emit();
+    });
 }
 
 fn unused_crates_lint(tcx: TyCtxt<'_>) {
@@ -110,9 +99,20 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
 
     // Collect all the extern crates (in a reliable order).
     let mut crates_to_lint = vec![];
-    tcx.hir().visit_all_item_likes(&mut CollectExternCrateVisitor {
-        crates_to_lint: &mut crates_to_lint,
-    });
+
+    for id in tcx.hir().items() {
+        if matches!(tcx.hir().def_kind(id.def_id), DefKind::ExternCrate) {
+            let item = tcx.hir().item(id);
+            if let hir::ItemKind::ExternCrate(orig_name) = item.kind {
+                crates_to_lint.push(ExternCrateToLint {
+                    def_id: item.def_id.to_def_id(),
+                    span: item.span,
+                    orig_name,
+                    warn_if_unused: !item.ident.as_str().starts_with('_'),
+                });
+            }
+        }
+    }
 
     let extern_prelude = &tcx.resolutions(()).extern_prelude;
 
@@ -179,7 +179,7 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
                 Some(orig_name) => format!("use {} as {};", orig_name, item.ident.name),
                 None => format!("use {};", item.ident.name),
             };
-            let vis = tcx.sess.source_map().span_to_snippet(item.vis.span).unwrap_or_default();
+            let vis = tcx.sess.source_map().span_to_snippet(item.vis_span).unwrap_or_default();
             let add_vis = |to| if vis.is_empty() { to } else { format!("{} {}", vis, to) };
             lint.build("`extern crate` is not idiomatic in the new edition")
                 .span_suggestion_short(
@@ -193,10 +193,6 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
     }
 }
 
-struct CollectExternCrateVisitor<'a> {
-    crates_to_lint: &'a mut Vec<ExternCrateToLint>,
-}
-
 struct ExternCrateToLint {
     /// `DefId` of the extern crate
     def_id: DefId,
@@ -213,22 +209,3 @@ struct ExternCrateToLint {
     /// about it going unused (but we should still emit idiom lints).
     warn_if_unused: bool,
 }
-
-impl<'a, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a> {
-    fn visit_item(&mut self, item: &hir::Item<'_>) {
-        if let hir::ItemKind::ExternCrate(orig_name) = item.kind {
-            self.crates_to_lint.push(ExternCrateToLint {
-                def_id: item.def_id.to_def_id(),
-                span: item.span,
-                orig_name,
-                warn_if_unused: !item.ident.as_str().starts_with('_'),
-            });
-        }
-    }
-
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
-
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
-
-    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
-}
index 77a537448291719a0966c6435cb68f45c95ed087..19e68f0b14f4f23934dba64e53f2a41e36a521d7 100644 (file)
@@ -50,6 +50,7 @@ fn orphan_check_impl(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGua
             tcx,
             sp,
             tr.path.span,
+            trait_ref.self_ty(),
             impl_.self_ty.span,
             &impl_.generics,
             err,
@@ -201,18 +202,23 @@ fn emit_orphan_check_error<'tcx>(
     tcx: TyCtxt<'tcx>,
     sp: Span,
     trait_span: Span,
+    self_ty: Ty<'tcx>,
     self_ty_span: Span,
     generics: &hir::Generics<'tcx>,
     err: traits::OrphanCheckErr<'tcx>,
 ) -> Result<!, ErrorGuaranteed> {
     Err(match err {
         traits::OrphanCheckErr::NonLocalInputType(tys) => {
+            let msg = match self_ty.kind() {
+                ty::Adt(..) => "can be implemented for types defined outside of the crate",
+                _ if self_ty.is_primitive() => "can be implemented for primitive types",
+                _ => "can be implemented for arbitrary types",
+            };
             let mut err = struct_span_err!(
                 tcx.sess,
                 sp,
                 E0117,
-                "only traits defined in the current crate can be implemented for \
-                        arbitrary types"
+                "only traits defined in the current crate {msg}"
             );
             err.span_label(sp, "impl doesn't use only types from inside the current crate");
             for (ty, is_target_ty) in &tys {
index 153ab8d95fd4bdcec34b3046a46b9e596058f9ad..be77bdb0bf5f06e3b16840f6ab2e67fed4489e28 100644 (file)
@@ -160,6 +160,33 @@ struct CollectItemTypesVisitor<'tcx> {
         return;
     }
 
+    placeholder_type_error_diag(
+        tcx,
+        span,
+        generics,
+        placeholder_types,
+        vec![],
+        suggest,
+        hir_ty,
+        kind,
+    )
+    .emit();
+}
+
+crate fn placeholder_type_error_diag<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    span: Option<Span>,
+    generics: &[hir::GenericParam<'_>],
+    placeholder_types: Vec<Span>,
+    additional_spans: Vec<Span>,
+    suggest: bool,
+    hir_ty: Option<&hir::Ty<'_>>,
+    kind: &'static str,
+) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+    if placeholder_types.is_empty() {
+        return bad_placeholder(tcx, additional_spans, kind);
+    }
+
     let type_name = generics.next_type_param_name(None);
     let mut sugg: Vec<_> =
         placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect();
@@ -182,7 +209,8 @@ struct CollectItemTypesVisitor<'tcx> {
         sugg.push((span, format!(", {}", type_name)));
     }
 
-    let mut err = bad_placeholder(tcx, placeholder_types, kind);
+    let mut err =
+        bad_placeholder(tcx, placeholder_types.into_iter().chain(additional_spans).collect(), kind);
 
     // Suggest, but only if it is not a function in const or static
     if suggest {
@@ -218,7 +246,8 @@ struct CollectItemTypesVisitor<'tcx> {
             );
         }
     }
-    err.emit();
+
+    err
 }
 
 fn reject_placeholder_type_signatures_in_item<'tcx>(
@@ -1868,50 +1897,17 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
             generics,
             ..
         })
-        | ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), ident, generics, .. })
         | Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), ident, .. }) => {
-            match get_infer_ret_ty(&sig.decl.output) {
-                Some(ty) => {
-                    let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
-                    // Typeck doesn't expect erased regions to be returned from `type_of`.
-                    let fn_sig = tcx.fold_regions(fn_sig, &mut false, |r, _| match *r {
-                        ty::ReErased => tcx.lifetimes.re_static,
-                        _ => r,
-                    });
-                    let fn_sig = ty::Binder::dummy(fn_sig);
-
-                    let mut visitor = HirPlaceholderCollector::default();
-                    visitor.visit_ty(ty);
-                    let mut diag = bad_placeholder(tcx, visitor.0, "return type");
-                    let ret_ty = fn_sig.skip_binder().output();
-                    if !ret_ty.references_error() {
-                        if !ret_ty.is_closure() {
-                            let ret_ty_str = match ret_ty.kind() {
-                                // Suggest a function pointer return type instead of a unique function definition
-                                // (e.g. `fn() -> i32` instead of `fn() -> i32 { f }`, the latter of which is invalid
-                                // syntax)
-                                ty::FnDef(..) => ret_ty.fn_sig(tcx).to_string(),
-                                _ => ret_ty.to_string(),
-                            };
-                            diag.span_suggestion(
-                                ty.span,
-                                "replace with the correct return type",
-                                ret_ty_str,
-                                Applicability::MaybeIncorrect,
-                            );
-                        } else {
-                            // We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds
-                            // to prevent the user from getting a papercut while trying to use the unique closure
-                            // syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`).
-                            diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
-                            diag.note("for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html");
-                        }
-                    }
-                    diag.emit();
+            infer_return_ty_for_fn_sig(tcx, sig, *ident, generics, def_id, &icx)
+        }
 
-                    fn_sig
-                }
-                None => <dyn AstConv<'_>>::ty_of_fn(
+        ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), ident, generics, .. }) => {
+            // Do not try to inference the return type for a impl method coming from a trait
+            if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) =
+                tcx.hir().get(tcx.hir().get_parent_node(hir_id))
+                && i.of_trait.is_some()
+            {
+                <dyn AstConv<'_>>::ty_of_fn(
                     &icx,
                     hir_id,
                     sig.header.unsafety,
@@ -1920,7 +1916,9 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
                     generics,
                     Some(ident.span),
                     None,
-                ),
+                )
+            } else {
+                infer_return_ty_for_fn_sig(tcx, sig, *ident, generics, def_id, &icx)
             }
         }
 
@@ -1982,6 +1980,70 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
     }
 }
 
+fn infer_return_ty_for_fn_sig<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    sig: &hir::FnSig<'_>,
+    ident: Ident,
+    generics: &hir::Generics<'_>,
+    def_id: LocalDefId,
+    icx: &ItemCtxt<'tcx>,
+) -> ty::PolyFnSig<'tcx> {
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+
+    match get_infer_ret_ty(&sig.decl.output) {
+        Some(ty) => {
+            let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
+            // Typeck doesn't expect erased regions to be returned from `type_of`.
+            let fn_sig = tcx.fold_regions(fn_sig, &mut false, |r, _| match *r {
+                ty::ReErased => tcx.lifetimes.re_static,
+                _ => r,
+            });
+            let fn_sig = ty::Binder::dummy(fn_sig);
+
+            let mut visitor = HirPlaceholderCollector::default();
+            visitor.visit_ty(ty);
+            let mut diag = bad_placeholder(tcx, visitor.0, "return type");
+            let ret_ty = fn_sig.skip_binder().output();
+            if !ret_ty.references_error() {
+                if !ret_ty.is_closure() {
+                    let ret_ty_str = match ret_ty.kind() {
+                        // Suggest a function pointer return type instead of a unique function definition
+                        // (e.g. `fn() -> i32` instead of `fn() -> i32 { f }`, the latter of which is invalid
+                        // syntax)
+                        ty::FnDef(..) => ret_ty.fn_sig(tcx).to_string(),
+                        _ => ret_ty.to_string(),
+                    };
+                    diag.span_suggestion(
+                        ty.span,
+                        "replace with the correct return type",
+                        ret_ty_str,
+                        Applicability::MaybeIncorrect,
+                    );
+                } else {
+                    // We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds
+                    // to prevent the user from getting a papercut while trying to use the unique closure
+                    // syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`).
+                    diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
+                    diag.note("for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html");
+                }
+            }
+            diag.emit();
+
+            fn_sig
+        }
+        None => <dyn AstConv<'_>>::ty_of_fn(
+            icx,
+            hir_id,
+            sig.header.unsafety,
+            sig.header.abi,
+            sig.decl,
+            generics,
+            Some(ident.span),
+            None,
+        ),
+    }
+}
+
 fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
     let icx = ItemCtxt::new(tcx, def_id);
     match tcx.hir().expect_item(def_id.expect_local()).kind {
index 785538ab0df3d621c3517d5094f06230968cbd33..fa06ec09fce22c6e7ed0960af0240f2752ff2275 100644 (file)
@@ -450,7 +450,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                 Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
                 | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
                     if asm.operands.iter().any(|(op, _op_sp)| match op {
-                        hir::InlineAsmOperand::Const { anon_const } => anon_const.hir_id == hir_id,
+                        hir::InlineAsmOperand::Const { anon_const }
+                        | hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id,
                         _ => false,
                     }) =>
                 {
index 1088be5f566571d2ff7039c47a40b04012519dee..fc08171d2f4c290c00f831bca2b3de293c5c8e80 100644 (file)
@@ -134,7 +134,7 @@ pub struct TypeofReservedKeywordUsed<'tcx> {
     #[primary_span]
     #[label]
     pub span: Span,
-    #[suggestion_verbose(message = "suggestion", code = "{ty}")]
+    #[suggestion_verbose(code = "{ty}")]
     pub opt_sugg: Option<(Span, Applicability)>,
 }
 
index 055e391d7069efe430ead0b1dd899a1405ad360f..2bcf2d3b2ed71aabc5a68172464226e808ce06bc 100644 (file)
@@ -358,8 +358,7 @@ pub fn walk_expr(&mut self, expr: &hir::Expr<'_>) {
             hir::ExprKind::InlineAsm(asm) => {
                 for (op, _op_sp) in asm.operands {
                     match op {
-                        hir::InlineAsmOperand::In { expr, .. }
-                        | hir::InlineAsmOperand::Sym { expr, .. } => self.consume_expr(expr),
+                        hir::InlineAsmOperand::In { expr, .. } => self.consume_expr(expr),
                         hir::InlineAsmOperand::Out { expr: Some(expr), .. }
                         | hir::InlineAsmOperand::InOut { expr, .. } => {
                             self.mutate_expr(expr);
@@ -371,7 +370,9 @@ pub fn walk_expr(&mut self, expr: &hir::Expr<'_>) {
                             }
                         }
                         hir::InlineAsmOperand::Out { expr: None, .. }
-                        | hir::InlineAsmOperand::Const { .. } => {}
+                        | hir::InlineAsmOperand::Const { .. }
+                        | hir::InlineAsmOperand::SymFn { .. }
+                        | hir::InlineAsmOperand::SymStatic { .. } => {}
                     }
                 }
             }
index d0c4726bb0a8c41193c3b3d7b20c8a055fec3852..9fb9652b849c9142b87d47fb8f8a90ce30e915a0 100644 (file)
 #![feature(box_patterns)]
 #![feature(control_flow_enum)]
 #![feature(crate_visibility_modifier)]
+#![feature(drain_filter)]
 #![feature(hash_drain_filter)]
 #![feature(if_let_guard)]
 #![feature(is_sorted)]
+#![feature(label_break_value)]
 #![feature(let_chains)]
 #![feature(let_else)]
 #![feature(min_specialization)]
index 00163c72974ad93482149675b88121ffc1ccc2e8..6f842c6e71a5b5aaf399f55a6a240f90f3e40cb8 100644 (file)
@@ -1,7 +1,6 @@
 use rustc_data_structures::fx::FxHashMap;
-use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
@@ -29,81 +28,57 @@ pub fn infer_predicates<'tcx>(
     while predicates_added {
         predicates_added = false;
 
-        let mut visitor = InferVisitor {
-            tcx,
-            global_inferred_outlives: &mut global_inferred_outlives,
-            predicates_added: &mut predicates_added,
-            explicit_map,
-        };
-
         // Visit all the crates and infer predicates
-        tcx.hir().visit_all_item_likes(&mut visitor);
-    }
+        for id in tcx.hir().items() {
+            let item_did = id.def_id;
 
-    global_inferred_outlives
-}
+            debug!("InferVisitor::visit_item(item={:?})", item_did);
 
-pub struct InferVisitor<'cx, 'tcx> {
-    tcx: TyCtxt<'tcx>,
-    global_inferred_outlives: &'cx mut FxHashMap<DefId, RequiredPredicates<'tcx>>,
-    predicates_added: &'cx mut bool,
-    explicit_map: &'cx mut ExplicitPredicatesMap<'tcx>,
-}
-
-impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> {
-    fn visit_item(&mut self, item: &hir::Item<'_>) {
-        let item_did = item.def_id;
-
-        debug!("InferVisitor::visit_item(item={:?})", item_did);
+            let mut item_required_predicates = RequiredPredicates::default();
+            match tcx.hir().def_kind(item_did) {
+                DefKind::Union | DefKind::Enum | DefKind::Struct => {
+                    let adt_def = tcx.adt_def(item_did.to_def_id());
 
-        let mut item_required_predicates = RequiredPredicates::default();
-        match item.kind {
-            hir::ItemKind::Union(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) => {
-                let adt_def = self.tcx.adt_def(item_did.to_def_id());
-
-                // Iterate over all fields in item_did
-                for field_def in adt_def.all_fields() {
-                    // Calculating the predicate requirements necessary
-                    // for item_did.
-                    //
-                    // For field of type &'a T (reference) or Adt
-                    // (struct/enum/union) there will be outlive
-                    // requirements for adt_def.
-                    let field_ty = self.tcx.type_of(field_def.did);
-                    let field_span = self.tcx.def_span(field_def.did);
-                    insert_required_predicates_to_be_wf(
-                        self.tcx,
-                        field_ty,
-                        field_span,
-                        self.global_inferred_outlives,
-                        &mut item_required_predicates,
-                        &mut self.explicit_map,
-                    );
+                    // Iterate over all fields in item_did
+                    for field_def in adt_def.all_fields() {
+                        // Calculating the predicate requirements necessary
+                        // for item_did.
+                        //
+                        // For field of type &'a T (reference) or Adt
+                        // (struct/enum/union) there will be outlive
+                        // requirements for adt_def.
+                        let field_ty = tcx.type_of(field_def.did);
+                        let field_span = tcx.def_span(field_def.did);
+                        insert_required_predicates_to_be_wf(
+                            tcx,
+                            field_ty,
+                            field_span,
+                            &mut global_inferred_outlives,
+                            &mut item_required_predicates,
+                            explicit_map,
+                        );
+                    }
                 }
-            }
 
-            _ => {}
-        };
+                _ => {}
+            };
 
-        // If new predicates were added (`local_predicate_map` has more
-        // predicates than the `global_inferred_outlives`), the new predicates
-        // might result in implied predicates for their parent types.
-        // Therefore mark `predicates_added` as true and which will ensure
-        // we walk the crates again and re-calculate predicates for all
-        // items.
-        let item_predicates_len: usize =
-            self.global_inferred_outlives.get(&item_did.to_def_id()).map_or(0, |p| p.len());
-        if item_required_predicates.len() > item_predicates_len {
-            *self.predicates_added = true;
-            self.global_inferred_outlives.insert(item_did.to_def_id(), item_required_predicates);
+            // If new predicates were added (`local_predicate_map` has more
+            // predicates than the `global_inferred_outlives`), the new predicates
+            // might result in implied predicates for their parent types.
+            // Therefore mark `predicates_added` as true and which will ensure
+            // we walk the crates again and re-calculate predicates for all
+            // items.
+            let item_predicates_len: usize =
+                global_inferred_outlives.get(&item_did.to_def_id()).map_or(0, |p| p.len());
+            if item_required_predicates.len() > item_predicates_len {
+                predicates_added = true;
+                global_inferred_outlives.insert(item_did.to_def_id(), item_required_predicates);
+            }
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem<'tcx>) {}
-
-    fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem<'tcx>) {}
-
-    fn visit_foreign_item(&mut self, _foreign_item: &'tcx hir::ForeignItem<'tcx>) {}
+    global_inferred_outlives
 }
 
 fn insert_required_predicates_to_be_wf<'tcx>(
index 1b1a2037d9eaa9dd5c819c67f8a76dea55d3b9af..5cd7a7d578e4bbcdaca2d1a1bf533c7b7f8bc0f4 100644 (file)
@@ -6,9 +6,10 @@
 use rustc_hir as hir;
 use rustc_middle::hir::map::fn_sig;
 use rustc_middle::middle::resolve_lifetime::LifetimeScopeForPath;
-use rustc_middle::ty::{self as ty, TyCtxt};
+use rustc_middle::ty::{self as ty, AssocItems, AssocKind, TyCtxt};
 use rustc_session::Session;
 use rustc_span::def_id::DefId;
+use std::iter;
 
 use GenericArgsInfo::*;
 
@@ -334,6 +335,22 @@ fn get_type_or_const_args_suggestions_from_param_names(
             .join(", ")
     }
 
+    fn get_unbound_associated_types(&self) -> Vec<String> {
+        if self.tcx.is_trait(self.def_id) {
+            let items: &AssocItems<'_> = self.tcx.associated_items(self.def_id);
+            items
+                .in_definition_order()
+                .filter(|item| item.kind == AssocKind::Type)
+                .filter(|item| {
+                    !self.gen_args.bindings.iter().any(|binding| binding.ident.name == item.name)
+                })
+                .map(|item| item.name.to_ident_string())
+                .collect()
+        } else {
+            Vec::default()
+        }
+    }
+
     fn create_error_message(&self) -> String {
         let def_path = self.tcx.def_path_str(self.def_id);
         let def_kind = self.tcx.def_kind(self.def_id).descr(self.def_id);
@@ -618,6 +635,7 @@ fn suggest_adding_type_and_const_args(&self, err: &mut Diagnostic) {
     fn suggest_removing_args_or_generics(&self, err: &mut Diagnostic) {
         let num_provided_lt_args = self.num_provided_lifetime_args();
         let num_provided_type_const_args = self.num_provided_type_or_const_args();
+        let unbound_types = self.get_unbound_associated_types();
         let num_provided_args = num_provided_lt_args + num_provided_type_const_args;
         assert!(num_provided_args > 0);
 
@@ -629,6 +647,8 @@ fn suggest_removing_args_or_generics(&self, err: &mut Diagnostic) {
         let redundant_type_or_const_args = num_redundant_type_or_const_args > 0;
 
         let remove_entire_generics = num_redundant_args >= self.gen_args.args.len();
+        let provided_args_matches_unbound_traits =
+            unbound_types.len() == num_redundant_type_or_const_args;
 
         let remove_lifetime_args = |err: &mut Diagnostic| {
             let mut lt_arg_spans = Vec::new();
@@ -713,7 +733,28 @@ fn suggest_removing_args_or_generics(&self, err: &mut Diagnostic) {
             );
         };
 
-        if remove_entire_generics {
+        // If there is a single unbound associated type and a single excess generic param
+        // suggest replacing the generic param with the associated type bound
+        if provided_args_matches_unbound_traits && !unbound_types.is_empty() {
+            let mut suggestions = vec![];
+            let unused_generics = &self.gen_args.args[self.num_expected_type_or_const_args()..];
+            for (potential, name) in iter::zip(unused_generics, &unbound_types) {
+                if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(potential.span()) {
+                    suggestions.push((potential.span(), format!("{} = {}", name, snippet)));
+                }
+            }
+
+            if !suggestions.is_empty() {
+                err.multipart_suggestion(
+                    &format!(
+                        "replace the generic bound{s} with the associated type{s}",
+                        s = pluralize!(unbound_types.len())
+                    ),
+                    suggestions,
+                    Applicability::MaybeIncorrect,
+                );
+            }
+        } else if remove_entire_generics {
             let span = self
                 .path_segment
                 .args
index 6e53d9b442f1609ec929f1c021984391d038e879..dd886879b145d897f50d9ddae5307caacc3293ac 100644 (file)
@@ -473,13 +473,23 @@ changelog-seen = 2
 # FIXME(#61117): Some tests fail when this option is enabled.
 #debuginfo-level-tests = 0
 
-# Whether to run `dsymutil` on Apple platforms to gather debug info into .dSYM
-# bundles. `dsymutil` adds time to builds for no clear benefit, and also makes
-# it more difficult for debuggers to find debug info. The compiler currently
-# defaults to running `dsymutil` to preserve its historical default, but when
-# compiling the compiler itself, we skip it by default since we know it's safe
-# to do so in that case.
-#run-dsymutil = false
+# Should rustc be build with split debuginfo? Default is platform dependent.
+# Valid values are the same as those accepted by `-C split-debuginfo`
+# (`off`/`unpacked`/`packed`).
+#
+# On Linux, split debuginfo is disabled by default.
+#
+# On Apple platforms, unpacked split debuginfo is used by default. Unpacked
+# debuginfo does not run `dsymutil`, which packages debuginfo from disparate
+# object files into a single `.dSYM` file. `dsymutil` adds time to builds for
+# no clear benefit, and also makes it more difficult for debuggers to find
+# debug info. The compiler currently defaults to running `dsymutil` to preserve
+# its historical default, but when compiling the compiler itself, we skip it by
+# default since we know it's safe to do so in that case.
+#
+# On Windows platforms, packed debuginfo is the only supported option,
+# producing a `.pdb` file.
+#split-debuginfo = if linux { off } else if windows { packed } else if apple { unpacked }
 
 # Whether or not `panic!`s generate backtraces (RUST_BACKTRACE)
 #backtrace = true
index cc986e93698b7cd1387173fd33165235ff933b5c..47ba1777ae90327e6ead8404c4508a33332d7210 100644 (file)
@@ -1878,6 +1878,96 @@ fn test_first_last_entry() {
     a.check();
 }
 
+#[test]
+fn test_pop_first_last() {
+    let mut map = BTreeMap::new();
+    assert_eq!(map.pop_first(), None);
+    assert_eq!(map.pop_last(), None);
+
+    map.insert(1, 10);
+    map.insert(2, 20);
+    map.insert(3, 30);
+    map.insert(4, 40);
+
+    assert_eq!(map.len(), 4);
+
+    let (key, val) = map.pop_first().unwrap();
+    assert_eq!(key, 1);
+    assert_eq!(val, 10);
+    assert_eq!(map.len(), 3);
+
+    let (key, val) = map.pop_first().unwrap();
+    assert_eq!(key, 2);
+    assert_eq!(val, 20);
+    assert_eq!(map.len(), 2);
+    let (key, val) = map.pop_last().unwrap();
+    assert_eq!(key, 4);
+    assert_eq!(val, 40);
+    assert_eq!(map.len(), 1);
+
+    map.insert(5, 50);
+    map.insert(6, 60);
+    assert_eq!(map.len(), 3);
+
+    let (key, val) = map.pop_first().unwrap();
+    assert_eq!(key, 3);
+    assert_eq!(val, 30);
+    assert_eq!(map.len(), 2);
+
+    let (key, val) = map.pop_last().unwrap();
+    assert_eq!(key, 6);
+    assert_eq!(val, 60);
+    assert_eq!(map.len(), 1);
+
+    let (key, val) = map.pop_last().unwrap();
+    assert_eq!(key, 5);
+    assert_eq!(val, 50);
+    assert_eq!(map.len(), 0);
+
+    assert_eq!(map.pop_first(), None);
+    assert_eq!(map.pop_last(), None);
+
+    map.insert(7, 70);
+    map.insert(8, 80);
+
+    let (key, val) = map.pop_last().unwrap();
+    assert_eq!(key, 8);
+    assert_eq!(val, 80);
+    assert_eq!(map.len(), 1);
+
+    let (key, val) = map.pop_last().unwrap();
+    assert_eq!(key, 7);
+    assert_eq!(val, 70);
+    assert_eq!(map.len(), 0);
+
+    assert_eq!(map.pop_first(), None);
+    assert_eq!(map.pop_last(), None);
+}
+
+#[test]
+fn test_get_key_value() {
+    let mut map = BTreeMap::new();
+
+    assert!(map.is_empty());
+    assert_eq!(map.get_key_value(&1), None);
+    assert_eq!(map.get_key_value(&2), None);
+
+    map.insert(1, 10);
+    map.insert(2, 20);
+    map.insert(3, 30);
+
+    assert_eq!(map.len(), 3);
+    assert_eq!(map.get_key_value(&1), Some((&1, &10)));
+    assert_eq!(map.get_key_value(&3), Some((&3, &30)));
+    assert_eq!(map.get_key_value(&4), None);
+
+    map.remove(&3);
+
+    assert_eq!(map.len(), 2);
+    assert_eq!(map.get_key_value(&3), None);
+    assert_eq!(map.get_key_value(&2), Some((&2, &20)));
+}
+
 #[test]
 fn test_insert_into_full_height_0() {
     let size = node::CAPACITY;
@@ -1904,6 +1994,21 @@ fn test_insert_into_full_height_1() {
     }
 }
 
+#[test]
+fn test_try_insert() {
+    let mut map = BTreeMap::new();
+
+    assert!(map.is_empty());
+
+    assert_eq!(map.try_insert(1, 10).unwrap(), &10);
+    assert_eq!(map.try_insert(2, 20).unwrap(), &20);
+
+    let err = map.try_insert(2, 200).unwrap_err();
+    assert_eq!(err.entry.key(), &2);
+    assert_eq!(err.entry.get(), &20);
+    assert_eq!(err.value, 200);
+}
+
 macro_rules! create_append_test {
     ($name:ident, $len:expr) => {
         #[test]
index d3e9e65c3fe57b493001b6c77c9afc99287ff126..22c19243e7f53fca729e9e75503e51b59802355f 100644 (file)
@@ -34,7 +34,7 @@
 /// be mindful of side effects.
 ///
 /// [`Vec`]: crate::vec::Vec
-#[cfg(not(test))]
+#[cfg(all(not(no_global_oom_handling), not(test)))]
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_diagnostic_item = "vec_macro"]
@@ -55,7 +55,7 @@ macro_rules! vec {
 // required for this macro definition, is not available. Instead use the
 // `slice::into_vec`  function which is only available with cfg(test)
 // NB see the slice::hack module in slice.rs for more information
-#[cfg(test)]
+#[cfg(all(not(no_global_oom_handling), test))]
 macro_rules! vec {
     () => (
         $crate::vec::Vec::new()
index d0d37c08d13068afe56809fb7c3338aebd52732c..a42f1c3b4bbae1cc154726eccf840b2d3d4af71f 100644 (file)
@@ -2511,14 +2511,23 @@ fn strong(&self) -> usize {
     fn inc_strong(&self) {
         let strong = self.strong();
 
+        // We insert an `assume` here to hint LLVM at an otherwise
+        // missed optimization.
+        // SAFETY: The reference count will never be zero when this is
+        // called.
+        unsafe {
+            core::intrinsics::assume(strong != 0);
+        }
+
+        let strong = strong.wrapping_add(1);
+        self.strong_ref().set(strong);
+
         // We want to abort on overflow instead of dropping the value.
-        // The reference count will never be zero when this is called;
-        // nevertheless, we insert an abort here to hint LLVM at
-        // an otherwise missed optimization.
-        if strong == 0 || strong == usize::MAX {
+        // Checking for overflow after the store instead of before
+        // allows for slightly better code generation.
+        if core::intrinsics::unlikely(strong == 0) {
             abort();
         }
-        self.strong_ref().set(strong + 1);
     }
 
     #[inline]
@@ -2535,14 +2544,23 @@ fn weak(&self) -> usize {
     fn inc_weak(&self) {
         let weak = self.weak();
 
+        // We insert an `assume` here to hint LLVM at an otherwise
+        // missed optimization.
+        // SAFETY: The reference count will never be zero when this is
+        // called.
+        unsafe {
+            core::intrinsics::assume(weak != 0);
+        }
+
+        let weak = weak.wrapping_add(1);
+        self.weak_ref().set(weak);
+
         // We want to abort on overflow instead of dropping the value.
-        // The reference count will never be zero when this is called;
-        // nevertheless, we insert an abort here to hint LLVM at
-        // an otherwise missed optimization.
-        if weak == 0 || weak == usize::MAX {
+        // Checking for overflow after the store instead of before
+        // allows for slightly better code generation.
+        if core::intrinsics::unlikely(weak == 0) {
             abort();
         }
-        self.weak_ref().set(weak + 1);
     }
 
     #[inline]
index 74bcac2b5414de6886b4666ce9ad524ea1678041..8c2f52172ee70d44286fdadb06d0b982694eae33 100644 (file)
@@ -1881,7 +1881,18 @@ pub fn drain<R>(&mut self, range: R) -> Drain<'_, T, A>
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn clear(&mut self) {
-        self.truncate(0)
+        let elems: *mut [T] = self.as_mut_slice();
+
+        // SAFETY:
+        // - `elems` comes directly from `as_mut_slice` and is therefore valid.
+        // - Setting `self.len` before calling `drop_in_place` means that,
+        //   if an element's `Drop` impl panics, the vector's `Drop` impl will
+        //   do nothing (leaking the rest of the elements) instead of dropping
+        //   some twice.
+        unsafe {
+            self.len = 0;
+            ptr::drop_in_place(elems);
+        }
     }
 
     /// Returns the number of elements in the vector, also referred to
index 729b0a04eb6ba092795405ffb85f302ae8b542d3..a42a1dcfe39881d50134ab409e4ca38713f1fcb1 100644 (file)
@@ -77,6 +77,6 @@ fn is_ascii_align_to_unrolled(bytes: &[u8]) -> bool {
 
 #[inline]
 fn contains_nonascii(v: usize) -> bool {
-    const NONASCII_MASK: usize = 0x80808080_80808080u64 as usize;
+    const NONASCII_MASK: usize = usize::from_ne_bytes([0x80; core::mem::size_of::<usize>()]);
     (NONASCII_MASK & v) != 0
 }
index 5809ed1f33b07d6836f816565263dca0701029af..0bec38a877ed5fcd2ce0d6a7f908077f25691604 100644 (file)
@@ -343,10 +343,10 @@ pub fn is_digit(self, radix: u32) -> bool {
                   without modifying the original"]
     #[inline]
     pub const fn to_digit(self, radix: u32) -> Option<u32> {
-        assert!(radix <= 36, "to_digit: radix is too high (maximum 36)");
         // If not a digit, a number greater than radix will be created.
         let mut digit = (self as u32).wrapping_sub('0' as u32);
         if radix > 10 {
+            assert!(radix <= 36, "to_digit: radix is too high (maximum 36)");
             if digit < 10 {
                 return Some(digit);
             }
index 8e02ca8431744b4effcffb88f1e85ef2e6b2351a..bddbe2b9b0df104da8c8c9b500835c2fe86969ad 100644 (file)
@@ -1,7 +1,7 @@
 //! Compiler intrinsics.
 //!
-//! The corresponding definitions are in `compiler/rustc_codegen_llvm/src/intrinsic.rs`.
-//! The corresponding const implementations are in `compiler/rustc_mir/src/interpret/intrinsics.rs`
+//! The corresponding definitions are in <https://github.com/rust-lang/rust/blob/master/compiler/rustc_codegen_llvm/src/intrinsic.rs>.
+//! The corresponding const implementations are in <https://github.com/rust-lang/rust/blob/master/compiler/rustc_const_eval/src/interpret/intrinsics.rs>.
 //!
 //! # Const intrinsics
 //!
@@ -10,8 +10,8 @@
 //!
 //! In order to make an intrinsic usable at compile-time, one needs to copy the implementation
 //! from <https://github.com/rust-lang/miri/blob/master/src/shims/intrinsics.rs> to
-//! `compiler/rustc_mir/src/interpret/intrinsics.rs` and add a
-//! `#[rustc_const_unstable(feature = "foo", issue = "01234")]` to the intrinsic.
+//! <https://github.com/rust-lang/rust/blob/master/compiler/rustc_const_eval/src/interpret/intrinsics.rs> and add a
+//! `#[rustc_const_unstable(feature = "const_such_and_such", issue = "01234")]` to the intrinsic declaration.
 //!
 //! If an intrinsic is supposed to be used from a `const fn` with a `rustc_const_stable` attribute,
 //! the intrinsic's attribute must be `rustc_const_stable`, too. Such a change should not be done
index 7b75ab96ee7deea69f7f194b115490bc51702a64..e6900742c31d235d7ce15e4f1f1c1b5e4f2341fc 100644 (file)
@@ -267,8 +267,9 @@ pub trait IntoIterator {
     fn into_iter(self) -> Self::IntoIter;
 }
 
+#[rustc_const_unstable(feature = "const_intoiterator_identity", issue = "90603")]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<I: Iterator> IntoIterator for I {
+impl<I: ~const Iterator> const IntoIterator for I {
     type Item = I::Item;
     type IntoIter = I;
 
index 53fbe4cbc42f53fca6dd42ccfa1c59b53c29522f..69f06fb06ef5d19c478a691dc9b0b29fca84a69d 100644 (file)
@@ -470,6 +470,10 @@ fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter>
     /// it will first try to advance the first iterator at most one time and if it still yielded an item
     /// try to advance the second iterator at most one time.
     ///
+    /// To 'undo' the result of zipping up two iterators, see [`unzip`].
+    ///
+    /// [`unzip`]: Iterator::unzip
+    ///
     /// # Examples
     ///
     /// Basic usage:
index 8aa355a554d70a0d2c415c35f95aea42f1ee9d03..1612aa582ad17a39de7ded0ccb7579c977a895f5 100644 (file)
 #![feature(const_intrinsic_copy)]
 #![feature(const_intrinsic_forget)]
 #![feature(const_likely)]
+#![feature(const_maybe_uninit_uninit_array)]
 #![feature(const_maybe_uninit_as_mut_ptr)]
 #![feature(const_maybe_uninit_assume_init)]
+#![feature(const_nonnull_new)]
 #![feature(const_num_from_num)]
 #![feature(const_ops)]
 #![feature(const_option)]
 #![feature(const_option_ext)]
 #![feature(const_pin)]
 #![feature(const_replace)]
+#![feature(const_ptr_as_ref)]
 #![feature(const_ptr_is_null)]
 #![feature(const_ptr_offset_from)]
 #![feature(const_ptr_read)]
index 58d682fc4c8d4b31cb53e0541e48f063f94864fb..cac7f435573a52500efb05f678a6fceda527ff5b 100644 (file)
@@ -350,13 +350,13 @@ pub const fn uninit() -> MaybeUninit<T> {
     /// let mut buf: [MaybeUninit<u8>; 32] = MaybeUninit::uninit_array();
     /// let data = read(&mut buf);
     /// ```
-    #[unstable(feature = "maybe_uninit_uninit_array", issue = "none")]
-    #[rustc_const_unstable(feature = "maybe_uninit_uninit_array", issue = "none")]
+    #[unstable(feature = "maybe_uninit_uninit_array", issue = "96097")]
+    #[rustc_const_unstable(feature = "const_maybe_uninit_uninit_array", issue = "96097")]
     #[must_use]
     #[inline(always)]
-    pub const fn uninit_array<const LEN: usize>() -> [Self; LEN] {
+    pub const fn uninit_array<const N: usize>() -> [Self; N] {
         // SAFETY: An uninitialized `[MaybeUninit<_>; LEN]` is valid.
-        unsafe { MaybeUninit::<[MaybeUninit<T>; LEN]>::uninit().assume_init() }
+        unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() }
     }
 
     /// Creates a new `MaybeUninit<T>` in an uninitialized state, with the memory being
@@ -942,19 +942,24 @@ pub unsafe fn assume_init_drop(&mut self) {
     ///
     /// assert_eq!(array, [0, 1, 2]);
     /// ```
-    #[unstable(feature = "maybe_uninit_array_assume_init", issue = "80908")]
+    #[unstable(feature = "maybe_uninit_array_assume_init", issue = "96097")]
+    #[rustc_const_unstable(feature = "const_maybe_uninit_array_assume_init", issue = "96097")]
     #[inline(always)]
     #[track_caller]
-    pub unsafe fn array_assume_init<const N: usize>(array: [Self; N]) -> [T; N] {
+    pub const unsafe fn array_assume_init<const N: usize>(array: [Self; N]) -> [T; N] {
         // SAFETY:
         // * The caller guarantees that all elements of the array are initialized
         // * `MaybeUninit<T>` and T are guaranteed to have the same layout
         // * `MaybeUninit` does not drop, so there are no double-frees
         // And thus the conversion is safe
-        unsafe {
+        let ret = unsafe {
             intrinsics::assert_inhabited::<[T; N]>();
             (&array as *const _ as *const [T; N]).read()
-        }
+        };
+
+        // FIXME: required to avoid `~const Destruct` bound
+        super::forget(array);
+        ret
     }
 
     /// Assuming all the elements are initialized, get a slice to them.
index a983d0872bcf00828f16cc63385dadc44899e1b8..e1a46086af060407134011f5bacce82997acd4d4 100644 (file)
@@ -449,7 +449,8 @@ pub const fn is_nan(self) -> bool {
     #[inline]
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     pub(crate) const fn abs_private(self) -> f32 {
-        f32::from_bits(self.to_bits() & 0x7fff_ffff)
+        // SAFETY: This transmutation is fine. Probably. For the reasons std is using it.
+        unsafe { mem::transmute::<u32, f32>(mem::transmute::<f32, u32>(self) & 0x7fff_ffff) }
     }
 
     /// Returns `true` if this value is positive infinity or negative infinity, and
@@ -472,7 +473,10 @@ pub(crate) const fn abs_private(self) -> f32 {
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     #[inline]
     pub const fn is_infinite(self) -> bool {
-        self.abs_private() == Self::INFINITY
+        // Getting clever with transmutation can result in incorrect answers on some FPUs
+        // FIXME: alter the Rust <-> Rust calling convention to prevent this problem.
+        // See https://github.com/rust-lang/rust/issues/72327
+        (self == f32::INFINITY) | (self == f32::NEG_INFINITY)
     }
 
     /// Returns `true` if this number is neither infinite nor `NaN`.
@@ -568,15 +572,76 @@ pub const fn is_normal(self) -> bool {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     pub const fn classify(self) -> FpCategory {
+        // A previous implementation tried to only use bitmask-based checks,
+        // using f32::to_bits to transmute the float to its bit repr and match on that.
+        // Unfortunately, floating point numbers can be much worse than that.
+        // This also needs to not result in recursive evaluations of f64::to_bits.
+        //
+        // On some processors, in some cases, LLVM will "helpfully" lower floating point ops,
+        // in spite of a request for them using f32 and f64, to things like x87 operations.
+        // These have an f64's mantissa, but can have a larger than normal exponent.
+        // FIXME(jubilee): Using x87 operations is never necessary in order to function
+        // on x86 processors for Rust-to-Rust calls, so this issue should not happen.
+        // Code generation should be adjusted to use non-C calling conventions, avoiding this.
+        //
+        if self.is_infinite() {
+            // Thus, a value may compare unequal to infinity, despite having a "full" exponent mask.
+            FpCategory::Infinite
+        } else if self.is_nan() {
+            // And it may not be NaN, as it can simply be an "overextended" finite value.
+            FpCategory::Nan
+        } else {
+            // However, std can't simply compare to zero to check for zero, either,
+            // as correctness requires avoiding equality tests that may be Subnormal == -0.0
+            // because it may be wrong under "denormals are zero" and "flush to zero" modes.
+            // Most of std's targets don't use those, but they are used for thumbv7neon.
+            // So, this does use bitpattern matching for the rest.
+
+            // SAFETY: f32 to u32 is fine. Usually.
+            // If classify has gotten this far, the value is definitely in one of these categories.
+            unsafe { f32::partial_classify(self) }
+        }
+    }
+
+    // This doesn't actually return a right answer for NaN on purpose,
+    // seeing as how it cannot correctly discern between a floating point NaN,
+    // and some normal floating point numbers truncated from an x87 FPU.
+    // FIXME(jubilee): This probably could at least answer things correctly for Infinity,
+    // like the f64 version does, but I need to run more checks on how things go on x86.
+    // I fear losing mantissa data that would have answered that differently.
+    //
+    // # Safety
+    // This requires making sure you call this function for values it answers correctly on,
+    // otherwise it returns a wrong answer. This is not important for memory safety per se,
+    // but getting floats correct is important for not accidentally leaking const eval
+    // runtime-deviating logic which may or may not be acceptable.
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
+    const unsafe fn partial_classify(self) -> FpCategory {
         const EXP_MASK: u32 = 0x7f800000;
         const MAN_MASK: u32 = 0x007fffff;
 
-        let bits = self.to_bits();
-        match (bits & MAN_MASK, bits & EXP_MASK) {
+        // SAFETY: The caller is not asking questions for which this will tell lies.
+        let b = unsafe { mem::transmute::<f32, u32>(self) };
+        match (b & MAN_MASK, b & EXP_MASK) {
             (0, 0) => FpCategory::Zero,
             (_, 0) => FpCategory::Subnormal,
+            _ => FpCategory::Normal,
+        }
+    }
+
+    // This operates on bits, and only bits, so it can ignore concerns about weird FPUs.
+    // FIXME(jubilee): In a just world, this would be the entire impl for classify,
+    // plus a transmute. We do not live in a just world, but we can make it more so.
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
+    const fn classify_bits(b: u32) -> FpCategory {
+        const EXP_MASK: u32 = 0x7f800000;
+        const MAN_MASK: u32 = 0x007fffff;
+
+        match (b & MAN_MASK, b & EXP_MASK) {
             (0, EXP_MASK) => FpCategory::Infinite,
             (_, EXP_MASK) => FpCategory::Nan,
+            (0, 0) => FpCategory::Zero,
+            (_, 0) => FpCategory::Subnormal,
             _ => FpCategory::Normal,
         }
     }
@@ -616,7 +681,8 @@ pub const fn is_sign_positive(self) -> bool {
     pub const fn is_sign_negative(self) -> bool {
         // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
         // applies to zeros and NaNs as well.
-        self.to_bits() & 0x8000_0000 != 0
+        // SAFETY: This is just transmuting to get the sign bit, it's fine.
+        unsafe { mem::transmute::<f32, u32>(self) & 0x8000_0000 != 0 }
     }
 
     /// Takes the reciprocal (inverse) of a number, `1/x`.
@@ -831,8 +897,49 @@ pub unsafe fn to_int_unchecked<Int>(self) -> Int
     #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
     #[inline]
     pub const fn to_bits(self) -> u32 {
-        // SAFETY: `u32` is a plain old datatype so we can always transmute to it
-        unsafe { mem::transmute(self) }
+        // SAFETY: `u32` is a plain old datatype so we can always transmute to it.
+        // ...sorta.
+        //
+        // It turns out that at runtime, it is possible for a floating point number
+        // to be subject to a floating point mode that alters nonzero subnormal numbers
+        // to zero on reads and writes, aka "denormals are zero" and "flush to zero".
+        // This is not a problem per se, but at least one tier2 platform for Rust
+        // actually exhibits this behavior by default.
+        //
+        // In addition, on x86 targets with SSE or SSE2 disabled and the x87 FPU enabled,
+        // i.e. not soft-float, the way Rust does parameter passing can actually alter
+        // a number that is "not infinity" to have the same exponent as infinity,
+        // in a slightly unpredictable manner.
+        //
+        // And, of course evaluating to a NaN value is fairly nondeterministic.
+        // More precisely: when NaN should be returned is knowable, but which NaN?
+        // So far that's defined by a combination of LLVM and the CPU, not Rust.
+        // This function, however, allows observing the bitstring of a NaN,
+        // thus introspection on CTFE.
+        //
+        // In order to preserve, at least for the moment, const-to-runtime equivalence,
+        // we reject any of these possible situations from happening.
+        #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+        const fn ct_f32_to_u32(ct: f32) -> u32 {
+            match ct.classify() {
+                FpCategory::Nan => {
+                    panic!("const-eval error: cannot use f32::to_bits on a NaN")
+                }
+                FpCategory::Subnormal => {
+                    panic!("const-eval error: cannot use f32::to_bits on a subnormal number")
+                }
+                FpCategory::Infinite | FpCategory::Normal | FpCategory::Zero => {
+                    // SAFETY: We have a normal floating point number. Now we transmute, i.e. do a bitcopy.
+                    unsafe { mem::transmute::<f32, u32>(ct) }
+                }
+            }
+        }
+        // SAFETY: `u32` is a plain old datatype so we can always... uh...
+        // ...look, just pretend you forgot what you just read.
+        // Stability concerns.
+        let rt_f32_to_u32 = |rt| unsafe { mem::transmute::<f32, u32>(rt) };
+        // SAFETY: We use internal implementations that either always work or fail at compile time.
+        unsafe { intrinsics::const_eval_select((self,), ct_f32_to_u32, rt_f32_to_u32) }
     }
 
     /// Raw transmutation from `u32`.
@@ -876,9 +983,51 @@ pub const fn to_bits(self) -> u32 {
     #[must_use]
     #[inline]
     pub const fn from_bits(v: u32) -> Self {
-        // SAFETY: `u32` is a plain old datatype so we can always transmute from it
         // It turns out the safety issues with sNaN were overblown! Hooray!
-        unsafe { mem::transmute(v) }
+        // SAFETY: `u32` is a plain old datatype so we can always transmute from it
+        // ...sorta.
+        //
+        // It turns out that at runtime, it is possible for a floating point number
+        // to be subject to floating point modes that alter nonzero subnormal numbers
+        // to zero on reads and writes, aka "denormals are zero" and "flush to zero".
+        // This is not a problem usually, but at least one tier2 platform for Rust
+        // actually exhibits this behavior by default: thumbv7neon
+        // aka "the Neon FPU in AArch32 state"
+        //
+        // In addition, on x86 targets with SSE or SSE2 disabled and the x87 FPU enabled,
+        // i.e. not soft-float, the way Rust does parameter passing can actually alter
+        // a number that is "not infinity" to have the same exponent as infinity,
+        // in a slightly unpredictable manner.
+        //
+        // And, of course evaluating to a NaN value is fairly nondeterministic.
+        // More precisely: when NaN should be returned is knowable, but which NaN?
+        // So far that's defined by a combination of LLVM and the CPU, not Rust.
+        // This function, however, allows observing the bitstring of a NaN,
+        // thus introspection on CTFE.
+        //
+        // In order to preserve, at least for the moment, const-to-runtime equivalence,
+        // reject any of these possible situations from happening.
+        #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+        const fn ct_u32_to_f32(ct: u32) -> f32 {
+            match f32::classify_bits(ct) {
+                FpCategory::Subnormal => {
+                    panic!("const-eval error: cannot use f32::from_bits on a subnormal number")
+                }
+                FpCategory::Nan => {
+                    panic!("const-eval error: cannot use f32::from_bits on NaN")
+                }
+                FpCategory::Infinite | FpCategory::Normal | FpCategory::Zero => {
+                    // SAFETY: It's not a frumious number
+                    unsafe { mem::transmute::<u32, f32>(ct) }
+                }
+            }
+        }
+        // SAFETY: `u32` is a plain old datatype so we can always... uh...
+        // ...look, just pretend you forgot what you just read.
+        // Stability concerns.
+        let rt_u32_to_f32 = |rt| unsafe { mem::transmute::<u32, f32>(rt) };
+        // SAFETY: We use internal implementations that either always work or fail at compile time.
+        unsafe { intrinsics::const_eval_select((v,), ct_u32_to_f32, rt_u32_to_f32) }
     }
 
     /// Return the memory representation of this floating point number as a byte array in
index 05598e5fe7b07f81d94d5c41c51422a7c6641918..b07f201ca4ad282aa08069d21ed06e25586fc761 100644 (file)
@@ -448,7 +448,10 @@ pub const fn is_nan(self) -> bool {
     #[inline]
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     pub(crate) const fn abs_private(self) -> f64 {
-        f64::from_bits(self.to_bits() & 0x7fff_ffff_ffff_ffff)
+        // SAFETY: This transmutation is fine. Probably. For the reasons std is using it.
+        unsafe {
+            mem::transmute::<u64, f64>(mem::transmute::<f64, u64>(self) & 0x7fff_ffff_ffff_ffff)
+        }
     }
 
     /// Returns `true` if this value is positive infinity or negative infinity, and
@@ -471,7 +474,10 @@ pub(crate) const fn abs_private(self) -> f64 {
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     #[inline]
     pub const fn is_infinite(self) -> bool {
-        self.abs_private() == Self::INFINITY
+        // Getting clever with transmutation can result in incorrect answers on some FPUs
+        // FIXME: alter the Rust <-> Rust calling convention to prevent this problem.
+        // See https://github.com/rust-lang/rust/issues/72327
+        (self == f64::INFINITY) | (self == f64::NEG_INFINITY)
     }
 
     /// Returns `true` if this number is neither infinite nor `NaN`.
@@ -567,15 +573,67 @@ pub const fn is_normal(self) -> bool {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     pub const fn classify(self) -> FpCategory {
+        // A previous implementation tried to only use bitmask-based checks,
+        // using f64::to_bits to transmute the float to its bit repr and match on that.
+        // Unfortunately, floating point numbers can be much worse than that.
+        // This also needs to not result in recursive evaluations of f64::to_bits.
+        //
+        // On some processors, in some cases, LLVM will "helpfully" lower floating point ops,
+        // in spite of a request for them using f32 and f64, to things like x87 operations.
+        // These have an f64's mantissa, but can have a larger than normal exponent.
+        // FIXME(jubilee): Using x87 operations is never necessary in order to function
+        // on x86 processors for Rust-to-Rust calls, so this issue should not happen.
+        // Code generation should be adjusted to use non-C calling conventions, avoiding this.
+        //
+        // Thus, a value may compare unequal to infinity, despite having a "full" exponent mask.
+        // And it may not be NaN, as it can simply be an "overextended" finite value.
+        if self.is_nan() {
+            FpCategory::Nan
+        } else {
+            // However, std can't simply compare to zero to check for zero, either,
+            // as correctness requires avoiding equality tests that may be Subnormal == -0.0
+            // because it may be wrong under "denormals are zero" and "flush to zero" modes.
+            // Most of std's targets don't use those, but they are used for thumbv7neon.
+            // So, this does use bitpattern matching for the rest.
+
+            // SAFETY: f64 to u64 is fine. Usually.
+            // If control flow has gotten this far, the value is definitely in one of the categories
+            // that f64::partial_classify can correctly analyze.
+            unsafe { f64::partial_classify(self) }
+        }
+    }
+
+    // This doesn't actually return a right answer for NaN on purpose,
+    // seeing as how it cannot correctly discern between a floating point NaN,
+    // and some normal floating point numbers truncated from an x87 FPU.
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
+    const unsafe fn partial_classify(self) -> FpCategory {
         const EXP_MASK: u64 = 0x7ff0000000000000;
         const MAN_MASK: u64 = 0x000fffffffffffff;
 
-        let bits = self.to_bits();
-        match (bits & MAN_MASK, bits & EXP_MASK) {
+        // SAFETY: The caller is not asking questions for which this will tell lies.
+        let b = unsafe { mem::transmute::<f64, u64>(self) };
+        match (b & MAN_MASK, b & EXP_MASK) {
+            (0, EXP_MASK) => FpCategory::Infinite,
             (0, 0) => FpCategory::Zero,
             (_, 0) => FpCategory::Subnormal,
+            _ => FpCategory::Normal,
+        }
+    }
+
+    // This operates on bits, and only bits, so it can ignore concerns about weird FPUs.
+    // FIXME(jubilee): In a just world, this would be the entire impl for classify,
+    // plus a transmute. We do not live in a just world, but we can make it more so.
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
+    const fn classify_bits(b: u64) -> FpCategory {
+        const EXP_MASK: u64 = 0x7ff0000000000000;
+        const MAN_MASK: u64 = 0x000fffffffffffff;
+
+        match (b & MAN_MASK, b & EXP_MASK) {
             (0, EXP_MASK) => FpCategory::Infinite,
             (_, EXP_MASK) => FpCategory::Nan,
+            (0, 0) => FpCategory::Zero,
+            (_, 0) => FpCategory::Subnormal,
             _ => FpCategory::Normal,
         }
     }
@@ -622,7 +680,10 @@ pub fn is_positive(self) -> bool {
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     #[inline]
     pub const fn is_sign_negative(self) -> bool {
-        self.to_bits() & 0x8000_0000_0000_0000 != 0
+        // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
+        // applies to zeros and NaNs as well.
+        // SAFETY: This is just transmuting to get the sign bit, it's fine.
+        unsafe { mem::transmute::<f64, u64>(self) & 0x8000_0000_0000_0000 != 0 }
     }
 
     #[must_use]
@@ -847,8 +908,31 @@ pub unsafe fn to_int_unchecked<Int>(self) -> Int
     #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
     #[inline]
     pub const fn to_bits(self) -> u64 {
-        // SAFETY: `u64` is a plain old datatype so we can always transmute to it
-        unsafe { mem::transmute(self) }
+        // SAFETY: `u64` is a plain old datatype so we can always transmute to it.
+        // ...sorta.
+        //
+        // See the SAFETY comment in f64::from_bits for more.
+        #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+        const fn ct_f64_to_u64(ct: f64) -> u64 {
+            match ct.classify() {
+                FpCategory::Nan => {
+                    panic!("const-eval error: cannot use f64::to_bits on a NaN")
+                }
+                FpCategory::Subnormal => {
+                    panic!("const-eval error: cannot use f64::to_bits on a subnormal number")
+                }
+                FpCategory::Infinite | FpCategory::Normal | FpCategory::Zero => {
+                    // SAFETY: We have a normal floating point number. Now we transmute, i.e. do a bitcopy.
+                    unsafe { mem::transmute::<f64, u64>(ct) }
+                }
+            }
+        }
+        // SAFETY: `u64` is a plain old datatype so we can always... uh...
+        // ...look, just pretend you forgot what you just read.
+        // Stability concerns.
+        let rt_f64_to_u64 = |rt| unsafe { mem::transmute::<f64, u64>(rt) };
+        // SAFETY: We use internal implementations that either always work or fail at compile time.
+        unsafe { intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64) }
     }
 
     /// Raw transmutation from `u64`.
@@ -892,9 +976,56 @@ pub const fn to_bits(self) -> u64 {
     #[must_use]
     #[inline]
     pub const fn from_bits(v: u64) -> Self {
-        // SAFETY: `u64` is a plain old datatype so we can always transmute from it
         // It turns out the safety issues with sNaN were overblown! Hooray!
-        unsafe { mem::transmute(v) }
+        // SAFETY: `u64` is a plain old datatype so we can always transmute from it
+        // ...sorta.
+        //
+        // It turns out that at runtime, it is possible for a floating point number
+        // to be subject to floating point modes that alter nonzero subnormal numbers
+        // to zero on reads and writes, aka "denormals are zero" and "flush to zero".
+        // This is not a problem usually, but at least one tier2 platform for Rust
+        // actually exhibits an FTZ behavior by default: thumbv7neon
+        // aka "the Neon FPU in AArch32 state"
+        //
+        // Even with this, not all instructions exhibit the FTZ behaviors on thumbv7neon,
+        // so this should load the same bits if LLVM emits the "correct" instructions,
+        // but LLVM sometimes makes interesting choices about float optimization,
+        // and other FPUs may do similar. Thus, it is wise to indulge luxuriously in caution.
+        //
+        // In addition, on x86 targets with SSE or SSE2 disabled and the x87 FPU enabled,
+        // i.e. not soft-float, the way Rust does parameter passing can actually alter
+        // a number that is "not infinity" to have the same exponent as infinity,
+        // in a slightly unpredictable manner.
+        //
+        // And, of course evaluating to a NaN value is fairly nondeterministic.
+        // More precisely: when NaN should be returned is knowable, but which NaN?
+        // So far that's defined by a combination of LLVM and the CPU, not Rust.
+        // This function, however, allows observing the bitstring of a NaN,
+        // thus introspection on CTFE.
+        //
+        // In order to preserve, at least for the moment, const-to-runtime equivalence,
+        // reject any of these possible situations from happening.
+        #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+        const fn ct_u64_to_f64(ct: u64) -> f64 {
+            match f64::classify_bits(ct) {
+                FpCategory::Subnormal => {
+                    panic!("const-eval error: cannot use f64::from_bits on a subnormal number")
+                }
+                FpCategory::Nan => {
+                    panic!("const-eval error: cannot use f64::from_bits on NaN")
+                }
+                FpCategory::Infinite | FpCategory::Normal | FpCategory::Zero => {
+                    // SAFETY: It's not a frumious number
+                    unsafe { mem::transmute::<u64, f64>(ct) }
+                }
+            }
+        }
+        // SAFETY: `u64` is a plain old datatype so we can always... uh...
+        // ...look, just pretend you forgot what you just read.
+        // Stability concerns.
+        let rt_u64_to_f64 = |rt| unsafe { mem::transmute::<u64, f64>(rt) };
+        // SAFETY: We use internal implementations that either always work or fail at compile time.
+        unsafe { intrinsics::const_eval_select((v,), ct_u64_to_f64, rt_u64_to_f64) }
     }
 
     /// Return the memory representation of this floating point number as a byte array in
index 8b93cd39d5df3c07d064ea611377cad1239ac5ae..66193eaf5da73c1da12d93265d8b8b8f5a78636c 100644 (file)
@@ -890,6 +890,27 @@ impl usize {
     widening_impl! { usize, u128, 64, unsigned }
 }
 
+impl usize {
+    /// Returns an `usize` where every byte is equal to `x`.
+    #[inline]
+    pub(crate) const fn repeat_u8(x: u8) -> usize {
+        usize::from_ne_bytes([x; mem::size_of::<usize>()])
+    }
+
+    /// Returns an `usize` where every byte pair is equal to `x`.
+    #[inline]
+    pub(crate) const fn repeat_u16(x: u16) -> usize {
+        let mut r = 0usize;
+        let mut i = 0;
+        while i < mem::size_of::<usize>() {
+            // Use `wrapping_shl` to make it work on targets with 16-bit `usize`
+            r = r.wrapping_shl(16) | (x as usize);
+            i += 2;
+        }
+        r
+    }
+}
+
 /// A classification of floating point numbers.
 ///
 /// This `enum` is used as the return type for [`f32::classify`] and [`f64::classify`]. See
index 68f39dc434780fe1471d84cf5bc41d27a76970c0..7ef2e95542bba6b3a0ec1e7fb92491cc88c240dc 100644 (file)
@@ -295,7 +295,7 @@ pub const fn to_raw_parts(self) -> (*const (), <T as super::Pointee>::Metadata)
     ///
     /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
     ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
-    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   In particular, while this reference exists, the memory the pointer points to must
     ///   not get mutated (except inside `UnsafeCell`).
     ///
     /// This applies even if the result of this method is unused!
@@ -358,7 +358,7 @@ pub const fn to_raw_parts(self) -> (*const (), <T as super::Pointee>::Metadata)
     ///
     /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
     ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
-    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   In particular, while this reference exists, the memory the pointer points to must
     ///   not get mutated (except inside `UnsafeCell`).
     ///
     /// This applies even if the result of this method is unused!
@@ -1188,7 +1188,7 @@ pub const fn as_ptr(self) -> *const T {
     ///
     /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
     ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
-    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   In particular, while this reference exists, the memory the pointer points to must
     ///   not get mutated (except inside `UnsafeCell`).
     ///
     /// This applies even if the result of this method is unused!
index 4c9b0f7cc0c0513934871184251a4a728f5243d4..56f9c84f5af6f3341db11472f75528917fc9b76e 100644 (file)
@@ -302,7 +302,7 @@ pub const fn to_raw_parts(self) -> (*mut (), <T as super::Pointee>::Metadata) {
     ///
     /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
     ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
-    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   In particular, while this reference exists, the memory the pointer points to must
     ///   not get mutated (except inside `UnsafeCell`).
     ///
     /// This applies even if the result of this method is unused!
@@ -368,7 +368,7 @@ pub const fn to_raw_parts(self) -> (*mut (), <T as super::Pointee>::Metadata) {
     ///
     /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
     ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
-    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   In particular, while this reference exists, the memory the pointer points to must
     ///   not get mutated (except inside `UnsafeCell`).
     ///
     /// This applies even if the result of this method is unused!
@@ -550,7 +550,7 @@ pub const fn wrapping_offset(self, count: isize) -> *mut T
     ///
     /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
     ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
-    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   In particular, while this reference exists, the memory the pointer points to must
     ///   not get accessed (read or written) through any other pointer.
     ///
     /// This applies even if the result of this method is unused!
@@ -615,7 +615,7 @@ pub const fn wrapping_offset(self, count: isize) -> *mut T
     ///
     /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
     ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
-    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   In particular, while this reference exists, the memory the pointer points to must
     ///   not get accessed (read or written) through any other pointer.
     ///
     /// This applies even if the result of this method is unused!
@@ -1461,7 +1461,7 @@ pub const fn as_mut_ptr(self) -> *mut T {
     ///
     /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
     ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
-    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   In particular, while this reference exists, the memory the pointer points to must
     ///   not get mutated (except inside `UnsafeCell`).
     ///
     /// This applies even if the result of this method is unused!
@@ -1513,7 +1513,7 @@ pub const fn as_mut_ptr(self) -> *mut T {
     ///
     /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
     ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
-    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   In particular, while this reference exists, the memory the pointer points to must
     ///   not get accessed (read or written) through any other pointer.
     ///
     /// This applies even if the result of this method is unused!
index 6f402924e75dfadec1cb0bb3acdf2ff0e8c40e6c..5ebe61509063f3a7807bacdc5ace278d7666366b 100644 (file)
@@ -114,7 +114,7 @@ pub const fn dangling() -> Self {
     ///
     /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
     ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
-    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   In particular, while this reference exists, the memory the pointer points to must
     ///   not get mutated (except inside `UnsafeCell`).
     ///
     /// This applies even if the result of this method is unused!
@@ -148,7 +148,7 @@ pub const fn dangling() -> Self {
     ///
     /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
     ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
-    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   In particular, while this reference exists, the memory the pointer points to must
     ///   not get accessed (read or written) through any other pointer.
     ///
     /// This applies even if the result of this method is unused!
@@ -350,7 +350,7 @@ pub const fn as_ptr(self) -> *mut T {
     ///
     /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
     ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
-    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   In particular, while this reference exists, the memory the pointer points to must
     ///   not get mutated (except inside `UnsafeCell`).
     ///
     /// This applies even if the result of this method is unused!
@@ -400,7 +400,7 @@ pub const fn as_ptr(self) -> *mut T {
     ///
     /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
     ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
-    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   In particular, while this reference exists, the memory the pointer points to must
     ///   not get accessed (read or written) through any other pointer.
     ///
     /// This applies even if the result of this method is unused!
@@ -580,7 +580,7 @@ pub const fn as_mut_ptr(self) -> *mut T {
     ///
     /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
     ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
-    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   In particular, while this reference exists, the memory the pointer points to must
     ///   not get mutated (except inside `UnsafeCell`).
     ///
     /// This applies even if the result of this method is unused!
@@ -626,7 +626,7 @@ pub const fn as_mut_ptr(self) -> *mut T {
     ///
     /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
     ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
-    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   In particular, while this reference exists, the memory the pointer points to must
     ///   not get accessed (read or written) through any other pointer.
     ///
     /// This applies even if the result of this method is unused!
index 29398cbeb238dbeee8bd49f0e9285bd02e7792af..64616142b4188442863eab4ad527f4f9452cfcc3 100644 (file)
@@ -1,8 +1,8 @@
 use crate::convert::From;
 use crate::fmt;
 use crate::marker::{PhantomData, Unsize};
-use crate::mem;
 use crate::ops::{CoerceUnsized, DispatchFromDyn};
+use crate::ptr::NonNull;
 
 /// A wrapper around a raw non-null `*mut T` that indicates that the possessor
 /// of this wrapper owns the referent. Useful for building abstractions like
@@ -32,9 +32,8 @@
 )]
 #[doc(hidden)]
 #[repr(transparent)]
-#[rustc_layout_scalar_valid_range_start(1)]
 pub struct Unique<T: ?Sized> {
-    pointer: *const T,
+    pointer: NonNull<T>,
     // NOTE: this marker has no consequences for variance, but is necessary
     // for dropck to understand that we logically own a `T`.
     //
@@ -71,9 +70,7 @@ impl<T: Sized> Unique<T> {
     #[must_use]
     #[inline]
     pub const fn dangling() -> Self {
-        // SAFETY: mem::align_of() returns a valid, non-null pointer. The
-        // conditions to call new_unchecked() are thus respected.
-        unsafe { Unique::new_unchecked(crate::ptr::invalid_mut::<T>(mem::align_of::<T>())) }
+        Self::from(NonNull::dangling())
     }
 }
 
@@ -87,15 +84,14 @@ impl<T: ?Sized> Unique<T> {
     #[inline]
     pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
         // SAFETY: the caller must guarantee that `ptr` is non-null.
-        unsafe { Unique { pointer: ptr as _, _marker: PhantomData } }
+        unsafe { Unique { pointer: NonNull::new_unchecked(ptr), _marker: PhantomData } }
     }
 
     /// Creates a new `Unique` if `ptr` is non-null.
     #[inline]
     pub const fn new(ptr: *mut T) -> Option<Self> {
-        if !ptr.is_null() {
-            // SAFETY: The pointer has already been checked and is not null.
-            Some(unsafe { Unique { pointer: ptr as _, _marker: PhantomData } })
+        if let Some(pointer) = NonNull::new(ptr) {
+            Some(Unique { pointer, _marker: PhantomData })
         } else {
             None
         }
@@ -105,7 +101,7 @@ pub const fn new(ptr: *mut T) -> Option<Self> {
     #[must_use = "`self` will be dropped if the result is not used"]
     #[inline]
     pub const fn as_ptr(self) -> *mut T {
-        self.pointer as *mut T
+        self.pointer.as_ptr()
     }
 
     /// Dereferences the content.
@@ -118,7 +114,7 @@ pub const fn as_ptr(self) -> *mut T {
     pub const unsafe fn as_ref(&self) -> &T {
         // SAFETY: the caller must guarantee that `self` meets all the
         // requirements for a reference.
-        unsafe { &*self.as_ptr() }
+        unsafe { self.pointer.as_ref() }
     }
 
     /// Mutably dereferences the content.
@@ -131,17 +127,14 @@ pub const fn as_ptr(self) -> *mut T {
     pub const unsafe fn as_mut(&mut self) -> &mut T {
         // SAFETY: the caller must guarantee that `self` meets all the
         // requirements for a mutable reference.
-        unsafe { &mut *self.as_ptr() }
+        unsafe { self.pointer.as_mut() }
     }
 
     /// Casts to a pointer of another type.
     #[must_use = "`self` will be dropped if the result is not used"]
     #[inline]
     pub const fn cast<U>(self) -> Unique<U> {
-        // SAFETY: Unique::new_unchecked() creates a new unique and needs
-        // the given pointer to not be null.
-        // Since we are passing self as a pointer, it cannot be null.
-        unsafe { Unique::new_unchecked(self.as_ptr() as *mut U) }
+        Unique::from(self.pointer.cast())
     }
 }
 
@@ -184,7 +177,17 @@ impl<T: ?Sized> const From<&mut T> for Unique<T> {
     /// This conversion is infallible since references cannot be null.
     #[inline]
     fn from(reference: &mut T) -> Self {
-        // SAFETY: A mutable reference cannot be null
-        unsafe { Unique { pointer: reference as *mut T, _marker: PhantomData } }
+        Self::from(NonNull::from(reference))
+    }
+}
+
+#[unstable(feature = "ptr_internals", issue = "none")]
+impl<T: ?Sized> const From<NonNull<T>> for Unique<T> {
+    /// Converts a `NonNull<T>` to a `Unique<T>`.
+    ///
+    /// This conversion is infallible since `NonNull` cannot be null.
+    #[inline]
+    fn from(pointer: NonNull<T>) -> Self {
+        Unique { pointer, _marker: PhantomData }
     }
 }
index 9aa5c88a62c8e22714afc6a991cfb025483f8e5a..63715a6b86b97fd42913bf06d71241c8afab3a28 100644 (file)
@@ -235,7 +235,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// from `../str/mod.rs`, which does something similar for utf8 validation.
 #[inline]
 fn contains_nonascii(v: usize) -> bool {
-    const NONASCII_MASK: usize = 0x80808080_80808080u64 as usize;
+    const NONASCII_MASK: usize = usize::repeat_u8(0x80);
     (NONASCII_MASK & v) != 0
 }
 
index 22662f7d18d07da1bb1d533a1e0d73711fa43c1b..98dd1521d0e85bea969b63d583f976bd74a023ee 100644 (file)
@@ -358,6 +358,20 @@ impl<'a, T: 'a, P: FnMut(&T) -> bool> Split<'a, T, P> {
     pub(super) fn new(slice: &'a [T], pred: P) -> Self {
         Self { v: slice, pred, finished: false }
     }
+    /// Returns a slice which contains items not yet handled by split.
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(split_as_slice)]
+    /// let slice = [1,2,3,4,5];
+    /// let mut split = slice.split(|v| v % 2 == 0);
+    /// assert!(split.next().is_some());
+    /// assert_eq!(split.as_slice(), &[3,4,5]);
+    /// ```
+    #[unstable(feature = "split_as_slice", issue = "96137")]
+    pub fn as_slice(&self) -> &'a [T] {
+        if self.finished { &[] } else { &self.v }
+    }
 }
 
 #[stable(feature = "core_impl_debug", since = "1.9.0")]
index 6da99055f2d5af887c03997e0f90e7880d561a89..dffeaf6a834e75739ac296dc31ab29138d78ac28 100644 (file)
@@ -4,12 +4,8 @@
 use crate::cmp;
 use crate::mem;
 
-const LO_U64: u64 = 0x0101010101010101;
-const HI_U64: u64 = 0x8080808080808080;
-
-// Use truncation.
-const LO_USIZE: usize = LO_U64 as usize;
-const HI_USIZE: usize = HI_U64 as usize;
+const LO_USIZE: usize = usize::repeat_u8(0x01);
+const HI_USIZE: usize = usize::repeat_u8(0x80);
 const USIZE_BYTES: usize = mem::size_of::<usize>();
 
 /// Returns `true` if `x` contains any zero byte.
index 5abc2b34c075a9314c5c5afba556608a287b3a7c..28567a7e753aa88b1eee668928bb47b0c1d4c69a 100644 (file)
@@ -112,7 +112,7 @@ fn do_count_chars(s: &str) -> usize {
 // true)
 #[inline]
 fn contains_non_continuation_byte(w: usize) -> usize {
-    const LSB: usize = 0x0101_0101_0101_0101u64 as usize;
+    const LSB: usize = usize::repeat_u8(0x01);
     ((!w >> 7) | (w >> 6)) & LSB
 }
 
@@ -120,8 +120,8 @@ fn contains_non_continuation_byte(w: usize) -> usize {
 // more efficient.
 #[inline]
 fn sum_bytes_in_usize(values: usize) -> usize {
-    const LSB_SHORTS: usize = 0x0001_0001_0001_0001_u64 as usize;
-    const SKIP_BYTES: usize = 0x00ff_00ff_00ff_00ff_u64 as usize;
+    const LSB_SHORTS: usize = usize::repeat_u16(0x0001);
+    const SKIP_BYTES: usize = usize::repeat_u16(0x00ff);
 
     let pair_sum: usize = (values & SKIP_BYTES) + ((values >> 8) & SKIP_BYTES);
     pair_sum.wrapping_mul(LSB_SHORTS) >> ((USIZE_SIZE - 2) * 8)
index 0d3dc856be577c44669176a29cb182c6cdc95316..04bc665233e385dc859f466730c030cf9b64ac20 100644 (file)
@@ -112,8 +112,7 @@ pub(super) unsafe fn next_code_point_reverse<'a, I>(bytes: &mut I) -> Option<u32
     Some(ch)
 }
 
-// use truncation to fit u64 into usize
-const NONASCII_MASK: usize = 0x80808080_80808080u64 as usize;
+const NONASCII_MASK: usize = usize::repeat_u8(0x80);
 
 /// Returns `true` if any byte in the word `x` is nonascii (>= 128).
 #[inline]
index 5c0e114e93c158098ea579352ab50fc9c208fa82..877d0841830551b0b104f0f3d5967e553007278f 100644 (file)
@@ -15,28 +15,6 @@ fn hash<H: Hasher>(&self, state: &mut H) {
     }
 }
 
-macro_rules! u8to64_le {
-    ($buf:expr, $i:expr) => {
-        $buf[0 + $i] as u64
-            | ($buf[1 + $i] as u64) << 8
-            | ($buf[2 + $i] as u64) << 16
-            | ($buf[3 + $i] as u64) << 24
-            | ($buf[4 + $i] as u64) << 32
-            | ($buf[5 + $i] as u64) << 40
-            | ($buf[6 + $i] as u64) << 48
-            | ($buf[7 + $i] as u64) << 56
-    };
-    ($buf:expr, $i:expr, $len:expr) => {{
-        let mut t = 0;
-        let mut out = 0;
-        while t < $len {
-            out |= ($buf[t + $i] as u64) << t * 8;
-            t += 1;
-        }
-        out
-    }};
-}
-
 fn hash_with<H: Hasher, T: Hash>(mut st: H, x: &T) -> u64 {
     x.hash(&mut st);
     st.finish()
@@ -123,7 +101,7 @@ fn test_siphash_1_3() {
     let mut state_inc = SipHasher13::new_with_keys(k0, k1);
 
     while t < 64 {
-        let vec = u8to64_le!(vecs[t], 0);
+        let vec = u64::from_le_bytes(vecs[t]);
         let out = hash_with(SipHasher13::new_with_keys(k0, k1), &Bytes(&buf));
         assert_eq!(vec, out);
 
@@ -217,7 +195,7 @@ fn test_siphash_2_4() {
     let mut state_inc = SipHasher::new_with_keys(k0, k1);
 
     while t < 64 {
-        let vec = u8to64_le!(vecs[t], 0);
+        let vec = u64::from_le_bytes(vecs[t]);
         let out = hash_with(SipHasher::new_with_keys(k0, k1), &Bytes(&buf));
         assert_eq!(vec, out);
 
index 447a6fcf7567e5c4242676c32fe0a4d6a3f7bae8..485fa305c00e19834cc3f4b590f08fdc15615607 100644 (file)
@@ -46,6 +46,7 @@
 #![feature(sort_internals)]
 #![feature(slice_take)]
 #![feature(slice_from_ptr_range)]
+#![feature(split_as_slice)]
 #![feature(maybe_uninit_uninit_array)]
 #![feature(maybe_uninit_array_assume_init)]
 #![feature(maybe_uninit_write_slice)]
index ada479147db95806c3e638a9ecc36687d91bba9c..872786ed1bd8083427ef1b4f2f3719e5a51947ca 100644 (file)
@@ -2339,6 +2339,18 @@ fn slice_rsplit_array_mut() {
     }
 }
 
+#[test]
+fn split_as_slice() {
+    let arr = [1, 2, 3, 4, 5, 6];
+    let mut split = arr.split(|v| v % 2 == 0);
+    assert_eq!(split.as_slice(), &[1, 2, 3, 4, 5, 6]);
+    assert!(split.next().is_some());
+    assert_eq!(split.as_slice(), &[3, 4, 5, 6]);
+    assert!(split.next().is_some());
+    assert!(split.next().is_some());
+    assert_eq!(split.as_slice(), &[]);
+}
+
 #[should_panic]
 #[test]
 fn slice_split_array_ref_out_of_bounds() {
index 426c4de6ab1eae5046a72ba5cb42c307ed562d76..82508c6882daba5340e2be67bd87d84b6c2a363c 100644 (file)
     /// xor
     pub(crate) fn simd_xor<T>(x: T, y: T) -> T;
 
+    /// getelementptr (without inbounds)
+    #[cfg(not(bootstrap))]
+    pub(crate) fn simd_arith_offset<T, U>(ptrs: T, offsets: U) -> T;
+
     /// fptoui/fptosi/uitofp/sitofp
     /// casting floats to integers is truncating, so it is safe to convert values like e.g. 1.5
     /// but the truncated value must fit in the target type or the result is poison.
index 417d255c28d63b26db02107d73a650d2566aebf2..68a9c67f795af984749230c2934564cee15bfe16 100644 (file)
@@ -1,5 +1,8 @@
 //! Private implementation details of public gather/scatter APIs.
+#[cfg(not(bootstrap))]
+use crate::simd::intrinsics;
 use crate::simd::{LaneCount, Simd, SupportedLaneCount};
+#[cfg(bootstrap)]
 use core::mem;
 
 /// A vector of *const T.
@@ -21,12 +24,16 @@ pub fn splat(ptr: *const T) -> Self {
     #[inline]
     #[must_use]
     pub fn wrapping_add(self, addend: Simd<usize, LANES>) -> Self {
+        #[cfg(bootstrap)]
         // Safety: converting pointers to usize and vice-versa is safe
         // (even if using that pointer is not)
         unsafe {
             let x: Simd<usize, LANES> = mem::transmute_copy(&self);
             mem::transmute_copy(&{ x + (addend * Simd::splat(mem::size_of::<T>())) })
         }
+        #[cfg(not(bootstrap))]
+        // Safety: this intrinsic doesn't have a precondition
+        unsafe { intrinsics::simd_arith_offset(self, addend) }
     }
 }
 
@@ -49,11 +56,15 @@ pub fn splat(ptr: *mut T) -> Self {
     #[inline]
     #[must_use]
     pub fn wrapping_add(self, addend: Simd<usize, LANES>) -> Self {
+        #[cfg(bootstrap)]
         // Safety: converting pointers to usize and vice-versa is safe
         // (even if using that pointer is not)
         unsafe {
             let x: Simd<usize, LANES> = mem::transmute_copy(&self);
             mem::transmute_copy(&{ x + (addend * Simd::splat(mem::size_of::<T>())) })
         }
+        #[cfg(not(bootstrap))]
+        // Safety: this intrinsic doesn't have a precondition
+        unsafe { intrinsics::simd_arith_offset(self, addend) }
     }
 }
index db5e2e4e245ea59f84c5828116a313d543f29c4c..e54a50aa15c616bcf16b03e186ec4abf4985e51d 100644 (file)
@@ -5,3 +5,7 @@ edition = "2021"
 
 [dependencies]
 std = { path = "../std" }
+# Workaround: when documenting this crate rustdoc will try to load crate named
+# `core` when resolving doc links. Without this line a different `core` will be
+# loaded from sysroot causing duplicate lang items and other similar errors.
+core = { path = "../core" }
index da7753216d0630b91aa893f256adf54036d96f3f..f60b604f1b167a832b6d4185dc980e74ee861fc0 100644 (file)
 #![feature(exhaustive_patterns)]
 #![feature(intra_doc_pointers)]
 #![feature(lang_items)]
+#![feature(let_chains)]
 #![feature(linkage)]
 #![feature(min_specialization)]
 #![feature(must_not_suspend)]
index 4e16a55edece26a1b71d9acf7578d712d8efa0ca..fb292ed29a18a5b90d508aaf81df12247fdb6863 100644 (file)
@@ -59,12 +59,12 @@ fn read_atomically<T, F>(&mut self, inner: F) -> Option<T>
 
     /// Run a parser, but fail if the entire input wasn't consumed.
     /// Doesn't run atomically.
-    fn parse_with<T, F>(&mut self, inner: F) -> Result<T, AddrParseError>
+    fn parse_with<T, F>(&mut self, inner: F, kind: AddrKind) -> Result<T, AddrParseError>
     where
         F: FnOnce(&mut Parser<'_>) -> Option<T>,
     {
         let result = inner(self);
-        if self.state.is_empty() { result } else { None }.ok_or(AddrParseError(()))
+        if self.state.is_empty() { result } else { None }.ok_or(AddrParseError(kind))
     }
 
     /// Peek the next character from the input
@@ -278,7 +278,7 @@ fn read_socket_addr(&mut self) -> Option<SocketAddr> {
 impl FromStr for IpAddr {
     type Err = AddrParseError;
     fn from_str(s: &str) -> Result<IpAddr, AddrParseError> {
-        Parser::new(s).parse_with(|p| p.read_ip_addr())
+        Parser::new(s).parse_with(|p| p.read_ip_addr(), AddrKind::Ip)
     }
 }
 
@@ -288,9 +288,9 @@ impl FromStr for Ipv4Addr {
     fn from_str(s: &str) -> Result<Ipv4Addr, AddrParseError> {
         // don't try to parse if too long
         if s.len() > 15 {
-            Err(AddrParseError(()))
+            Err(AddrParseError(AddrKind::Ipv4))
         } else {
-            Parser::new(s).parse_with(|p| p.read_ipv4_addr())
+            Parser::new(s).parse_with(|p| p.read_ipv4_addr(), AddrKind::Ipv4)
         }
     }
 }
@@ -299,7 +299,7 @@ fn from_str(s: &str) -> Result<Ipv4Addr, AddrParseError> {
 impl FromStr for Ipv6Addr {
     type Err = AddrParseError;
     fn from_str(s: &str) -> Result<Ipv6Addr, AddrParseError> {
-        Parser::new(s).parse_with(|p| p.read_ipv6_addr())
+        Parser::new(s).parse_with(|p| p.read_ipv6_addr(), AddrKind::Ipv6)
     }
 }
 
@@ -307,7 +307,7 @@ fn from_str(s: &str) -> Result<Ipv6Addr, AddrParseError> {
 impl FromStr for SocketAddrV4 {
     type Err = AddrParseError;
     fn from_str(s: &str) -> Result<SocketAddrV4, AddrParseError> {
-        Parser::new(s).parse_with(|p| p.read_socket_addr_v4())
+        Parser::new(s).parse_with(|p| p.read_socket_addr_v4(), AddrKind::SocketV4)
     }
 }
 
@@ -315,7 +315,7 @@ fn from_str(s: &str) -> Result<SocketAddrV4, AddrParseError> {
 impl FromStr for SocketAddrV6 {
     type Err = AddrParseError;
     fn from_str(s: &str) -> Result<SocketAddrV6, AddrParseError> {
-        Parser::new(s).parse_with(|p| p.read_socket_addr_v6())
+        Parser::new(s).parse_with(|p| p.read_socket_addr_v6(), AddrKind::SocketV6)
     }
 }
 
@@ -323,10 +323,20 @@ fn from_str(s: &str) -> Result<SocketAddrV6, AddrParseError> {
 impl FromStr for SocketAddr {
     type Err = AddrParseError;
     fn from_str(s: &str) -> Result<SocketAddr, AddrParseError> {
-        Parser::new(s).parse_with(|p| p.read_socket_addr())
+        Parser::new(s).parse_with(|p| p.read_socket_addr(), AddrKind::Socket)
     }
 }
 
+#[derive(Debug, Clone, PartialEq, Eq)]
+enum AddrKind {
+    Ip,
+    Ipv4,
+    Ipv6,
+    Socket,
+    SocketV4,
+    SocketV6,
+}
+
 /// An error which can be returned when parsing an IP address or a socket address.
 ///
 /// This error is used as the error type for the [`FromStr`] implementation for
@@ -353,7 +363,7 @@ fn from_str(s: &str) -> Result<SocketAddr, AddrParseError> {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug, Clone, PartialEq, Eq)]
-pub struct AddrParseError(());
+pub struct AddrParseError(AddrKind);
 
 #[stable(feature = "addr_parse_error_error", since = "1.4.0")]
 impl fmt::Display for AddrParseError {
@@ -367,6 +377,13 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
 impl Error for AddrParseError {
     #[allow(deprecated)]
     fn description(&self) -> &str {
-        "invalid IP address syntax"
+        match self.0 {
+            AddrKind::Ip => "invalid IP address syntax",
+            AddrKind::Ipv4 => "invalid IPv4 address syntax",
+            AddrKind::Ipv6 => "invalid IPv6 address syntax",
+            AddrKind::Socket => "invalid socket address syntax",
+            AddrKind::SocketV4 => "invalid IPv4 socket address syntax",
+            AddrKind::SocketV6 => "invalid IPv6 socket address syntax",
+        }
     }
 }
index d95bc9b15c9c42b98aa9ad46de9dbb7ad921e44c..9a6778c0e869b1ea6852b3ff091b84367b7b2fb0 100644 (file)
@@ -24,8 +24,8 @@ pub trait CommandExt: Sealed {
     #[stable(feature = "rust1", since = "1.0.0")]
     fn uid(
         &mut self,
-        #[cfg(not(target_os = "vxworks"))] id: u32,
-        #[cfg(target_os = "vxworks")] id: u16,
+        #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] id: u32,
+        #[cfg(any(target_os = "vxworks", target_os = "espidf"))] id: u16,
     ) -> &mut process::Command;
 
     /// Similar to `uid`, but sets the group ID of the child process. This has
@@ -33,8 +33,8 @@ fn uid(
     #[stable(feature = "rust1", since = "1.0.0")]
     fn gid(
         &mut self,
-        #[cfg(not(target_os = "vxworks"))] id: u32,
-        #[cfg(target_os = "vxworks")] id: u16,
+        #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] id: u32,
+        #[cfg(any(target_os = "vxworks", target_os = "espidf"))] id: u16,
     ) -> &mut process::Command;
 
     /// Sets the supplementary group IDs for the calling process. Translates to
@@ -42,8 +42,8 @@ fn gid(
     #[unstable(feature = "setgroups", issue = "90747")]
     fn groups(
         &mut self,
-        #[cfg(not(target_os = "vxworks"))] groups: &[u32],
-        #[cfg(target_os = "vxworks")] groups: &[u16],
+        #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] groups: &[u32],
+        #[cfg(any(target_os = "vxworks", target_os = "espidf"))] groups: &[u16],
     ) -> &mut process::Command;
 
     /// Schedules a closure to be run just before the `exec` function is
@@ -160,8 +160,8 @@ fn arg0<S>(&mut self, arg: S) -> &mut process::Command
 impl CommandExt for process::Command {
     fn uid(
         &mut self,
-        #[cfg(not(target_os = "vxworks"))] id: u32,
-        #[cfg(target_os = "vxworks")] id: u16,
+        #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] id: u32,
+        #[cfg(any(target_os = "vxworks", target_os = "espidf"))] id: u16,
     ) -> &mut process::Command {
         self.as_inner_mut().uid(id);
         self
@@ -169,8 +169,8 @@ fn uid(
 
     fn gid(
         &mut self,
-        #[cfg(not(target_os = "vxworks"))] id: u32,
-        #[cfg(target_os = "vxworks")] id: u16,
+        #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] id: u32,
+        #[cfg(any(target_os = "vxworks", target_os = "espidf"))] id: u16,
     ) -> &mut process::Command {
         self.as_inner_mut().gid(id);
         self
@@ -178,8 +178,8 @@ fn gid(
 
     fn groups(
         &mut self,
-        #[cfg(not(target_os = "vxworks"))] groups: &[u32],
-        #[cfg(target_os = "vxworks")] groups: &[u16],
+        #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] groups: &[u32],
+        #[cfg(any(target_os = "vxworks", target_os = "espidf"))] groups: &[u16],
     ) -> &mut process::Command {
         self.as_inner_mut().groups(groups);
         self
index 8ecea8ce07f6b7aa7560788f3945c05bfc71d6f4..c03d197e0194c9c4f2a6ea9ddc89d873ce81a290 100644 (file)
@@ -168,8 +168,8 @@ pub enum Prefix<'a> {
 
     /// Device namespace prefix, e.g., `\\.\COM42`.
     ///
-    /// Device namespace prefixes consist of `\\.\` immediately followed by the
-    /// device name.
+    /// Device namespace prefixes consist of `\\.\` (possibly using `/`
+    /// instead of `\`), immediately followed by the device name.
     #[stable(feature = "rust1", since = "1.0.0")]
     DeviceNS(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
 
@@ -193,7 +193,7 @@ impl<'a> Prefix<'a> {
     fn len(&self) -> usize {
         use self::Prefix::*;
         fn os_str_len(s: &OsStr) -> usize {
-            os_str_as_u8_slice(s).len()
+            s.bytes().len()
         }
         match *self {
             Verbatim(x) => 4 + os_str_len(x),
@@ -299,19 +299,17 @@ fn iter_after<'a, 'b, I, J>(mut iter: I, mut prefix: J) -> Option<I>
     }
 }
 
-// See note at the top of this module to understand why these are used:
-//
-// These casts are safe as OsStr is internally a wrapper around [u8] on all
-// platforms.
-//
-// Note that currently this relies on the special knowledge that libstd has;
-// these types are single-element structs but are not marked repr(transparent)
-// or repr(C) which would make these casts allowable outside std.
-fn os_str_as_u8_slice(s: &OsStr) -> &[u8] {
-    unsafe { &*(s as *const OsStr as *const [u8]) }
-}
 unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr {
-    // SAFETY: see the comment of `os_str_as_u8_slice`
+    // SAFETY: See note at the top of this module to understand why this and
+    // `OsStr::bytes` are used:
+    //
+    // This casts are safe as OsStr is internally a wrapper around [u8] on all
+    // platforms.
+    //
+    // Note that currently this relies on the special knowledge that libstd has;
+    // these types are single-element structs but are not marked
+    // repr(transparent) or repr(C) which would make these casts not allowable
+    // outside std.
     unsafe { &*(s as *const [u8] as *const OsStr) }
 }
 
@@ -332,7 +330,7 @@ fn has_physical_root(s: &[u8], prefix: Option<Prefix<'_>>) -> bool {
 
 // basic workhorse for splitting stem and extension
 fn rsplit_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) {
-    if os_str_as_u8_slice(file) == b".." {
+    if file.bytes() == b".." {
         return (Some(file), None);
     }
 
@@ -340,7 +338,7 @@ fn rsplit_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) {
     // and back. This is safe to do because (1) we only look at ASCII
     // contents of the encoding and (2) new &OsStr values are produced
     // only from ASCII-bounded slices of existing &OsStr values.
-    let mut iter = os_str_as_u8_slice(file).rsplitn(2, |b| *b == b'.');
+    let mut iter = file.bytes().rsplitn(2, |b| *b == b'.');
     let after = iter.next();
     let before = iter.next();
     if before == Some(b"") {
@@ -351,7 +349,7 @@ fn rsplit_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) {
 }
 
 fn split_file_at_dot(file: &OsStr) -> (&OsStr, Option<&OsStr>) {
-    let slice = os_str_as_u8_slice(file);
+    let slice = file.bytes();
     if slice == b".." {
         return (file, None);
     }
@@ -1445,17 +1443,17 @@ pub fn set_extension<S: AsRef<OsStr>>(&mut self, extension: S) -> bool {
     fn _set_extension(&mut self, extension: &OsStr) -> bool {
         let file_stem = match self.file_stem() {
             None => return false,
-            Some(f) => os_str_as_u8_slice(f),
+            Some(f) => f.bytes(),
         };
 
         // truncate until right after the file stem
         let end_file_stem = file_stem[file_stem.len()..].as_ptr().addr();
-        let start = os_str_as_u8_slice(&self.inner).as_ptr().addr();
+        let start = self.inner.bytes().as_ptr().addr();
         let v = self.as_mut_vec();
         v.truncate(end_file_stem.wrapping_sub(start));
 
         // add the new extension, if any
-        let new = os_str_as_u8_slice(extension);
+        let new = extension.bytes();
         if !new.is_empty() {
             v.reserve_exact(new.len() + 1);
             v.push(b'.');
@@ -1948,7 +1946,7 @@ unsafe fn from_u8_slice(s: &[u8]) -> &Path {
     }
     // The following (private!) function reveals the byte encoding used for OsStr.
     fn as_u8_slice(&self) -> &[u8] {
-        os_str_as_u8_slice(&self.inner)
+        self.inner.bytes()
     }
 
     /// Directly wraps a string slice as a `Path` slice.
index d1f59d2786e91f05f9f5cfbcb2f7208b5d938eda..0d8ea29c2be759b1580f2b36f20560d5d2b6ecb7 100644 (file)
@@ -971,15 +971,15 @@ pub fn test_decompositions_windows() {
     file_prefix: None
     );
 
-    t!("\\\\?\\C:/foo",
-    iter: ["\\\\?\\C:/foo"],
+    t!("\\\\?\\C:/foo/bar",
+    iter: ["\\\\?\\C:", "\\", "foo/bar"],
     has_root: true,
     is_absolute: true,
-    parent: None,
-    file_name: None,
-    file_stem: None,
+    parent: Some("\\\\?\\C:/"),
+    file_name: Some("foo/bar"),
+    file_stem: Some("foo/bar"),
     extension: None,
-    file_prefix: None
+    file_prefix: Some("foo/bar")
     );
 
     t!("\\\\.\\foo\\bar",
index 415cbba101c67061fd197808fc1463b344f829f0..97b4c49896f63f1aaa783071d44004019a4c2c44 100644 (file)
@@ -1,6 +1,5 @@
 use crate::cell::UnsafeCell;
 use crate::collections::VecDeque;
-use crate::ffi::c_void;
 use crate::hint;
 use crate::ops::{Deref, DerefMut, Drop};
 use crate::ptr;
@@ -220,38 +219,3 @@ pub unsafe fn try_lock(&self) -> bool {
     #[inline]
     pub unsafe fn destroy(&self) {}
 }
-
-pub struct ReentrantMutex {
-    inner: *const c_void,
-}
-
-impl ReentrantMutex {
-    pub const unsafe fn uninitialized() -> ReentrantMutex {
-        ReentrantMutex { inner: ptr::null() }
-    }
-
-    #[inline]
-    pub unsafe fn init(&self) {
-        let _ = abi::recmutex_init(&self.inner as *const *const c_void as *mut _);
-    }
-
-    #[inline]
-    pub unsafe fn lock(&self) {
-        let _ = abi::recmutex_lock(self.inner);
-    }
-
-    #[inline]
-    pub unsafe fn try_lock(&self) -> bool {
-        true
-    }
-
-    #[inline]
-    pub unsafe fn unlock(&self) {
-        let _ = abi::recmutex_unlock(self.inner);
-    }
-
-    #[inline]
-    pub unsafe fn destroy(&self) {
-        let _ = abi::recmutex_destroy(self.inner);
-    }
-}
index e01f595ac54abeefcb835b8fa54891209e95251c..5ee231882bb589e8faf273d9ddab311e8b239045 100644 (file)
@@ -5,7 +5,6 @@
     error::{expect_success, expect_success_aborting, fail, ItronError},
     spin::SpinIdOnceCell,
 };
-use crate::cell::UnsafeCell;
 
 pub struct Mutex {
     /// The ID of the underlying mutex object
@@ -89,95 +88,3 @@ fn drop(&mut self) {
         unsafe { self.0.unlock() };
     }
 }
-
-// All empty stubs because this platform does not yet support threads, so lock
-// acquisition always succeeds.
-pub struct ReentrantMutex {
-    /// The ID of the underlying mutex object
-    mtx: abi::ID,
-    /// The lock count.
-    count: UnsafeCell<usize>,
-}
-
-unsafe impl Send for ReentrantMutex {}
-unsafe impl Sync for ReentrantMutex {}
-
-impl ReentrantMutex {
-    pub const unsafe fn uninitialized() -> ReentrantMutex {
-        ReentrantMutex { mtx: 0, count: UnsafeCell::new(0) }
-    }
-
-    pub unsafe fn init(&mut self) {
-        self.mtx = expect_success(
-            unsafe {
-                abi::acre_mtx(&abi::T_CMTX {
-                    // Priority inheritance mutex
-                    mtxatr: abi::TA_INHERIT,
-                    // Unused
-                    ceilpri: 0,
-                })
-            },
-            &"acre_mtx",
-        );
-    }
-
-    pub unsafe fn lock(&self) {
-        match unsafe { abi::loc_mtx(self.mtx) } {
-            abi::E_OBJ => {
-                // Recursive lock
-                unsafe {
-                    let count = &mut *self.count.get();
-                    if let Some(new_count) = count.checked_add(1) {
-                        *count = new_count;
-                    } else {
-                        // counter overflow
-                        rtabort!("lock count overflow");
-                    }
-                }
-            }
-            er => {
-                expect_success(er, &"loc_mtx");
-            }
-        }
-    }
-
-    pub unsafe fn unlock(&self) {
-        unsafe {
-            let count = &mut *self.count.get();
-            if *count > 0 {
-                *count -= 1;
-                return;
-            }
-        }
-
-        expect_success_aborting(unsafe { abi::unl_mtx(self.mtx) }, &"unl_mtx");
-    }
-
-    pub unsafe fn try_lock(&self) -> bool {
-        let er = unsafe { abi::ploc_mtx(self.mtx) };
-        if er == abi::E_OBJ {
-            // Recursive lock
-            unsafe {
-                let count = &mut *self.count.get();
-                if let Some(new_count) = count.checked_add(1) {
-                    *count = new_count;
-                } else {
-                    // counter overflow
-                    rtabort!("lock count overflow");
-                }
-            }
-            true
-        } else if er == abi::E_TMOUT {
-            // Locked by another thread
-            false
-        } else {
-            expect_success(er, &"ploc_mtx");
-            // Top-level lock by the current thread
-            true
-        }
-    }
-
-    pub unsafe fn destroy(&self) {
-        expect_success_aborting(unsafe { abi::del_mtx(self.mtx) }, &"del_mtx");
-    }
-}
index 0b2d1f4487f618dac25f4453f2e29d8caabaf014..98a390c4c2bcabe06cae174626f442ecb4324ee3 100644 (file)
@@ -1,8 +1,4 @@
-use fortanix_sgx_abi::Tcs;
-
-use super::abi::thread;
-
-use super::waitqueue::{try_lock_or_false, NotifiedTcs, SpinMutex, WaitQueue, WaitVariable};
+use super::waitqueue::{try_lock_or_false, SpinMutex, WaitQueue, WaitVariable};
 
 pub struct Mutex {
     inner: SpinMutex<WaitVariable<bool>>,
@@ -60,84 +56,3 @@ pub unsafe fn try_lock(&self) -> bool {
     #[inline]
     pub unsafe fn destroy(&self) {}
 }
-
-struct ReentrantLock {
-    owner: Option<Tcs>,
-    count: usize,
-}
-
-pub struct ReentrantMutex {
-    inner: SpinMutex<WaitVariable<ReentrantLock>>,
-}
-
-impl ReentrantMutex {
-    pub const fn uninitialized() -> ReentrantMutex {
-        ReentrantMutex {
-            inner: SpinMutex::new(WaitVariable::new(ReentrantLock { owner: None, count: 0 })),
-        }
-    }
-
-    #[inline]
-    pub unsafe fn init(&self) {}
-
-    #[inline]
-    pub unsafe fn lock(&self) {
-        let mut guard = self.inner.lock();
-        match guard.lock_var().owner {
-            Some(tcs) if tcs != thread::current() => {
-                // Another thread has the lock, wait
-                WaitQueue::wait(guard, || {});
-                // Another thread has passed the lock to us
-            }
-            _ => {
-                // We are just now obtaining the lock
-                guard.lock_var_mut().owner = Some(thread::current());
-                guard.lock_var_mut().count += 1;
-            }
-        }
-    }
-
-    #[inline]
-    pub unsafe fn unlock(&self) {
-        let mut guard = self.inner.lock();
-        if guard.lock_var().count > 1 {
-            guard.lock_var_mut().count -= 1;
-        } else {
-            match WaitQueue::notify_one(guard) {
-                Err(mut guard) => {
-                    // No other waiters, unlock
-                    guard.lock_var_mut().count = 0;
-                    guard.lock_var_mut().owner = None;
-                }
-                Ok(mut guard) => {
-                    // There was a thread waiting, just pass the lock
-                    if let NotifiedTcs::Single(tcs) = guard.notified_tcs() {
-                        guard.lock_var_mut().owner = Some(tcs)
-                    } else {
-                        unreachable!() // called notify_one
-                    }
-                }
-            }
-        }
-    }
-
-    #[inline]
-    pub unsafe fn try_lock(&self) -> bool {
-        let mut guard = try_lock_or_false!(self.inner);
-        match guard.lock_var().owner {
-            Some(tcs) if tcs != thread::current() => {
-                // Another thread has the lock
-                false
-            }
-            _ => {
-                // We are just now obtaining the lock
-                guard.lock_var_mut().owner = Some(thread::current());
-                guard.lock_var_mut().count += 1;
-                true
-            }
-        }
-    }
-
-    #[inline]
-    pub unsafe fn destroy(&self) {}
-}
index 3de7c68a6866dbde7bb55aa2f749e621a164f30b..40a645858025012070792daa8745473b903dedb5 100644 (file)
 
 use libc::{c_int, c_void};
 
+#[cfg(any(
+    target_os = "android",
+    target_os = "linux",
+    target_os = "emscripten",
+    target_os = "l4re"
+))]
+use libc::off64_t;
+#[cfg(not(any(
+    target_os = "linux",
+    target_os = "emscripten",
+    target_os = "l4re",
+    target_os = "android"
+)))]
+use libc::off_t as off64_t;
+
 #[derive(Debug)]
 pub struct FileDesc(OwnedFd);
 
@@ -109,7 +124,7 @@ pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
                 self.as_raw_fd(),
                 buf.as_mut_ptr() as *mut c_void,
                 cmp::min(buf.len(), READ_LIMIT),
-                offset as i64,
+                offset as off64_t,
             ))
             .map(|n| n as usize)
         }
@@ -176,7 +191,7 @@ pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
                 self.as_raw_fd(),
                 buf.as_ptr() as *const c_void,
                 cmp::min(buf.len(), READ_LIMIT),
-                offset as i64,
+                offset as off64_t,
             ))
             .map(|n| n as usize)
         }
index 7181451de575fcb8ff7df27ba5a66b18a08904be..27fc7accdaeca404dbafd7c1add31598a9c9ebd8 100644 (file)
@@ -966,7 +966,7 @@ pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
             SeekFrom::End(off) => (libc::SEEK_END, off),
             SeekFrom::Current(off) => (libc::SEEK_CUR, off),
         };
-        let n = cvt(unsafe { lseek64(self.as_raw_fd(), pos, whence) })?;
+        let n = cvt(unsafe { lseek64(self.as_raw_fd(), pos as off64_t, whence) })?;
         Ok(n as u64)
     }
 
@@ -1647,8 +1647,9 @@ fn is_dir(ent: &DirEntry) -> Option<bool> {
     fn remove_dir_all_recursive(parent_fd: Option<RawFd>, path: &CStr) -> io::Result<()> {
         // try opening as directory
         let fd = match openat_nofollow_dironly(parent_fd, &path) {
-            Err(err) if err.raw_os_error() == Some(libc::ENOTDIR) => {
+            Err(err) if matches!(err.raw_os_error(), Some(libc::ENOTDIR | libc::ELOOP)) => {
                 // not a directory - don't traverse further
+                // (for symlinks, older Linux kernels may return ELOOP instead of ENOTDIR)
                 return match parent_fd {
                     // unlink...
                     Some(parent_fd) => {
index 62760373a6affecba019d63754011973ffaa2db1..c12ee169e797aa78c904d3e5d125e16ceed4145d 100644 (file)
@@ -52,25 +52,6 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
     }
 }
 
-#[cfg(target_os = "emscripten")]
-pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) {
-    extern "C" {
-        fn emscripten_futex_wait(
-            addr: *const AtomicU32,
-            val: libc::c_uint,
-            max_wait_ms: libc::c_double,
-        ) -> libc::c_int;
-    }
-
-    unsafe {
-        emscripten_futex_wait(
-            futex,
-            expected,
-            timeout.map_or(crate::f64::INFINITY, |d| d.as_secs_f64() * 1000.0),
-        );
-    }
-}
-
 /// Wake up one thread that's blocked on futex_wait on this futex.
 ///
 /// Returns true if this actually woke up such a thread,
@@ -101,10 +82,32 @@ pub fn futex_wake_all(futex: &AtomicU32) {
 }
 
 #[cfg(target_os = "emscripten")]
-pub fn futex_wake(futex: &AtomicU32) -> bool {
-    extern "C" {
-        fn emscripten_futex_wake(addr: *const AtomicU32, count: libc::c_int) -> libc::c_int;
+extern "C" {
+    fn emscripten_futex_wake(addr: *const AtomicU32, count: libc::c_int) -> libc::c_int;
+    fn emscripten_futex_wait(
+        addr: *const AtomicU32,
+        val: libc::c_uint,
+        max_wait_ms: libc::c_double,
+    ) -> libc::c_int;
+}
+
+#[cfg(target_os = "emscripten")]
+pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool {
+    unsafe {
+        emscripten_futex_wait(
+            futex,
+            expected,
+            timeout.map_or(f64::INFINITY, |d| d.as_secs_f64() * 1000.0),
+        ) != -libc::ETIMEDOUT
     }
+}
 
+#[cfg(target_os = "emscripten")]
+pub fn futex_wake(futex: &AtomicU32) -> bool {
     unsafe { emscripten_futex_wake(futex, 1) > 0 }
 }
+
+#[cfg(target_os = "emscripten")]
+pub fn futex_wake_all(futex: &AtomicU32) {
+    unsafe { emscripten_futex_wake(futex, i32::MAX) };
+}
index b166e7c453cad17bbdee1ad7f4bae550d6a02e71..7a63af1ad7cf7dfa45bc95efbd20ae62545f78f0 100644 (file)
@@ -1,6 +1,5 @@
-use crate::cell::UnsafeCell;
 use crate::sync::atomic::{
-    AtomicU32, AtomicUsize,
+    AtomicU32,
     Ordering::{Acquire, Relaxed, Release},
 };
 use crate::sys::futex::{futex_wait, futex_wake, futex_wake_all};
@@ -163,98 +162,3 @@ unsafe fn wait_optional_timeout(&self, mutex: &Mutex, timeout: Option<Duration>)
         r
     }
 }
-
-/// A reentrant mutex. Used by stdout().lock() and friends.
-///
-/// The 'owner' field tracks which thread has locked the mutex.
-///
-/// We use current_thread_unique_ptr() as the thread identifier,
-/// which is just the address of a thread local variable.
-///
-/// If `owner` is set to the identifier of the current thread,
-/// we assume the mutex is already locked and instead of locking it again,
-/// we increment `lock_count`.
-///
-/// When unlocking, we decrement `lock_count`, and only unlock the mutex when
-/// it reaches zero.
-///
-/// `lock_count` is protected by the mutex and only accessed by the thread that has
-/// locked the mutex, so needs no synchronization.
-///
-/// `owner` can be checked by other threads that want to see if they already
-/// hold the lock, so needs to be atomic. If it compares equal, we're on the
-/// same thread that holds the mutex and memory access can use relaxed ordering
-/// since we're not dealing with multiple threads. If it compares unequal,
-/// synchronization is left to the mutex, making relaxed memory ordering for
-/// the `owner` field fine in all cases.
-pub struct ReentrantMutex {
-    mutex: Mutex,
-    owner: AtomicUsize,
-    lock_count: UnsafeCell<u32>,
-}
-
-unsafe impl Send for ReentrantMutex {}
-unsafe impl Sync for ReentrantMutex {}
-
-impl ReentrantMutex {
-    #[inline]
-    pub const unsafe fn uninitialized() -> Self {
-        Self { mutex: Mutex::new(), owner: AtomicUsize::new(0), lock_count: UnsafeCell::new(0) }
-    }
-
-    #[inline]
-    pub unsafe fn init(&self) {}
-
-    #[inline]
-    pub unsafe fn destroy(&self) {}
-
-    pub unsafe fn try_lock(&self) -> bool {
-        let this_thread = current_thread_unique_ptr();
-        if self.owner.load(Relaxed) == this_thread {
-            self.increment_lock_count();
-            true
-        } else if self.mutex.try_lock() {
-            self.owner.store(this_thread, Relaxed);
-            debug_assert_eq!(*self.lock_count.get(), 0);
-            *self.lock_count.get() = 1;
-            true
-        } else {
-            false
-        }
-    }
-
-    pub unsafe fn lock(&self) {
-        let this_thread = current_thread_unique_ptr();
-        if self.owner.load(Relaxed) == this_thread {
-            self.increment_lock_count();
-        } else {
-            self.mutex.lock();
-            self.owner.store(this_thread, Relaxed);
-            debug_assert_eq!(*self.lock_count.get(), 0);
-            *self.lock_count.get() = 1;
-        }
-    }
-
-    unsafe fn increment_lock_count(&self) {
-        *self.lock_count.get() = (*self.lock_count.get())
-            .checked_add(1)
-            .expect("lock count overflow in reentrant mutex");
-    }
-
-    pub unsafe fn unlock(&self) {
-        *self.lock_count.get() -= 1;
-        if *self.lock_count.get() == 0 {
-            self.owner.store(0, Relaxed);
-            self.mutex.unlock();
-        }
-    }
-}
-
-/// Get an address that is unique per running thread.
-///
-/// This can be used as a non-null usize-sized ID.
-pub fn current_thread_unique_ptr() -> usize {
-    // Use a non-drop type to make sure it's still available during thread destruction.
-    thread_local! { static X: u8 = const { 0 } }
-    X.with(|x| <*const _>::addr(x))
-}
index e0404f40c69bfbdcd0b9fddce862b4d5af2f2ade..3e39c8b9b23e7a00ab22c9c317d49d97e73d45a2 100644 (file)
@@ -2,18 +2,17 @@
     if #[cfg(any(
         target_os = "linux",
         target_os = "android",
+        all(target_os = "emscripten", target_feature = "atomics"),
     ))] {
         mod futex;
         mod futex_rwlock;
-        pub use futex::{Mutex, MovableMutex, Condvar, MovableCondvar, ReentrantMutex};
+        pub use futex::{Mutex, MovableMutex, Condvar, MovableCondvar};
         pub use futex_rwlock::{RwLock, MovableRwLock};
     } else {
         mod pthread_mutex;
-        mod pthread_remutex;
         mod pthread_rwlock;
         mod pthread_condvar;
         pub use pthread_mutex::{Mutex, MovableMutex};
-        pub use pthread_remutex::ReentrantMutex;
         pub use pthread_rwlock::{RwLock, MovableRwLock};
         pub use pthread_condvar::{Condvar, MovableCondvar};
     }
diff --git a/library/std/src/sys/unix/locks/pthread_remutex.rs b/library/std/src/sys/unix/locks/pthread_remutex.rs
deleted file mode 100644 (file)
index b006181..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-use super::pthread_mutex::PthreadMutexAttr;
-use crate::cell::UnsafeCell;
-use crate::mem::MaybeUninit;
-use crate::sys::cvt_nz;
-
-pub struct ReentrantMutex {
-    inner: UnsafeCell<libc::pthread_mutex_t>,
-}
-
-unsafe impl Send for ReentrantMutex {}
-unsafe impl Sync for ReentrantMutex {}
-
-impl ReentrantMutex {
-    pub const unsafe fn uninitialized() -> ReentrantMutex {
-        ReentrantMutex { inner: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER) }
-    }
-
-    pub unsafe fn init(&self) {
-        let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit();
-        cvt_nz(libc::pthread_mutexattr_init(attr.as_mut_ptr())).unwrap();
-        let attr = PthreadMutexAttr(&mut attr);
-        cvt_nz(libc::pthread_mutexattr_settype(attr.0.as_mut_ptr(), libc::PTHREAD_MUTEX_RECURSIVE))
-            .unwrap();
-        cvt_nz(libc::pthread_mutex_init(self.inner.get(), attr.0.as_ptr())).unwrap();
-    }
-
-    pub unsafe fn lock(&self) {
-        let result = libc::pthread_mutex_lock(self.inner.get());
-        debug_assert_eq!(result, 0);
-    }
-
-    #[inline]
-    pub unsafe fn try_lock(&self) -> bool {
-        libc::pthread_mutex_trylock(self.inner.get()) == 0
-    }
-
-    pub unsafe fn unlock(&self) {
-        let result = libc::pthread_mutex_unlock(self.inner.get());
-        debug_assert_eq!(result, 0);
-    }
-
-    pub unsafe fn destroy(&self) {
-        let result = libc::pthread_mutex_destroy(self.inner.get());
-        debug_assert_eq!(result, 0);
-    }
-}
index 1be733ba106e866828c87a9f8cc1769a1530ba14..92bea9346d8f8ea888515778589c5d42c66d8ea8 100644 (file)
@@ -427,7 +427,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
     crate::fs::read_to_string("sys:exe").map(PathBuf::from)
 }
 
-#[cfg(any(target_os = "fuchsia", target_os = "l4re"))]
+#[cfg(target_os = "l4re")]
 pub fn current_exe() -> io::Result<PathBuf> {
     use crate::io::ErrorKind;
     Err(io::const_io_error!(ErrorKind::Unsupported, "Not yet implemented!"))
@@ -451,6 +451,26 @@ pub fn current_exe() -> io::Result<PathBuf> {
     super::unsupported::unsupported()
 }
 
+#[cfg(target_os = "fuchsia")]
+pub fn current_exe() -> io::Result<PathBuf> {
+    use crate::io::ErrorKind;
+
+    #[cfg(test)]
+    use realstd::env;
+
+    #[cfg(not(test))]
+    use crate::env;
+
+    let exe_path = env::args().next().ok_or(io::const_io_error!(
+        ErrorKind::Uncategorized,
+        "an executable path was not found because no arguments were provided through argv"
+    ))?;
+    let path = PathBuf::from(exe_path);
+
+    // Prepend the current working directory to the path if it's not absolute.
+    if !path.is_absolute() { getcwd().map(|cwd| cwd.join(path)) } else { Ok(path) }
+}
+
 pub struct Env {
     iter: vec::IntoIter<(OsString, OsString)>,
 }
index 9f1a645372f42b06f09552aa26244e55d415d822..1956b3692a7ea8f2cc37dfb9c9ff6a99a781c6eb 100644 (file)
@@ -3,7 +3,7 @@
 use crate::ffi::OsStr;
 use crate::mem;
 use crate::ptr;
-use crate::sys::cvt;
+use crate::sys::{cvt, cvt_nz};
 
 macro_rules! t {
     ($e:expr) => {
@@ -39,7 +39,7 @@ fn test_process_mask() {
         let mut old_set = mem::MaybeUninit::<libc::sigset_t>::uninit();
         t!(cvt(sigemptyset(set.as_mut_ptr())));
         t!(cvt(sigaddset(set.as_mut_ptr(), libc::SIGINT)));
-        t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(), old_set.as_mut_ptr())));
+        t!(cvt_nz(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(), old_set.as_mut_ptr())));
 
         cmd.stdin(Stdio::MakePipe);
         cmd.stdout(Stdio::MakePipe);
@@ -48,7 +48,7 @@ fn test_process_mask() {
         let stdin_write = pipes.stdin.take().unwrap();
         let stdout_read = pipes.stdout.take().unwrap();
 
-        t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, old_set.as_ptr(), ptr::null_mut())));
+        t!(cvt_nz(libc::pthread_sigmask(libc::SIG_SETMASK, old_set.as_ptr(), ptr::null_mut())));
 
         t!(cvt(libc::kill(cat.id() as libc::pid_t, libc::SIGINT)));
         // We need to wait until SIGINT is definitely delivered. The
index 3d305cd7310fd4b8419d220d1adeadebb9fda914..d48faaa88fb4f56e91082d73172a97ceed6d8cc7 100644 (file)
@@ -328,6 +328,7 @@ unsafe fn do_exec(
         #[cfg(not(target_os = "emscripten"))]
         {
             use crate::mem::MaybeUninit;
+            use crate::sys::cvt_nz;
             // Reset signal handling so the child process starts in a
             // standardized state. libstd ignores SIGPIPE, and signal-handling
             // libraries often set a mask. Child processes inherit ignored
@@ -337,7 +338,7 @@ unsafe fn do_exec(
             // we're about to run.
             let mut set = MaybeUninit::<libc::sigset_t>::uninit();
             cvt(sigemptyset(set.as_mut_ptr()))?;
-            cvt(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(), ptr::null_mut()))?;
+            cvt_nz(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(), ptr::null_mut()))?;
 
             #[cfg(target_os = "android")] // see issue #88585
             {
index da63c068384a2b56a4926360db10c4213646d616..e4ff21b25bd9ce47aea69b7fd0f2eb696c873306 100644 (file)
@@ -25,7 +25,8 @@
 use crate::ffi::CStr;
 use crate::marker::PhantomData;
 use crate::mem;
-use crate::sync::atomic::{self, AtomicUsize, Ordering};
+use crate::ptr;
+use crate::sync::atomic::{self, AtomicPtr, Ordering};
 
 // We can use true weak linkage on ELF targets.
 #[cfg(not(any(target_os = "macos", target_os = "ios")))]
@@ -83,13 +84,13 @@ pub(crate) fn get(&self) -> Option<F> {
 }
 pub(crate) struct DlsymWeak<F> {
     name: &'static str,
-    addr: AtomicUsize,
+    func: AtomicPtr<libc::c_void>,
     _marker: PhantomData<F>,
 }
 
 impl<F> DlsymWeak<F> {
     pub(crate) const fn new(name: &'static str) -> Self {
-        DlsymWeak { name, addr: AtomicUsize::new(1), _marker: PhantomData }
+        DlsymWeak { name, func: AtomicPtr::new(ptr::invalid_mut(1)), _marker: PhantomData }
     }
 
     #[inline]
@@ -97,11 +98,11 @@ pub(crate) fn get(&self) -> Option<F> {
         unsafe {
             // Relaxed is fine here because we fence before reading through the
             // pointer (see the comment below).
-            match self.addr.load(Ordering::Relaxed) {
-                1 => self.initialize(),
-                0 => None,
-                addr => {
-                    let func = mem::transmute_copy::<usize, F>(&addr);
+            match self.func.load(Ordering::Relaxed) {
+                func if func.addr() == 1 => self.initialize(),
+                func if func.is_null() => None,
+                func => {
+                    let func = mem::transmute_copy::<*mut libc::c_void, F>(&func);
                     // The caller is presumably going to read through this value
                     // (by calling the function we've dlsymed). This means we'd
                     // need to have loaded it with at least C11's consume
@@ -129,25 +130,22 @@ pub(crate) fn get(&self) -> Option<F> {
     // Cold because it should only happen during first-time initialization.
     #[cold]
     unsafe fn initialize(&self) -> Option<F> {
-        assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>());
+        assert_eq!(mem::size_of::<F>(), mem::size_of::<*mut libc::c_void>());
 
         let val = fetch(self.name);
         // This synchronizes with the acquire fence in `get`.
-        self.addr.store(val, Ordering::Release);
+        self.func.store(val, Ordering::Release);
 
-        match val {
-            0 => None,
-            addr => Some(mem::transmute_copy::<usize, F>(&addr)),
-        }
+        if val.is_null() { None } else { Some(mem::transmute_copy::<*mut libc::c_void, F>(&val)) }
     }
 }
 
-unsafe fn fetch(name: &str) -> usize {
+unsafe fn fetch(name: &str) -> *mut libc::c_void {
     let name = match CStr::from_bytes_with_nul(name.as_bytes()) {
         Ok(cstr) => cstr,
-        Err(..) => return 0,
+        Err(..) => return ptr::null_mut(),
     };
-    libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize
+    libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr())
 }
 
 #[cfg(not(any(target_os = "linux", target_os = "android")))]
index 35bd59130346f2bb7672ea13397cb7c4fbed012b..d412ff152a047daa4a56475300d0eb164631f92a 100644 (file)
@@ -2,5 +2,5 @@
 mod mutex;
 mod rwlock;
 pub use condvar::{Condvar, MovableCondvar};
-pub use mutex::{MovableMutex, Mutex, ReentrantMutex};
+pub use mutex::{MovableMutex, Mutex};
 pub use rwlock::{MovableRwLock, RwLock};
index b3203c16c50022bb6f67e436899dd7a9879640ed..cad991aae5e961257ef56edccf0e06b36ba5fb8f 100644 (file)
@@ -36,26 +36,3 @@ pub unsafe fn try_lock(&self) -> bool {
     #[inline]
     pub unsafe fn destroy(&self) {}
 }
-
-// All empty stubs because this platform does not yet support threads, so lock
-// acquisition always succeeds.
-pub struct ReentrantMutex {}
-
-impl ReentrantMutex {
-    pub const unsafe fn uninitialized() -> ReentrantMutex {
-        ReentrantMutex {}
-    }
-
-    pub unsafe fn init(&self) {}
-
-    pub unsafe fn lock(&self) {}
-
-    #[inline]
-    pub unsafe fn try_lock(&self) -> bool {
-        true
-    }
-
-    pub unsafe fn unlock(&self) {}
-
-    pub unsafe fn destroy(&self) {}
-}
diff --git a/library/std/src/sys/wasm/atomics/condvar.rs b/library/std/src/sys/wasm/atomics/condvar.rs
deleted file mode 100644 (file)
index f06c07c..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-use crate::arch::wasm32;
-use crate::cmp;
-use crate::mem;
-use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
-use crate::sys::locks::Mutex;
-use crate::time::Duration;
-
-pub struct Condvar {
-    cnt: AtomicUsize,
-}
-
-pub type MovableCondvar = Condvar;
-
-// Condition variables are implemented with a simple counter internally that is
-// likely to cause spurious wakeups. Blocking on a condition variable will first
-// read the value of the internal counter, unlock the given mutex, and then
-// block if and only if the counter's value is still the same. Notifying a
-// condition variable will modify the counter (add one for now) and then wake up
-// a thread waiting on the address of the counter.
-//
-// A thread waiting on the condition variable will as a result avoid going to
-// sleep if it's notified after the lock is unlocked but before it fully goes to
-// sleep. A sleeping thread is guaranteed to be woken up at some point as it can
-// only be woken up with a call to `wake`.
-//
-// Note that it's possible for 2 or more threads to be woken up by a call to
-// `notify_one` with this implementation. That can happen where the modification
-// of `cnt` causes any threads in the middle of `wait` to avoid going to sleep,
-// and the subsequent `wake` may wake up a thread that's actually blocking. We
-// consider this a spurious wakeup, though, which all users of condition
-// variables must already be prepared to handle. As a result, this source of
-// spurious wakeups is currently though to be ok, although it may be problematic
-// later on if it causes too many spurious wakeups.
-
-impl Condvar {
-    pub const fn new() -> Condvar {
-        Condvar { cnt: AtomicUsize::new(0) }
-    }
-
-    #[inline]
-    pub unsafe fn init(&mut self) {
-        // nothing to do
-    }
-
-    pub unsafe fn notify_one(&self) {
-        self.cnt.fetch_add(1, SeqCst);
-        // SAFETY: ptr() is always valid
-        unsafe {
-            wasm32::memory_atomic_notify(self.ptr(), 1);
-        }
-    }
-
-    #[inline]
-    pub unsafe fn notify_all(&self) {
-        self.cnt.fetch_add(1, SeqCst);
-        // SAFETY: ptr() is always valid
-        unsafe {
-            wasm32::memory_atomic_notify(self.ptr(), u32::MAX); // -1 == "wake everyone"
-        }
-    }
-
-    pub unsafe fn wait(&self, mutex: &Mutex) {
-        // "atomically block and unlock" implemented by loading our current
-        // counter's value, unlocking the mutex, and blocking if the counter
-        // still has the same value.
-        //
-        // Notifications happen by incrementing the counter and then waking a
-        // thread. Incrementing the counter after we unlock the mutex will
-        // prevent us from sleeping and otherwise the call to `wake` will
-        // wake us up once we're asleep.
-        let ticket = self.cnt.load(SeqCst) as i32;
-        mutex.unlock();
-        let val = wasm32::memory_atomic_wait32(self.ptr(), ticket, -1);
-        // 0 == woken, 1 == not equal to `ticket`, 2 == timeout (shouldn't happen)
-        debug_assert!(val == 0 || val == 1);
-        mutex.lock();
-    }
-
-    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
-        let ticket = self.cnt.load(SeqCst) as i32;
-        mutex.unlock();
-        let nanos = dur.as_nanos();
-        let nanos = cmp::min(i64::MAX as u128, nanos);
-
-        // If the return value is 2 then a timeout happened, so we return
-        // `false` as we weren't actually notified.
-        let ret = wasm32::memory_atomic_wait32(self.ptr(), ticket, nanos as i64) != 2;
-        mutex.lock();
-        return ret;
-    }
-
-    #[inline]
-    pub unsafe fn destroy(&self) {
-        // nothing to do
-    }
-
-    #[inline]
-    fn ptr(&self) -> *mut i32 {
-        assert_eq!(mem::size_of::<usize>(), mem::size_of::<i32>());
-        self.cnt.as_mut_ptr() as *mut i32
-    }
-}
index bbe9bd6951af967e12d9be38040d0e07b9349292..11413ba3bf5642d484b1a3de09f3c0579b18e426 100644 (file)
@@ -3,19 +3,33 @@
 use crate::sync::atomic::AtomicU32;
 use crate::time::Duration;
 
-pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) {
+/// Wait for a futex_wake operation to wake us.
+///
+/// Returns directly if the futex doesn't hold the expected value.
+///
+/// Returns false on timeout, and true in all other cases.
+pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool {
     let timeout = timeout.and_then(|t| t.as_nanos().try_into().ok()).unwrap_or(-1);
     unsafe {
         wasm32::memory_atomic_wait32(
             futex as *const AtomicU32 as *mut i32,
             expected as i32,
             timeout,
-        );
+        ) < 2
     }
 }
 
-pub fn futex_wake(futex: &AtomicU32) {
+/// Wake up one thread that's blocked on futex_wait on this futex.
+///
+/// Returns true if this actually woke up such a thread,
+/// or false if no thread was waiting on this futex.
+pub fn futex_wake(futex: &AtomicU32) -> bool {
+    unsafe { wasm32::memory_atomic_notify(futex as *const AtomicU32 as *mut i32, 1) > 0 }
+}
+
+/// Wake up all threads that are waiting on futex_wait on this futex.
+pub fn futex_wake_all(futex: &AtomicU32) {
     unsafe {
-        wasm32::memory_atomic_notify(futex as *const AtomicU32 as *mut i32, 1);
+        wasm32::memory_atomic_notify(futex as *const AtomicU32 as *mut i32, i32::MAX as u32);
     }
 }
diff --git a/library/std/src/sys/wasm/atomics/mutex.rs b/library/std/src/sys/wasm/atomics/mutex.rs
deleted file mode 100644 (file)
index 3a09f0b..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-use crate::arch::wasm32;
-use crate::cell::UnsafeCell;
-use crate::mem;
-use crate::sync::atomic::{AtomicU32, AtomicUsize, Ordering::SeqCst};
-use crate::sys::thread;
-
-pub struct Mutex {
-    locked: AtomicUsize,
-}
-
-pub type MovableMutex = Mutex;
-
-// Mutexes have a pretty simple implementation where they contain an `i32`
-// internally that is 0 when unlocked and 1 when the mutex is locked.
-// Acquisition has a fast path where it attempts to cmpxchg the 0 to a 1, and
-// if it fails it then waits for a notification. Releasing a lock is then done
-// by swapping in 0 and then notifying any waiters, if present.
-
-impl Mutex {
-    pub const fn new() -> Mutex {
-        Mutex { locked: AtomicUsize::new(0) }
-    }
-
-    #[inline]
-    pub unsafe fn init(&mut self) {
-        // nothing to do
-    }
-
-    pub unsafe fn lock(&self) {
-        while !self.try_lock() {
-            // SAFETY: the caller must uphold the safety contract for `memory_atomic_wait32`.
-            let val = unsafe {
-                wasm32::memory_atomic_wait32(
-                    self.ptr(),
-                    1,  // we expect our mutex is locked
-                    -1, // wait infinitely
-                )
-            };
-            // we should have either woke up (0) or got a not-equal due to a
-            // race (1). We should never time out (2)
-            debug_assert!(val == 0 || val == 1);
-        }
-    }
-
-    pub unsafe fn unlock(&self) {
-        let prev = self.locked.swap(0, SeqCst);
-        debug_assert_eq!(prev, 1);
-        wasm32::memory_atomic_notify(self.ptr(), 1); // wake up one waiter, if any
-    }
-
-    #[inline]
-    pub unsafe fn try_lock(&self) -> bool {
-        self.locked.compare_exchange(0, 1, SeqCst, SeqCst).is_ok()
-    }
-
-    #[inline]
-    pub unsafe fn destroy(&self) {
-        // nothing to do
-    }
-
-    #[inline]
-    fn ptr(&self) -> *mut i32 {
-        assert_eq!(mem::size_of::<usize>(), mem::size_of::<i32>());
-        self.locked.as_mut_ptr() as *mut i32
-    }
-}
-
-pub struct ReentrantMutex {
-    owner: AtomicU32,
-    recursions: UnsafeCell<u32>,
-}
-
-unsafe impl Send for ReentrantMutex {}
-unsafe impl Sync for ReentrantMutex {}
-
-// Reentrant mutexes are similarly implemented to mutexes above except that
-// instead of "1" meaning unlocked we use the id of a thread to represent
-// whether it has locked a mutex. That way we have an atomic counter which
-// always holds the id of the thread that currently holds the lock (or 0 if the
-// lock is unlocked).
-//
-// Once a thread acquires a lock recursively, which it detects by looking at
-// the value that's already there, it will update a local `recursions` counter
-// in a nonatomic fashion (as we hold the lock). The lock is then fully
-// released when this recursion counter reaches 0.
-
-impl ReentrantMutex {
-    pub const unsafe fn uninitialized() -> ReentrantMutex {
-        ReentrantMutex { owner: AtomicU32::new(0), recursions: UnsafeCell::new(0) }
-    }
-
-    pub unsafe fn init(&self) {
-        // nothing to do...
-    }
-
-    pub unsafe fn lock(&self) {
-        let me = thread::my_id();
-        while let Err(owner) = self._try_lock(me) {
-            // SAFETY: the caller must guarantee that `self.ptr()` and `owner` are valid i32.
-            let val = unsafe { wasm32::memory_atomic_wait32(self.ptr(), owner as i32, -1) };
-            debug_assert!(val == 0 || val == 1);
-        }
-    }
-
-    #[inline]
-    pub unsafe fn try_lock(&self) -> bool {
-        unsafe { self._try_lock(thread::my_id()).is_ok() }
-    }
-
-    #[inline]
-    unsafe fn _try_lock(&self, id: u32) -> Result<(), u32> {
-        let id = id.checked_add(1).unwrap();
-        match self.owner.compare_exchange(0, id, SeqCst, SeqCst) {
-            // we transitioned from unlocked to locked
-            Ok(_) => {
-                debug_assert_eq!(*self.recursions.get(), 0);
-                Ok(())
-            }
-
-            // we currently own this lock, so let's update our count and return
-            // true.
-            Err(n) if n == id => {
-                *self.recursions.get() += 1;
-                Ok(())
-            }
-
-            // Someone else owns the lock, let our caller take care of it
-            Err(other) => Err(other),
-        }
-    }
-
-    pub unsafe fn unlock(&self) {
-        // If we didn't ever recursively lock the lock then we fully unlock the
-        // mutex and wake up a waiter, if any. Otherwise we decrement our
-        // recursive counter and let some one else take care of the zero.
-        match *self.recursions.get() {
-            0 => {
-                self.owner.swap(0, SeqCst);
-                // SAFETY: the caller must guarantee that `self.ptr()` is valid i32.
-                unsafe {
-                    wasm32::memory_atomic_notify(self.ptr() as *mut i32, 1);
-                } // wake up one waiter, if any
-            }
-            ref mut n => *n -= 1,
-        }
-    }
-
-    pub unsafe fn destroy(&self) {
-        // nothing to do...
-    }
-
-    #[inline]
-    fn ptr(&self) -> *mut i32 {
-        self.owner.as_mut_ptr() as *mut i32
-    }
-}
diff --git a/library/std/src/sys/wasm/atomics/rwlock.rs b/library/std/src/sys/wasm/atomics/rwlock.rs
deleted file mode 100644 (file)
index 690bb15..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-use crate::cell::UnsafeCell;
-use crate::sys::locks::{Condvar, Mutex};
-
-pub struct RwLock {
-    lock: Mutex,
-    cond: Condvar,
-    state: UnsafeCell<State>,
-}
-
-pub type MovableRwLock = RwLock;
-
-enum State {
-    Unlocked,
-    Reading(usize),
-    Writing,
-}
-
-unsafe impl Send for RwLock {}
-unsafe impl Sync for RwLock {}
-
-// This rwlock implementation is a relatively simple implementation which has a
-// condition variable for readers/writers as well as a mutex protecting the
-// internal state of the lock. A current downside of the implementation is that
-// unlocking the lock will notify *all* waiters rather than just readers or just
-// writers. This can cause lots of "thundering stampede" problems. While
-// hopefully correct this implementation is very likely to want to be changed in
-// the future.
-
-impl RwLock {
-    pub const fn new() -> RwLock {
-        RwLock { lock: Mutex::new(), cond: Condvar::new(), state: UnsafeCell::new(State::Unlocked) }
-    }
-
-    #[inline]
-    pub unsafe fn read(&self) {
-        self.lock.lock();
-        while !(*self.state.get()).inc_readers() {
-            self.cond.wait(&self.lock);
-        }
-        self.lock.unlock();
-    }
-
-    #[inline]
-    pub unsafe fn try_read(&self) -> bool {
-        self.lock.lock();
-        let ok = (*self.state.get()).inc_readers();
-        self.lock.unlock();
-        return ok;
-    }
-
-    #[inline]
-    pub unsafe fn write(&self) {
-        self.lock.lock();
-        while !(*self.state.get()).inc_writers() {
-            self.cond.wait(&self.lock);
-        }
-        self.lock.unlock();
-    }
-
-    #[inline]
-    pub unsafe fn try_write(&self) -> bool {
-        self.lock.lock();
-        let ok = (*self.state.get()).inc_writers();
-        self.lock.unlock();
-        return ok;
-    }
-
-    #[inline]
-    pub unsafe fn read_unlock(&self) {
-        self.lock.lock();
-        let notify = (*self.state.get()).dec_readers();
-        self.lock.unlock();
-        if notify {
-            // FIXME: should only wake up one of these some of the time
-            self.cond.notify_all();
-        }
-    }
-
-    #[inline]
-    pub unsafe fn write_unlock(&self) {
-        self.lock.lock();
-        (*self.state.get()).dec_writers();
-        self.lock.unlock();
-        // FIXME: should only wake up one of these some of the time
-        self.cond.notify_all();
-    }
-
-    #[inline]
-    pub unsafe fn destroy(&self) {
-        self.lock.destroy();
-        self.cond.destroy();
-    }
-}
-
-impl State {
-    fn inc_readers(&mut self) -> bool {
-        match *self {
-            State::Unlocked => {
-                *self = State::Reading(1);
-                true
-            }
-            State::Reading(ref mut cnt) => {
-                *cnt += 1;
-                true
-            }
-            State::Writing => false,
-        }
-    }
-
-    fn inc_writers(&mut self) -> bool {
-        match *self {
-            State::Unlocked => {
-                *self = State::Writing;
-                true
-            }
-            State::Reading(_) | State::Writing => false,
-        }
-    }
-
-    fn dec_readers(&mut self) -> bool {
-        let zero = match *self {
-            State::Reading(ref mut cnt) => {
-                *cnt -= 1;
-                *cnt == 0
-            }
-            State::Unlocked | State::Writing => invalid(),
-        };
-        if zero {
-            *self = State::Unlocked;
-        }
-        zero
-    }
-
-    fn dec_writers(&mut self) {
-        match *self {
-            State::Writing => {}
-            State::Unlocked | State::Reading(_) => invalid(),
-        }
-        *self = State::Unlocked;
-    }
-}
-
-fn invalid() -> ! {
-    panic!("inconsistent rwlock");
-}
index 16418a06226e4884a89e022feb6152f255ecae7d..714b7049227940bdcd8578cc0f3f609a4478f2d0 100644 (file)
@@ -53,37 +53,3 @@ pub unsafe fn init() -> Option<Guard> {
         None
     }
 }
-
-// We currently just use our own thread-local to store our
-// current thread's ID, and then we lazily initialize it to something allocated
-// from a global counter.
-pub fn my_id() -> u32 {
-    use crate::sync::atomic::{AtomicU32, Ordering::SeqCst};
-
-    static NEXT_ID: AtomicU32 = AtomicU32::new(0);
-
-    #[thread_local]
-    static mut MY_ID: u32 = 0;
-
-    unsafe {
-        // If our thread ID isn't set yet then we need to allocate one. Do so
-        // with with a simple "atomically add to a global counter" strategy.
-        // This strategy doesn't handled what happens when the counter
-        // overflows, however, so just abort everything once the counter
-        // overflows and eventually we could have some sort of recycling scheme
-        // (or maybe this is all totally irrelevant by that point!). In any case
-        // though we're using a CAS loop instead of a `fetch_add` to ensure that
-        // the global counter never overflows.
-        if MY_ID == 0 {
-            let mut cur = NEXT_ID.load(SeqCst);
-            MY_ID = loop {
-                let next = cur.checked_add(1).unwrap_or_else(|| crate::process::abort());
-                match NEXT_ID.compare_exchange(cur, next, SeqCst, SeqCst) {
-                    Ok(_) => break next,
-                    Err(i) => cur = i,
-                }
-            };
-        }
-        MY_ID
-    }
-}
index 9f6700caf14bf9dbc7d7c40e9b981ec94dd931dc..9992e44b0e7566b2fb9f8857550dcb2e29999477 100644 (file)
 
 cfg_if::cfg_if! {
     if #[cfg(target_feature = "atomics")] {
-        #[path = "atomics/condvar.rs"]
-        mod condvar;
-        #[path = "atomics/mutex.rs"]
-        mod mutex;
-        #[path = "atomics/rwlock.rs"]
-        mod rwlock;
+        #[path = "../unix/locks"]
         pub mod locks {
-            pub use super::condvar::*;
-            pub use super::mutex::*;
-            pub use super::rwlock::*;
+            #![allow(unsafe_op_in_unsafe_fn)]
+            mod futex;
+            mod futex_rwlock;
+            pub use futex::{Mutex, MovableMutex, Condvar, MovableCondvar};
+            pub use futex_rwlock::{RwLock, MovableRwLock};
         }
         #[path = "atomics/futex.rs"]
         pub mod futex;
index 336264d99f90030e40188d0714f234d6f40bb016..5f14edaf067c096f66039e7502d4626440373a6d 100644 (file)
@@ -536,15 +536,6 @@ pub struct CONDITION_VARIABLE {
 pub struct SRWLOCK {
     pub ptr: LPVOID,
 }
-#[repr(C)]
-pub struct CRITICAL_SECTION {
-    CriticalSectionDebug: LPVOID,
-    LockCount: LONG,
-    RecursionCount: LONG,
-    OwningThread: HANDLE,
-    LockSemaphore: HANDLE,
-    SpinCount: ULONG_PTR,
-}
 
 #[repr(C)]
 pub struct REPARSE_MOUNTPOINT_DATA_BUFFER {
@@ -875,11 +866,6 @@ pub struct FILE_STANDARD_INFO {
 #[link(name = "kernel32")]
 extern "system" {
     pub fn GetCurrentProcessId() -> DWORD;
-    pub fn InitializeCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
-    pub fn EnterCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
-    pub fn TryEnterCriticalSection(CriticalSection: *mut CRITICAL_SECTION) -> BOOL;
-    pub fn LeaveCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
-    pub fn DeleteCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
 
     pub fn GetSystemDirectoryW(lpBuffer: LPWSTR, uSize: UINT) -> UINT;
     pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL;
index 35bd59130346f2bb7672ea13397cb7c4fbed012b..d412ff152a047daa4a56475300d0eb164631f92a 100644 (file)
@@ -2,5 +2,5 @@
 mod mutex;
 mod rwlock;
 pub use condvar::{Condvar, MovableCondvar};
-pub use mutex::{MovableMutex, Mutex, ReentrantMutex};
+pub use mutex::{MovableMutex, Mutex};
 pub use rwlock::{MovableRwLock, RwLock};
index 56f91ebe5828721777df75b3bf4372545a867748..9fa280b8b765994fdb096a1317f4130f5198004c 100644 (file)
@@ -15,7 +15,6 @@
 //!    is that there are no guarantees of fairness.
 
 use crate::cell::UnsafeCell;
-use crate::mem::MaybeUninit;
 use crate::sys::c;
 
 pub struct Mutex {
@@ -60,37 +59,3 @@ pub unsafe fn destroy(&self) {
         // SRWLock does not need to be destroyed.
     }
 }
-
-pub struct ReentrantMutex {
-    inner: MaybeUninit<UnsafeCell<c::CRITICAL_SECTION>>,
-}
-
-unsafe impl Send for ReentrantMutex {}
-unsafe impl Sync for ReentrantMutex {}
-
-impl ReentrantMutex {
-    pub const fn uninitialized() -> ReentrantMutex {
-        ReentrantMutex { inner: MaybeUninit::uninit() }
-    }
-
-    pub unsafe fn init(&self) {
-        c::InitializeCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
-    }
-
-    pub unsafe fn lock(&self) {
-        c::EnterCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
-    }
-
-    #[inline]
-    pub unsafe fn try_lock(&self) -> bool {
-        c::TryEnterCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr())) != 0
-    }
-
-    pub unsafe fn unlock(&self) {
-        c::LeaveCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
-    }
-
-    pub unsafe fn destroy(&self) {
-        c::DeleteCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
-    }
-}
index 31c7208bbf1eef3951d9a87cbd85b387ef036730..4e9d408291d2a1402a4e34a069637b3dc72c13ec 100644 (file)
@@ -156,7 +156,13 @@ macro_rules! if_return {
 
 pub fn to_u16s<S: AsRef<OsStr>>(s: S) -> crate::io::Result<Vec<u16>> {
     fn inner(s: &OsStr) -> crate::io::Result<Vec<u16>> {
-        let mut maybe_result: Vec<u16> = s.encode_wide().collect();
+        // Most paths are ASCII, so reserve capacity for as much as there are bytes
+        // in the OsStr plus one for the null-terminating character. We are not
+        // wasting bytes here as paths created by this function are primarily used
+        // in an ephemeral fashion.
+        let mut maybe_result = Vec::with_capacity(s.len() + 1);
+        maybe_result.extend(s.encode_wide());
+
         if unrolled_find_u16s(0, &maybe_result).is_some() {
             return Err(crate::io::const_io_error!(
                 ErrorKind::InvalidInput,
@@ -190,6 +196,10 @@ fn fill_utf16_buf<F1, F2, T>(mut f1: F1, f2: F2) -> crate::io::Result<T>
 {
     // Start off with a stack buf but then spill over to the heap if we end up
     // needing more space.
+    //
+    // This initial size also works around `GetFullPathNameW` returning
+    // incorrect size hints for some short paths:
+    // https://github.com/dylni/normpath/issues/5
     let mut stack_buf = [0u16; 512];
     let mut heap_buf = Vec::new();
     unsafe {
index e54fcaed4957d8ab38d440234ed36bd123991209..a0f822070992f5032e6f54a5c16b77d19c0eaa85 100644 (file)
@@ -50,37 +50,101 @@ pub(crate) fn append_suffix(path: PathBuf, suffix: &OsStr) -> PathBuf {
     path.into()
 }
 
+struct PrefixParser<'a, const LEN: usize> {
+    path: &'a OsStr,
+    prefix: [u8; LEN],
+}
+
+impl<'a, const LEN: usize> PrefixParser<'a, LEN> {
+    #[inline]
+    fn get_prefix(path: &OsStr) -> [u8; LEN] {
+        let mut prefix = [0; LEN];
+        // SAFETY: Only ASCII characters are modified.
+        for (i, &ch) in path.bytes().iter().take(LEN).enumerate() {
+            prefix[i] = if ch == b'/' { b'\\' } else { ch };
+        }
+        prefix
+    }
+
+    fn new(path: &'a OsStr) -> Self {
+        Self { path, prefix: Self::get_prefix(path) }
+    }
+
+    fn as_slice(&self) -> PrefixParserSlice<'a, '_> {
+        PrefixParserSlice {
+            path: self.path,
+            prefix: &self.prefix[..LEN.min(self.path.len())],
+            index: 0,
+        }
+    }
+}
+
+struct PrefixParserSlice<'a, 'b> {
+    path: &'a OsStr,
+    prefix: &'b [u8],
+    index: usize,
+}
+
+impl<'a> PrefixParserSlice<'a, '_> {
+    fn strip_prefix(&self, prefix: &str) -> Option<Self> {
+        self.prefix[self.index..]
+            .starts_with(prefix.as_bytes())
+            .then(|| Self { index: self.index + prefix.len(), ..*self })
+    }
+
+    fn prefix_bytes(&self) -> &'a [u8] {
+        &self.path.bytes()[..self.index]
+    }
+
+    fn finish(self) -> &'a OsStr {
+        // SAFETY: The unsafety here stems from converting between &OsStr and
+        // &[u8] and back. This is safe to do because (1) we only look at ASCII
+        // contents of the encoding and (2) new &OsStr values are produced only
+        // from ASCII-bounded slices of existing &OsStr values.
+        unsafe { bytes_as_os_str(&self.path.bytes()[self.index..]) }
+    }
+}
+
 pub fn parse_prefix(path: &OsStr) -> Option<Prefix<'_>> {
     use Prefix::{DeviceNS, Disk, Verbatim, VerbatimDisk, VerbatimUNC, UNC};
 
-    if let Some(path) = strip_prefix(path, r"\\") {
+    let parser = PrefixParser::<8>::new(path);
+    let parser = parser.as_slice();
+    if let Some(parser) = parser.strip_prefix(r"\\") {
         // \\
-        if let Some(path) = strip_prefix(path, r"?\") {
+
+        // The meaning of verbatim paths can change when they use a different
+        // separator.
+        if let Some(parser) = parser.strip_prefix(r"?\") && !parser.prefix_bytes().iter().any(|&x| x == b'/') {
             // \\?\
-            if let Some(path) = strip_prefix(path, r"UNC\") {
+            if let Some(parser) = parser.strip_prefix(r"UNC\") {
                 // \\?\UNC\server\share
 
+                let path = parser.finish();
                 let (server, path) = parse_next_component(path, true);
                 let (share, _) = parse_next_component(path, true);
 
                 Some(VerbatimUNC(server, share))
             } else {
-                let (prefix, _) = parse_next_component(path, true);
+                let path = parser.finish();
 
                 // in verbatim paths only recognize an exact drive prefix
-                if let Some(drive) = parse_drive_exact(prefix) {
+                if let Some(drive) = parse_drive_exact(path) {
                     // \\?\C:
                     Some(VerbatimDisk(drive))
                 } else {
                     // \\?\prefix
+                    let (prefix, _) = parse_next_component(path, true);
                     Some(Verbatim(prefix))
                 }
             }
-        } else if let Some(path) = strip_prefix(path, r".\") {
+        } else if let Some(parser) = parser.strip_prefix(r".\") {
             // \\.\COM42
+            let path = parser.finish();
             let (prefix, _) = parse_next_component(path, false);
             Some(DeviceNS(prefix))
         } else {
+            let path = parser.finish();
             let (server, path) = parse_next_component(path, false);
             let (share, _) = parse_next_component(path, false);
 
@@ -102,31 +166,26 @@ pub fn parse_prefix(path: &OsStr) -> Option<Prefix<'_>> {
 }
 
 // Parses a drive prefix, e.g. "C:" and "C:\whatever"
-fn parse_drive(prefix: &OsStr) -> Option<u8> {
+fn parse_drive(path: &OsStr) -> Option<u8> {
     // In most DOS systems, it is not possible to have more than 26 drive letters.
     // See <https://en.wikipedia.org/wiki/Drive_letter_assignment#Common_assignments>.
     fn is_valid_drive_letter(drive: &u8) -> bool {
         drive.is_ascii_alphabetic()
     }
 
-    match prefix.bytes() {
+    match path.bytes() {
         [drive, b':', ..] if is_valid_drive_letter(drive) => Some(drive.to_ascii_uppercase()),
         _ => None,
     }
 }
 
 // Parses a drive prefix exactly, e.g. "C:"
-fn parse_drive_exact(prefix: &OsStr) -> Option<u8> {
+fn parse_drive_exact(path: &OsStr) -> Option<u8> {
     // only parse two bytes: the drive letter and the drive separator
-    if prefix.len() == 2 { parse_drive(prefix) } else { None }
-}
-
-fn strip_prefix<'a>(path: &'a OsStr, prefix: &str) -> Option<&'a OsStr> {
-    // `path` and `prefix` are valid wtf8 and utf8 encoded slices respectively, `path[prefix.len()]`
-    // is thus a code point boundary and `path[prefix.len()..]` is a valid wtf8 encoded slice.
-    match path.bytes().strip_prefix(prefix.as_bytes()) {
-        Some(path) => unsafe { Some(bytes_as_os_str(path)) },
-        None => None,
+    if path.bytes().get(2).map(|&x| is_sep_byte(x)).unwrap_or(true) {
+        parse_drive(path)
+    } else {
+        None
     }
 }
 
@@ -219,15 +278,7 @@ pub(crate) fn maybe_verbatim(path: &Path) -> io::Result<Vec<u16>> {
         // SAFETY: `fill_utf16_buf` ensures the `buffer` and `size` are valid.
         // `lpfilename` is a pointer to a null terminated string that is not
         // invalidated until after `GetFullPathNameW` returns successfully.
-        |buffer, size| unsafe {
-            // While the docs for `GetFullPathNameW` have the standard note
-            // about needing a `\\?\` path for a long lpfilename, this does not
-            // appear to be true in practice.
-            // See:
-            // https://stackoverflow.com/questions/38036943/getfullpathnamew-and-long-windows-file-paths
-            // https://googleprojectzero.blogspot.com/2016/02/the-definitive-guide-on-win32-to-nt.html
-            c::GetFullPathNameW(lpfilename, size, buffer, ptr::null_mut())
-        },
+        |buffer, size| unsafe { c::GetFullPathNameW(lpfilename, size, buffer, ptr::null_mut()) },
         |mut absolute| {
             path.clear();
 
@@ -263,9 +314,20 @@ pub(crate) fn maybe_verbatim(path: &Path) -> io::Result<Vec<u16>> {
 
 /// Make a Windows path absolute.
 pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> {
-    if path.as_os_str().bytes().starts_with(br"\\?\") {
-        return Ok(path.into());
+    let path = path.as_os_str();
+    let prefix = parse_prefix(path);
+    // Verbatim paths should not be modified.
+    if prefix.map(|x| x.is_verbatim()).unwrap_or(false) {
+        // NULs in verbatim paths are rejected for consistency.
+        if path.bytes().contains(&0) {
+            return Err(io::const_io_error!(
+                io::ErrorKind::InvalidInput,
+                "strings passed to WinAPI cannot contain NULs",
+            ));
+        }
+        return Ok(path.to_owned().into());
     }
+
     let path = to_u16s(path)?;
     let lpfilename = path.as_ptr();
     fill_utf16_buf(
index 425c2011b32390bdf4c3900cc873880e597e019c..8656b04e4f410320befd75d198bd9c9a1690d254 100644 (file)
@@ -94,3 +94,23 @@ fn check(path: &str, expected: &str) {
     // A path that contains null is not a valid path.
     assert!(maybe_verbatim(Path::new("\0")).is_err());
 }
+
+fn parse_prefix(path: &str) -> Option<Prefix<'_>> {
+    super::parse_prefix(OsStr::new(path))
+}
+
+#[test]
+fn test_parse_prefix_verbatim() {
+    let prefix = Some(Prefix::VerbatimDisk(b'C'));
+    assert_eq!(prefix, parse_prefix(r"\\?\C:/windows/system32/notepad.exe"));
+    assert_eq!(prefix, parse_prefix(r"\\?\C:\windows\system32\notepad.exe"));
+}
+
+#[test]
+fn test_parse_prefix_verbatim_device() {
+    let prefix = Some(Prefix::UNC(OsStr::new("?"), OsStr::new("C:")));
+    assert_eq!(prefix, parse_prefix(r"//?/C:/windows/system32/notepad.exe"));
+    assert_eq!(prefix, parse_prefix(r"//?/C:\windows\system32\notepad.exe"));
+    assert_eq!(prefix, parse_prefix(r"/\?\C:\windows\system32\notepad.exe"));
+    assert_eq!(prefix, parse_prefix(r"\\?/C:\windows\system32\notepad.exe"));
+}
index 801c9c28dd388a871fada0b020427bfdde9fd1bd..8f252308de760e8515212aaf4209ecfa9089b032 100644 (file)
@@ -1,10 +1,12 @@
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests;
 
+use crate::cell::UnsafeCell;
 use crate::marker::PhantomPinned;
 use crate::ops::Deref;
 use crate::panic::{RefUnwindSafe, UnwindSafe};
 use crate::pin::Pin;
+use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed};
 use crate::sys::locks as sys;
 
 /// A re-entrant mutual exclusion
 /// This mutex will block *other* threads waiting for the lock to become
 /// available. The thread which has already locked the mutex can lock it
 /// multiple times without blocking, preventing a common source of deadlocks.
+///
+/// This is used by stdout().lock() and friends.
+///
+/// ## Implementation details
+///
+/// The 'owner' field tracks which thread has locked the mutex.
+///
+/// We use current_thread_unique_ptr() as the thread identifier,
+/// which is just the address of a thread local variable.
+///
+/// If `owner` is set to the identifier of the current thread,
+/// we assume the mutex is already locked and instead of locking it again,
+/// we increment `lock_count`.
+///
+/// When unlocking, we decrement `lock_count`, and only unlock the mutex when
+/// it reaches zero.
+///
+/// `lock_count` is protected by the mutex and only accessed by the thread that has
+/// locked the mutex, so needs no synchronization.
+///
+/// `owner` can be checked by other threads that want to see if they already
+/// hold the lock, so needs to be atomic. If it compares equal, we're on the
+/// same thread that holds the mutex and memory access can use relaxed ordering
+/// since we're not dealing with multiple threads. If it compares unequal,
+/// synchronization is left to the mutex, making relaxed memory ordering for
+/// the `owner` field fine in all cases.
 pub struct ReentrantMutex<T> {
-    inner: sys::ReentrantMutex,
+    mutex: sys::Mutex,
+    owner: AtomicUsize,
+    lock_count: UnsafeCell<u32>,
     data: T,
     _pinned: PhantomPinned,
 }
@@ -53,7 +83,9 @@ impl<T> ReentrantMutex<T> {
     /// lock/unlock methods safe.
     pub const unsafe fn new(t: T) -> ReentrantMutex<T> {
         ReentrantMutex {
-            inner: sys::ReentrantMutex::uninitialized(),
+            mutex: sys::Mutex::new(),
+            owner: AtomicUsize::new(0),
+            lock_count: UnsafeCell::new(0),
             data: t,
             _pinned: PhantomPinned,
         }
@@ -66,7 +98,7 @@ impl<T> ReentrantMutex<T> {
     /// Unsafe to call more than once, and must be called after this will no
     /// longer move in memory.
     pub unsafe fn init(self: Pin<&mut Self>) {
-        self.get_unchecked_mut().inner.init()
+        self.get_unchecked_mut().mutex.init()
     }
 
     /// Acquires a mutex, blocking the current thread until it is able to do so.
@@ -82,7 +114,19 @@ pub unsafe fn init(self: Pin<&mut Self>) {
     /// this call will return failure if the mutex would otherwise be
     /// acquired.
     pub fn lock(self: Pin<&Self>) -> ReentrantMutexGuard<'_, T> {
-        unsafe { self.inner.lock() }
+        let this_thread = current_thread_unique_ptr();
+        // Safety: We only touch lock_count when we own the lock,
+        // and since self is pinned we can safely call the lock() on the mutex.
+        unsafe {
+            if self.owner.load(Relaxed) == this_thread {
+                self.increment_lock_count();
+            } else {
+                self.mutex.lock();
+                self.owner.store(this_thread, Relaxed);
+                debug_assert_eq!(*self.lock_count.get(), 0);
+                *self.lock_count.get() = 1;
+            }
+        }
         ReentrantMutexGuard { lock: self }
     }
 
@@ -99,20 +143,35 @@ pub fn lock(self: Pin<&Self>) -> ReentrantMutexGuard<'_, T> {
     /// this call will return failure if the mutex would otherwise be
     /// acquired.
     pub fn try_lock(self: Pin<&Self>) -> Option<ReentrantMutexGuard<'_, T>> {
-        if unsafe { self.inner.try_lock() } {
-            Some(ReentrantMutexGuard { lock: self })
-        } else {
-            None
+        let this_thread = current_thread_unique_ptr();
+        // Safety: We only touch lock_count when we own the lock,
+        // and since self is pinned we can safely call the try_lock on the mutex.
+        unsafe {
+            if self.owner.load(Relaxed) == this_thread {
+                self.increment_lock_count();
+                Some(ReentrantMutexGuard { lock: self })
+            } else if self.mutex.try_lock() {
+                self.owner.store(this_thread, Relaxed);
+                debug_assert_eq!(*self.lock_count.get(), 0);
+                *self.lock_count.get() = 1;
+                Some(ReentrantMutexGuard { lock: self })
+            } else {
+                None
+            }
         }
     }
+
+    unsafe fn increment_lock_count(&self) {
+        *self.lock_count.get() = (*self.lock_count.get())
+            .checked_add(1)
+            .expect("lock count overflow in reentrant mutex");
+    }
 }
 
 impl<T> Drop for ReentrantMutex<T> {
     fn drop(&mut self) {
-        // This is actually safe b/c we know that there is no further usage of
-        // this mutex (it's up to the user to arrange for a mutex to get
-        // dropped, that's not our job)
-        unsafe { self.inner.destroy() }
+        // Safety: We're the unique owner of this mutex and not going to use it afterwards.
+        unsafe { self.mutex.destroy() }
     }
 }
 
@@ -127,8 +186,22 @@ fn deref(&self) -> &T {
 impl<T> Drop for ReentrantMutexGuard<'_, T> {
     #[inline]
     fn drop(&mut self) {
+        // Safety: We own the lock, and the lock is pinned.
         unsafe {
-            self.lock.inner.unlock();
+            *self.lock.lock_count.get() -= 1;
+            if *self.lock.lock_count.get() == 0 {
+                self.lock.owner.store(0, Relaxed);
+                self.lock.mutex.unlock();
+            }
         }
     }
 }
+
+/// Get an address that is unique per running thread.
+///
+/// This can be used as a non-null usize-sized ID.
+pub fn current_thread_unique_ptr() -> usize {
+    // Use a non-drop type to make sure it's still available during thread destruction.
+    thread_local! { static X: u8 = const { 0 } }
+    X.with(|x| <*const _>::addr(x))
+}
index 047d07ad57df148035ae8a1003082529985c91c3..4ab8fb2e9052c6d20b0233e43d3f34495a30be8c 100644 (file)
@@ -178,7 +178,7 @@ macro_rules! thread_local {
 macro_rules! __thread_local_inner {
     // used to generate the `LocalKey` value for const-initialized thread locals
     (@key $t:ty, const $init:expr) => {{
-        #[cfg_attr(not(windows), inline(always))] // see comments below
+        #[cfg_attr(not(windows), inline)] // see comments below
         #[deny(unsafe_op_in_unsafe_fn)]
         unsafe fn __getit(
             _init: $crate::option::Option<&mut $crate::option::Option<$t>>,
@@ -312,7 +312,7 @@ fn __init() -> $t { $init }
             // gets the pessimistic path for now where it's never inlined.
             //
             // The issue of "should enable on Windows sometimes" is #84933
-            #[cfg_attr(not(windows), inline(always))]
+            #[cfg_attr(not(windows), inline)]
             unsafe fn __getit(
                 init: $crate::option::Option<&mut $crate::option::Option<$t>>,
             ) -> $crate::option::Option<&'static $t> {
index 4bba2eb4507440ed07d6cb9242dfcdba33964446..0349277a36b906ff68473089470cd369b4457a03 100644 (file)
@@ -31,7 +31,9 @@ fn main() {
 
     let mut cmd = Command::new(rustdoc);
 
-    if target.is_some() {
+    // I am not actually sure why it's necessary to pass the sysroot for `--test`,
+    // but `test --doc --stage 0` is broken without it :(
+    if target.is_some() || args.iter().any(|x| x == "--test") {
         // The stage0 compiler has a special sysroot distinct from what we
         // actually downloaded, so we just always pass the `--sysroot` option,
         // unless one is already set.
index d437397045c64d0920b6d6330891fad2ac858b2c..ac1c47524fd0e2f65c295411645e47dfafcfe69a 100644 (file)
@@ -817,7 +817,7 @@ class RustBuild(object):
         return os.path.join(self.bin_root(True), '.rustfmt-stamp')
 
     def llvm_stamp(self):
-        """Return the path for .rustfmt-stamp
+        """Return the path for .llvm-stamp
 
         >>> rb = RustBuild()
         >>> rb.build_dir = "build"
index 0276d15a5b472bb857bdb8add33e031e54e3f047..0c4f3265dbf9e7869d0fb7599cceb70981a7b336 100644 (file)
@@ -3,7 +3,7 @@
 use std::collections::BTreeSet;
 use std::env;
 use std::ffi::OsStr;
-use std::fmt::Debug;
+use std::fmt::{Debug, Write};
 use std::fs;
 use std::hash::Hash;
 use std::ops::Deref;
@@ -14,7 +14,7 @@
 use crate::cache::{Cache, Interned, INTERNER};
 use crate::check;
 use crate::compile;
-use crate::config::TargetSelection;
+use crate::config::{SplitDebuginfo, TargetSelection};
 use crate::dist;
 use crate::doc;
 use crate::flags::{Color, Subcommand};
@@ -125,7 +125,8 @@ pub fn parse(path: impl Into<PathBuf>) -> TaskPath {
                     if found_kind.is_empty() {
                         panic!("empty kind in task path {}", path.display());
                     }
-                    kind = Some(Kind::parse(found_kind));
+                    kind = Kind::parse(found_kind);
+                    assert!(kind.is_some());
                     path = Path::new(found_prefix).join(components.as_path());
                 }
             }
@@ -364,6 +365,19 @@ pub fn krate(mut self, name: &str) -> Self {
         self
     }
 
+    // single alias, which does not correspond to any on-disk path
+    pub fn alias(mut self, alias: &str) -> Self {
+        assert!(
+            !self.builder.src.join(alias).exists(),
+            "use `builder.path()` for real paths: {}",
+            alias
+        );
+        self.paths.insert(PathSet::Set(
+            std::iter::once(TaskPath { path: alias.into(), kind: Some(self.kind) }).collect(),
+        ));
+        self
+    }
+
     // single, non-aliased path
     pub fn path(self, path: &str) -> Self {
         self.paths(&[path])
@@ -372,7 +386,19 @@ pub fn path(self, path: &str) -> Self {
     // multiple aliases for the same job
     pub fn paths(mut self, paths: &[&str]) -> Self {
         self.paths.insert(PathSet::Set(
-            paths.iter().map(|p| TaskPath { path: p.into(), kind: Some(self.kind) }).collect(),
+            paths
+                .iter()
+                .map(|p| {
+                    // FIXME(#96188): make sure this is actually a path.
+                    // This currently breaks for paths within submodules.
+                    //assert!(
+                    //    self.builder.src.join(p).exists(),
+                    //    "`should_run.paths` should correspond to real on-disk paths - use `alias` if there is no relevant path: {}",
+                    //    p
+                    //);
+                    TaskPath { path: p.into(), kind: Some(self.kind) }
+                })
+                .collect(),
         ));
         self
     }
@@ -406,43 +432,53 @@ pub enum Kind {
     Check,
     Clippy,
     Fix,
+    Format,
     Test,
     Bench,
-    Dist,
     Doc,
+    Clean,
+    Dist,
     Install,
     Run,
+    Setup,
 }
 
 impl Kind {
-    fn parse(string: &str) -> Kind {
-        match string {
-            "build" => Kind::Build,
-            "check" => Kind::Check,
+    pub fn parse(string: &str) -> Option<Kind> {
+        // these strings, including the one-letter aliases, must match the x.py help text
+        Some(match string {
+            "build" | "b" => Kind::Build,
+            "check" | "c" => Kind::Check,
             "clippy" => Kind::Clippy,
             "fix" => Kind::Fix,
-            "test" => Kind::Test,
+            "fmt" => Kind::Format,
+            "test" | "t" => Kind::Test,
             "bench" => Kind::Bench,
+            "doc" | "d" => Kind::Doc,
+            "clean" => Kind::Clean,
             "dist" => Kind::Dist,
-            "doc" => Kind::Doc,
             "install" => Kind::Install,
-            "run" => Kind::Run,
-            other => panic!("unknown kind: {}", other),
-        }
+            "run" | "r" => Kind::Run,
+            "setup" => Kind::Setup,
+            _ => return None,
+        })
     }
 
-    fn as_str(&self) -> &'static str {
+    pub fn as_str(&self) -> &'static str {
         match self {
             Kind::Build => "build",
             Kind::Check => "check",
             Kind::Clippy => "clippy",
             Kind::Fix => "fix",
+            Kind::Format => "fmt",
             Kind::Test => "test",
             Kind::Bench => "bench",
-            Kind::Dist => "dist",
             Kind::Doc => "doc",
+            Kind::Clean => "clean",
+            Kind::Dist => "dist",
             Kind::Install => "install",
             Kind::Run => "run",
+            Kind::Setup => "setup",
         }
     }
 }
@@ -486,7 +522,7 @@ macro_rules! describe {
                 native::Lld,
                 native::CrtBeginEnd
             ),
-            Kind::Check | Kind::Clippy { .. } | Kind::Fix => describe!(
+            Kind::Check => describe!(
                 check::Std,
                 check::Rustc,
                 check::Rustdoc,
@@ -616,32 +652,29 @@ macro_rules! describe {
                 install::Rustc
             ),
             Kind::Run => describe!(run::ExpandYamlAnchors, run::BuildManifest, run::BumpStage0),
+            // These commands either don't use paths, or they're special-cased in Build::build()
+            Kind::Clean | Kind::Clippy | Kind::Fix | Kind::Format | Kind::Setup => vec![],
         }
     }
 
-    pub fn get_help(build: &Build, subcommand: &str) -> Option<String> {
-        let kind = match subcommand {
-            "build" | "b" => Kind::Build,
-            "doc" | "d" => Kind::Doc,
-            "test" | "t" => Kind::Test,
-            "bench" => Kind::Bench,
-            "dist" => Kind::Dist,
-            "install" => Kind::Install,
-            _ => return None,
-        };
+    pub fn get_help(build: &Build, kind: Kind) -> Option<String> {
+        let step_descriptions = Builder::get_step_descriptions(kind);
+        if step_descriptions.is_empty() {
+            return None;
+        }
 
         let builder = Self::new_internal(build, kind, vec![]);
         let builder = &builder;
         // The "build" kind here is just a placeholder, it will be replaced with something else in
         // the following statement.
         let mut should_run = ShouldRun::new(builder, Kind::Build);
-        for desc in Builder::get_step_descriptions(builder.kind) {
+        for desc in step_descriptions {
             should_run.kind = desc.kind;
             should_run = (desc.should_run)(should_run);
         }
         let mut help = String::from("Available paths:\n");
         let mut add_path = |path: &Path| {
-            help.push_str(&format!("    ./x.py {} {}\n", subcommand, path.display()));
+            t!(write!(help, "    ./x.py {} {}\n", kind.as_str(), path.display()));
         };
         for pathset in should_run.paths {
             match pathset {
@@ -1365,17 +1398,17 @@ pub fn cargo(
             },
         );
 
-        // `dsymutil` adds time to builds on Apple platforms for no clear benefit, and also makes
-        // it more difficult for debuggers to find debug info. The compiler currently defaults to
-        // running `dsymutil` to preserve its historical default, but when compiling the compiler
-        // itself, we skip it by default since we know it's safe to do so in that case.
-        // See https://github.com/rust-lang/rust/issues/79361 for more info on this flag.
-        if target.contains("apple") {
-            if self.config.rust_run_dsymutil {
-                rustflags.arg("-Csplit-debuginfo=packed");
-            } else {
-                rustflags.arg("-Csplit-debuginfo=unpacked");
+        // FIXME(davidtwco): #[cfg(not(bootstrap))] - #95612 needs to be in the bootstrap compiler
+        // for this conditional to be removed.
+        if !target.contains("windows") || compiler.stage >= 1 {
+            if target.contains("linux") || target.contains("windows") {
+                rustflags.arg("-Zunstable-options");
             }
+            match self.config.rust_split_debuginfo {
+                SplitDebuginfo::Packed => rustflags.arg("-Csplit-debuginfo=packed"),
+                SplitDebuginfo::Unpacked => rustflags.arg("-Csplit-debuginfo=unpacked"),
+                SplitDebuginfo::Off => rustflags.arg("-Csplit-debuginfo=off"),
+            };
         }
 
         if self.config.cmd.bless() {
index a59f72ed968b4bac5f5f486efb0b378cc40c934f..3b6cd7564f08ae57e77365128feefc9908217ba3 100644 (file)
@@ -7,6 +7,7 @@ fn configure(cmd: &str, host: &[&str], target: &[&str]) -> Config {
     // don't save toolstates
     config.save_toolstates = None;
     config.dry_run = true;
+    config.submodules = Some(false);
     config.ninja_in_file = false;
     // try to avoid spurious failures in dist where we create/delete each others file
     // HACK: rather than pull in `tempdir`, use the one that cargo has conveniently created for us
@@ -25,36 +26,74 @@ fn first<A, B>(v: Vec<(A, B)>) -> Vec<A> {
     v.into_iter().map(|(a, _)| a).collect::<Vec<_>>()
 }
 
+fn run_build(paths: &[PathBuf], config: Config) -> Cache {
+    let kind = config.cmd.kind();
+    let build = Build::new(config);
+    let builder = Builder::new(&build);
+    builder.run_step_descriptions(&Builder::get_step_descriptions(kind), paths);
+    builder.cache
+}
+
+#[test]
+fn test_exclude() {
+    let mut config = configure("test", &["A"], &["A"]);
+    config.exclude = vec![TaskPath::parse("src/tools/tidy")];
+    let cache = run_build(&[], config);
+
+    // Ensure we have really excluded tidy
+    assert!(!cache.contains::<test::Tidy>());
+
+    // Ensure other tests are not affected.
+    assert!(cache.contains::<test::RustdocUi>());
+}
+
+#[test]
+fn test_exclude_kind() {
+    let path = PathBuf::from("src/tools/cargotest");
+    let exclude = TaskPath::parse("test::src/tools/cargotest");
+    assert_eq!(exclude, TaskPath { kind: Some(Kind::Test), path: path.clone() });
+
+    let mut config = configure("test", &["A"], &["A"]);
+    // Ensure our test is valid, and `test::Cargotest` would be run without the exclude.
+    assert!(run_build(&[path.clone()], config.clone()).contains::<test::Cargotest>());
+    // Ensure tests for cargotest are skipped.
+    config.exclude = vec![exclude.clone()];
+    assert!(!run_build(&[path.clone()], config).contains::<test::Cargotest>());
+
+    // Ensure builds for cargotest are not skipped.
+    let mut config = configure("build", &["A"], &["A"]);
+    config.exclude = vec![exclude];
+    assert!(run_build(&[path], config).contains::<tool::CargoTest>());
+}
+
 mod defaults {
-    use super::{configure, first};
+    use super::{configure, first, run_build};
     use crate::builder::*;
     use crate::Config;
     use pretty_assertions::assert_eq;
 
     #[test]
     fn build_default() {
-        let build = Build::new(configure("build", &["A"], &["A"]));
-        let mut builder = Builder::new(&build);
-        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
+        let mut cache = run_build(&[], configure("build", &["A"], &["A"]));
 
         let a = TargetSelection::from_user("A");
         assert_eq!(
-            first(builder.cache.all::<compile::Std>()),
+            first(cache.all::<compile::Std>()),
             &[
                 compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
                 compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
             ]
         );
-        assert!(!builder.cache.all::<compile::Assemble>().is_empty());
+        assert!(!cache.all::<compile::Assemble>().is_empty());
         // Make sure rustdoc is only built once.
         assert_eq!(
-            first(builder.cache.all::<tool::Rustdoc>()),
+            first(cache.all::<tool::Rustdoc>()),
             // Recall that rustdoc stages are off-by-one
             // - this is the compiler it's _linked_ to, not built with.
             &[tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } }],
         );
         assert_eq!(
-            first(builder.cache.all::<compile::Rustc>()),
+            first(cache.all::<compile::Rustc>()),
             &[compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },]
         );
     }
@@ -62,31 +101,27 @@ fn build_default() {
     #[test]
     fn build_stage_0() {
         let config = Config { stage: 0, ..configure("build", &["A"], &["A"]) };
-        let build = Build::new(config);
-        let mut builder = Builder::new(&build);
-        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
+        let mut cache = run_build(&[], config);
 
         let a = TargetSelection::from_user("A");
         assert_eq!(
-            first(builder.cache.all::<compile::Std>()),
+            first(cache.all::<compile::Std>()),
             &[compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },]
         );
-        assert!(!builder.cache.all::<compile::Assemble>().is_empty());
+        assert!(!cache.all::<compile::Assemble>().is_empty());
         assert_eq!(
-            first(builder.cache.all::<tool::Rustdoc>()),
+            first(cache.all::<tool::Rustdoc>()),
             // This is the beta rustdoc.
             // Add an assert here to make sure this is the only rustdoc built.
             &[tool::Rustdoc { compiler: Compiler { host: a, stage: 0 } }],
         );
-        assert!(builder.cache.all::<compile::Rustc>().is_empty());
+        assert!(cache.all::<compile::Rustc>().is_empty());
     }
 
     #[test]
     fn build_cross_compile() {
         let config = Config { stage: 1, ..configure("build", &["A", "B"], &["A", "B"]) };
-        let build = Build::new(config);
-        let mut builder = Builder::new(&build);
-        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
+        let mut cache = run_build(&[], config);
 
         let a = TargetSelection::from_user("A");
         let b = TargetSelection::from_user("B");
@@ -97,7 +132,7 @@ fn build_cross_compile() {
         // (since we're producing stage 1 libraries/binaries).  But currently
         // rustbuild is just a bit buggy here; this should be fixed though.
         assert_eq!(
-            first(builder.cache.all::<compile::Std>()),
+            first(cache.all::<compile::Std>()),
             &[
                 compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
                 compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
@@ -106,7 +141,7 @@ fn build_cross_compile() {
             ]
         );
         assert_eq!(
-            first(builder.cache.all::<compile::Assemble>()),
+            first(cache.all::<compile::Assemble>()),
             &[
                 compile::Assemble { target_compiler: Compiler { host: a, stage: 0 } },
                 compile::Assemble { target_compiler: Compiler { host: a, stage: 1 } },
@@ -114,14 +149,14 @@ fn build_cross_compile() {
             ]
         );
         assert_eq!(
-            first(builder.cache.all::<tool::Rustdoc>()),
+            first(cache.all::<tool::Rustdoc>()),
             &[
                 tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } },
                 tool::Rustdoc { compiler: Compiler { host: b, stage: 1 } },
             ],
         );
         assert_eq!(
-            first(builder.cache.all::<compile::Rustc>()),
+            first(cache.all::<compile::Rustc>()),
             &[
                 compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
                 compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: b },
@@ -134,33 +169,28 @@ fn doc_default() {
         let mut config = configure("doc", &["A"], &["A"]);
         config.compiler_docs = true;
         config.cmd = Subcommand::Doc { paths: Vec::new(), open: false };
-        let build = Build::new(config);
-        let mut builder = Builder::new(&build);
-        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), &[]);
+        let mut cache = run_build(&[], config);
         let a = TargetSelection::from_user("A");
 
         // error_index_generator uses stage 0 to share rustdoc artifacts with the
         // rustdoc tool.
+        assert_eq!(first(cache.all::<doc::ErrorIndex>()), &[doc::ErrorIndex { target: a },]);
         assert_eq!(
-            first(builder.cache.all::<doc::ErrorIndex>()),
-            &[doc::ErrorIndex { target: a },]
-        );
-        assert_eq!(
-            first(builder.cache.all::<tool::ErrorIndex>()),
+            first(cache.all::<tool::ErrorIndex>()),
             &[tool::ErrorIndex { compiler: Compiler { host: a, stage: 0 } }]
         );
         // docs should be built with the beta compiler, not with the stage0 artifacts.
         // recall that rustdoc is off-by-one: `stage` is the compiler rustdoc is _linked_ to,
         // not the one it was built by.
         assert_eq!(
-            first(builder.cache.all::<tool::Rustdoc>()),
+            first(cache.all::<tool::Rustdoc>()),
             &[tool::Rustdoc { compiler: Compiler { host: a, stage: 0 } },]
         );
     }
 }
 
 mod dist {
-    use super::{first, Config};
+    use super::{first, run_build, Config};
     use crate::builder::*;
     use pretty_assertions::assert_eq;
 
@@ -170,94 +200,88 @@ fn configure(host: &[&str], target: &[&str]) -> Config {
 
     #[test]
     fn dist_baseline() {
-        let build = Build::new(configure(&["A"], &["A"]));
-        let mut builder = Builder::new(&build);
-        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+        let mut cache = run_build(&[], configure(&["A"], &["A"]));
 
         let a = TargetSelection::from_user("A");
 
-        assert_eq!(first(builder.cache.all::<dist::Docs>()), &[dist::Docs { host: a },]);
-        assert_eq!(first(builder.cache.all::<dist::Mingw>()), &[dist::Mingw { host: a },]);
+        assert_eq!(first(cache.all::<dist::Docs>()), &[dist::Docs { host: a },]);
+        assert_eq!(first(cache.all::<dist::Mingw>()), &[dist::Mingw { host: a },]);
         assert_eq!(
-            first(builder.cache.all::<dist::Rustc>()),
+            first(cache.all::<dist::Rustc>()),
             &[dist::Rustc { compiler: Compiler { host: a, stage: 2 } },]
         );
         assert_eq!(
-            first(builder.cache.all::<dist::Std>()),
+            first(cache.all::<dist::Std>()),
             &[dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },]
         );
-        assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
+        assert_eq!(first(cache.all::<dist::Src>()), &[dist::Src]);
         // Make sure rustdoc is only built once.
         assert_eq!(
-            first(builder.cache.all::<tool::Rustdoc>()),
+            first(cache.all::<tool::Rustdoc>()),
             &[tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },]
         );
     }
 
     #[test]
     fn dist_with_targets() {
-        let build = Build::new(configure(&["A"], &["A", "B"]));
-        let mut builder = Builder::new(&build);
-        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+        let mut cache = run_build(&[], configure(&["A"], &["A", "B"]));
 
         let a = TargetSelection::from_user("A");
         let b = TargetSelection::from_user("B");
 
         assert_eq!(
-            first(builder.cache.all::<dist::Docs>()),
+            first(cache.all::<dist::Docs>()),
             &[dist::Docs { host: a }, dist::Docs { host: b },]
         );
         assert_eq!(
-            first(builder.cache.all::<dist::Mingw>()),
+            first(cache.all::<dist::Mingw>()),
             &[dist::Mingw { host: a }, dist::Mingw { host: b },]
         );
         assert_eq!(
-            first(builder.cache.all::<dist::Rustc>()),
+            first(cache.all::<dist::Rustc>()),
             &[dist::Rustc { compiler: Compiler { host: a, stage: 2 } },]
         );
         assert_eq!(
-            first(builder.cache.all::<dist::Std>()),
+            first(cache.all::<dist::Std>()),
             &[
                 dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
                 dist::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
             ]
         );
-        assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
+        assert_eq!(first(cache.all::<dist::Src>()), &[dist::Src]);
     }
 
     #[test]
     fn dist_with_hosts() {
-        let build = Build::new(configure(&["A", "B"], &["A", "B"]));
-        let mut builder = Builder::new(&build);
-        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+        let mut cache = run_build(&[], configure(&["A", "B"], &["A", "B"]));
 
         let a = TargetSelection::from_user("A");
         let b = TargetSelection::from_user("B");
 
         assert_eq!(
-            first(builder.cache.all::<dist::Docs>()),
+            first(cache.all::<dist::Docs>()),
             &[dist::Docs { host: a }, dist::Docs { host: b },]
         );
         assert_eq!(
-            first(builder.cache.all::<dist::Mingw>()),
+            first(cache.all::<dist::Mingw>()),
             &[dist::Mingw { host: a }, dist::Mingw { host: b },]
         );
         assert_eq!(
-            first(builder.cache.all::<dist::Rustc>()),
+            first(cache.all::<dist::Rustc>()),
             &[
                 dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
                 dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
             ]
         );
         assert_eq!(
-            first(builder.cache.all::<dist::Std>()),
+            first(cache.all::<dist::Std>()),
             &[
                 dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
                 dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
             ]
         );
         assert_eq!(
-            first(builder.cache.all::<compile::Std>()),
+            first(cache.all::<compile::Std>()),
             &[
                 compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
                 compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
@@ -266,26 +290,25 @@ fn dist_with_hosts() {
                 compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
             ],
         );
-        assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
+        assert_eq!(first(cache.all::<dist::Src>()), &[dist::Src]);
     }
 
     #[test]
     fn dist_only_cross_host() {
         let a = TargetSelection::from_user("A");
         let b = TargetSelection::from_user("B");
-        let mut build = Build::new(configure(&["A", "B"], &["A", "B"]));
-        build.config.docs = false;
-        build.config.extended = true;
-        build.hosts = vec![b];
-        let mut builder = Builder::new(&build);
-        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+        let mut config = configure(&["A", "B"], &["A", "B"]);
+        config.docs = false;
+        config.extended = true;
+        config.hosts = vec![b];
+        let mut cache = run_build(&[], config);
 
         assert_eq!(
-            first(builder.cache.all::<dist::Rustc>()),
+            first(cache.all::<dist::Rustc>()),
             &[dist::Rustc { compiler: Compiler { host: b, stage: 2 } },]
         );
         assert_eq!(
-            first(builder.cache.all::<compile::Rustc>()),
+            first(cache.all::<compile::Rustc>()),
             &[
                 compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
                 compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b },
@@ -295,92 +318,86 @@ fn dist_only_cross_host() {
 
     #[test]
     fn dist_with_targets_and_hosts() {
-        let build = Build::new(configure(&["A", "B"], &["A", "B", "C"]));
-        let mut builder = Builder::new(&build);
-        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+        let mut cache = run_build(&[], configure(&["A", "B"], &["A", "B", "C"]));
 
         let a = TargetSelection::from_user("A");
         let b = TargetSelection::from_user("B");
         let c = TargetSelection::from_user("C");
 
         assert_eq!(
-            first(builder.cache.all::<dist::Docs>()),
+            first(cache.all::<dist::Docs>()),
             &[dist::Docs { host: a }, dist::Docs { host: b }, dist::Docs { host: c },]
         );
         assert_eq!(
-            first(builder.cache.all::<dist::Mingw>()),
+            first(cache.all::<dist::Mingw>()),
             &[dist::Mingw { host: a }, dist::Mingw { host: b }, dist::Mingw { host: c },]
         );
         assert_eq!(
-            first(builder.cache.all::<dist::Rustc>()),
+            first(cache.all::<dist::Rustc>()),
             &[
                 dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
                 dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
             ]
         );
         assert_eq!(
-            first(builder.cache.all::<dist::Std>()),
+            first(cache.all::<dist::Std>()),
             &[
                 dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
                 dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
                 dist::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
             ]
         );
-        assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
+        assert_eq!(first(cache.all::<dist::Src>()), &[dist::Src]);
     }
 
     #[test]
     fn dist_with_empty_host() {
         let config = configure(&[], &["C"]);
-        let build = Build::new(config);
-        let mut builder = Builder::new(&build);
-        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+        let mut cache = run_build(&[], config);
 
         let a = TargetSelection::from_user("A");
         let c = TargetSelection::from_user("C");
 
-        assert_eq!(first(builder.cache.all::<dist::Docs>()), &[dist::Docs { host: c },]);
-        assert_eq!(first(builder.cache.all::<dist::Mingw>()), &[dist::Mingw { host: c },]);
+        assert_eq!(first(cache.all::<dist::Docs>()), &[dist::Docs { host: c },]);
+        assert_eq!(first(cache.all::<dist::Mingw>()), &[dist::Mingw { host: c },]);
         assert_eq!(
-            first(builder.cache.all::<dist::Std>()),
+            first(cache.all::<dist::Std>()),
             &[dist::Std { compiler: Compiler { host: a, stage: 2 }, target: c },]
         );
     }
 
     #[test]
     fn dist_with_same_targets_and_hosts() {
-        let build = Build::new(configure(&["A", "B"], &["A", "B"]));
-        let mut builder = Builder::new(&build);
-        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+        let mut cache = run_build(&[], configure(&["A", "B"], &["A", "B"]));
 
         let a = TargetSelection::from_user("A");
         let b = TargetSelection::from_user("B");
 
         assert_eq!(
-            first(builder.cache.all::<dist::Docs>()),
+            first(cache.all::<dist::Docs>()),
             &[dist::Docs { host: a }, dist::Docs { host: b },]
         );
         assert_eq!(
-            first(builder.cache.all::<dist::Mingw>()),
+            first(cache.all::<dist::Mingw>()),
             &[dist::Mingw { host: a }, dist::Mingw { host: b },]
         );
         assert_eq!(
-            first(builder.cache.all::<dist::Rustc>()),
+            first(cache.all::<dist::Rustc>()),
             &[
                 dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
                 dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
             ]
         );
         assert_eq!(
-            first(builder.cache.all::<dist::Std>()),
+            first(cache.all::<dist::Std>()),
             &[
                 dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
                 dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
             ]
         );
-        assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
+        assert_eq!(first(cache.all::<dist::Src>()), &[dist::Src]);
         assert_eq!(
-            first(builder.cache.all::<compile::Std>()),
+            first(cache.all::<compile::Std>()),
             &[
                 compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
                 compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
@@ -390,7 +407,7 @@ fn dist_with_same_targets_and_hosts() {
             ]
         );
         assert_eq!(
-            first(builder.cache.all::<compile::Assemble>()),
+            first(cache.all::<compile::Assemble>()),
             &[
                 compile::Assemble { target_compiler: Compiler { host: a, stage: 0 } },
                 compile::Assemble { target_compiler: Compiler { host: a, stage: 1 } },
@@ -514,35 +531,6 @@ fn test_with_no_doc_stage0() {
         );
     }
 
-    #[test]
-    fn test_exclude() {
-        let mut config = configure(&["A"], &["A"]);
-        config.exclude = vec![TaskPath::parse("src/tools/tidy")];
-        config.cmd = Subcommand::Test {
-            paths: Vec::new(),
-            test_args: Vec::new(),
-            rustc_args: Vec::new(),
-            fail_fast: true,
-            doc_tests: DocTests::No,
-            bless: false,
-            force_rerun: false,
-            compare_mode: None,
-            rustfix_coverage: false,
-            pass: None,
-            run: None,
-        };
-
-        let build = Build::new(config);
-        let builder = Builder::new(&build);
-        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]);
-
-        // Ensure we have really excluded tidy
-        assert!(!builder.cache.contains::<test::Tidy>());
-
-        // Ensure other tests are not affected.
-        assert!(builder.cache.contains::<test::RustdocUi>());
-    }
-
     #[test]
     fn doc_ci() {
         let mut config = configure(&["A"], &["A"]);
index 7ce446876118af13244c4c914dc2dfcdf1ca525a..dca782c29c252f72ac6087787ac559541ff28cd2 100644 (file)
@@ -149,6 +149,10 @@ pub fn find(build: &mut Build) {
             build.verbose(&format!("AR_{} = {:?}", &target.triple, ar));
             build.ar.insert(target, ar);
         }
+
+        if let Some(ranlib) = config.and_then(|c| c.ranlib.clone()) {
+            build.ranlib.insert(target, ranlib);
+        }
     }
 }
 
index 432a6c34ed58415c934989acf542546a3cc13c4a..731ebc41bb9a00b075022cbf9eba827bdf189f71 100644 (file)
@@ -64,7 +64,7 @@ impl Step for Std {
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.all_krates("test")
+        run.all_krates("test").path("library")
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -162,7 +162,7 @@ impl Step for Rustc {
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.all_krates("rustc-main")
+        run.all_krates("rustc-main").path("compiler")
     }
 
     fn make_run(run: RunConfig<'_>) {
index 45991381dc0fe1d9a70b64062d40b78624326bce..a212c659b5c2b3a9931ab3b0690299d00388bc6a 100644 (file)
@@ -43,7 +43,7 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         // When downloading stage1, the standard library has already been copied to the sysroot, so
         // there's no need to rebuild it.
         let download_rustc = run.builder.config.download_rustc;
-        run.all_krates("test").default_condition(!download_rustc)
+        run.all_krates("test").path("library").default_condition(!download_rustc)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -1047,7 +1047,7 @@ impl Step for Assemble {
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("compiler/rustc")
+        run.path("compiler/rustc").path("compiler")
     }
 
     fn make_run(run: RunConfig<'_>) {
index 9534cc5f4341e3aad4057a4ea2d5c903a4c18cc9..1638d3ed3c2814fe19351268c733e540ea284002 100644 (file)
@@ -41,6 +41,7 @@ macro_rules! check_ci_llvm {
 /// each field, see the corresponding fields in
 /// `config.toml.example`.
 #[derive(Default)]
+#[cfg_attr(test, derive(Clone))]
 pub struct Config {
     pub changelog_seen: Option<usize>,
     pub ccache: Option<String>,
@@ -130,7 +131,7 @@ pub struct Config {
     pub rust_debuginfo_level_std: u32,
     pub rust_debuginfo_level_tools: u32,
     pub rust_debuginfo_level_tests: u32,
-    pub rust_run_dsymutil: bool,
+    pub rust_split_debuginfo: SplitDebuginfo,
     pub rust_rpath: bool,
     pub rustc_parallel: bool,
     pub rustc_default_linker: Option<String>,
@@ -221,7 +222,47 @@ fn from_str(value: &str) -> Result<Self, Self::Err> {
     }
 }
 
-#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum SplitDebuginfo {
+    Packed,
+    Unpacked,
+    Off,
+}
+
+impl Default for SplitDebuginfo {
+    fn default() -> Self {
+        SplitDebuginfo::Off
+    }
+}
+
+impl std::str::FromStr for SplitDebuginfo {
+    type Err = ();
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s {
+            "packed" => Ok(SplitDebuginfo::Packed),
+            "unpacked" => Ok(SplitDebuginfo::Unpacked),
+            "off" => Ok(SplitDebuginfo::Off),
+            _ => Err(()),
+        }
+    }
+}
+
+impl SplitDebuginfo {
+    /// Returns the default `-Csplit-debuginfo` value for the current target. See the comment for
+    /// `rust.split-debuginfo` in `config.toml.example`.
+    fn default_for_platform(target: &str) -> Self {
+        if target.contains("apple") {
+            SplitDebuginfo::Unpacked
+        } else if target.contains("windows") {
+            SplitDebuginfo::Packed
+        } else {
+            SplitDebuginfo::Off
+        }
+    }
+}
+
+#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct TargetSelection {
     pub triple: Interned<String>,
     file: Option<Interned<String>>,
@@ -276,6 +317,12 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
+impl fmt::Debug for TargetSelection {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", self)
+    }
+}
+
 impl PartialEq<&str> for TargetSelection {
     fn eq(&self, other: &&str) -> bool {
         self.triple == *other
@@ -284,6 +331,7 @@ fn eq(&self, other: &&str) -> bool {
 
 /// Per-target configuration stored in the global configuration structure.
 #[derive(Default)]
+#[cfg_attr(test, derive(Clone))]
 pub struct Target {
     /// Some(path to llvm-config) if using an external LLVM.
     pub llvm_config: Option<PathBuf>,
@@ -580,6 +628,7 @@ struct Rust {
         debuginfo_level_std: Option<u32> = "debuginfo-level-std",
         debuginfo_level_tools: Option<u32> = "debuginfo-level-tools",
         debuginfo_level_tests: Option<u32> = "debuginfo-level-tests",
+        split_debuginfo: Option<String> = "split-debuginfo",
         run_dsymutil: Option<bool> = "run-dsymutil",
         backtrace: Option<bool> = "backtrace",
         incremental: Option<bool> = "incremental",
@@ -986,7 +1035,12 @@ pub fn parse(args: &[String]) -> Config {
             debuginfo_level_std = rust.debuginfo_level_std;
             debuginfo_level_tools = rust.debuginfo_level_tools;
             debuginfo_level_tests = rust.debuginfo_level_tests;
-            config.rust_run_dsymutil = rust.run_dsymutil.unwrap_or(false);
+            config.rust_split_debuginfo = rust
+                .split_debuginfo
+                .as_deref()
+                .map(SplitDebuginfo::from_str)
+                .map(|v| v.expect("invalid value for rust.split_debuginfo"))
+                .unwrap_or(SplitDebuginfo::default_for_platform(&config.build.triple));
             optimize = rust.optimize;
             ignore_git = rust.ignore_git;
             config.rust_new_symbol_mangling = rust.new_symbol_mangling;
index fdd1581d9cd95460adb5eca62b2306a3f622d65c..e3287e35227b9915cb1825f21e0dcdfb78bd15a9 100644 (file)
@@ -61,7 +61,7 @@ impl Step for Docs {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let default = run.builder.config.docs;
-        run.path("rust-docs").default_condition(default)
+        run.alias("rust-docs").default_condition(default)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -94,7 +94,7 @@ impl Step for RustcDocs {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let builder = run.builder;
-        run.path("rustc-docs").default_condition(builder.config.compiler_docs)
+        run.alias("rustc-docs").default_condition(builder.config.compiler_docs)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -272,7 +272,7 @@ impl Step for Mingw {
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("rust-mingw")
+        run.alias("rust-mingw")
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -313,7 +313,7 @@ impl Step for Rustc {
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("rustc")
+        run.alias("rustc")
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -456,7 +456,7 @@ impl Step for DebuggerScripts {
     type Output = ();
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("src/lldb_batchmode.py")
+        run.path("src/etc/lldb_batchmode.py")
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -547,7 +547,7 @@ impl Step for Std {
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("rust-std")
+        run.alias("rust-std")
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -594,7 +594,7 @@ impl Step for RustcDev {
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("rustc-dev")
+        run.alias("rustc-dev")
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -653,7 +653,7 @@ impl Step for Analysis {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let default = should_build_extended_tool(&run.builder, "analysis");
-        run.path("rust-analysis").default_condition(default)
+        run.alias("rust-analysis").default_condition(default)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -790,7 +790,7 @@ impl Step for Src {
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("rust-src")
+        run.alias("rust-src")
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -848,7 +848,7 @@ impl Step for PlainSourceTarball {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let builder = run.builder;
-        run.path("rustc-src").default_condition(builder.config.rust_dist_src)
+        run.alias("rustc-src").default_condition(builder.config.rust_dist_src)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -942,7 +942,7 @@ impl Step for Cargo {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let default = should_build_extended_tool(&run.builder, "cargo");
-        run.path("cargo").default_condition(default)
+        run.alias("cargo").default_condition(default)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -998,7 +998,7 @@ impl Step for Rls {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let default = should_build_extended_tool(&run.builder, "rls");
-        run.path("rls").default_condition(default)
+        run.alias("rls").default_condition(default)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -1045,7 +1045,7 @@ impl Step for RustAnalyzer {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let default = should_build_extended_tool(&run.builder, "rust-analyzer");
-        run.path("rust-analyzer").default_condition(default)
+        run.alias("rust-analyzer").default_condition(default)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -1101,7 +1101,7 @@ impl Step for Clippy {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let default = should_build_extended_tool(&run.builder, "clippy");
-        run.path("clippy").default_condition(default)
+        run.alias("clippy").default_condition(default)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -1152,7 +1152,7 @@ impl Step for Miri {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let default = should_build_extended_tool(&run.builder, "miri");
-        run.path("miri").default_condition(default)
+        run.alias("miri").default_condition(default)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -1212,7 +1212,7 @@ impl Step for Rustfmt {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let default = should_build_extended_tool(&run.builder, "rustfmt");
-        run.path("rustfmt").default_condition(default)
+        run.alias("rustfmt").default_condition(default)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -1271,7 +1271,7 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         // we run the step by default when only `extended = true`, and decide whether to actually
         // run it or not later.
         let default = run.builder.config.extended;
-        run.path("rust-demangler").default_condition(default)
+        run.alias("rust-demangler").default_condition(default)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -1324,7 +1324,7 @@ impl Step for Extended {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let builder = run.builder;
-        run.path("extended").default_condition(builder.config.extended)
+        run.alias("extended").default_condition(builder.config.extended)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -1968,7 +1968,8 @@ impl Step for LlvmTools {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let default = should_build_extended_tool(&run.builder, "llvm-tools");
-        run.path("llvm-tools").default_condition(default)
+        // FIXME: allow using the names of the tools themselves?
+        run.alias("llvm-tools").default_condition(default)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -2022,7 +2023,7 @@ impl Step for RustDev {
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("rust-dev")
+        run.alias("rust-dev")
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -2098,7 +2099,7 @@ impl Step for BuildManifest {
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("build-manifest")
+        run.alias("build-manifest")
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -2130,7 +2131,7 @@ impl Step for ReproducibleArtifacts {
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("reproducible-artifacts")
+        run.alias("reproducible-artifacts")
     }
 
     fn make_run(run: RunConfig<'_>) {
index 077a86af50b2e0bf36aeb35f87ae89d72450132e..fcef784d2d1fa3547379fac1cd135784f4ecc060 100644 (file)
@@ -416,7 +416,7 @@ impl Step for Std {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let builder = run.builder;
-        run.all_krates("test").default_condition(builder.config.docs)
+        run.all_krates("test").path("library").default_condition(builder.config.docs)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -441,7 +441,6 @@ fn run(self, builder: &Builder<'_>) {
         t!(fs::create_dir_all(&out));
         let compiler = builder.compiler(stage, builder.config.build);
 
-        builder.ensure(compile::Std { compiler, target });
         let out_dir = builder.stage_out(compiler, Mode::Std).join(target.triple).join("doc");
 
         t!(fs::copy(builder.src.join("src/doc/rust.css"), out.join("rust.css")));
@@ -478,11 +477,14 @@ fn run(self, builder: &Builder<'_>) {
             .iter()
             .map(components_simplified)
             .filter_map(|path| {
-                if path.get(0) == Some(&"library") {
+                if path.len() >= 2 && path.get(0) == Some(&"library") {
+                    // single crate
                     Some(path[1].to_owned())
                 } else if !path.is_empty() {
+                    // ??
                     Some(path[0].to_owned())
                 } else {
+                    // all library crates
                     None
                 }
             })
@@ -548,7 +550,6 @@ fn make_run(run: RunConfig<'_>) {
     fn run(self, builder: &Builder<'_>) {
         let stage = self.stage;
         let target = self.target;
-        builder.info(&format!("Documenting stage{} compiler ({})", stage, target));
 
         let paths = builder
             .paths
@@ -563,9 +564,12 @@ fn run(self, builder: &Builder<'_>) {
         let out = builder.compiler_doc_out(target);
         t!(fs::create_dir_all(&out));
 
-        // Build rustc.
+        // Build the standard library, so that proc-macros can use it.
+        // (Normally, only the metadata would be necessary, but proc-macros are special since they run at compile-time.)
         let compiler = builder.compiler(stage, builder.config.build);
-        builder.ensure(compile::Rustc { compiler, target });
+        builder.ensure(compile::Std { compiler, target: builder.config.build });
+
+        builder.info(&format!("Documenting stage{} compiler ({})", stage, target));
 
         // This uses a shared directory so that librustdoc documentation gets
         // correctly built and merged with the rustc documentation. This is
@@ -642,7 +646,6 @@ macro_rules! tool_doc {
     ($tool: ident, $should_run: literal, $path: literal, [$($krate: literal),+ $(,)?] $(,)?) => {
         #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
         pub struct $tool {
-            stage: u32,
             target: TargetSelection,
         }
 
@@ -657,7 +660,7 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
             }
 
             fn make_run(run: RunConfig<'_>) {
-                run.builder.ensure($tool { stage: run.builder.top_stage, target: run.target });
+                run.builder.ensure($tool { target: run.target });
             }
 
             /// Generates compiler documentation.
@@ -667,8 +670,21 @@ fn make_run(run: RunConfig<'_>) {
             /// we do not merge it with the other documentation from std, test and
             /// proc_macros. This is largely just a wrapper around `cargo doc`.
             fn run(self, builder: &Builder<'_>) {
-                let stage = self.stage;
+                let stage = builder.top_stage;
                 let target = self.target;
+
+                // This is the intended out directory for compiler documentation.
+                let out = builder.compiler_doc_out(target);
+                t!(fs::create_dir_all(&out));
+
+                // Build rustc docs so that we generate relative links.
+                builder.ensure(Rustc { stage, target });
+                // Rustdoc needs the rustc sysroot available to build.
+                // FIXME: is there a way to only ensure `check::Rustc` here? Last time I tried it failed
+                // with strange errors, but only on a full bors test ...
+                let compiler = builder.compiler(stage, builder.config.build);
+                builder.ensure(compile::Rustc { compiler, target });
+
                 builder.info(
                     &format!(
                         "Documenting stage{} {} ({})",
@@ -678,15 +694,6 @@ fn run(self, builder: &Builder<'_>) {
                     ),
                 );
 
-                // This is the intended out directory for compiler documentation.
-                let out = builder.compiler_doc_out(target);
-                t!(fs::create_dir_all(&out));
-
-                let compiler = builder.compiler(stage, builder.config.build);
-
-                // Build rustc docs so that we generate relative links.
-                builder.ensure(Rustc { stage, target });
-
                 // Symlink compiler docs to the output directory of rustdoc documentation.
                 let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc");
                 t!(fs::create_dir_all(&out_dir));
index 1a4e6a9688803b544295aa7d1c7ba0d5d2d9c2d0..58571ea129c1940b68766ae64f5b78c9a78a19a7 100644 (file)
@@ -8,12 +8,13 @@
 
 use getopts::Options;
 
-use crate::builder::Builder;
+use crate::builder::{Builder, Kind};
 use crate::config::{Config, TargetSelection};
 use crate::setup::Profile;
 use crate::util::t;
 use crate::{Build, DocTests};
 
+#[derive(Copy, Clone)]
 pub enum Color {
     Always,
     Never,
@@ -79,6 +80,7 @@ pub struct Flags {
     pub llvm_profile_generate: bool,
 }
 
+#[cfg_attr(test, derive(Clone))]
 pub enum Subcommand {
     Build {
         paths: Vec<PathBuf>,
@@ -243,27 +245,7 @@ pub fn parse(args: &[String]) -> Flags {
         // the subcommand. Therefore we must manually identify the subcommand first, so that we can
         // complete the definition of the options.  Then we can use the getopt::Matches object from
         // there on out.
-        let subcommand = args.iter().find(|&s| {
-            (s == "build")
-                || (s == "b")
-                || (s == "check")
-                || (s == "c")
-                || (s == "clippy")
-                || (s == "fix")
-                || (s == "fmt")
-                || (s == "test")
-                || (s == "t")
-                || (s == "bench")
-                || (s == "doc")
-                || (s == "d")
-                || (s == "clean")
-                || (s == "dist")
-                || (s == "install")
-                || (s == "run")
-                || (s == "r")
-                || (s == "setup")
-        });
-        let subcommand = match subcommand {
+        let subcommand = match args.iter().find_map(|s| Kind::parse(&s)) {
             Some(s) => s,
             None => {
                 // No or an invalid subcommand -- show the general usage and subcommand help
@@ -276,8 +258,8 @@ pub fn parse(args: &[String]) -> Flags {
         };
 
         // Some subcommands get extra options
-        match subcommand.as_str() {
-            "test" | "t" => {
+        match subcommand {
+            Kind::Test => {
                 opts.optflag("", "no-fail-fast", "Run all tests regardless of failure");
                 opts.optmulti(
                     "",
@@ -316,22 +298,22 @@ pub fn parse(args: &[String]) -> Flags {
                         `/<build_base>/rustfix_missing_coverage.txt`",
                 );
             }
-            "check" | "c" => {
+            Kind::Check => {
                 opts.optflag("", "all-targets", "Check all targets");
             }
-            "bench" => {
+            Kind::Bench => {
                 opts.optmulti("", "test-args", "extra arguments", "ARGS");
             }
-            "clippy" => {
+            Kind::Clippy => {
                 opts.optflag("", "fix", "automatically apply lint suggestions");
             }
-            "doc" | "d" => {
+            Kind::Doc => {
                 opts.optflag("", "open", "open the docs in a browser");
             }
-            "clean" => {
+            Kind::Clean => {
                 opts.optflag("", "all", "clean all build artifacts");
             }
-            "fmt" => {
+            Kind::Format => {
                 opts.optflag("", "check", "check formatting instead of applying.");
             }
             _ => {}
@@ -339,25 +321,22 @@ pub fn parse(args: &[String]) -> Flags {
 
         // fn usage()
         let usage = |exit_code: i32, opts: &Options, verbose: bool, subcommand_help: &str| -> ! {
-            let mut extra_help = String::new();
-
-            // All subcommands except `clean` can have an optional "Available paths" section
-            if verbose {
-                let config = Config::parse(&["build".to_string()]);
-                let build = Build::new(config);
-
-                let maybe_rules_help = Builder::get_help(&build, subcommand.as_str());
-                extra_help.push_str(maybe_rules_help.unwrap_or_default().as_str());
-            } else if !(subcommand.as_str() == "clean" || subcommand.as_str() == "fmt") {
-                extra_help.push_str(
-                    format!("Run `./x.py {} -h -v` to see a list of available paths.", subcommand)
-                        .as_str(),
-                );
-            }
+            let config = Config::parse(&["build".to_string()]);
+            let build = Build::new(config);
+            let paths = Builder::get_help(&build, subcommand);
 
             println!("{}", opts.usage(subcommand_help));
-            if !extra_help.is_empty() {
-                println!("{}", extra_help);
+            if let Some(s) = paths {
+                if verbose {
+                    println!("{}", s);
+                } else {
+                    println!(
+                        "Run `./x.py {} -h -v` to see a list of available paths.",
+                        subcommand.as_str()
+                    );
+                }
+            } else if verbose {
+                panic!("No paths available for subcommand `{}`", subcommand.as_str());
             }
             process::exit(exit_code);
         };
@@ -375,7 +354,7 @@ pub fn parse(args: &[String]) -> Flags {
         //            ^-- option  ^     ^- actual subcommand
         //                        \_ arg to option could be mistaken as subcommand
         let mut pass_sanity_check = true;
-        match matches.free.get(0) {
+        match matches.free.get(0).and_then(|s| Kind::parse(&s)) {
             Some(check_subcommand) => {
                 if check_subcommand != subcommand {
                     pass_sanity_check = false;
@@ -394,8 +373,8 @@ pub fn parse(args: &[String]) -> Flags {
             process::exit(1);
         }
         // Extra help text for some commands
-        match subcommand.as_str() {
-            "build" | "b" => {
+        match subcommand {
+            Kind::Build => {
                 subcommand_help.push_str(
                     "\n
 Arguments:
@@ -415,7 +394,7 @@ pub fn parse(args: &[String]) -> Flags {
         ./x.py build ",
                 );
             }
-            "check" | "c" => {
+            Kind::Check => {
                 subcommand_help.push_str(
                     "\n
 Arguments:
@@ -427,7 +406,7 @@ pub fn parse(args: &[String]) -> Flags {
     If no arguments are passed then many artifacts are checked.",
                 );
             }
-            "clippy" => {
+            Kind::Clippy => {
                 subcommand_help.push_str(
                     "\n
 Arguments:
@@ -438,7 +417,7 @@ pub fn parse(args: &[String]) -> Flags {
         ./x.py clippy library/core library/proc_macro",
                 );
             }
-            "fix" => {
+            Kind::Fix => {
                 subcommand_help.push_str(
                     "\n
 Arguments:
@@ -449,7 +428,7 @@ pub fn parse(args: &[String]) -> Flags {
         ./x.py fix library/core library/proc_macro",
                 );
             }
-            "fmt" => {
+            Kind::Format => {
                 subcommand_help.push_str(
                     "\n
 Arguments:
@@ -460,7 +439,7 @@ pub fn parse(args: &[String]) -> Flags {
         ./x.py fmt --check",
                 );
             }
-            "test" | "t" => {
+            Kind::Test => {
                 subcommand_help.push_str(
                     "\n
 Arguments:
@@ -488,7 +467,7 @@ pub fn parse(args: &[String]) -> Flags {
         ./x.py test --stage 1",
                 );
             }
-            "doc" | "d" => {
+            Kind::Doc => {
                 subcommand_help.push_str(
                     "\n
 Arguments:
@@ -506,7 +485,7 @@ pub fn parse(args: &[String]) -> Flags {
         ./x.py doc --stage 1",
                 );
             }
-            "run" | "r" => {
+            Kind::Run => {
                 subcommand_help.push_str(
                     "\n
 Arguments:
@@ -518,7 +497,7 @@ pub fn parse(args: &[String]) -> Flags {
     At least a tool needs to be called.",
                 );
             }
-            "setup" => {
+            Kind::Setup => {
                 subcommand_help.push_str(&format!(
                     "\n
 x.py setup creates a `config.toml` which changes the defaults for x.py itself.
@@ -535,7 +514,7 @@ pub fn parse(args: &[String]) -> Flags {
                     Profile::all_for_help("        ").trim_end()
                 ));
             }
-            _ => {}
+            Kind::Bench | Kind::Clean | Kind::Dist | Kind::Install => {}
         };
         // Get any optional paths which occur after the subcommand
         let mut paths = matches.free[1..].iter().map(|p| p.into()).collect::<Vec<PathBuf>>();
@@ -547,9 +526,9 @@ pub fn parse(args: &[String]) -> Flags {
             usage(0, &opts, verbose, &subcommand_help);
         }
 
-        let cmd = match subcommand.as_str() {
-            "build" | "b" => Subcommand::Build { paths },
-            "check" | "c" => {
+        let cmd = match subcommand {
+            Kind::Build => Subcommand::Build { paths },
+            Kind::Check => {
                 if matches.opt_present("all-targets") {
                     eprintln!(
                         "Warning: --all-targets is now on by default and does not need to be passed explicitly."
@@ -557,9 +536,9 @@ pub fn parse(args: &[String]) -> Flags {
                 }
                 Subcommand::Check { paths }
             }
-            "clippy" => Subcommand::Clippy { paths, fix: matches.opt_present("fix") },
-            "fix" => Subcommand::Fix { paths },
-            "test" | "t" => Subcommand::Test {
+            Kind::Clippy => Subcommand::Clippy { paths, fix: matches.opt_present("fix") },
+            Kind::Fix => Subcommand::Fix { paths },
+            Kind::Test => Subcommand::Test {
                 paths,
                 bless: matches.opt_present("bless"),
                 force_rerun: matches.opt_present("force-rerun"),
@@ -578,9 +557,9 @@ pub fn parse(args: &[String]) -> Flags {
                     DocTests::Yes
                 },
             },
-            "bench" => Subcommand::Bench { paths, test_args: matches.opt_strs("test-args") },
-            "doc" | "d" => Subcommand::Doc { paths, open: matches.opt_present("open") },
-            "clean" => {
+            Kind::Bench => Subcommand::Bench { paths, test_args: matches.opt_strs("test-args") },
+            Kind::Doc => Subcommand::Doc { paths, open: matches.opt_present("open") },
+            Kind::Clean => {
                 if !paths.is_empty() {
                     println!("\nclean does not take a path argument\n");
                     usage(1, &opts, verbose, &subcommand_help);
@@ -588,17 +567,17 @@ pub fn parse(args: &[String]) -> Flags {
 
                 Subcommand::Clean { all: matches.opt_present("all") }
             }
-            "fmt" => Subcommand::Format { check: matches.opt_present("check"), paths },
-            "dist" => Subcommand::Dist { paths },
-            "install" => Subcommand::Install { paths },
-            "run" | "r" => {
+            Kind::Format => Subcommand::Format { check: matches.opt_present("check"), paths },
+            Kind::Dist => Subcommand::Dist { paths },
+            Kind::Install => Subcommand::Install { paths },
+            Kind::Run => {
                 if paths.is_empty() {
                     println!("\nrun requires at least a path!\n");
                     usage(1, &opts, verbose, &subcommand_help);
                 }
                 Subcommand::Run { paths }
             }
-            "setup" => {
+            Kind::Setup => {
                 let profile = if paths.len() > 1 {
                     println!("\nat most one profile can be passed to setup\n");
                     usage(1, &opts, verbose, &subcommand_help)
@@ -618,9 +597,6 @@ pub fn parse(args: &[String]) -> Flags {
                 };
                 Subcommand::Setup { profile }
             }
-            _ => {
-                usage(1, &opts, verbose, &subcommand_help);
-            }
         };
 
         if let Subcommand::Check { .. } = &cmd {
@@ -694,6 +670,24 @@ pub fn parse(args: &[String]) -> Flags {
 }
 
 impl Subcommand {
+    pub fn kind(&self) -> Kind {
+        match self {
+            Subcommand::Bench { .. } => Kind::Bench,
+            Subcommand::Build { .. } => Kind::Build,
+            Subcommand::Check { .. } => Kind::Check,
+            Subcommand::Clippy { .. } => Kind::Clippy,
+            Subcommand::Doc { .. } => Kind::Doc,
+            Subcommand::Fix { .. } => Kind::Fix,
+            Subcommand::Format { .. } => Kind::Format,
+            Subcommand::Test { .. } => Kind::Test,
+            Subcommand::Clean { .. } => Kind::Clean,
+            Subcommand::Dist { .. } => Kind::Dist,
+            Subcommand::Install { .. } => Kind::Install,
+            Subcommand::Run { .. } => Kind::Run,
+            Subcommand::Setup { .. } => Kind::Setup,
+        }
+    }
+
     pub fn test_args(&self) -> Vec<&str> {
         match *self {
             Subcommand::Test { ref test_args, .. } | Subcommand::Bench { ref test_args, .. } => {
index 27b9196d9868e10d23deb5cfb8682ef03f788397..08e37a16279903a8a7f080cf7f6bcdcdab1826f4 100644 (file)
@@ -93,7 +93,7 @@ fn prepare_dir(mut path: PathBuf) -> String {
 macro_rules! install {
     (($sel:ident, $builder:ident, $_config:ident),
        $($name:ident,
-       $path:expr,
+       $condition_name: ident = $path_or_alias: literal,
        $default_cond:expr,
        only_hosts: $only_hosts:expr,
        $run_item:block $(, $c:ident)*;)+) => {
@@ -108,7 +108,7 @@ impl $name {
             #[allow(dead_code)]
             fn should_build(config: &Config) -> bool {
                 config.extended && config.tools.as_ref()
-                    .map_or(true, |t| t.contains($path))
+                    .map_or(true, |t| t.contains($path_or_alias))
             }
         }
 
@@ -120,7 +120,7 @@ impl Step for $name {
 
             fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
                 let $_config = &run.builder.config;
-                run.path($path).default_condition($default_cond)
+                run.$condition_name($path_or_alias).default_condition($default_cond)
             }
 
             fn make_run(run: RunConfig<'_>) {
@@ -138,11 +138,11 @@ fn run($sel, $builder: &Builder<'_>) {
 }
 
 install!((self, builder, _config),
-    Docs, "src/doc", _config.docs, only_hosts: false, {
+    Docs, path = "src/doc", _config.docs, only_hosts: false, {
         let tarball = builder.ensure(dist::Docs { host: self.target }).expect("missing docs");
         install_sh(builder, "docs", self.compiler.stage, Some(self.target), &tarball);
     };
-    Std, "library/std", true, only_hosts: false, {
+    Std, path = "library/std", true, only_hosts: false, {
         for target in &builder.targets {
             // `expect` should be safe, only None when host != build, but this
             // only runs when host == build
@@ -153,13 +153,13 @@ fn run($sel, $builder: &Builder<'_>) {
             install_sh(builder, "std", self.compiler.stage, Some(*target), &tarball);
         }
     };
-    Cargo, "cargo", Self::should_build(_config), only_hosts: true, {
+    Cargo, alias = "cargo", Self::should_build(_config), only_hosts: true, {
         let tarball = builder
             .ensure(dist::Cargo { compiler: self.compiler, target: self.target })
             .expect("missing cargo");
         install_sh(builder, "cargo", self.compiler.stage, Some(self.target), &tarball);
     };
-    Rls, "rls", Self::should_build(_config), only_hosts: true, {
+    Rls, alias = "rls", Self::should_build(_config), only_hosts: true, {
         if let Some(tarball) = builder.ensure(dist::Rls { compiler: self.compiler, target: self.target }) {
             install_sh(builder, "rls", self.compiler.stage, Some(self.target), &tarball);
         } else {
@@ -168,7 +168,7 @@ fn run($sel, $builder: &Builder<'_>) {
             );
         }
     };
-    RustAnalyzer, "rust-analyzer", Self::should_build(_config), only_hosts: true, {
+    RustAnalyzer, alias = "rust-analyzer", Self::should_build(_config), only_hosts: true, {
         if let Some(tarball) =
             builder.ensure(dist::RustAnalyzer { compiler: self.compiler, target: self.target })
         {
@@ -179,13 +179,13 @@ fn run($sel, $builder: &Builder<'_>) {
             );
         }
     };
-    Clippy, "clippy", Self::should_build(_config), only_hosts: true, {
+    Clippy, alias = "clippy", Self::should_build(_config), only_hosts: true, {
         let tarball = builder
             .ensure(dist::Clippy { compiler: self.compiler, target: self.target })
             .expect("missing clippy");
         install_sh(builder, "clippy", self.compiler.stage, Some(self.target), &tarball);
     };
-    Miri, "miri", Self::should_build(_config), only_hosts: true, {
+    Miri, alias = "miri", Self::should_build(_config), only_hosts: true, {
         if let Some(tarball) = builder.ensure(dist::Miri { compiler: self.compiler, target: self.target }) {
             install_sh(builder, "miri", self.compiler.stage, Some(self.target), &tarball);
         } else {
@@ -194,7 +194,7 @@ fn run($sel, $builder: &Builder<'_>) {
             );
         }
     };
-    Rustfmt, "rustfmt", Self::should_build(_config), only_hosts: true, {
+    Rustfmt, alias = "rustfmt", Self::should_build(_config), only_hosts: true, {
         if let Some(tarball) = builder.ensure(dist::Rustfmt {
             compiler: self.compiler,
             target: self.target
@@ -206,7 +206,7 @@ fn run($sel, $builder: &Builder<'_>) {
             );
         }
     };
-    RustDemangler, "rust-demangler", Self::should_build(_config), only_hosts: true, {
+    RustDemangler, alias = "rust-demangler", Self::should_build(_config), only_hosts: true, {
         // Note: Even though `should_build` may return true for `extended` default tools,
         // dist::RustDemangler may still return None, unless the target-dependent `profiler` config
         // is also true, or the `tools` array explicitly includes "rust-demangler".
@@ -222,7 +222,7 @@ fn run($sel, $builder: &Builder<'_>) {
             );
         }
     };
-    Analysis, "analysis", Self::should_build(_config), only_hosts: false, {
+    Analysis, alias = "analysis", Self::should_build(_config), only_hosts: false, {
         // `expect` should be safe, only None with host != build, but this
         // only uses the `build` compiler
         let tarball = builder.ensure(dist::Analysis {
@@ -234,7 +234,7 @@ fn run($sel, $builder: &Builder<'_>) {
         }).expect("missing analysis");
         install_sh(builder, "analysis", self.compiler.stage, Some(self.target), &tarball);
     };
-    Rustc, "src/librustc", true, only_hosts: true, {
+    Rustc, path = "compiler/rustc", true, only_hosts: true, {
         let tarball = builder.ensure(dist::Rustc {
             compiler: builder.compiler(builder.top_stage, self.target),
         });
index 6d7ca9a94cfbde9432fcff3e52c30dc7e435a125..73fb2dad1e3c23ea3d39cbba0d68dd3169054d7b 100644 (file)
@@ -122,7 +122,7 @@ impl Step for Llvm {
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("src/llvm-project").path("src/llvm-project/llvm").path("src/llvm")
+        run.path("src/llvm-project").path("src/llvm-project/llvm")
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -605,7 +605,7 @@ impl Step for Lld {
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("src/llvm-project/lld").path("src/tools/lld")
+        run.path("src/llvm-project/lld")
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -771,7 +771,7 @@ impl Step for Sanitizers {
     type Output = Vec<SanitizerRuntime>;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("src/llvm-project/compiler-rt").path("src/sanitizers")
+        run.alias("sanitizers")
     }
 
     fn make_run(run: RunConfig<'_>) {
index c743c5188e7545f47d7f858b74005107e731c01e..689b4819cdd36622eebecc552347c25458a77baa 100644 (file)
@@ -262,11 +262,13 @@ pub(crate) fn bare(self) -> GeneratedTarball {
         t!(std::fs::rename(&self.image_dir, &dest));
 
         self.run(|this, cmd| {
+            let distdir = crate::dist::distdir(this.builder);
+            t!(std::fs::create_dir_all(&distdir));
             cmd.arg("tarball")
                 .arg("--input")
                 .arg(&dest)
                 .arg("--output")
-                .arg(crate::dist::distdir(this.builder).join(this.package_name()));
+                .arg(distdir.join(this.package_name()));
         })
     }
 
index f60766bde726ebc1416239005e46318a0689da9f..9c376602d283f35af052c956683ca63e5580a691 100644 (file)
@@ -1400,9 +1400,7 @@ fn run(self, builder: &Builder<'_>) {
         targetflags.extend(builder.lld_flags(target));
         cmd.arg("--target-rustcflags").arg(targetflags.join(" "));
 
-        cmd.arg("--docck-python").arg(builder.python());
-
-        cmd.arg("--lldb-python").arg(builder.python());
+        cmd.arg("--python").arg(builder.python());
 
         if let Some(ref gdb) = builder.config.gdb {
             cmd.arg("--gdb").arg(gdb);
@@ -1892,7 +1890,8 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
 
     fn make_run(run: RunConfig<'_>) {
         let builder = run.builder;
-        let compiler = builder.compiler(builder.top_stage, run.build_triple());
+        let host = run.build_triple();
+        let compiler = builder.compiler_for(builder.top_stage, host, host);
         let krate = builder.crate_paths[&run.path];
         let test_kind = builder.kind.into();
 
@@ -1929,7 +1928,8 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
 
     fn make_run(run: RunConfig<'_>) {
         let builder = run.builder;
-        let compiler = builder.compiler(builder.top_stage, run.build_triple());
+        let host = run.build_triple();
+        let compiler = builder.compiler_for(builder.top_stage, host, host);
         let test_kind = builder.kind.into();
         let krate = builder.crate_paths[&run.path];
 
@@ -2288,7 +2288,7 @@ impl Step for Distcheck {
     type Output = ();
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("distcheck")
+        run.alias("distcheck")
     }
 
     fn make_run(run: RunConfig<'_>) {
index c7ea254c5b1d7ac6a242493b56ebcc5bb4c5fad1..3ee6a42d987a05385ee1f9156ea86e36ae668384 100644 (file)
@@ -234,7 +234,7 @@ fn run(self, builder: &Builder<'_>) {
     }
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("check-tools")
+        run.alias("check-tools")
     }
 
     fn make_run(run: RunConfig<'_>) {
index 5622422d50f52f7c38aaa1b794d3aa01d7b5fa70..173ee170c9f585ae79aab4c8f30cd5869231d0a2 100644 (file)
@@ -99,7 +99,7 @@ x--expand-yaml-anchors--remove:
         run: git config --global core.autocrlf false
 
       - name: checkout the source code
-        uses: actions/checkout@v2
+        uses: actions/checkout@v3
         with:
           fetch-depth: 2
 
@@ -703,7 +703,7 @@ jobs:
     if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'rust-lang-ci/rust'
     steps:
       - name: checkout the source code
-        uses: actions/checkout@v2
+        uses: actions/checkout@v3
         with:
           fetch-depth: 2
 
index ea90bbaf53ba64ef4e2da9ac2352b298aec6bec8..de0dbffc5812fd885700874e8d258dd334733ac4 160000 (submodule)
@@ -1 +1 @@
-Subproject commit ea90bbaf53ba64ef4e2da9ac2352b298aec6bec8
+Subproject commit de0dbffc5812fd885700874e8d258dd334733ac4
index a6de8b6e3ea5d4f0de8b7b9a7e5c1405dc2c2ddb..f7cefbb995eec8c6148f213235e9e2e03268e775 160000 (submodule)
@@ -1 +1 @@
-Subproject commit a6de8b6e3ea5d4f0de8b7b9a7e5c1405dc2c2ddb
+Subproject commit f7cefbb995eec8c6148f213235e9e2e03268e775
index 11f1165e8a2f5840467e748c8108dc53c948ee9a..c7d8467ca9158da58ef295ae65dbf00a308752d9 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 11f1165e8a2f5840467e748c8108dc53c948ee9a
+Subproject commit c7d8467ca9158da58ef295ae65dbf00a308752d9
index c97d14fa6fed0baa9255432b8a93cb70614f80e3..b5f6c2362baf932db9440fbfcb509b309237ee85 160000 (submodule)
@@ -1 +1 @@
-Subproject commit c97d14fa6fed0baa9255432b8a93cb70614f80e3
+Subproject commit b5f6c2362baf932db9440fbfcb509b309237ee85
index ec954f35eedf592cd173b21c05a7f80a65b61d8a..44a80e8d8bfc5881c9bd69a2cb3a570776ee4181 160000 (submodule)
@@ -1 +1 @@
-Subproject commit ec954f35eedf592cd173b21c05a7f80a65b61d8a
+Subproject commit 44a80e8d8bfc5881c9bd69a2cb3a570776ee4181
index 155126b1d2e2cb01ddb1d7ba9489b90d7cd173ad..043e60f4f191651e9f8bf52fa32df14defbb23d9 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 155126b1d2e2cb01ddb1d7ba9489b90d7cd173ad
+Subproject commit 043e60f4f191651e9f8bf52fa32df14defbb23d9
index 2cf26603273844f696a3b64923a0c1946f603f7b..952d8ef48fe57d15cb61e613aa3cad12e802b88b 100644 (file)
 - [Platform Support](platform-support.md)
     - [Template for target-specific documentation](platform-support/TEMPLATE.md)
     - [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md)
+    - [aarch64-unknown-none-hermitkernel](platform-support/aarch64-unknown-none-hermitkernel.md)
     - [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md)
     - [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md)
     - [\*-kmc-solid_\*](platform-support/kmc-solid.md)
+    - [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md)
+    - [mips64-openwrt-linux-musl](platform-support/mips64-openwrt-linux-musl.md)
     - [*-unknown-openbsd](platform-support/openbsd.md)
-    - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
     - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
+    - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
 - [Target Tier Policy](target-tier-policy.md)
 - [Targets](targets/index.md)
     - [Built-in Targets](targets/built-in.md)
index b3c4a52c414b2b746bcf74c847c0aa40cc53e135..12ac575210aa3df68522649f598ec1be30253273 100644 (file)
@@ -248,9 +248,9 @@ target | std | host | notes
 `i686-uwp-windows-gnu` | ? |  |
 `i686-uwp-windows-msvc` | ? |  |
 `i686-wrs-vxworks` | ? |  |
-`m68k-unknown-linux-gnu` | ? |  | Motorola 680x0 Linux
+[`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? |  | Motorola 680x0 Linux
 `mips-unknown-linux-uclibc` | ✓ |  | MIPS Linux with uClibc
-`mips64-openwrt-linux-musl` | ? |  | MIPS64 for OpenWrt Linux MUSL
+[`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? |  | MIPS64 for OpenWrt Linux MUSL
 `mipsel-sony-psp` | * |  | MIPS (LE) Sony PlayStation Portable (PSP)
 `mipsel-unknown-linux-uclibc` | ✓ |  | MIPS (LE) Linux with uClibc
 `mipsel-unknown-none` | * |  | Bare MIPS (LE) softfloat
diff --git a/src/doc/unstable-book/src/compiler-flags/extern-location.md b/src/doc/unstable-book/src/compiler-flags/extern-location.md
deleted file mode 100644 (file)
index 1c80d54..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-# `extern-location`
-
-MCP for this feature: [#303]
-
-[#303]: https://github.com/rust-lang/compiler-team/issues/303
-
-------------------------
-
-The `unused-extern-crates` lint reports when a crate was specified on the rustc
-command-line with `--extern name=path` but no symbols were referenced in it.
-This is useful to know, but it's hard to map that back to a specific place a user
-or tool could fix (ie, to remove the unused dependency).
-
-The `--extern-location` flag allows the build system to associate a location with
-the `--extern` option, which is then emitted as part of the diagnostics. This location
-is abstract and just round-tripped through rustc; the compiler never attempts to
-interpret it in any way.
-
-There are two supported forms of location: a bare string, or a blob of json:
-- `--extern-location foo=raw:Makefile:123` would associate the raw string `Makefile:123`
-- `--extern-location 'bar=json:{"target":"//my_project:library","dep":"//common:serde"}` would
-  associate the json structure with `--extern bar=<path>`, indicating which dependency of
-  which rule introduced the unused extern crate.
-
-This primarily intended to be used with tooling - for example a linter which can automatically
-remove unused dependencies - rather than being directly presented to users.
-
-`raw` locations are presented as part of the normal rendered diagnostics and included in
-the json form. `json` locations are only included in the json form of diagnostics,
-as a `tool_metadata` field. For `raw` locations `tool_metadata` is simply a json string,
-whereas `json` allows the rustc invoker to fully control its form and content.
index e75f1aea992294db3a73c571094a7b1cc0b1ce0d..b15f5ee66aba1eaf8448b3116f30488a250f4197 100644 (file)
@@ -7,7 +7,7 @@ The tracking issue for this feature is: [#43781]
 The `doc_cfg` feature allows an API be documented as only available in some specific platforms.
 This attribute has two effects:
 
-1. In the annotated item's documentation, there will be a message saying "This is supported on
+1. In the annotated item's documentation, there will be a message saying "Available on
     (platform) only".
 
 2. The item's doc-tests will only run on the specific platform.
index 33d26db547efc8c2ceed8353904b81652a09bcec..0a52b8c976f6ad87bb0c0482b36736ad6e813b55 100644 (file)
@@ -12,8 +12,10 @@ FIRST_FIELD = "__1"
 def unwrap_unique_or_non_null(unique_or_nonnull):
     # BACKCOMPAT: rust 1.32
     # https://github.com/rust-lang/rust/commit/7a0911528058e87d22ea305695f4047572c5e067
+    # BACKCOMPAT: rust 1.60
+    # https://github.com/rust-lang/rust/commit/2a91eeac1a2d27dd3de1bf55515d765da20fd86f
     ptr = unique_or_nonnull["pointer"]
-    return ptr if ptr.type.code == gdb.TYPE_CODE_PTR else ptr[ZERO_FIELD]
+    return ptr if ptr.type.code == gdb.TYPE_CODE_PTR else ptr[ptr.type.fields()[0]]
 
 
 class EnumProvider:
index 6bb235b2c8347cddbd461e9d6316b92b8dfb7291..269b6868e29f9a9c4bed287ba3d28c9ba4058714 100644 (file)
@@ -285,6 +285,11 @@ def flatten(node):
     return ''.join(acc)
 
 
+def make_xml(text):
+    xml = ET.XML('<xml>%s</xml>' % text)
+    return xml
+
+
 def normalize_xpath(path):
     path = path.replace("{{channel}}", channel)
     if path.startswith('//'):
@@ -401,7 +406,7 @@ def get_tree_count(tree, path):
     return len(tree.findall(path))
 
 
-def check_snapshot(snapshot_name, tree, normalize_to_text):
+def check_snapshot(snapshot_name, actual_tree, normalize_to_text):
     assert rust_test_path.endswith('.rs')
     snapshot_path = '{}.{}.{}'.format(rust_test_path[:-3], snapshot_name, 'html')
     try:
@@ -414,11 +419,19 @@ def check_snapshot(snapshot_name, tree, normalize_to_text):
             raise FailedCheck('No saved snapshot value')
 
     if not normalize_to_text:
-        actual_str = ET.tostring(tree).decode('utf-8')
+        actual_str = ET.tostring(actual_tree).decode('utf-8')
     else:
-        actual_str = flatten(tree)
+        actual_str = flatten(actual_tree)
+
+    # Conditions:
+    #  1. Is --bless
+    #  2. Are actual and expected tree different
+    #  3. Are actual and expected text different
+    if not expected_str \
+        or (not normalize_to_text and \
+            not compare_tree(make_xml(actual_str), make_xml(expected_str), stderr)) \
+        or (normalize_to_text and actual_str != expected_str):
 
-    if expected_str != actual_str:
         if bless:
             with open(snapshot_path, 'w') as snapshot_file:
                 snapshot_file.write(actual_str)
@@ -430,6 +443,59 @@ def check_snapshot(snapshot_name, tree, normalize_to_text):
             print()
             raise FailedCheck('Actual snapshot value is different than expected')
 
+
+# Adapted from https://github.com/formencode/formencode/blob/3a1ba9de2fdd494dd945510a4568a3afeddb0b2e/formencode/doctest_xml_compare.py#L72-L120
+def compare_tree(x1, x2, reporter=None):
+    if x1.tag != x2.tag:
+        if reporter:
+            reporter('Tags do not match: %s and %s' % (x1.tag, x2.tag))
+        return False
+    for name, value in x1.attrib.items():
+        if x2.attrib.get(name) != value:
+            if reporter:
+                reporter('Attributes do not match: %s=%r, %s=%r'
+                         % (name, value, name, x2.attrib.get(name)))
+            return False
+    for name in x2.attrib:
+        if name not in x1.attrib:
+            if reporter:
+                reporter('x2 has an attribute x1 is missing: %s'
+                         % name)
+            return False
+    if not text_compare(x1.text, x2.text):
+        if reporter:
+            reporter('text: %r != %r' % (x1.text, x2.text))
+        return False
+    if not text_compare(x1.tail, x2.tail):
+        if reporter:
+            reporter('tail: %r != %r' % (x1.tail, x2.tail))
+        return False
+    cl1 = list(x1)
+    cl2 = list(x2)
+    if len(cl1) != len(cl2):
+        if reporter:
+            reporter('children length differs, %i != %i'
+                     % (len(cl1), len(cl2)))
+        return False
+    i = 0
+    for c1, c2 in zip(cl1, cl2):
+        i += 1
+        if not compare_tree(c1, c2, reporter=reporter):
+            if reporter:
+                reporter('children %i do not match: %s'
+                         % (i, c1.tag))
+            return False
+    return True
+
+
+def text_compare(t1, t2):
+    if not t1 and not t2:
+        return True
+    if t1 == '*' or t2 == '*':
+        return True
+    return (t1 or '').strip() == (t2 or '').strip()
+
+
 def stderr(*args):
     if sys.version_info.major < 3:
         file = codecs.getwriter('utf-8')(sys.stderr)
index 86dcc335e3cbfdcf2daab64d64fe5810b22f1cbd..35ac07f0db763c860c0d19eb276508ee5c74a699 100644 (file)
@@ -63,6 +63,8 @@ class ValueBuilder:
 def unwrap_unique_or_non_null(unique_or_nonnull):
     # BACKCOMPAT: rust 1.32
     # https://github.com/rust-lang/rust/commit/7a0911528058e87d22ea305695f4047572c5e067
+    # BACKCOMPAT: rust 1.60
+    # https://github.com/rust-lang/rust/commit/2a91eeac1a2d27dd3de1bf55515d765da20fd86f
     ptr = unique_or_nonnull.GetChildMemberWithName("pointer")
     return ptr if ptr.TypeIsPointerType() else ptr.GetChildAtIndex(0)
 
@@ -268,7 +270,9 @@ class StdVecSyntheticProvider:
     struct RawVec<T> { ptr: Unique<T>, cap: usize, ... }
     rust 1.31.1: struct Unique<T: ?Sized> { pointer: NonZero<*const T>, ... }
     rust 1.33.0: struct Unique<T: ?Sized> { pointer: *const T, ... }
+    rust 1.62.0: struct Unique<T: ?Sized> { pointer: NonNull<T>, ... }
     struct NonZero<T>(T)
+    struct NonNull<T> { pointer: *const T }
     """
 
     def __init__(self, valobj, dict):
index d001f40fccbc7d573c526511f5772f162bc2403e..83ca8ed932e46bc7045cd082f0d981d25f648664 100644 (file)
@@ -7,7 +7,7 @@
       <Item Name="[capacity]" ExcludeView="simple">buf.cap</Item>
       <ArrayItems>
         <Size>len</Size>
-        <ValuePointer>buf.ptr.pointer</ValuePointer>
+        <ValuePointer>buf.ptr.pointer.pointer</ValuePointer>
       </ArrayItems>
     </Expand>
   </Type>
@@ -24,7 +24,7 @@
           <If Condition="i == head">
             <Break/>
           </If>
-          <Item>buf.ptr.pointer[i]</Item>
+          <Item>buf.ptr.pointer.pointer[i]</Item>
           <Exec>i = (i + 1 == buf.cap ? 0 : i + 1)</Exec>
         </Loop>
       </CustomListItems>
     </Expand>
   </Type>
   <Type Name="alloc::string::String">
-    <DisplayString>{(char*)vec.buf.ptr.pointer,[vec.len]s8}</DisplayString>
-    <StringView>(char*)vec.buf.ptr.pointer,[vec.len]s8</StringView>
+    <DisplayString>{(char*)vec.buf.ptr.pointer.pointer,[vec.len]s8}</DisplayString>
+    <StringView>(char*)vec.buf.ptr.pointer.pointer,[vec.len]s8</StringView>
     <Expand>
       <Item Name="[len]" ExcludeView="simple">vec.len</Item>
       <Item Name="[capacity]" ExcludeView="simple">vec.buf.cap</Item>
       <Synthetic Name="[chars]">
-        <DisplayString>{(char*)vec.buf.ptr.pointer,[vec.len]s8}</DisplayString>
+        <DisplayString>{(char*)vec.buf.ptr.pointer.pointer,[vec.len]s8}</DisplayString>
         <Expand>
           <ArrayItems>
             <Size>vec.len</Size>
-            <ValuePointer>(char*)vec.buf.ptr.pointer</ValuePointer>
+            <ValuePointer>(char*)vec.buf.ptr.pointer.pointer</ValuePointer>
           </ArrayItems>
         </Expand>
       </Synthetic>
index fa8ee2d70bbab4a775a38ca7e401639b4f74b564..643590fc977870f1c89f83ccff373dc0f1f128bd 100644 (file)
   </Type>
 
   <Type Name="core::ptr::unique::Unique&lt;*&gt;">
-    <DisplayString>Unique({(void*)pointer}: {pointer})</DisplayString>
+    <DisplayString>Unique({(void*)pointer.pointer}: {pointer.pointer})</DisplayString>
     <Expand>
       <ExpandedItem>pointer</ExpandedItem>
     </Expand>
index eb2b9c848aa6f419870e9424428b03119963585f..4371b9953181779ef464e5839af6ea13b2b720f1 100644 (file)
   </Type>
 
   <Type Name="std::ffi::os_str::OsString">
-    <DisplayString>{(char*)inner.inner.bytes.buf.ptr.pointer,[inner.inner.bytes.len]}</DisplayString>
+    <DisplayString>{(char*)inner.inner.bytes.buf.ptr.pointer.pointer,[inner.inner.bytes.len]}</DisplayString>
     <Expand>
       <Synthetic Name="[chars]">
-        <DisplayString>{(char*)inner.inner.bytes.buf.ptr.pointer,[inner.inner.bytes.len]}</DisplayString>
+        <DisplayString>{(char*)inner.inner.bytes.buf.ptr.pointer.pointer,[inner.inner.bytes.len]}</DisplayString>
         <Expand>
           <ArrayItems>
             <Size>inner.inner.bytes.len</Size>
-            <ValuePointer>(char*)inner.inner.bytes.buf.ptr.pointer</ValuePointer>
+            <ValuePointer>(char*)inner.inner.bytes.buf.ptr.pointer.pointer</ValuePointer>
           </ArrayItems>
         </Expand>
       </Synthetic>
index cc5c583bea8e25d81dda1b114b6e96a04dffeedf..21efd040663b8aa9e848aa6ff3456f1fa864fa89 100644 (file)
@@ -22,6 +22,7 @@ regex = "1"
 rustdoc-json-types = { path = "../rustdoc-json-types" }
 tracing = "0.1"
 tracing-tree = "0.2.0"
+once_cell = "1.10.0"
 
 [dependencies.tracing-subscriber]
 version = "0.3.3"
index 62f3527525e0e49bf2bbf32841683d6e2bb2028a..fffd94992093b22d9cb1a20555bc90efb98ee13d 100644 (file)
@@ -116,7 +116,7 @@ fn generate_for_trait(
             name: None,
             attrs: Default::default(),
             visibility: Inherited,
-            def_id: ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
+            item_id: ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
             kind: box ImplItem(Impl {
                 unsafety: hir::Unsafety::Normal,
                 generics: new_generics,
index 6f4b87750ff858d1c6cba411e1bc64ddfc3b2332..f0d87f7ce4cd582908f9a7211ea4b520f5fff928 100644 (file)
@@ -105,7 +105,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                         name: None,
                         attrs: Default::default(),
                         visibility: Inherited,
-                        def_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
+                        item_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
                         kind: box ImplItem(Impl {
                             unsafety: hir::Unsafety::Normal,
                             generics: clean_ty_generics(
index b72d2624177552907a01c2d70a1909e5170cb4e9..0d213a5a2dee9d201e62c8a1315a8346dd41a8b6 100644 (file)
@@ -171,11 +171,8 @@ pub(crate) fn render_short_html(&self) -> String {
     pub(crate) fn render_long_html(&self) -> String {
         let on = if self.should_use_with_in_description() { "with" } else { "on" };
 
-        let mut msg = format!(
-            "This is supported {} <strong>{}</strong>",
-            on,
-            Display(self, Format::LongHtml)
-        );
+        let mut msg =
+            format!("Available {on} <strong>{}</strong>", Display(self, Format::LongHtml));
         if self.should_append_only_to_description() {
             msg.push_str(" only");
         }
@@ -187,7 +184,7 @@ pub(crate) fn render_long_html(&self) -> String {
     pub(crate) fn render_long_plain(&self) -> String {
         let on = if self.should_use_with_in_description() { "with" } else { "on" };
 
-        let mut msg = format!("This is supported {} {}", on, Display(self, Format::LongPlain));
+        let mut msg = format!("Available {on} {}", Display(self, Format::LongPlain));
         if self.should_append_only_to_description() {
             msg.push_str(" only");
         }
index 275d1b3ebd938add90368a1cee9e59077a29d5cf..ece3fcb18b6f357c5605a6c2d9237802df66f1a5 100644 (file)
@@ -359,81 +359,73 @@ fn test_render_short_html() {
 #[test]
 fn test_render_long_html() {
     create_default_session_globals_then(|| {
-        assert_eq!(
-            word_cfg("unix").render_long_html(),
-            "This is supported on <strong>Unix</strong> only."
-        );
+        assert_eq!(word_cfg("unix").render_long_html(), "Available on <strong>Unix</strong> only.");
         assert_eq!(
             name_value_cfg("target_os", "macos").render_long_html(),
-            "This is supported on <strong>macOS</strong> only."
+            "Available on <strong>macOS</strong> only."
         );
         assert_eq!(
             name_value_cfg("target_os", "wasi").render_long_html(),
-            "This is supported on <strong>WASI</strong> only."
+            "Available on <strong>WASI</strong> only."
         );
         assert_eq!(
             name_value_cfg("target_pointer_width", "16").render_long_html(),
-            "This is supported on <strong>16-bit</strong> only."
+            "Available on <strong>16-bit</strong> only."
         );
         assert_eq!(
             name_value_cfg("target_endian", "little").render_long_html(),
-            "This is supported on <strong>little-endian</strong> only."
+            "Available on <strong>little-endian</strong> only."
         );
         assert_eq!(
             (!word_cfg("windows")).render_long_html(),
-            "This is supported on <strong>non-Windows</strong> only."
+            "Available on <strong>non-Windows</strong> only."
         );
         assert_eq!(
             (word_cfg("unix") & word_cfg("windows")).render_long_html(),
-            "This is supported on <strong>Unix and Windows</strong> only."
+            "Available on <strong>Unix and Windows</strong> only."
         );
         assert_eq!(
             (word_cfg("unix") | word_cfg("windows")).render_long_html(),
-            "This is supported on <strong>Unix or Windows</strong> only."
+            "Available on <strong>Unix or Windows</strong> only."
         );
         assert_eq!(
             (word_cfg("unix") & word_cfg("windows") & word_cfg("debug_assertions"))
                 .render_long_html(),
-            "This is supported on <strong>Unix and Windows and debug-assertions enabled\
-             </strong> only."
+            "Available on <strong>Unix and Windows and debug-assertions enabled</strong> only."
         );
         assert_eq!(
             (word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions"))
                 .render_long_html(),
-            "This is supported on <strong>Unix or Windows or debug-assertions enabled\
-             </strong> only."
+            "Available on <strong>Unix or Windows or debug-assertions enabled</strong> only."
         );
         assert_eq!(
             (!(word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions")))
                 .render_long_html(),
-            "This is supported on <strong>neither Unix nor Windows nor debug-assertions \
-             enabled</strong>."
+            "Available on <strong>neither Unix nor Windows nor debug-assertions enabled</strong>."
         );
         assert_eq!(
             ((word_cfg("unix") & name_value_cfg("target_arch", "x86_64"))
                 | (word_cfg("windows") & name_value_cfg("target_pointer_width", "64")))
             .render_long_html(),
-            "This is supported on <strong>Unix and x86-64, or Windows and 64-bit</strong> only."
+            "Available on <strong>Unix and x86-64, or Windows and 64-bit</strong> only."
         );
         assert_eq!(
             (!(word_cfg("unix") & word_cfg("windows"))).render_long_html(),
-            "This is supported on <strong>not (Unix and Windows)</strong>."
+            "Available on <strong>not (Unix and Windows)</strong>."
         );
         assert_eq!(
             ((word_cfg("debug_assertions") | word_cfg("windows")) & word_cfg("unix"))
                 .render_long_html(),
-            "This is supported on <strong>(debug-assertions enabled or Windows) and Unix\
-             </strong> only."
+            "Available on <strong>(debug-assertions enabled or Windows) and Unix</strong> only."
         );
         assert_eq!(
             name_value_cfg("target_feature", "sse2").render_long_html(),
-            "This is supported with <strong>target feature <code>sse2</code></strong> only."
+            "Available with <strong>target feature <code>sse2</code></strong> only."
         );
         assert_eq!(
             (name_value_cfg("target_arch", "x86_64") & name_value_cfg("target_feature", "sse2"))
                 .render_long_html(),
-            "This is supported on <strong>x86-64 and target feature \
-             <code>sse2</code></strong> only."
+            "Available on <strong>x86-64 and target feature <code>sse2</code></strong> only."
         );
     })
 }
index 33db6583125efbc9d03ecf9fea4a9244042d72a3..261eb39bf723d3aaf22da9a1c3238fe3dab8dbdf 100644 (file)
@@ -534,7 +534,7 @@ fn build_module(
                 items.push(clean::Item {
                     name: None,
                     attrs: box clean::Attributes::default(),
-                    def_id: ItemId::Primitive(prim_ty, did.krate),
+                    item_id: ItemId::Primitive(prim_ty, did.krate),
                     visibility: clean::Public,
                     kind: box clean::ImportItem(clean::Import::new_simple(
                         item.ident.name,
index a6763d2827cec0fc486919126d422ac006d8a83c..a070cef227252b5b3bf25001bba3fc2ebd82f249 100644 (file)
@@ -15,7 +15,7 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
-use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
 use rustc_middle::middle::resolve_lifetime as rl;
 use rustc_middle::ty::fold::TypeFolder;
@@ -1975,7 +1975,7 @@ fn clean_extern_crate(
     // this is the ID of the `extern crate` statement
     let cnum = cx.tcx.extern_mod_stmt_cnum(krate.def_id).unwrap_or(LOCAL_CRATE);
     // this is the ID of the crate itself
-    let crate_def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
+    let crate_def_id = cnum.as_def_id();
     let attrs = cx.tcx.hir().attrs(krate.hir_id());
     let ty_vis = cx.tcx.visibility(krate.def_id);
     let please_inline = ty_vis.is_public()
@@ -2009,7 +2009,7 @@ fn clean_extern_crate(
     vec![Item {
         name: Some(name),
         attrs: box attrs.clean(cx),
-        def_id: crate_def_id.into(),
+        item_id: crate_def_id.into(),
         visibility: ty_vis.clean(cx),
         kind: box ExternCrateItem { src: orig_name },
         cfg: attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
@@ -2094,7 +2094,7 @@ fn clean_use_statement(
     } else {
         if inline_attr.is_none() {
             if let Res::Def(DefKind::Mod, did) = path.res {
-                if !did.is_local() && did.index == CRATE_DEF_INDEX {
+                if !did.is_local() && did.is_crate_root() {
                     // if we're `pub use`ing an extern crate root, don't inline it unless we
                     // were specifically asked for it
                     denied = true;
index d2abfc35b932cfa1f3e6be1ef946ec737b985cb4..2b65b8f910c7069b74c23d24c4847a5240898dc8 100644 (file)
@@ -1,13 +1,11 @@
 use std::cell::RefCell;
 use std::default::Default;
-use std::fmt;
 use std::hash::Hash;
-use std::iter;
 use std::lazy::SyncOnceCell as OnceCell;
 use std::path::PathBuf;
 use std::rc::Rc;
 use std::sync::Arc;
-use std::vec;
+use std::{cmp, fmt, iter};
 
 use arrayvec::ArrayVec;
 
@@ -20,7 +18,7 @@
 use rustc_data_structures::thin_vec::ThinVec;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{BodyId, Mutability};
 use rustc_index::vec::IndexVec;
@@ -55,6 +53,9 @@
 };
 crate use self::Visibility::{Inherited, Public};
 
+#[cfg(test)]
+mod tests;
+
 crate type ItemIdSet = FxHashSet<ItemId>;
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
@@ -104,14 +105,6 @@ impl ItemId {
             ItemId::Primitive(_, krate) => krate,
         }
     }
-
-    #[inline]
-    crate fn index(self) -> Option<DefIndex> {
-        match self {
-            ItemId::DefId(id) => Some(id.index),
-            _ => None,
-        }
-    }
 }
 
 impl From<DefId> for ItemId {
@@ -160,7 +153,7 @@ impl ExternalCrate {
 
     #[inline]
     crate fn def_id(&self) -> DefId {
-        DefId { krate: self.crate_num, index: CRATE_DEF_INDEX }
+        self.crate_num.as_def_id()
     }
 
     crate fn src(&self, tcx: TyCtxt<'_>) -> FileName {
@@ -217,7 +210,7 @@ fn to_remote(url: impl ToString) -> ExternalLocation {
 
         // Failing that, see if there's an attribute specifying where to find this
         // external crate
-        let did = DefId { krate: self.crate_num, index: CRATE_DEF_INDEX };
+        let did = self.crate_num.as_def_id();
         tcx.get_attrs(did)
             .lists(sym::doc)
             .filter(|a| a.has_name(sym::html_root_url))
@@ -366,7 +359,7 @@ fn to_remote(url: impl ToString) -> ExternalLocation {
     /// Information about this item that is specific to what kind of item it is.
     /// E.g., struct vs enum vs function.
     crate kind: Box<ItemKind>,
-    crate def_id: ItemId,
+    crate item_id: ItemId,
 
     crate cfg: Option<Arc<Cfg>>,
 }
@@ -380,7 +373,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut fmt = f.debug_struct("Item");
         fmt.field("name", &self.name)
             .field("visibility", &self.visibility)
-            .field("def_id", &self.def_id);
+            .field("item_id", &self.item_id);
         // allow printing the full item if someone really wants to
         if alternate {
             fmt.field("attrs", &self.attrs).field("kind", &self.kind).field("cfg", &self.cfg);
@@ -408,19 +401,19 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 impl Item {
     crate fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<Stability> {
-        self.def_id.as_def_id().and_then(|did| tcx.lookup_stability(did))
+        self.item_id.as_def_id().and_then(|did| tcx.lookup_stability(did))
     }
 
     crate fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<ConstStability> {
-        self.def_id.as_def_id().and_then(|did| tcx.lookup_const_stability(did))
+        self.item_id.as_def_id().and_then(|did| tcx.lookup_const_stability(did))
     }
 
     crate fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
-        self.def_id.as_def_id().and_then(|did| tcx.lookup_deprecation(did))
+        self.item_id.as_def_id().and_then(|did| tcx.lookup_deprecation(did))
     }
 
     crate fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
-        self.def_id.as_def_id().map(|did| tcx.get_attrs(did).inner_docs()).unwrap_or(false)
+        self.item_id.as_def_id().map(|did| tcx.get_attrs(did).inner_docs()).unwrap_or(false)
     }
 
     crate fn span(&self, tcx: TyCtxt<'_>) -> Span {
@@ -432,14 +425,14 @@ impl Item {
             ItemKind::ModuleItem(Module { span, .. }) => *span,
             ItemKind::ImplItem(Impl { kind: ImplKind::Auto, .. }) => Span::dummy(),
             ItemKind::ImplItem(Impl { kind: ImplKind::Blanket(_), .. }) => {
-                if let ItemId::Blanket { impl_id, .. } = self.def_id {
+                if let ItemId::Blanket { impl_id, .. } = self.item_id {
                     rustc_span(impl_id, tcx)
                 } else {
                     panic!("blanket impl item has non-blanket ID")
                 }
             }
             _ => {
-                self.def_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(Span::dummy)
+                self.item_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(Span::dummy)
             }
         }
     }
@@ -503,7 +496,7 @@ impl Item {
             cx.tcx.visibility(def_id).clean(cx)
         };
 
-        Item { def_id: def_id.into(), kind: box kind, name, attrs, visibility, cfg }
+        Item { item_id: def_id.into(), kind: box kind, name, attrs, visibility, cfg }
     }
 
     /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
@@ -517,7 +510,7 @@ impl Item {
 
         cx.cache()
             .intra_doc_links
-            .get(&self.def_id)
+            .get(&self.item_id)
             .map_or(&[][..], |v| v.as_slice())
             .iter()
             .filter_map(|ItemLink { link: s, link_text, did, ref fragment }| {
@@ -547,7 +540,7 @@ impl Item {
     crate fn link_names(&self, cache: &Cache) -> Vec<RenderedLink> {
         cache
             .intra_doc_links
-            .get(&self.def_id)
+            .get(&self.item_id)
             .map_or(&[][..], |v| v.as_slice())
             .iter()
             .map(|ItemLink { link: s, link_text, .. }| RenderedLink {
@@ -559,7 +552,7 @@ impl Item {
     }
 
     crate fn is_crate(&self) -> bool {
-        self.is_mod() && self.def_id.as_def_id().map_or(false, |did| did.index == CRATE_DEF_INDEX)
+        self.is_mod() && self.item_id.as_def_id().map_or(false, |did| did.is_crate_root())
     }
     crate fn is_mod(&self) -> bool {
         self.type_() == ItemType::Module
@@ -695,7 +688,7 @@ fn build_fn_header(
         }
         let header = match *self.kind {
             ItemKind::ForeignFunctionItem(_) => {
-                let abi = tcx.fn_sig(self.def_id.as_def_id().unwrap()).abi();
+                let abi = tcx.fn_sig(self.item_id.as_def_id().unwrap()).abi();
                 hir::FnHeader {
                     unsafety: if abi == Abi::RustIntrinsic {
                         intrinsic_operation_unsafety(self.name.unwrap())
@@ -708,11 +701,11 @@ fn build_fn_header(
                 }
             }
             ItemKind::FunctionItem(_) | ItemKind::MethodItem(_, _) => {
-                let def_id = self.def_id.as_def_id().unwrap();
+                let def_id = self.item_id.as_def_id().unwrap();
                 build_fn_header(def_id, tcx, tcx.asyncness(def_id))
             }
             ItemKind::TyMethodItem(_) => {
-                build_fn_header(self.def_id.as_def_id().unwrap(), tcx, hir::IsAsync::NotAsync)
+                build_fn_header(self.item_id.as_def_id().unwrap(), tcx, hir::IsAsync::NotAsync)
             }
             _ => return None,
         };
@@ -1036,6 +1029,86 @@ fn add_doc_fragment(out: &mut String, frag: &DocFragment) {
     acc
 }
 
+/// Removes excess indentation on comments in order for the Markdown
+/// to be parsed correctly. This is necessary because the convention for
+/// writing documentation is to provide a space between the /// or //! marker
+/// and the doc text, but Markdown is whitespace-sensitive. For example,
+/// a block of text with four-space indentation is parsed as a code block,
+/// so if we didn't unindent comments, these list items
+///
+/// /// A list:
+/// ///
+/// ///    - Foo
+/// ///    - Bar
+///
+/// would be parsed as if they were in a code block, which is likely not what the user intended.
+fn unindent_doc_fragments(docs: &mut Vec<DocFragment>) {
+    // `add` is used in case the most common sugared doc syntax is used ("/// "). The other
+    // fragments kind's lines are never starting with a whitespace unless they are using some
+    // markdown formatting requiring it. Therefore, if the doc block have a mix between the two,
+    // we need to take into account the fact that the minimum indent minus one (to take this
+    // whitespace into account).
+    //
+    // For example:
+    //
+    // /// hello!
+    // #[doc = "another"]
+    //
+    // In this case, you want "hello! another" and not "hello!  another".
+    let add = if docs.windows(2).any(|arr| arr[0].kind != arr[1].kind)
+        && docs.iter().any(|d| d.kind == DocFragmentKind::SugaredDoc)
+    {
+        // In case we have a mix of sugared doc comments and "raw" ones, we want the sugared one to
+        // "decide" how much the minimum indent will be.
+        1
+    } else {
+        0
+    };
+
+    // `min_indent` is used to know how much whitespaces from the start of each lines must be
+    // removed. Example:
+    //
+    // ///     hello!
+    // #[doc = "another"]
+    //
+    // In here, the `min_indent` is 1 (because non-sugared fragment are always counted with minimum
+    // 1 whitespace), meaning that "hello!" will be considered a codeblock because it starts with 4
+    // (5 - 1) whitespaces.
+    let Some(min_indent) = docs
+        .iter()
+        .map(|fragment| {
+            fragment.doc.as_str().lines().fold(usize::MAX, |min_indent, line| {
+                if line.chars().all(|c| c.is_whitespace()) {
+                    min_indent
+                } else {
+                    // Compare against either space or tab, ignoring whether they are
+                    // mixed or not.
+                    let whitespace = line.chars().take_while(|c| *c == ' ' || *c == '\t').count();
+                    cmp::min(min_indent, whitespace)
+                        + if fragment.kind == DocFragmentKind::SugaredDoc { 0 } else { add }
+                }
+            })
+        })
+        .min()
+    else {
+        return;
+    };
+
+    for fragment in docs {
+        if fragment.doc == kw::Empty {
+            continue;
+        }
+
+        let min_indent = if fragment.kind != DocFragmentKind::SugaredDoc && min_indent > 0 {
+            min_indent - add
+        } else {
+            min_indent
+        };
+
+        fragment.indent = min_indent;
+    }
+}
+
 /// A link that has not yet been rendered.
 ///
 /// This link will be turned into a rendered link by [`Item::links`].
@@ -1097,35 +1170,37 @@ impl Attributes {
         attrs: &[ast::Attribute],
         additional_attrs: Option<(&[ast::Attribute], DefId)>,
     ) -> Attributes {
-        let mut doc_strings: Vec<DocFragment> = vec![];
-        let clean_attr = |(attr, parent_module): (&ast::Attribute, Option<DefId>)| {
-            if let Some((value, kind)) = attr.doc_str_and_comment_kind() {
-                trace!("got doc_str={:?}", value);
-                let value = beautify_doc_string(value, kind);
+        // Additional documentation should be shown before the original documentation.
+        let attrs1 = additional_attrs
+            .into_iter()
+            .flat_map(|(attrs, def_id)| attrs.iter().map(move |attr| (attr, Some(def_id))));
+        let attrs2 = attrs.iter().map(|attr| (attr, None));
+        Attributes::from_ast_iter(attrs1.chain(attrs2), false)
+    }
+
+    crate fn from_ast_iter<'a>(
+        attrs: impl Iterator<Item = (&'a ast::Attribute, Option<DefId>)>,
+        doc_only: bool,
+    ) -> Attributes {
+        let mut doc_strings = Vec::new();
+        let mut other_attrs = Vec::new();
+        for (attr, parent_module) in attrs {
+            if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() {
+                trace!("got doc_str={doc_str:?}");
+                let doc = beautify_doc_string(doc_str, comment_kind);
                 let kind = if attr.is_doc_comment() {
                     DocFragmentKind::SugaredDoc
                 } else {
                     DocFragmentKind::RawDoc
                 };
-
-                let frag =
-                    DocFragment { span: attr.span, doc: value, kind, parent_module, indent: 0 };
-
-                doc_strings.push(frag);
-
-                None
-            } else {
-                Some(attr.clone())
+                let fragment = DocFragment { span: attr.span, doc, kind, parent_module, indent: 0 };
+                doc_strings.push(fragment);
+            } else if !doc_only {
+                other_attrs.push(attr.clone());
             }
-        };
+        }
 
-        // Additional documentation should be shown before the original documentation
-        let other_attrs = additional_attrs
-            .into_iter()
-            .flat_map(|(attrs, id)| attrs.iter().map(move |attr| (attr, Some(id))))
-            .chain(attrs.iter().map(|attr| (attr, None)))
-            .filter_map(clean_attr)
-            .collect();
+        unindent_doc_fragments(&mut doc_strings);
 
         Attributes { doc_strings, other_attrs }
     }
@@ -1146,23 +1221,17 @@ impl Attributes {
     }
 
     /// Return the doc-comments on this item, grouped by the module they came from.
-    ///
     /// The module can be different if this is a re-export with added documentation.
-    crate fn collapsed_doc_value_by_module_level(&self) -> FxHashMap<Option<DefId>, String> {
-        let mut ret = FxHashMap::default();
-        if self.doc_strings.len() == 0 {
-            return ret;
-        }
-        let last_index = self.doc_strings.len() - 1;
-
-        for (i, new_frag) in self.doc_strings.iter().enumerate() {
-            let out = ret.entry(new_frag.parent_module).or_default();
-            add_doc_fragment(out, new_frag);
-            if i == last_index {
-                out.pop();
-            }
+    ///
+    /// The last newline is not trimmed so the produced strings are reusable between
+    /// early and late doc link resolution regardless of their position.
+    crate fn prepare_to_doc_link_resolution(&self) -> FxHashMap<Option<DefId>, String> {
+        let mut res = FxHashMap::default();
+        for fragment in &self.doc_strings {
+            let out_str = res.entry(fragment.parent_module).or_default();
+            add_doc_fragment(out_str, fragment);
         }
-        ret
+        res
     }
 
     /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
diff --git a/src/librustdoc/clean/types/tests.rs b/src/librustdoc/clean/types/tests.rs
new file mode 100644 (file)
index 0000000..71eddf4
--- /dev/null
@@ -0,0 +1,70 @@
+use super::*;
+
+use crate::clean::collapse_doc_fragments;
+
+use rustc_span::create_default_session_globals_then;
+use rustc_span::source_map::DUMMY_SP;
+use rustc_span::symbol::Symbol;
+
+fn create_doc_fragment(s: &str) -> Vec<DocFragment> {
+    vec![DocFragment {
+        span: DUMMY_SP,
+        parent_module: None,
+        doc: Symbol::intern(s),
+        kind: DocFragmentKind::SugaredDoc,
+        indent: 0,
+    }]
+}
+
+#[track_caller]
+fn run_test(input: &str, expected: &str) {
+    create_default_session_globals_then(|| {
+        let mut s = create_doc_fragment(input);
+        unindent_doc_fragments(&mut s);
+        assert_eq!(collapse_doc_fragments(&s), expected);
+    });
+}
+
+#[test]
+fn should_unindent() {
+    run_test("    line1\n    line2", "line1\nline2");
+}
+
+#[test]
+fn should_unindent_multiple_paragraphs() {
+    run_test("    line1\n\n    line2", "line1\n\nline2");
+}
+
+#[test]
+fn should_leave_multiple_indent_levels() {
+    // Line 2 is indented another level beyond the
+    // base indentation and should be preserved
+    run_test("    line1\n\n        line2", "line1\n\n    line2");
+}
+
+#[test]
+fn should_ignore_first_line_indent() {
+    run_test("line1\n    line2", "line1\n    line2");
+}
+
+#[test]
+fn should_not_ignore_first_line_indent_in_a_single_line_para() {
+    run_test("line1\n\n    line2", "line1\n\n    line2");
+}
+
+#[test]
+fn should_unindent_tabs() {
+    run_test("\tline1\n\tline2", "line1\nline2");
+}
+
+#[test]
+fn should_trim_mixed_indentation() {
+    run_test("\t    line1\n\t    line2", "line1\nline2");
+    run_test("    \tline1\n    \tline2", "line1\nline2");
+}
+
+#[test]
+fn should_not_trim() {
+    run_test("\t    line1  \n\t    line2", "line1  \nline2");
+    run_test("    \tline1  \n    \tline2", "line1  \nline2");
+}
index fe6d680991f80f3e6652cf532a7fb4f065907ae6..abfc5b80a3ef0f8bda47c6216c36db0557fcd67c 100644 (file)
@@ -44,9 +44,9 @@
                 // `#[doc(masked)]` to the injected `extern crate` because it's unstable.
                 if it.is_extern_crate()
                     && (it.attrs.has_doc_flag(sym::masked)
-                        || cx.tcx.is_compiler_builtins(it.def_id.krate()))
+                        || cx.tcx.is_compiler_builtins(it.item_id.krate()))
                 {
-                    cx.cache.masked_crates.insert(it.def_id.krate());
+                    cx.cache.masked_crates.insert(it.item_id.krate());
                 }
             }
         }
index 81c11dc30cb58edae9ff907d5804ef08f87d577e..1db6064551cae362fc30911ba5528b00e052b1c7 100644 (file)
@@ -4,7 +4,7 @@
 use rustc_errors::emitter::{Emitter, EmitterWriter};
 use rustc_errors::json::JsonEmitter;
 use rustc_feature::UnstableFeatures;
-use rustc_hir::def::Res;
+use rustc_hir::def::{Namespace, Res};
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{HirId, Path, TraitCandidate};
 use crate::clean::{self, ItemId, TraitWithExtraInfo};
 use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions};
 use crate::formats::cache::Cache;
+use crate::passes::collect_intra_doc_links::PreprocessedMarkdownLink;
 use crate::passes::{self, Condition::*};
 
 crate use rustc_session::config::{DebuggingOptions, Input, Options};
 
 crate struct ResolverCaches {
+    crate markdown_links: Option<FxHashMap<String, Vec<PreprocessedMarkdownLink>>>,
+    crate doc_link_resolutions: FxHashMap<(Symbol, Namespace, DefId), Option<Res<NodeId>>>,
     /// Traits in scope for a given module.
     /// See `collect_intra_doc_links::traits_implemented_by` for more details.
     crate traits_in_scope: DefIdMap<Vec<TraitCandidate>>,
@@ -113,8 +116,8 @@ impl<'tcx> DocContext<'tcx> {
 
     /// Like `hir().local_def_id_to_hir_id()`, but skips calling it on fake DefIds.
     /// (This avoids a slice-index-out-of-bounds panic.)
-    crate fn as_local_hir_id(tcx: TyCtxt<'_>, def_id: ItemId) -> Option<HirId> {
-        match def_id {
+    crate fn as_local_hir_id(tcx: TyCtxt<'_>, item_id: ItemId) -> Option<HirId> {
+        match item_id {
             ItemId::DefId(real_id) => {
                 real_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
             }
@@ -390,7 +393,7 @@ impl<'tcx> DocContext<'tcx> {
         );
         tcx.struct_lint_node(
             crate::lint::MISSING_CRATE_LEVEL_DOCS,
-            DocContext::as_local_hir_id(tcx, krate.module.def_id).unwrap(),
+            DocContext::as_local_hir_id(tcx, krate.module.item_id).unwrap(),
             |lint| {
                 let mut diag =
                     lint.build("no documentation found for this crate's top-level module");
index 618268445743acbb10d3959b33aafffbc3d8e832..45ac16e75aa37474e81be14ddbaf9068d06375cf 100644 (file)
@@ -1174,8 +1174,6 @@ fn visit_testable<F: FnOnce(&mut Self)>(
         nested: F,
     ) {
         let ast_attrs = self.tcx.hir().attrs(hir_id);
-        let mut attrs = Attributes::from_ast(ast_attrs, None);
-
         if let Some(ref cfg) = ast_attrs.cfg(self.tcx, &FxHashSet::default()) {
             if !cfg.matches(&self.sess.parse_sess, Some(self.sess.features_untracked())) {
                 return;
@@ -1187,9 +1185,9 @@ fn visit_testable<F: FnOnce(&mut Self)>(
             self.collector.names.push(name);
         }
 
-        attrs.unindent_doc_comments();
         // The collapse-docs pass won't combine sugared/raw doc attributes, or included files with
         // anything else, this will combine them for us.
+        let attrs = Attributes::from_ast(ast_attrs, None);
         if let Some(doc) = attrs.collapsed_doc_value() {
             // Use the outermost invocation, so that doctest names come from where the docs were written.
             let span = ast_attrs
index 663e18fe9129fd594ebae6885b74ee88b7f25e0d..b4d2772b31da2d2ea0c860d398157fa3b777f47a 100644 (file)
@@ -1,7 +1,7 @@
 use std::mem;
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_middle::middle::privacy::AccessLevels;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::{sym, Symbol};
 /// This struct is used to wrap the `cache` and `tcx` in order to run `DocFolder`.
 struct CacheBuilder<'a, 'tcx> {
     cache: &'a mut Cache,
+    /// This field is used to prevent duplicated impl blocks.
+    impl_ids: FxHashMap<DefId, FxHashSet<DefId>>,
     tcx: TyCtxt<'tcx>,
 }
 
@@ -170,12 +172,19 @@ impl Cache {
                 .insert(def_id, (vec![crate_name, prim.as_sym()], ItemType::Primitive));
         }
 
-        krate = CacheBuilder { tcx, cache: &mut cx.cache }.fold_crate(krate);
+        let (krate, mut impl_ids) = {
+            let mut cache_builder =
+                CacheBuilder { tcx, cache: &mut cx.cache, impl_ids: FxHashMap::default() };
+            krate = cache_builder.fold_crate(krate);
+            (krate, cache_builder.impl_ids)
+        };
 
         for (trait_did, dids, impl_) in cx.cache.orphan_trait_impls.drain(..) {
             if cx.cache.traits.contains_key(&trait_did) {
                 for did in dids {
-                    cx.cache.impls.entry(did).or_default().push(impl_.clone());
+                    if impl_ids.entry(did).or_default().insert(impl_.def_id()) {
+                        cx.cache.impls.entry(did).or_default().push(impl_.clone());
+                    }
                 }
             }
         }
@@ -186,8 +195,8 @@ impl Cache {
 
 impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
     fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
-        if item.def_id.is_local() {
-            debug!("folding {} \"{:?}\", id {:?}", item.type_(), item.name, item.def_id);
+        if item.item_id.is_local() {
+            debug!("folding {} \"{:?}\", id {:?}", item.type_(), item.name, item.item_id);
         }
 
         // If this is a stripped module,
@@ -202,7 +211,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
         // If the impl is from a masked crate or references something from a
         // masked crate then remove it completely.
         if let clean::ImplItem(ref i) = *item.kind {
-            if self.cache.masked_crates.contains(&item.def_id.krate())
+            if self.cache.masked_crates.contains(&item.item_id.krate())
                 || i.trait_
                     .as_ref()
                     .map_or(false, |t| self.cache.masked_crates.contains(&t.def_id().krate))
@@ -217,7 +226,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
         // Propagate a trait method's documentation to all implementors of the
         // trait.
         if let clean::TraitItem(ref t) = *item.kind {
-            self.cache.traits.entry(item.def_id.expect_def_id()).or_insert_with(|| {
+            self.cache.traits.entry(item.item_id.expect_def_id()).or_insert_with(|| {
                 clean::TraitWithExtraInfo {
                     trait_: t.clone(),
                     is_notable: item.attrs.has_doc_flag(sym::notable_trait),
@@ -293,7 +302,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                     // A crate has a module at its root, containing all items,
                     // which should not be indexed. The crate-item itself is
                     // inserted later on when serializing the search-index.
-                    if item.def_id.index().map_or(false, |idx| idx != CRATE_DEF_INDEX) {
+                    if item.item_id.as_def_id().map_or(false, |idx| !idx.is_crate_root()) {
                         let desc = item.doc_value().map_or_else(String::new, |x| {
                             short_markdown_summary(x.as_str(), &item.link_names(self.cache))
                         });
@@ -351,11 +360,11 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                     // `public_items` map, so we can skip inserting into the
                     // paths map if there was already an entry present and we're
                     // not a public item.
-                    if !self.cache.paths.contains_key(&item.def_id.expect_def_id())
-                        || self.cache.access_levels.is_public(item.def_id.expect_def_id())
+                    if !self.cache.paths.contains_key(&item.item_id.expect_def_id())
+                        || self.cache.access_levels.is_public(item.item_id.expect_def_id())
                     {
                         self.cache.paths.insert(
-                            item.def_id.expect_def_id(),
+                            item.item_id.expect_def_id(),
                             (self.cache.stack.clone(), item.type_()),
                         );
                     }
@@ -364,7 +373,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
             clean::PrimitiveItem(..) => {
                 self.cache
                     .paths
-                    .insert(item.def_id.expect_def_id(), (self.cache.stack.clone(), item.type_()));
+                    .insert(item.item_id.expect_def_id(), (self.cache.stack.clone(), item.type_()));
             }
 
             clean::ExternCrateItem { .. }
@@ -396,7 +405,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
             | clean::StructItem(..)
             | clean::UnionItem(..)
             | clean::VariantItem(..) => {
-                self.cache.parent_stack.push(item.def_id.expect_def_id());
+                self.cache.parent_stack.push(item.item_id.expect_def_id());
                 self.cache.parent_is_trait_impl = false;
                 true
             }
@@ -467,7 +476,13 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
             let impl_item = Impl { impl_item: item };
             if impl_item.trait_did().map_or(true, |d| self.cache.traits.contains_key(&d)) {
                 for did in dids {
-                    self.cache.impls.entry(did).or_insert_with(Vec::new).push(impl_item.clone());
+                    if self.impl_ids.entry(did).or_default().insert(impl_item.def_id()) {
+                        self.cache
+                            .impls
+                            .entry(did)
+                            .or_insert_with(Vec::new)
+                            .push(impl_item.clone());
+                    }
                 }
             } else {
                 let trait_did = impl_item.trait_did().expect("no trait did");
index 4f0c5a9edee7185581c71bd1846d0151105f015a..3e36318eb71b0cb65e225a65a2bb183a2092cd1c 100644 (file)
@@ -6,7 +6,7 @@
 
 crate use renderer::{run_format, FormatRenderer};
 
-use crate::clean;
+use crate::clean::{self, ItemId};
 
 /// Specifies whether rendering directly implemented trait items or ones from a certain Deref
 /// impl.
@@ -40,4 +40,24 @@ impl Impl {
     crate fn trait_did(&self) -> Option<DefId> {
         self.inner_impl().trait_.as_ref().map(|t| t.def_id())
     }
+
+    /// This function is used to extract a `DefId` to be used as a key for the `Cache::impls` field.
+    ///
+    /// It allows to prevent having duplicated implementations showing up (the biggest issue was
+    /// with blanket impls).
+    ///
+    /// It panics if `self` is a `ItemId::Primitive`.
+    crate fn def_id(&self) -> DefId {
+        match self.impl_item.item_id {
+            ItemId::Blanket { impl_id, .. } => impl_id,
+            ItemId::Auto { trait_, .. } => trait_,
+            ItemId::DefId(def_id) => def_id,
+            ItemId::Primitive(_, _) => {
+                panic!(
+                    "Unexpected ItemId::Primitive in expect_def_id: {:?}",
+                    self.impl_item.item_id
+                )
+            }
+        }
+    }
 }
index 55b0028180f66fece8164bb2f1c903a36154e7c4..d3545236e3dfe5a0d48cbc073e13b8d835a13f54 100644 (file)
@@ -18,7 +18,6 @@
 use rustc_middle::ty;
 use rustc_middle::ty::DefIdTree;
 use rustc_middle::ty::TyCtxt;
-use rustc_span::def_id::CRATE_DEF_INDEX;
 use rustc_span::{sym, Symbol};
 use rustc_target::spec::abi::Abi;
 
@@ -268,6 +267,8 @@ impl clean::Generics {
     indent: usize,
     end_newline: bool,
 ) -> impl fmt::Display + 'a + Captures<'tcx> {
+    use fmt::Write;
+
     display_fn(move |f| {
         let mut where_predicates = gens.where_predicates.iter().filter(|pred| {
             !matches!(pred, clean::WherePredicate::BoundPredicate { bounds, .. } if bounds.is_empty())
@@ -281,56 +282,44 @@ impl clean::Generics {
 
                 match pred {
                     clean::WherePredicate::BoundPredicate { ty, bounds, bound_params } => {
-                        let bounds = bounds;
-                        let for_prefix = if bound_params.is_empty() {
-                            String::new()
-                        } else if f.alternate() {
-                            format!(
-                                "for&lt;{:#}&gt; ",
-                                comma_sep(bound_params.iter().map(|lt| lt.print()), true)
-                            )
-                        } else {
-                            format!(
-                                "for&lt;{}&gt; ",
-                                comma_sep(bound_params.iter().map(|lt| lt.print()), true)
-                            )
-                        };
+                        let ty_cx = ty.print(cx);
+                        let generic_bounds = print_generic_bounds(bounds, cx);
 
-                        if f.alternate() {
-                            write!(
-                                f,
-                                "{}{:#}: {:#}",
-                                for_prefix,
-                                ty.print(cx),
-                                print_generic_bounds(bounds, cx)
-                            )
+                        if bound_params.is_empty() {
+                            if f.alternate() {
+                                write!(f, "{ty_cx:#}: {generic_bounds:#}")
+                            } else {
+                                write!(f, "{ty_cx}: {generic_bounds}")
+                            }
                         } else {
-                            write!(
-                                f,
-                                "{}{}: {}",
-                                for_prefix,
-                                ty.print(cx),
-                                print_generic_bounds(bounds, cx)
-                            )
+                            if f.alternate() {
+                                write!(
+                                    f,
+                                    "for<{:#}> {ty_cx:#}: {generic_bounds:#}",
+                                    comma_sep(bound_params.iter().map(|lt| lt.print()), true)
+                                )
+                            } else {
+                                write!(
+                                    f,
+                                    "for&lt;{}&gt; {ty_cx}: {generic_bounds}",
+                                    comma_sep(bound_params.iter().map(|lt| lt.print()), true)
+                                )
+                            }
                         }
                     }
                     clean::WherePredicate::RegionPredicate { lifetime, bounds } => {
-                        write!(
-                            f,
-                            "{}: {}",
-                            lifetime.print(),
-                            bounds
-                                .iter()
-                                .map(|b| b.print(cx).to_string())
-                                .collect::<Vec<_>>()
-                                .join(" + ")
-                        )
+                        let mut bounds_display = String::new();
+                        for bound in bounds.iter().map(|b| b.print(cx)) {
+                            write!(bounds_display, "{bound} + ")?;
+                        }
+                        bounds_display.truncate(bounds_display.len() - " + ".len());
+                        write!(f, "{}: {bounds_display}", lifetime.print())
                     }
                     clean::WherePredicate::EqPredicate { lhs, rhs } => {
                         if f.alternate() {
-                            write!(f, "{:#} == {:#}", lhs.print(cx), rhs.print(cx),)
+                            write!(f, "{:#} == {:#}", lhs.print(cx), rhs.print(cx))
                         } else {
-                            write!(f, "{} == {}", lhs.print(cx), rhs.print(cx),)
+                            write!(f, "{} == {}", lhs.print(cx), rhs.print(cx))
                         }
                     }
                 }
@@ -341,40 +330,43 @@ impl clean::Generics {
             return Ok(());
         }
 
-        let mut clause = String::new();
-
-        if f.alternate() {
-            clause.push_str(" where");
-        } else {
+        let where_preds = comma_sep(where_predicates, false);
+        let clause = if f.alternate() {
             if end_newline {
-                clause.push_str(" <span class=\"where fmt-newline\">where");
+                // add a space so stripping <br> tags and breaking spaces still renders properly
+                format!(" where{where_preds}, ")
             } else {
-                clause.push_str(" <span class=\"where\">where");
+                format!(" where{where_preds}")
             }
-        }
-
-        clause.push_str(&comma_sep(where_predicates, false).to_string());
-
-        if end_newline {
-            clause.push(',');
-            // add a space so stripping <br> tags and breaking spaces still renders properly
-            if f.alternate() {
-                clause.push(' ');
-            } else {
-                clause.push_str("&nbsp;");
+        } else {
+            let mut br_with_padding = String::with_capacity(6 * indent + 28);
+            br_with_padding.push_str("<br>");
+            for _ in 0..indent + 4 {
+                br_with_padding.push_str("&nbsp;");
             }
-        }
+            let where_preds = where_preds.to_string().replace("<br>", &br_with_padding);
 
-        if !f.alternate() {
-            clause.push_str("</span>");
-            let padding = "&nbsp;".repeat(indent + 4);
-            clause = clause.replace("<br>", &format!("<br>{}", padding));
-            clause.insert_str(0, &"&nbsp;".repeat(indent.saturating_sub(1)));
-            if !end_newline {
-                clause.insert_str(0, "<br>");
+            if end_newline {
+                let mut clause = "&nbsp;".repeat(indent.saturating_sub(1));
+                // add a space so stripping <br> tags and breaking spaces still renders properly
+                write!(
+                    clause,
+                    " <span class=\"where fmt-newline\">where{where_preds},&nbsp;</span>"
+                )?;
+                clause
+            } else {
+                // insert a <br> tag after a single space but before multiple spaces at the start
+                if indent == 0 {
+                    format!(" <br><span class=\"where\">where{where_preds}</span>")
+                } else {
+                    let mut clause = br_with_padding;
+                    clause.truncate(clause.len() - 5 * "&nbsp;".len());
+                    write!(clause, " <span class=\"where\">where{where_preds}</span>")?;
+                    clause
+                }
             }
-        }
-        write!(f, "{}", clause)
+        };
+        write!(f, "{clause}")
     })
 }
 
@@ -1312,7 +1304,7 @@ impl clean::Visibility {
                 //                 visibility, so it shouldn't matter.
                 let parent_module = find_nearest_parent_module(cx.tcx(), item_did.expect_def_id());
 
-                if vis_did.index == CRATE_DEF_INDEX {
+                if vis_did.is_crate_root() {
                     "pub(crate) ".to_owned()
                 } else if parent_module == Some(vis_did) {
                     // `pub(in foo)` where `foo` is the parent module
@@ -1360,7 +1352,7 @@ impl clean::Visibility {
                 //                 visibility, so it shouldn't matter.
                 let parent_module = find_nearest_parent_module(tcx, item_did);
 
-                if vis_did.index == CRATE_DEF_INDEX {
+                if vis_did.is_crate_root() {
                     "pub(crate) ".to_owned()
                 } else if parent_module == Some(vis_did) {
                     // `pub(in foo)` where `foo` is the parent module
index 1ebb41b5933d0b0350165494ce61bbe4198cd7d9..9e76af982985416563472f544b8f21c13c89e443 100644 (file)
@@ -32,6 +32,7 @@
 use rustc_span::edition::Edition;
 use rustc_span::Span;
 
+use once_cell::sync::Lazy;
 use std::borrow::Cow;
 use std::cell::RefCell;
 use std::collections::VecDeque;
@@ -1255,7 +1256,7 @@ fn markdown_summary_with_limit(
     pub range: Range<usize>,
 }
 
-crate fn markdown_links(md: &str) -> Vec<MarkdownLink> {
+crate fn markdown_links<R>(md: &str, filter_map: impl Fn(MarkdownLink) -> Option<R>) -> Vec<R> {
     if md.is_empty() {
         return vec![];
     }
@@ -1295,11 +1296,12 @@ fn markdown_summary_with_limit(
 
     let mut push = |link: BrokenLink<'_>| {
         let span = span_for_link(&link.reference, link.span);
-        links.borrow_mut().push(MarkdownLink {
+        filter_map(MarkdownLink {
             kind: LinkType::ShortcutUnknown,
             link: link.reference.to_string(),
             range: span,
-        });
+        })
+        .map(|link| links.borrow_mut().push(link));
         None
     };
     let p = Parser::new_with_broken_link_callback(md, main_body_opts(), Some(&mut push))
@@ -1311,10 +1313,23 @@ fn markdown_summary_with_limit(
     let iter = Footnotes::new(HeadingLinks::new(p, None, &mut ids, HeadingOffset::H1));
 
     for ev in iter {
-        if let Event::Start(Tag::Link(kind, dest, _)) = ev.0 {
+        if let Event::Start(Tag::Link(
+            // `<>` links cannot be intra-doc links so we skip them.
+            kind @ (LinkType::Inline
+            | LinkType::Reference
+            | LinkType::ReferenceUnknown
+            | LinkType::Collapsed
+            | LinkType::CollapsedUnknown
+            | LinkType::Shortcut
+            | LinkType::ShortcutUnknown),
+            dest,
+            _,
+        )) = ev.0
+        {
             debug!("found link: {dest}");
             let span = span_for_link(&dest, ev.1);
-            links.borrow_mut().push(MarkdownLink { kind, link: dest.into_string(), range: span });
+            filter_map(MarkdownLink { kind, link: dest.into_string(), range: span })
+                .map(|link| links.borrow_mut().push(link));
         }
     }
 
@@ -1415,62 +1430,65 @@ fn markdown_summary_with_limit(
 
 #[derive(Clone, Default, Debug)]
 pub struct IdMap {
-    map: FxHashMap<String, usize>,
+    map: FxHashMap<Cow<'static, str>, usize>,
 }
 
-fn init_id_map() -> FxHashMap<String, usize> {
+// The map is pre-initialized and cloned each time to avoid reinitializing it repeatedly.
+static DEFAULT_ID_MAP: Lazy<FxHashMap<Cow<'static, str>, usize>> = Lazy::new(|| init_id_map());
+
+fn init_id_map() -> FxHashMap<Cow<'static, str>, usize> {
     let mut map = FxHashMap::default();
     // This is the list of IDs used in Javascript.
-    map.insert("help".to_owned(), 1);
+    map.insert("help".into(), 1);
     // This is the list of IDs used in HTML generated in Rust (including the ones
     // used in tera template files).
-    map.insert("mainThemeStyle".to_owned(), 1);
-    map.insert("themeStyle".to_owned(), 1);
-    map.insert("theme-picker".to_owned(), 1);
-    map.insert("theme-choices".to_owned(), 1);
-    map.insert("settings-menu".to_owned(), 1);
-    map.insert("help-button".to_owned(), 1);
-    map.insert("main-content".to_owned(), 1);
-    map.insert("search".to_owned(), 1);
-    map.insert("crate-search".to_owned(), 1);
-    map.insert("render-detail".to_owned(), 1);
-    map.insert("toggle-all-docs".to_owned(), 1);
-    map.insert("all-types".to_owned(), 1);
-    map.insert("default-settings".to_owned(), 1);
-    map.insert("rustdoc-vars".to_owned(), 1);
-    map.insert("sidebar-vars".to_owned(), 1);
-    map.insert("copy-path".to_owned(), 1);
-    map.insert("TOC".to_owned(), 1);
+    map.insert("mainThemeStyle".into(), 1);
+    map.insert("themeStyle".into(), 1);
+    map.insert("theme-picker".into(), 1);
+    map.insert("theme-choices".into(), 1);
+    map.insert("settings-menu".into(), 1);
+    map.insert("help-button".into(), 1);
+    map.insert("main-content".into(), 1);
+    map.insert("search".into(), 1);
+    map.insert("crate-search".into(), 1);
+    map.insert("render-detail".into(), 1);
+    map.insert("toggle-all-docs".into(), 1);
+    map.insert("all-types".into(), 1);
+    map.insert("default-settings".into(), 1);
+    map.insert("rustdoc-vars".into(), 1);
+    map.insert("sidebar-vars".into(), 1);
+    map.insert("copy-path".into(), 1);
+    map.insert("TOC".into(), 1);
     // This is the list of IDs used by rustdoc sections (but still generated by
     // rustdoc).
-    map.insert("fields".to_owned(), 1);
-    map.insert("variants".to_owned(), 1);
-    map.insert("implementors-list".to_owned(), 1);
-    map.insert("synthetic-implementors-list".to_owned(), 1);
-    map.insert("foreign-impls".to_owned(), 1);
-    map.insert("implementations".to_owned(), 1);
-    map.insert("trait-implementations".to_owned(), 1);
-    map.insert("synthetic-implementations".to_owned(), 1);
-    map.insert("blanket-implementations".to_owned(), 1);
-    map.insert("required-associated-types".to_owned(), 1);
-    map.insert("provided-associated-types".to_owned(), 1);
-    map.insert("provided-associated-consts".to_owned(), 1);
-    map.insert("required-associated-consts".to_owned(), 1);
-    map.insert("required-methods".to_owned(), 1);
-    map.insert("provided-methods".to_owned(), 1);
-    map.insert("implementors".to_owned(), 1);
-    map.insert("synthetic-implementors".to_owned(), 1);
-    map.insert("implementations-list".to_owned(), 1);
-    map.insert("trait-implementations-list".to_owned(), 1);
-    map.insert("synthetic-implementations-list".to_owned(), 1);
-    map.insert("blanket-implementations-list".to_owned(), 1);
-    map.insert("deref-methods".to_owned(), 1);
+    map.insert("fields".into(), 1);
+    map.insert("variants".into(), 1);
+    map.insert("implementors-list".into(), 1);
+    map.insert("synthetic-implementors-list".into(), 1);
+    map.insert("foreign-impls".into(), 1);
+    map.insert("implementations".into(), 1);
+    map.insert("trait-implementations".into(), 1);
+    map.insert("synthetic-implementations".into(), 1);
+    map.insert("blanket-implementations".into(), 1);
+    map.insert("required-associated-types".into(), 1);
+    map.insert("provided-associated-types".into(), 1);
+    map.insert("provided-associated-consts".into(), 1);
+    map.insert("required-associated-consts".into(), 1);
+    map.insert("required-methods".into(), 1);
+    map.insert("provided-methods".into(), 1);
+    map.insert("implementors".into(), 1);
+    map.insert("synthetic-implementors".into(), 1);
+    map.insert("implementations-list".into(), 1);
+    map.insert("trait-implementations-list".into(), 1);
+    map.insert("synthetic-implementations-list".into(), 1);
+    map.insert("blanket-implementations-list".into(), 1);
+    map.insert("deref-methods".into(), 1);
     map
 }
 
 impl IdMap {
     pub fn new() -> Self {
-        IdMap { map: init_id_map() }
+        IdMap { map: DEFAULT_ID_MAP.clone() }
     }
 
     crate fn derive<S: AsRef<str> + ToString>(&mut self, candidate: S) -> String {
@@ -1483,7 +1501,7 @@ pub fn new() -> Self {
             }
         };
 
-        self.map.insert(id.clone(), 1);
+        self.map.insert(id.clone().into(), 1);
         id
     }
 }
index 90123655758cce202a8521f87d43d7df2fed9fae..8e643107353ddadc1de5887ab3eeee002445157d 100644 (file)
@@ -222,7 +222,7 @@ fn render_item(&self, it: &clean::Item, is_module: bool) -> String {
                 &self.shared.style_files,
             )
         } else {
-            if let Some(&(ref names, ty)) = self.cache().paths.get(&it.def_id.expect_def_id()) {
+            if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id()) {
                 if self.current.len() + 1 != names.len()
                     || self.current.iter().zip(names.iter()).any(|(a, b)| a != b)
                 {
index a4cc42e2a0185834e3573d4e08cdb105167a318d..7a4289b8e60e9eebd0caa60683b1039887c35882 100644 (file)
@@ -830,7 +830,7 @@ fn assoc_const(
         w,
         "{extra}{vis}const <a{href} class=\"constant\">{name}</a>: {ty}",
         extra = extra,
-        vis = it.visibility.print_with_space(it.def_id, cx),
+        vis = it.visibility.print_with_space(it.item_id, cx),
         href = assoc_href_attr(it, link, cx),
         name = it.name.as_ref().unwrap(),
         ty = ty.print(cx),
@@ -884,7 +884,7 @@ fn assoc_method(
 ) {
     let header = meth.fn_header(cx.tcx()).expect("Trying to get header from a non-function item");
     let name = meth.name.as_ref().unwrap();
-    let vis = meth.visibility.print_with_space(meth.def_id, cx).to_string();
+    let vis = meth.visibility.print_with_space(meth.item_id, cx).to_string();
     // FIXME: Once https://github.com/rust-lang/rust/issues/67792 is implemented, we can remove
     // this condition.
     let constness = match render_mode {
@@ -2060,7 +2060,7 @@ fn small_url_encode(s: String) -> String {
 }
 
 fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
-    let did = it.def_id.expect_def_id();
+    let did = it.item_id.expect_def_id();
     let cache = cx.cache();
 
     if let Some(v) = cache.impls.get(&did) {
@@ -2412,7 +2412,7 @@ fn print_sidebar_section(
     );
 
     let cache = cx.cache();
-    if let Some(implementors) = cache.implementors.get(&it.def_id.expect_def_id()) {
+    if let Some(implementors) = cache.implementors.get(&it.item_id.expect_def_id()) {
         let mut res = implementors
             .iter()
             .filter(|i| {
@@ -2761,7 +2761,7 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> {
 /// Generates the HTML for example call locations generated via the --scrape-examples flag.
 fn render_call_locations(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item) {
     let tcx = cx.tcx();
-    let def_id = item.def_id.expect_def_id();
+    let def_id = item.item_id.expect_def_id();
     let key = tcx.def_path_hash(def_id);
     let Some(call_locations) = cx.shared.call_locations.get(&key) else { return };
 
index 1ed5c662c41cc162280b91829ff0b813b06d92ac..f1915920b6d05dd79832656d491f2ffb06e3198d 100644 (file)
@@ -264,7 +264,7 @@ fn cmp(
     // (which is the position in the vector).
     indices.dedup_by_key(|i| {
         (
-            items[*i].def_id,
+            items[*i].item_id,
             if items[*i].name.is_some() { Some(full_path(cx, &items[*i])) } else { None },
             items[*i].type_(),
             if items[*i].is_import() { *i } else { 0 },
@@ -306,15 +306,15 @@ fn cmp(
                     Some(src) => write!(
                         w,
                         "<div class=\"item-left\"><code>{}extern crate {} as {};",
-                        myitem.visibility.print_with_space(myitem.def_id, cx),
-                        anchor(myitem.def_id.expect_def_id(), src, cx),
+                        myitem.visibility.print_with_space(myitem.item_id, cx),
+                        anchor(myitem.item_id.expect_def_id(), src, cx),
                         myitem.name.unwrap(),
                     ),
                     None => write!(
                         w,
                         "<div class=\"item-left\"><code>{}extern crate {};",
-                        myitem.visibility.print_with_space(myitem.def_id, cx),
-                        anchor(myitem.def_id.expect_def_id(), myitem.name.unwrap(), cx),
+                        myitem.visibility.print_with_space(myitem.item_id, cx),
+                        anchor(myitem.item_id.expect_def_id(), myitem.name.unwrap(), cx),
                     ),
                 }
                 w.write_str("</code></div>");
@@ -328,7 +328,7 @@ fn cmp(
 
                     // Just need an item with the correct def_id and attrs
                     let import_item = clean::Item {
-                        def_id: import_def_id.into(),
+                        item_id: import_def_id.into(),
                         attrs: import_attrs,
                         cfg: ast_attrs.cfg(cx.tcx(), &cx.cache().hidden_cfg),
                         ..myitem.clone()
@@ -352,7 +352,7 @@ fn cmp(
                      <div class=\"item-right docblock-short\">{stab_tags}</div>",
                     stab = stab.unwrap_or_default(),
                     add = add,
-                    vis = myitem.visibility.print_with_space(myitem.def_id, cx),
+                    vis = myitem.visibility.print_with_space(myitem.item_id, cx),
                     imp = import.print(cx),
                     stab_tags = stab_tags.unwrap_or_default(),
                 );
@@ -468,7 +468,7 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
     let unsafety = header.unsafety.print_with_space();
     let abi = print_abi_with_space(header.abi).to_string();
     let asyncness = header.asyncness.print_with_space();
-    let visibility = it.visibility.print_with_space(it.def_id, cx).to_string();
+    let visibility = it.visibility.print_with_space(it.item_id, cx).to_string();
     let name = it.name.unwrap();
 
     let generics_len = format!("{:#}", f.generics.print(cx)).len();
@@ -524,7 +524,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
             write!(
                 w,
                 "{}{}{}trait {}{}{}",
-                it.visibility.print_with_space(it.def_id, cx),
+                it.visibility.print_with_space(it.item_id, cx),
                 t.unsafety.print_with_space(),
                 if t.is_auto { "auto " } else { "" },
                 it.name.unwrap(),
@@ -787,10 +787,10 @@ fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item
     }
 
     // If there are methods directly on this trait object, render them here.
-    render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All);
+    render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All);
 
     let cache = cx.cache();
-    if let Some(implementors) = cache.implementors.get(&it.def_id.expect_def_id()) {
+    if let Some(implementors) = cache.implementors.get(&it.item_id.expect_def_id()) {
         // The DefId is for the first Type found with that name. The bool is
         // if any Types with the same name but different DefId have been found.
         let mut implementor_dups: FxHashMap<Symbol, (DefId, bool)> = FxHashMap::default();
@@ -827,7 +827,7 @@ fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item
             for implementor in foreign {
                 let provided_methods = implementor.inner_impl().provided_trait_methods(cx.tcx());
                 let assoc_link =
-                    AssocItemLink::GotoSource(implementor.impl_item.def_id, &provided_methods);
+                    AssocItemLink::GotoSource(implementor.impl_item.item_id, &provided_methods);
                 render_impl(
                     w,
                     cx,
@@ -902,10 +902,10 @@ fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item
         .take(cx.current.len())
         .chain(std::iter::once("implementors"))
         .collect();
-    if it.def_id.is_local() {
+    if it.item_id.is_local() {
         js_src_path.extend(cx.current.iter().copied());
     } else {
-        let (ref path, _) = cache.external_paths[&it.def_id.expect_def_id()];
+        let (ref path, _) = cache.external_paths[&it.item_id.expect_def_id()];
         js_src_path.extend(path[..path.len() - 1].iter().copied());
     }
     js_src_path.push_fmt(format_args!("{}.{}.js", it.type_(), it.name.unwrap()));
@@ -937,7 +937,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clea
     // won't be visible anywhere in the docs. It would be nice to also show
     // associated items from the aliased type (see discussion in #32077), but
     // we need #14072 to make sense of the generics.
-    render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
+    render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
 }
 
 fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) {
@@ -961,14 +961,14 @@ fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean:
     // won't be visible anywhere in the docs. It would be nice to also show
     // associated items from the aliased type (see discussion in #32077), but
     // we need #14072 to make sense of the generics.
-    render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
+    render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
 }
 
 fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) {
     fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) {
         wrap_item(w, "typedef", |w| {
             render_attributes_in_pre(w, it, "");
-            write!(w, "{}", it.visibility.print_with_space(it.def_id, cx));
+            write!(w, "{}", it.visibility.print_with_space(it.item_id, cx));
             write!(
                 w,
                 "type {}{}{where_clause} = {type_};",
@@ -984,7 +984,7 @@ fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::
 
     document(w, cx, it, None, HeadingOffset::H2);
 
-    let def_id = it.def_id.expect_def_id();
+    let def_id = it.item_id.expect_def_id();
     // Render any items associated directly to this alias, as otherwise they
     // won't be visible anywhere in the docs. It would be nice to also show
     // associated items from the aliased type (see discussion in #32077), but
@@ -1037,7 +1037,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
             document(w, cx, field, Some(it), HeadingOffset::H3);
         }
     }
-    let def_id = it.def_id.expect_def_id();
+    let def_id = it.item_id.expect_def_id();
     render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
     document_type_layout(w, cx, def_id);
 }
@@ -1062,7 +1062,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
             write!(
                 w,
                 "{}enum {}{}{}",
-                it.visibility.print_with_space(it.def_id, cx),
+                it.visibility.print_with_space(it.item_id, cx),
                 it.name.unwrap(),
                 e.generics.print(cx),
                 print_where_clause(&e.generics, cx, 0, true),
@@ -1197,7 +1197,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
             document(w, cx, variant, Some(it), HeadingOffset::H4);
         }
     }
-    let def_id = it.def_id.expect_def_id();
+    let def_id = it.item_id.expect_def_id();
     render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
     document_type_layout(w, cx, def_id);
 }
@@ -1253,7 +1253,7 @@ fn item_proc_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, m: &clean
 
 fn item_primitive(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
     document(w, cx, it, None, HeadingOffset::H2);
-    render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
+    render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
 }
 
 fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::Constant) {
@@ -1264,7 +1264,7 @@ fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::
             write!(
                 w,
                 "{vis}const {name}: {typ}",
-                vis = it.visibility.print_with_space(it.def_id, cx),
+                vis = it.visibility.print_with_space(it.item_id, cx),
                 name = it.name.unwrap(),
                 typ = c.type_.print(cx),
             );
@@ -1344,7 +1344,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
             }
         }
     }
-    let def_id = it.def_id.expect_def_id();
+    let def_id = it.item_id.expect_def_id();
     render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
     document_type_layout(w, cx, def_id);
 }
@@ -1356,7 +1356,7 @@ fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
             write!(
                 w,
                 "{vis}static {mutability}{name}: {typ}",
-                vis = it.visibility.print_with_space(it.def_id, cx),
+                vis = it.visibility.print_with_space(it.item_id, cx),
                 mutability = s.mutability.print_with_space(),
                 name = it.name.unwrap(),
                 typ = s.type_.print(cx)
@@ -1374,7 +1374,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
             write!(
                 w,
                 "    {}type {};\n}}",
-                it.visibility.print_with_space(it.def_id, cx),
+                it.visibility.print_with_space(it.item_id, cx),
                 it.name.unwrap(),
             );
         });
@@ -1382,7 +1382,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
 
     document(w, cx, it, None, HeadingOffset::H2);
 
-    render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
+    render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
 }
 
 fn item_keyword(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
@@ -1543,7 +1543,7 @@ fn render_union(
     tab: &str,
     cx: &Context<'_>,
 ) {
-    write!(w, "{}union {}", it.visibility.print_with_space(it.def_id, cx), it.name.unwrap());
+    write!(w, "{}union {}", it.visibility.print_with_space(it.item_id, cx), it.name.unwrap());
     if let Some(g) = g {
         write!(w, "{}", g.print(cx));
         write!(w, "{}", print_where_clause(g, cx, 0, true));
@@ -1562,7 +1562,7 @@ fn render_union(
             write!(
                 w,
                 "    {}{}: {},\n{}",
-                field.visibility.print_with_space(field.def_id, cx),
+                field.visibility.print_with_space(field.item_id, cx),
                 field.name.unwrap(),
                 ty.print(cx),
                 tab
@@ -1592,7 +1592,7 @@ fn render_struct(
     write!(
         w,
         "{}{}{}",
-        it.visibility.print_with_space(it.def_id, cx),
+        it.visibility.print_with_space(it.item_id, cx),
         if structhead { "struct " } else { "" },
         it.name.unwrap()
     );
@@ -1618,7 +1618,7 @@ fn render_struct(
                         w,
                         "\n{}    {}{}: {},",
                         tab,
-                        field.visibility.print_with_space(field.def_id, cx),
+                        field.visibility.print_with_space(field.item_id, cx),
                         field.name.unwrap(),
                         ty.print(cx),
                     );
@@ -1650,7 +1650,7 @@ fn render_struct(
                         write!(
                             w,
                             "{}{}",
-                            field.visibility.print_with_space(field.def_id, cx),
+                            field.visibility.print_with_space(field.item_id, cx),
                             ty.print(cx),
                         )
                     }
index 3fa16c6c3b88067287439c3eb2267e59827655e9..371d0e84087544d4223a3427721fd102570702a6 100644 (file)
@@ -535,7 +535,7 @@ struct Implementor {
                 //
                 // If the implementation is from another crate then that crate
                 // should add it.
-                if imp.impl_item.def_id.krate() == did.krate || !imp.impl_item.def_id.is_local() {
+                if imp.impl_item.item_id.krate() == did.krate || !imp.impl_item.item_id.is_local() {
                     None
                 } else {
                     Some(Implementor {
index 629f90728d2f61cfaa952de308a3c613079a31af..0fe0fdadbd21050b3c27aa51331e81797a5a74b5 100644 (file)
@@ -8,10 +8,34 @@ function initSearch(searchIndex){}
 
 /**
  * @typedef {{
- *   raw: string,
- *   query: string,
- *   type: string,
- *   id: string,
+ *     name: string,
+ *     fullPath: Array<string>,
+ *     pathWithoutLast: Array<string>,
+ *     pathLast: string,
+ *     generics: Array<QueryElement>,
+ * }}
+ */
+var QueryElement;
+
+/**
+ * @typedef {{
+ *      pos: number,
+ *      totalElems: number,
+ *      typeFilter: (null|string),
+ *      userQuery: string,
+ * }}
+ */
+var ParserState;
+
+/**
+ * @typedef {{
+ *     original: string,
+ *     userQuery: string,
+ *     typeFilter: number,
+ *     elems: Array<QueryElement>,
+ *     args: Array<QueryElement>,
+ *     returned: Array<QueryElement>,
+ *     foundElems: number,
  * }}
  */
 var ParsedQuery;
@@ -30,3 +54,30 @@ var ParsedQuery;
  * }}
  */
 var Row;
+
+/**
+ * @typedef {{
+ *    in_args: Array<Object>,
+ *    returned: Array<Object>,
+ *    others: Array<Object>,
+ *    query: ParsedQuery,
+ * }}
+ */
+var ResultsTable;
+
+/**
+ * @typedef {{
+ *     desc: string,
+ *     displayPath: string,
+ *     fullPath: string,
+ *     href: string,
+ *     id: number,
+ *     lev: number,
+ *     name: string,
+ *     normalizedName: string,
+ *     parent: (Object|undefined),
+ *     path: string,
+ *     ty: number,
+ * }}
+ */
+var Results;
index ab52304491a2bc17841d3515f9227f9c916a57a2..0d4e0a0b3289dac7f763875b074733448725459c 100644 (file)
@@ -61,15 +61,6 @@ function printTab(nb) {
     });
 }
 
-function removeEmptyStringsFromArray(x) {
-    for (var i = 0, len = x.length; i < len; ++i) {
-        if (x[i] === "") {
-            x.splice(i, 1);
-            i -= 1;
-        }
-    }
-}
-
 /**
  * A function to compute the Levenshtein distance between two strings
  * Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported
@@ -133,11 +124,436 @@ window.initSearch = function(rawSearchIndex) {
         searchState.input.value = params.search || "";
     }
 
+    function isWhitespace(c) {
+        return " \t\n\r".indexOf(c) !== -1;
+    }
+
+    function isSpecialStartCharacter(c) {
+        return "<\"".indexOf(c) !== -1;
+    }
+
+    function isEndCharacter(c) {
+        return ",>-".indexOf(c) !== -1;
+    }
+
+    function isStopCharacter(c) {
+        return isWhitespace(c) || isEndCharacter(c);
+    }
+
+    function isErrorCharacter(c) {
+        return "()".indexOf(c) !== -1;
+    }
+
+    function itemTypeFromName(typename) {
+        for (var i = 0, len = itemTypes.length; i < len; ++i) {
+            if (itemTypes[i] === typename) {
+                return i;
+            }
+        }
+
+        throw new Error("Unknown type filter `" + typename + "`");
+    }
+
+    /**
+     * If we encounter a `"`, then we try to extract the string from it until we find another `"`.
+     *
+     * This function will throw an error in the following cases:
+     * * There is already another string element.
+     * * We are parsing a generic argument.
+     * * There is more than one element.
+     * * There is no closing `"`.
+     *
+     * @param {ParsedQuery} query
+     * @param {ParserState} parserState
+     * @param {boolean} isInGenerics
+     */
+    function getStringElem(query, parserState, isInGenerics) {
+        if (isInGenerics) {
+            throw new Error("`\"` cannot be used in generics");
+        } else if (query.literalSearch) {
+            throw new Error("Cannot have more than one literal search element");
+        } else if (parserState.totalElems - parserState.genericsElems > 0) {
+            throw new Error("Cannot use literal search when there is more than one element");
+        }
+        parserState.pos += 1;
+        var start = parserState.pos;
+        var end = getIdentEndPosition(parserState);
+        if (parserState.pos >= parserState.length) {
+            throw new Error("Unclosed `\"`");
+        } else if (parserState.userQuery[end] !== "\"") {
+            throw new Error(`Unexpected \`${parserState.userQuery[end]}\` in a string element`);
+        } else if (start === end) {
+            throw new Error("Cannot have empty string element");
+        }
+        // To skip the quote at the end.
+        parserState.pos += 1;
+        query.literalSearch = true;
+    }
+
+    /**
+     * Returns `true` if the current parser position is starting with "::".
+     *
+     * @param {ParserState} parserState
+     *
+     * @return {boolean}
+     */
+    function isPathStart(parserState) {
+        return parserState.userQuery.slice(parserState.pos, parserState.pos + 2) == '::';
+    }
+
+    /**
+     * Returns `true` if the current parser position is starting with "->".
+     *
+     * @param {ParserState} parserState
+     *
+     * @return {boolean}
+     */
+    function isReturnArrow(parserState) {
+        return parserState.userQuery.slice(parserState.pos, parserState.pos + 2) == '->';
+    }
+
+    /**
+     * Returns `true` if the given `c` character is valid for an ident.
+     *
+     * @param {string} c
+     *
+     * @return {boolean}
+     */
+    function isIdentCharacter(c) {
+        return (
+            c === '_' ||
+            (c >= '0' && c <= '9') ||
+            (c >= 'a' && c <= 'z') ||
+            (c >= 'A' && c <= 'Z'));
+    }
+
+    /**
+     * Returns `true` if the given `c` character is a separator.
+     *
+     * @param {string} c
+     *
+     * @return {boolean}
+     */
+    function isSeparatorCharacter(c) {
+        return c === "," || isWhitespaceCharacter(c);
+    }
+
+    /**
+     * Returns `true` if the given `c` character is a whitespace.
+     *
+     * @param {string} c
+     *
+     * @return {boolean}
+     */
+    function isWhitespaceCharacter(c) {
+        return c === " " || c === "\t";
+    }
+
+    /**
+     * @param {ParsedQuery} query
+     * @param {ParserState} parserState
+     * @param {string} name                  - Name of the query element.
+     * @param {Array<QueryElement>} generics - List of generics of this query element.
+     *
+     * @return {QueryElement}                - The newly created `QueryElement`.
+     */
+    function createQueryElement(query, parserState, name, generics, isInGenerics) {
+        if (name === '*' || (name.length === 0 && generics.length === 0)) {
+            return;
+        }
+        if (query.literalSearch && parserState.totalElems - parserState.genericsElems > 0) {
+            throw new Error("You cannot have more than one element if you use quotes");
+        }
+        var pathSegments = name.split("::");
+        if (pathSegments.length > 1) {
+            for (var i = 0, len = pathSegments.length; i < len; ++i) {
+                var pathSegment = pathSegments[i];
+
+                if (pathSegment.length === 0) {
+                    if (i === 0) {
+                        throw new Error("Paths cannot start with `::`");
+                    } else if (i + 1 === len) {
+                        throw new Error("Paths cannot end with `::`");
+                    }
+                    throw new Error("Unexpected `::::`");
+                }
+            }
+        }
+        // In case we only have something like `<p>`, there is no name.
+        if (pathSegments.length === 0 || (pathSegments.length === 1 && pathSegments[0] === "")) {
+            throw new Error("Found generics without a path");
+        }
+        parserState.totalElems += 1;
+        if (isInGenerics) {
+            parserState.genericsElems += 1;
+        }
+        return {
+            name: name,
+            fullPath: pathSegments,
+            pathWithoutLast: pathSegments.slice(0, pathSegments.length - 1),
+            pathLast: pathSegments[pathSegments.length - 1],
+            generics: generics,
+        };
+    }
+
+    /**
+     * This function goes through all characters until it reaches an invalid ident character or the
+     * end of the query. It returns the position of the last character of the ident.
+     *
+     * @param {ParserState} parserState
+     *
+     * @return {integer}
+     */
+    function getIdentEndPosition(parserState) {
+        var end = parserState.pos;
+        while (parserState.pos < parserState.length) {
+            var c = parserState.userQuery[parserState.pos];
+            if (!isIdentCharacter(c)) {
+                if (isErrorCharacter(c)) {
+                    throw new Error(`Unexpected \`${c}\``);
+                } else if (
+                    isStopCharacter(c) ||
+                    isSpecialStartCharacter(c) ||
+                    isSeparatorCharacter(c))
+                {
+                    break;
+                }
+                // If we allow paths ("str::string" for example).
+                else if (c === ":") {
+                    if (!isPathStart(parserState)) {
+                        break;
+                    }
+                    // Skip current ":".
+                    parserState.pos += 1;
+                } else {
+                    throw new Error(`Unexpected \`${c}\``);
+                }
+            }
+            parserState.pos += 1;
+            end = parserState.pos;
+        }
+        return end;
+    }
+
+    /**
+     * @param {ParsedQuery} query
+     * @param {ParserState} parserState
+     * @param {Array<QueryElement>} elems - This is where the new {QueryElement} will be added.
+     * @param {boolean} isInGenerics
+     */
+    function getNextElem(query, parserState, elems, isInGenerics) {
+        var generics = [];
+
+        var start = parserState.pos;
+        var end;
+        // We handle the strings on their own mostly to make code easier to follow.
+        if (parserState.userQuery[parserState.pos] === "\"") {
+            start += 1;
+            getStringElem(query, parserState, isInGenerics);
+            end = parserState.pos - 1;
+        } else {
+            end = getIdentEndPosition(parserState);
+        }
+        if (parserState.pos < parserState.length &&
+            parserState.userQuery[parserState.pos] === "<")
+        {
+            if (isInGenerics) {
+                throw new Error("Unexpected `<` after `<`");
+            } else if (start >= end) {
+                throw new Error("Found generics without a path");
+            }
+            parserState.pos += 1;
+            getItemsBefore(query, parserState, generics, ">");
+        }
+        if (start >= end && generics.length === 0) {
+            return;
+        }
+        elems.push(
+            createQueryElement(
+                query,
+                parserState,
+                parserState.userQuery.slice(start, end),
+                generics,
+                isInGenerics
+            )
+        );
+    }
+
+    /**
+     * This function parses the next query element until it finds `endChar`, calling `getNextElem`
+     * to collect each element.
+     *
+     * If there is no `endChar`, this function will implicitly stop at the end without raising an
+     * error.
+     *
+     * @param {ParsedQuery} query
+     * @param {ParserState} parserState
+     * @param {Array<QueryElement>} elems - This is where the new {QueryElement} will be added.
+     * @param {string} endChar            - This function will stop when it'll encounter this
+     *                                      character.
+     */
+    function getItemsBefore(query, parserState, elems, endChar) {
+        var foundStopChar = true;
+
+        while (parserState.pos < parserState.length) {
+            var c = parserState.userQuery[parserState.pos];
+            if (c === endChar) {
+                break;
+            } else if (isSeparatorCharacter(c)) {
+                parserState.pos += 1;
+                foundStopChar = true;
+                continue;
+            } else if (c === ":" && isPathStart(parserState)) {
+                throw new Error("Unexpected `::`: paths cannot start with `::`");
+            } else if (c === ":" || isEndCharacter(c)) {
+                var extra = "";
+                if (endChar === ">") {
+                    extra = "`<`";
+                } else if (endChar === "") {
+                    extra = "`->`";
+                }
+                throw new Error("Unexpected `" + c + "` after " + extra);
+            }
+            if (!foundStopChar) {
+                if (endChar !== "") {
+                    throw new Error(`Expected \`,\`, \` \` or \`${endChar}\`, found \`${c}\``);
+                }
+                throw new Error(`Expected \`,\` or \` \`, found \`${c}\``);
+            }
+            var posBefore = parserState.pos;
+            getNextElem(query, parserState, elems, endChar === ">");
+            // This case can be encountered if `getNextElem` encounted a "stop character" right from
+            // the start. For example if you have `,,` or `<>`. In this case, we simply move up the
+            // current position to continue the parsing.
+            if (posBefore === parserState.pos) {
+                parserState.pos += 1;
+            }
+            foundStopChar = false;
+        }
+        // We are either at the end of the string or on the `endChar`` character, let's move forward
+        // in any case.
+        parserState.pos += 1;
+    }
+
+    /**
+     * Checks that the type filter doesn't have unwanted characters like `<>` (which are ignored
+     * if empty).
+     *
+     * @param {ParserState} parserState
+     */
+    function checkExtraTypeFilterCharacters(parserState) {
+        var query = parserState.userQuery;
+
+        for (var pos = 0; pos < parserState.pos; ++pos) {
+            if (!isIdentCharacter(query[pos]) && !isWhitespaceCharacter(query[pos])) {
+                throw new Error(`Unexpected \`${query[pos]}\` in type filter`);
+            }
+        }
+    }
+
+    /**
+     * Parses the provided `query` input to fill `parserState`. If it encounters an error while
+     * parsing `query`, it'll throw an error.
+     *
+     * @param {ParsedQuery} query
+     * @param {ParserState} parserState
+     */
+    function parseInput(query, parserState) {
+        var c, before;
+        var foundStopChar = true;
+
+        while (parserState.pos < parserState.length) {
+            c = parserState.userQuery[parserState.pos];
+            if (isStopCharacter(c)) {
+                foundStopChar = true;
+                if (isSeparatorCharacter(c)) {
+                    parserState.pos += 1;
+                    continue;
+                } else if (c === "-" || c === ">") {
+                    if (isReturnArrow(parserState)) {
+                        break;
+                    }
+                    throw new Error(`Unexpected \`${c}\` (did you mean \`->\`?)`);
+                }
+                throw new Error(`Unexpected \`${c}\``);
+            } else if (c === ":" && !isPathStart(parserState)) {
+                if (parserState.typeFilter !== null) {
+                    throw new Error("Unexpected `:`");
+                }
+                if (query.elems.length === 0) {
+                    throw new Error("Expected type filter before `:`");
+                } else if (query.elems.length !== 1 || parserState.totalElems !== 1) {
+                    throw new Error("Unexpected `:`");
+                } else if (query.literalSearch) {
+                    throw new Error("You cannot use quotes on type filter");
+                }
+                checkExtraTypeFilterCharacters(parserState);
+                // The type filter doesn't count as an element since it's a modifier.
+                parserState.typeFilter = query.elems.pop().name;
+                parserState.pos += 1;
+                parserState.totalElems = 0;
+                query.literalSearch = false;
+                foundStopChar = true;
+                continue;
+            }
+            if (!foundStopChar) {
+                if (parserState.typeFilter !== null) {
+                    throw new Error(`Expected \`,\`, \` \` or \`->\`, found \`${c}\``);
+                }
+                throw new Error(`Expected \`,\`, \` \`, \`:\` or \`->\`, found \`${c}\``);
+            }
+            before = query.elems.length;
+            getNextElem(query, parserState, query.elems, false);
+            if (query.elems.length === before) {
+                // Nothing was added, weird... Let's increase the position to not remain stuck.
+                parserState.pos += 1;
+            }
+            foundStopChar = false;
+        }
+        while (parserState.pos < parserState.length) {
+            c = parserState.userQuery[parserState.pos];
+            if (isReturnArrow(parserState)) {
+                parserState.pos += 2;
+                // Get returned elements.
+                getItemsBefore(query, parserState, query.returned, "");
+                // Nothing can come afterward!
+                if (query.returned.length === 0) {
+                    throw new Error("Expected at least one item after `->`");
+                }
+                break;
+            } else {
+                parserState.pos += 1;
+            }
+        }
+    }
+
+    /**
+     * Takes the user search input and returns an empty `ParsedQuery`.
+     *
+     * @param {string} userQuery
+     *
+     * @return {ParsedQuery}
+     */
+    function newParsedQuery(userQuery) {
+        return {
+            original: userQuery,
+            userQuery: userQuery.toLowerCase(),
+            typeFilter: NO_TYPE_FILTER,
+            elems: [],
+            returned: [],
+            // Total number of "top" elements (does not include generics).
+            foundElems: 0,
+            literalSearch: false,
+            error: null,
+        };
+    }
+
     /**
      * Build an URL with search parameters.
      *
      * @param {string} search            - The current search being performed.
      * @param {string|null} filterCrates - The current filtering crate (if any).
+     *
      * @return {string}
      */
     function buildUrl(search, filterCrates) {
@@ -167,33 +583,139 @@ window.initSearch = function(rawSearchIndex) {
     }
 
     /**
-     * Executes the query and returns a list of results for each results tab.
-     * @param  {Object}        query          - The user query
-     * @param  {Array<string>} searchWords    - The list of search words to query against
-     * @param  {string}        [filterCrates] - Crate to search in
-     * @return {{
-     *   in_args: Array<?>,
-     *   returned: Array<?>,
-     *   others: Array<?>
-     * }}
+     * Parses the query.
+     *
+     * The supported syntax by this parser is as follow:
+     *
+     * ident = *(ALPHA / DIGIT / "_")
+     * path = ident *(DOUBLE-COLON ident)
+     * arg = path [generics]
+     * arg-without-generic = path
+     * type-sep = COMMA/WS *(COMMA/WS)
+     * nonempty-arg-list = *(type-sep) arg *(type-sep arg) *(type-sep)
+     * nonempty-arg-list-without-generics = *(type-sep) arg-without-generic
+     *                                      *(type-sep arg-without-generic) *(type-sep)
+     * generics = OPEN-ANGLE-BRACKET [ nonempty-arg-list-without-generics ] *(type-sep)
+     *            CLOSE-ANGLE-BRACKET/EOF
+     * return-args = RETURN-ARROW *(type-sep) nonempty-arg-list
+     *
+     * exact-search = [type-filter *WS COLON] [ RETURN-ARROW ] *WS QUOTE ident QUOTE [ generics ]
+     * type-search = [type-filter *WS COLON] [ nonempty-arg-list ] [ return-args ]
+     *
+     * query = *WS (exact-search / type-search) *WS
+     *
+     * type-filter = (
+     *     "mod" /
+     *     "externcrate" /
+     *     "import" /
+     *     "struct" /
+     *     "enum" /
+     *     "fn" /
+     *     "type" /
+     *     "static" /
+     *     "trait" /
+     *     "impl" /
+     *     "tymethod" /
+     *     "method" /
+     *     "structfield" /
+     *     "variant" /
+     *     "macro" /
+     *     "primitive" /
+     *     "associatedtype" /
+     *     "constant" /
+     *     "associatedconstant" /
+     *     "union" /
+     *     "foreigntype" /
+     *     "keyword" /
+     *     "existential" /
+     *     "attr" /
+     *     "derive" /
+     *     "traitalias")
+     *
+     * OPEN-ANGLE-BRACKET = "<"
+     * CLOSE-ANGLE-BRACKET = ">"
+     * COLON = ":"
+     * DOUBLE-COLON = "::"
+     * QUOTE = %x22
+     * COMMA = ","
+     * RETURN-ARROW = "->"
+     *
+     * ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
+     * DIGIT = %x30-39
+     * WS = %x09 / " "
+     *
+     * @param  {string} val     - The user query
+     *
+     * @return {ParsedQuery}    - The parsed query
      */
-    function execQuery(query, searchWords, filterCrates) {
-        function itemTypeFromName(typename) {
-            for (var i = 0, len = itemTypes.length; i < len; ++i) {
-                if (itemTypes[i] === typename) {
-                    return i;
+    function parseQuery(userQuery) {
+        userQuery = userQuery.trim();
+        var parserState = {
+            length: userQuery.length,
+            pos: 0,
+            // Total number of elements (includes generics).
+            totalElems: 0,
+            genericsElems: 0,
+            typeFilter: null,
+            userQuery: userQuery.toLowerCase(),
+        };
+        var query = newParsedQuery(userQuery);
+
+        try {
+            parseInput(query, parserState);
+            if (parserState.typeFilter !== null) {
+                var typeFilter = parserState.typeFilter;
+                if (typeFilter === "const") {
+                    typeFilter = "constant";
                 }
+                query.typeFilter = itemTypeFromName(typeFilter);
             }
-            return NO_TYPE_FILTER;
+        } catch (err) {
+            query = newParsedQuery(userQuery);
+            query.error = err.message;
+            query.typeFilter = -1;
+            return query;
         }
 
-        var valLower = query.query.toLowerCase(),
-            val = valLower,
-            typeFilter = itemTypeFromName(query.type),
-            results = {}, results_in_args = {}, results_returned = {},
-            split = valLower.split("::");
+        if (!query.literalSearch) {
+            // If there is more than one element in the query, we switch to literalSearch in any
+            // case.
+            query.literalSearch = parserState.totalElems > 1;
+        }
+        query.foundElems = query.elems.length + query.returned.length;
+        return query;
+    }
 
-        removeEmptyStringsFromArray(split);
+    /**
+     * Creates the query results.
+     *
+     * @param {Array<Result>} results_in_args
+     * @param {Array<Result>} results_returned
+     * @param {Array<Result>} results_in_args
+     * @param {ParsedQuery} parsedQuery
+     *
+     * @return {ResultsTable}
+     */
+    function createQueryResults(results_in_args, results_returned, results_others, parsedQuery) {
+        return {
+            "in_args": results_in_args,
+            "returned": results_returned,
+            "others": results_others,
+            "query": parsedQuery,
+        };
+    }
+
+    /**
+     * Executes the parsed query and builds a {ResultsTable}.
+     *
+     * @param  {ParsedQuery} parsedQuery - The parsed user query
+     * @param  {Object} searchWords      - The list of search words to query against
+     * @param  {Object} [filterCrates]   - Crate to search in if defined
+     *
+     * @return {ResultsTable}
+     */
+    function execQuery(parsedQuery, searchWords, filterCrates) {
+        var results_others = {}, results_in_args = {}, results_returned = {};
 
         function transformResults(results) {
             var duplicates = {};
@@ -227,6 +749,7 @@ window.initSearch = function(rawSearchIndex) {
         }
 
         function sortResults(results, isType) {
+            var userQuery = parsedQuery.userQuery;
             var ar = [];
             for (var entry in results) {
                 if (hasOwnPropertyRustdoc(results, entry)) {
@@ -246,8 +769,8 @@ window.initSearch = function(rawSearchIndex) {
                 var a, b;
 
                 // sort by exact match with regard to the last word (mismatch goes later)
-                a = (aaa.word !== val);
-                b = (bbb.word !== val);
+                a = (aaa.word !== userQuery);
+                b = (bbb.word !== userQuery);
                 if (a !== b) { return a - b; }
 
                 // Sort by non levenshtein results and then levenshtein results by the distance
@@ -309,6 +832,12 @@ window.initSearch = function(rawSearchIndex) {
                 return 0;
             });
 
+            var nameSplit = null;
+            if (parsedQuery.elems.length === 1) {
+                var hasPath = typeof parsedQuery.elems[0].path === "undefined";
+                nameSplit = hasPath ? null : parsedQuery.elems[0].path;
+            }
+
             for (var i = 0, len = results.length; i < len; ++i) {
                 result = results[i];
 
@@ -320,215 +849,222 @@ window.initSearch = function(rawSearchIndex) {
                     path = result.item.path.toLowerCase(),
                     parent = result.item.parent;
 
-                if (!isType && !validateResult(name, path, split, parent)) {
+                if (!isType && !validateResult(name, path, nameSplit, parent)) {
                     result.id = -1;
                 }
             }
             return transformResults(results);
         }
 
-        function extractGenerics(val) {
-            val = val.toLowerCase();
-            if (val.indexOf("<") !== -1) {
-                var values = val.substring(val.indexOf("<") + 1, val.lastIndexOf(">"));
-                return {
-                    name: val.substring(0, val.indexOf("<")),
-                    generics: values.split(/\s*,\s*/),
-                };
+        /**
+         * This function checks if the object (`row`) generics match the given type (`elem`)
+         * generics. If there are no generics on `row`, `defaultLev` is returned.
+         *
+         * @param {Row} row            - The object to check.
+         * @param {QueryElement} elem  - The element from the parsed query.
+         * @param {integer} defaultLev - This is the value to return in case there are no generics.
+         *
+         * @return {integer}           - Returns the best match (if any) or `MAX_LEV_DISTANCE + 1`.
+         */
+        function checkGenerics(row, elem, defaultLev) {
+            if (row.length <= GENERICS_DATA || row[GENERICS_DATA].length === 0) {
+                return elem.generics.length === 0 ? defaultLev : MAX_LEV_DISTANCE + 1;
+            } else if (row[GENERICS_DATA].length > 0 && row[GENERICS_DATA][0][NAME] === "") {
+                if (row.length > GENERICS_DATA) {
+                    return checkGenerics(row[GENERICS_DATA][0], elem, defaultLev);
+                }
+                return elem.generics.length === 0 ? defaultLev : MAX_LEV_DISTANCE + 1;
             }
-            return {
-                name: val,
-                generics: [],
-            };
-        }
-
-        function checkGenerics(obj, val) {
             // The names match, but we need to be sure that all generics kinda
             // match as well.
-            var tmp_lev, elem_name;
-            if (val.generics.length > 0) {
-                if (obj.length > GENERICS_DATA &&
-                      obj[GENERICS_DATA].length >= val.generics.length) {
-                    var elems = Object.create(null);
-                    var elength = obj[GENERICS_DATA].length;
-                    for (var x = 0; x < elength; ++x) {
-                        if (!elems[obj[GENERICS_DATA][x][NAME]]) {
-                            elems[obj[GENERICS_DATA][x][NAME]] = 0;
+            var elem_name;
+            if (elem.generics.length > 0 && row[GENERICS_DATA].length >= elem.generics.length) {
+                var elems = Object.create(null);
+                for (var x = 0, length = row[GENERICS_DATA].length; x < length; ++x) {
+                    elem_name = row[GENERICS_DATA][x][NAME];
+                    if (elem_name === "") {
+                        // Pure generic, needs to check into it.
+                        if (checkGenerics(
+                                row[GENERICS_DATA][x], elem, MAX_LEV_DISTANCE + 1) !== 0) {
+                            return MAX_LEV_DISTANCE + 1;
                         }
-                        elems[obj[GENERICS_DATA][x][NAME]] += 1;
+                        continue;
+                    }
+                    if (elems[elem_name] === undefined) {
+                        elems[elem_name] = 0;
                     }
-                    var total = 0;
-                    var done = 0;
-                    // We need to find the type that matches the most to remove it in order
-                    // to move forward.
-                    var vlength = val.generics.length;
-                    for (x = 0; x < vlength; ++x) {
-                        var lev = MAX_LEV_DISTANCE + 1;
-                        var firstGeneric = val.generics[x];
-                        var match = null;
-                        if (elems[firstGeneric]) {
-                            match = firstGeneric;
-                            lev = 0;
-                        } else {
-                            for (elem_name in elems) {
-                                tmp_lev = levenshtein(elem_name, firstGeneric);
-                                if (tmp_lev < lev) {
-                                    lev = tmp_lev;
-                                    match = elem_name;
-                                }
+                    elems[elem_name] += 1;
+                }
+                // We need to find the type that matches the most to remove it in order
+                // to move forward.
+                for (x = 0, length = elem.generics.length; x < length; ++x) {
+                    var generic = elem.generics[x];
+                    var match = null;
+                    if (elems[generic.name]) {
+                        match = generic.name;
+                    } else {
+                        for (elem_name in elems) {
+                            if (!hasOwnPropertyRustdoc(elems, elem_name)) {
+                                continue;
                             }
-                        }
-                        if (match !== null) {
-                            elems[match] -= 1;
-                            if (elems[match] == 0) {
-                                delete elems[match];
+                            if (elem_name === generic) {
+                                match = elem_name;
+                                break;
                             }
-                            total += lev;
-                            done += 1;
-                        } else {
-                            return MAX_LEV_DISTANCE + 1;
                         }
                     }
-                    return Math.ceil(total / done);
+                    if (match === null) {
+                        return MAX_LEV_DISTANCE + 1;
+                    }
+                    elems[match] -= 1;
+                    if (elems[match] === 0) {
+                        delete elems[match];
+                    }
                 }
+                return 0;
             }
             return MAX_LEV_DISTANCE + 1;
         }
 
         /**
-          * This function checks if the object (`obj`) matches the given type (`val`) and its
+          * This function checks if the object (`row`) matches the given type (`elem`) and its
+          * generics (if any).
+          *
+          * @param {Row} row
+          * @param {QueryElement} elem    - The element from the parsed query.
+          *
+          * @return {integer} - Returns a Levenshtein distance to the best match.
+          */
+        function checkIfInGenerics(row, elem) {
+            var lev = MAX_LEV_DISTANCE + 1;
+            for (var x = 0, length = row[GENERICS_DATA].length; x < length && lev !== 0; ++x) {
+                lev = Math.min(
+                    checkType(row[GENERICS_DATA][x], elem, true),
+                    lev
+                );
+            }
+            return lev;
+        }
+
+        /**
+          * This function checks if the object (`row`) matches the given type (`elem`) and its
           * generics (if any).
           *
-          * @param {Object} obj
-          * @param {string} val
+          * @param {Row} row
+          * @param {QueryElement} elem      - The element from the parsed query.
           * @param {boolean} literalSearch
           *
           * @return {integer} - Returns a Levenshtein distance to the best match. If there is
           *                     no match, returns `MAX_LEV_DISTANCE + 1`.
           */
-        function checkType(obj, val, literalSearch) {
-            var lev_distance = MAX_LEV_DISTANCE + 1;
-            var tmp_lev = MAX_LEV_DISTANCE + 1;
-            var len, x, firstGeneric;
-            if (obj[NAME] === val.name) {
-                if (literalSearch) {
-                    if (val.generics && val.generics.length !== 0) {
-                        if (obj.length > GENERICS_DATA &&
-                             obj[GENERICS_DATA].length > 0) {
-                            var elems = Object.create(null);
-                            len = obj[GENERICS_DATA].length;
-                            for (x = 0; x < len; ++x) {
-                                if (!elems[obj[GENERICS_DATA][x][NAME]]) {
-                                    elems[obj[GENERICS_DATA][x][NAME]] = 0;
-                                }
-                                elems[obj[GENERICS_DATA][x][NAME]] += 1;
-                            }
+        function checkType(row, elem, literalSearch) {
+            if (row[NAME].length === 0) {
+                // This is a pure "generic" search, no need to run other checks.
+                if (row.length > GENERICS_DATA) {
+                    return checkIfInGenerics(row, elem);
+                }
+                return MAX_LEV_DISTANCE + 1;
+            }
 
-                            len = val.generics.length;
-                            for (x = 0; x < len; ++x) {
-                                firstGeneric = val.generics[x];
-                                if (elems[firstGeneric]) {
-                                    elems[firstGeneric] -= 1;
-                                } else {
-                                    // Something wasn't found and this is a literal search so
-                                    // abort and return a "failing" distance.
-                                    return MAX_LEV_DISTANCE + 1;
-                                }
-                            }
-                            // Everything was found, success!
+            var lev = levenshtein(row[NAME], elem.name);
+            if (literalSearch) {
+                if (lev !== 0) {
+                    // The name didn't match, let's try to check if the generics do.
+                    if (elem.generics.length === 0) {
+                        var checkGeneric = (row.length > GENERICS_DATA &&
+                            row[GENERICS_DATA].length > 0);
+                        if (checkGeneric && row[GENERICS_DATA].findIndex(function(tmp_elem) {
+                            return tmp_elem[NAME] === elem.name;
+                        }) !== -1) {
                             return 0;
                         }
-                        return MAX_LEV_DISTANCE + 1;
                     }
-                    return 0;
-                } else {
-                    // If the type has generics but don't match, then it won't return at this point.
-                    // Otherwise, `checkGenerics` will return 0 and it'll return.
-                    if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length !== 0) {
-                        tmp_lev = checkGenerics(obj, val);
-                        if (tmp_lev <= MAX_LEV_DISTANCE) {
-                            return tmp_lev;
-                        }
-                    }
-                }
-            } else if (literalSearch) {
-                var found = false;
-                if ((!val.generics || val.generics.length === 0) &&
-                      obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
-                    found = obj[GENERICS_DATA].some(
-                        function(gen) {
-                            return gen[NAME] === val.name;
-                        });
-                }
-                return found ? 0 : MAX_LEV_DISTANCE + 1;
-            }
-            lev_distance = Math.min(levenshtein(obj[NAME], val.name), lev_distance);
-            if (lev_distance <= MAX_LEV_DISTANCE) {
-                // The generics didn't match but the name kinda did so we give it
-                // a levenshtein distance value that isn't *this* good so it goes
-                // into the search results but not too high.
-                lev_distance = Math.ceil((checkGenerics(obj, val) + lev_distance) / 2);
-            }
-            if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
-                // We can check if the type we're looking for is inside the generics!
-                var olength = obj[GENERICS_DATA].length;
-                for (x = 0; x < olength; ++x) {
-                    tmp_lev = Math.min(levenshtein(obj[GENERICS_DATA][x][NAME], val.name), tmp_lev);
+                    return MAX_LEV_DISTANCE + 1;
+                } else if (elem.generics.length > 0) {
+                    return checkGenerics(row, elem, MAX_LEV_DISTANCE + 1);
                 }
-                if (tmp_lev !== 0) {
-                    // If we didn't find a good enough result, we go check inside the generics of
-                    // the generics.
-                    for (x = 0; x < olength && tmp_lev !== 0; ++x) {
-                        tmp_lev = Math.min(
-                            checkType(obj[GENERICS_DATA][x], val, literalSearch),
-                            tmp_lev
-                        );
+                return 0;
+            } else if (row.length > GENERICS_DATA) {
+                if (elem.generics.length === 0) {
+                    if (lev === 0) {
+                        return 0;
+                    }
+                    // The name didn't match so we now check if the type we're looking for is inside
+                    // the generics!
+                    lev = checkIfInGenerics(row, elem);
+                    // Now whatever happens, the returned distance is "less good" so we should mark
+                    // it as such, and so we add 0.5 to the distance to make it "less good".
+                    return lev + 0.5;
+                } else if (lev > MAX_LEV_DISTANCE) {
+                    // So our item's name doesn't match at all and has generics.
+                    //
+                    // Maybe it's present in a sub generic? For example "f<A<B<C>>>()", if we're
+                    // looking for "B<C>", we'll need to go down.
+                    return checkIfInGenerics(row, elem);
+                } else {
+                    // At this point, the name kinda match and we have generics to check, so
+                    // let's go!
+                    var tmp_lev = checkGenerics(row, elem, lev);
+                    if (tmp_lev > MAX_LEV_DISTANCE) {
+                        return MAX_LEV_DISTANCE + 1;
                     }
+                    // We compute the median value of both checks and return it.
+                    return (tmp_lev + lev) / 2;
                 }
+            } else if (elem.generics.length > 0) {
+                // In this case, we were expecting generics but there isn't so we simply reject this
+                // one.
+                return MAX_LEV_DISTANCE + 1;
             }
-            // Now whatever happens, the returned distance is "less good" so we should mark it
-            // as such, and so we add 1 to the distance to make it "less good".
-            return Math.min(lev_distance, tmp_lev) + 1;
+            // No generics on our query or on the target type so we can return without doing
+            // anything else.
+            return lev;
         }
 
         /**
-         * This function checks if the object (`obj`) has an argument with the given type (`val`).
+         * This function checks if the object (`row`) has an argument with the given type (`elem`).
          *
-         * @param {Object} obj
-         * @param {string} val
-         * @param {boolean} literalSearch
+         * @param {Row} row
+         * @param {QueryElement} elem    - The element from the parsed query.
          * @param {integer} typeFilter
          *
          * @return {integer} - Returns a Levenshtein distance to the best match. If there is no
          *                      match, returns `MAX_LEV_DISTANCE + 1`.
          */
-        function findArg(obj, val, literalSearch, typeFilter) {
-            var lev_distance = MAX_LEV_DISTANCE + 1;
+        function findArg(row, elem, typeFilter) {
+            var lev = MAX_LEV_DISTANCE + 1;
 
-            if (obj && obj.type && obj.type[INPUTS_DATA] && obj.type[INPUTS_DATA].length > 0) {
-                var length = obj.type[INPUTS_DATA].length;
+            if (row && row.type && row.type[INPUTS_DATA] && row.type[INPUTS_DATA].length > 0) {
+                var length = row.type[INPUTS_DATA].length;
                 for (var i = 0; i < length; i++) {
-                    var tmp = obj.type[INPUTS_DATA][i];
+                    var tmp = row.type[INPUTS_DATA][i];
                     if (!typePassesFilter(typeFilter, tmp[1])) {
                         continue;
                     }
-                    tmp = checkType(tmp, val, literalSearch);
-                    if (tmp === 0) {
+                    lev = Math.min(lev, checkType(tmp, elem, parsedQuery.literalSearch));
+                    if (lev === 0) {
                         return 0;
-                    } else if (literalSearch) {
-                        continue;
                     }
-                    lev_distance = Math.min(tmp, lev_distance);
                 }
             }
-            return literalSearch ? MAX_LEV_DISTANCE + 1 : lev_distance;
+            return parsedQuery.literalSearch ? MAX_LEV_DISTANCE + 1 : lev;
         }
 
-        function checkReturned(obj, val, literalSearch, typeFilter) {
-            var lev_distance = MAX_LEV_DISTANCE + 1;
+        /**
+         * This function checks if the object (`row`) returns the given type (`elem`).
+         *
+         * @param {Row} row
+         * @param {QueryElement} elem   - The element from the parsed query.
+         * @param {integer} typeFilter
+         *
+         * @return {integer} - Returns a Levenshtein distance to the best match. If there is no
+         *                      match, returns `MAX_LEV_DISTANCE + 1`.
+         */
+        function checkReturned(row, elem, typeFilter) {
+            var lev = MAX_LEV_DISTANCE + 1;
 
-            if (obj && obj.type && obj.type.length > OUTPUT_DATA) {
-                var ret = obj.type[OUTPUT_DATA];
+            if (row && row.type && row.type.length > OUTPUT_DATA) {
+                var ret = row.type[OUTPUT_DATA];
                 if (typeof ret[0] === "string") {
                     ret = [ret];
                 }
@@ -537,16 +1073,13 @@ window.initSearch = function(rawSearchIndex) {
                     if (!typePassesFilter(typeFilter, tmp[1])) {
                         continue;
                     }
-                    tmp = checkType(tmp, val, literalSearch);
-                    if (tmp === 0) {
+                    lev = Math.min(lev, checkType(tmp, elem, parsedQuery.literalSearch));
+                    if (lev === 0) {
                         return 0;
-                    } else if (literalSearch) {
-                        continue;
                     }
-                    lev_distance = Math.min(tmp, lev_distance);
                 }
             }
-            return literalSearch ? MAX_LEV_DISTANCE + 1 : lev_distance;
+            return parsedQuery.literalSearch ? MAX_LEV_DISTANCE + 1 : lev;
         }
 
         function checkPath(contains, lastElem, ty) {
@@ -621,13 +1154,14 @@ window.initSearch = function(rawSearchIndex) {
         }
 
         function handleAliases(ret, query, filterCrates) {
+            var lowerQuery = query.toLowerCase();
             // We separate aliases and crate aliases because we want to have current crate
             // aliases to be before the others in the displayed results.
             var aliases = [];
             var crateAliases = [];
             if (filterCrates !== null) {
-                if (ALIASES[filterCrates] && ALIASES[filterCrates][query.search]) {
-                    var query_aliases = ALIASES[filterCrates][query.search];
+                if (ALIASES[filterCrates] && ALIASES[filterCrates][lowerQuery]) {
+                    var query_aliases = ALIASES[filterCrates][lowerQuery];
                     var len = query_aliases.length;
                     for (var i = 0; i < len; ++i) {
                         aliases.push(createAliasFromItem(searchIndex[query_aliases[i]]));
@@ -635,9 +1169,9 @@ window.initSearch = function(rawSearchIndex) {
                 }
             } else {
                 Object.keys(ALIASES).forEach(function(crate) {
-                    if (ALIASES[crate][query.search]) {
+                    if (ALIASES[crate][lowerQuery]) {
                         var pushTo = crate === window.currentCrate ? crateAliases : aliases;
-                        var query_aliases = ALIASES[crate][query.search];
+                        var query_aliases = ALIASES[crate][lowerQuery];
                         var len = query_aliases.length;
                         for (var i = 0; i < len; ++i) {
                             pushTo.push(createAliasFromItem(searchIndex[query_aliases[i]]));
@@ -658,7 +1192,7 @@ window.initSearch = function(rawSearchIndex) {
             aliases.sort(sortFunc);
 
             var pushFunc = function(alias) {
-                alias.alias = query.raw;
+                alias.alias = query;
                 var res = buildHrefAndPath(alias);
                 alias.displayPath = pathSplitter(res[0]);
                 alias.fullPath = alias.displayPath + alias.name;
@@ -674,208 +1208,237 @@ window.initSearch = function(rawSearchIndex) {
         }
 
         /**
-         * This function adds the given result into the provided `res` map if it matches the
+         * This function adds the given result into the provided `results` map if it matches the
          * following condition:
          *
-         * * If it is a "literal search" (`isExact`), then `lev` must be 0.
+         * * If it is a "literal search" (`parsedQuery.literalSearch`), then `lev` must be 0.
          * * If it is not a "literal search", `lev` must be <= `MAX_LEV_DISTANCE`.
          *
-         * The `res` map contains information which will be used to sort the search results:
+         * The `results` map contains information which will be used to sort the search results:
          *
-         * * `fullId` is a `string`` used as the key of the object we use for the `res` map.
+         * * `fullId` is a `string`` used as the key of the object we use for the `results` map.
          * * `id` is the index in both `searchWords` and `searchIndex` arrays for this element.
          * * `index` is an `integer`` used to sort by the position of the word in the item's name.
          * * `lev` is the main metric used to sort the search results.
          *
-         * @param {boolean} isExact
-         * @param {Object} res
+         * @param {Results} results
          * @param {string} fullId
          * @param {integer} id
          * @param {integer} index
          * @param {integer} lev
          */
-        function addIntoResults(isExact, res, fullId, id, index, lev) {
-            if (lev === 0 || (!isExact && lev <= MAX_LEV_DISTANCE)) {
-                if (res[fullId] !== undefined) {
-                    var result = res[fullId];
+        function addIntoResults(results, fullId, id, index, lev) {
+            if (lev === 0 || (!parsedQuery.literalSearch && lev <= MAX_LEV_DISTANCE)) {
+                if (results[fullId] !== undefined) {
+                    var result = results[fullId];
                     if (result.dontValidate || result.lev <= lev) {
                         return;
                     }
                 }
-                res[fullId] = {
+                results[fullId] = {
                     id: id,
                     index: index,
-                    dontValidate: isExact,
+                    dontValidate: parsedQuery.literalSearch,
                     lev: lev,
                 };
             }
         }
 
-        // quoted values mean literal search
-        var nSearchWords = searchWords.length;
-        var i, it;
-        var ty;
-        var fullId;
-        var returned;
-        var in_args;
-        var len;
-        if ((val.charAt(0) === "\"" || val.charAt(0) === "'") &&
-            val.charAt(val.length - 1) === val.charAt(0))
-        {
-            val = extractGenerics(val.substr(1, val.length - 2));
-            for (i = 0; i < nSearchWords; ++i) {
-                if (filterCrates !== null && searchIndex[i].crate !== filterCrates) {
-                    continue;
+        /**
+         * This function is called in case the query is only one element (with or without generics).
+         * This element will be compared to arguments' and returned values' items and also to items.
+         *
+         * Other important thing to note: since there is only one element, we use levenshtein
+         * distance for name comparisons.
+         *
+         * @param {Row} row
+         * @param {integer} pos              - Position in the `searchIndex`.
+         * @param {QueryElement} elem        - The element from the parsed query.
+         * @param {Results} results_others   - Unqualified results (not in arguments nor in
+         *                                     returned values).
+         * @param {Results} results_in_args  - Matching arguments results.
+         * @param {Results} results_returned - Matching returned arguments results.
+         */
+        function handleSingleArg(
+            row,
+            pos,
+            elem,
+            results_others,
+            results_in_args,
+            results_returned
+        ) {
+            if (!row || (filterCrates !== null && row.crate !== filterCrates)) {
+                return;
+            }
+            var lev, lev_add = 0, index = -1;
+            var fullId = row.id;
+
+            var in_args = findArg(row, elem, parsedQuery.typeFilter);
+            var returned = checkReturned(row, elem, parsedQuery.typeFilter);
+
+            addIntoResults(results_in_args, fullId, pos, index, in_args);
+            addIntoResults(results_returned, fullId, pos, index, returned);
+
+            if (!typePassesFilter(parsedQuery.typeFilter, row.ty)) {
+                return;
+            }
+            var searchWord = searchWords[pos];
+
+            if (parsedQuery.literalSearch) {
+                if (searchWord === elem.name) {
+                    addIntoResults(results_others, fullId, pos, -1, 0);
                 }
-                in_args = findArg(searchIndex[i], val, true, typeFilter);
-                returned = checkReturned(searchIndex[i], val, true, typeFilter);
-                ty = searchIndex[i];
-                fullId = ty.id;
-
-                if (searchWords[i] === val.name
-                    && typePassesFilter(typeFilter, searchIndex[i].ty)) {
-                    addIntoResults(true, results, fullId, i, -1, 0);
+                return;
+            }
+
+            // No need to check anything else if it's a "pure" generics search.
+            if (elem.name.length === 0) {
+                if (row.type !== null) {
+                    lev = checkGenerics(row.type, elem, MAX_LEV_DISTANCE + 1);
+                    addIntoResults(results_others, fullId, pos, index, lev);
                 }
-                addIntoResults(true, results_in_args, fullId, i, -1, in_args);
-                addIntoResults(true, results_returned, fullId, i, -1, returned);
-            }
-            query.inputs = [val];
-            query.output = val;
-            query.search = val;
-        // searching by type
-        } else if (val.search("->") > -1) {
-            var trimmer = function(s) { return s.trim(); };
-            var parts = val.split("->").map(trimmer);
-            var input = parts[0];
-            // sort inputs so that order does not matter
-            var inputs = input.split(",").map(trimmer).sort();
-            for (i = 0, len = inputs.length; i < len; ++i) {
-                inputs[i] = extractGenerics(inputs[i]);
-            }
-            var output = extractGenerics(parts[1]);
-
-            for (i = 0; i < nSearchWords; ++i) {
-                if (filterCrates !== null && searchIndex[i].crate !== filterCrates) {
-                    continue;
+                return;
+            }
+
+            if (elem.fullPath.length > 1) {
+                lev = checkPath(elem.pathWithoutLast, elem.pathLast, row);
+                if (lev > MAX_LEV_DISTANCE || (parsedQuery.literalSearch && lev !== 0)) {
+                    return;
+                } else if (lev > 0) {
+                    lev_add = lev / 10;
                 }
-                var type = searchIndex[i].type;
-                ty = searchIndex[i];
-                if (!type) {
-                    continue;
+            }
+
+            if (searchWord.indexOf(elem.pathLast) > -1 ||
+                row.normalizedName.indexOf(elem.pathLast) > -1)
+            {
+                // filter type: ... queries
+                if (!results_others[fullId] !== undefined) {
+                    index = row.normalizedName.indexOf(elem.pathLast);
                 }
-                fullId = ty.id;
+            }
+            lev = levenshtein(searchWord, elem.pathLast);
+            lev += lev_add;
+            if (lev > 0 && elem.pathLast.length > 2 && searchWord.indexOf(elem.pathLast) > -1)
+            {
+                if (elem.pathLast.length < 6) {
+                    lev = 1;
+                } else {
+                    lev = 0;
+                }
+            }
+            if (lev > MAX_LEV_DISTANCE) {
+                return;
+            } else if (index !== -1 && elem.fullPath.length < 2) {
+                lev -= 1;
+            }
+            if (lev < 0) {
+                lev = 0;
+            }
+            addIntoResults(results_others, fullId, pos, index, lev);
+        }
 
-                returned = checkReturned(ty, output, true, NO_TYPE_FILTER);
-                if (output.name === "*" || returned === 0) {
-                    in_args = false;
-                    var is_module = false;
+        /**
+         * This function is called in case the query has more than one element. In this case, it'll
+         * try to match the items which validates all the elements. For `aa -> bb` will look for
+         * functions which have a parameter `aa` and has `bb` in its returned values.
+         *
+         * @param {Row} row
+         * @param {integer} pos      - Position in the `searchIndex`.
+         * @param {Object} results
+         */
+        function handleArgs(row, pos, results) {
+            if (!row || (filterCrates !== null && row.crate !== filterCrates)) {
+                return;
+            }
 
-                    if (input === "*") {
-                        is_module = true;
+            var totalLev = 0;
+            var nbLev = 0;
+            var lev;
+
+            // If the result is too "bad", we return false and it ends this search.
+            function checkArgs(elems, callback) {
+                for (var i = 0, len = elems.length; i < len; ++i) {
+                    var elem = elems[i];
+                    // There is more than one parameter to the query so all checks should be "exact"
+                    lev = callback(row, elem, NO_TYPE_FILTER);
+                    if (lev <= 1) {
+                        nbLev += 1;
+                        totalLev += lev;
                     } else {
-                        var firstNonZeroDistance = 0;
-                        for (it = 0, len = inputs.length; it < len; it++) {
-                            var distance = checkType(type, inputs[it], true);
-                            if (distance > 0) {
-                                firstNonZeroDistance = distance;
-                                break;
-                            }
-                        }
-                        in_args = firstNonZeroDistance;
-                    }
-                    addIntoResults(true, results_in_args, fullId, i, -1, in_args);
-                    addIntoResults(true, results_returned, fullId, i, -1, returned);
-                    if (is_module) {
-                        addIntoResults(true, results, fullId, i, -1, 0);
+                        return false;
                     }
                 }
+                return true;
+            }
+            if (!checkArgs(parsedQuery.elems, findArg)) {
+                return;
+            }
+            if (!checkArgs(parsedQuery.returned, checkReturned)) {
+                return;
             }
-            query.inputs = inputs.map(function(input) {
-                return input.name;
-            });
-            query.output = output.name;
-        } else {
-            query.inputs = [val];
-            query.output = val;
-            query.search = val;
-            // gather matching search results up to a certain maximum
-            val = val.replace(/_/g, "");
-
-            var valGenerics = extractGenerics(val);
-
-            var paths = valLower.split("::");
-            removeEmptyStringsFromArray(paths);
-            val = paths[paths.length - 1];
-            var contains = paths.slice(0, paths.length > 1 ? paths.length - 1 : 1);
-
-            var lev, j;
-            for (j = 0; j < nSearchWords; ++j) {
-                ty = searchIndex[j];
-                if (!ty || (filterCrates !== null && ty.crate !== filterCrates)) {
-                    continue;
-                }
-                var lev_add = 0;
-                if (paths.length > 1) {
-                    lev = checkPath(contains, paths[paths.length - 1], ty);
-                    if (lev > MAX_LEV_DISTANCE) {
-                        continue;
-                    } else if (lev > 0) {
-                        lev_add = lev / 10;
-                    }
-                }
 
-                returned = MAX_LEV_DISTANCE + 1;
-                in_args = MAX_LEV_DISTANCE + 1;
-                var index = -1;
-                // we want lev results to go lower than others
-                lev = MAX_LEV_DISTANCE + 1;
-                fullId = ty.id;
+            if (nbLev === 0) {
+                return;
+            }
+            lev = Math.round(totalLev / nbLev);
+            addIntoResults(results, row.id, pos, 0, lev);
+        }
 
-                if (searchWords[j].indexOf(split[i]) > -1 ||
-                    searchWords[j].indexOf(val) > -1 ||
-                    ty.normalizedName.indexOf(val) > -1)
-                {
-                    // filter type: ... queries
-                    if (typePassesFilter(typeFilter, ty.ty) && results[fullId] === undefined) {
-                        index = ty.normalizedName.indexOf(val);
+        function innerRunQuery() {
+            var elem, i, nSearchWords, in_returned, row;
+
+            if (parsedQuery.foundElems === 1) {
+                if (parsedQuery.elems.length === 1) {
+                    elem = parsedQuery.elems[0];
+                    for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {
+                        // It means we want to check for this element everywhere (in names, args and
+                        // returned).
+                        handleSingleArg(
+                            searchIndex[i],
+                            i,
+                            elem,
+                            results_others,
+                            results_in_args,
+                            results_returned
+                        );
                     }
-                }
-                if ((lev = levenshtein(searchWords[j], val)) <= MAX_LEV_DISTANCE) {
-                    if (typePassesFilter(typeFilter, ty.ty)) {
-                        lev += 1;
-                    } else {
-                        lev = MAX_LEV_DISTANCE + 1;
+                } else if (parsedQuery.returned.length === 1) {
+                    // We received one returned argument to check, so looking into returned values.
+                    elem = parsedQuery.returned[0];
+                    for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {
+                        row = searchIndex[i];
+                        in_returned = checkReturned(row, elem, parsedQuery.typeFilter);
+                        addIntoResults(results_returned, row.id, i, -1, in_returned);
                     }
                 }
-                in_args = findArg(ty, valGenerics, false, typeFilter);
-                returned = checkReturned(ty, valGenerics, false, typeFilter);
-
-                lev += lev_add;
-                if (lev > 0 && val.length > 3 && searchWords[j].indexOf(val) > -1) {
-                    if (val.length < 6) {
-                        lev -= 1;
-                    } else {
-                        lev = 0;
-                    }
+            } else if (parsedQuery.foundElems > 0) {
+                var container = results_others;
+                // In the special case where only a "returned" information is available, we want to
+                // put the information into the "results_returned" dict.
+                if (parsedQuery.returned.length !== 0 && parsedQuery.elems.length === 0) {
+                    container = results_returned;
                 }
-                addIntoResults(false, results_in_args, fullId, j, index, in_args);
-                addIntoResults(false, results_returned, fullId, j, index, returned);
-                if (typePassesFilter(typeFilter, ty.ty) &&
-                        (index !== -1 || lev <= MAX_LEV_DISTANCE)) {
-                    if (index !== -1 && paths.length < 2) {
-                        lev = 0;
-                    }
-                    addIntoResults(false, results, fullId, j, index, lev);
+                for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {
+                    handleArgs(searchIndex[i], i, container);
                 }
             }
         }
 
-        var ret = {
-            "in_args": sortResults(results_in_args, true),
-            "returned": sortResults(results_returned, true),
-            "others": sortResults(results, false),
-        };
-        handleAliases(ret, query, filterCrates);
+        if (parsedQuery.error === null) {
+            innerRunQuery();
+        }
+
+        var ret = createQueryResults(
+            sortResults(results_in_args, true),
+            sortResults(results_returned, true),
+            sortResults(results_others, false),
+            parsedQuery);
+        handleAliases(ret, parsedQuery.original.replace(/"/g, ""), filterCrates);
+        if (parsedQuery.error !== null && ret.others.length !== 0) {
+            // It means some doc aliases were found so let's "remove" the error!
+            ret.query.error = null;
+        }
         return ret;
     }
 
@@ -892,9 +1455,13 @@ window.initSearch = function(rawSearchIndex) {
      * @param  {string} path   - The path of the result
      * @param  {string} keys   - The keys to be used (["file", "open"])
      * @param  {Object} parent - The parent of the result
+     *
      * @return {boolean}       - Whether the result is valid or not
      */
     function validateResult(name, path, keys, parent) {
+        if (!keys || !keys.length) {
+            return true;
+        }
         for (var i = 0, len = keys.length; i < len; ++i) {
             // each check is for validation so we negate the conditions and invalidate
             if (!(
@@ -913,30 +1480,6 @@ window.initSearch = function(rawSearchIndex) {
         return true;
     }
 
-    /**
-     * Parse a string into a query object.
-     *
-     * @param {string} raw - The text that the user typed.
-     * @returns {ParsedQuery}
-     */
-    function getQuery(raw) {
-        var matches, type = "", query;
-        query = raw;
-
-        matches = query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);
-        if (matches) {
-            type = matches[1].replace(/^const$/, "constant");
-            query = query.substring(matches[0].length);
-        }
-
-        return {
-            raw: raw,
-            query: query,
-            type: type,
-            id: query + type
-        };
-    }
-
     function nextTab(direction) {
         var next = (searchState.currentTab + direction + 3) % searchState.focusedByTab.length;
         searchState.focusedByTab[searchState.currentTab] = document.activeElement;
@@ -1088,11 +1631,11 @@ window.initSearch = function(rawSearchIndex) {
                 link.appendChild(wrapper);
                 output.appendChild(link);
             });
-        } else {
+        } else if (query.error === null) {
             output.className = "search-failed" + extraClass;
             output.innerHTML = "No results :(<br/>" +
                 "Try on <a href=\"https://duckduckgo.com/?q=" +
-                encodeURIComponent("rust " + query.query) +
+                encodeURIComponent("rust " + query.userQuery) +
                 "\">DuckDuckGo</a>?<br/><br/>" +
                 "Or try looking in one of these:<ul><li>The <a " +
                 "href=\"https://doc.rust-lang.org/reference/index.html\">Rust Reference</a> " +
@@ -1115,6 +1658,11 @@ window.initSearch = function(rawSearchIndex) {
         return "<button>" + text + " <div class=\"count\">(" + nbElems + ")</div></button>";
     }
 
+    /**
+     * @param {ResultsTable} results
+     * @param {boolean} go_to_first
+     * @param {string} filterCrates
+     */
     function showResults(results, go_to_first, filterCrates) {
         var search = searchState.outputElement();
         if (go_to_first || (results.others.length === 1
@@ -1132,13 +1680,15 @@ window.initSearch = function(rawSearchIndex) {
             elem.click();
             return;
         }
-        var query = getQuery(searchState.input.value);
+        if (results.query === undefined) {
+            results.query = parseQuery(searchState.input.value);
+        }
 
-        currentResults = query.id;
+        currentResults = results.query.userQuery;
 
-        var ret_others = addTab(results.others, query, true);
-        var ret_in_args = addTab(results.in_args, query, false);
-        var ret_returned = addTab(results.returned, query, false);
+        var ret_others = addTab(results.others, results.query, true);
+        var ret_in_args = addTab(results.in_args, results.query, false);
+        var ret_returned = addTab(results.returned, results.query, false);
 
         // Navigate to the relevant tab if the current tab is empty, like in case users search
         // for "-> String". If they had selected another tab previously, they have to click on
@@ -1164,11 +1714,19 @@ window.initSearch = function(rawSearchIndex) {
             }
             crates += `</select>`;
         }
-        var output = `<div id="search-settings">
-            <h1 class="search-results-title">Results for ${escape(query.query)} ` +
-            (query.type ? " (type: " + escape(query.type) + ")" : "") + "</h1>" +
-            crates +
-            `</div><div id="titles">` +
+
+        var typeFilter = "";
+        if (results.query.typeFilter !== NO_TYPE_FILTER) {
+            typeFilter = " (type: " + escape(itemTypes[results.query.typeFilter]) + ")";
+        }
+
+        var output = `<div id="search-settings">` +
+            `<h1 class="search-results-title">Results for ${escape(results.query.userQuery)}` +
+            `${typeFilter}</h1> in ${crates} </div>`;
+        if (results.query.error !== null) {
+            output += `<h3>Query parser error: "${results.query.error}".</h3>`;
+        }
+        output += `<div id="titles">` +
             makeTabHeader(0, "In Names", ret_others[1]) +
             makeTabHeader(1, "In Parameters", ret_in_args[1]) +
             makeTabHeader(2, "In Return Types", ret_returned[1]) +
@@ -1196,28 +1754,6 @@ window.initSearch = function(rawSearchIndex) {
         printTab(currentTab);
     }
 
-    function execSearch(query, searchWords, filterCrates) {
-        query = query.raw.trim();
-        var results = {
-            "in_args": [],
-            "returned": [],
-            "others": [],
-        };
-
-        if (query.length !== 0) {
-            var tmp = execQuery(getQuery(query), searchWords, filterCrates);
-
-            results.in_args.push(tmp.in_args);
-            results.returned.push(tmp.returned);
-            results.others.push(tmp.others);
-        }
-        return {
-            "in_args": results.in_args[0],
-            "returned": results.returned[0],
-            "others": results.others[0],
-        };
-    }
-
     /**
      * Perform a search based on the current state of the search input element
      * and display the results.
@@ -1226,17 +1762,14 @@ window.initSearch = function(rawSearchIndex) {
      */
     function search(e, forced) {
         var params = searchState.getQueryStringParams();
-        var query = getQuery(searchState.input.value.trim());
+        var query = parseQuery(searchState.input.value.trim());
 
         if (e) {
             e.preventDefault();
         }
 
-        if (query.query.length === 0) {
-            return;
-        }
-        if (!forced && query.id === currentResults) {
-            if (query.query.length > 0) {
+        if (!forced && query.userQuery === currentResults) {
+            if (query.userQuery.length > 0) {
                 putBackSearch();
             }
             return;
@@ -1251,13 +1784,12 @@ window.initSearch = function(rawSearchIndex) {
         }
 
         // Update document title to maintain a meaningful browser history
-        searchState.title = "Results for " + query.query + " - Rust";
+        searchState.title = "Results for " + query.original + " - Rust";
 
         // Because searching is incremental by character, only the most
         // recent search query is added to the browser history.
         if (searchState.browserSupportsHistoryApi()) {
-            var newURL = buildUrl(query.raw, filterCrates);
-
+            var newURL = buildUrl(query.original, filterCrates);
             if (!history.state && !params.search) {
                 history.pushState(null, "", newURL);
             } else {
@@ -1265,8 +1797,10 @@ window.initSearch = function(rawSearchIndex) {
             }
         }
 
-        showResults(execSearch(query, searchWords, filterCrates),
-            params["go_to_first"], filterCrates);
+        showResults(
+            execQuery(query, searchWords, filterCrates),
+            params.go_to_first,
+            filterCrates);
     }
 
     function buildIndex(rawSearchIndex) {
index a9a6a31fccd0d7c8b3457feda0250b6fab56bc83..56b02cd848041236e30fab13cfc70fa0de4f62ff 100644 (file)
@@ -10,7 +10,6 @@
 use rustc_ast::ast;
 use rustc_hir::{def::CtorKind, def_id::DefId};
 use rustc_middle::ty::{self, TyCtxt};
-use rustc_span::def_id::CRATE_DEF_INDEX;
 use rustc_span::Pos;
 use rustc_target::spec::abi::Abi as RustcAbi;
 
@@ -27,7 +26,7 @@ pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> {
         let links = self
             .cache
             .intra_doc_links
-            .get(&item.def_id)
+            .get(&item.item_id)
             .into_iter()
             .flatten()
             .map(|clean::ItemLink { link, did, .. }| (link.clone(), from_item_id((*did).into())))
@@ -40,14 +39,14 @@ pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> {
             .map(rustc_ast_pretty::pprust::attribute_to_string)
             .collect();
         let span = item.span(self.tcx);
-        let clean::Item { name, attrs: _, kind: _, visibility, def_id, cfg: _ } = item;
+        let clean::Item { name, attrs: _, kind: _, visibility, item_id, cfg: _ } = item;
         let inner = match *item.kind {
             clean::StrippedItem(_) => return None,
             _ => from_clean_item(item, self.tcx),
         };
         Some(Item {
-            id: from_item_id(def_id),
-            crate_id: def_id.krate().as_u32(),
+            id: from_item_id(item_id),
+            crate_id: item_id.krate().as_u32(),
             name: name.map(|sym| sym.to_string()),
             span: self.convert_span(span),
             visibility: self.convert_visibility(visibility),
@@ -83,7 +82,7 @@ fn convert_visibility(&self, v: clean::Visibility) -> Visibility {
         match v {
             Public => Visibility::Public,
             Inherited => Visibility::Default,
-            Restricted(did) if did.index == CRATE_DEF_INDEX => Visibility::Crate,
+            Restricted(did) if did.is_crate_root() => Visibility::Crate,
             Restricted(did) => Visibility::Restricted {
                 parent: from_item_id(did.into()),
                 path: self.tcx.def_path(did).to_string_no_crate_verbose(),
@@ -174,7 +173,7 @@ fn from_tcx(kind: clean::TypeBindingKind, tcx: TyCtxt<'_>) -> Self {
     }
 }
 
-crate fn from_item_id(did: ItemId) -> Id {
+crate fn from_item_id(item_id: ItemId) -> Id {
     struct DisplayDefId(DefId);
 
     impl fmt::Display for DisplayDefId {
@@ -183,7 +182,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         }
     }
 
-    match did {
+    match item_id {
         ItemId::DefId(did) => Id(format!("{}", DisplayDefId(did))),
         ItemId::Blanket { for_, impl_id } => {
             Id(format!("b:{}-{}", DisplayDefId(impl_id), DisplayDefId(for_)))
@@ -732,5 +731,5 @@ fn from_tcx(kind: ItemType, _tcx: TyCtxt<'_>) -> Self {
 }
 
 fn ids(items: impl IntoIterator<Item = clean::Item>) -> Vec<Id> {
-    items.into_iter().filter(|x| !x.is_stripped()).map(|i| from_item_id(i.def_id)).collect()
+    items.into_iter().filter(|x| !x.is_stripped()).map(|i| from_item_id(i.item_id)).collect()
 }
index 126c5d89ca97c03896c61f9d512fc76488cc763e..e6e5bba7f006745d94d8cba6ef31d283f76192bc 100644 (file)
@@ -54,7 +54,7 @@ fn get_trait_implementors(&mut self, id: DefId) -> Vec<types::Id> {
                     .map(|i| {
                         let item = &i.impl_item;
                         self.item(item.clone()).unwrap();
-                        from_item_id(item.def_id)
+                        from_item_id(item.item_id)
                     })
                     .collect()
             })
@@ -84,9 +84,9 @@ fn get_impls(&mut self, id: DefId) -> Vec<types::Id> {
                             }
                         }
 
-                        if item.def_id.is_local() || is_primitive_impl {
+                        if item.item_id.is_local() || is_primitive_impl {
                             self.item(item.clone()).unwrap();
-                            Some(from_item_id(item.def_id))
+                            Some(from_item_id(item.item_id))
                         } else {
                             None
                         }
@@ -176,18 +176,18 @@ fn item(&mut self, item: clean::Item) -> Result<(), Error> {
         // Flatten items that recursively store other items
         item.kind.inner_items().for_each(|i| self.item(i.clone()).unwrap());
 
-        let id = item.def_id;
+        let item_id = item.item_id;
         if let Some(mut new_item) = self.convert_item(item) {
             if let types::ItemEnum::Trait(ref mut t) = new_item.inner {
-                t.implementations = self.get_trait_implementors(id.expect_def_id())
+                t.implementations = self.get_trait_implementors(item_id.expect_def_id())
             } else if let types::ItemEnum::Struct(ref mut s) = new_item.inner {
-                s.impls = self.get_impls(id.expect_def_id())
+                s.impls = self.get_impls(item_id.expect_def_id())
             } else if let types::ItemEnum::Enum(ref mut e) = new_item.inner {
-                e.impls = self.get_impls(id.expect_def_id())
+                e.impls = self.get_impls(item_id.expect_def_id())
             } else if let types::ItemEnum::Union(ref mut u) = new_item.inner {
-                u.impls = self.get_impls(id.expect_def_id())
+                u.impls = self.get_impls(item_id.expect_def_id())
             }
-            let removed = self.index.borrow_mut().insert(from_item_id(id), new_item.clone());
+            let removed = self.index.borrow_mut().insert(from_item_id(item_id), new_item.clone());
 
             // FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check
             // to make sure the items are unique. The main place this happens is when an item, is
index 0fcfabba4c0a12bec4075833fbad95ba14ed0ddc..cd196a01847991d108335f367f35fe0f28b7e68b 100644 (file)
@@ -795,6 +795,7 @@ fn main_options(options: config::Options) -> MainResult {
                 let resolver_caches = resolver.borrow_mut().access(|resolver| {
                     collect_intra_doc_links::early_resolve_intra_doc_links(
                         resolver,
+                        sess,
                         krate,
                         externs,
                         document_private,
index 81f371840ae4638ecc6534728216ae57dbf2a35c..1839a35a8b14bb38f24ef318a4a0ffd4ab38c14e 100644 (file)
@@ -61,7 +61,7 @@ fn find_raw_urls(
 
 impl<'a, 'tcx> DocVisitor for BareUrlsLinter<'a, 'tcx> {
     fn visit_item(&mut self, item: &Item) {
-        let Some(hir_id) = DocContext::as_local_hir_id(self.cx.tcx, item.def_id)
+        let Some(hir_id) = DocContext::as_local_hir_id(self.cx.tcx, item.item_id)
         else {
             // If non-local, no need to check anything.
             return;
index 6111c982de92253b51f52c65d86910dbaeaf5f35..33d83aa339d95313441d9f47a2e6cab5285b5ac9 100644 (file)
@@ -185,7 +185,7 @@ fn print_table_record(
 
 impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> {
     fn visit_item(&mut self, i: &clean::Item) {
-        if !i.def_id.is_local() {
+        if !i.item_id.is_local() {
             // non-local items are skipped because they can be out of the users control,
             // especially in the case of trait impls, which rustdoc eagerly inlines
             return;
@@ -223,7 +223,7 @@ fn visit_item(&mut self, i: &clean::Item) {
                     .ctx
                     .tcx
                     .hir()
-                    .local_def_id_to_hir_id(i.def_id.expect_def_id().expect_local());
+                    .local_def_id_to_hir_id(i.item_id.expect_def_id().expect_local());
                 let (level, source) = self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id);
 
                 // In case we have:
@@ -237,7 +237,7 @@ fn visit_item(&mut self, i: &clean::Item) {
                 // there is no need to require documentation on the fields of tuple variants and
                 // tuple structs.
                 let should_be_ignored = i
-                    .def_id
+                    .item_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))
index d66dfca07f186850f5893d4cffb7964fad6ec0e5..23d947c4d7227e74c869b64bef89eda9261588ea 100644 (file)
@@ -69,7 +69,7 @@ fn check_rust_syntax(&self, item: &clean::Item, dox: &str, code_block: RustCodeB
             return;
         }
 
-        let Some(local_id) = item.def_id.as_def_id().and_then(|x| x.as_local())
+        let Some(local_id) = item.item_id.as_def_id().and_then(|x| x.as_local())
         else {
             // We don't need to check the syntax for other crates so returning
             // without doing anything should not be a problem.
@@ -153,7 +153,7 @@ fn visit_item(&mut self, item: &clean::Item) {
             let sp = item.attr_span(self.cx.tcx);
             let extra = crate::html::markdown::ExtraInfo::new_did(
                 self.cx.tcx,
-                item.def_id.expect_def_id(),
+                item.item_id.expect_def_id(),
                 sp,
             );
             for code_block in markdown::rust_code_blocks(dox, &extra) {
index b541fb63bd413422e694053c68a2bb86cb28a63f..80a2683fde7f4f87fd2cae41e2f7bfc2766c17d7 100644 (file)
@@ -56,7 +56,7 @@ fn add_test(&mut self, _: String, config: LangString, _: usize) {
 }
 
 crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> bool {
-    if !cx.cache.access_levels.is_public(item.def_id.expect_def_id())
+    if !cx.cache.access_levels.is_public(item.item_id.expect_def_id())
         || matches!(
             *item.kind,
             clean::StructFieldItem(_)
@@ -79,7 +79,7 @@ fn add_test(&mut self, _: String, config: LangString, _: usize) {
 
     // 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());
+    let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.item_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) {
@@ -107,7 +107,7 @@ fn add_test(&mut self, _: String, config: LangString, _: usize) {
 }
 
 crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
-    let Some(hir_id) = DocContext::as_local_hir_id(cx.tcx, item.def_id)
+    let Some(hir_id) = DocContext::as_local_hir_id(cx.tcx, item.item_id)
     else {
         // If non-local, no need to check anything.
         return;
@@ -131,7 +131,7 @@ fn add_test(&mut self, _: String, config: LangString, _: usize) {
             );
         }
     } else if tests.found_tests > 0
-        && !cx.cache.access_levels.is_exported(item.def_id.expect_def_id())
+        && !cx.cache.access_levels.is_exported(item.item_id.expect_def_id())
     {
         cx.tcx.struct_span_lint_hir(
             crate::lint::PRIVATE_DOC_TESTS,
index c1b1139ad8cf95ec5ac178662a6fbebe774c5185..42e87f3f9610b1b54cb855fce0679998e7cce810 100644 (file)
@@ -3,6 +3,7 @@
 //! [RFC 1946]: https://github.com/rust-lang/rfcs/blob/master/text/1946-intra-rustdoc-links.md
 
 use pulldown_cmark::LinkType;
+use rustc_ast::util::comments::may_have_doc_links;
 use rustc_data_structures::{fx::FxHashMap, intern::Interned, stable_set::FxHashSet};
 use rustc_errors::{Applicability, Diagnostic};
 use rustc_hir::def::Namespace::*;
@@ -159,7 +160,7 @@ fn try_from(res: ResolveRes) -> Result<Self, ()> {
 }
 
 /// A link failed to resolve.
-#[derive(Debug)]
+#[derive(Clone, Debug)]
 enum ResolutionFailure<'a> {
     /// This resolved, but with the wrong namespace.
     WrongNamespace {
@@ -199,7 +200,7 @@ enum ResolutionFailure<'a> {
     Dummy,
 }
 
-#[derive(Debug)]
+#[derive(Clone, Debug)]
 enum MalformedGenerics {
     /// This link has unbalanced angle brackets.
     ///
@@ -252,6 +253,7 @@ fn full_res(&self) -> Option<Res> {
     }
 }
 
+#[derive(Clone, Copy)]
 enum AnchorFailure {
     /// User error: `[std#x#y]` is not valid
     MultipleAnchors,
@@ -556,7 +558,15 @@ fn resolve_path(
         // Resolver doesn't know about true, false, and types that aren't paths (e.g. `()`).
         let result = self
             .cx
-            .enter_resolver(|resolver| resolver.resolve_rustdoc_path(path_str, ns, module_id))
+            .resolver_caches
+            .doc_link_resolutions
+            .get(&(Symbol::intern(path_str), ns, module_id))
+            .copied()
+            .unwrap_or_else(|| {
+                self.cx.enter_resolver(|resolver| {
+                    resolver.resolve_rustdoc_path(path_str, ns, module_id)
+                })
+            })
             .and_then(|res| res.try_into().ok())
             .or_else(|| resolve_primitive(path_str, ns))
             .or_else(|| self.resolve_macro_rules(path_str, ns));
@@ -1025,37 +1035,50 @@ fn is_derive_trait_collision<T>(ns: &PerNS<Result<(Res, T), ResolutionFailure<'_
 impl<'a, 'tcx> DocVisitor for LinkCollector<'a, 'tcx> {
     fn visit_item(&mut self, item: &Item) {
         let parent_node =
-            item.def_id.as_def_id().and_then(|did| find_nearest_parent_module(self.cx.tcx, did));
+            item.item_id.as_def_id().and_then(|did| find_nearest_parent_module(self.cx.tcx, did));
         if parent_node.is_some() {
-            trace!("got parent node for {:?} {:?}, id {:?}", item.type_(), item.name, item.def_id);
+            trace!("got parent node for {:?} {:?}, id {:?}", item.type_(), item.name, item.item_id);
         }
 
         let inner_docs = item.inner_docs(self.cx.tcx);
 
         if item.is_mod() && inner_docs {
-            self.mod_ids.push(item.def_id.expect_def_id());
+            self.mod_ids.push(item.item_id.expect_def_id());
         }
 
         // We want to resolve in the lexical scope of the documentation.
         // In the presence of re-exports, this is not the same as the module of the item.
         // Rather than merging all documentation into one, resolve it one attribute at a time
         // so we know which module it came from.
-        for (parent_module, doc) in item.attrs.collapsed_doc_value_by_module_level() {
+        for (parent_module, doc) in item.attrs.prepare_to_doc_link_resolution() {
+            if !may_have_doc_links(&doc) {
+                continue;
+            }
             debug!("combined_docs={}", doc);
             // NOTE: if there are links that start in one crate and end in another, this will not resolve them.
             // This is a degenerate case and it's not supported by rustdoc.
             let parent_node = parent_module.or(parent_node);
-            for md_link in markdown_links(&doc) {
+            let mut tmp_links = self
+                .cx
+                .resolver_caches
+                .markdown_links
+                .take()
+                .expect("`markdown_links` are already borrowed");
+            if !tmp_links.contains_key(&doc) {
+                tmp_links.insert(doc.clone(), preprocessed_markdown_links(&doc));
+            }
+            for md_link in &tmp_links[&doc] {
                 let link = self.resolve_link(&item, &doc, parent_node, md_link);
                 if let Some(link) = link {
-                    self.cx.cache.intra_doc_links.entry(item.def_id).or_default().push(link);
+                    self.cx.cache.intra_doc_links.entry(item.item_id).or_default().push(link);
                 }
             }
+            self.cx.resolver_caches.markdown_links = Some(tmp_links);
         }
 
         if item.is_mod() {
             if !inner_docs {
-                self.mod_ids.push(item.def_id.expect_def_id());
+                self.mod_ids.push(item.item_id.expect_def_id());
             }
 
             self.visit_item_recur(item);
@@ -1066,18 +1089,19 @@ fn visit_item(&mut self, item: &Item) {
     }
 }
 
-enum PreprocessingError<'a> {
+enum PreprocessingError {
     Anchor(AnchorFailure),
     Disambiguator(Range<usize>, String),
-    Resolution(ResolutionFailure<'a>, String, Option<Disambiguator>),
+    Resolution(ResolutionFailure<'static>, String, Option<Disambiguator>),
 }
 
-impl From<AnchorFailure> for PreprocessingError<'_> {
+impl From<AnchorFailure> for PreprocessingError {
     fn from(err: AnchorFailure) -> Self {
         Self::Anchor(err)
     }
 }
 
+#[derive(Clone)]
 struct PreprocessingInfo {
     path_str: String,
     disambiguator: Option<Disambiguator>,
@@ -1085,15 +1109,18 @@ struct PreprocessingInfo {
     link_text: String,
 }
 
+// Not a typedef to avoid leaking several private structures from this module.
+crate struct PreprocessedMarkdownLink(Result<PreprocessingInfo, PreprocessingError>, MarkdownLink);
+
 /// Returns:
 /// - `None` if the link should be ignored.
 /// - `Some(Err)` if the link should emit an error
 /// - `Some(Ok)` if the link is valid
 ///
 /// `link_buffer` is needed for lifetime reasons; it will always be overwritten and the contents ignored.
-fn preprocess_link<'a>(
-    ori_link: &'a MarkdownLink,
-) -> Option<Result<PreprocessingInfo, PreprocessingError<'a>>> {
+fn preprocess_link(
+    ori_link: &MarkdownLink,
+) -> Option<Result<PreprocessingInfo, PreprocessingError>> {
     // [] is mostly likely not supposed to be a link
     if ori_link.link.is_empty() {
         return None;
@@ -1172,6 +1199,12 @@ fn preprocess_link<'a>(
     }))
 }
 
+fn preprocessed_markdown_links(s: &str) -> Vec<PreprocessedMarkdownLink> {
+    markdown_links(s, |link| {
+        preprocess_link(&link).map(|pp_link| PreprocessedMarkdownLink(pp_link, link))
+    })
+}
+
 impl LinkCollector<'_, '_> {
     /// This is the entry point for resolving an intra-doc link.
     ///
@@ -1181,8 +1214,9 @@ fn resolve_link(
         item: &Item,
         dox: &str,
         parent_node: Option<DefId>,
-        ori_link: MarkdownLink,
+        link: &PreprocessedMarkdownLink,
     ) -> Option<ItemLink> {
+        let PreprocessedMarkdownLink(pp_link, ori_link) = link;
         trace!("considering link '{}'", ori_link.link);
 
         let diag_info = DiagnosticInfo {
@@ -1192,28 +1226,29 @@ fn resolve_link(
             link_range: ori_link.range.clone(),
         };
 
-        let PreprocessingInfo { ref path_str, disambiguator, extra_fragment, link_text } =
-            match preprocess_link(&ori_link)? {
-                Ok(x) => x,
-                Err(err) => {
-                    match err {
-                        PreprocessingError::Anchor(err) => anchor_failure(self.cx, diag_info, err),
-                        PreprocessingError::Disambiguator(range, msg) => {
-                            disambiguator_error(self.cx, diag_info, range, &msg)
-                        }
-                        PreprocessingError::Resolution(err, path_str, disambiguator) => {
-                            resolution_failure(
-                                self,
-                                diag_info,
-                                &path_str,
-                                disambiguator,
-                                smallvec![err],
-                            );
-                        }
+        let PreprocessingInfo { path_str, disambiguator, extra_fragment, link_text } = match pp_link
+        {
+            Ok(x) => x,
+            Err(err) => {
+                match err {
+                    PreprocessingError::Anchor(err) => anchor_failure(self.cx, diag_info, *err),
+                    PreprocessingError::Disambiguator(range, msg) => {
+                        disambiguator_error(self.cx, diag_info, range.clone(), msg)
+                    }
+                    PreprocessingError::Resolution(err, path_str, disambiguator) => {
+                        resolution_failure(
+                            self,
+                            diag_info,
+                            path_str,
+                            *disambiguator,
+                            smallvec![err.clone()],
+                        );
                     }
-                    return None;
                 }
-            };
+                return None;
+            }
+        };
+        let disambiguator = *disambiguator;
 
         let inner_docs = item.inner_docs(self.cx.tcx);
 
@@ -1246,11 +1281,11 @@ fn resolve_link(
 
         let (mut res, fragment) = self.resolve_with_disambiguator_cached(
             ResolutionInfo {
-                item_id: item.def_id,
+                item_id: item.item_id,
                 module_id,
                 dis: disambiguator,
                 path_str: path_str.to_owned(),
-                extra_fragment,
+                extra_fragment: extra_fragment.clone(),
             },
             diag_info.clone(), // this struct should really be Copy, but Range is not :(
             matches!(ori_link.kind, LinkType::Reference | LinkType::Shortcut),
@@ -1302,7 +1337,7 @@ fn resolve_link(
                     // FIXME: it would be nice to check that the feature gate was enabled in the original crate, not just ignore it altogether.
                     // However I'm not sure how to check that across crates.
                     if prim == PrimitiveType::RawPointer
-                        && item.def_id.is_local()
+                        && item.item_id.is_local()
                         && !self.cx.tcx.features().intra_doc_pointers
                     {
                         self.report_rawptr_assoc_feature_gate(dox, &ori_link, item);
@@ -1320,8 +1355,8 @@ fn resolve_link(
                 }
 
                 Some(ItemLink {
-                    link: ori_link.link,
-                    link_text,
+                    link: ori_link.link.clone(),
+                    link_text: link_text.clone(),
                     did: res.def_id(self.cx.tcx),
                     fragment,
                 })
@@ -1343,7 +1378,12 @@ fn resolve_link(
                     &diag_info,
                 )?;
                 let id = clean::register_res(self.cx, rustc_hir::def::Res::Def(kind, id));
-                Some(ItemLink { link: ori_link.link, link_text, did: id, fragment })
+                Some(ItemLink {
+                    link: ori_link.link.clone(),
+                    link_text: link_text.clone(),
+                    did: id,
+                    fragment,
+                })
             }
         }
     }
@@ -1386,7 +1426,7 @@ fn verify_disambiguator(
             // The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
             // would presumably panic if a fake `DefIndex` were passed.
             .and_then(|dst_id| {
-                item.def_id.expect_def_id().as_local().map(|src_id| (src_id, dst_id))
+                item.item_id.expect_def_id().as_local().map(|src_id| (src_id, dst_id))
             })
         {
             if self.cx.tcx.privacy_access_levels(()).is_exported(src_id)
@@ -1864,7 +1904,7 @@ fn report_diagnostic(
     DiagnosticInfo { item, ori_link: _, dox, link_range }: &DiagnosticInfo<'_>,
     decorate: impl FnOnce(&mut Diagnostic, Option<rustc_span::Span>),
 ) {
-    let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.def_id)
+    let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id)
     else {
         // If non-local, no need to check anything.
         info!("ignoring warning from parent crate: {}", msg);
index dffceff045d0b6d6e2cc239c422f6e97ff6f8655..68e10e3a18c7ec40b6e7acf2b1d2a5bb0c12f664 100644 (file)
@@ -1,33 +1,39 @@
 use crate::clean::Attributes;
 use crate::core::ResolverCaches;
-use crate::html::markdown::markdown_links;
-use crate::passes::collect_intra_doc_links::preprocess_link;
+use crate::passes::collect_intra_doc_links::preprocessed_markdown_links;
+use crate::passes::collect_intra_doc_links::PreprocessedMarkdownLink;
 
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
 use rustc_ast::{self as ast, ItemKind};
 use rustc_ast_lowering::ResolverAstLowering;
-use rustc_hir::def::Namespace::TypeNS;
-use rustc_hir::def::{DefKind, Res};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def::Namespace::*;
+use rustc_hir::def::{DefKind, Namespace, Res};
 use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, CRATE_DEF_ID};
 use rustc_hir::TraitCandidate;
 use rustc_middle::ty::{DefIdTree, Visibility};
 use rustc_resolve::{ParentScope, Resolver};
 use rustc_session::config::Externs;
-use rustc_span::SyntaxContext;
+use rustc_session::Session;
+use rustc_span::{Symbol, SyntaxContext};
 
 use std::collections::hash_map::Entry;
 use std::mem;
 
 crate fn early_resolve_intra_doc_links(
     resolver: &mut Resolver<'_>,
+    sess: &Session,
     krate: &ast::Crate,
     externs: Externs,
     document_private_items: bool,
 ) -> ResolverCaches {
     let mut link_resolver = EarlyDocLinkResolver {
         resolver,
+        sess,
         current_mod: CRATE_DEF_ID,
         visited_mods: Default::default(),
+        markdown_links: Default::default(),
+        doc_link_resolutions: Default::default(),
         traits_in_scope: Default::default(),
         all_traits: Default::default(),
         all_trait_impls: Default::default(),
@@ -36,7 +42,7 @@
 
     // Overridden `visit_item` below doesn't apply to the crate root,
     // so we have to visit its attributes and reexports separately.
-    link_resolver.load_links_in_attrs(&krate.attrs);
+    link_resolver.resolve_doc_links_local(&krate.attrs);
     link_resolver.process_module_children_or_reexports(CRATE_DEF_ID.to_def_id());
     visit::walk_crate(&mut link_resolver, krate);
     link_resolver.process_extern_impls();
@@ -50,6 +56,8 @@
     }
 
     ResolverCaches {
+        markdown_links: Some(link_resolver.markdown_links),
+        doc_link_resolutions: link_resolver.doc_link_resolutions,
         traits_in_scope: link_resolver.traits_in_scope,
         all_traits: Some(link_resolver.all_traits),
         all_trait_impls: Some(link_resolver.all_trait_impls),
     }
 }
 
+fn doc_attrs<'a>(attrs: impl Iterator<Item = &'a ast::Attribute>) -> Attributes {
+    Attributes::from_ast_iter(attrs.map(|attr| (attr, None)), true)
+}
+
 struct EarlyDocLinkResolver<'r, 'ra> {
     resolver: &'r mut Resolver<'ra>,
+    sess: &'r Session,
     current_mod: LocalDefId,
     visited_mods: DefIdSet,
+    markdown_links: FxHashMap<String, Vec<PreprocessedMarkdownLink>>,
+    doc_link_resolutions: FxHashMap<(Symbol, Namespace, DefId), Option<Res<ast::NodeId>>>,
     traits_in_scope: DefIdMap<Vec<TraitCandidate>>,
     all_traits: Vec<DefId>,
     all_trait_impls: Vec<DefId>,
@@ -92,18 +107,11 @@ fn add_traits_in_scope(&mut self, def_id: DefId) {
         }
     }
 
-    fn add_traits_in_parent_scope(&mut self, def_id: DefId) {
-        if let Some(module_id) = self.resolver.parent(def_id) {
-            self.add_traits_in_scope(module_id);
-        }
-    }
-
     /// Add traits in scope for links in impls collected by the `collect-intra-doc-links` pass.
     /// That pass filters impls using type-based information, but we don't yet have such
     /// information here, so we just conservatively calculate traits in scope for *all* modules
     /// having impls in them.
     fn process_extern_impls(&mut self) {
-        // FIXME: Need to resolve doc links on all these impl and trait items below.
         // Resolving links in already existing crates may trigger loading of new crates.
         let mut start_cnum = 0;
         loop {
@@ -124,7 +132,7 @@ fn process_extern_impls(&mut self) {
                 // the current crate, and links in their doc comments are not resolved.
                 for &def_id in &all_traits {
                     if self.resolver.cstore().visibility_untracked(def_id) == Visibility::Public {
-                        self.add_traits_in_parent_scope(def_id);
+                        self.resolve_doc_links_extern_impl(def_id, false);
                     }
                 }
                 for &(trait_def_id, impl_def_id, simplified_self_ty) in &all_trait_impls {
@@ -135,17 +143,17 @@ fn process_extern_impls(&mut self) {
                                 == Visibility::Public
                         })
                     {
-                        self.add_traits_in_parent_scope(impl_def_id);
+                        self.resolve_doc_links_extern_impl(impl_def_id, false);
                     }
                 }
                 for (ty_def_id, impl_def_id) in all_inherent_impls {
                     if self.resolver.cstore().visibility_untracked(ty_def_id) == Visibility::Public
                     {
-                        self.add_traits_in_parent_scope(impl_def_id);
+                        self.resolve_doc_links_extern_impl(impl_def_id, true);
                     }
                 }
-                for def_id in all_incoherent_impls {
-                    self.add_traits_in_parent_scope(def_id);
+                for impl_def_id in all_incoherent_impls {
+                    self.resolve_doc_links_extern_impl(impl_def_id, true);
                 }
 
                 self.all_traits.extend(all_traits);
@@ -161,16 +169,63 @@ fn process_extern_impls(&mut self) {
         }
     }
 
-    fn load_links_in_attrs(&mut self, attrs: &[ast::Attribute]) {
+    fn resolve_doc_links_extern_impl(&mut self, def_id: DefId, is_inherent: bool) {
+        self.resolve_doc_links_extern_outer(def_id, def_id);
+        let assoc_item_def_ids = Vec::from_iter(
+            self.resolver.cstore().associated_item_def_ids_untracked(def_id, self.sess),
+        );
+        for assoc_def_id in assoc_item_def_ids {
+            if !is_inherent
+                || self.resolver.cstore().visibility_untracked(assoc_def_id) == Visibility::Public
+            {
+                self.resolve_doc_links_extern_outer(assoc_def_id, def_id);
+            }
+        }
+    }
+
+    fn resolve_doc_links_extern_outer(&mut self, def_id: DefId, scope_id: DefId) {
+        if !self.resolver.cstore().may_have_doc_links_untracked(def_id) {
+            return;
+        }
+        // FIXME: actually resolve links, not just add traits in scope.
+        if let Some(parent_id) = self.resolver.parent(scope_id) {
+            self.add_traits_in_scope(parent_id);
+        }
+    }
+
+    fn resolve_doc_links_extern_inner(&mut self, def_id: DefId) {
+        if !self.resolver.cstore().may_have_doc_links_untracked(def_id) {
+            return;
+        }
+        // FIXME: actually resolve links, not just add traits in scope.
+        self.add_traits_in_scope(def_id);
+    }
+
+    fn resolve_doc_links_local(&mut self, attrs: &[ast::Attribute]) {
+        if !attrs.iter().any(|attr| attr.may_have_doc_links()) {
+            return;
+        }
         let module_id = self.current_mod.to_def_id();
+        self.resolve_doc_links(doc_attrs(attrs.iter()), module_id);
+    }
+
+    fn resolve_doc_links(&mut self, attrs: Attributes, module_id: DefId) {
         let mut need_traits_in_scope = false;
-        for (doc_module, doc) in
-            Attributes::from_ast(attrs, None).collapsed_doc_value_by_module_level()
-        {
+        for (doc_module, doc) in attrs.prepare_to_doc_link_resolution() {
             assert_eq!(doc_module, None);
-            for link in markdown_links(&doc.as_str()) {
-                if let Some(Ok(pinfo)) = preprocess_link(&link) {
-                    self.resolver.resolve_rustdoc_path(&pinfo.path_str, TypeNS, module_id);
+            let links = self
+                .markdown_links
+                .entry(doc)
+                .or_insert_with_key(|doc| preprocessed_markdown_links(doc));
+            for PreprocessedMarkdownLink(pp_link, _) in links {
+                if let Ok(pinfo) = pp_link {
+                    // FIXME: Resolve the path in all namespaces and resolve its prefixes too.
+                    let ns = TypeNS;
+                    self.doc_link_resolutions
+                        .entry((Symbol::intern(&pinfo.path_str), ns, module_id))
+                        .or_insert_with_key(|(path, ns, module_id)| {
+                            self.resolver.resolve_rustdoc_path(path.as_str(), *ns, *module_id)
+                        });
                     need_traits_in_scope = true;
                 }
             }
@@ -197,15 +252,13 @@ fn process_module_children_or_reexports(&mut self, module_id: DefId) {
                     && module_id.is_local()
             {
                 if let Some(def_id) = child.res.opt_def_id() && !def_id.is_local() {
-                    // FIXME: Need to resolve doc links on all these extern items
-                    // reached through reexports.
                     let scope_id = match child.res {
                         Res::Def(DefKind::Variant, ..) => self.resolver.parent(def_id).unwrap(),
                         _ => def_id,
                     };
-                    self.add_traits_in_parent_scope(scope_id); // Outer attribute scope
+                    self.resolve_doc_links_extern_outer(def_id, scope_id); // Outer attribute scope
                     if let Res::Def(DefKind::Mod, ..) = child.res {
-                        self.add_traits_in_scope(def_id); // Inner attribute scope
+                        self.resolve_doc_links_extern_inner(def_id); // Inner attribute scope
                     }
                     // Traits are processed in `add_extern_traits_in_scope`.
                     if let Res::Def(DefKind::Mod | DefKind::Enum, ..) = child.res {
@@ -219,10 +272,10 @@ fn process_module_children_or_reexports(&mut self, module_id: DefId) {
 
 impl Visitor<'_> for EarlyDocLinkResolver<'_, '_> {
     fn visit_item(&mut self, item: &ast::Item) {
-        self.load_links_in_attrs(&item.attrs); // Outer attribute scope
+        self.resolve_doc_links_local(&item.attrs); // Outer attribute scope
         if let ItemKind::Mod(..) = item.kind {
             let old_mod = mem::replace(&mut self.current_mod, self.resolver.local_def_id(item.id));
-            self.load_links_in_attrs(&item.attrs); // Inner attribute scope
+            self.resolve_doc_links_local(&item.attrs); // Inner attribute scope
             self.process_module_children_or_reexports(self.current_mod.to_def_id());
             visit::walk_item(self, item);
             self.current_mod = old_mod;
@@ -241,22 +294,22 @@ fn visit_item(&mut self, item: &ast::Item) {
     }
 
     fn visit_assoc_item(&mut self, item: &ast::AssocItem, ctxt: AssocCtxt) {
-        self.load_links_in_attrs(&item.attrs);
+        self.resolve_doc_links_local(&item.attrs);
         visit::walk_assoc_item(self, item, ctxt)
     }
 
     fn visit_foreign_item(&mut self, item: &ast::ForeignItem) {
-        self.load_links_in_attrs(&item.attrs);
+        self.resolve_doc_links_local(&item.attrs);
         visit::walk_foreign_item(self, item)
     }
 
     fn visit_variant(&mut self, v: &ast::Variant) {
-        self.load_links_in_attrs(&v.attrs);
+        self.resolve_doc_links_local(&v.attrs);
         visit::walk_variant(self, v)
     }
 
     fn visit_field_def(&mut self, field: &ast::FieldDef) {
-        self.load_links_in_attrs(&field.attrs);
+        self.resolve_doc_links_local(&field.attrs);
         visit::walk_field_def(self, field)
     }
 
index 4ab942c8f1bdc977ab9d482c714edd34261f06f9..6962b5c7ee302fd18a30b8b4556182d0b8dd654e 100644 (file)
         }
     });
 
-    // Also try to inline primitive impls from other crates.
     cx.tcx.sess.prof.generic_activity("build_primitive_trait_impls").run(|| {
         for def_id in PrimitiveType::all_impls(cx.tcx) {
+            // Try to inline primitive impls from other crates.
             if !def_id.is_local() {
                 inline::build_impl(cx, None, def_id, None, &mut new_items);
-
-                // FIXME(eddyb) is this `doc(hidden)` check needed?
-                if !cx.tcx.is_doc_hidden(def_id) {
+            }
+        }
+        for (prim, did) in PrimitiveType::primitive_locations(cx.tcx) {
+            // Do not calculate blanket impl list for docs that are not going to be rendered.
+            // While the `impl` blocks themselves are only in `libcore`, the module with `doc`
+            // attached is directly included in `libstd` as well.
+            if did.is_local() {
+                for def_id in prim.impls(cx.tcx) {
                     let impls = get_auto_trait_and_blanket_impls(cx, def_id);
-                    new_items.extend(impls.filter(|i| cx.inlined.insert(i.def_id)));
+                    new_items.extend(impls.filter(|i| cx.inlined.insert(i.item_id)));
                 }
             }
         }
@@ -176,9 +181,9 @@ impl<'a, 'tcx> DocVisitor for SyntheticImplCollector<'a, 'tcx> {
     fn visit_item(&mut self, i: &Item) {
         if i.is_struct() || i.is_enum() || i.is_union() {
             // FIXME(eddyb) is this `doc(hidden)` check needed?
-            if !self.cx.tcx.is_doc_hidden(i.def_id.expect_def_id()) {
+            if !self.cx.tcx.is_doc_hidden(i.item_id.expect_def_id()) {
                 self.impls
-                    .extend(get_auto_trait_and_blanket_impls(self.cx, i.def_id.expect_def_id()));
+                    .extend(get_auto_trait_and_blanket_impls(self.cx, i.item_id.expect_def_id()));
             }
         }
 
@@ -199,7 +204,7 @@ fn new() -> Self {
 
 impl DocVisitor for ItemCollector {
     fn visit_item(&mut self, i: &Item) {
-        self.items.insert(i.def_id);
+        self.items.insert(i.item_id);
 
         self.visit_item_recur(i)
     }
@@ -225,7 +230,7 @@ fn keep_impl(&self, ty: &Type, is_deref: bool) -> bool {
         }
     }
 
-    fn keep_impl_with_def_id(&self, did: ItemId) -> bool {
-        self.items.contains(&did)
+    fn keep_impl_with_def_id(&self, item_id: ItemId) -> bool {
+        self.items.contains(&item_id)
     }
 }
index 00e10c6d5a7c75043c7dda4a1cf79552d8433fab..044f224e7885c24727e4907977331b2faef474df 100644 (file)
@@ -197,7 +197,7 @@ fn extract_tags(
 impl<'a, 'tcx> DocVisitor for InvalidHtmlTagsLinter<'a, 'tcx> {
     fn visit_item(&mut self, item: &Item) {
         let tcx = self.cx.tcx;
-        let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.def_id)
+        let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id)
         // If non-local, no need to check anything.
         else { return };
         let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
@@ -215,7 +215,7 @@ fn visit_item(&mut self, item: &Item) {
                     // We don't try to detect stuff `<like, this>` because that's not valid HTML,
                     // and we don't try to detect stuff `<like this>` because that's not valid Rust.
                     if let Some(Some(generics_start)) = (is_open_tag
-                        && dox[..range.end].ends_with(">"))
+                        && dox[..range.end].ends_with('>'))
                     .then(|| extract_path_backwards(&dox, range.start))
                     {
                         let generics_sp = match super::source_span_for_markdown_range(
index 5db2d0747c83bb7f9de930dae440fac140f95d75..97a436c7500701f626c4136227d91759ddaffea2 100644 (file)
@@ -24,9 +24,6 @@
 mod strip_priv_imports;
 crate use self::strip_priv_imports::STRIP_PRIV_IMPORTS;
 
-mod unindent_comments;
-crate use self::unindent_comments::UNINDENT_COMMENTS;
-
 mod propagate_doc_cfg;
 crate use self::propagate_doc_cfg::PROPAGATE_DOC_CFG;
 
@@ -81,7 +78,6 @@
 crate const PASSES: &[Pass] = &[
     CHECK_DOC_TEST_VISIBILITY,
     STRIP_HIDDEN,
-    UNINDENT_COMMENTS,
     STRIP_PRIVATE,
     STRIP_PRIV_IMPORTS,
     PROPAGATE_DOC_CFG,
@@ -96,7 +92,6 @@
 /// The list of passes run by default.
 crate const DEFAULT_PASSES: &[ConditionalPass] = &[
     ConditionalPass::always(COLLECT_TRAIT_IMPLS),
-    ConditionalPass::always(UNINDENT_COMMENTS),
     ConditionalPass::always(CHECK_DOC_TEST_VISIBILITY),
     ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden),
     ConditionalPass::new(STRIP_PRIVATE, WhenNotDocumentPrivate),
index e7a99ee7bfd840fb24f724150c13d6b6a405dd93..6b052185bbdb84b7c7c2a0fcd6b8a881c5143159 100644 (file)
@@ -53,7 +53,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
             }
         } else {
             if self.update_retained {
-                self.retained.insert(i.def_id);
+                self.retained.insert(i.item_id);
             }
         }
         Some(self.fold_item_recur(i))
index 82627aaf7a4cb339ff5deff0dea4f6f703345d8b..6a522bdacf997849e1fc4bd4bfbdcf3106069d5e 100644 (file)
@@ -45,7 +45,8 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
             | clean::TraitAliasItem(..)
             | clean::MacroItem(..)
             | clean::ForeignTypeItem => {
-                if i.def_id.is_local() && !self.access_levels.is_exported(i.def_id.expect_def_id())
+                if i.item_id.is_local()
+                    && !self.access_levels.is_exported(i.item_id.expect_def_id())
                 {
                     debug!("Stripper: stripping {:?} {:?}", i.type_(), i.name);
                     return None;
@@ -59,7 +60,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
             }
 
             clean::ModuleItem(..) => {
-                if i.def_id.is_local() && !i.visibility.is_public() {
+                if i.item_id.is_local() && !i.visibility.is_public() {
                     debug!("Stripper: stripping module {:?}", i.name);
                     let old = mem::replace(&mut self.update_retained, false);
                     let ret = strip_item(self.fold_item_recur(i));
@@ -100,7 +101,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
 
         let i = if fastreturn {
             if self.update_retained {
-                self.retained.insert(i.def_id);
+                self.retained.insert(i.item_id);
             }
             return Some(i);
         } else {
@@ -108,7 +109,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
         };
 
         if self.update_retained {
-            self.retained.insert(i.def_id);
+            self.retained.insert(i.item_id);
         }
         Some(i)
     }
diff --git a/src/librustdoc/passes/unindent_comments.rs b/src/librustdoc/passes/unindent_comments.rs
deleted file mode 100644 (file)
index 0f60415..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-//! Removes excess indentation on comments in order for the Markdown
-//! to be parsed correctly. This is necessary because the convention for
-//! writing documentation is to provide a space between the /// or //! marker
-//! and the doc text, but Markdown is whitespace-sensitive. For example,
-//! a block of text with four-space indentation is parsed as a code block,
-//! so if we didn't unindent comments, these list items
-//!
-//! /// A list:
-//! ///
-//! ///    - Foo
-//! ///    - Bar
-//!
-//! would be parsed as if they were in a code block, which is likely not what the user intended.
-use std::cmp;
-
-use rustc_span::symbol::kw;
-
-use crate::clean::{self, DocFragment, DocFragmentKind, Item};
-use crate::core::DocContext;
-use crate::fold::{self, DocFolder};
-use crate::passes::Pass;
-
-#[cfg(test)]
-mod tests;
-
-crate const UNINDENT_COMMENTS: Pass = Pass {
-    name: "unindent-comments",
-    run: unindent_comments,
-    description: "removes excess indentation on comments in order for markdown to like it",
-};
-
-crate fn unindent_comments(krate: clean::Crate, _: &mut DocContext<'_>) -> clean::Crate {
-    CommentCleaner.fold_crate(krate)
-}
-
-struct CommentCleaner;
-
-impl fold::DocFolder for CommentCleaner {
-    fn fold_item(&mut self, mut i: Item) -> Option<Item> {
-        i.attrs.unindent_doc_comments();
-        Some(self.fold_item_recur(i))
-    }
-}
-
-impl clean::Attributes {
-    crate fn unindent_doc_comments(&mut self) {
-        unindent_fragments(&mut self.doc_strings);
-    }
-}
-
-fn unindent_fragments(docs: &mut Vec<DocFragment>) {
-    // `add` is used in case the most common sugared doc syntax is used ("/// "). The other
-    // fragments kind's lines are never starting with a whitespace unless they are using some
-    // markdown formatting requiring it. Therefore, if the doc block have a mix between the two,
-    // we need to take into account the fact that the minimum indent minus one (to take this
-    // whitespace into account).
-    //
-    // For example:
-    //
-    // /// hello!
-    // #[doc = "another"]
-    //
-    // In this case, you want "hello! another" and not "hello!  another".
-    let add = if docs.windows(2).any(|arr| arr[0].kind != arr[1].kind)
-        && docs.iter().any(|d| d.kind == DocFragmentKind::SugaredDoc)
-    {
-        // In case we have a mix of sugared doc comments and "raw" ones, we want the sugared one to
-        // "decide" how much the minimum indent will be.
-        1
-    } else {
-        0
-    };
-
-    // `min_indent` is used to know how much whitespaces from the start of each lines must be
-    // removed. Example:
-    //
-    // ///     hello!
-    // #[doc = "another"]
-    //
-    // In here, the `min_indent` is 1 (because non-sugared fragment are always counted with minimum
-    // 1 whitespace), meaning that "hello!" will be considered a codeblock because it starts with 4
-    // (5 - 1) whitespaces.
-    let Some(min_indent) = docs
-        .iter()
-        .map(|fragment| {
-            fragment.doc.as_str().lines().fold(usize::MAX, |min_indent, line| {
-                if line.chars().all(|c| c.is_whitespace()) {
-                    min_indent
-                } else {
-                    // Compare against either space or tab, ignoring whether they are
-                    // mixed or not.
-                    let whitespace = line.chars().take_while(|c| *c == ' ' || *c == '\t').count();
-                    cmp::min(min_indent, whitespace)
-                        + if fragment.kind == DocFragmentKind::SugaredDoc { 0 } else { add }
-                }
-            })
-        })
-        .min()
-    else {
-        return;
-    };
-
-    for fragment in docs {
-        if fragment.doc == kw::Empty {
-            continue;
-        }
-
-        let min_indent = if fragment.kind != DocFragmentKind::SugaredDoc && min_indent > 0 {
-            min_indent - add
-        } else {
-            min_indent
-        };
-
-        fragment.indent = min_indent;
-    }
-}
diff --git a/src/librustdoc/passes/unindent_comments/tests.rs b/src/librustdoc/passes/unindent_comments/tests.rs
deleted file mode 100644 (file)
index baff839..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-use super::*;
-
-use crate::clean::collapse_doc_fragments;
-
-use rustc_span::create_default_session_globals_then;
-use rustc_span::source_map::DUMMY_SP;
-use rustc_span::symbol::Symbol;
-
-fn create_doc_fragment(s: &str) -> Vec<DocFragment> {
-    vec![DocFragment {
-        span: DUMMY_SP,
-        parent_module: None,
-        doc: Symbol::intern(s),
-        kind: DocFragmentKind::SugaredDoc,
-        indent: 0,
-    }]
-}
-
-#[track_caller]
-fn run_test(input: &str, expected: &str) {
-    create_default_session_globals_then(|| {
-        let mut s = create_doc_fragment(input);
-        unindent_fragments(&mut s);
-        assert_eq!(collapse_doc_fragments(&s), expected);
-    });
-}
-
-#[test]
-fn should_unindent() {
-    run_test("    line1\n    line2", "line1\nline2");
-}
-
-#[test]
-fn should_unindent_multiple_paragraphs() {
-    run_test("    line1\n\n    line2", "line1\n\nline2");
-}
-
-#[test]
-fn should_leave_multiple_indent_levels() {
-    // Line 2 is indented another level beyond the
-    // base indentation and should be preserved
-    run_test("    line1\n\n        line2", "line1\n\n    line2");
-}
-
-#[test]
-fn should_ignore_first_line_indent() {
-    run_test("line1\n    line2", "line1\n    line2");
-}
-
-#[test]
-fn should_not_ignore_first_line_indent_in_a_single_line_para() {
-    run_test("line1\n\n    line2", "line1\n\n    line2");
-}
-
-#[test]
-fn should_unindent_tabs() {
-    run_test("\tline1\n\tline2", "line1\nline2");
-}
-
-#[test]
-fn should_trim_mixed_indentation() {
-    run_test("\t    line1\n\t    line2", "line1\nline2");
-    run_test("    \tline1\n    \tline2", "line1\nline2");
-}
-
-#[test]
-fn should_not_trim() {
-    run_test("\t    line1  \n\t    line2", "line1  \nline2");
-    run_test("    \tline1  \n    \tline2", "line1  \nline2");
-}
index 5bcec779bc0e7d130be976f1cb17ba9d660b13ed..9723cdbe3345f3e1fc572f4c0cea5919de4b9457 100644 (file)
@@ -1,6 +1,6 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_middle::middle::privacy::{AccessLevel, AccessLevels};
 use rustc_middle::ty::TyCtxt;
 
@@ -29,7 +29,7 @@ impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> {
     }
 
     crate fn visit_lib(&mut self, cnum: CrateNum) {
-        let did = DefId { krate: cnum, index: CRATE_DEF_INDEX };
+        let did = cnum.as_def_id();
         self.update(did, Some(AccessLevel::Public));
         self.visit_mod(did);
     }
index 9168e236c548d1d0e9938ee6dd4cdbd308fdfd72..fd336816c3a6d228dcef22171c43140f6fa7656f 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 9168e236c548d1d0e9938ee6dd4cdbd308fdfd72
+Subproject commit fd336816c3a6d228dcef22171c43140f6fa7656f
index 0358bc6d27c29eac5a6ff13a2a34d466eb5b88f2..b76ce7ac387facd52e042e716c52f5589505e680 100644 (file)
@@ -1,15 +1,26 @@
 // only-x86_64
+// only-linux
 // assembly-output: emit-asm
 // compile-flags: -C llvm-args=--x86-asm-syntax=intel
 
-#![feature(asm_const)]
+#![feature(asm_const, asm_sym)]
 #![crate_type = "rlib"]
 
 use std::arch::global_asm;
 
+#[no_mangle]
+fn my_func() {}
+
+#[no_mangle]
+static MY_STATIC: i32 = 0;
+
 // CHECK: mov eax, eax
 global_asm!("mov eax, eax");
 // CHECK: mov ebx, 5
 global_asm!("mov ebx, {}", const 5);
 // CHECK: mov ecx, 5
 global_asm!("movl ${}, %ecx", const 5, options(att_syntax));
+// CHECK: call my_func
+global_asm!("call {}", sym my_func);
+// CHECK: lea rax, [rip + MY_STATIC]
+global_asm!("lea rax, [rip + {}]", sym MY_STATIC);
index 69e35270266555d0f0cdf8f583cda8d63a382217..a87152e0321b9b4a658f53e1772894c8e471b904 100644 (file)
@@ -6,21 +6,21 @@
 use std::arch::asm;
 
 // CHECK-LABEL: @clobber_sysv64
-// CHECK: ={ax},={cx},={dx},={si},={di},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{dirflag},~{fpsr},~{flags},~{memory}
+// CHECK: ={ax},={cx},={dx},={si},={di},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k0},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{dirflag},~{fpsr},~{flags},~{memory}
 #[no_mangle]
 pub unsafe fn clobber_sysv64() {
     asm!("", clobber_abi("sysv64"));
 }
 
 // CHECK-LABEL: @clobber_win64
-// CHECK: ={ax},={cx},={dx},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{dirflag},~{fpsr},~{flags},~{memory}
+// CHECK: ={ax},={cx},={dx},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k0},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{dirflag},~{fpsr},~{flags},~{memory}
 #[no_mangle]
 pub unsafe fn clobber_win64() {
     asm!("", clobber_abi("win64"));
 }
 
 // CHECK-LABEL: @clobber_sysv64
-// CHECK: =&{dx},={ax},={cx},={si},={di},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{dirflag},~{fpsr},~{flags},~{memory}
+// CHECK: =&{dx},={ax},={cx},={si},={di},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k0},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{dirflag},~{fpsr},~{flags},~{memory}
 #[no_mangle]
 pub unsafe fn clobber_sysv64_edx() {
     let foo: i32;
@@ -28,7 +28,7 @@ pub unsafe fn clobber_sysv64_edx() {
 }
 
 // CHECK-LABEL: @clobber_win64
-// CHECK: =&{dx},={ax},={cx},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{dirflag},~{fpsr},~{flags},~{memory}
+// CHECK: =&{dx},={ax},={cx},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k0},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{dirflag},~{fpsr},~{flags},~{memory}
 #[no_mangle]
 pub unsafe fn clobber_win64_edx() {
     let foo: i32;
index d9614f062b7e96e8ab3d2af71e4a2c3b635214e0..bccb9e4c7586254462e1164cb29b2d81fe4a5261 100644 (file)
@@ -28,7 +28,7 @@ impl IntoError<Error> for Api
     #[no_mangle]
     fn into_error(self, error: Self::Source) -> Error {
         Error::Api {
-            source: (|v| v)(error),
+            source: error,
         }
     }
 }
diff --git a/src/test/codegen/simd_arith_offset.rs b/src/test/codegen/simd_arith_offset.rs
new file mode 100644 (file)
index 0000000..a858270
--- /dev/null
@@ -0,0 +1,26 @@
+// compile-flags: -C no-prepopulate-passes
+// only-64bit (because the LLVM type of i64 for usize shows up)
+//
+
+#![crate_type = "lib"]
+#![feature(repr_simd, platform_intrinsics)]
+
+extern "platform-intrinsic" {
+    pub(crate) fn simd_arith_offset<T, U>(ptrs: T, offsets: U) -> T;
+}
+
+/// A vector of *const T.
+#[derive(Debug, Copy, Clone)]
+#[repr(simd)]
+pub struct SimdConstPtr<T, const LANES: usize>([*const T; LANES]);
+
+#[derive(Debug, Copy, Clone)]
+#[repr(simd)]
+pub struct Simd<T, const LANES: usize>([T; LANES]);
+
+// CHECK-LABEL: smoke
+#[no_mangle]
+pub fn smoke(ptrs: SimdConstPtr<u8, 8>, offsets: Simd<usize, 8>) -> SimdConstPtr<u8, 8> {
+    // CHECK: getelementptr i8, <8 x i8*> %_3, <8 x i64> %_4
+    unsafe { simd_arith_offset(ptrs, offsets) }
+}
diff --git a/src/test/codegen/vec-clear.rs b/src/test/codegen/vec-clear.rs
deleted file mode 100644 (file)
index 15bfe42..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// compile-flags: -O
-
-#![crate_type = "lib"]
-
-// CHECK-LABEL: @vec_clear
-#[no_mangle]
-pub fn vec_clear(x: &mut Vec<u32>) {
-    // CHECK-NOT: load
-    // CHECK-NOT: icmp
-    x.clear()
-}
index a656c9e6f656a8f01db6717e3bfff5ec27d5d3bc..13c41f7d4a9061f3715dc4af80e15ce328d8b577 100644 (file)
@@ -1,13 +1,72 @@
+// min-llvm-version: 14.0
 // ignore-debug: the debug assertions get in the way
-// compile-flags: -O
+// compile-flags: -O -Z merge-functions=disabled
 #![crate_type = "lib"]
 
 // Ensure that trivial casts of vec elements are O(1)
 
-// CHECK-LABEL: @vec_iterator_cast
+pub struct Wrapper<T>(T);
+
+#[repr(C)]
+pub struct Foo {
+    a: u64,
+    b: u64,
+    c: u64,
+    d: u64,
+}
+
+// Going from an aggregate struct to another type currently requires Copy to
+// enable the TrustedRandomAccess specialization. Without it optimizations do not yet
+// reliably recognize the loops as noop for for repr(C) or non-Copy structs.
+#[derive(Copy, Clone)]
+pub struct Bar {
+    a: u64,
+    b: u64,
+    c: u64,
+    d: u64,
+}
+
+// CHECK-LABEL: @vec_iterator_cast_primitive
+#[no_mangle]
+pub fn vec_iterator_cast_primitive(vec: Vec<i8>) -> Vec<u8> {
+    // CHECK-NOT: loop
+    // CHECK-NOT: call
+    vec.into_iter().map(|e| e as u8).collect()
+}
+
+// CHECK-LABEL: @vec_iterator_cast_wrapper
+#[no_mangle]
+pub fn vec_iterator_cast_wrapper(vec: Vec<u8>) -> Vec<Wrapper<u8>> {
+    // CHECK-NOT: loop
+    // CHECK-NOT: call
+    vec.into_iter().map(|e| Wrapper(e)).collect()
+}
+
+// CHECK-LABEL: @vec_iterator_cast_unwrap
+#[no_mangle]
+pub fn vec_iterator_cast_unwrap(vec: Vec<Wrapper<u8>>) -> Vec<u8> {
+    // CHECK-NOT: loop
+    // CHECK-NOT: call
+    vec.into_iter().map(|e| e.0).collect()
+}
+
+// CHECK-LABEL: @vec_iterator_cast_aggregate
 #[no_mangle]
-pub fn vec_iterator_cast(vec: Vec<isize>) -> Vec<usize> {
+pub fn vec_iterator_cast_aggregate(vec: Vec<[u64; 4]>) -> Vec<Foo> {
     // CHECK-NOT: loop
     // CHECK-NOT: call
-    vec.into_iter().map(|e| e as usize).collect()
+    vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect()
+}
+
+// CHECK-LABEL: @vec_iterator_cast_deaggregate
+#[no_mangle]
+pub fn vec_iterator_cast_deaggregate(vec: Vec<Bar>) -> Vec<[u64; 4]> {
+    // CHECK-NOT: loop
+    // CHECK-NOT: call
+
+    // Safety: For the purpose of this test we assume that Bar layout matches [u64; 4].
+    // This currently is not guaranteed for repr(Rust) types, but it happens to work here and
+    // the UCG may add additional guarantees for homogenous types in the future that would make this
+    // correct.
+    vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect()
 }
diff --git a/src/test/debuginfo/unit-type.rs b/src/test/debuginfo/unit-type.rs
new file mode 100644 (file)
index 0000000..7aab41a
--- /dev/null
@@ -0,0 +1,71 @@
+// compile-flags:-g
+
+// We only test Rust-aware versions of GDB:
+// min-gdb-version: 8.2
+
+// === GDB TESTS ===================================================================================
+
+// gdb-command: run
+
+// gdb-command: print _ref
+// gdb-check: $1 = (*mut ()) 0x[...]
+
+// gdb-command: print _ptr
+// gdb-check: $2 = (*mut ()) 0x[...]
+
+// gdb-command: print _local
+// gdb-check: $3 = ()
+
+// gdb-command: print _field
+// gdb-check: $4 = unit_type::_TypeContainingUnitField {_a: 123, _unit: (), _b: 456}
+
+// Check that we can cast "void pointers" to their actual type in the debugger
+// gdb-command: print /x *(_ptr as *const u64)
+// gdb-check: $5 = 0x1122334455667788
+
+// === CDB TESTS ===================================================================================
+
+// cdb-command: g
+// cdb-check: Breakpoint 0 hit
+
+// cdb-command: dx _ref
+// cdb-check: _ref             : 0x[...] : () [Type: tuple$<> *]
+
+// cdb-command: dx _ptr
+// cdb-check: _ptr             : 0x[...] : () [Type: tuple$<> *]
+
+// cdb-command: dx _local
+// cdb-check: _local           : () [Type: tuple$<>]
+
+// cdb-command: dx _field,d
+// cdb-check: _field,d         [Type: unit_type::_TypeContainingUnitField]
+// cdb-check:     [+0x[...]] _a               : 123 [Type: unsigned int]
+// cdb-check:     [+0x[...]] _unit            : () [Type: tuple$<>]
+// cdb-check:     [+0x[...]] _b               : 456 [Type: unsigned __int64]
+
+// Check that we can cast "void pointers" to their actual type in the debugger
+// cdb-command: dx ((__int64 *)_ptr),x
+// cdb-check: ((__int64 *)_ptr),x : 0x[...] : 0x1122334455667788 [Type: __int64 *]
+// cdb-check:     0x1122334455667788 [Type: __int64]
+
+struct _TypeContainingUnitField {
+    _a: u32,
+    _unit: (),
+    _b: u64,
+}
+
+fn foo(_ref: &(), _ptr: *const ()) {
+    let _local = ();
+    let _field = _TypeContainingUnitField { _a: 123, _unit: (), _b: 456 };
+
+    zzz(); // #break
+}
+
+fn main() {
+    let pointee = 0x1122_3344_5566_7788i64;
+
+    foo(&(), &pointee as *const i64 as *const ());
+}
+
+#[inline(never)]
+fn zzz() {}
index ab9c740844b8fd3967b28fd69d8a3461fda9f2d0..6582cdc4a2c85e4ba16c11e3329022092a9af43a 100644 (file)
 
 // Change enum visibility -----------------------------------------------------
 #[cfg(any(cfail1,cfail4))]
-enum EnumVisibility { A }
+enum     EnumVisibility { A }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail6")]
-pub enum EnumVisibility {
-    A
-}
+pub enum EnumVisibility { A }
 
 
 
index 22508e41bf83496ec0535b332a501ee6729ade27..5463b0dc87e4020ba43ee5c236d781b5e8af157d 100644 (file)
@@ -116,7 +116,7 @@ pub fn method_body_inlined() {
 // Change Method Privacy -------------------------------------------------------
 #[cfg(any(cfail1,cfail4))]
 impl Foo {
-    //------------------------------------------------------------------------------
+    //----------------------------------------------------
     //--------------------------
     //------------------------------------------------------------------------------
     //--------------------------
@@ -129,9 +129,9 @@ pub fn method_privacy() { }
 #[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="cfail2", except="associated_item")]
     #[rustc_clean(cfg="cfail3")]
-    #[rustc_clean(cfg="cfail5", except="associated_item,hir_owner,hir_owner_nodes")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,associated_item")]
     #[rustc_clean(cfg="cfail6")]
     fn     method_privacy() { }
 }
index 2b2658b2f5f07b8f2107deb8535ab5c40fb24541..697be056761530e4312b751604fb17ee09d51c25 100644 (file)
 
 // Change static visibility
 #[cfg(any(cfail1,cfail4))]
-static STATIC_VISIBILITY: u8 = 0;
+static     STATIC_VISIBILITY: u8 = 0;
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail6")]
index b5d8a3ab34103d0d6380ae91cb46e2136a70ef65..b4d558d259fe696b734fa402af305ede5fdb45e9 100644 (file)
@@ -84,12 +84,12 @@ struct TupleStructAddField(
 // Tuple Struct Field Visibility -----------------------------------------------
 
 #[cfg(any(cfail1,cfail4))]
-struct TupleStructFieldVisibility(char);
+struct TupleStructFieldVisibility(    char);
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail2", except="type_of")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail6")]
 struct TupleStructFieldVisibility(pub char);
 
@@ -142,16 +142,14 @@ struct RecordStructAddField {
 // Record Struct Field Visibility ----------------------------------------------
 
 #[cfg(any(cfail1,cfail4))]
-struct RecordStructFieldVisibility { x: f32 }
+struct RecordStructFieldVisibility {     x: f32 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail2", except="type_of")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail6")]
-struct RecordStructFieldVisibility {
-    pub x: f32
-}
+struct RecordStructFieldVisibility { pub x: f32 }
 
 
 // Add Lifetime Parameter ------------------------------------------------------
@@ -257,12 +255,12 @@ struct AddTypeParameterBoundWhereClause<T>(
 // Visibility ------------------------------------------------------------------
 
 #[cfg(any(cfail1,cfail4))]
-struct Visibility;
+struct     Visibility;
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail6")]
 pub struct Visibility;
 
index 279449fce5e6feefc14393745407d15dcd34d794..717e9e8c8e1112bea8ad0679fc0d4c73e4b98c25 100644 (file)
@@ -31,9 +31,9 @@
 trait TraitVisibility { }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail6")]
 pub trait TraitVisibility { }
 
index 0972d2d68a115f143b3d4660ebca56941e325c2d..7cc50a86e21e1d5ab813f4de454f456ca9403b93 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -C opt-level=0 -Z inline_mir=no
+// unit-test: InstCombine
 // ignore-wasm32 compiled with panic=abort by default
 
 // EMIT_MIR combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff
index 678e965cd67f268826bef48339f298e36283fd39..fdc016a95d58e68738edefe4e7dc7f82455d8b88 100644 (file)
       }
   
       bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
           _2 = &((*_1).0: T);              // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
+          StorageLive(_3);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
           _3 = &((*_1).1: u64);            // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
+          StorageLive(_4);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
           _4 = &((*_1).2: [f32; 3]);       // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
+          StorageLive(_5);                 // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
+          StorageLive(_6);                 // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
+          StorageLive(_7);                 // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
 -         _7 = &(*_2);                     // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
 -         _6 = &(*_7);                     // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
 +         _7 = _2;                         // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
       }
   
       bb1: {
+          StorageDead(_6);                 // scope 1 at $DIR/combine_clone_of_primitives.rs:8:8: 8:9
+          StorageLive(_8);                 // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
+          StorageLive(_9);                 // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
+          StorageLive(_10);                // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
 -         _10 = &(*_3);                    // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
 -         _9 = &(*_10);                    // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
 -         _8 = <u64 as Clone>::clone(move _9) -> [return: bb2, unwind: bb4]; // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
       }
   
       bb2: {
+          StorageDead(_9);                 // scope 1 at $DIR/combine_clone_of_primitives.rs:9:10: 9:11
+          StorageLive(_11);                // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
+          StorageLive(_12);                // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
+          StorageLive(_13);                // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
 -         _13 = &(*_4);                    // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
 -         _12 = &(*_13);                   // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
 -         _11 = <[f32; 3] as Clone>::clone(move _12) -> [return: bb3, unwind: bb4]; // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
       }
   
       bb3: {
+          StorageDead(_12);                // scope 1 at $DIR/combine_clone_of_primitives.rs:10:15: 10:16
           Deinit(_0);                      // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15
           (_0.0: T) = move _5;             // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15
           (_0.1: u64) = move _8;           // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15
           (_0.2: [f32; 3]) = move _11;     // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15
+          StorageDead(_13);                // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
+          StorageDead(_11);                // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
+          StorageDead(_10);                // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
+          StorageDead(_8);                 // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
+          StorageDead(_7);                 // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
+          StorageDead(_5);                 // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
+          StorageDead(_4);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
+          StorageDead(_3);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
+          StorageDead(_2);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
           return;                          // scope 0 at $DIR/combine_clone_of_primitives.rs:6:15: 6:15
       }
   
index e40274dc393401734ba33a5a1a4b2e30c1f142b1..038a1afc58bb6e44becf9780f93ee84489a895d3 100644 (file)
 +     bb3: {
           StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch.rs:8:1: 8:2
           return;                          // scope 0 at $DIR/early_otherwise_branch.rs:8:2: 8:2
-+     }
-+ 
+      }
+  
+-     bb5 (cleanup): {
+-         resume;                          // scope 0 at $DIR/early_otherwise_branch.rs:3:1: 8:2
 +     bb4: {
 +         StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 4:17
 +         switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 4:17
index 4f2b9696f8c821ccab2bfe4a5ff7deced7841d8f..75549c1b3ddf276e0e5749c38637a160623f2761 100644 (file)
@@ -32,7 +32,7 @@
           StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch.rs:12:16: 12:17
           StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch.rs:12:16: 12:17
           _8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:12:11: 12:17
--         switchInt(move _8) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb7]; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
+-         switchInt(move _8) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
 +         StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
 +         _11 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
 +         StorageLive(_12);                // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
@@ -84,8 +84,8 @@
           return;                          // scope 0 at $DIR/early_otherwise_branch.rs:17:2: 17:2
       }
   
--     bb7: {
--         unreachable;                     // scope 0 at $DIR/early_otherwise_branch.rs:15:14: 15:15
+-     bb7 (cleanup): {
+-         resume;                          // scope 0 at $DIR/early_otherwise_branch.rs:11:1: 17:2
 +     bb5: {
 +         StorageDead(_12);                // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
 +         switchInt(_8) -> [0_isize: bb3, 1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
index 96c7e46853f145d994797691c16b078868156316..30726d8621e1f98f63a6758829dcace56c9bd42b 100644 (file)
 +     bb3: {
           StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch.rs:26:1: 26:2
           return;                          // scope 0 at $DIR/early_otherwise_branch.rs:26:2: 26:2
-+     }
-+ 
+      }
+  
+-     bb5 (cleanup): {
+-         resume;                          // scope 0 at $DIR/early_otherwise_branch.rs:21:1: 26:2
 +     bb4: {
 +         StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:22:5: 22:17
 +         switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:22:5: 22:17
index e0ebcfeebfcc79622f24369c0dc9166911d8add3..7be9fbd0326f65fbbca5d0e26afa540d4e51ca58 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z mir-opt-level=4 -Z unsound-mir-opts
+// unit-test: EarlyOtherwiseBranch
 // EMIT_MIR early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
 fn opt1(x: Option<u32>, y: Option<u32>) -> u32 {
     match (x, y) {
index 379d0e9ea48b38ff83254fe909f836fa8a0c1e46..ddf26ad8ab323c5ef55aa6c48e61bf4165717ad5 100644 (file)
 +     bb4: {
           StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:9:1: 9:2
           return;                          // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:9:2: 9:2
-+     }
-+ 
+      }
+  
+-     bb6 (cleanup): {
+-         resume;                          // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:4:1: 9:2
 +     bb5: {
 +         StorageDead(_15);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 5:20
 +         switchInt(_10) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 5:20
index 8527c01d756589ec0446deaee306eee29886eb3c..76055e1330fa7c88beec278069d74d0b5e99f3ad 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z mir-opt-level=4 -Z unsound-mir-opts
+// unit-test: EarlyOtherwiseBranch
 
 // EMIT_MIR early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
 fn opt1(x: Option<u32>, y: Option<u32>, z: Option<u32>) -> u32 {
index 6adc5194aec75963419fd915aab8a3e133f4f454..4d2db490836d834ab49144e9fe12a3a87e80a6c1 100644 (file)
           StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:16: 8:17
           StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:16: 8:17
           _8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:17
-          switchInt(move _8) -> [0_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 8:17
+          switchInt(move _8) -> [0_isize: bb1, 1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 8:17
       }
   
       bb1: {
           _6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:17
-          switchInt(move _6) -> [0_isize: bb2, otherwise: bb6]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 8:17
+          switchInt(move _6) -> [0_isize: bb2, 1_isize: bb7, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 8:17
       }
   
       bb2: {
           _0 = const 3_u32;                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:25: 12:26
-          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:25: 12:26
+          goto -> bb8;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:25: 12:26
       }
   
       bb3: {
-          _7 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:17
-          switchInt(move _7) -> [0_isize: bb5, otherwise: bb4]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 8:17
+          unreachable;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:17
       }
   
       bb4: {
+          _7 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:17
+          switchInt(move _7) -> [0_isize: bb6, 1_isize: bb5, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 8:17
+      }
+  
+      bb5: {
           StorageLive(_9);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:15: 9:16
           _9 = (((_3.0: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:15: 9:16
           StorageLive(_10);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:24: 9:25
           _0 = const 0_u32;                // scope 1 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32
           StorageDead(_10);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32
           StorageDead(_9);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32
-          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32
+          goto -> bb8;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32
       }
   
-      bb5: {
+      bb6: {
           StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:15: 10:16
           _11 = (((_3.0: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:15: 10:16
           _0 = const 1_u32;                // scope 2 at $DIR/early_otherwise_branch_noopt.rs:10:28: 10:29
           StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:28: 10:29
-          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:28: 10:29
+          goto -> bb8;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:28: 10:29
       }
   
-      bb6: {
+      bb7: {
           StorageLive(_12);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:21: 11:22
           _12 = (((_3.1: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:21: 11:22
           _0 = const 2_u32;                // scope 3 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
           StorageDead(_12);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
-          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
+          goto -> bb8;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
       }
   
-      bb7: {
+      bb8: {
           StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:14:1: 14:2
           return;                          // scope 0 at $DIR/early_otherwise_branch_noopt.rs:14:2: 14:2
       }
+  
+      bb9 (cleanup): {
+          resume;                          // scope 0 at $DIR/early_otherwise_branch_noopt.rs:7:1: 14:2
+      }
   }
   
index 1f8c59df35fff019ad64595fbbc5f13c7976a0ff..ef766bbd4a651b6ff664af1f1f6a915c1774a350 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z mir-opt-level=4 -Zunsound-mir-opts
+// unit-test: EarlyOtherwiseBranch
 
 // must not optimize as it does not follow the pattern of
 // left and right hand side being the same variant
index a272266066246ce21169db924e061d480a578125..92a719d997d6bea4738cf21a3adb84964124a0b0 100644 (file)
@@ -19,7 +19,7 @@
   
       bb1: {
           _0 = const 0_i32;                // scope 0 at $DIR/early_otherwise_branch_soundness.rs:25:14: 25:15
-          return;                          // scope 0 at $DIR/early_otherwise_branch_soundness.rs:25:14: 25:15
+          goto -> bb5;                     // scope 0 at $DIR/early_otherwise_branch_soundness.rs:25:14: 25:15
       }
   
       bb2: {
@@ -29,7 +29,7 @@
   
       bb3: {
           _0 = const 0_i32;                // scope 0 at $DIR/early_otherwise_branch_soundness.rs:23:18: 23:19
-          return;                          // scope 0 at $DIR/early_otherwise_branch_soundness.rs:23:18: 23:19
+          goto -> bb5;                     // scope 0 at $DIR/early_otherwise_branch_soundness.rs:23:18: 23:19
       }
   
       bb4: {
           _5 = (((*_2) as Some).0: i32);   // scope 0 at $DIR/early_otherwise_branch_soundness.rs:22:18: 22:19
           _0 = _5;                         // scope 1 at $DIR/early_otherwise_branch_soundness.rs:22:24: 22:25
           StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_soundness.rs:22:24: 22:25
-          return;                          // scope 0 at $DIR/early_otherwise_branch_soundness.rs:22:24: 22:25
+          goto -> bb5;                     // scope 0 at $DIR/early_otherwise_branch_soundness.rs:22:24: 22:25
+      }
+  
+      bb5: {
+          return;                          // scope 0 at $DIR/early_otherwise_branch_soundness.rs:27:2: 27:2
+      }
+  
+      bb6 (cleanup): {
+          resume;                          // scope 0 at $DIR/early_otherwise_branch_soundness.rs:18:1: 27:2
       }
   }
   
index 56b7c9a2db47815e93b688c19054e01a1eb35e42..c43b32c7fc6e3d4b0503cc0f850c754187f2aa2d 100644 (file)
   
       bb2: {
           _0 = const 1_u32;                // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:38: 13:39
-          return;                          // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:5: 13:52
+          goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:5: 13:52
       }
   
       bb3: {
           _0 = const 2_u32;                // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:49: 13:50
-          return;                          // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:5: 13:52
+          goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:5: 13:52
+      }
+  
+      bb4: {
+          return;                          // scope 0 at $DIR/early_otherwise_branch_soundness.rs:14:2: 14:2
+      }
+  
+      bb5 (cleanup): {
+          resume;                          // scope 0 at $DIR/early_otherwise_branch_soundness.rs:12:1: 14:2
       }
   }
   
index d2513213d796f7591efe2a5fadc7774df2aa9dab..cd458923245348dcfd013b31b74c96487146c6f4 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z mir-opt-level=4 -Zunsound-mir-opts
+// unit-test: EarlyOtherwiseBranch
 
 // Tests various cases that the `early_otherwise_branch` opt should *not* optimize
 
index b34389a0ab5271b5347a9c045808964499256289..398311e6bb8e2b9249f495287ea1ee858b7aed39 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -O
+// unit-test: SimplifyComparisonIntegral
 // EMIT_MIR if_condition_int.opt_u32.SimplifyComparisonIntegral.diff
 // EMIT_MIR if_condition_int.opt_negative.SimplifyComparisonIntegral.diff
 // EMIT_MIR if_condition_int.opt_char.SimplifyComparisonIntegral.diff
index dddb7acae2b2c21c7bf8e4479051b1700b043f6f..319a47367b3ab6bbc117a63f7fa3214bbbd14711 100644 (file)
@@ -26,5 +26,9 @@
           StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:17:25: 17:26
           return;                          // scope 0 at $DIR/if-condition-int.rs:18:2: 18:2
       }
+  
+      bb4 (cleanup): {
+          resume;                          // scope 0 at $DIR/if-condition-int.rs:16:1: 18:2
+      }
   }
   
index 2ff8386b205bd024894f9bfe903e0b4712ede733..98a6c83cbffae6da358335b4fc1915f87c0acc68 100644 (file)
@@ -30,5 +30,9 @@
           StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:53:34: 53:35
           return;                          // scope 0 at $DIR/if-condition-int.rs:54:2: 54:2
       }
+  
+      bb4 (cleanup): {
+          resume;                          // scope 0 at $DIR/if-condition-int.rs:52:1: 54:2
+      }
   }
   
index fd4dcb2265e61df2a0530bb17aca2151e9b61cf8..4019021ede8d57bb6a54e43cd6c47e2162628de9 100644 (file)
@@ -54,5 +54,9 @@
           StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:49:1: 49:2
           return;                          // scope 0 at $DIR/if-condition-int.rs:49:2: 49:2
       }
+  
+      bb4 (cleanup): {
+          resume;                          // scope 0 at $DIR/if-condition-int.rs:43:1: 49:2
+      }
   }
   
index 40de48385f02e3894129090d91eb2557ad08b780..d4f100e289f06d860a1f577feaea5de964729ed6 100644 (file)
@@ -35,5 +35,9 @@
           StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:21:32: 21:33
           return;                          // scope 0 at $DIR/if-condition-int.rs:22:2: 22:2
       }
+  
+      bb4 (cleanup): {
+          resume;                          // scope 0 at $DIR/if-condition-int.rs:20:1: 22:2
+      }
   }
   
index 28c36aed84c38270a3b9a705a4e2965416db6a21..06d2c666aeca69d17b4d6f51b5b9fac53840d681 100644 (file)
@@ -35,5 +35,9 @@
           StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:25:31: 25:32
           return;                          // scope 0 at $DIR/if-condition-int.rs:26:2: 26:2
       }
+  
+      bb4 (cleanup): {
+          resume;                          // scope 0 at $DIR/if-condition-int.rs:24:1: 26:2
+      }
   }
   
index 55932fee9600cb28a3644461026d20246356ee7e..a7e4edf40a8d66686afa346b54efd17056bc54dd 100644 (file)
@@ -61,5 +61,9 @@
           StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:39:5: 39:6
           return;                          // scope 0 at $DIR/if-condition-int.rs:40:2: 40:2
       }
+  
+      bb7 (cleanup): {
+          resume;                          // scope 0 at $DIR/if-condition-int.rs:32:1: 40:2
+      }
   }
   
index c4574b32a59991f086505352cc870fee9c1a7dac..47f69b85e898c71256e46a7a03b4f686e4515457 100644 (file)
@@ -35,5 +35,9 @@
           StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:29:32: 29:33
           return;                          // scope 0 at $DIR/if-condition-int.rs:30:2: 30:2
       }
+  
+      bb4 (cleanup): {
+          resume;                          // scope 0 at $DIR/if-condition-int.rs:28:1: 30:2
+      }
   }
   
index 88d9d5622b8ec060a8d3ff45fcb66d7db8069218..3920627d5248783f9edb5ea5a97a1b92bf273bb0 100644 (file)
@@ -35,5 +35,9 @@
           StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:12:31: 12:32
           return;                          // scope 0 at $DIR/if-condition-int.rs:13:2: 13:2
       }
+  
+      bb4 (cleanup): {
+          resume;                          // scope 0 at $DIR/if-condition-int.rs:11:1: 13:2
+      }
   }
   
index bea33073366f733e63a08450723fee0fdb890890..3b890e4be2e290f4ce98f0f44797418eed439191 100644 (file)
@@ -4,21 +4,22 @@
   fn h() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/inline-diverging.rs:21:12: 21:12
       let _1: (!, !);                      // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
-+     let mut _2: fn() -> ! {sleep};       // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
-+     let mut _9: ();                      // in scope 0 at $DIR/inline-diverging.rs:27:13: 27:16
-+     let mut _10: ();                     // in scope 0 at $DIR/inline-diverging.rs:28:13: 28:16
++     let mut _2: (!, !);                  // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
++     let mut _3: fn() -> ! {sleep};       // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
++     let mut _10: ();                     // in scope 0 at $DIR/inline-diverging.rs:27:13: 27:16
++     let mut _11: ();                     // in scope 0 at $DIR/inline-diverging.rs:28:13: 28:16
 +     scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) { // at $DIR/inline-diverging.rs:22:5: 22:22
-+         debug f => _2;                   // in scope 1 at $DIR/inline-diverging.rs:26:36: 26:37
-+         let _3: !;                       // in scope 1 at $DIR/inline-diverging.rs:27:9: 27:10
-+         let mut _4: &fn() -> ! {sleep};  // in scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
-+         let mut _6: &fn() -> ! {sleep};  // in scope 1 at $DIR/inline-diverging.rs:28:13: 28:14
-+         let mut _7: !;                   // in scope 1 at $DIR/inline-diverging.rs:29:6: 29:7
-+         let mut _8: !;                   // in scope 1 at $DIR/inline-diverging.rs:29:9: 29:10
++         debug f => _3;                   // in scope 1 at $DIR/inline-diverging.rs:26:36: 26:37
++         let _4: !;                       // in scope 1 at $DIR/inline-diverging.rs:27:9: 27:10
++         let mut _5: &fn() -> ! {sleep};  // in scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
++         let mut _7: &fn() -> ! {sleep};  // in scope 1 at $DIR/inline-diverging.rs:28:13: 28:14
++         let mut _8: !;                   // in scope 1 at $DIR/inline-diverging.rs:29:6: 29:7
++         let mut _9: !;                   // in scope 1 at $DIR/inline-diverging.rs:29:9: 29:10
 +         scope 2 {
-+             debug a => _3;               // in scope 2 at $DIR/inline-diverging.rs:27:9: 27:10
-+             let _5: !;                   // in scope 2 at $DIR/inline-diverging.rs:28:9: 28:10
++             debug a => _4;               // in scope 2 at $DIR/inline-diverging.rs:27:9: 27:10
++             let _6: !;                   // in scope 2 at $DIR/inline-diverging.rs:28:9: 28:10
 +             scope 3 {
-+                 debug b => _5;           // in scope 3 at $DIR/inline-diverging.rs:28:9: 28:10
++                 debug b => _6;           // in scope 3 at $DIR/inline-diverging.rs:28:9: 28:10
 +             }
 +             scope 6 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline-diverging.rs:28:13: 28:16
 +                 scope 7 (inlined sleep) { // at $SRC_DIR/core/src/ops/function.rs:LL:COL
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
--         _1 = call_twice::<!, fn() -> ! {sleep}>(sleep) -> bb1; // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
+-         call_twice::<!, fn() -> ! {sleep}>(sleep); // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
 +         StorageLive(_2);                 // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
-+         _2 = sleep;                      // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
++         StorageLive(_3);                 // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
++         _3 = sleep;                      // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
                                            // mir::Constant
 -                                          // + span: $DIR/inline-diverging.rs:22:5: 22:15
 -                                          // + literal: Const { ty: fn(fn() -> ! {sleep}) -> (!, !) {call_twice::<!, fn() -> ! {sleep}>}, val: Value(Scalar(<ZST>)) }
 -                                          // mir::Constant
                                            // + span: $DIR/inline-diverging.rs:22:16: 22:21
                                            // + literal: Const { ty: fn() -> ! {sleep}, val: Value(Scalar(<ZST>)) }
-+         StorageLive(_3);                 // scope 1 at $DIR/inline-diverging.rs:27:9: 27:10
-+         StorageLive(_4);                 // scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
-+         _4 = &_2;                        // scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
-+         StorageLive(_9);                 // scope 1 at $DIR/inline-diverging.rs:27:13: 27:16
-+         _9 = const ();                   // scope 1 at $DIR/inline-diverging.rs:27:13: 27:16
++         StorageLive(_4);                 // scope 1 at $DIR/inline-diverging.rs:27:9: 27:10
++         StorageLive(_5);                 // scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
++         _5 = &_3;                        // scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
++         StorageLive(_10);                // scope 1 at $DIR/inline-diverging.rs:27:13: 27:16
++         _10 = const ();                  // scope 1 at $DIR/inline-diverging.rs:27:13: 27:16
 +         goto -> bb1;                     // scope 5 at $DIR/inline-diverging.rs:39:5: 39:12
-      }
-  
-      bb1: {
--         StorageDead(_1);                 // scope 0 at $DIR/inline-diverging.rs:22:22: 22:23
--         _0 = const ();                   // scope 0 at $DIR/inline-diverging.rs:21:12: 23:2
--         return;                          // scope 0 at $DIR/inline-diverging.rs:23:2: 23:2
++     }
++ 
++     bb1: {
 +         goto -> bb1;                     // scope 5 at $DIR/inline-diverging.rs:39:5: 39:12
       }
   }
index 072ab5e8df4f7cbe63794cc8369e9087c20aca02..074ad067ff899b3da47374188d4d82d4200df912 100644 (file)
@@ -35,7 +35,7 @@
 +         StorageLive(_7);                 // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
 +         _7 = &mut (*_5);                 // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
 +         Deinit((*_7));                   // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-+         ((*_7).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: {0x4 as *const u32}, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
++         ((*_7).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: NonNull::<u32> { pointer: {0x4 as *const u32} }, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
                                            // mir::Constant
 -                                          // + span: $DIR/inline-into-box-place.rs:8:33: 8:41
 -                                          // + user_ty: UserType(1)
index 8b8a741ec12da6a51a3a676b08b3efcf2a027565..a055ae9864f5fa2193ed50e11f6449660b224511 100644 (file)
@@ -35,7 +35,7 @@
 +         StorageLive(_7);                 // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
 +         _7 = &mut (*_5);                 // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
 +         Deinit((*_7));                   // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-+         ((*_7).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: {0x4 as *const u32}, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
++         ((*_7).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: NonNull::<u32> { pointer: {0x4 as *const u32} }, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
                                            // mir::Constant
 -                                          // + span: $DIR/inline-into-box-place.rs:8:33: 8:41
 -                                          // + user_ty: UserType(1)
index 5fb57c285becac09f46b5cc6ee447bc308bc6ce5..4aff4445158098efdaa023a3393314f1d9e207d6 100644 (file)
@@ -21,7 +21,7 @@ fn main() -> () {
         StorageLive(_2);                 // scope 0 at $DIR/issue-72181-1.rs:16:9: 16:10
         StorageLive(_3);                 // scope 2 at $DIR/issue-72181-1.rs:17:41: 17:43
         _3 = ();                         // scope 2 at $DIR/issue-72181-1.rs:17:41: 17:43
-        _2 = transmute::<(), Void>(move _3) -> [return: bb1, unwind: bb4]; // scope 2 at $DIR/issue-72181-1.rs:17:9: 17:44
+        transmute::<(), Void>(move _3) -> bb4; // scope 2 at $DIR/issue-72181-1.rs:17:9: 17:44
                                          // mir::Constant
                                          // + span: $DIR/issue-72181-1.rs:17:9: 17:40
                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(()) -> Void {transmute::<(), Void>}, val: Value(Scalar(<ZST>)) }
index f2438e69749905d71f917c13cc180718b495148f..12955aed1fbbe242b22061e33e0df6f5731cd49d 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z mir-opt-level=3
+// unit-test: LowerSliceLenCalls
 
 // EMIT_MIR lower_slice_len.bound.LowerSliceLenCalls.diff
 pub fn bound(index: usize, slice: &[u8]) -> u8 {
index 9f235248ca59f9a2c61112c005979684576aa0a5..8423128123ab76e108fcee5a8866a21ff2d1287d 100644 (file)
 | '_#2r live at {bb0[0..=1]}
 | '_#3r live at {bb0[0..=1]}
 | '_#4r live at {bb0[0..=1]}
-| '_#1r: '_#6r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27)
-| '_#1r: '_#8r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55)
-| '_#2r: '_#7r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43)
-| '_#3r: '_#9r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67)
-| '_#6r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27)
-| '_#7r: '_#2r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43)
-| '_#8r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55)
-| '_#9r: '_#3r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67)
+| '_#1r: '_#6r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27) ($DIR/named-lifetimes-basic.rs:12:26: 12:27 (#0)
+| '_#1r: '_#8r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55) ($DIR/named-lifetimes-basic.rs:12:54: 12:55 (#0)
+| '_#2r: '_#7r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43) ($DIR/named-lifetimes-basic.rs:12:42: 12:43 (#0)
+| '_#3r: '_#9r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67) ($DIR/named-lifetimes-basic.rs:12:66: 12:67 (#0)
+| '_#6r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27) ($DIR/named-lifetimes-basic.rs:12:26: 12:27 (#0)
+| '_#7r: '_#2r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43) ($DIR/named-lifetimes-basic.rs:12:42: 12:43 (#0)
+| '_#8r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55) ($DIR/named-lifetimes-basic.rs:12:54: 12:55 (#0)
+| '_#9r: '_#3r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67) ($DIR/named-lifetimes-basic.rs:12:66: 12:67 (#0)
 |
 fn use_x(_1: &'_#6r mut i32, _2: &'_#7r u32, _3: &'_#8r u32, _4: &'_#9r u32) -> bool {
     debug w => _1;                       // in scope 0 at $DIR/named-lifetimes-basic.rs:12:26: 12:27
index ed94a1ecf006252f79da61898d048595d549c779..f79e2705ad29cce82115f971e7ec67ee98567dff 100644 (file)
@@ -18,8 +18,8 @@
 | '_#3r live at {bb1[0]}
 | '_#4r live at {bb1[1..=3]}
 | '_#5r live at {bb1[4..=7], bb2[0..=2]}
-| '_#3r: '_#4r due to Assignment at Single(bb1[0])
-| '_#4r: '_#5r due to Assignment at Single(bb1[3])
+| '_#3r: '_#4r due to Assignment at Single(bb1[0]) ($DIR/region-subtyping-basic.rs:18:13: 18:18 (#0)
+| '_#4r: '_#5r due to Assignment at Single(bb1[3]) ($DIR/region-subtyping-basic.rs:19:13: 19:14 (#0)
 |
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/region-subtyping-basic.rs:16:11: 16:11
index 95997b2070172d955de39b41256af0eec0df2c76..162cacef8a54afab04bf2bc554858e6cbb6fb96f 100644 (file)
@@ -18,8 +18,8 @@
 | '_#3r live at {bb1[0]}
 | '_#4r live at {bb1[1..=3]}
 | '_#5r live at {bb1[4..=7], bb2[0..=2]}
-| '_#3r: '_#4r due to Assignment at Single(bb1[0])
-| '_#4r: '_#5r due to Assignment at Single(bb1[3])
+| '_#3r: '_#4r due to Assignment at Single(bb1[0]) ($DIR/region-subtyping-basic.rs:18:13: 18:18 (#0)
+| '_#4r: '_#5r due to Assignment at Single(bb1[3]) ($DIR/region-subtyping-basic.rs:19:13: 19:14 (#0)
 |
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/region-subtyping-basic.rs:16:11: 16:11
index ab46d7b94c72c09872aec2d17d961ae5f1cc4d97..5786ae62127054cbd56a2e507ba8b9da07befd86 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Zmir-opt-level=1
+// unit-test: RenameReturnPlace
 
 // EMIT_MIR nrvo_simple.nrvo.RenameReturnPlace.diff
 fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] {
index f438eaa002780958f07d88a70f123bd229129de0..e07af6d5983112bb846139193059f86c0a8370a4 100644 (file)
@@ -39,5 +39,9 @@
 -         StorageDead(_2);                 // scope 0 at $DIR/nrvo-simple.rs:8:1: 8:2
           return;                          // scope 0 at $DIR/nrvo-simple.rs:8:2: 8:2
       }
+  
+      bb2 (cleanup): {
+          resume;                          // scope 0 at $DIR/nrvo-simple.rs:4:1: 8:2
+      }
   }
   
index e02580135af38f3f9a02d8745b52b024052d91c9..b383c5ec9dc60a173fc9a8391828a6467faa3d86 100644 (file)
@@ -16,7 +16,7 @@
 | '_#1r live at {bb0[0..=22]}
 | '_#3r live at {bb0[10]}
 | '_#4r live at {bb0[11]}
-| '_#3r: '_#4r due to Assignment at Single(bb0[10])
+| '_#3r: '_#4r due to Assignment at Single(bb0[10]) ($DIR/storage_ranges.rs:6:17: 6:25 (#0)
 |
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/storage_ranges.rs:3:11: 3:11
index 9b10fd86c4778d8ee4f744d6566c667d6c5cea63..a59a3002c7f68508c28bdfda5ff2e2ffc5e1b7f8 100644 (file)
@@ -6,4 +6,4 @@ extern crate std;
 // pretty-mode:hir
 // pp-exact:hir-pretty-loop.pp
 
-pub fn foo() { loop { break; } }
+fn foo() { loop { break; } }
index ea74a267be81e1cd03831aeaf6b75c8c2ff54a42..752c36a0fbc5a58759f1fa0d0e564990c783f301 100644 (file)
@@ -8,9 +8,9 @@ extern crate std;
 
 // #4264 fixed-length vector types
 
-pub fn foo(_: [i32; (3 as usize)]) ({ } as ())
+fn foo(_: [i32; (3 as usize)]) ({ } as ())
 
-pub fn bar() ({
+fn bar() ({
         const FOO: usize = ((5 as usize) - (4 as usize) as usize);
         let _: [(); (FOO as usize)] = ([(() as ())] as [(); 1]);
 
@@ -41,14 +41,14 @@ pub fn bar() ({
                 (res as String)
             } as String);
     } as ())
-pub type Foo = [i32; (3 as usize)];
-pub struct Bar {
-    pub x: [i32; (3 as usize)],
+type Foo = [i32; (3 as usize)];
+struct Bar {
+    x: [i32; (3 as usize)],
 }
-pub struct TupleBar([i32; (4 as usize)]);
-pub enum Baz { BazVariant([i32; (5 as usize)]), }
-pub fn id<T>(x: T) -> T ({ (x as T) } as T)
-pub fn use_id() ({
+struct TupleBar([i32; (4 as usize)]);
+enum Baz { BazVariant([i32; (5 as usize)]), }
+fn id<T>(x: T) -> T ({ (x as T) } as T)
+fn use_id() ({
         let _ =
             ((id::<[i32; (3 as usize)]> as
                     fn([i32; 3]) -> [i32; 3] {id::<[i32; 3]>})(([(1 as i32),
index 7ab22f1960c2d8fbc8daf2f8c5d253b97104135d..c01379065d1cd5ded2faa70b9e0daedce9ec065e 100644 (file)
@@ -1,6 +1,8 @@
 // pp-exact
 
 #![feature(box_syntax)]
+#![feature(inline_const)]
+#![feature(inline_const_pat)]
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 
@@ -16,6 +18,7 @@ fn _1() {
 
     #[rustc_dummy]
     unsafe {
+        #![rustc_dummy]
         // code
     }
 }
@@ -206,6 +209,12 @@ fn _11() {
             let _ = ();
             ()
         };
+    let const {
+                    #![rustc_dummy]
+                } =
+        #[rustc_dummy] const {
+                #![rustc_dummy]
+            };
     let mut x = 0;
     let _ = #[rustc_dummy] x = 15;
     let _ = #[rustc_dummy] x += 15;
index d8ceace7fff250e1dbfcb638303c21a8adb61a87..4cda243ffb5a3d255dcea63e345650b42d861f89 100644 (file)
@@ -2,10 +2,25 @@ include ../tools.mk
 
 # ignore-stage1
 
+# This test both exists as a check that -Zcodegen-backend is capable of loading external codegen
+# backends and that this external codegen backend is only included in the dep info if
+# -Zbinary-dep-depinfo is used.
+
 all:
        /bin/echo || exit 0 # This test requires /bin/echo to exist
        $(RUSTC) the_backend.rs --crate-name the_backend --crate-type dylib \
                -o $(TMPDIR)/the_backend.dylib
+
+       $(RUSTC) some_crate.rs --crate-name some_crate --crate-type lib -o $(TMPDIR)/some_crate \
+               -Z codegen-backend=$(TMPDIR)/the_backend.dylib -Z unstable-options \
+               --emit link,dep-info
+       grep -x "This has been \"compiled\" successfully." $(TMPDIR)/libsome_crate.rlib
+       # don't declare a dependency on the codegen backend if -Zbinary-dep-depinfo isn't used.
+       grep -v "the_backend.dylib" $(TMPDIR)/some_crate.d
+       
        $(RUSTC) some_crate.rs --crate-name some_crate --crate-type lib -o $(TMPDIR)/some_crate \
-               -Z codegen-backend=$(TMPDIR)/the_backend.dylib -Z unstable-options
-       grep -x "This has been \"compiled\" successfully." $(TMPDIR)/some_crate
+               -Z codegen-backend=$(TMPDIR)/the_backend.dylib -Z unstable-options \
+               --emit link,dep-info -Zbinary-dep-depinfo
+       grep -x "This has been \"compiled\" successfully." $(TMPDIR)/libsome_crate.rlib
+       # but declare a dependency on the codegen backend if -Zbinary-dep-depinfo it used.
+       grep "the_backend.dylib" $(TMPDIR)/some_crate.d
index 4ff719bfb7ddcf6257b1f8109efb3d38b90d6a7d..d6385e2acb8e637083f77ffdf8c8090a7da41232 100644 (file)
@@ -8,7 +8,7 @@ assert-property: (".item-info", {"scrollWidth": "890"})
 // Just to be sure we're comparing the correct "item-info":
 assert-text: (
     ".item-info",
-    "This is supported on Android or Linux or Emscripten or DragonFly BSD",
+    "Available on Android or Linux or Emscripten or DragonFly BSD",
     STARTS_WITH,
 )
 
@@ -23,6 +23,6 @@ assert-property: ("#impl-SimpleTrait .item-info", {"scrollWidth": "866"})
 // Just to be sure we're comparing the correct "item-info":
 assert-text: (
     "#impl-SimpleTrait .item-info",
-    "This is supported on Android or Linux or Emscripten or DragonFly BSD",
+    "Available on Android or Linux or Emscripten or DragonFly BSD",
     STARTS_WITH,
 )
index 7a32d9029103a4067696b73da350f76957c41c76..8b6d355a8f1a7f488911fd79c505a6a793b6bda9 100644 (file)
@@ -4,5 +4,5 @@ goto: file://|DOC_PATH|/lib2/struct.Foo.html
 size: (1100, 800)
 // We check that ".item-info" is bigger than its content.
 assert-css: (".item-info", {"width": "790px"})
-assert-css: (".item-info .stab", {"width": "340px"})
+assert-css: (".item-info .stab", {"width": "289px"})
 assert-position: (".item-info .stab", {"x": 295})
index 2e0330c449721153bc3c57d08d8b61694828e38b..b47a1fefa41d00d7e8646c32bdf38d1016733914 100644 (file)
@@ -1,6 +1,6 @@
 // exact-check
 
-const QUERY = 'hashmap';
+const QUERY = '"hashmap"';
 const FILTER_CRATE = 'core';
 
 const EXPECTED = {
diff --git a/src/test/rustdoc-js-std/parser-errors.js b/src/test/rustdoc-js-std/parser-errors.js
new file mode 100644 (file)
index 0000000..779ab86
--- /dev/null
@@ -0,0 +1,365 @@
+const QUERY = [
+    '<P>',
+    '-> <P>',
+    'a<"P">',
+    '"P" "P"',
+    'P "P"',
+    '"p" p',
+    '"const": p',
+    "a<:a>",
+    "a<::a>",
+    "((a))",
+    "(p -> p",
+    "::a::b",
+    "a::::b",
+    "a::b::",
+    ":a",
+    "a b:",
+    "a (b:",
+    "_:",
+    "a-bb",
+    "a>bb",
+    "ab'",
+    "a->",
+    '"p" <a>',
+    '"p" a<a>',
+    "a,<",
+    "aaaaa<>b",
+    "fn:aaaaa<>b",
+    "->a<>b",
+    "a<->",
+    "a:: a",
+    "a ::a",
+    "a<a>:",
+    "a<>:",
+    "a,:",
+    "  a<>  :",
+    "mod : :",
+];
+
+const PARSED = [
+    {
+        elems: [],
+        foundElems: 0,
+        original: "<P>",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "<p>",
+        error: "Found generics without a path",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "-> <P>",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "-> <p>",
+        error: "Found generics without a path",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "a<\"P\">",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a<\"p\">",
+        error: "`\"` cannot be used in generics",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "\"P\" \"P\"",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "\"p\" \"p\"",
+        error: "Cannot have more than one literal search element",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "P \"P\"",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "p \"p\"",
+        error: "Cannot use literal search when there is more than one element",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "\"p\" p",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "\"p\" p",
+        error: "You cannot have more than one element if you use quotes",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "\"const\": p",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "\"const\": p",
+        error: "You cannot use quotes on type filter",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "a<:a>",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a<:a>",
+        error: "Unexpected `:` after `<`",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "a<::a>",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a<::a>",
+        error: "Unexpected `::`: paths cannot start with `::`",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "((a))",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "((a))",
+        error: "Unexpected `(`",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "(p -> p",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "(p -> p",
+        error: "Unexpected `(`",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "::a::b",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "::a::b",
+        error: "Paths cannot start with `::`",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "a::::b",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a::::b",
+        error: "Unexpected `::::`",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "a::b::",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a::b::",
+        error: "Paths cannot end with `::`",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: ":a",
+        returned: [],
+        typeFilter: -1,
+        userQuery: ":a",
+        error: "Expected type filter before `:`",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "a b:",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a b:",
+        error: "Unexpected `:`",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "a (b:",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a (b:",
+        error: "Unexpected `(`",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "_:",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "_:",
+        error: "Unknown type filter `_`",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "a-bb",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a-bb",
+        error: "Unexpected `-` (did you mean `->`?)",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "a>bb",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a>bb",
+        error: "Unexpected `>` (did you mean `->`?)",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "ab'",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "ab'",
+        error: "Unexpected `'`",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "a->",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a->",
+        error: "Expected at least one item after `->`",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: '"p" <a>',
+        returned: [],
+        typeFilter: -1,
+        userQuery: '"p" <a>',
+        error: "Found generics without a path",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: '"p" a<a>',
+        returned: [],
+        typeFilter: -1,
+        userQuery: '"p" a<a>',
+        error: "You cannot have more than one element if you use quotes",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: 'a,<',
+        returned: [],
+        typeFilter: -1,
+        userQuery: 'a,<',
+        error: 'Found generics without a path',
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: 'aaaaa<>b',
+        returned: [],
+        typeFilter: -1,
+        userQuery: 'aaaaa<>b',
+        error: 'Expected `,`, ` `, `:` or `->`, found `b`',
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: 'fn:aaaaa<>b',
+        returned: [],
+        typeFilter: -1,
+        userQuery: 'fn:aaaaa<>b',
+        error: 'Expected `,`, ` ` or `->`, found `b`',
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: '->a<>b',
+        returned: [],
+        typeFilter: -1,
+        userQuery: '->a<>b',
+        error: 'Expected `,` or ` `, found `b`',
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: 'a<->',
+        returned: [],
+        typeFilter: -1,
+        userQuery: 'a<->',
+        error: 'Unexpected `-` after `<`',
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: 'a:: a',
+        returned: [],
+        typeFilter: -1,
+        userQuery: 'a:: a',
+        error: 'Paths cannot end with `::`',
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: 'a ::a',
+        returned: [],
+        typeFilter: -1,
+        userQuery: 'a ::a',
+        error: 'Paths cannot start with `::`',
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "a<a>:",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a<a>:",
+        error: 'Unexpected `:`',
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "a<>:",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a<>:",
+        error: 'Unexpected `<` in type filter',
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "a,:",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a,:",
+        error: 'Unexpected `,` in type filter',
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "a<>  :",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a<>  :",
+        error: 'Unexpected `<` in type filter',
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "mod : :",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "mod : :",
+        error: 'Unexpected `:`',
+    },
+];
diff --git a/src/test/rustdoc-js-std/parser-filter.js b/src/test/rustdoc-js-std/parser-filter.js
new file mode 100644 (file)
index 0000000..e5a87a4
--- /dev/null
@@ -0,0 +1,43 @@
+const QUERY = ['fn:foo', 'enum : foo', 'macro<f>:foo'];
+
+const PARSED = [
+    {
+        elems: [{
+            name: "foo",
+            fullPath: ["foo"],
+            pathWithoutLast: [],
+            pathLast: "foo",
+            generics: [],
+        }],
+        foundElems: 1,
+        original: "fn:foo",
+        returned: [],
+        typeFilter: 5,
+        userQuery: "fn:foo",
+        error: null,
+    },
+    {
+        elems: [{
+            name: "foo",
+            fullPath: ["foo"],
+            pathWithoutLast: [],
+            pathLast: "foo",
+            generics: [],
+        }],
+        foundElems: 1,
+        original: "enum : foo",
+        returned: [],
+        typeFilter: 4,
+        userQuery: "enum : foo",
+        error: null,
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "macro<f>:foo",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "macro<f>:foo",
+        error: "Unexpected `:`",
+    },
+];
diff --git a/src/test/rustdoc-js-std/parser-generics.js b/src/test/rustdoc-js-std/parser-generics.js
new file mode 100644 (file)
index 0000000..0cf7f50
--- /dev/null
@@ -0,0 +1,62 @@
+const QUERY = ['A<B<C<D>,  E>', 'p<> u8', '"p"<a>'];
+
+const PARSED = [
+    {
+        elems: [],
+        foundElems: 0,
+        original: 'A<B<C<D>,  E>',
+        returned: [],
+        typeFilter: -1,
+        userQuery: 'a<b<c<d>,  e>',
+        error: 'Unexpected `<` after `<`',
+    },
+    {
+        elems: [
+            {
+                name: "p",
+                fullPath: ["p"],
+                pathWithoutLast: [],
+                pathLast: "p",
+                generics: [],
+            },
+            {
+                name: "u8",
+                fullPath: ["u8"],
+                pathWithoutLast: [],
+                pathLast: "u8",
+                generics: [],
+            },
+        ],
+        foundElems: 2,
+        original: "p<> u8",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "p<> u8",
+        error: null,
+    },
+    {
+        elems: [
+            {
+                name: "p",
+                fullPath: ["p"],
+                pathWithoutLast: [],
+                pathLast: "p",
+                generics: [
+                    {
+                        name: "a",
+                        fullPath: ["a"],
+                        pathWithoutLast: [],
+                        pathLast: "a",
+                        generics: [],
+                    },
+                ],
+            },
+        ],
+        foundElems: 1,
+        original: '"p"<a>',
+        returned: [],
+        typeFilter: -1,
+        userQuery: '"p"<a>',
+        error: null,
+    },
+];
diff --git a/src/test/rustdoc-js-std/parser-literal.js b/src/test/rustdoc-js-std/parser-literal.js
new file mode 100644 (file)
index 0000000..87b3baf
--- /dev/null
@@ -0,0 +1,27 @@
+const QUERY = ['R<P>'];
+
+const PARSED = [
+    {
+        elems: [{
+            name: "r",
+            fullPath: ["r"],
+            pathWithoutLast: [],
+            pathLast: "r",
+            generics: [
+                {
+                    name: "p",
+                    fullPath: ["p"],
+                    pathWithoutLast: [],
+                    pathLast: "p",
+                    generics: [],
+                },
+            ],
+        }],
+        foundElems: 1,
+        original: "R<P>",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "r<p>",
+        error: null,
+    }
+];
diff --git a/src/test/rustdoc-js-std/parser-paths.js b/src/test/rustdoc-js-std/parser-paths.js
new file mode 100644 (file)
index 0000000..9f823f9
--- /dev/null
@@ -0,0 +1,90 @@
+const QUERY = ['A::B', 'A::B,C',  'A::B<f>,C', 'mod::a'];
+
+const PARSED = [
+    {
+        elems: [{
+            name: "a::b",
+            fullPath: ["a", "b"],
+            pathWithoutLast: ["a"],
+            pathLast: "b",
+            generics: [],
+        }],
+        foundElems: 1,
+        original: "A::B",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a::b",
+        error: null,
+    },
+    {
+        elems: [
+            {
+                name: "a::b",
+                fullPath: ["a", "b"],
+                pathWithoutLast: ["a"],
+                pathLast: "b",
+                generics: [],
+            },
+            {
+                name: "c",
+                fullPath: ["c"],
+                pathWithoutLast: [],
+                pathLast: "c",
+                generics: [],
+            },
+        ],
+        foundElems: 2,
+        original: 'A::B,C',
+        returned: [],
+        typeFilter: -1,
+        userQuery: 'a::b,c',
+        error: null,
+    },
+    {
+        elems: [
+            {
+                name: "a::b",
+                fullPath: ["a", "b"],
+                pathWithoutLast: ["a"],
+                pathLast: "b",
+                generics: [
+                    {
+                        name: "f",
+                        fullPath: ["f"],
+                        pathWithoutLast: [],
+                        pathLast: "f",
+                        generics: [],
+                    },
+                ],
+            },
+            {
+                name: "c",
+                fullPath: ["c"],
+                pathWithoutLast: [],
+                pathLast: "c",
+                generics: [],
+            },
+        ],
+        foundElems: 2,
+        original: 'A::B<f>,C',
+        returned: [],
+        typeFilter: -1,
+        userQuery: 'a::b<f>,c',
+        error: null,
+    },
+    {
+        elems: [{
+            name: "mod::a",
+            fullPath: ["mod", "a"],
+            pathWithoutLast: ["mod"],
+            pathLast: "a",
+            generics: [],
+        }],
+        foundElems: 1,
+        original: "mod::a",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "mod::a",
+        error: null,
+    },
+];
diff --git a/src/test/rustdoc-js-std/parser-quote.js b/src/test/rustdoc-js-std/parser-quote.js
new file mode 100644 (file)
index 0000000..1e16c90
--- /dev/null
@@ -0,0 +1,87 @@
+const QUERY = [
+    '-> "p"',
+    '"p",',
+    '"p" -> a',
+    '"a" -> "p"',
+    '->"-"',
+    '"a',
+    '""',
+];
+
+const PARSED = [
+    {
+        elems: [],
+        foundElems: 1,
+        original: '-> "p"',
+        returned: [{
+            name: "p",
+            fullPath: ["p"],
+            pathWithoutLast: [],
+            pathLast: "p",
+            generics: [],
+        }],
+        typeFilter: -1,
+        userQuery: '-> "p"',
+        error: null,
+    },
+    {
+        elems: [{
+            name: "p",
+            fullPath: ["p"],
+            pathWithoutLast: [],
+            pathLast: "p",
+            generics: [],
+        }],
+        foundElems: 1,
+        original: '"p",',
+        returned: [],
+        typeFilter: -1,
+        userQuery: '"p",',
+        error: null,
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: '"p" -> a',
+        returned: [],
+        typeFilter: -1,
+        userQuery: '"p" -> a',
+        error: "You cannot have more than one element if you use quotes",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: '"a" -> "p"',
+        returned: [],
+        typeFilter: -1,
+        userQuery: '"a" -> "p"',
+        error: "Cannot have more than one literal search element",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: '->"-"',
+        returned: [],
+        typeFilter: -1,
+        userQuery: '->"-"',
+        error: 'Unexpected `-` in a string element',
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: '"a',
+        returned: [],
+        typeFilter: -1,
+        userQuery: '"a',
+        error: 'Unclosed `"`',
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: '""',
+        returned: [],
+        typeFilter: -1,
+        userQuery: '""',
+        error: 'Cannot have empty string element',
+    },
+];
diff --git a/src/test/rustdoc-js-std/parser-returned.js b/src/test/rustdoc-js-std/parser-returned.js
new file mode 100644 (file)
index 0000000..b45466a
--- /dev/null
@@ -0,0 +1,78 @@
+const QUERY = ['-> F<P>', '-> P', '->,a', 'aaaaa->a'];
+
+const PARSED = [
+    {
+        elems: [],
+        foundElems: 1,
+        original: "-> F<P>",
+        returned: [{
+            name: "f",
+            fullPath: ["f"],
+            pathWithoutLast: [],
+            pathLast: "f",
+            generics: [
+                {
+                    name: "p",
+                    fullPath: ["p"],
+                    pathWithoutLast: [],
+                    pathLast: "p",
+                    generics: [],
+                },
+            ],
+        }],
+        typeFilter: -1,
+        userQuery: "-> f<p>",
+        error: null,
+    },
+    {
+        elems: [],
+        foundElems: 1,
+        original: "-> P",
+        returned: [{
+            name: "p",
+            fullPath: ["p"],
+            pathWithoutLast: [],
+            pathLast: "p",
+            generics: [],
+        }],
+        typeFilter: -1,
+        userQuery: "-> p",
+        error: null,
+    },
+    {
+        elems: [],
+        foundElems: 1,
+        original: "->,a",
+        returned: [{
+            name: "a",
+            fullPath: ["a"],
+            pathWithoutLast: [],
+            pathLast: "a",
+            generics: [],
+        }],
+        typeFilter: -1,
+        userQuery: "->,a",
+        error: null,
+    },
+    {
+        elems: [{
+            name: "aaaaa",
+            fullPath: ["aaaaa"],
+            pathWithoutLast: [],
+            pathLast: "aaaaa",
+            generics: [],
+        }],
+        foundElems: 2,
+        original: "aaaaa->a",
+        returned: [{
+            name: "a",
+            fullPath: ["a"],
+            pathWithoutLast: [],
+            pathLast: "a",
+            generics: [],
+        }],
+        typeFilter: -1,
+        userQuery: "aaaaa->a",
+        error: null,
+    },
+];
diff --git a/src/test/rustdoc-js-std/parser-separators.js b/src/test/rustdoc-js-std/parser-separators.js
new file mode 100644 (file)
index 0000000..5b7abdf
--- /dev/null
@@ -0,0 +1,206 @@
+// ignore-tidy-tab
+
+const QUERY = [
+    'aaaaaa    b',
+    'a b',
+    'a,b',
+    'a\tb',
+    'a<b c>',
+    'a<b,c>',
+    'a<b\tc>',
+];
+
+const PARSED = [
+    {
+        elems: [
+            {
+                name: 'aaaaaa',
+                fullPath: ['aaaaaa'],
+                pathWithoutLast: [],
+                pathLast: 'aaaaaa',
+                generics: [],
+            },
+            {
+                name: 'b',
+                fullPath: ['b'],
+                pathWithoutLast: [],
+                pathLast: 'b',
+                generics: [],
+            },
+        ],
+        foundElems: 2,
+        original: "aaaaaa      b",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "aaaaaa     b",
+        error: null,
+    },
+    {
+        elems: [
+            {
+                name: 'a',
+                fullPath: ['a'],
+                pathWithoutLast: [],
+                pathLast: 'a',
+                generics: [],
+            },
+            {
+                name: 'b',
+                fullPath: ['b'],
+                pathWithoutLast: [],
+                pathLast: 'b',
+                generics: [],
+            },
+        ],
+        foundElems: 2,
+        original: "a b",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a b",
+        error: null,
+    },
+    {
+        elems: [
+            {
+                name: 'a',
+                fullPath: ['a'],
+                pathWithoutLast: [],
+                pathLast: 'a',
+                generics: [],
+            },
+            {
+                name: 'b',
+                fullPath: ['b'],
+                pathWithoutLast: [],
+                pathLast: 'b',
+                generics: [],
+            },
+        ],
+        foundElems: 2,
+        original: "a,b",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a,b",
+        error: null,
+    },
+    {
+        elems: [
+            {
+                name: 'a',
+                fullPath: ['a'],
+                pathWithoutLast: [],
+                pathLast: 'a',
+                generics: [],
+            },
+            {
+                name: 'b',
+                fullPath: ['b'],
+                pathWithoutLast: [],
+                pathLast: 'b',
+                generics: [],
+            },
+        ],
+        foundElems: 2,
+        original: "a\tb",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a\tb",
+        error: null,
+    },
+    {
+        elems: [
+            {
+                name: 'a',
+                fullPath: ['a'],
+                pathWithoutLast: [],
+                pathLast: 'a',
+                generics: [
+                    {
+                        name: 'b',
+                        fullPath: ['b'],
+                        pathWithoutLast: [],
+                        pathLast: 'b',
+                        generics: [],
+                    },
+                    {
+                        name: 'c',
+                        fullPath: ['c'],
+                        pathWithoutLast: [],
+                        pathLast: 'c',
+                        generics: [],
+                    },
+                ],
+            },
+        ],
+        foundElems: 1,
+        original: "a<b c>",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a<b c>",
+        error: null,
+    },
+    {
+        elems: [
+            {
+                name: 'a',
+                fullPath: ['a'],
+                pathWithoutLast: [],
+                pathLast: 'a',
+                generics: [
+                    {
+                        name: 'b',
+                        fullPath: ['b'],
+                        pathWithoutLast: [],
+                        pathLast: 'b',
+                        generics: [],
+                    },
+                    {
+                        name: 'c',
+                        fullPath: ['c'],
+                        pathWithoutLast: [],
+                        pathLast: 'c',
+                        generics: [],
+                    },
+                ],
+            },
+        ],
+        foundElems: 1,
+        original: "a<b,c>",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a<b,c>",
+        error: null,
+    },
+    {
+        elems: [
+            {
+                name: 'a',
+                fullPath: ['a'],
+                pathWithoutLast: [],
+                pathLast: 'a',
+                generics: [
+                    {
+                        name: 'b',
+                        fullPath: ['b'],
+                        pathWithoutLast: [],
+                        pathLast: 'b',
+                        generics: [],
+                    },
+                    {
+                        name: 'c',
+                        fullPath: ['c'],
+                        pathWithoutLast: [],
+                        pathLast: 'c',
+                        generics: [],
+                    },
+                ],
+            },
+        ],
+        foundElems: 1,
+        original: "a<b\tc>",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a<b\tc>",
+        error: null,
+    },
+];
diff --git a/src/test/rustdoc-js-std/parser-weird-queries.js b/src/test/rustdoc-js-std/parser-weird-queries.js
new file mode 100644 (file)
index 0000000..a3d85ae
--- /dev/null
@@ -0,0 +1,123 @@
+// This test is mostly to check that the parser still kinda outputs something
+// (and doesn't enter an infinite loop!) even though the query is completely
+// invalid.
+const QUERY = [
+    'a b',
+    'a   b',
+    'a,b(c)',
+    'aaa,a',
+    ',,,,',
+    'mod    :',
+    'mod\t:',
+];
+
+const PARSED = [
+    {
+        elems: [
+            {
+                name: "a",
+                fullPath: ["a"],
+                pathWithoutLast: [],
+                pathLast: "a",
+                generics: [],
+            },
+            {
+                name: "b",
+                fullPath: ["b"],
+                pathWithoutLast: [],
+                pathLast: "b",
+                generics: [],
+            },
+        ],
+        foundElems: 2,
+        original: "a b",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a b",
+        error: null,
+    },
+    {
+        elems: [
+            {
+                name: "a",
+                fullPath: ["a"],
+                pathWithoutLast: [],
+                pathLast: "a",
+                generics: [],
+            },
+            {
+                name: "b",
+                fullPath: ["b"],
+                pathWithoutLast: [],
+                pathLast: "b",
+                generics: [],
+            },
+        ],
+        foundElems: 2,
+        original: "a   b",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a   b",
+        error: null,
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "a,b(c)",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a,b(c)",
+        error: "Unexpected `(`",
+    },
+    {
+        elems: [
+            {
+                name: "aaa",
+                fullPath: ["aaa"],
+                pathWithoutLast: [],
+                pathLast: "aaa",
+                generics: [],
+            },
+            {
+                name: "a",
+                fullPath: ["a"],
+                pathWithoutLast: [],
+                pathLast: "a",
+                generics: [],
+            },
+        ],
+        foundElems: 2,
+        original: "aaa,a",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "aaa,a",
+        error: null,
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: ",,,,",
+        returned: [],
+        typeFilter: -1,
+        userQuery: ",,,,",
+        error: null,
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: 'mod    :',
+        returned: [],
+        typeFilter: 0,
+        userQuery: 'mod    :',
+        error: null,
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: 'mod\t:',
+        returned: [],
+        typeFilter: 0,
+        userQuery: 'mod\t:',
+        error: null,
+    },
+];
index 924129f86c8680214c07e2569cbea02aa2bc2a63..aec8484a41f6dcb6e27ad2cee6a0247163bdc4d3 100644 (file)
@@ -1,4 +1,7 @@
+// ignore-order
+
 const QUERY = '"error"';
+const FILTER_CRATE = 'std';
 
 const EXPECTED = {
     'others': [
@@ -6,7 +9,12 @@ const EXPECTED = {
         { 'path': 'std::fmt', 'name': 'Error' },
         { 'path': 'std::io', 'name': 'Error' },
     ],
-    'in_args': [],
+    'in_args': [
+        { 'path': 'std::fmt::Error', 'name': 'eq' },
+        { 'path': 'std::fmt::Error', 'name': 'cmp' },
+        { 'path': 'std::fmt::Error', 'name': 'partial_cmp' },
+
+    ],
     'returned': [
         { 'path': 'std::fmt::LowerExp', 'name': 'fmt' },
     ],
index 2c808143bae67fb434fda6307c5da81ef57d71c3..29609904b1957a52f893b9de8f097f796d399a49 100644 (file)
@@ -1,8 +1,8 @@
-const QUERY = 'struct:Vec';
+const QUERY = 'struct:VecD';
 
 const EXPECTED = {
     'others': [
-        { 'path': 'std::vec', 'name': 'Vec' },
         { 'path': 'std::collections', 'name': 'VecDeque' },
+        { 'path': 'std::vec', 'name': 'Vec' },
     ],
 };
index 3915ee7dc5d23196249c8499452744471076cfbb..25efbad26954003233d959692152f34888221bd7 100644 (file)
@@ -1,6 +1,7 @@
 // exact-check
 
 const QUERY = 'macro:print';
+const FILTER_CRATE = 'std';
 
 const EXPECTED = {
     'others': [
@@ -9,6 +10,8 @@ const EXPECTED = {
         { 'path': 'std', 'name': 'println' },
         { 'path': 'std', 'name': 'eprintln' },
         { 'path': 'std::pin', 'name': 'pin' },
-        { 'path': 'core::pin', 'name': 'pin' },
+        { 'path': 'std::future', 'name': 'join' },
+        { 'path': 'std', 'name': 'line' },
+        { 'path': 'std', 'name': 'write' },
     ],
 };
index e1a3256876bde15af94274c65d1ab29a71c6ce62..cd0e8e7b4a9eb41524adbb55fc8d9c931a8d20d4 100644 (file)
@@ -4,6 +4,6 @@ const EXPECTED = {
     'others': [
         { 'path': 'std::vec::Vec', 'name': 'new' },
         { 'path': 'std::vec::Vec', 'name': 'ne' },
-        { 'path': 'std::rc::Rc', 'name': 'ne' },
+        { 'path': 'alloc::vec::Vec', 'name': 'ne' },
     ],
 };
index 4b1e2e2970479d386c87370b03e783017937f588..e06047ba7606e78b8de5591ec8ecbbda03993a9d 100644 (file)
@@ -1,6 +1,6 @@
 // exact-check
 
-const QUERY = 'true';
+const QUERY = '"true"';
 
 const FILTER_CRATE = 'doc_alias_filter';
 
index ff188d5145801ad127793bf1094137b6cadb743f..7bb0cbe388fee1c8d7626b2d4aa74edd9ac80d10 100644 (file)
@@ -27,6 +27,7 @@ const QUERY = [
 
 const EXPECTED = [
     {
+        // StructItem
         'others': [
             {
                 'path': 'doc_alias',
@@ -38,6 +39,7 @@ const EXPECTED = [
         ],
     },
     {
+        // StructFieldItem
         'others': [
             {
                 'path': 'doc_alias::Struct',
@@ -49,6 +51,7 @@ const EXPECTED = [
         ],
     },
     {
+        // StructMethodItem
         'others': [
             {
                 'path': 'doc_alias::Struct',
@@ -76,6 +79,7 @@ const EXPECTED = [
         ],
     },
     {
+        // ImplTraitFunction
         'others': [
             {
                 'path': 'doc_alias::Struct',
@@ -87,6 +91,7 @@ const EXPECTED = [
         ],
     },
     {
+        // EnumItem
         'others': [
             {
                 'path': 'doc_alias',
@@ -98,6 +103,7 @@ const EXPECTED = [
         ],
     },
     {
+        // VariantItem
         'others': [
             {
                 'path': 'doc_alias::Enum',
@@ -109,6 +115,7 @@ const EXPECTED = [
         ],
     },
     {
+        // EnumMethodItem
         'others': [
             {
                 'path': 'doc_alias::Enum',
@@ -120,6 +127,7 @@ const EXPECTED = [
         ],
     },
     {
+        // TypedefItem
         'others': [
             {
                 'path': 'doc_alias',
@@ -131,6 +139,7 @@ const EXPECTED = [
         ],
     },
     {
+        // TraitItem
         'others': [
             {
                 'path': 'doc_alias',
@@ -142,6 +151,7 @@ const EXPECTED = [
         ],
     },
     {
+        // TraitTypeItem
         'others': [
             {
                 'path': 'doc_alias::Trait',
@@ -153,6 +163,7 @@ const EXPECTED = [
         ],
     },
     {
+        // AssociatedConstItem
         'others': [
             {
                 'path': 'doc_alias::Trait',
@@ -164,6 +175,7 @@ const EXPECTED = [
         ],
     },
     {
+        // TraitFunctionItem
         'others': [
             {
                 'path': 'doc_alias::Trait',
@@ -175,6 +187,7 @@ const EXPECTED = [
         ],
     },
     {
+        // FunctionItem
         'others': [
             {
                 'path': 'doc_alias',
@@ -186,6 +199,7 @@ const EXPECTED = [
         ],
     },
     {
+        // ModuleItem
         'others': [
             {
                 'path': 'doc_alias',
@@ -197,6 +211,7 @@ const EXPECTED = [
         ],
     },
     {
+        // ConstItem
         'others': [
             {
                 'path': 'doc_alias',
@@ -212,6 +227,7 @@ const EXPECTED = [
         ],
     },
     {
+        // StaticItem
         'others': [
             {
                 'path': 'doc_alias',
@@ -223,6 +239,7 @@ const EXPECTED = [
         ],
     },
     {
+        // UnionItem
         'others': [
             {
                 'path': 'doc_alias',
@@ -240,6 +257,7 @@ const EXPECTED = [
         ],
     },
     {
+        // UnionFieldItem
         'others': [
             {
                 'path': 'doc_alias::Union',
@@ -251,6 +269,7 @@ const EXPECTED = [
         ],
     },
     {
+        // UnionMethodItem
         'others': [
             {
                 'path': 'doc_alias::Union',
@@ -262,6 +281,7 @@ const EXPECTED = [
         ],
     },
     {
+        // MacroItem
         'others': [
             {
                 'path': 'doc_alias',
index 63a9ad5381244c635e80674ea8eafc11e04bd839..5e5ba7cd9ac8f55c35c4525e182390592ae6c335 100644 (file)
@@ -1,16 +1,18 @@
 // exact-check
 
 const QUERY = [
-    '"R<P>"',
+    'R<P>',
     '"P"',
     'P',
-    '"ExtraCreditStructMulti<ExtraCreditInnerMulti, ExtraCreditInnerMulti>"',
+    'ExtraCreditStructMulti<ExtraCreditInnerMulti, ExtraCreditInnerMulti>',
     'TraitCat',
     'TraitDog',
+    'Result<String>',
 ];
 
 const EXPECTED = [
     {
+        // R<P>
         'returned': [
             { 'path': 'generics', 'name': 'alef' },
         ],
@@ -19,6 +21,7 @@ const EXPECTED = [
         ],
     },
     {
+        // "P"
         'others': [
             { 'path': 'generics', 'name': 'P' },
         ],
@@ -30,29 +33,41 @@ const EXPECTED = [
         ],
     },
     {
+        // P
         'returned': [
             { 'path': 'generics', 'name': 'alef' },
-            { 'path': 'generics', 'name': 'bet' },
         ],
         'in_args': [
             { 'path': 'generics', 'name': 'alpha' },
-            { 'path': 'generics', 'name': 'beta' },
         ],
     },
     {
+        // "ExtraCreditStructMulti"<ExtraCreditInnerMulti, ExtraCreditInnerMulti>
         'in_args': [
             { 'path': 'generics', 'name': 'extracreditlabhomework' },
         ],
         'returned': [],
     },
     {
+        // TraitCat
         'in_args': [
             { 'path': 'generics', 'name': 'gamma' },
         ],
     },
     {
+        // TraitDog
         'in_args': [
             { 'path': 'generics', 'name': 'gamma' },
         ],
     },
+    {
+        // Result<String>
+        'others': [],
+        'returned': [
+            { 'path': 'generics', 'name': 'super_soup' },
+        ],
+        'in_args': [
+            { 'path': 'generics', 'name': 'super_soup' },
+        ],
+    },
 ];
index 5e11a6d6018856f75daaa7e73cc43fe7cd03764e..055c51c7ec5781f819196bbf9e1907b5ff61194b 100644 (file)
@@ -24,3 +24,5 @@ pub trait TraitCat {}
 pub trait TraitDog {}
 
 pub fn gamma<T: TraitCat + TraitDog>(t: T) {}
+
+pub fn super_soup(s: Result<String, i32>) -> Result<String, i32> { s }
index 9465e8e7ab99649bfff1c0a9fe6f64c3f267ca03..7a5156e81c4c875fbd0a5d58bb216ff0b7074b8e 100644 (file)
@@ -1,7 +1,7 @@
 // normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
+// check-pass
 #![deny(warnings)]
 
 //! Email me at <hello@localhost>.
-//~^ ERROR unknown disambiguator `hello`
 
 //! This should *not* warn: <hello@example.com>.
diff --git a/src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr b/src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr
deleted file mode 100644 (file)
index 1b07828..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-error: unknown disambiguator `hello`
-  --> $DIR/email-address-localhost.rs:4:18
-   |
-LL | //! Email me at <hello@localhost>.
-   |                  ^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/email-address-localhost.rs:2:9
-   |
-LL | #![deny(warnings)]
-   |         ^^^^^^^^
-   = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]`
-   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
-
-error: aborting due to previous error
-
diff --git a/src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.rs b/src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.rs
new file mode 100644 (file)
index 0000000..c71e5be
--- /dev/null
@@ -0,0 +1,6 @@
+// Regression test for issue #95879.
+
+use unresolved_crate::module::Name; //~ ERROR failed to resolve
+
+/// [Name]
+pub struct S;
diff --git a/src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr b/src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr
new file mode 100644 (file)
index 0000000..b60ab60
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0433]: failed to resolve: maybe a missing crate `unresolved_crate`?
+  --> $DIR/unresolved-import-recovery.rs:3:5
+   |
+LL | use unresolved_crate::module::Name;
+   |     ^^^^^^^^^^^^^^^^ maybe a missing crate `unresolved_crate`?
+
+error: Compilation failed, aborting rustdoc
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
index d0372d4945f3a4598043fea06c2565c2f5ae8373..a19e452b459e19c85d84fb048b34a3b03cac84fc 100644 (file)
@@ -1,7 +1,6 @@
 Available passes for running rustdoc:
 check_doc_test_visibility - run various visibility-related lints on doctests
         strip-hidden - strips all `#[doc(hidden)]` items from the output
-   unindent-comments - removes excess indentation on comments in order for markdown to like it
        strip-private - strips all private items from a crate which cannot be seen externally, implies strip-priv-imports
   strip-priv-imports - strips all private import statements (`use`, `extern crate`) from a crate
    propagate-doc-cfg - propagates `#[doc(cfg(...))]` to child items
@@ -14,7 +13,6 @@ check-invalid-html-tags - detects invalid HTML tags in doc comments
 
 Default passes for rustdoc:
  collect-trait-impls
-   unindent-comments
 check_doc_test_visibility
         strip-hidden  (when not --document-hidden-items)
        strip-private  (when not --document-private-items)
index 9465c8a35c886f83e6681b4eb70c963b68ee47f3..4cddb0b76d410125eb708e69f86a433156642fdb 100644 (file)
@@ -4,21 +4,21 @@
 // @has doc_cfg/struct.Portable.html
 // @!has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' ''
 // @has - '//*[@id="method.unix_and_arm_only_function"]' 'fn unix_and_arm_only_function()'
-// @has - '//*[@class="stab portability"]' 'This is supported on Unix and ARM only.'
+// @has - '//*[@class="stab portability"]' 'Available on Unix and ARM only.'
 // @has - '//*[@id="method.wasi_and_wasm32_only_function"]' 'fn wasi_and_wasm32_only_function()'
-// @has - '//*[@class="stab portability"]' 'This is supported on WASI and WebAssembly only.'
+// @has - '//*[@class="stab portability"]' 'Available on WASI and WebAssembly only.'
 pub struct Portable;
 
 // @has doc_cfg/unix_only/index.html \
 //  '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
-//  'This is supported on Unix only.'
+//  'Available on Unix only.'
 // @matches - '//*[@class="item-left module-item"]//*[@class="stab portability"]' '\AARM\Z'
 // @count - '//*[@class="stab portability"]' 2
 #[doc(cfg(unix))]
 pub mod unix_only {
     // @has doc_cfg/unix_only/fn.unix_only_function.html \
     //  '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
-    //  'This is supported on Unix only.'
+    //  'Available on Unix only.'
     // @count - '//*[@class="stab portability"]' 1
     pub fn unix_only_function() {
         content::should::be::irrelevant();
@@ -26,7 +26,7 @@ pub fn unix_only_function() {
 
     // @has doc_cfg/unix_only/trait.ArmOnly.html \
     //  '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
-    //  'This is supported on Unix and ARM only.'
+    //  'Available on Unix and ARM only.'
     // @count - '//*[@class="stab portability"]' 1
     #[doc(cfg(target_arch = "arm"))]
     pub trait ArmOnly {
@@ -41,14 +41,14 @@ fn unix_and_arm_only_function() {}
 
 // @has doc_cfg/wasi_only/index.html \
 //  '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
-//  'This is supported on WASI only.'
+//  'Available on WASI only.'
 // @matches - '//*[@class="item-left module-item"]//*[@class="stab portability"]' '\AWebAssembly\Z'
 // @count - '//*[@class="stab portability"]' 2
 #[doc(cfg(target_os = "wasi"))]
 pub mod wasi_only {
     // @has doc_cfg/wasi_only/fn.wasi_only_function.html \
     //  '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
-    //  'This is supported on WASI only.'
+    //  'Available on WASI only.'
     // @count - '//*[@class="stab portability"]' 1
     pub fn wasi_only_function() {
         content::should::be::irrelevant();
@@ -56,7 +56,7 @@ pub fn wasi_only_function() {
 
     // @has doc_cfg/wasi_only/trait.Wasm32Only.html \
     //  '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
-    //  'This is supported on WASI and WebAssembly only.'
+    //  'Available on WASI and WebAssembly only.'
     // @count - '//*[@class="stab portability"]' 1
     #[doc(cfg(target_arch = "wasm32"))]
     pub trait Wasm32Only {
@@ -78,7 +78,7 @@ fn wasi_and_wasm32_only_function() {}
 
 // @has doc_cfg/fn.uses_target_feature.html
 // @has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
-//        'This is supported with target feature avx only.'
+//        'Available with target feature avx only.'
 #[target_feature(enable = "avx")]
 pub unsafe fn uses_target_feature() {
     content::should::be::irrelevant();
@@ -86,7 +86,7 @@ pub unsafe fn uses_target_feature() {
 
 // @has doc_cfg/fn.uses_cfg_target_feature.html
 // @has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
-//        'This is supported with target feature avx only.'
+//        'Available with target feature avx only.'
 #[doc(cfg(target_feature = "avx"))]
 pub fn uses_cfg_target_feature() {
     uses_target_feature();
@@ -95,7 +95,7 @@ pub fn uses_cfg_target_feature() {
 // multiple attributes should be allowed
 // @has doc_cfg/fn.multiple_attrs.html \
 //  '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
-//  'This is supported on x and y and z only.'
+//  'Available on x and y and z only.'
 #[doc(cfg(x))]
 #[doc(cfg(y), cfg(z))]
 pub fn multiple_attrs() {}
index 886ec6750304abb092266e2f6832e5aa95f7f36d..18f3900b263b0b7617def5151e60c43519be7d5f 100644 (file)
@@ -3,7 +3,7 @@
 
 // @has 'foo/index.html'
 // @matches '-' '//*[@class="item-left module-item"]//*[@class="stab portability"]' '^sync$'
-// @has '-' '//*[@class="item-left module-item"]//*[@class="stab portability"]/@title' 'This is supported on crate feature `sync` only'
+// @has '-' '//*[@class="item-left module-item"]//*[@class="stab portability"]/@title' 'Available on crate feature `sync` only'
 
 // @has 'foo/struct.Foo.html'
 // @has '-' '//*[@class="stab portability"]' 'sync'
 pub struct Foo;
 
 // @has 'foo/bar/index.html'
-// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync only.'
+// @has '-' '//*[@class="stab portability"]' 'Available on crate feature sync only.'
 #[doc(cfg(feature = "sync"))]
 pub mod bar {
     // @has 'foo/bar/struct.Bar.html'
-    // @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync only.'
+    // @has '-' '//*[@class="stab portability"]' 'Available on crate feature sync only.'
     #[doc(cfg(feature = "sync"))]
     pub struct Bar;
 }
 
 // @has 'foo/baz/index.html'
-// @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.'
+// @has '-' '//*[@class="stab portability"]' 'Available on crate features sync and send only.'
 #[doc(cfg(all(feature = "sync", feature = "send")))]
 pub mod baz {
     // @has 'foo/baz/struct.Baz.html'
-    // @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.'
+    // @has '-' '//*[@class="stab portability"]' 'Available on crate features sync and send only.'
     #[doc(cfg(feature = "sync"))]
     pub struct Baz;
 }
 
 // @has 'foo/qux/index.html'
-// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync only.'
+// @has '-' '//*[@class="stab portability"]' 'Available on crate feature sync only.'
 #[doc(cfg(feature = "sync"))]
 pub mod qux {
     // @has 'foo/qux/struct.Qux.html'
-    // @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.'
+    // @has '-' '//*[@class="stab portability"]' 'Available on crate features sync and send only.'
     #[doc(cfg(all(feature = "sync", feature = "send")))]
     pub struct Qux;
 }
 
 // @has 'foo/quux/index.html'
-// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync and crate feature send and foo only.'
+// @has '-' '//*[@class="stab portability"]' 'Available on crate feature sync and crate feature send and foo only.'
 #[doc(cfg(all(feature = "sync", feature = "send", foo)))]
 pub mod quux {
     // @has 'foo/quux/struct.Quux.html'
-    // @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync and crate feature send and foo and bar only.'
+    // @has '-' '//*[@class="stab portability"]' 'Available on crate feature sync and crate feature send and foo and bar only.'
     #[doc(cfg(all(feature = "send", feature = "sync", bar)))]
     pub struct Quux;
 }
diff --git a/src/test/rustdoc/duplicated_impl.rs b/src/test/rustdoc/duplicated_impl.rs
new file mode 100644 (file)
index 0000000..4e901b3
--- /dev/null
@@ -0,0 +1,14 @@
+// This test ensures that the same implementation doesn't show more than once.
+// It's a regression test for https://github.com/rust-lang/rust/issues/96036.
+
+#![crate_name = "foo"]
+
+// We check that there is only one "impl<T> Something<Whatever> for T" listed in the
+// blanket implementations.
+
+// @has 'foo/struct.Whatever.html'
+// @count - '//*[@id="blanket-implementations-list"]/section[@class="impl has-srclink"]' 1
+
+pub trait Something<T> { }
+pub struct Whatever;
+impl<T> Something<Whatever> for T {}
diff --git a/src/test/rustdoc/early-unindent.rs b/src/test/rustdoc/early-unindent.rs
new file mode 100644 (file)
index 0000000..791a452
--- /dev/null
@@ -0,0 +1,26 @@
+// This is a regression for https://github.com/rust-lang/rust/issues/96079.
+
+#![crate_name = "foo"]
+
+pub mod app {
+    pub struct S;
+
+    impl S {
+        // @has 'foo/app/struct.S.html'
+        // @has - '//a[@href="../enums/enum.Foo.html#method.by_name"]' 'Foo::by_name'
+        /**
+        Doc comment hello! [`Foo::by_name`](`crate::enums::Foo::by_name`).
+        */
+        pub fn whatever(&self) {}
+    }
+}
+
+pub mod enums {
+    pub enum Foo {
+        Bar,
+    }
+
+    impl Foo {
+        pub fn by_name(&self) {}
+    }
+}
diff --git a/src/test/rustdoc/where.SWhere_Simd_item-decl.html b/src/test/rustdoc/where.SWhere_Simd_item-decl.html
new file mode 100644 (file)
index 0000000..0133bca
--- /dev/null
@@ -0,0 +1 @@
+<div class="docblock item-decl"><pre class="rust struct"><code>pub struct Simd&lt;T&gt;(_) <br /><span class="where">where<br />&#160;&#160;&#160;&#160;T: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a></span>;</code></pre></div>
\ No newline at end of file
diff --git a/src/test/rustdoc/where.SWhere_TraitWhere_item-decl.html b/src/test/rustdoc/where.SWhere_TraitWhere_item-decl.html
new file mode 100644 (file)
index 0000000..54026ff
--- /dev/null
@@ -0,0 +1,3 @@
+<div class="docblock item-decl"><pre class="rust trait"><code>pub trait TraitWhere {
+    type <a href="#associatedtype.Item" class="associatedtype">Item</a>&lt;'a&gt;<br />&#160;&#160;&#160; <span class="where">where<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Self: 'a</span>;
+}</code></pre></div>
\ No newline at end of file
index 549cfff96cb6dc37e5c56aa7f06c99ff778e60dd..50a5722fbaff6926e5feec51c6ffd18d531bac5a 100644 (file)
@@ -1,3 +1,4 @@
+#![feature(generic_associated_types)]
 #![crate_name = "foo"]
 
 pub trait MyTrait { fn dummy(&self) { } }
@@ -19,6 +20,18 @@ pub fn delta() {}
 
 pub struct Echo<E>(E);
 
+// @has 'foo/struct.Simd.html'
+// @snapshot SWhere_Simd_item-decl - '//div[@class="docblock item-decl"]'
+pub struct Simd<T>([T; 1])
+where
+    T: MyTrait;
+
+// @has 'foo/trait.TraitWhere.html'
+// @snapshot SWhere_TraitWhere_item-decl - '//div[@class="docblock item-decl"]'
+pub trait TraitWhere {
+    type Item<'a> where Self: 'a;
+}
+
 // @has foo/struct.Echo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 //          "impl<E> MyTrait for Echo<E> where E: MyTrait"
 // @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header in-band"]' \
diff --git a/src/test/ui/arg-count-mismatch.rs b/src/test/ui/arg-count-mismatch.rs
deleted file mode 100644 (file)
index 18926f5..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-// error-pattern: arguments were supplied
-
-fn f(x: isize) { }
-
-fn main() { let i: (); i = f(); }
diff --git a/src/test/ui/arg-count-mismatch.stderr b/src/test/ui/arg-count-mismatch.stderr
deleted file mode 100644 (file)
index d0577e4..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0061]: this function takes 1 argument but 0 arguments were supplied
-  --> $DIR/arg-count-mismatch.rs:5:28
-   |
-LL | fn main() { let i: (); i = f(); }
-   |                            ^-- supplied 0 arguments
-   |                            |
-   |                            expected 1 argument
-   |
-note: function defined here
-  --> $DIR/arg-count-mismatch.rs:3:4
-   |
-LL | fn f(x: isize) { }
-   |    ^ --------
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/arg-type-mismatch.rs b/src/test/ui/arg-type-mismatch.rs
deleted file mode 100644 (file)
index 04ce288..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-// error-pattern: mismatched types
-
-fn f(x: isize) { }
-
-fn main() { let i: (); i = f(()); }
diff --git a/src/test/ui/arg-type-mismatch.stderr b/src/test/ui/arg-type-mismatch.stderr
deleted file mode 100644 (file)
index 05b21ef..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/arg-type-mismatch.rs:5:30
-   |
-LL | fn main() { let i: (); i = f(()); }
-   |                              ^^ expected `isize`, found `()`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/argument-suggestions/basic.rs b/src/test/ui/argument-suggestions/basic.rs
new file mode 100644 (file)
index 0000000..765b2d5
--- /dev/null
@@ -0,0 +1,25 @@
+// Some basic "obvious" cases for the heuristic error messages added for #65853
+// One for each of the detected cases
+
+enum E { X, Y }
+enum F { X2, Y2 }
+struct G {}
+struct H {}
+struct X {}
+struct Y {}
+struct Z {}
+
+
+fn invalid(_i: u32) {}
+fn extra() {}
+fn missing(_i: u32) {}
+fn swapped(_i: u32, _s: &str) {}
+fn permuted(_x: X, _y: Y, _z: Z) {}
+
+fn main() {
+    invalid(1.0); //~ ERROR mismatched types
+    extra(""); //~ ERROR this function takes
+    missing(); //~ ERROR this function takes
+    swapped("", 1); //~ ERROR arguments to this function are incorrect
+    permuted(Y {}, Z {}, X {}); //~ ERROR arguments to this function are incorrect
+}
diff --git a/src/test/ui/argument-suggestions/basic.stderr b/src/test/ui/argument-suggestions/basic.stderr
new file mode 100644 (file)
index 0000000..78f82b0
--- /dev/null
@@ -0,0 +1,87 @@
+error[E0308]: mismatched types
+  --> $DIR/basic.rs:20:13
+   |
+LL |     invalid(1.0);
+   |     ------- ^^^ expected `u32`, found floating-point number
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/basic.rs:13:4
+   |
+LL | fn invalid(_i: u32) {}
+   |    ^^^^^^^ -------
+
+error[E0061]: this function takes 0 arguments but 1 argument was supplied
+  --> $DIR/basic.rs:21:5
+   |
+LL |     extra("");
+   |     ^^^^^ -- argument unexpected
+   |
+note: function defined here
+  --> $DIR/basic.rs:14:4
+   |
+LL | fn extra() {}
+   |    ^^^^^
+help: remove the extra argument
+   |
+LL |     extra();
+   |     ~~~~~~~
+
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
+  --> $DIR/basic.rs:22:5
+   |
+LL |     missing();
+   |     ^^^^^^^-- an argument of type `u32` is missing
+   |
+note: function defined here
+  --> $DIR/basic.rs:15:4
+   |
+LL | fn missing(_i: u32) {}
+   |    ^^^^^^^ -------
+help: provide the argument
+   |
+LL |     missing({u32});
+   |     ~~~~~~~~~~~~~~
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/basic.rs:23:5
+   |
+LL |     swapped("", 1);
+   |     ^^^^^^^ --  - expected `&str`,found `{integer}`
+   |             |
+   |             expected `u32`,found `&'static str`
+   |
+note: function defined here
+  --> $DIR/basic.rs:16:4
+   |
+LL | fn swapped(_i: u32, _s: &str) {}
+   |    ^^^^^^^ -------  --------
+help: swap these arguments
+   |
+LL |     swapped(1, "");
+   |     ~~~~~~~~~~~~~~
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/basic.rs:24:5
+   |
+LL |     permuted(Y {}, Z {}, X {});
+   |     ^^^^^^^^ ----  ----  ---- expected `Z`,found `X`
+   |              |     |
+   |              |     expected `Y`,found `Z`
+   |              expected `X`,found `Y`
+   |
+note: function defined here
+  --> $DIR/basic.rs:17:4
+   |
+LL | fn permuted(_x: X, _y: Y, _z: Z) {}
+   |    ^^^^^^^^ -----  -----  -----
+help: reorder these arguments
+   |
+LL |     permuted(X {}, Y {}, Z {});
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0061, E0308.
+For more information about an error, try `rustc --explain E0061`.
diff --git a/src/test/ui/argument-suggestions/complex.rs b/src/test/ui/argument-suggestions/complex.rs
new file mode 100644 (file)
index 0000000..384cdca
--- /dev/null
@@ -0,0 +1,16 @@
+// A complex case with mixed suggestions from #65853
+
+enum E { X, Y }
+enum F { X2, Y2 }
+struct G {}
+struct H {}
+struct X {}
+struct Y {}
+struct Z {}
+
+fn complex(_i: u32, _s: &str, _e: E, _f: F, _g: G, _x: X, _y: Y, _z: Z ) {}
+
+fn main() {
+  complex(1.0, H {}, &"", G{}, F::X2, Z {}, X {}, Y {});
+  //~^ ERROR arguments to this function are incorrect
+}
diff --git a/src/test/ui/argument-suggestions/complex.stderr b/src/test/ui/argument-suggestions/complex.stderr
new file mode 100644 (file)
index 0000000..c628f7d
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/complex.rs:14:3
+   |
+LL |   complex(1.0, H {}, &"", G{}, F::X2, Z {}, X {}, Y {});
+   |   ^^^^^^^ --- expected `u32`, found floating-point number
+   |
+note: function defined here
+  --> $DIR/complex.rs:11:4
+   |
+LL | fn complex(_i: u32, _s: &str, _e: E, _f: F, _g: G, _x: X, _y: Y, _z: Z ) {}
+   |    ^^^^^^^ -------  --------  -----  -----  -----  -----  -----  ------
+help: did you mean
+   |
+LL |   complex({u32}, &"", {E}, F::X2, G{}, X {}, Y {}, Z {});
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/argument-suggestions/extra_arguments.rs b/src/test/ui/argument-suggestions/extra_arguments.rs
new file mode 100644 (file)
index 0000000..3706ac4
--- /dev/null
@@ -0,0 +1,35 @@
+fn empty() {}
+fn one_arg(_a: i32) {}
+fn two_arg_same(_a: i32, _b: i32) {}
+fn two_arg_diff(_a: i32, _b: &str) {}
+
+fn main() {
+  empty(""); //~ ERROR this function takes
+
+  one_arg(1, 1); //~ ERROR this function takes
+  one_arg(1, ""); //~ ERROR this function takes
+  one_arg(1, "", 1.0); //~ ERROR this function takes
+
+  two_arg_same(1, 1, 1); //~ ERROR this function takes
+  two_arg_same(1, 1, 1.0); //~ ERROR this function takes
+
+  two_arg_diff(1, 1, ""); //~ ERROR this function takes
+  two_arg_diff(1, "", ""); //~ ERROR this function takes
+  two_arg_diff(1, 1, "", ""); //~ ERROR this function takes
+  two_arg_diff(1, "", 1, ""); //~ ERROR this function takes
+
+  // Check with weird spacing and newlines
+  two_arg_same(1, 1,     ""); //~ ERROR this function takes
+  two_arg_diff(1, 1,     ""); //~ ERROR this function takes
+  two_arg_same( //~ ERROR this function takes
+    1,
+    1,
+    ""
+  );
+
+  two_arg_diff( //~ ERROR this function takes
+    1,
+    1,
+    ""
+  );
+}
diff --git a/src/test/ui/argument-suggestions/extra_arguments.stderr b/src/test/ui/argument-suggestions/extra_arguments.stderr
new file mode 100644 (file)
index 0000000..9b63f9b
--- /dev/null
@@ -0,0 +1,239 @@
+error[E0061]: this function takes 0 arguments but 1 argument was supplied
+  --> $DIR/extra_arguments.rs:7:3
+   |
+LL |   empty("");
+   |   ^^^^^ -- argument unexpected
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:1:4
+   |
+LL | fn empty() {}
+   |    ^^^^^
+help: remove the extra argument
+   |
+LL |   empty();
+   |   ~~~~~~~
+
+error[E0061]: this function takes 1 argument but 2 arguments were supplied
+  --> $DIR/extra_arguments.rs:9:3
+   |
+LL |   one_arg(1, 1);
+   |   ^^^^^^^    - argument unexpected
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:2:4
+   |
+LL | fn one_arg(_a: i32) {}
+   |    ^^^^^^^ -------
+help: remove the extra argument
+   |
+LL |   one_arg(1);
+   |   ~~~~~~~~~~
+
+error[E0061]: this function takes 1 argument but 2 arguments were supplied
+  --> $DIR/extra_arguments.rs:10:3
+   |
+LL |   one_arg(1, "");
+   |   ^^^^^^^    -- argument unexpected
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:2:4
+   |
+LL | fn one_arg(_a: i32) {}
+   |    ^^^^^^^ -------
+help: remove the extra argument
+   |
+LL |   one_arg(1);
+   |   ~~~~~~~~~~
+
+error[E0061]: this function takes 1 argument but 3 arguments were supplied
+  --> $DIR/extra_arguments.rs:11:3
+   |
+LL |   one_arg(1, "", 1.0);
+   |   ^^^^^^^    --  --- argument unexpected
+   |              |
+   |              argument unexpected
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:2:4
+   |
+LL | fn one_arg(_a: i32) {}
+   |    ^^^^^^^ -------
+help: remove the extra arguments
+   |
+LL |   one_arg(1);
+   |   ~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+  --> $DIR/extra_arguments.rs:13:3
+   |
+LL |   two_arg_same(1, 1, 1);
+   |   ^^^^^^^^^^^^       - argument unexpected
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:3:4
+   |
+LL | fn two_arg_same(_a: i32, _b: i32) {}
+   |    ^^^^^^^^^^^^ -------  -------
+help: remove the extra argument
+   |
+LL |   two_arg_same(1, 1);
+   |   ~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+  --> $DIR/extra_arguments.rs:14:3
+   |
+LL |   two_arg_same(1, 1, 1.0);
+   |   ^^^^^^^^^^^^       --- argument unexpected
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:3:4
+   |
+LL | fn two_arg_same(_a: i32, _b: i32) {}
+   |    ^^^^^^^^^^^^ -------  -------
+help: remove the extra argument
+   |
+LL |   two_arg_same(1, 1);
+   |   ~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+  --> $DIR/extra_arguments.rs:16:3
+   |
+LL |   two_arg_diff(1, 1, "");
+   |   ^^^^^^^^^^^^    - argument of type `&str` unexpected
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:4:4
+   |
+LL | fn two_arg_diff(_a: i32, _b: &str) {}
+   |    ^^^^^^^^^^^^ -------  --------
+help: remove the extra argument
+   |
+LL |   two_arg_diff(1, "");
+   |   ~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+  --> $DIR/extra_arguments.rs:17:3
+   |
+LL |   two_arg_diff(1, "", "");
+   |   ^^^^^^^^^^^^        -- argument unexpected
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:4:4
+   |
+LL | fn two_arg_diff(_a: i32, _b: &str) {}
+   |    ^^^^^^^^^^^^ -------  --------
+help: remove the extra argument
+   |
+LL |   two_arg_diff(1, "");
+   |   ~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 4 arguments were supplied
+  --> $DIR/extra_arguments.rs:18:3
+   |
+LL |   two_arg_diff(1, 1, "", "");
+   |   ^^^^^^^^^^^^    -      -- argument unexpected
+   |                   |
+   |                   argument of type `&str` unexpected
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:4:4
+   |
+LL | fn two_arg_diff(_a: i32, _b: &str) {}
+   |    ^^^^^^^^^^^^ -------  --------
+help: remove the extra arguments
+   |
+LL |   two_arg_diff(1, "");
+   |   ~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 4 arguments were supplied
+  --> $DIR/extra_arguments.rs:19:3
+   |
+LL |   two_arg_diff(1, "", 1, "");
+   |   ^^^^^^^^^^^^        -  -- argument unexpected
+   |                       |
+   |                       argument unexpected
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:4:4
+   |
+LL | fn two_arg_diff(_a: i32, _b: &str) {}
+   |    ^^^^^^^^^^^^ -------  --------
+help: remove the extra arguments
+   |
+LL |   two_arg_diff(1, "");
+   |   ~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+  --> $DIR/extra_arguments.rs:22:3
+   |
+LL |   two_arg_same(1, 1,     "");
+   |   ^^^^^^^^^^^^           -- argument unexpected
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:3:4
+   |
+LL | fn two_arg_same(_a: i32, _b: i32) {}
+   |    ^^^^^^^^^^^^ -------  -------
+help: remove the extra argument
+   |
+LL |   two_arg_same(1, 1);
+   |   ~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+  --> $DIR/extra_arguments.rs:23:3
+   |
+LL |   two_arg_diff(1, 1,     "");
+   |   ^^^^^^^^^^^^    - argument of type `&str` unexpected
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:4:4
+   |
+LL | fn two_arg_diff(_a: i32, _b: &str) {}
+   |    ^^^^^^^^^^^^ -------  --------
+help: remove the extra argument
+   |
+LL |   two_arg_diff(1, "");
+   |   ~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+  --> $DIR/extra_arguments.rs:24:3
+   |
+LL |   two_arg_same(
+   |   ^^^^^^^^^^^^
+...
+LL |     ""
+   |     -- argument unexpected
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:3:4
+   |
+LL | fn two_arg_same(_a: i32, _b: i32) {}
+   |    ^^^^^^^^^^^^ -------  -------
+help: remove the extra argument
+   |
+LL |   two_arg_same(1, 1);
+   |   ~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+  --> $DIR/extra_arguments.rs:30:3
+   |
+LL |   two_arg_diff(
+   |   ^^^^^^^^^^^^
+LL |     1,
+LL |     1,
+   |     - argument of type `&str` unexpected
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:4:4
+   |
+LL | fn two_arg_diff(_a: i32, _b: &str) {}
+   |    ^^^^^^^^^^^^ -------  --------
+help: remove the extra argument
+   |
+LL |   two_arg_diff(1, "");
+   |   ~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/argument-suggestions/invalid_arguments.rs b/src/test/ui/argument-suggestions/invalid_arguments.rs
new file mode 100644 (file)
index 0000000..53fbdd4
--- /dev/null
@@ -0,0 +1,43 @@
+// More nuanced test cases for invalid arguments #65853
+
+struct X {}
+
+fn one_arg(_a: i32) {}
+fn two_arg_same(_a: i32, _b: i32) {}
+fn two_arg_diff(_a: i32, _b: f32) {}
+fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
+fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
+
+fn main() {
+  // Providing an incorrect argument for a single parameter function
+  one_arg(1.0); //~ ERROR mismatched types
+
+  // Providing one or two invalid arguments to a two parameter function
+  two_arg_same(1, ""); //~ ERROR mismatched types
+  two_arg_same("", 1); //~ ERROR mismatched types
+  two_arg_same("", ""); //~ ERROR arguments to this function are incorrect
+  two_arg_diff(1, ""); //~ ERROR mismatched types
+  two_arg_diff("", 1.0); //~ ERROR mismatched types
+  two_arg_diff("", ""); //~ ERROR arguments to this function are incorrect
+
+  // Providing invalid arguments to a three parameter function
+  three_arg_diff(X{}, 1.0, ""); //~ ERROR mismatched types
+  three_arg_diff(1, X {}, ""); //~ ERROR mismatched types
+  three_arg_diff(1, 1.0, X {}); //~ ERROR mismatched types
+
+  three_arg_diff(X {}, X {}, ""); //~ ERROR arguments to this function are incorrect
+  three_arg_diff(X {}, 1.0, X {}); //~ ERROR arguments to this function are incorrect
+  three_arg_diff(1, X {}, X {}); //~ ERROR arguments to this function are incorrect
+
+  three_arg_diff(X {}, X {}, X {}); //~ ERROR arguments to this function are incorrect
+
+  three_arg_repeat(X {}, 1, ""); //~ ERROR mismatched types
+  three_arg_repeat(1, X {}, ""); //~ ERROR mismatched types
+  three_arg_repeat(1, 1, X {}); //~ ERROR mismatched types
+
+  three_arg_repeat(X {}, X {}, ""); //~ ERROR arguments to this function are incorrect
+  three_arg_repeat(X {}, 1, X {}); //~ ERROR arguments to this function are incorrect
+  three_arg_repeat(1, X {}, X{}); //~ ERROR arguments to this function are incorrect
+
+  three_arg_repeat(X {}, X {}, X {}); //~ ERROR arguments to this function are incorrect
+}
diff --git a/src/test/ui/argument-suggestions/invalid_arguments.stderr b/src/test/ui/argument-suggestions/invalid_arguments.stderr
new file mode 100644 (file)
index 0000000..33f27d4
--- /dev/null
@@ -0,0 +1,299 @@
+error[E0308]: mismatched types
+  --> $DIR/invalid_arguments.rs:13:11
+   |
+LL |   one_arg(1.0);
+   |   ------- ^^^ expected `i32`, found floating-point number
+   |   |
+   |   arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/invalid_arguments.rs:5:4
+   |
+LL | fn one_arg(_a: i32) {}
+   |    ^^^^^^^ -------
+
+error[E0308]: mismatched types
+  --> $DIR/invalid_arguments.rs:16:19
+   |
+LL |   two_arg_same(1, "");
+   |   ------------    ^^ expected `i32`, found `&str`
+   |   |
+   |   arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/invalid_arguments.rs:6:4
+   |
+LL | fn two_arg_same(_a: i32, _b: i32) {}
+   |    ^^^^^^^^^^^^ -------  -------
+
+error[E0308]: mismatched types
+  --> $DIR/invalid_arguments.rs:17:16
+   |
+LL |   two_arg_same("", 1);
+   |   ------------ ^^ expected `i32`, found `&str`
+   |   |
+   |   arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/invalid_arguments.rs:6:4
+   |
+LL | fn two_arg_same(_a: i32, _b: i32) {}
+   |    ^^^^^^^^^^^^ -------  -------
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/invalid_arguments.rs:18:3
+   |
+LL |   two_arg_same("", "");
+   |   ^^^^^^^^^^^^ --  -- expected `i32`, found `&str`
+   |                |
+   |                expected `i32`, found `&str`
+   |
+note: function defined here
+  --> $DIR/invalid_arguments.rs:6:4
+   |
+LL | fn two_arg_same(_a: i32, _b: i32) {}
+   |    ^^^^^^^^^^^^ -------  -------
+
+error[E0308]: mismatched types
+  --> $DIR/invalid_arguments.rs:19:19
+   |
+LL |   two_arg_diff(1, "");
+   |   ------------    ^^ expected `f32`, found `&str`
+   |   |
+   |   arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/invalid_arguments.rs:7:4
+   |
+LL | fn two_arg_diff(_a: i32, _b: f32) {}
+   |    ^^^^^^^^^^^^ -------  -------
+
+error[E0308]: mismatched types
+  --> $DIR/invalid_arguments.rs:20:16
+   |
+LL |   two_arg_diff("", 1.0);
+   |   ------------ ^^ expected `i32`, found `&str`
+   |   |
+   |   arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/invalid_arguments.rs:7:4
+   |
+LL | fn two_arg_diff(_a: i32, _b: f32) {}
+   |    ^^^^^^^^^^^^ -------  -------
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/invalid_arguments.rs:21:3
+   |
+LL |   two_arg_diff("", "");
+   |   ^^^^^^^^^^^^ --  -- expected `f32`, found `&str`
+   |                |
+   |                expected `i32`, found `&str`
+   |
+note: function defined here
+  --> $DIR/invalid_arguments.rs:7:4
+   |
+LL | fn two_arg_diff(_a: i32, _b: f32) {}
+   |    ^^^^^^^^^^^^ -------  -------
+
+error[E0308]: mismatched types
+  --> $DIR/invalid_arguments.rs:24:18
+   |
+LL |   three_arg_diff(X{}, 1.0, "");
+   |   -------------- ^^^ expected `i32`, found struct `X`
+   |   |
+   |   arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/invalid_arguments.rs:8:4
+   |
+LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^^^^^ -------  -------  --------
+
+error[E0308]: mismatched types
+  --> $DIR/invalid_arguments.rs:25:21
+   |
+LL |   three_arg_diff(1, X {}, "");
+   |   --------------    ^^^^ expected `f32`, found struct `X`
+   |   |
+   |   arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/invalid_arguments.rs:8:4
+   |
+LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^^^^^ -------  -------  --------
+
+error[E0308]: mismatched types
+  --> $DIR/invalid_arguments.rs:26:26
+   |
+LL |   three_arg_diff(1, 1.0, X {});
+   |   --------------         ^^^^ expected `&str`, found struct `X`
+   |   |
+   |   arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/invalid_arguments.rs:8:4
+   |
+LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^^^^^ -------  -------  --------
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/invalid_arguments.rs:28:3
+   |
+LL |   three_arg_diff(X {}, X {}, "");
+   |   ^^^^^^^^^^^^^^ ----  ---- expected `f32`, found struct `X`
+   |                  |
+   |                  expected `i32`, found struct `X`
+   |
+note: function defined here
+  --> $DIR/invalid_arguments.rs:8:4
+   |
+LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^^^^^ -------  -------  --------
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/invalid_arguments.rs:29:3
+   |
+LL |   three_arg_diff(X {}, 1.0, X {});
+   |   ^^^^^^^^^^^^^^ ----       ---- expected `&str`, found struct `X`
+   |                  |
+   |                  expected `i32`, found struct `X`
+   |
+note: function defined here
+  --> $DIR/invalid_arguments.rs:8:4
+   |
+LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^^^^^ -------  -------  --------
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/invalid_arguments.rs:30:3
+   |
+LL |   three_arg_diff(1, X {}, X {});
+   |   ^^^^^^^^^^^^^^    ----  ---- expected `&str`, found struct `X`
+   |                     |
+   |                     expected `f32`, found struct `X`
+   |
+note: function defined here
+  --> $DIR/invalid_arguments.rs:8:4
+   |
+LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^^^^^ -------  -------  --------
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/invalid_arguments.rs:32:3
+   |
+LL |   three_arg_diff(X {}, X {}, X {});
+   |   ^^^^^^^^^^^^^^ ----  ----  ---- expected `&str`, found struct `X`
+   |                  |     |
+   |                  |     expected `f32`, found struct `X`
+   |                  expected `i32`, found struct `X`
+   |
+note: function defined here
+  --> $DIR/invalid_arguments.rs:8:4
+   |
+LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^^^^^ -------  -------  --------
+
+error[E0308]: mismatched types
+  --> $DIR/invalid_arguments.rs:34:20
+   |
+LL |   three_arg_repeat(X {}, 1, "");
+   |   ---------------- ^^^^ expected `i32`, found struct `X`
+   |   |
+   |   arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/invalid_arguments.rs:9:4
+   |
+LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
+   |    ^^^^^^^^^^^^^^^^ -------  -------  --------
+
+error[E0308]: mismatched types
+  --> $DIR/invalid_arguments.rs:35:23
+   |
+LL |   three_arg_repeat(1, X {}, "");
+   |   ----------------    ^^^^ expected `i32`, found struct `X`
+   |   |
+   |   arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/invalid_arguments.rs:9:4
+   |
+LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
+   |    ^^^^^^^^^^^^^^^^ -------  -------  --------
+
+error[E0308]: mismatched types
+  --> $DIR/invalid_arguments.rs:36:26
+   |
+LL |   three_arg_repeat(1, 1, X {});
+   |   ----------------       ^^^^ expected `&str`, found struct `X`
+   |   |
+   |   arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/invalid_arguments.rs:9:4
+   |
+LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
+   |    ^^^^^^^^^^^^^^^^ -------  -------  --------
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/invalid_arguments.rs:38:3
+   |
+LL |   three_arg_repeat(X {}, X {}, "");
+   |   ^^^^^^^^^^^^^^^^ ----  ---- expected `i32`, found struct `X`
+   |                    |
+   |                    expected `i32`, found struct `X`
+   |
+note: function defined here
+  --> $DIR/invalid_arguments.rs:9:4
+   |
+LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
+   |    ^^^^^^^^^^^^^^^^ -------  -------  --------
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/invalid_arguments.rs:39:3
+   |
+LL |   three_arg_repeat(X {}, 1, X {});
+   |   ^^^^^^^^^^^^^^^^ ----     ---- expected `&str`, found struct `X`
+   |                    |
+   |                    expected `i32`, found struct `X`
+   |
+note: function defined here
+  --> $DIR/invalid_arguments.rs:9:4
+   |
+LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
+   |    ^^^^^^^^^^^^^^^^ -------  -------  --------
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/invalid_arguments.rs:40:3
+   |
+LL |   three_arg_repeat(1, X {}, X{});
+   |   ^^^^^^^^^^^^^^^^    ----  --- expected `&str`, found struct `X`
+   |                       |
+   |                       expected `i32`, found struct `X`
+   |
+note: function defined here
+  --> $DIR/invalid_arguments.rs:9:4
+   |
+LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
+   |    ^^^^^^^^^^^^^^^^ -------  -------  --------
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/invalid_arguments.rs:42:3
+   |
+LL |   three_arg_repeat(X {}, X {}, X {});
+   |   ^^^^^^^^^^^^^^^^ ----  ----  ---- expected `&str`, found struct `X`
+   |                    |     |
+   |                    |     expected `i32`, found struct `X`
+   |                    expected `i32`, found struct `X`
+   |
+note: function defined here
+  --> $DIR/invalid_arguments.rs:9:4
+   |
+LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
+   |    ^^^^^^^^^^^^^^^^ -------  -------  --------
+
+error: aborting due to 21 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/argument-suggestions/missing_arguments.rs b/src/test/ui/argument-suggestions/missing_arguments.rs
new file mode 100644 (file)
index 0000000..ae0dabf
--- /dev/null
@@ -0,0 +1,40 @@
+fn one_arg(_a: i32) {}
+fn two_same(_a: i32, _b: i32) {}
+fn two_diff(_a: i32, _b: f32) {}
+fn three_same(_a: i32, _b: i32, _c: i32) {}
+fn three_diff(_a: i32, _b: f32, _c: &str) {}
+fn four_repeated(_a: i32, _b: f32, _c: f32, _d: &str) {}
+fn complex(_a: i32, _b: f32, _c: i32, _d: f32, _e: &str) {}
+
+fn main() {
+  one_arg(); //~ ERROR this function takes
+  // The headers here show the types expected,
+  // with formatting to emphasize which arguments are missing
+  /*         i32     f32    */
+  two_same(               ); //~ ERROR this function takes
+  two_same(   1           ); //~ ERROR this function takes
+  two_diff(               ); //~ ERROR this function takes
+  two_diff(   1           ); //~ ERROR this function takes
+  two_diff(          1.0  ); //~ ERROR this function takes
+
+  /*           i32     i32     i32    */
+  three_same(                       ); //~ ERROR this function takes
+  three_same(   1                   ); //~ ERROR this function takes
+  three_same(   1,      1           ); //~ ERROR this function takes
+
+  /*           i32     f32     &str   */
+  three_diff(          1.0,     ""  ); //~ ERROR this function takes
+  three_diff(   1,              ""  ); //~ ERROR this function takes
+  three_diff(   1,     1.0          ); //~ ERROR this function takes
+  three_diff(                   ""  ); //~ ERROR this function takes
+  three_diff(          1.0          ); //~ ERROR this function takes
+  three_diff(   1                   ); //~ ERROR this function takes
+
+  /*              i32     f32     f32     &str   */
+  four_repeated(                               ); //~ ERROR this function takes
+  four_repeated(   1,                     ""   ); //~ ERROR this function takes
+
+  /*        i32   f32   i32   f32   &str   */
+  complex(                               ); //~ ERROR this function takes
+  complex(   1,                     ""   ); //~ ERROR this function takes
+}
diff --git a/src/test/ui/argument-suggestions/missing_arguments.stderr b/src/test/ui/argument-suggestions/missing_arguments.stderr
new file mode 100644 (file)
index 0000000..b4dadb1
--- /dev/null
@@ -0,0 +1,310 @@
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
+  --> $DIR/missing_arguments.rs:10:3
+   |
+LL |   one_arg();
+   |   ^^^^^^^-- an argument of type `i32` is missing
+   |
+note: function defined here
+  --> $DIR/missing_arguments.rs:1:4
+   |
+LL | fn one_arg(_a: i32) {}
+   |    ^^^^^^^ -------
+help: provide the argument
+   |
+LL |   one_arg({i32});
+   |   ~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 0 arguments were supplied
+  --> $DIR/missing_arguments.rs:14:3
+   |
+LL |   two_same(               );
+   |   ^^^^^^^^----------------- two arguments of type `i32` and `i32` are missing
+   |
+note: function defined here
+  --> $DIR/missing_arguments.rs:2:4
+   |
+LL | fn two_same(_a: i32, _b: i32) {}
+   |    ^^^^^^^^ -------  -------
+help: provide the arguments
+   |
+LL |   two_same({i32}, {i32});
+   |   ~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 1 argument was supplied
+  --> $DIR/missing_arguments.rs:15:3
+   |
+LL |   two_same(   1           );
+   |   ^^^^^^^^----------------- an argument of type `i32` is missing
+   |
+note: function defined here
+  --> $DIR/missing_arguments.rs:2:4
+   |
+LL | fn two_same(_a: i32, _b: i32) {}
+   |    ^^^^^^^^ -------  -------
+help: provide the argument
+   |
+LL |   two_same(1, {i32});
+   |   ~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 0 arguments were supplied
+  --> $DIR/missing_arguments.rs:16:3
+   |
+LL |   two_diff(               );
+   |   ^^^^^^^^----------------- two arguments of type `i32` and `f32` are missing
+   |
+note: function defined here
+  --> $DIR/missing_arguments.rs:3:4
+   |
+LL | fn two_diff(_a: i32, _b: f32) {}
+   |    ^^^^^^^^ -------  -------
+help: provide the arguments
+   |
+LL |   two_diff({i32}, {f32});
+   |   ~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 1 argument was supplied
+  --> $DIR/missing_arguments.rs:17:3
+   |
+LL |   two_diff(   1           );
+   |   ^^^^^^^^----------------- an argument of type `f32` is missing
+   |
+note: function defined here
+  --> $DIR/missing_arguments.rs:3:4
+   |
+LL | fn two_diff(_a: i32, _b: f32) {}
+   |    ^^^^^^^^ -------  -------
+help: provide the argument
+   |
+LL |   two_diff(1, {f32});
+   |   ~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 1 argument was supplied
+  --> $DIR/missing_arguments.rs:18:3
+   |
+LL |   two_diff(          1.0  );
+   |   ^^^^^^^^           --- an argument of type `i32` is missing
+   |
+note: function defined here
+  --> $DIR/missing_arguments.rs:3:4
+   |
+LL | fn two_diff(_a: i32, _b: f32) {}
+   |    ^^^^^^^^ -------  -------
+help: provide the argument
+   |
+LL |   two_diff({i32}, 1.0);
+   |   ~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 0 arguments were supplied
+  --> $DIR/missing_arguments.rs:21:3
+   |
+LL |   three_same(                       );
+   |   ^^^^^^^^^^------------------------- three arguments of type `i32`, `i32`, and `i32` are missing
+   |
+note: function defined here
+  --> $DIR/missing_arguments.rs:4:4
+   |
+LL | fn three_same(_a: i32, _b: i32, _c: i32) {}
+   |    ^^^^^^^^^^ -------  -------  -------
+help: provide the arguments
+   |
+LL |   three_same({i32}, {i32}, {i32});
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 1 argument was supplied
+  --> $DIR/missing_arguments.rs:22:3
+   |
+LL |   three_same(   1                   );
+   |   ^^^^^^^^^^------------------------- two arguments of type `i32` and `i32` are missing
+   |
+note: function defined here
+  --> $DIR/missing_arguments.rs:4:4
+   |
+LL | fn three_same(_a: i32, _b: i32, _c: i32) {}
+   |    ^^^^^^^^^^ -------  -------  -------
+help: provide the arguments
+   |
+LL |   three_same(1, {i32}, {i32});
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 2 arguments were supplied
+  --> $DIR/missing_arguments.rs:23:3
+   |
+LL |   three_same(   1,      1           );
+   |   ^^^^^^^^^^------------------------- an argument of type `i32` is missing
+   |
+note: function defined here
+  --> $DIR/missing_arguments.rs:4:4
+   |
+LL | fn three_same(_a: i32, _b: i32, _c: i32) {}
+   |    ^^^^^^^^^^ -------  -------  -------
+help: provide the argument
+   |
+LL |   three_same(1, 1, {i32});
+   |   ~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 2 arguments were supplied
+  --> $DIR/missing_arguments.rs:26:3
+   |
+LL |   three_diff(          1.0,     ""  );
+   |   ^^^^^^^^^^           --- an argument of type `i32` is missing
+   |
+note: function defined here
+  --> $DIR/missing_arguments.rs:5:4
+   |
+LL | fn three_diff(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^ -------  -------  --------
+help: provide the argument
+   |
+LL |   three_diff({i32}, 1.0, "");
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 2 arguments were supplied
+  --> $DIR/missing_arguments.rs:27:3
+   |
+LL |   three_diff(   1,              ""  );
+   |   ^^^^^^^^^^                    -- an argument of type `f32` is missing
+   |
+note: function defined here
+  --> $DIR/missing_arguments.rs:5:4
+   |
+LL | fn three_diff(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^ -------  -------  --------
+help: provide the argument
+   |
+LL |   three_diff(1, {f32}, "");
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 2 arguments were supplied
+  --> $DIR/missing_arguments.rs:28:3
+   |
+LL |   three_diff(   1,     1.0          );
+   |   ^^^^^^^^^^------------------------- an argument of type `&str` is missing
+   |
+note: function defined here
+  --> $DIR/missing_arguments.rs:5:4
+   |
+LL | fn three_diff(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^ -------  -------  --------
+help: provide the argument
+   |
+LL |   three_diff(1, 1.0, {&str});
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 1 argument was supplied
+  --> $DIR/missing_arguments.rs:29:3
+   |
+LL |   three_diff(                   ""  );
+   |   ^^^^^^^^^^------------------------- two arguments of type `i32` and `f32` are missing
+   |
+note: function defined here
+  --> $DIR/missing_arguments.rs:5:4
+   |
+LL | fn three_diff(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^ -------  -------  --------
+help: provide the arguments
+   |
+LL |   three_diff({i32}, {f32}, "");
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 1 argument was supplied
+  --> $DIR/missing_arguments.rs:30:3
+   |
+LL |   three_diff(          1.0          );
+   |   ^^^^^^^^^^-------------------------
+   |             |          |
+   |             |          an argument of type `i32` is missing
+   |             an argument of type `&str` is missing
+   |
+note: function defined here
+  --> $DIR/missing_arguments.rs:5:4
+   |
+LL | fn three_diff(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^ -------  -------  --------
+help: provide the arguments
+   |
+LL |   three_diff({i32}, 1.0, {&str});
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 1 argument was supplied
+  --> $DIR/missing_arguments.rs:31:3
+   |
+LL |   three_diff(   1                   );
+   |   ^^^^^^^^^^------------------------- two arguments of type `f32` and `&str` are missing
+   |
+note: function defined here
+  --> $DIR/missing_arguments.rs:5:4
+   |
+LL | fn three_diff(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^ -------  -------  --------
+help: provide the arguments
+   |
+LL |   three_diff(1, {f32}, {&str});
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 4 arguments but 0 arguments were supplied
+  --> $DIR/missing_arguments.rs:34:3
+   |
+LL |   four_repeated(                               );
+   |   ^^^^^^^^^^^^^--------------------------------- multiple arguments are missing
+   |
+note: function defined here
+  --> $DIR/missing_arguments.rs:6:4
+   |
+LL | fn four_repeated(_a: i32, _b: f32, _c: f32, _d: &str) {}
+   |    ^^^^^^^^^^^^^ -------  -------  -------  --------
+help: provide the arguments
+   |
+LL |   four_repeated({i32}, {f32}, {f32}, {&str});
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 4 arguments but 2 arguments were supplied
+  --> $DIR/missing_arguments.rs:35:3
+   |
+LL |   four_repeated(   1,                     ""   );
+   |   ^^^^^^^^^^^^^--------------------------------- two arguments of type `f32` and `f32` are missing
+   |
+note: function defined here
+  --> $DIR/missing_arguments.rs:6:4
+   |
+LL | fn four_repeated(_a: i32, _b: f32, _c: f32, _d: &str) {}
+   |    ^^^^^^^^^^^^^ -------  -------  -------  --------
+help: provide the arguments
+   |
+LL |   four_repeated(1, {f32}, {f32}, "");
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 5 arguments but 0 arguments were supplied
+  --> $DIR/missing_arguments.rs:38:3
+   |
+LL |   complex(                               );
+   |   ^^^^^^^--------------------------------- multiple arguments are missing
+   |
+note: function defined here
+  --> $DIR/missing_arguments.rs:7:4
+   |
+LL | fn complex(_a: i32, _b: f32, _c: i32, _d: f32, _e: &str) {}
+   |    ^^^^^^^ -------  -------  -------  -------  --------
+help: provide the arguments
+   |
+LL |   complex({i32}, {f32}, {i32}, {f32}, {&str});
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 5 arguments but 2 arguments were supplied
+  --> $DIR/missing_arguments.rs:39:3
+   |
+LL |   complex(   1,                     ""   );
+   |   ^^^^^^^--------------------------------- three arguments of type `f32`, `i32`, and `i32` are missing
+   |
+note: function defined here
+  --> $DIR/missing_arguments.rs:7:4
+   |
+LL | fn complex(_a: i32, _b: f32, _c: i32, _d: f32, _e: &str) {}
+   |    ^^^^^^^ -------  -------  -------  -------  --------
+help: provide the arguments
+   |
+LL |   complex(1, {f32}, {i32}, {f32}, "");
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 19 previous errors
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/argument-suggestions/mixed_cases.rs b/src/test/ui/argument-suggestions/mixed_cases.rs
new file mode 100644 (file)
index 0000000..7367848
--- /dev/null
@@ -0,0 +1,24 @@
+// Cases where multiple argument suggestions are mixed
+
+struct X {}
+
+fn two_args(_a: i32, _b: f32) {}
+fn three_args(_a: i32, _b: f32, _c: &str) {}
+
+fn main() {
+  // Extra + Invalid
+  two_args(1, "", X {}); //~ ERROR this function takes
+  three_args(1, "", X {}, ""); //~ ERROR this function takes
+
+  // Missing and Invalid
+  three_args(1, X {}); //~ ERROR this function takes
+
+  // Missing and Extra
+  three_args(1, "", X {}); //~ ERROR arguments to this function are incorrect
+
+  // Swapped and Invalid
+  three_args("", X {}, 1); //~ ERROR arguments to this function are incorrect
+
+  // Swapped and missing
+  three_args("", 1); //~ ERROR this function takes
+}
diff --git a/src/test/ui/argument-suggestions/mixed_cases.stderr b/src/test/ui/argument-suggestions/mixed_cases.stderr
new file mode 100644 (file)
index 0000000..61da02f
--- /dev/null
@@ -0,0 +1,117 @@
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+  --> $DIR/mixed_cases.rs:10:3
+   |
+LL |   two_args(1, "", X {});
+   |   ^^^^^^^^    --  ---- argument unexpected
+   |               |
+   |               expected `f32`, found `&str`
+   |
+note: function defined here
+  --> $DIR/mixed_cases.rs:5:4
+   |
+LL | fn two_args(_a: i32, _b: f32) {}
+   |    ^^^^^^^^ -------  -------
+help: remove the extra argument
+   |
+LL |   two_args(1, {f32});
+   |   ~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 4 arguments were supplied
+  --> $DIR/mixed_cases.rs:11:3
+   |
+LL |   three_args(1, "", X {}, "");
+   |   ^^^^^^^^^^    --  ----  -- argument unexpected
+   |                 |   |
+   |                 |   argument of type `&str` unexpected
+   |                 an argument of type `f32` is missing
+   |
+note: function defined here
+  --> $DIR/mixed_cases.rs:6:4
+   |
+LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^ -------  -------  --------
+help: did you mean
+   |
+LL |   three_args(1, {f32}, "");
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 2 arguments were supplied
+  --> $DIR/mixed_cases.rs:14:3
+   |
+LL |   three_args(1, X {});
+   |   ^^^^^^^^^^---------
+   |             |   |
+   |             |   expected `f32`, found struct `X`
+   |             an argument of type `&str` is missing
+   |
+note: function defined here
+  --> $DIR/mixed_cases.rs:6:4
+   |
+LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^ -------  -------  --------
+help: provide the argument
+   |
+LL |   three_args(1, {f32}, {&str});
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/mixed_cases.rs:17:3
+   |
+LL |   three_args(1, "", X {});
+   |   ^^^^^^^^^^    --  ---- argument of type `&str` unexpected
+   |                 |
+   |                 an argument of type `f32` is missing
+   |
+note: function defined here
+  --> $DIR/mixed_cases.rs:6:4
+   |
+LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^ -------  -------  --------
+help: did you mean
+   |
+LL |   three_args(1, {f32}, "");
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/mixed_cases.rs:20:3
+   |
+LL |   three_args("", X {}, 1);
+   |   ^^^^^^^^^^ --  ----  - expected `&str`,found `{integer}`
+   |              |   |
+   |              |   expected `f32`, found struct `X`
+   |              expected `i32`,found `&'static str`
+   |
+note: function defined here
+  --> $DIR/mixed_cases.rs:6:4
+   |
+LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^ -------  -------  --------
+help: swap these arguments
+   |
+LL |   three_args(1, {f32}, "");
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 2 arguments were supplied
+  --> $DIR/mixed_cases.rs:23:3
+   |
+LL |   three_args("", 1);
+   |   ^^^^^^^^^^ --  -
+   |              |   |
+   |              |   an argument of type `f32` is missing
+   |              |   expected `&str`,found `{integer}`
+   |              expected `i32`,found `&'static str`
+   |
+note: function defined here
+  --> $DIR/mixed_cases.rs:6:4
+   |
+LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^ -------  -------  --------
+help: did you mean
+   |
+LL |   three_args(1, {f32}, "");
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0061, E0308.
+For more information about an error, try `rustc --explain E0061`.
diff --git a/src/test/ui/argument-suggestions/permuted_arguments.rs b/src/test/ui/argument-suggestions/permuted_arguments.rs
new file mode 100644 (file)
index 0000000..f512fde
--- /dev/null
@@ -0,0 +1,13 @@
+// More complicated permutations
+struct X {}
+struct Y {}
+
+fn three_args(_a: i32, _b: f32, _c: &str) {}
+fn many_args(_a: i32, _b: f32, _c: &str, _d: X, _e: Y) {}
+
+fn main() {
+  // b, c, a
+  three_args(1.0, "", 1); //~ ERROR arguments to this function are incorrect
+  // d, e, b, a, c
+  many_args(X {}, Y {}, 1, 1.0, ""); //~ ERROR arguments to this function are incorrect
+}
diff --git a/src/test/ui/argument-suggestions/permuted_arguments.stderr b/src/test/ui/argument-suggestions/permuted_arguments.stderr
new file mode 100644 (file)
index 0000000..52890f4
--- /dev/null
@@ -0,0 +1,43 @@
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/permuted_arguments.rs:10:3
+   |
+LL |   three_args(1.0, "", 1);
+   |   ^^^^^^^^^^ ---  --  - expected `&str`,found `{integer}`
+   |              |    |
+   |              |    expected `f32`,found `&'static str`
+   |              expected `i32`,found `{float}`
+   |
+note: function defined here
+  --> $DIR/permuted_arguments.rs:5:4
+   |
+LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^ -------  -------  --------
+help: reorder these arguments
+   |
+LL |   three_args(1, 1.0, "");
+   |   ~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/permuted_arguments.rs:12:3
+   |
+LL |   many_args(X {}, Y {}, 1, 1.0, "");
+   |   ^^^^^^^^^ ----  ----  -  ---  -- expected `Y`,found `&'static str`
+   |             |     |     |  |
+   |             |     |     |  expected `X`,found `{float}`
+   |             |     |     expected `&str`,found `{integer}`
+   |             |     expected `f32`,found `Y`
+   |             expected `i32`,found `X`
+   |
+note: function defined here
+  --> $DIR/permuted_arguments.rs:6:4
+   |
+LL | fn many_args(_a: i32, _b: f32, _c: &str, _d: X, _e: Y) {}
+   |    ^^^^^^^^^ -------  -------  --------  -----  -----
+help: reorder these arguments
+   |
+LL |   many_args(1, 1.0, "", X {}, Y {});
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/argument-suggestions/swapped_arguments.rs b/src/test/ui/argument-suggestions/swapped_arguments.rs
new file mode 100644 (file)
index 0000000..a21de61
--- /dev/null
@@ -0,0 +1,14 @@
+struct X {}
+
+fn two_args(_a: i32, _b: f32) {}
+fn three_args(_a: i32, _b: f32, _c: &str) {}
+fn four_args(_a: i32, _b: f32, _c: &str, _d: X) {}
+
+fn main() {
+  two_args(1.0, 1); //~ ERROR arguments to this function are incorrect
+  three_args(1.0,   1,  ""); //~ ERROR arguments to this function are incorrect
+  three_args(  1,  "", 1.0); //~ ERROR arguments to this function are incorrect
+  three_args( "", 1.0,   1); //~ ERROR arguments to this function are incorrect
+
+  four_args(1.0, 1, X {}, ""); //~ ERROR arguments to this function are incorrect
+}
diff --git a/src/test/ui/argument-suggestions/swapped_arguments.stderr b/src/test/ui/argument-suggestions/swapped_arguments.stderr
new file mode 100644 (file)
index 0000000..672f0d5
--- /dev/null
@@ -0,0 +1,95 @@
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/swapped_arguments.rs:8:3
+   |
+LL |   two_args(1.0, 1);
+   |   ^^^^^^^^ ---  - expected `f32`,found `{integer}`
+   |            |
+   |            expected `i32`,found `{float}`
+   |
+note: function defined here
+  --> $DIR/swapped_arguments.rs:3:4
+   |
+LL | fn two_args(_a: i32, _b: f32) {}
+   |    ^^^^^^^^ -------  -------
+help: swap these arguments
+   |
+LL |   two_args(1, 1.0);
+   |   ~~~~~~~~~~~~~~~~
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/swapped_arguments.rs:9:3
+   |
+LL |   three_args(1.0,   1,  "");
+   |   ^^^^^^^^^^ ---    - expected `f32`,found `{integer}`
+   |              |
+   |              expected `i32`,found `{float}`
+   |
+note: function defined here
+  --> $DIR/swapped_arguments.rs:4:4
+   |
+LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^ -------  -------  --------
+help: swap these arguments
+   |
+LL |   three_args(1, 1.0, "");
+   |   ~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/swapped_arguments.rs:10:3
+   |
+LL |   three_args(  1,  "", 1.0);
+   |   ^^^^^^^^^^       --  --- expected `&str`,found `{float}`
+   |                    |
+   |                    expected `f32`,found `&'static str`
+   |
+note: function defined here
+  --> $DIR/swapped_arguments.rs:4:4
+   |
+LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^ -------  -------  --------
+help: swap these arguments
+   |
+LL |   three_args(1, 1.0, "");
+   |   ~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/swapped_arguments.rs:11:3
+   |
+LL |   three_args( "", 1.0,   1);
+   |   ^^^^^^^^^^  --         - expected `&str`,found `{integer}`
+   |               |
+   |               expected `i32`,found `&'static str`
+   |
+note: function defined here
+  --> $DIR/swapped_arguments.rs:4:4
+   |
+LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
+   |    ^^^^^^^^^^ -------  -------  --------
+help: swap these arguments
+   |
+LL |   three_args(1, 1.0, "");
+   |   ~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/swapped_arguments.rs:13:3
+   |
+LL |   four_args(1.0, 1, X {}, "");
+   |   ^^^^^^^^^ ---  -  ----  -- expected `X`,found `&'static str`
+   |             |    |  |
+   |             |    |  expected `&str`,found `X`
+   |             |    expected `f32`,found `{integer}`
+   |             expected `i32`,found `{float}`
+   |
+note: function defined here
+  --> $DIR/swapped_arguments.rs:5:4
+   |
+LL | fn four_args(_a: i32, _b: f32, _c: &str, _d: X) {}
+   |    ^^^^^^^^^ -------  -------  --------  -----
+help: did you mean
+   |
+LL |   four_args(1, 1.0, "", X {});
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index 59d6b28d0fd99bc160f4454af93f01876b70f118..cbc93cd3f7530c6bcbb93d8a6b6dc4acc956c493 100644 (file)
@@ -29,7 +29,7 @@ fn main() {
         asm!("{}", in(reg) foo => bar);
         //~^ ERROR expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>`
         asm!("{}", sym foo + bar);
-        //~^ ERROR argument to `sym` must be a path expression
+        //~^ ERROR expected a path for argument to `sym`
         asm!("", options(foo));
         //~^ ERROR expected one of
         asm!("", options(nomem foo));
index 3f705ba5b64c2995eeddfc8d1c10da25f94f9b78..f2013046cda4207043b3e2f6fd5146a170d39528 100644 (file)
@@ -58,7 +58,7 @@ error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>`
 LL |         asm!("{}", in(reg) foo => bar);
    |                                ^^ expected one of 7 possible tokens
 
-error: argument to `sym` must be a path expression
+error: expected a path for argument to `sym`
   --> $DIR/parse-error.rs:31:24
    |
 LL |         asm!("{}", sym foo + bar);
@@ -350,17 +350,17 @@ 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 `""`
+error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `""`
   --> $DIR/parse-error.rs:126:28
    |
 LL | global_asm!("", options(), "");
-   |                            ^^ expected one of `clobber_abi`, `const`, or `options`
+   |                            ^^ expected one of `clobber_abi`, `const`, `options`, or `sym`
 
-error: expected one of `clobber_abi`, `const`, or `options`, found `"{}"`
+error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `"{}"`
   --> $DIR/parse-error.rs:128:30
    |
 LL | global_asm!("{}", const FOO, "{}", const FOO);
-   |                              ^^^^ expected one of `clobber_abi`, `const`, or `options`
+   |                              ^^^^ expected one of `clobber_abi`, `const`, `options`, or `sym`
 
 error: asm template must be a string literal
   --> $DIR/parse-error.rs:130:13
index 1b91f5d0678b4102eacadce733181d61a52909c2..9e53a2e0c5230cfd768b6506f14faf97317de89a 100644 (file)
@@ -2,7 +2,7 @@
 
 #![feature(repr_simd, never_type, asm_sym)]
 
-use std::arch::asm;
+use std::arch::{asm, global_asm};
 
 #[repr(simd)]
 #[derive(Clone, Copy)]
@@ -39,9 +39,7 @@ fn main() {
         asm!("{}", sym S);
         asm!("{}", sym main);
         asm!("{}", sym C);
-        //~^ ERROR asm `sym` operand must point to a fn or static
-        asm!("{}", sym x);
-        //~^ ERROR asm `sym` operand must point to a fn or static
+        //~^ ERROR invalid `sym` operand
 
         // Register operands must be Copy
 
@@ -84,3 +82,12 @@ fn main() {
         asm!("{}", in(reg) u);
     }
 }
+
+// Sym operands must point to a function or static
+
+const C: i32 = 0;
+static S: i32 = 0;
+global_asm!("{}", sym S);
+global_asm!("{}", sym main);
+global_asm!("{}", sym C);
+//~^ ERROR invalid `sym` operand
index beb301c7c7417675c4360a2b411b8fbbc154d0b7..6047bed6e7802bb36b8f8fda8e2ad87caeecf347 100644 (file)
@@ -1,13 +1,13 @@
 error: arguments for inline assembly must be copyable
-  --> $DIR/type-check-2.rs:48:31
+  --> $DIR/type-check-2.rs:46:31
    |
 LL |         asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `SimdNonCopy` does not implement the Copy trait
 
-error: cannot use value of type `[closure@$DIR/type-check-2.rs:60:28: 60:38]` for inline assembly
-  --> $DIR/type-check-2.rs:60:28
+error: cannot use value of type `[closure@$DIR/type-check-2.rs:58:28: 58:38]` for inline assembly
+  --> $DIR/type-check-2.rs:58:28
    |
 LL |         asm!("{}", in(reg) |x: i32| x);
    |                            ^^^^^^^^^^
@@ -15,7 +15,7 @@ LL |         asm!("{}", in(reg) |x: i32| x);
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `Vec<i32>` for inline assembly
-  --> $DIR/type-check-2.rs:62:28
+  --> $DIR/type-check-2.rs:60:28
    |
 LL |         asm!("{}", in(reg) vec![0]);
    |                            ^^^^^^^
@@ -24,7 +24,7 @@ LL |         asm!("{}", in(reg) vec![0]);
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: cannot use value of type `(i32, i32, i32)` for inline assembly
-  --> $DIR/type-check-2.rs:64:28
+  --> $DIR/type-check-2.rs:62:28
    |
 LL |         asm!("{}", in(reg) (1, 2, 3));
    |                            ^^^^^^^^^
@@ -32,7 +32,7 @@ LL |         asm!("{}", in(reg) (1, 2, 3));
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `[i32; 3]` for inline assembly
-  --> $DIR/type-check-2.rs:66:28
+  --> $DIR/type-check-2.rs:64:28
    |
 LL |         asm!("{}", in(reg) [1, 2, 3]);
    |                            ^^^^^^^^^
@@ -40,7 +40,7 @@ LL |         asm!("{}", in(reg) [1, 2, 3]);
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `fn() {main}` for inline assembly
-  --> $DIR/type-check-2.rs:74:31
+  --> $DIR/type-check-2.rs:72:31
    |
 LL |         asm!("{}", inout(reg) f);
    |                               ^
@@ -48,24 +48,28 @@ LL |         asm!("{}", inout(reg) f);
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `&mut i32` for inline assembly
-  --> $DIR/type-check-2.rs:77:31
+  --> $DIR/type-check-2.rs:75:31
    |
 LL |         asm!("{}", inout(reg) r);
    |                               ^
    |
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
-error: asm `sym` operand must point to a fn or static
-  --> $DIR/type-check-2.rs:41:24
+error: invalid `sym` operand
+  --> $DIR/type-check-2.rs:41:20
    |
 LL |         asm!("{}", sym C);
-   |                        ^
+   |                    ^^^^^ is an `i32`
+   |
+   = help: `sym` operands must refer to either a function or a static
 
-error: asm `sym` operand must point to a fn or static
-  --> $DIR/type-check-2.rs:43:24
+error: invalid `sym` operand
+  --> $DIR/type-check-2.rs:92:19
+   |
+LL | global_asm!("{}", sym C);
+   |                   ^^^^^ is an `i32`
    |
-LL |         asm!("{}", sym x);
-   |                        ^
+   = help: `sym` operands must refer to either a function or a static
 
 error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/type-check-2.rs:19:28
index 695fd27efd4e3216a0f9d2da30eafc1c1441bd52..9f0121e11b4470a001e1f2f7e1ae3a1aa07aefaa 100644 (file)
@@ -3,7 +3,7 @@
 // ignore-spirv
 // ignore-wasm32
 
-#![feature(asm_const)]
+#![feature(asm_const, asm_sym)]
 
 use std::arch::{asm, global_asm};
 
@@ -44,6 +44,8 @@ const fn const_bar<T>(x: T) -> T {
         asm!("{}", const const_bar(0));
         asm!("{}", const const_bar(x));
         //~^ ERROR attempt to use a non-constant value in a constant
+        asm!("{}", sym x);
+        //~^ ERROR invalid `sym` operand
 
         // Const operands must be integers and must be constants.
 
@@ -59,6 +61,11 @@ const fn const_bar<T>(x: T) -> T {
     }
 }
 
+unsafe fn generic<T>() {
+    asm!("{}", sym generic::<T>);
+    //~^ generic parameters may not be used in const operations
+}
+
 // Const operands must be integers and must be constants.
 
 global_asm!("{}", const 0);
index d774c78ca9a721974a6e9c65da25f2979f156b9f..7dba69fb7459276987dc7ac45bf996507fb44ab9 100644 (file)
@@ -25,14 +25,31 @@ LL |         let x = 0;
 LL |         asm!("{}", const const_bar(x));
    |                                    ^ non-constant value
 
+error: invalid `sym` operand
+  --> $DIR/type-check-1.rs:47:24
+   |
+LL |         asm!("{}", sym x);
+   |                        ^ is a local variable
+   |
+   = help: `sym` operands must refer to either a function or a static
+
+error: generic parameters may not be used in const operations
+  --> $DIR/type-check-1.rs:65:30
+   |
+LL |     asm!("{}", sym generic::<T>);
+   |                              ^ cannot perform const operation using `T`
+   |
+   = note: type parameters may not be used in const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:53:26
+  --> $DIR/type-check-1.rs:55:26
    |
 LL |         asm!("{}", const 0f32);
    |                          ^^^^ expected integer, found `f32`
 
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:55:26
+  --> $DIR/type-check-1.rs:57:26
    |
 LL |         asm!("{}", const 0 as *mut u8);
    |                          ^^^^^^^^^^^^ expected integer, found *-ptr
@@ -41,7 +58,7 @@ LL |         asm!("{}", const 0 as *mut u8);
            found raw pointer `*mut u8`
 
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:57:26
+  --> $DIR/type-check-1.rs:59:26
    |
 LL |         asm!("{}", const &0);
    |                          ^^ expected integer, found `&{integer}`
@@ -92,13 +109,13 @@ LL |         asm!("{}", inout(reg) v[..]);
    = note: all inline asm arguments must have a statically known size
 
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:67:25
+  --> $DIR/type-check-1.rs:74:25
    |
 LL | global_asm!("{}", const 0f32);
    |                         ^^^^ expected integer, found `f32`
 
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:69:25
+  --> $DIR/type-check-1.rs:76:25
    |
 LL | global_asm!("{}", const 0 as *mut u8);
    |                         ^^^^^^^^^^^^ expected integer, found *-ptr
@@ -106,7 +123,7 @@ LL | global_asm!("{}", const 0 as *mut u8);
    = note:     expected type `{integer}`
            found raw pointer `*mut u8`
 
-error: aborting due to 13 previous errors
+error: aborting due to 15 previous errors
 
 Some errors have detailed explanations: E0277, E0308, E0435.
 For more information about an error, try `rustc --explain E0277`.
index 4c4ce8b5e9e493ecd6f22fcc9bd70a9d036b4038..272372ebedc1d01c5f716badcc5c7a6b2c08dffd 100644 (file)
@@ -29,13 +29,13 @@ fn main() {
         //~^ ERROR invalid register `rsp`: the stack pointer cannot be used as an operand
         asm!("", in("ip") foo);
         //~^ ERROR invalid register `ip`: the instruction pointer cannot be used as an operand
-        asm!("", in("k0") foo);
-        //~^ ERROR invalid register `k0`: the k0 AVX mask register cannot be used as an operand
 
         asm!("", in("st(2)") foo);
         //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
         asm!("", in("mm0") foo);
         //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output
+        asm!("", in("k0") foo);
+        //~^ ERROR register class `kreg0` can only be used as a clobber, not as an input or output
         asm!("", out("st(2)") _);
         asm!("", out("mm0") _);
         asm!("{}", in(x87_reg) foo);
index f8b024e1acd62c3b7d8891d4cc80ce558a312f63..84b8b5ec2850b77d81505c0b3754e3a20d4f2777 100644 (file)
@@ -64,24 +64,24 @@ error: invalid register `ip`: the instruction pointer cannot be used as an opera
 LL |         asm!("", in("ip") foo);
    |                  ^^^^^^^^^^^^
 
-error: invalid register `k0`: the k0 AVX mask register cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:32:18
-   |
-LL |         asm!("", in("k0") foo);
-   |                  ^^^^^^^^^^^^
-
 error: register class `x87_reg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:35:18
+  --> $DIR/bad-reg.rs:33:18
    |
 LL |         asm!("", in("st(2)") foo);
    |                  ^^^^^^^^^^^^^^^
 
 error: register class `mmx_reg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:37:18
+  --> $DIR/bad-reg.rs:35:18
    |
 LL |         asm!("", in("mm0") foo);
    |                  ^^^^^^^^^^^^^
 
+error: register class `kreg0` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:37:18
+   |
+LL |         asm!("", in("k0") foo);
+   |                  ^^^^^^^^^^^^
+
 error: register class `x87_reg` can only be used as a clobber, not as an input or output
   --> $DIR/bad-reg.rs:41:20
    |
index f0629f9f51cdf33d0d877b64c1f5251775621b10..9aeb6b2853fba8397aa322176a72af922ab1605f 100644 (file)
@@ -29,7 +29,7 @@ fn main() {
         asm!("{}", in(reg) foo => bar);
         //~^ ERROR expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>`
         asm!("{}", sym foo + bar);
-        //~^ ERROR argument to `sym` must be a path expression
+        //~^ ERROR expected a path for argument to `sym`
         asm!("", options(foo));
         //~^ ERROR expected one of
         asm!("", options(nomem foo));
index 194cd66a66e96325ae9e63e4201d96fe616f56ec..1fd317a96a8a6c09f5ab3c44e959f0ba4a497ba6 100644 (file)
@@ -58,7 +58,7 @@ error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>`
 LL |         asm!("{}", in(reg) foo => bar);
    |                                ^^ expected one of 7 possible tokens
 
-error: argument to `sym` must be a path expression
+error: expected a path for argument to `sym`
   --> $DIR/parse-error.rs:31:24
    |
 LL |         asm!("{}", sym foo + bar);
@@ -362,17 +362,17 @@ 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 `""`
+error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `""`
   --> $DIR/parse-error.rs:130:28
    |
 LL | global_asm!("", options(), "");
-   |                            ^^ expected one of `clobber_abi`, `const`, or `options`
+   |                            ^^ expected one of `clobber_abi`, `const`, `options`, or `sym`
 
-error: expected one of `clobber_abi`, `const`, or `options`, found `"{}"`
+error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `"{}"`
   --> $DIR/parse-error.rs:132:30
    |
 LL | global_asm!("{}", const FOO, "{}", const FOO);
-   |                              ^^^^ expected one of `clobber_abi`, `const`, or `options`
+   |                              ^^^^ expected one of `clobber_abi`, `const`, `options`, or `sym`
 
 error: asm template must be a string literal
   --> $DIR/parse-error.rs:134:13
index f95aebb78b5f8a425998472ffc6ac506f0e5feb2..eb87ea91085f0ca5ab6f695f077622480f625d98 100644 (file)
@@ -2,7 +2,7 @@
 
 #![feature(repr_simd, never_type, asm_sym)]
 
-use std::arch::asm;
+use std::arch::{asm, global_asm};
 
 #[repr(simd)]
 struct SimdNonCopy(f32, f32, f32, f32);
@@ -35,9 +35,7 @@ fn main() {
         asm!("{}", sym S);
         asm!("{}", sym main);
         asm!("{}", sym C);
-        //~^ ERROR asm `sym` operand must point to a fn or static
-        asm!("{}", sym x);
-        //~^ ERROR asm `sym` operand must point to a fn or static
+        //~^ ERROR invalid `sym` operand
 
         // Register operands must be Copy
 
@@ -80,3 +78,12 @@ fn main() {
         asm!("{}", in(reg) u);
     }
 }
+
+// Sym operands must point to a function or static
+
+const C: i32 = 0;
+static S: i32 = 0;
+global_asm!("{}", sym S);
+global_asm!("{}", sym main);
+global_asm!("{}", sym C);
+//~^ ERROR invalid `sym` operand
index cec750fdf9a55c00cf004f5a3f6326660239c781..cb3960acdf9d317e0e0661e79c5d52463bd9c475 100644 (file)
@@ -1,13 +1,13 @@
 error: arguments for inline assembly must be copyable
-  --> $DIR/type-check-2.rs:44:32
+  --> $DIR/type-check-2.rs:42:32
    |
 LL |         asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `SimdNonCopy` does not implement the Copy trait
 
-error: cannot use value of type `[closure@$DIR/type-check-2.rs:56:28: 56:38]` for inline assembly
-  --> $DIR/type-check-2.rs:56:28
+error: cannot use value of type `[closure@$DIR/type-check-2.rs:54:28: 54:38]` for inline assembly
+  --> $DIR/type-check-2.rs:54:28
    |
 LL |         asm!("{}", in(reg) |x: i32| x);
    |                            ^^^^^^^^^^
@@ -15,7 +15,7 @@ LL |         asm!("{}", in(reg) |x: i32| x);
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `Vec<i32>` for inline assembly
-  --> $DIR/type-check-2.rs:58:28
+  --> $DIR/type-check-2.rs:56:28
    |
 LL |         asm!("{}", in(reg) vec![0]);
    |                            ^^^^^^^
@@ -24,7 +24,7 @@ LL |         asm!("{}", in(reg) vec![0]);
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: cannot use value of type `(i32, i32, i32)` for inline assembly
-  --> $DIR/type-check-2.rs:60:28
+  --> $DIR/type-check-2.rs:58:28
    |
 LL |         asm!("{}", in(reg) (1, 2, 3));
    |                            ^^^^^^^^^
@@ -32,7 +32,7 @@ LL |         asm!("{}", in(reg) (1, 2, 3));
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `[i32; 3]` for inline assembly
-  --> $DIR/type-check-2.rs:62:28
+  --> $DIR/type-check-2.rs:60:28
    |
 LL |         asm!("{}", in(reg) [1, 2, 3]);
    |                            ^^^^^^^^^
@@ -40,7 +40,7 @@ LL |         asm!("{}", in(reg) [1, 2, 3]);
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `fn() {main}` for inline assembly
-  --> $DIR/type-check-2.rs:70:31
+  --> $DIR/type-check-2.rs:68:31
    |
 LL |         asm!("{}", inout(reg) f);
    |                               ^
@@ -48,24 +48,28 @@ LL |         asm!("{}", inout(reg) f);
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `&mut i32` for inline assembly
-  --> $DIR/type-check-2.rs:73:31
+  --> $DIR/type-check-2.rs:71:31
    |
 LL |         asm!("{}", inout(reg) r);
    |                               ^
    |
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
-error: asm `sym` operand must point to a fn or static
-  --> $DIR/type-check-2.rs:37:24
+error: invalid `sym` operand
+  --> $DIR/type-check-2.rs:37:20
    |
 LL |         asm!("{}", sym C);
-   |                        ^
+   |                    ^^^^^ is an `i32`
+   |
+   = help: `sym` operands must refer to either a function or a static
 
-error: asm `sym` operand must point to a fn or static
-  --> $DIR/type-check-2.rs:39:24
+error: invalid `sym` operand
+  --> $DIR/type-check-2.rs:88:19
+   |
+LL | global_asm!("{}", sym C);
+   |                   ^^^^^ is an `i32`
    |
-LL |         asm!("{}", sym x);
-   |                        ^
+   = help: `sym` operands must refer to either a function or a static
 
 error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/type-check-2.rs:15:28
index 07f207627f4df2faadd79986c7a2d292c9b03446..b904ad102e97e794468a1281066144f9577e66ed 100644 (file)
@@ -2,25 +2,57 @@ error[E0308]: mismatched types
   --> $DIR/associated-type-projection-from-supertrait.rs:27:23
    |
 LL | fn b() { dent(ModelT, Blue); }
-   |                       ^^^^ expected struct `Black`, found struct `Blue`
+   |          ----         ^^^^ expected struct `Black`, found struct `Blue`
+   |          |
+   |          arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/associated-type-projection-from-supertrait.rs:25:4
+   |
+LL | fn dent<C:Car>(c: C, color: C::Color) { c.chip_paint(color) }
+   |    ^^^^        ----  ---------------
 
 error[E0308]: mismatched types
   --> $DIR/associated-type-projection-from-supertrait.rs:28:23
    |
 LL | fn c() { dent(ModelU, Black); }
-   |                       ^^^^^ expected struct `Blue`, found struct `Black`
+   |          ----         ^^^^^ expected struct `Blue`, found struct `Black`
+   |          |
+   |          arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/associated-type-projection-from-supertrait.rs:25:4
+   |
+LL | fn dent<C:Car>(c: C, color: C::Color) { c.chip_paint(color) }
+   |    ^^^^        ----  ---------------
 
 error[E0308]: mismatched types
   --> $DIR/associated-type-projection-from-supertrait.rs:32:28
    |
 LL | fn f() { ModelT.chip_paint(Blue); }
-   |                            ^^^^ expected struct `Black`, found struct `Blue`
+   |                 ---------- ^^^^ expected struct `Black`, found struct `Blue`
+   |                 |
+   |                 arguments to this function are incorrect
+   |
+note: associated function defined here
+  --> $DIR/associated-type-projection-from-supertrait.rs:12:8
+   |
+LL |     fn chip_paint(&self, c: Self::Color) { }
+   |        ^^^^^^^^^^ -----  --------------
 
 error[E0308]: mismatched types
   --> $DIR/associated-type-projection-from-supertrait.rs:33:28
    |
 LL | fn g() { ModelU.chip_paint(Black); }
-   |                            ^^^^^ expected struct `Blue`, found struct `Black`
+   |                 ---------- ^^^^^ expected struct `Blue`, found struct `Black`
+   |                 |
+   |                 arguments to this function are incorrect
+   |
+note: associated function defined here
+  --> $DIR/associated-type-projection-from-supertrait.rs:12:8
+   |
+LL |     fn chip_paint(&self, c: Self::Color) { }
+   |        ^^^^^^^^^^ -----  --------------
 
 error: aborting due to 4 previous errors
 
index 2d8d513409d3a83dcc70f6343a05bc772a66272e..1d0b84d31d4104e4331424a3618ca45d7e07670a 100644 (file)
@@ -2,8 +2,15 @@ error[E0308]: mismatched types
   --> $DIR/associated-types-path-2.rs:19:14
    |
 LL |     f1(2i32, 4i32);
-   |              ^^^^ expected `u32`, found `i32`
+   |     --       ^^^^ expected `u32`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/associated-types-path-2.rs:13:8
    |
+LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
+   |        ^^         ----  -------
 help: change the type of the numeric literal from `i32` to `u32`
    |
 LL |     f1(2i32, 4u32);
index 3d18d9c4125962970e090809b4b12016320b02b1..5e0c8c299891093d2067028a0bd25e7ad30bab06 100644 (file)
@@ -2,9 +2,13 @@ error[E0726]: implicit elided lifetime not allowed here
   --> $DIR/async-fn-path-elision.rs:5:20
    |
 LL | async fn error(lt: HasLifetime) {
-   |                    ^^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
+   |                    ^^^^^^^^^^^ expected lifetime parameter
    |
    = note: assuming a `'static` lifetime...
+help: indicate the anonymous lifetime
+   |
+LL | async fn error(lt: HasLifetime<'_>) {
+   |                               ++++
 
 error: aborting due to previous error
 
index 289a567209c4958ea5c50ca1b82c336d478eb423..627bf05bba2d9c77110d0f7b00af849089c8b5d1 100644 (file)
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/dont-suggest-missing-await.rs:14:18
    |
 LL |         take_u32(x)
-   |                  ^ expected `u32`, found opaque type
+   |         -------- ^ expected `u32`, found opaque type
+   |         |
+   |         arguments to this function are incorrect
    |
 note: while checking the return type of the `async fn`
   --> $DIR/dont-suggest-missing-await.rs:7:24
@@ -11,6 +13,11 @@ LL | async fn make_u32() -> u32 {
    |                        ^^^ checked the `Output` of this `async fn`, found opaque type
    = note:     expected type `u32`
            found opaque type `impl Future<Output = u32>`
+note: function defined here
+  --> $DIR/dont-suggest-missing-await.rs:5:4
+   |
+LL | fn take_u32(x: u32) {}
+   |    ^^^^^^^^ ------
 help: consider `await`ing on the `Future`
    |
 LL |         take_u32(x.await)
index 3ebc4392f2c8d85a9a103eed8930fa7eb0b41056..b205fd619155e447de187a27327f1ef846728640 100644 (file)
@@ -2,52 +2,67 @@ error[E0308]: mismatched types
   --> $DIR/generator-desc.rs:10:25
    |
 LL |     fun(async {}, async {});
-   |               --        ^^ expected `async` block, found a different `async` block
-   |               |
+   |               --        ^^
+   |               |         |
+   |               |         expected `async` block, found a different `async` block
+   |               |         arguments to this function are incorrect
    |               the expected `async` block
    |
    = note: expected `async` block `[static generator@$DIR/generator-desc.rs:10:15: 10:17]`
               found `async` block `[static generator@$DIR/generator-desc.rs:10:25: 10:27]`
+note: function defined here
+  --> $SRC_DIR/core/src/future/mod.rs:LL:COL
+   |
+LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
+   |              ^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/generator-desc.rs:12:16
    |
 LL |     fun(one(), two());
-   |                ^^^^^ expected opaque type, found a different opaque type
-   |
-note: while checking the return type of the `async fn`
-  --> $DIR/generator-desc.rs:5:16
+   |     ---        ^^^^^ expected opaque type, found a different opaque type
+   |     |
+   |     arguments to this function are incorrect
    |
-LL | async fn one() {}
-   |                ^ checked the `Output` of this `async fn`, expected opaque type
 note: while checking the return type of the `async fn`
   --> $DIR/generator-desc.rs:6:16
    |
 LL | async fn two() {}
    |                ^ checked the `Output` of this `async fn`, found opaque type
-   = note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:5:16>)
-              found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:6:16>)
+   = note:     expected type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:5:16>)
+           found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:6:16>)
    = help: consider `await`ing on both `Future`s
    = note: distinct uses of `impl Trait` result in different opaque types
+note: function defined here
+  --> $DIR/generator-desc.rs:8:4
+   |
+LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
+   |    ^^^                         -----  -----
 
 error[E0308]: mismatched types
   --> $DIR/generator-desc.rs:14:26
    |
 LL |     fun((async || {})(), (async || {})());
-   |                   --     ^^^^^^^^^^^^^^^ expected `async` closure body, found a different `async` closure body
-   |                   |
-   |                   the expected `async` closure body
+   |     ---                  ^^^^^^^^^^^^^^^ expected `async` closure body, found a different `async` closure body
+   |     |
+   |     arguments to this function are incorrect
    |
   ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
    |
 LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
-   |                                           -------------------------------
-   |                                           |
-   |                                           the expected opaque type
-   |                                           the found opaque type
+   |                                           ------------------------------- the found opaque type
+   |
+   = note:     expected type `impl Future<Output = ()>` (`async` closure body)
+           found opaque type `impl Future<Output = ()>` (`async` closure body)
+note: function defined here
+  --> $DIR/generator-desc.rs:8:4
+   |
+LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
+   |    ^^^                         -----  -----
+help: consider `await`ing on the `Future`
    |
-   = note: expected opaque type `impl Future<Output = ()>` (`async` closure body)
-              found opaque type `impl Future<Output = ()>` (`async` closure body)
+LL |     fun((async || {})(), (async || {})().await);
+   |                                         ++++++
 
 error: aborting due to 3 previous errors
 
index 8b53408d758e110ef55992fc4f94c42390e4f5cd..d73772e5fa0d9b3616287e11efad261464f9dfbf 100644 (file)
@@ -7,5 +7,5 @@ fn g(_: impl Send) {}
 
 fn main() {
     g(issue_67893::run())
-    //~^ ERROR generator cannot be sent between threads safely
+    //~^ ERROR future cannot be sent between threads safely
 }
index 0aa0d5d7ccdde9c30840aaf7f6239a26d456412b..316b6d06f932ac1189cbbe6370beb920c259a178 100644 (file)
@@ -1,10 +1,22 @@
-error: generator cannot be sent between threads safely
+error: future cannot be sent between threads safely
   --> $DIR/issue-67893.rs:9:7
    |
 LL |     g(issue_67893::run())
-   |       ^^^^^^^^^^^^^^^^^^ generator is not `Send`
+   |       ^^^^^^^^^^^^^^^^^^ future is not `Send`
    |
    = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `MutexGuard<'_, ()>`
+note: future is not `Send` as this value is used across an await
+  --> $DIR/auxiliary/issue_67893.rs:9:26
+   |
+LL |     f(*x.lock().unwrap()).await;
+   |        ----------------- ^^^^^^ await occurs here, with `x.lock().unwrap()` maybe used later
+   |        |
+   |        has type `MutexGuard<'_, ()>` which is not `Send`
+note: `x.lock().unwrap()` is later dropped here
+  --> $DIR/auxiliary/issue_67893.rs:9:32
+   |
+LL |     f(*x.lock().unwrap()).await;
+   |                                ^
 note: required by a bound in `g`
   --> $DIR/issue-67893.rs:6:14
    |
index d951c8ed094e703dd42041e9903a17a50fe2b580..a5958baffbaf72719eb8ba87c6f3f17163c2ea4b 100644 (file)
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/suggest-missing-await-closure.rs:16:18
    |
 LL |         take_u32(x)
-   |                  ^ expected `u32`, found opaque type
+   |         -------- ^ expected `u32`, found opaque type
+   |         |
+   |         arguments to this function are incorrect
    |
 note: while checking the return type of the `async fn`
   --> $DIR/suggest-missing-await-closure.rs:8:24
@@ -11,6 +13,11 @@ LL | async fn make_u32() -> u32 {
    |                        ^^^ checked the `Output` of this `async fn`, found opaque type
    = note:     expected type `u32`
            found opaque type `impl Future<Output = u32>`
+note: function defined here
+  --> $DIR/suggest-missing-await-closure.rs:6:4
+   |
+LL | fn take_u32(_x: u32) {}
+   |    ^^^^^^^^ -------
 help: consider `await`ing on the `Future`
    |
 LL |         take_u32(x.await)
index 76073c4c879967d48a99ac596fc71ef10eb60665..ba9ed5cb65fc9b716ec4ae1285ec1a5a695a8783 100644 (file)
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/suggest-missing-await.rs:12:14
    |
 LL |     take_u32(x)
-   |              ^ expected `u32`, found opaque type
+   |     -------- ^ expected `u32`, found opaque type
+   |     |
+   |     arguments to this function are incorrect
    |
 note: while checking the return type of the `async fn`
   --> $DIR/suggest-missing-await.rs:5:24
@@ -11,6 +13,11 @@ LL | async fn make_u32() -> u32 {
    |                        ^^^ checked the `Output` of this `async fn`, found opaque type
    = note:     expected type `u32`
            found opaque type `impl Future<Output = u32>`
+note: function defined here
+  --> $DIR/suggest-missing-await.rs:3:4
+   |
+LL | fn take_u32(_x: u32) {}
+   |    ^^^^^^^^ -------
 help: consider `await`ing on the `Future`
    |
 LL |     take_u32(x.await)
index ca4f0efd2392b3c20517eb9f3fb739aa4e092a5d..5042ad024afff00bfabc1e48272c2a46e15c4dcf 100644 (file)
@@ -20,13 +20,13 @@ fn let_wild_gets_unsafe_field() {
     let u1 = U { a: I(0) };
     let u2 = U { a: I(1) };
     let p = P { a: &2, b: &3 };
-    let _ = &p.b;  //~ WARN    reference to packed field
+    let _ = &p.b;  //~ ERROR    reference to packed field
     //~^  WARN will become a hard error
     let _ = u1.a;  // #53114: should eventually signal error as well
     let _ = &u2.a; //~ ERROR  [E0133]
 
     // variation on above with `_` in substructure
-    let (_,) = (&p.b,);  //~ WARN     reference to packed field
+    let (_,) = (&p.b,);  //~ ERROR     reference to packed field
     //~^  WARN will become a hard error
     let (_,) = (u1.a,);  //~ ERROR   [E0133]
     let (_,) = (&u2.a,); //~ ERROR   [E0133]
@@ -36,13 +36,13 @@ fn match_unsafe_field_to_wild() {
     let u1 = U { a: I(0) };
     let u2 = U { a: I(1) };
     let p = P { a: &2, b: &3 };
-    match &p.b  { _ => { } } //~ WARN     reference to packed field
+    match &p.b  { _ => { } } //~ ERROR     reference to packed field
     //~^  WARN will become a hard error
     match u1.a  { _ => { } } //~ ERROR   [E0133]
     match &u2.a { _ => { } } //~ ERROR   [E0133]
 
     // variation on above with `_` in substructure
-    match (&p.b,)  { (_,) => { } } //~ WARN     reference to packed field
+    match (&p.b,)  { (_,) => { } } //~ ERROR     reference to packed field
     //~^  WARN will become a hard error
     match (u1.a,)  { (_,) => { } } //~ ERROR   [E0133]
     match (&u2.a,) { (_,) => { } } //~ ERROR   [E0133]
index 84cdb1453f82d4d0c7e2f6a3b904726efb2ff7a1..f3840273cfaf7ae4a4c4ad25eb414002649aa827 100644 (file)
@@ -1,16 +1,16 @@
-warning: reference to packed field is unaligned
+error: reference to packed field is unaligned
   --> $DIR/issue-53114-safety-checks.rs:23:13
    |
 LL |     let _ = &p.b;
    |             ^^^^
    |
-   = note: `#[warn(unaligned_references)]` on by default
+   = note: `#[deny(unaligned_references)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
    = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
 
-warning: reference to packed field is unaligned
+error: reference to packed field is unaligned
   --> $DIR/issue-53114-safety-checks.rs:29:17
    |
 LL |     let (_,) = (&p.b,);
@@ -21,7 +21,7 @@ LL |     let (_,) = (&p.b,);
    = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
    = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
 
-warning: reference to packed field is unaligned
+error: reference to packed field is unaligned
   --> $DIR/issue-53114-safety-checks.rs:39:11
    |
 LL |     match &p.b  { _ => { } }
@@ -32,7 +32,7 @@ LL |     match &p.b  { _ => { } }
    = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
    = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
 
-warning: reference to packed field is unaligned
+error: reference to packed field is unaligned
   --> $DIR/issue-53114-safety-checks.rs:45:12
    |
 LL |     match (&p.b,)  { (_,) => { } }
@@ -99,6 +99,58 @@ LL |     match (&u2.a,) { (_,) => { } }
    |
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
-error: aborting due to 7 previous errors; 4 warnings emitted
+error: aborting due to 11 previous errors
 
 For more information about this error, try `rustc --explain E0133`.
+Future incompatibility report: Future breakage diagnostic:
+error: reference to packed field is unaligned
+  --> $DIR/issue-53114-safety-checks.rs:23:13
+   |
+LL |     let _ = &p.b;
+   |             ^^^^
+   |
+   = note: `#[deny(unaligned_references)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+  --> $DIR/issue-53114-safety-checks.rs:29:17
+   |
+LL |     let (_,) = (&p.b,);
+   |                 ^^^^
+   |
+   = note: `#[deny(unaligned_references)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+  --> $DIR/issue-53114-safety-checks.rs:39:11
+   |
+LL |     match &p.b  { _ => { } }
+   |           ^^^^
+   |
+   = note: `#[deny(unaligned_references)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+  --> $DIR/issue-53114-safety-checks.rs:45:12
+   |
+LL |     match (&p.b,)  { (_,) => { } }
+   |            ^^^^
+   |
+   = note: `#[deny(unaligned_references)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
index 5b4e656d9dca147a55d638380c30ad360e02913f..9acf1e93b077395a4f2e65daea7d26c987eb5946 100644 (file)
@@ -8,29 +8,33 @@ error[E0060]: this function takes at least 2 arguments but 0 arguments were supp
   --> $DIR/variadic-ffi-1.rs:20:9
    |
 LL |         foo();
-   |         ^^^-- supplied 0 arguments
-   |         |
-   |         expected at least 2 arguments
+   |         ^^^-- two arguments of type `isize` and `u8` are missing
    |
 note: function defined here
   --> $DIR/variadic-ffi-1.rs:13:8
    |
 LL |     fn foo(f: isize, x: u8, ...);
    |        ^^^
+help: provide the arguments
+   |
+LL |         foo({isize}, {u8});
+   |         ~~~~~~~~~~~~~~~~~~
 
 error[E0060]: this function takes at least 2 arguments but 1 argument was supplied
   --> $DIR/variadic-ffi-1.rs:21:9
    |
 LL |         foo(1);
-   |         ^^^ - supplied 1 argument
-   |         |
-   |         expected at least 2 arguments
+   |         ^^^--- an argument of type `u8` is missing
    |
 note: function defined here
   --> $DIR/variadic-ffi-1.rs:13:8
    |
 LL |     fn foo(f: isize, x: u8, ...);
    |        ^^^
+help: provide the argument
+   |
+LL |         foo(1, {u8});
+   |         ~~~~~~~~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/variadic-ffi-1.rs:23:56
index 55b9462db8df818e73bc23836bb26fa184ce2c81..ef606b6ae5fd4e5e687a7d72b615388b184373e3 100644 (file)
@@ -2,8 +2,15 @@ error[E0308]: mismatched types
   --> $DIR/cast-int-to-char.rs:4:16
    |
 LL |     foo::<u32>('0');
-   |                ^^^ expected `u32`, found `char`
+   |     ---------- ^^^ expected `u32`, found `char`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/cast-int-to-char.rs:1:4
+   |
+LL | fn foo<T>(_t: T) {}
+   |    ^^^    -----
 help: you can cast a `char` to a `u32`, since a `char` always occupies 4 bytes
    |
 LL |     foo::<u32>('0' as u32);
@@ -13,8 +20,15 @@ error[E0308]: mismatched types
   --> $DIR/cast-int-to-char.rs:5:16
    |
 LL |     foo::<i32>('0');
-   |                ^^^ expected `i32`, found `char`
+   |     ---------- ^^^ expected `i32`, found `char`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/cast-int-to-char.rs:1:4
    |
+LL | fn foo<T>(_t: T) {}
+   |    ^^^    -----
 help: you can cast a `char` to an `i32`, since a `char` always occupies 4 bytes
    |
 LL |     foo::<i32>('0' as i32);
@@ -24,8 +38,15 @@ error[E0308]: mismatched types
   --> $DIR/cast-int-to-char.rs:6:16
    |
 LL |     foo::<u64>('0');
-   |                ^^^ expected `u64`, found `char`
+   |     ---------- ^^^ expected `u64`, found `char`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/cast-int-to-char.rs:1:4
    |
+LL | fn foo<T>(_t: T) {}
+   |    ^^^    -----
 help: you can cast a `char` to a `u64`, since a `char` always occupies 4 bytes
    |
 LL |     foo::<u64>('0' as u64);
@@ -35,8 +56,15 @@ error[E0308]: mismatched types
   --> $DIR/cast-int-to-char.rs:7:16
    |
 LL |     foo::<i64>('0');
-   |                ^^^ expected `i64`, found `char`
+   |     ---------- ^^^ expected `i64`, found `char`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/cast-int-to-char.rs:1:4
+   |
+LL | fn foo<T>(_t: T) {}
+   |    ^^^    -----
 help: you can cast a `char` to an `i64`, since a `char` always occupies 4 bytes
    |
 LL |     foo::<i64>('0' as i64);
@@ -46,7 +74,15 @@ error[E0308]: mismatched types
   --> $DIR/cast-int-to-char.rs:8:17
    |
 LL |     foo::<char>(0u32);
-   |                 ^^^^ expected `char`, found `u32`
+   |     ----------- ^^^^ expected `char`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/cast-int-to-char.rs:1:4
+   |
+LL | fn foo<T>(_t: T) {}
+   |    ^^^    -----
 
 error: aborting due to 5 previous errors
 
index 4799f488d7d525eb0b21c12bf6f5991c3be107a6..1488f329648bb1c4149862a93d0bd288a79be357 100644 (file)
@@ -1,7 +1,5 @@
 // edition:2021
 
-// check-pass
-
 // Given how the closure desugaring is implemented (at least at the time of writing this test),
 // we don't need to truncate the captured path to a reference into a packed-struct if the field
 // being referenced will be moved into the closure, since it's safe to move out a field from a
@@ -11,9 +9,8 @@
 // inlined we will truncate the capture to access just the struct regardless of if the field
 // might get moved into the closure.
 //
-// It is possible for someone to try writing the code that relies on the desugaring to access a ref
-// into a packed-struct without explicity using unsafe. Here we test that the compiler warns the
-// user that such an access is still unsafe.
+// It is possible for someone to try writing the code that relies on the desugaring to create a ref
+// into a packed-struct. Here we test that the compiler still detects that case.
 fn test_missing_unsafe_warning_on_repr_packed() {
     #[repr(packed)]
     struct Foo { x: String }
@@ -22,7 +19,7 @@ struct Foo { x: String }
 
     let c = || {
         println!("{}", foo.x);
-        //~^ WARNING: reference to packed field is unaligned
+        //~^ ERROR: reference to packed field is unaligned
         //~| WARNING: this was previously accepted by the compiler but is being phased out
         let _z = foo.x;
     };
index fc0179d2cb4ca45779bc5e7619d7c673238145f7..8629837ba8d344ea0520ff44ffa375260581fd58 100644 (file)
@@ -1,15 +1,29 @@
-warning: reference to packed field is unaligned
-  --> $DIR/repr_packed.rs:24:24
+error: reference to packed field is unaligned
+  --> $DIR/repr_packed.rs:21:24
    |
 LL |         println!("{}", foo.x);
    |                        ^^^^^
    |
-   = note: `#[warn(unaligned_references)]` on by default
+   = note: `#[deny(unaligned_references)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
    = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-   = note: this warning originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-warning: 1 warning emitted
+error: aborting due to previous error
+
+Future incompatibility report: Future breakage diagnostic:
+error: reference to packed field is unaligned
+  --> $DIR/repr_packed.rs:21:24
+   |
+LL |         println!("{}", foo.x);
+   |                        ^^^^^
+   |
+   = note: `#[deny(unaligned_references)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
index 37813879ce7529d96fb4f656b6683c7654df9045..534828ab348fd32e09ba5d6b0583698272329c4b 100644 (file)
@@ -4,7 +4,9 @@ error[E0308]: mismatched types
 LL |     let f = |s: &str| println!("{}{}", s, string);
    |             ------------------------------------- the found closure
 LL |     call_bare(f)
-   |               ^ expected fn pointer, found closure
+   |     --------- ^ expected fn pointer, found closure
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected fn pointer `for<'r> fn(&'r str)`
                  found closure `[closure@$DIR/closure-reform-bad.rs:10:13: 10:50]`
@@ -13,6 +15,11 @@ note: closures can only be coerced to `fn` types if they do not capture any vari
    |
 LL |     let f = |s: &str| println!("{}{}", s, string);
    |                                           ^^^^^^ `string` captured here
+note: function defined here
+  --> $DIR/closure-reform-bad.rs:4:4
+   |
+LL | fn call_bare(f: fn(&str)) {
+   |    ^^^^^^^^^ -----------
 
 error: aborting due to previous error
 
index 70d9273ddf7ceb2af8dbd68ac158757b3d1ee232..09c44d261af0c449f373aeef4850a883f9d5761c 100644 (file)
@@ -2,13 +2,20 @@ error[E0308]: mismatched types
   --> $DIR/issue-84128.rs:13:13
    |
 LL |         Foo(())
-   |             ^^ expected integer, found `()`
+   |         --- ^^ expected integer, found `()`
+   |         |
+   |         arguments to this struct are incorrect
    |
 note: return type inferred to be `{integer}` here
   --> $DIR/issue-84128.rs:10:20
    |
 LL |             return Foo(0);
    |                    ^^^^^^
+note: tuple struct defined here
+  --> $DIR/issue-84128.rs:5:8
+   |
+LL | struct Foo<T>(T);
+   |        ^^^
 
 error: aborting due to previous error
 
index a3cff2c12124ae4fc533207fb0c3a8e304966a13..b35fa2b8c9aba0951f7547f2f0d8bb26eef2e611 100644 (file)
@@ -2,19 +2,25 @@ error[E0308]: mismatched types
   --> $DIR/issue-87461.rs:10:8
    |
 LL |     Ok(())
-   |        ^^ expected `u16`, found `()`
+   |     -- ^^ expected `u16`, found `()`
+   |     |
+   |     arguments to this enum variant are incorrect
 
 error[E0308]: mismatched types
   --> $DIR/issue-87461.rs:17:8
    |
 LL |     Ok(())
-   |        ^^ expected `u16`, found `()`
+   |     -- ^^ expected `u16`, found `()`
+   |     |
+   |     arguments to this enum variant are incorrect
 
 error[E0308]: mismatched types
   --> $DIR/issue-87461.rs:26:12
    |
 LL |         Ok(())
-   |            ^^ expected `u16`, found `()`
+   |         -- ^^ expected `u16`, found `()`
+   |         |
+   |         arguments to this enum variant are incorrect
 
 error: aborting due to 3 previous errors
 
index 2601ca5e91e5b4253a85258d7998dced020b674f..11a4f310154c539a8e40b72406e6639feef6c809 100644 (file)
@@ -2,10 +2,17 @@ error[E0308]: mismatched types
   --> $DIR/coerce-mut.rs:5:7
    |
 LL |     f(&x);
-   |       ^^ types differ in mutability
+   |     - ^^ types differ in mutability
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected mutable reference `&mut i32`
                       found reference `&{integer}`
+note: function defined here
+  --> $DIR/coerce-mut.rs:1:4
+   |
+LL | fn f(x: &mut i32) {}
+   |    ^ -----------
 
 error: aborting due to previous error
 
index 59b0ec496f16f5a2e4c721ee7d1f08883a964fb7..4f266b166d6987753d81957f2371962a8121661e 100644 (file)
@@ -2,10 +2,17 @@ error[E0308]: mismatched types
   --> $DIR/coerce-reborrow-multi-arg-fail.rs:4:18
    |
 LL |     test(&mut 7, &7);
-   |                  ^^ types differ in mutability
+   |     ----         ^^ types differ in mutability
+   |     |
+   |     arguments to this function are incorrect
    |
-   = note: expected mutable reference `&mut {integer}`
-                      found reference `&{integer}`
+   = note:   expected type `&mut {integer}`
+           found reference `&{integer}`
+note: function defined here
+  --> $DIR/coerce-reborrow-multi-arg-fail.rs:1:4
+   |
+LL | fn test<T>(_a: T, _b: T) {}
+   |    ^^^^    -----  -----
 
 error: aborting due to previous error
 
index 390aa7c692d1860829d15cf95521858fb82b7b77..add8f14cfa591884a3ee3fb8805313d85ec8144b 100644 (file)
@@ -2,46 +2,81 @@ error[E0308]: mismatched types
   --> $DIR/coerce-to-bang.rs:6:17
    |
 LL |     foo(return, 22, 44);
-   |                 ^^ expected `!`, found integer
+   |     ---         ^^ expected `!`, found integer
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected type `!`
               found type `{integer}`
+note: function defined here
+  --> $DIR/coerce-to-bang.rs:3:4
+   |
+LL | fn foo(x: usize, y: !, z: usize) { }
+   |    ^^^ --------  ----  --------
 
 error[E0308]: mismatched types
   --> $DIR/coerce-to-bang.rs:18:13
    |
 LL |     foo(22, 44, return);
-   |             ^^ expected `!`, found integer
+   |     ---     ^^ expected `!`, found integer
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected type `!`
               found type `{integer}`
+note: function defined here
+  --> $DIR/coerce-to-bang.rs:3:4
+   |
+LL | fn foo(x: usize, y: !, z: usize) { }
+   |    ^^^ --------  ----  --------
 
 error[E0308]: mismatched types
   --> $DIR/coerce-to-bang.rs:26:12
    |
 LL |     foo(a, b, c); // ... and hence a reference to `a` is expected to diverge.
-   |            ^ expected `!`, found integer
+   |     ---    ^ expected `!`, found integer
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected type `!`
               found type `{integer}`
+note: function defined here
+  --> $DIR/coerce-to-bang.rs:3:4
+   |
+LL | fn foo(x: usize, y: !, z: usize) { }
+   |    ^^^ --------  ----  --------
 
 error[E0308]: mismatched types
   --> $DIR/coerce-to-bang.rs:36:12
    |
 LL |     foo(a, b, c);
-   |            ^ expected `!`, found integer
+   |     ---    ^ expected `!`, found integer
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected type `!`
               found type `{integer}`
+note: function defined here
+  --> $DIR/coerce-to-bang.rs:3:4
+   |
+LL | fn foo(x: usize, y: !, z: usize) { }
+   |    ^^^ --------  ----  --------
 
 error[E0308]: mismatched types
   --> $DIR/coerce-to-bang.rs:45:12
    |
 LL |     foo(a, b, c);
-   |            ^ expected `!`, found integer
+   |     ---    ^ expected `!`, found integer
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected type `!`
               found type `{integer}`
+note: function defined here
+  --> $DIR/coerce-to-bang.rs:3:4
+   |
+LL | fn foo(x: usize, y: !, z: usize) { }
+   |    ^^^ --------  ----  --------
 
 error[E0308]: mismatched types
   --> $DIR/coerce-to-bang.rs:50:21
index 0cf2a406da443d6c97799f3d10304249e9c8461e..fe4b5b410789572e32aaae7e0a003c16eb51df1e 100644 (file)
@@ -1,4 +1,4 @@
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
   --> $DIR/coherence-cow.rs:18:1
    |
 LL | impl<T> Remote for Pair<T,Cover<T>> { }
index b523db4da23eaf0b2ac534ed57e57d7bcd08e3a6..da4ede3251ed83729fcfddde25d482c2b91df15b 100644 (file)
@@ -1,4 +1,4 @@
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
   --> $DIR/coherence-cow.rs:22:1
    |
 LL | impl<T> Remote for Pair<Cover<T>,T> { }
index bd635fc2e8c29353b8b4bf2673f97d932b821e73..d1a20c0ca101b99e1f597e1957438ba5c72edc8c 100644 (file)
@@ -1,4 +1,4 @@
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
   --> $DIR/coherence-cow.rs:26:1
    |
 LL | impl<T,U> Remote for Pair<Cover<T>,U> { }
index a7d6968a2967cc272de8e7fcb712ca75b96c8574..b3ca354c633aade9e89e5bfa9d21eba1407121a2 100644 (file)
@@ -1,4 +1,4 @@
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
   --> $DIR/coherence-impls-copy.rs:5:1
    |
 LL | impl Copy for i32 {}
index 52d2cc88cbe7f2668ad6484b3c829d0053d95668..01f166a21f7683aee5f4d7678f0ec5d598eb30dd 100644 (file)
@@ -1,4 +1,4 @@
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
   --> $DIR/coherence-orphan.rs:10:1
    |
 LL | impl TheTrait<usize> for isize { }
@@ -10,7 +10,7 @@ LL | impl TheTrait<usize> for isize { }
    |
    = note: define and implement a trait or new type instead
 
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
   --> $DIR/coherence-orphan.rs:17:1
    |
 LL | impl !Send for Vec<isize> { }
index c1a02681c1343f0b79f96e10c930a962303e2959..15c92dfeb07d73d26bc9ab2b6961c5fa5d2a2e07 100644 (file)
@@ -1,4 +1,4 @@
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
   --> $DIR/coherence-overlapping-pairs.rs:8:1
    |
 LL | impl<T> Remote for lib::Pair<T,Foo> { }
index b18bf44dbdf2894894a55dfe5760c4527c77843c..03d787123812874dd36776e8534131e79af04800 100644 (file)
@@ -1,4 +1,4 @@
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
   --> $DIR/coherence-pair-covered-uncovered-1.rs:12:1
    |
 LL | impl<T, U> Remote1<Pair<T, Local<U>>> for i32 { }
index 34fdf64ea109f8551b60e55f58bad11aeb319488..73dfe2f572ae3e205c55d8b85d6566401f23b3ac 100644 (file)
@@ -1,4 +1,4 @@
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
   --> $DIR/coherence-pair-covered-uncovered.rs:8:1
    |
 LL | impl<T,U> Remote for Pair<T,Local<U>> { }
index 567b6a6c17fda1e2faba5aef0bfc58a9f023e9e4..95fdf172ec255404e54378bd1dcb6837b7c8d48d 100644 (file)
@@ -1,4 +1,4 @@
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
   --> $DIR/coherence-vec-local-2.rs:11:1
    |
 LL | impl<T> Remote for Vec<Local<T>> { }
index 38464f12a21d041c8010013052a2916cf60f92c7..4835e771abd3bf807d77609c75e175ba9097063c 100644 (file)
@@ -1,4 +1,4 @@
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
   --> $DIR/coherence-vec-local.rs:11:1
    |
 LL | impl Remote for Vec<Local> { }
index 8c310b318a7af47761cd07084361c68c4cf77095..afc6fc45d0e03f890f5e9c5c020c2fd68f9c7bb4 100644 (file)
@@ -1,4 +1,4 @@
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
   --> $DIR/coherence_local_err_struct.rs:14:1
    |
 LL | impl lib::MyCopy for lib::MyStruct<MyType> { }
index fe7c9b93f5401245b540b1f3efad88c3c819aaf9..93f7a6fdc25d34eb43be6bb0832b416fd415e6da 100644 (file)
@@ -1,4 +1,4 @@
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
   --> $DIR/impl-foreign-for-foreign.rs:10:1
    |
 LL | impl Remote for i32 {
index bdf19cf00a7cee35b564d99e8ed538f2b0863ea5..e24537bce229a5f4942b6306a06c48efb599c9ef 100644 (file)
@@ -1,4 +1,4 @@
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
   --> $DIR/impl-foreign-for-foreign[foreign].rs:10:1
    |
 LL | impl Remote1<Rc<i32>> for i32 {
@@ -10,7 +10,7 @@ LL | impl Remote1<Rc<i32>> for i32 {
    |
    = note: define and implement a trait or new type instead
 
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
   --> $DIR/impl-foreign-for-foreign[foreign].rs:14:1
    |
 LL | impl Remote1<Rc<Local>> for f64 {
@@ -22,7 +22,7 @@ LL | impl Remote1<Rc<Local>> for f64 {
    |
    = note: define and implement a trait or new type instead
 
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
   --> $DIR/impl-foreign-for-foreign[foreign].rs:18:1
    |
 LL | impl<T> Remote1<Rc<T>> for f32 {
index 20dc955ffe42b9f4cac442ef8ae0fad3826032b9..55ea4409e6f362f9b7037308b3298b9f61359d16 100644 (file)
@@ -1,4 +1,4 @@
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
   --> $DIR/impl-foreign-for-fundamental[foreign].rs:10:1
    |
 LL | impl Remote for Box<i32> {
@@ -10,7 +10,7 @@ LL | impl Remote for Box<i32> {
    |
    = note: define and implement a trait or new type instead
 
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
   --> $DIR/impl-foreign-for-fundamental[foreign].rs:14:1
    |
 LL | impl<T> Remote for Box<Rc<T>> {
index 5552d825793715a819cd74ff5edd60da5062f692..65b3aa394a85f756e942841fa000c0d0822c0f6e 100644 (file)
@@ -1,4 +1,4 @@
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
   --> $DIR/impl-foreign[foreign]-for-foreign.rs:10:1
    |
 LL | impl Remote1<u32> for f64 {
index c1e2fdaf5e302e4f0da96d9a609d906ee6d7c59a..8e77c13e1116aef74a36dcd8f9fe2542d5bc2277 100644 (file)
@@ -1,4 +1,4 @@
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
   --> $DIR/impl-foreign[fundemental[foreign]]-for-foreign.rs:11:1
    |
 LL | impl Remote1<Box<String>> for i32 {
@@ -11,7 +11,7 @@ LL | impl Remote1<Box<String>> for i32 {
    |
    = note: define and implement a trait or new type instead
 
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
   --> $DIR/impl-foreign[fundemental[foreign]]-for-foreign.rs:15:1
    |
 LL | impl Remote1<Box<Rc<i32>>> for f64 {
@@ -24,7 +24,7 @@ LL | impl Remote1<Box<Rc<i32>>> for f64 {
    |
    = note: define and implement a trait or new type instead
 
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
   --> $DIR/impl-foreign[fundemental[foreign]]-for-foreign.rs:19:1
    |
 LL | impl<T> Remote1<Box<Rc<T>>> for f32 {
index 7f8ec83b24a8b9d39798d4204e8df52c2b2ca79c..92346c29198cede287a0edafea079342fd0578cb 100644 (file)
@@ -1,4 +1,4 @@
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
   --> $DIR/impl[t]-foreign-for-foreign[t].rs:11:1
    |
 LL | impl Remote for Rc<Local> {
@@ -9,7 +9,7 @@ LL | impl Remote for Rc<Local> {
    |
    = note: define and implement a trait or new type instead
 
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
   --> $DIR/impl[t]-foreign-for-foreign[t].rs:16:1
    |
 LL | impl<T> Remote for Arc<T> {
diff --git a/src/test/ui/const-generics/const-argument-cross-crate-mismatch.min.stderr b/src/test/ui/const-generics/const-argument-cross-crate-mismatch.min.stderr
new file mode 100644 (file)
index 0000000..e9854f0
--- /dev/null
@@ -0,0 +1,29 @@
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/const-argument-cross-crate-mismatch.rs:7:41
+   |
+LL |     let _ = const_generic_lib::function(const_generic_lib::Struct([0u8, 1u8]));
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^----------^
+   |                                                                   |
+   |                                                                   expected `[u8; 3]`, found `[u8; 2]`
+   |
+help: provide an argument of the correct type
+   |
+LL |     let _ = const_generic_lib::function(({[u8; 3]}));
+   |                                         ^^^^^^^^^^^
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/const-argument-cross-crate-mismatch.rs:9:39
+   |
+LL |     let _: const_generic_lib::Alias = const_generic_lib::Struct([0u8, 1u8, 2u8]);
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^
+   |                                                                 |
+   |                                                                 expected `[u8; 2]`, found `[u8; 3]`
+   |
+help: provide an argument of the correct type
+   |
+LL |     let _: const_generic_lib::Alias = ({[u8; 2]});
+   |                                       ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index aefd514f7a68ec65bb145a5ab9a33a9428f321f6..42f469d9817813c0a5fdec0a33d6f42562ab2f01 100644 (file)
@@ -2,13 +2,17 @@ error[E0308]: mismatched types
   --> $DIR/const-argument-cross-crate-mismatch.rs:6:67
    |
 LL |     let _ = const_generic_lib::function(const_generic_lib::Struct([0u8, 1u8]));
-   |                                                                   ^^^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements
+   |                                         ------------------------- ^^^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements
+   |                                         |
+   |                                         arguments to this struct are incorrect
 
 error[E0308]: mismatched types
   --> $DIR/const-argument-cross-crate-mismatch.rs:8:65
    |
 LL |     let _: const_generic_lib::Alias = const_generic_lib::Struct([0u8, 1u8, 2u8]);
-   |                                                                 ^^^^^^^^^^^^^^^ expected an array with a fixed size of 2 elements, found one with 3 elements
+   |                                       ------------------------- ^^^^^^^^^^^^^^^ expected an array with a fixed size of 2 elements, found one with 3 elements
+   |                                       |
+   |                                       arguments to this struct are incorrect
 
 error: aborting due to 2 previous errors
 
index 5d45e302888d424895cb88f12ac906c75de013ea..9bea4105d58b06099a7a07cfe46e581acea61060 100644 (file)
@@ -1,19 +1,26 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-62504.rs:18:25
+   |
+LL |         ArrayHolder([0; Self::SIZE])
+   |                         ^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
 error[E0308]: mismatched types
   --> $DIR/issue-62504.rs:18:21
    |
 LL |         ArrayHolder([0; Self::SIZE])
-   |                     ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE`
+   |         ----------- ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE`
+   |         |
+   |         arguments to this struct are incorrect
    |
    = note: expected array `[u32; X]`
               found array `[u32; _]`
-
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-62504.rs:18:25
+note: tuple struct defined here
+  --> $DIR/issue-62504.rs:14:8
    |
-LL |         ArrayHolder([0; Self::SIZE])
-   |                         ^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
+LL | struct ArrayHolder<const X: usize>([u32; X]);
+   |        ^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 8f92eeaffd19db4cf60f2a0e6a4a97e75c7025bb..f998c1187d810eb7f73e5631663bb5d7396cb69c 100644 (file)
@@ -13,7 +13,7 @@ error[E0107]: this trait takes 0 generic arguments but 1 generic argument was su
   --> $DIR/issue-87493.rs:8:8
    |
 LL |     T: MyTrait<Assoc == S::Assoc>,
-   |        ^^^^^^^------------------- help: remove these generics
+   |        ^^^^^^^ ----------------- help: replace the generic bound with the associated type: `Assoc = Assoc == S::Assoc`
    |        |
    |        expected 0 generic arguments
    |
index 111d243959a13257b9f9049be77ba4ad96f82ef2..b60bac541f4c815fe892d0a02d491a4cf4d72881 100644 (file)
@@ -119,27 +119,17 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran
                78 00 00 00 ff ff ff ff                         │ x.......
            }
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:92:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-enum.rs:92:77
    |
 LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(Ok)>.0.1: encountered a value of uninhabited type Never
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 8, align: 4) {
-               00 00 00 00 00 00 00 00                         │ ........
-           }
+   |                                                                             ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:94:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-enum.rs:94:77
    |
 LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(Ok)>.0.1: encountered a value of the never type `!`
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 8, align: 4) {
-               00 00 00 00 00 00 00 00                         │ ........
-           }
+   |                                                                             ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
 
 error: aborting due to 13 previous errors
 
index eee132bae00bc4ab032b3b66ac497cc598c97ac8..1d81e2b3eed86564cf23f96ad99f702a69577dec 100644 (file)
@@ -119,27 +119,17 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran
                78 00 00 00 ff ff ff ff                         │ x.......
            }
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:92:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-enum.rs:92:77
    |
 LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(Ok)>.0.1: encountered a value of uninhabited type Never
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 8, align: 4) {
-               00 00 00 00 00 00 00 00                         │ ........
-           }
+   |                                                                             ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:94:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-enum.rs:94:77
    |
 LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(Ok)>.0.1: encountered a value of the never type `!`
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 8, align: 4) {
-               00 00 00 00 00 00 00 00                         │ ........
-           }
+   |                                                                             ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
 
 error: aborting due to 13 previous errors
 
index e408d8ec072e318c6faa652c31204789affec2e3..86288685303cab71d3d733a3d6cfda0311fead9d 100644 (file)
@@ -90,9 +90,9 @@ enum UninhDiscriminant {
 // All variants are uninhabited but also have data.
 // Use `0` as constant to make behavior endianess-independent.
 const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
-//~^ ERROR is undefined behavior
+//~^ ERROR evaluation of constant value failed
 const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
-//~^ ERROR is undefined behavior
+//~^ ERROR evaluation of constant value failed
 
 fn main() {
 }
index 7dc1ec865af8a60a371ef1f4c1bd73d5aa0e2479..65ab1b02b3587d3cbbae56c1946f5e07c4db2f4e 100644 (file)
@@ -7,14 +7,14 @@ LL |     unsafe { std::mem::transmute(()) }
    |              transmuting to uninhabited type
    |              inside `foo` at $DIR/validate_uninhabited_zsts.rs:4:14
 ...
-LL | const FOO: [Empty; 3] = [foo(); 3];
-   |                          ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:13:26
+LL | const FOO: [empty::Empty; 3] = [foo(); 3];
+   |                                 ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:20:33
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/validate_uninhabited_zsts.rs:16:1
+  --> $DIR/validate_uninhabited_zsts.rs:23:1
    |
-LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0]: encountered a value of uninhabited type Empty
+LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0].0: encountered a value of uninhabited type empty::Void
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 0, align: 1) {}
@@ -31,16 +31,20 @@ LL |     unsafe { std::mem::transmute(()) }
    = note: `#[warn(invalid_value)]` on by default
    = note: the `!` type has no valid value
 
-warning: the type `Empty` does not permit zero-initialization
-  --> $DIR/validate_uninhabited_zsts.rs:16:35
+warning: the type `empty::Empty` does not permit zero-initialization
+  --> $DIR/validate_uninhabited_zsts.rs:23:42
    |
-LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
-   |                                   ^^^^^^^^^^^^^^^^^^^^^^^
-   |                                   |
-   |                                   this code causes undefined behavior when executed
-   |                                   help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^
+   |                                          |
+   |                                          this code causes undefined behavior when executed
+   |                                          help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: enums with no variants have no valid value
+note: enums with no variants have no valid value (in this struct field)
+  --> $DIR/validate_uninhabited_zsts.rs:16:22
+   |
+LL |     pub struct Empty(Void);
+   |                      ^^^^
 
 error: aborting due to 2 previous errors; 2 warnings emitted
 
index 7dc1ec865af8a60a371ef1f4c1bd73d5aa0e2479..65ab1b02b3587d3cbbae56c1946f5e07c4db2f4e 100644 (file)
@@ -7,14 +7,14 @@ LL |     unsafe { std::mem::transmute(()) }
    |              transmuting to uninhabited type
    |              inside `foo` at $DIR/validate_uninhabited_zsts.rs:4:14
 ...
-LL | const FOO: [Empty; 3] = [foo(); 3];
-   |                          ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:13:26
+LL | const FOO: [empty::Empty; 3] = [foo(); 3];
+   |                                 ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:20:33
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/validate_uninhabited_zsts.rs:16:1
+  --> $DIR/validate_uninhabited_zsts.rs:23:1
    |
-LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0]: encountered a value of uninhabited type Empty
+LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0].0: encountered a value of uninhabited type empty::Void
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 0, align: 1) {}
@@ -31,16 +31,20 @@ LL |     unsafe { std::mem::transmute(()) }
    = note: `#[warn(invalid_value)]` on by default
    = note: the `!` type has no valid value
 
-warning: the type `Empty` does not permit zero-initialization
-  --> $DIR/validate_uninhabited_zsts.rs:16:35
+warning: the type `empty::Empty` does not permit zero-initialization
+  --> $DIR/validate_uninhabited_zsts.rs:23:42
    |
-LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
-   |                                   ^^^^^^^^^^^^^^^^^^^^^^^
-   |                                   |
-   |                                   this code causes undefined behavior when executed
-   |                                   help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^
+   |                                          |
+   |                                          this code causes undefined behavior when executed
+   |                                          help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: enums with no variants have no valid value
+note: enums with no variants have no valid value (in this struct field)
+  --> $DIR/validate_uninhabited_zsts.rs:16:22
+   |
+LL |     pub struct Empty(Void);
+   |                      ^^^^
 
 error: aborting due to 2 previous errors; 2 warnings emitted
 
index 346504845561dc5144198bd3ee3881b0ceef390d..96f3312758292e34b8e9cf9a5e9f206de18c8e1e 100644 (file)
@@ -6,16 +6,23 @@ const fn foo() -> ! {
     //~| WARN the type `!` does not permit zero-initialization [invalid_value]
 }
 
-#[derive(Clone, Copy)]
-enum Empty { }
+// Type defined in a submodule, so that it is not "visibly"
+// uninhabited (which would change interpreter behavior).
+pub mod empty {
+    #[derive(Clone, Copy)]
+    enum Void {}
+
+    #[derive(Clone, Copy)]
+    pub struct Empty(Void);
+}
 
 #[warn(const_err)]
-const FOO: [Empty; 3] = [foo(); 3];
+const FOO: [empty::Empty; 3] = [foo(); 3];
 
 #[warn(const_err)]
-const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
+const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
 //~^ ERROR it is undefined behavior to use this value
-//~| WARN the type `Empty` does not permit zero-initialization
+//~| WARN the type `empty::Empty` does not permit zero-initialization
 
 fn main() {
     FOO;
index 5667d5535274d161c5b38bf434638d6ba476a006..f7bed91b03787bd899c01c2189ae16f28f7e31e1 100644 (file)
@@ -1,10 +1,13 @@
-// Check that `const extern fn` and `const unsafe extern fn` are feature-gated.
+// Check that `const extern fn` and `const unsafe extern fn` are feature-gated
+// for certain ABIs.
 
-const extern fn foo1() {} //~ ERROR `const extern fn` definitions are unstable
-const extern "C" fn foo2() {} //~ ERROR `const extern fn` definitions are unstable
-const extern "Rust" fn foo3() {} //~ ERROR `const extern fn` definitions are unstable
-const unsafe extern fn bar1() {} //~ ERROR `const extern fn` definitions are unstable
-const unsafe extern "C" fn bar2() {} //~ ERROR `const extern fn` definitions are unstable
-const unsafe extern "Rust" fn bar3() {} //~ ERROR `const extern fn` definitions are unstable
+const extern fn foo1() {}
+const extern "C" fn foo2() {}
+const extern "Rust" fn foo3() {}
+const extern "cdecl" fn foo4() {} //~ ERROR `cdecl` as a `const fn` ABI is unstable
+const unsafe extern fn bar1() {}
+const unsafe extern "C" fn bar2() {}
+const unsafe extern "Rust" fn bar3() {}
+const unsafe extern "cdecl" fn bar4() {} //~ ERROR `cdecl` as a `const fn` ABI is unstable
 
 fn main() {}
index bd5940a3fd60c17cf07a67b5fd6512c8ba149309..f8c3107bd221aa40b2f56682e3a871748b60ecb0 100644 (file)
@@ -1,57 +1,21 @@
-error[E0658]: `const extern fn` definitions are unstable
-  --> $DIR/feature-gate-const_extern_fn.rs:3:1
+error[E0658]: `cdecl` as a `const fn` ABI is unstable
+  --> $DIR/feature-gate-const_extern_fn.rs:7:14
    |
-LL | const extern fn foo1() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | const extern "cdecl" fn foo4() {}
+   |              ^^^^^^^
    |
    = note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
    = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
 
-error[E0658]: `const extern fn` definitions are unstable
-  --> $DIR/feature-gate-const_extern_fn.rs:4:1
+error[E0658]: `cdecl` as a `const fn` ABI is unstable
+  --> $DIR/feature-gate-const_extern_fn.rs:11:21
    |
-LL | const extern "C" fn foo2() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | const unsafe extern "cdecl" fn bar4() {}
+   |                     ^^^^^^^
    |
    = note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
    = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
 
-error[E0658]: `const extern fn` definitions are unstable
-  --> $DIR/feature-gate-const_extern_fn.rs:5:1
-   |
-LL | const extern "Rust" fn foo3() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
-   = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
-
-error[E0658]: `const extern fn` definitions are unstable
-  --> $DIR/feature-gate-const_extern_fn.rs:6:1
-   |
-LL | const unsafe extern fn bar1() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
-   = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
-
-error[E0658]: `const extern fn` definitions are unstable
-  --> $DIR/feature-gate-const_extern_fn.rs:7:1
-   |
-LL | const unsafe extern "C" fn bar2() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
-   = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
-
-error[E0658]: `const extern fn` definitions are unstable
-  --> $DIR/feature-gate-const_extern_fn.rs:8:1
-   |
-LL | const unsafe extern "Rust" fn bar3() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
-   = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
-
-error: aborting due to 6 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index c857ad6df2de24cec2e01771bdf1553f92789817..310db2174aafa34627b53fea6852346e56af4301 100644 (file)
@@ -37,22 +37,6 @@ fn f32() {
     const_assert!(f32::from_bits(0x44a72000), 1337.0);
     const_assert!(f32::from_ne_bytes(0x44a72000u32.to_ne_bytes()), 1337.0);
     const_assert!(f32::from_bits(0xc1640000), -14.25);
-
-    // Check that NaNs roundtrip their bits regardless of signalingness
-    // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
-    const MASKED_NAN1: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA;
-    const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555;
-
-    const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
-    const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
-
-    // LLVM does not guarantee that loads and stores of NaNs preserve their exact bit pattern.
-    // In practice, this seems to only cause a problem on x86, since the most widely used calling
-    // convention mandates that floating point values are returned on the x87 FPU stack. See #73328.
-    if !cfg!(target_arch = "x86") {
-        const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
-        const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
-    }
 }
 
 fn f64() {
@@ -70,20 +54,6 @@ fn f64() {
     const_assert!(f64::from_bits(0x4094e40000000000), 1337.0);
     const_assert!(f64::from_ne_bytes(0x4094e40000000000u64.to_ne_bytes()), 1337.0);
     const_assert!(f64::from_bits(0xc02c800000000000), -14.25);
-
-    // Check that NaNs roundtrip their bits regardless of signalingness
-    // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
-    const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
-    const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
-
-    const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
-    const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
-
-    // See comment above.
-    if !cfg!(target_arch = "x86") {
-        const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
-        const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
-    }
 }
 
 fn main() {
diff --git a/src/test/ui/consts/const-float-bits-reject-conv.rs b/src/test/ui/consts/const-float-bits-reject-conv.rs
new file mode 100644 (file)
index 0000000..122f5b9
--- /dev/null
@@ -0,0 +1,62 @@
+// compile-flags: -Zmir-opt-level=0
+#![feature(const_float_bits_conv)]
+#![feature(const_float_classify)]
+
+// Don't promote
+const fn nop<T>(x: T) -> T { x }
+
+macro_rules! const_assert {
+    ($a:expr) => {
+        {
+            const _: () = assert!($a);
+            assert!(nop($a));
+        }
+    };
+    ($a:expr, $b:expr) => {
+        {
+            const _: () = assert!($a == $b);
+            assert_eq!(nop($a), nop($b));
+        }
+    };
+}
+
+fn f32() {
+    // Check that NaNs roundtrip their bits regardless of signalingness
+    // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
+    // ...actually, let's just check that these break. :D
+    const MASKED_NAN1: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA;
+    const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555;
+
+    const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
+    const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
+
+    // LLVM does not guarantee that loads and stores of NaNs preserve their exact bit pattern.
+    // In practice, this seems to only cause a problem on x86, since the most widely used calling
+    // convention mandates that floating point values are returned on the x87 FPU stack. See #73328.
+    if !cfg!(target_arch = "x86") {
+        const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
+        const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
+    }
+}
+
+fn f64() {
+    // Check that NaNs roundtrip their bits regardless of signalingness
+    // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
+    // ...actually, let's just check that these break. :D
+    const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
+    const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
+
+    const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
+    const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
+
+    // See comment above.
+    if !cfg!(target_arch = "x86") {
+        const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
+        const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
+    }
+}
+
+fn main() {
+    f32();
+    f64();
+}
diff --git a/src/test/ui/consts/const-float-bits-reject-conv.stderr b/src/test/ui/consts/const-float-bits-reject-conv.stderr
new file mode 100644 (file)
index 0000000..b39e881
--- /dev/null
@@ -0,0 +1,119 @@
+error[E0080]: evaluation of constant value failed
+  --> $SRC_DIR/core/src/num/f32.rs:LL:COL
+   |
+LL |                     panic!("const-eval error: cannot use f32::to_bits on a NaN")
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                     |
+   |                     the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
+   |                     inside `core::f32::<impl f32>::to_bits::ct_f32_to_u32` at $SRC_DIR/core/src/panic.rs:LL:COL
+...
+LL |         unsafe { intrinsics::const_eval_select((self,), ct_f32_to_u32, rt_f32_to_u32) }
+   |                  -------------------------------------------------------------------- inside `core::f32::<impl f32>::to_bits` at $SRC_DIR/core/src/num/f32.rs:LL:COL
+   |
+  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL |     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+   |     ------------------------------------------------------------------ inside `<fn(f32) -> u32 {core::f32::<impl f32>::to_bits::ct_f32_to_u32} as FnOnce<(f32,)>>::call_once - shim(fn(f32) -> u32 {core::f32::<impl f32>::to_bits::ct_f32_to_u32})` at $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+  ::: $SRC_DIR/core/src/intrinsics.rs:LL:COL
+   |
+LL |     called_in_const.call_once(arg)
+   |     ------------------------------ inside `const_eval_select::<(f32,), fn(f32) -> u32 {core::f32::<impl f32>::to_bits::ct_f32_to_u32}, [closure@core::f32::<impl f32>::to_bits::{closure#0}], u32>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+   |
+  ::: $DIR/const-float-bits-reject-conv.rs:27:30
+   |
+LL |     const MASKED_NAN1: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA;
+   |                              ------------------ inside `f32::MASKED_NAN1` at $DIR/const-float-bits-reject-conv.rs:27:30
+   |
+   = 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
+  --> $SRC_DIR/core/src/num/f32.rs:LL:COL
+   |
+LL |                     panic!("const-eval error: cannot use f32::to_bits on a NaN")
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                     |
+   |                     the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
+   |                     inside `core::f32::<impl f32>::to_bits::ct_f32_to_u32` at $SRC_DIR/core/src/panic.rs:LL:COL
+...
+LL |         unsafe { intrinsics::const_eval_select((self,), ct_f32_to_u32, rt_f32_to_u32) }
+   |                  -------------------------------------------------------------------- inside `core::f32::<impl f32>::to_bits` at $SRC_DIR/core/src/num/f32.rs:LL:COL
+   |
+  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL |     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+   |     ------------------------------------------------------------------ inside `<fn(f32) -> u32 {core::f32::<impl f32>::to_bits::ct_f32_to_u32} as FnOnce<(f32,)>>::call_once - shim(fn(f32) -> u32 {core::f32::<impl f32>::to_bits::ct_f32_to_u32})` at $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+  ::: $SRC_DIR/core/src/intrinsics.rs:LL:COL
+   |
+LL |     called_in_const.call_once(arg)
+   |     ------------------------------ inside `const_eval_select::<(f32,), fn(f32) -> u32 {core::f32::<impl f32>::to_bits::ct_f32_to_u32}, [closure@core::f32::<impl f32>::to_bits::{closure#0}], u32>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+   |
+  ::: $DIR/const-float-bits-reject-conv.rs:28:30
+   |
+LL |     const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555;
+   |                              ------------------ inside `f32::MASKED_NAN2` at $DIR/const-float-bits-reject-conv.rs:28:30
+   |
+   = 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
+  --> $SRC_DIR/core/src/num/f64.rs:LL:COL
+   |
+LL |                     panic!("const-eval error: cannot use f64::to_bits on a NaN")
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                     |
+   |                     the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
+   |                     inside `core::f64::<impl f64>::to_bits::ct_f64_to_u64` at $SRC_DIR/core/src/panic.rs:LL:COL
+...
+LL |         unsafe { intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64) }
+   |                  -------------------------------------------------------------------- inside `core::f64::<impl f64>::to_bits` at $SRC_DIR/core/src/num/f64.rs:LL:COL
+   |
+  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL |     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+   |     ------------------------------------------------------------------ inside `<fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64} as FnOnce<(f64,)>>::call_once - shim(fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64})` at $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+  ::: $SRC_DIR/core/src/intrinsics.rs:LL:COL
+   |
+LL |     called_in_const.call_once(arg)
+   |     ------------------------------ inside `const_eval_select::<(f64,), fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64}, [closure@core::f64::<impl f64>::to_bits::{closure#0}], u64>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+   |
+  ::: $DIR/const-float-bits-reject-conv.rs:46:30
+   |
+LL |     const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
+   |                              ------------------ inside `f64::MASKED_NAN1` at $DIR/const-float-bits-reject-conv.rs:46:30
+   |
+   = 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
+  --> $SRC_DIR/core/src/num/f64.rs:LL:COL
+   |
+LL |                     panic!("const-eval error: cannot use f64::to_bits on a NaN")
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                     |
+   |                     the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
+   |                     inside `core::f64::<impl f64>::to_bits::ct_f64_to_u64` at $SRC_DIR/core/src/panic.rs:LL:COL
+...
+LL |         unsafe { intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64) }
+   |                  -------------------------------------------------------------------- inside `core::f64::<impl f64>::to_bits` at $SRC_DIR/core/src/num/f64.rs:LL:COL
+   |
+  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL |     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+   |     ------------------------------------------------------------------ inside `<fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64} as FnOnce<(f64,)>>::call_once - shim(fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64})` at $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+  ::: $SRC_DIR/core/src/intrinsics.rs:LL:COL
+   |
+LL |     called_in_const.call_once(arg)
+   |     ------------------------------ inside `const_eval_select::<(f64,), fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64}, [closure@core::f64::<impl f64>::to_bits::{closure#0}], u64>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+   |
+  ::: $DIR/const-float-bits-reject-conv.rs:47:30
+   |
+LL |     const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
+   |                              ------------------ inside `f64::MASKED_NAN2` at $DIR/const-float-bits-reject-conv.rs:47:30
+   |
+   = 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 4 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
index 4d53cfc35e1c4ab88db8e8b0bca1e545a23c99b2..e36324f0b3eea2680367b8780d7413fde536266e 100644 (file)
@@ -22,8 +22,8 @@ LL |     for i in 0..x {
 note: impl defined here, but it is not `const`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    |
-LL | impl<I: Iterator> IntoIterator for I {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<I: ~const Iterator> const IntoIterator for I {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
 error[E0658]: mutable references are not allowed in constant functions
index b0dc43eb8e8508f0d23cb136faa64e168408afb2..f2e1c8a4991a31c5f265db040cf518b6b0695c74 100644 (file)
@@ -7,8 +7,8 @@ LL |     for _ in 0..5 {}
 note: impl defined here, but it is not `const`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    |
-LL | impl<I: Iterator> IntoIterator for I {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<I: ~const Iterator> const IntoIterator for I {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
 error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants
index 667f82ee0cfef2fc72598204551dc027622440cf..1002b359f60bacaee5d0a4658e05c307e695ebcd 100644 (file)
@@ -45,3 +45,67 @@ LL | #[derive(PartialEq)]
 
 error: aborting due to 4 previous errors
 
+Future incompatibility report: Future breakage diagnostic:
+error: `#[derive]` can't be used on a `#[repr(packed)]` struct with type or const parameters (error E0133)
+  --> $DIR/deriving-with-repr-packed.rs:8:16
+   |
+LL | #[derive(Copy, Clone, PartialEq, Eq)]
+   |                ^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/deriving-with-repr-packed.rs:1:9
+   |
+LL | #![deny(unaligned_references)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+Future breakage diagnostic:
+error: `#[derive]` can't be used on a `#[repr(packed)]` struct with type or const parameters (error E0133)
+  --> $DIR/deriving-with-repr-packed.rs:8:23
+   |
+LL | #[derive(Copy, Clone, PartialEq, Eq)]
+   |                       ^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/deriving-with-repr-packed.rs:1:9
+   |
+LL | #![deny(unaligned_references)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+Future breakage diagnostic:
+error: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133)
+  --> $DIR/deriving-with-repr-packed.rs:16:10
+   |
+LL | #[derive(PartialEq, Eq)]
+   |          ^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/deriving-with-repr-packed.rs:1:9
+   |
+LL | #![deny(unaligned_references)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+Future breakage diagnostic:
+error: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133)
+  --> $DIR/deriving-with-repr-packed.rs:25:10
+   |
+LL | #[derive(PartialEq)]
+   |          ^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/deriving-with-repr-packed.rs:1:9
+   |
+LL | #![deny(unaligned_references)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
index dbe46704b9320224edc810d5b2488f9a5ca0deef..95b572133c5f7a5248549d12f1accfd7a322c66b 100644 (file)
@@ -2,10 +2,17 @@ error[E0308]: mismatched types
   --> $DIR/issue-42764.rs:11:43
    |
 LL |     this_function_expects_a_double_option(n);
-   |                                           ^ expected enum `DoubleOption`, found `usize`
+   |     ------------------------------------- ^ expected enum `DoubleOption`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected enum `DoubleOption<_>`
               found type `usize`
+note: function defined here
+  --> $DIR/issue-42764.rs:7:4
+   |
+LL | fn this_function_expects_a_double_option<T>(d: DoubleOption<T>) {}
+   |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^    ------------------
 help: try wrapping the expression in a variant of `DoubleOption`
    |
 LL |     this_function_expects_a_double_option(DoubleOption::FirstSome(n));
diff --git a/src/test/ui/did_you_mean/replace-impl-infer-ty-from-trait.fixed b/src/test/ui/did_you_mean/replace-impl-infer-ty-from-trait.fixed
new file mode 100644 (file)
index 0000000..4963790
--- /dev/null
@@ -0,0 +1,15 @@
+// run-rustfix
+#![allow(unused)]
+
+trait Foo<T>: Sized {
+    fn bar(i: i32, t: T, s: &Self) -> (T, i32);
+}
+
+impl Foo<usize> for () {
+    fn bar(i: i32, t: usize, s: &()) -> (usize, i32) {
+        //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
+        (1, 2)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/did_you_mean/replace-impl-infer-ty-from-trait.rs b/src/test/ui/did_you_mean/replace-impl-infer-ty-from-trait.rs
new file mode 100644 (file)
index 0000000..ddf39c9
--- /dev/null
@@ -0,0 +1,15 @@
+// run-rustfix
+#![allow(unused)]
+
+trait Foo<T>: Sized {
+    fn bar(i: i32, t: T, s: &Self) -> (T, i32);
+}
+
+impl Foo<usize> for () {
+    fn bar(i: _, t: _, s: _) -> _ {
+        //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
+        (1, 2)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/did_you_mean/replace-impl-infer-ty-from-trait.stderr b/src/test/ui/did_you_mean/replace-impl-infer-ty-from-trait.stderr
new file mode 100644 (file)
index 0000000..730836a
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/replace-impl-infer-ty-from-trait.rs:9:15
+   |
+LL |     fn bar(i: _, t: _, s: _) -> _ {
+   |               ^     ^     ^     ^ not allowed in type signatures
+   |               |     |     |
+   |               |     |     not allowed in type signatures
+   |               |     not allowed in type signatures
+   |               not allowed in type signatures
+   |
+help: try replacing `_` with the types in the corresponding trait method signature
+   |
+LL |     fn bar(i: i32, t: usize, s: &()) -> (usize, i32) {
+   |               ~~~     ~~~~~     ~~~     ~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0121`.
index 0c6bd9379f7539a1f64107e94d41b68287e27e1a..42925cfed5507f2ec6cc2e3b8fa4dc79eb20003d 100644 (file)
@@ -2,10 +2,17 @@ error[E0308]: mismatched types
   --> $DIR/disambiguate-identical-names.rs:13:10
    |
 LL |     test(&v);
-   |          ^^ expected struct `std::vec::Vec`, found struct `HashMap`
+   |     ---- ^^ expected struct `std::vec::Vec`, found struct `HashMap`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&std::vec::Vec<std::vec::Vec<u32>>`
               found reference `&HashMap<u8, u8>`
+note: function defined here
+  --> $DIR/disambiguate-identical-names.rs:6:4
+   |
+LL | fn test(_v: &Vec<Vec<u32>>) {
+   |    ^^^^ ------------------
 
 error: aborting due to previous error
 
index 31579e282896402d067d47b61d507c0921f252ae..a151b20f865b22866e7e6ed8ee906486b145f241 100644 (file)
@@ -2,17 +2,23 @@ error[E0057]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/E0057.rs:3:13
    |
 LL |     let a = f();
-   |             ^-- supplied 0 arguments
-   |             |
-   |             expected 1 argument
+   |             ^-- an argument is missing
+   |
+help: provide the argument
+   |
+LL |     let a = f({_});
+   |             ~~~~~~
 
 error[E0057]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/E0057.rs:5:13
    |
 LL |     let c = f(2, 3);
-   |             ^ -  - supplied 2 arguments
-   |             |
-   |             expected 1 argument
+   |             ^    - argument unexpected
+   |
+help: remove the extra argument
+   |
+LL |     let c = f(2);
+   |             ~~~~
 
 error: aborting due to 2 previous errors
 
index 941eb2a210bf37b0ab7c77d38f8c7c9d158d83b5..7050a1dff6c2faa54225ed4deef9d46a3626eaa6 100644 (file)
@@ -5,5 +5,4 @@
 fn main() {
     unsafe { printf(); }
     //~^ ERROR E0060
-    //~| expected at least 1 argument
 }
index c80014d14763bb420e8397e42545acbe2a8654ce..9dd649239e29f9ca1397d27fa322588314ddfb03 100644 (file)
@@ -2,15 +2,17 @@ error[E0060]: this function takes at least 1 argument but 0 arguments were suppl
   --> $DIR/E0060.rs:6:14
    |
 LL |     unsafe { printf(); }
-   |              ^^^^^^-- supplied 0 arguments
-   |              |
-   |              expected at least 1 argument
+   |              ^^^^^^-- an argument of type `*const u8` is missing
    |
 note: function defined here
   --> $DIR/E0060.rs:2:8
    |
 LL |     fn printf(_: *const u8, ...) -> u32;
    |        ^^^^^^
+help: provide the argument
+   |
+LL |     unsafe { printf({*const u8}); }
+   |              ~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
index c7b5fe4310e9328f5c7de0cb1bbbd20bc2732fa7..b6fae6c63d77a10cfe49a11793bc453b384d196b 100644 (file)
@@ -5,9 +5,7 @@ fn f2(a: u16) {}
 fn main() {
     f(0);
     //~^ ERROR E0061
-    //~| expected 2 arguments
 
     f2();
     //~^ ERROR E0061
-    //~| expected 1 argument
 }
index 98488a2d298b90182d861a9ddabd6ad3caeee7c9..f92c548f2de1f2ec67060d583fc18498d6400dd4 100644 (file)
@@ -2,29 +2,33 @@ error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/E0061.rs:6:5
    |
 LL |     f(0);
-   |     ^ - supplied 1 argument
-   |     |
-   |     expected 2 arguments
+   |     ^--- an argument of type `&str` is missing
    |
 note: function defined here
   --> $DIR/E0061.rs:1:4
    |
 LL | fn f(a: u16, b: &str) {}
    |    ^ ------  -------
+help: provide the argument
+   |
+LL |     f(0, {&str});
+   |     ~~~~~~~~~~~~
 
 error[E0061]: this function takes 1 argument but 0 arguments were supplied
-  --> $DIR/E0061.rs:10:5
+  --> $DIR/E0061.rs:9:5
    |
 LL |     f2();
-   |     ^^-- supplied 0 arguments
-   |     |
-   |     expected 1 argument
+   |     ^^-- an argument of type `u16` is missing
    |
 note: function defined here
   --> $DIR/E0061.rs:3:4
    |
 LL | fn f2(a: u16) {}
    |    ^^ ------
+help: provide the argument
+   |
+LL |     f2({u16});
+   |     ~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
index 840700c9cc6d6526c76de8063a501e21ef27af36..d369fc2a5658b28e3d8ce41d9189084fa4460f89 100644 (file)
@@ -47,4 +47,14 @@ struct Baz<'a, 'b, 'c> {
     //~| HELP remove this lifetime argument
 }
 
+pub trait T {
+    type A;
+    type B;
+}
+
+fn trait_bound_generic<I: T<u8, u16>>(_i: I) {
+    //~^ ERROR this trait takes 0 generic arguments
+    //~| HELP replace the generic bounds with the associated types
+}
+
 fn main() {}
index c90f85df967413b9ffbeae9e271d320ade216124..5ca03b45d82b3851e294cc5d8d62b2fdc6747f41 100644 (file)
@@ -128,6 +128,22 @@ note: struct defined here, with 0 lifetime parameters
 LL | struct Quux<T>(T);
    |        ^^^^
 
-error: aborting due to 9 previous errors
+error[E0107]: this trait takes 0 generic arguments but 2 generic arguments were supplied
+  --> $DIR/E0107.rs:55:27
+   |
+LL | fn trait_bound_generic<I: T<u8, u16>>(_i: I) {
+   |                           ^ expected 0 generic arguments
+   |
+note: trait defined here, with 0 generic parameters
+  --> $DIR/E0107.rs:50:11
+   |
+LL | pub trait T {
+   |           ^
+help: replace the generic bounds with the associated types
+   |
+LL | fn trait_bound_generic<I: T<A = u8, B = u16>>(_i: I) {
+   |                             ~~~~~~  ~~~~~~~
+
+error: aborting due to 10 previous errors
 
 For more information about this error, try `rustc --explain E0107`.
index cdbafff2a202bbc70e098609b28cb58660aea48a..76d9f5cc0e52a3f8cfdf2b29fd983bd08f8ed4bf 100644 (file)
@@ -1,4 +1,4 @@
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
   --> $DIR/E0117.rs:1:1
    |
 LL | impl Drop for u32 {}
diff --git a/src/test/ui/estr-subtyping.rs b/src/test/ui/estr-subtyping.rs
new file mode 100644 (file)
index 0000000..9c5825f
--- /dev/null
@@ -0,0 +1,15 @@
+fn wants_uniq(x: String) { }
+fn wants_slice(x: &str) { }
+
+fn has_uniq(x: String) {
+   wants_uniq(x);
+   wants_slice(&*x);
+}
+
+fn has_slice(x: &str) {
+   wants_uniq(x); //~ ERROR mismatched types
+   wants_slice(x);
+}
+
+fn main() {
+}
diff --git a/src/test/ui/estr-subtyping.stderr b/src/test/ui/estr-subtyping.stderr
new file mode 100644 (file)
index 0000000..adebb7d
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/estr-subtyping.rs:10:15
+   |
+LL |    wants_uniq(x);
+   |    ---------- ^- help: try using a conversion method: `.to_string()`
+   |    |          |
+   |    |          expected struct `String`, found `&str`
+   |    arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/estr-subtyping.rs:1:4
+   |
+LL | fn wants_uniq(x: String) { }
+   |    ^^^^^^^^^^ ---------
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/extern-flag/no-nounused.rs b/src/test/ui/extern-flag/no-nounused.rs
new file mode 100644 (file)
index 0000000..5ec7559
--- /dev/null
@@ -0,0 +1,6 @@
+// aux-crate:somedep=somedep.rs
+// compile-flags: -Zunstable-options -Dunused-crate-dependencies
+// edition:2018
+
+fn main() { //~ ERROR external crate `somedep` unused in `no_nounused`
+}
diff --git a/src/test/ui/extern-flag/no-nounused.stderr b/src/test/ui/extern-flag/no-nounused.stderr
new file mode 100644 (file)
index 0000000..6446c53
--- /dev/null
@@ -0,0 +1,10 @@
+error: external crate `somedep` unused in `no_nounused`: remove the dependency or add `use somedep as _;`
+  --> $DIR/no-nounused.rs:5:1
+   |
+LL | fn main() {
+   | ^
+   |
+   = note: requested on the command line with `-D unused-crate-dependencies`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/extern-flag/nounused.rs b/src/test/ui/extern-flag/nounused.rs
new file mode 100644 (file)
index 0000000..2513986
--- /dev/null
@@ -0,0 +1,7 @@
+// check-pass
+// aux-crate:nounused:somedep=somedep.rs
+// compile-flags: -Zunstable-options -Dunused-crate-dependencies
+// edition:2018
+
+fn main() {
+}
index 3f1f1006713ba46d9ffbdbee1af523e4ddfcb635..c25da900951cc658dda6fc7fe9da6c058a7685c1 100644 (file)
@@ -296,20 +296,36 @@ error[E0308]: mismatched types
   --> $DIR/ifmt-bad-arg.rs:78:32
    |
 LL |     println!("{} {:.*} {}", 1, 3.2, 4);
-   |                                ^^^ expected `usize`, found floating-point number
+   |     ---------------------------^^^----
+   |     |                          |
+   |     |                          expected `usize`, found floating-point number
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&usize`
               found reference `&{float}`
+note: associated function defined here
+  --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+   |
+LL |     pub fn from_usize(x: &usize) -> ArgumentV1<'_> {
+   |            ^^^^^^^^^^
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0308]: mismatched types
   --> $DIR/ifmt-bad-arg.rs:81:35
    |
 LL |     println!("{} {:07$.*} {}", 1, 3.2, 4);
-   |                                   ^^^ expected `usize`, found floating-point number
+   |     ------------------------------^^^----
+   |     |                             |
+   |     |                             expected `usize`, found floating-point number
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&usize`
               found reference `&{float}`
+note: associated function defined here
+  --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+   |
+LL |     pub fn from_usize(x: &usize) -> ArgumentV1<'_> {
+   |            ^^^^^^^^^^
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 36 previous errors
index 415e87b42fad23ce72e6ec12e9eb8ab38635e32f..16a0c10ea3a3a8f3d8ac7702953bbb72a0bab97b 100644 (file)
@@ -12,7 +12,7 @@ impl<T> Foo for T { /* `foo` is still default here */ }
 fn main() {
     eq(foo::<u8>, bar::<u8>);
     //~^ ERROR mismatched types
-    //~| expected fn item `fn(_) -> _ {foo::<u8>}`
+    //~| expected type `fn(_) -> _ {foo::<u8>}`
     //~| found fn item `fn(_) -> _ {bar::<u8>}`
     //~| expected fn item, found a different fn item
     //~| different `fn` items always have unique types, even if their signatures are the same
@@ -28,7 +28,7 @@ fn main() {
 
     eq(bar::<String>, bar::<Vec<u8>>);
     //~^ ERROR mismatched types
-    //~| expected fn item `fn(_) -> _ {bar::<String>}`
+    //~| expected type `fn(_) -> _ {bar::<String>}`
     //~| found fn item `fn(_) -> _ {bar::<Vec<u8>>}`
     //~| expected struct `String`, found struct `Vec`
     //~| different `fn` items always have unique types, even if their signatures are the same
@@ -45,7 +45,7 @@ fn main() {
 
     eq(foo::<u8>, bar::<u8> as fn(isize) -> isize);
     //~^ ERROR mismatched types
-    //~| expected fn item `fn(_) -> _ {foo::<u8>}`
+    //~| expected type `fn(_) -> _ {foo::<u8>}`
     //~| found fn pointer `fn(_) -> _`
     //~| expected fn item, found fn pointer
     //~| change the expected type to be function pointer
index 4bd51a668a6f7da358bd6e5a86c23d214877a7ee..1fb120eb7a77839cc708dde3f1b7b204789749bf 100644 (file)
@@ -2,60 +2,95 @@ error[E0308]: mismatched types
   --> $DIR/fn-item-type.rs:13:19
    |
 LL |     eq(foo::<u8>, bar::<u8>);
-   |                   ^^^^^^^^^ expected fn item, found a different fn item
+   |     --            ^^^^^^^^^ expected fn item, found a different fn item
+   |     |
+   |     arguments to this function are incorrect
    |
-   = note: expected fn item `fn(_) -> _ {foo::<u8>}`
-              found fn item `fn(_) -> _ {bar::<u8>}`
+   = note: expected type `fn(_) -> _ {foo::<u8>}`
+           found fn item `fn(_) -> _ {bar::<u8>}`
    = note: different `fn` items always have unique types, even if their signatures are the same
    = help: change the expected type to be function pointer `fn(isize) -> isize`
    = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo::<u8> as fn(isize) -> isize`
+note: function defined here
+  --> $DIR/fn-item-type.rs:7:4
+   |
+LL | fn eq<T>(x: T, y: T) { }
+   |    ^^    ----  ----
 
 error[E0308]: mismatched types
   --> $DIR/fn-item-type.rs:22:19
    |
 LL |     eq(foo::<u8>, foo::<i8>);
-   |                   ^^^^^^^^^ expected `u8`, found `i8`
+   |     --            ^^^^^^^^^ expected `u8`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
    |
-   = note: expected fn item `fn(_) -> _ {foo::<u8>}`
-              found fn item `fn(_) -> _ {foo::<i8>}`
+   = note: expected type `fn(_) -> _ {foo::<u8>}`
+           found fn item `fn(_) -> _ {foo::<i8>}`
    = note: different `fn` items always have unique types, even if their signatures are the same
    = help: change the expected type to be function pointer `fn(isize) -> isize`
    = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo::<u8> as fn(isize) -> isize`
+note: function defined here
+  --> $DIR/fn-item-type.rs:7:4
+   |
+LL | fn eq<T>(x: T, y: T) { }
+   |    ^^    ----  ----
 
 error[E0308]: mismatched types
   --> $DIR/fn-item-type.rs:29:23
    |
 LL |     eq(bar::<String>, bar::<Vec<u8>>);
-   |                       ^^^^^^^^^^^^^^ expected struct `String`, found struct `Vec`
+   |     --                ^^^^^^^^^^^^^^ expected struct `String`, found struct `Vec`
+   |     |
+   |     arguments to this function are incorrect
    |
-   = note: expected fn item `fn(_) -> _ {bar::<String>}`
-              found fn item `fn(_) -> _ {bar::<Vec<u8>>}`
+   = note: expected type `fn(_) -> _ {bar::<String>}`
+           found fn item `fn(_) -> _ {bar::<Vec<u8>>}`
    = note: different `fn` items always have unique types, even if their signatures are the same
    = help: change the expected type to be function pointer `fn(isize) -> isize`
    = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `bar::<String> as fn(isize) -> isize`
+note: function defined here
+  --> $DIR/fn-item-type.rs:7:4
+   |
+LL | fn eq<T>(x: T, y: T) { }
+   |    ^^    ----  ----
 
 error[E0308]: mismatched types
   --> $DIR/fn-item-type.rs:39:26
    |
 LL |     eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
-   |                          ^^^^^^^^^^^^^^^^^ expected `u8`, found `u16`
+   |     --                   ^^^^^^^^^^^^^^^^^ expected `u8`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
    |
-   = note: expected fn item `fn() {<u8 as Foo>::foo}`
-              found fn item `fn() {<u16 as Foo>::foo}`
+   = note: expected type `fn() {<u8 as Foo>::foo}`
+           found fn item `fn() {<u16 as Foo>::foo}`
    = note: different `fn` items always have unique types, even if their signatures are the same
    = help: change the expected type to be function pointer `fn()`
    = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `<u8 as Foo>::foo as fn()`
+note: function defined here
+  --> $DIR/fn-item-type.rs:7:4
+   |
+LL | fn eq<T>(x: T, y: T) { }
+   |    ^^    ----  ----
 
 error[E0308]: mismatched types
   --> $DIR/fn-item-type.rs:46:19
    |
 LL |     eq(foo::<u8>, bar::<u8> as fn(isize) -> isize);
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn item, found fn pointer
+   |     --            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn item, found fn pointer
+   |     |
+   |     arguments to this function are incorrect
    |
-   = note: expected fn item `fn(_) -> _ {foo::<u8>}`
+   = note:    expected type `fn(_) -> _ {foo::<u8>}`
            found fn pointer `fn(_) -> _`
    = help: change the expected type to be function pointer `fn(isize) -> isize`
    = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo::<u8> as fn(isize) -> isize`
+note: function defined here
+  --> $DIR/fn-item-type.rs:7:4
+   |
+LL | fn eq<T>(x: T, y: T) { }
+   |    ^^    ----  ----
 
 error: aborting due to 5 previous errors
 
index 9988acbcb73e198918e324cee34336a730b42374..92305609c835c6248b50d13477d9fd0c0cec387a 100644 (file)
@@ -1,5 +1,6 @@
 // edition:2021
 // run-pass
+// compile-flags: -Zdrop-tracking
 
 #![feature(never_type)]
 
@@ -32,7 +33,7 @@ fn never() -> Never {
 }
 
 async fn includes_never(crash: bool, x: u32) -> u32 {
-    let mut result = async { x * x }.await;
+    let result = async { x * x }.await;
     if !crash {
         return result;
     }
index 317897ae70f72c9037aa5123a067968d2d423605..1792d8db292c47ee798f144a1973477bcb6c1297 100644 (file)
@@ -2,9 +2,17 @@ error[E0261]: use of undeclared lifetime name `'x`
   --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:8:35
    |
 LL |   fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {}
-   |        -                          ^^ undeclared lifetime
-   |        |
-   |        help: consider introducing lifetime `'x` here: `<'x>`
+   |                                   ^^ undeclared lifetime
+   |
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'x` lifetime
+   |
+LL |   fn _f(arg : Box<dyn for<'x, 'a> X<Y<'x> = &'a [u32]>>) {}
+   |                           +++
+help: consider introducing lifetime `'x` here
+   |
+LL |   fn _f<'x>(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {}
+   |        ++++
 
 error[E0582]: binding for associated type `Y` references lifetime `'a`, which does not appear in the trait input types
   --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:8:33
index bf0ca8715036b130e46c9aa7da8f5d7564e65b1b..a4bb361900fe166f61a1adbc88d2d8af4f7160cb 100644 (file)
@@ -4,14 +4,19 @@ error[E0261]: use of undeclared lifetime name `'b`
 LL |         + Deref<Target = Self::Item<'b>>;
    |                                     ^^ undeclared lifetime
    |
-help: consider introducing lifetime `'b` here
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'b` lifetime
    |
-LL | trait Iterable<'b> {
-   |               ++++
+LL |         + for<'b> Deref<Target = Self::Item<'b>>;
+   |           +++++++
 help: consider introducing lifetime `'b` here
    |
 LL |     type Iter<'b, 'a>: Iterator<Item = Self::Item<'a>>
    |               +++
+help: consider introducing lifetime `'b` here
+   |
+LL | trait Iterable<'b> {
+   |               ++++
 
 error[E0261]: use of undeclared lifetime name `'undeclared`
   --> $DIR/generic_associated_type_undeclared_lifetimes.rs:11:41
@@ -21,12 +26,12 @@ LL |     fn iter<'a>(&'a self) -> Self::Iter<'undeclared>;
    |
 help: consider introducing lifetime `'undeclared` here
    |
-LL | trait Iterable<'undeclared> {
-   |               +++++++++++++
-help: consider introducing lifetime `'undeclared` here
-   |
 LL |     fn iter<'undeclared, 'a>(&'a self) -> Self::Iter<'undeclared>;
    |             ++++++++++++
+help: consider introducing lifetime `'undeclared` here
+   |
+LL | trait Iterable<'undeclared> {
+   |               +++++++++++++
 
 error: aborting due to 2 previous errors
 
index e81a5b231a0015f34f267b32f8324f04718bf61e..5725b660ab2342505f0e8aead790ab2081be77e4 100644 (file)
@@ -4,9 +4,9 @@ trait X {
     type Y<'a>;
 }
 
-fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {}
-  //~^ ERROR: use of undeclared lifetime name `'a`
-  //~| ERROR: use of undeclared lifetime name `'a`
-
+fn f(x: Box<dyn X<Y<'a> = &'a ()>>) {}
+//~^ ERROR: use of undeclared lifetime name `'a`
+//~| ERROR: use of undeclared lifetime name `'a`
+//~| ERROR: the trait `X` cannot be made into an object [E0038]
 
 fn main() {}
index abc02b33e0e6a115635876ba33c9a4cc2f998d4d..8aeda22bad75ffc1a853a844c88ccc78409a6916 100644 (file)
@@ -1,19 +1,50 @@
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/issue-67510.rs:7:21
    |
-LL | fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {}
-   |     -               ^^ undeclared lifetime
-   |     |
-   |     help: consider introducing lifetime `'a` here: `<'a>`
+LL | fn f(x: Box<dyn X<Y<'a> = &'a ()>>) {}
+   |                     ^^ undeclared lifetime
+   |
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'a` lifetime
+   |
+LL | fn f(x: Box<dyn for<'a> X<Y<'a> = &'a ()>>) {}
+   |                 +++++++
+help: consider introducing lifetime `'a` here
+   |
+LL | fn f<'a>(x: Box<dyn X<Y<'a> = &'a ()>>) {}
+   |     ++++
 
 error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/issue-67510.rs:7:26
+  --> $DIR/issue-67510.rs:7:28
+   |
+LL | fn f(x: Box<dyn X<Y<'a> = &'a ()>>) {}
+   |                            ^^ undeclared lifetime
+   |
+help: consider making the bound lifetime-generic with a new `'a` lifetime
+   |
+LL | fn f(x: Box<dyn for<'a> X<Y<'a> = &'a ()>>) {}
+   |                 +++++++
+help: consider introducing lifetime `'a` here
+   |
+LL | fn f<'a>(x: Box<dyn X<Y<'a> = &'a ()>>) {}
+   |     ++++
+
+error[E0038]: the trait `X` cannot be made into an object
+  --> $DIR/issue-67510.rs:7:13
+   |
+LL | fn f(x: Box<dyn X<Y<'a> = &'a ()>>) {}
+   |             ^^^^^^^^^^^^^^^^^^^^^ `X` 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-67510.rs:4:10
    |
-LL | fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {}
-   |     -                    ^^ undeclared lifetime
-   |     |
-   |     help: consider introducing lifetime `'a` here: `<'a>`
+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 2 previous errors
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0261`.
+Some errors have detailed explanations: E0038, E0261.
+For more information about an error, try `rustc --explain E0038`.
index 7a7d5a6c2313fbed08e806c66180b3ae643514e8..06c1efcd80b0df1ec52e304e13e30b67280a69c6 100644 (file)
@@ -4,10 +4,17 @@ error[E0308]: mismatched types
 LL | fn bug<'a, T: Fun<F<'a> = T>>(t: T) -> T::F<'a> {
    |            - this type parameter
 LL |     T::identity(())
-   |                 ^^ expected type parameter `T`, found `()`
+   |     ----------- ^^ expected type parameter `T`, found `()`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected type parameter `T`
                    found unit type `()`
+note: associated function defined here
+  --> $DIR/issue-68648-2.rs:6:8
+   |
+LL |     fn identity<'a>(t: Self::F<'a>) -> Self::F<'a> { t }
+   |        ^^^^^^^^     --------------
 
 error: aborting due to previous error
 
index ae64f9310d112912fb24bf32deaba3943153d377..448d7ec2873955bb67aaf6b7da37d509c59e3b01 100644 (file)
@@ -12,13 +12,10 @@ impl Document for DocumentImpl {
     type Cursor<'a> = DocCursorImpl<'a>;
 
     fn cursor(&self) -> Self::Cursor<'_> {
-        DocCursorImpl {
-            document: &self,
-        }
+        DocCursorImpl { document: &self }
     }
 }
 
-
 trait DocCursor<'a> {}
 
 struct DocCursorImpl<'a> {
@@ -35,7 +32,6 @@ struct Lexer<'d, Cursor>
     _phantom: std::marker::PhantomData<&'d ()>,
 }
 
-
 impl<'d, Cursor> Lexer<'d, Cursor>
 where
     Cursor: DocCursor<'d>,
@@ -44,15 +40,12 @@ pub fn from<Doc>(document: &'d Doc) -> Lexer<'d, Cursor>
     where
         Doc: Document<Cursor<'d> = Cursor>,
     {
-        Lexer {
-            cursor: document.cursor(),
-            _phantom: std::marker::PhantomData,
-        }
+        Lexer { cursor: document.cursor(), _phantom: std::marker::PhantomData }
     }
 }
 
 fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> {
-                                       //~^ ERROR: missing lifetime specifier
+    //~^ ERROR: missing lifetime specifier
     DocumentImpl {}
 }
 
index c53dbf63a3c5b98c2891a316cfa2462159fe79ef..c5f59a24057d24747704ea38c570f0d2950ecd87 100644 (file)
@@ -1,5 +1,5 @@
 error[E0106]: missing lifetime specifier
-  --> $DIR/issue-70304.rs:54:41
+  --> $DIR/issue-70304.rs:47:41
    |
 LL | fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> {
    |                                         ^^ expected named lifetime parameter
index c9603b8d1ea4a3bcebe045f1630099e1a08f51eb..240be93cf961708801d1b7af36267ba964f68485 100644 (file)
@@ -17,10 +17,17 @@ LL | impl<B> Add for A<B> where B: Add {
    |      - this type parameter
 ...
 LL |         A(self.0 + rhs.0)
-   |           ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type
+   |         - ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type
+   |         |
+   |         arguments to this struct are incorrect
    |
    = note: expected type parameter `B`
              found associated type `<B as Add>::Output`
+note: tuple struct defined here
+  --> $DIR/missing-bounds.rs:5:8
+   |
+LL | struct A<B>(B);
+   |        ^
 help: consider further restricting this bound
    |
 LL | impl<B> Add for A<B> where B: Add + Add<Output = B> {
@@ -33,10 +40,17 @@ LL | impl<B: Add> Add for C<B> {
    |      - this type parameter
 ...
 LL |         Self(self.0 + rhs.0)
-   |              ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type
+   |         ---- ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type
+   |         |
+   |         arguments to this function are incorrect
    |
    = note: expected type parameter `B`
              found associated type `<B as Add>::Output`
+note: tuple struct defined here
+  --> $DIR/missing-bounds.rs:15:8
+   |
+LL | struct C<B>(B);
+   |        ^
 help: consider further restricting this bound
    |
 LL | impl<B: Add + Add<Output = B>> Add for C<B> {
@@ -62,10 +76,17 @@ LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
    |      - this type parameter
 ...
 LL |         Self(self.0 + rhs.0)
-   |              ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type
+   |         ---- ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type
+   |         |
+   |         arguments to this function are incorrect
    |
    = note: expected type parameter `B`
              found associated type `<B as Add>::Output`
+note: tuple struct defined here
+  --> $DIR/missing-bounds.rs:35:8
+   |
+LL | struct E<B>(B);
+   |        ^
 help: consider further restricting type parameter `B`
    |
 LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B, B: Add<Output = B> {
index 909848604ec8a5048fad45f055cf8c20ac393d6c..33332e760f5823f3ec4ac018cb8f55426a43f2cb 100644 (file)
@@ -2,7 +2,9 @@ error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/generic-extern-lifetime.rs:6:26
    |
 LL |     pub fn life2<'b>(x: &'a i32, y: &'b i32);
-   |                          ^^ undeclared lifetime
+   |                  -       ^^ undeclared lifetime
+   |                  |
+   |                  help: consider introducing lifetime `'a` here: `'a,`
 
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/generic-extern-lifetime.rs:8:37
@@ -13,8 +15,12 @@ LL |     pub fn life4<'b>(x: for<'c> fn(&'a i32));
    = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
 help: consider making the type lifetime-generic with a new `'a` lifetime
    |
-LL |     pub fn life4<'b>(x: for<'c, 'a> fn(&'a i32));
-   |                               ++++
+LL |     pub fn life4<'b>(x: for<'a, 'c> fn(&'a i32));
+   |                             +++
+help: consider introducing lifetime `'a` here
+   |
+LL |     pub fn life4<'a, 'b>(x: for<'c> fn(&'a i32));
+   |                  +++
 
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/generic-extern-lifetime.rs:11:39
@@ -22,11 +28,14 @@ error[E0261]: use of undeclared lifetime name `'a`
 LL |     pub fn life7<'b>() -> for<'c> fn(&'a i32);
    |                                       ^^ undeclared lifetime
    |
-   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
 help: consider making the type lifetime-generic with a new `'a` lifetime
    |
-LL |     pub fn life7<'b>() -> for<'c, 'a> fn(&'a i32);
-   |                                 ++++
+LL |     pub fn life7<'b>() -> for<'a, 'c> fn(&'a i32);
+   |                               +++
+help: consider introducing lifetime `'a` here
+   |
+LL |     pub fn life7<'a, 'b>() -> for<'c> fn(&'a i32);
+   |                  +++
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/generics/issue-80512-param-reordering-with-defaults.rs b/src/test/ui/generics/issue-80512-param-reordering-with-defaults.rs
new file mode 100644 (file)
index 0000000..fe3e4fb
--- /dev/null
@@ -0,0 +1,4 @@
+#![crate_type = "lib"]
+
+struct S<T = (), 'a>(&'a T);
+//~^ ERROR lifetime parameters must be declared prior to type parameters
diff --git a/src/test/ui/generics/issue-80512-param-reordering-with-defaults.stderr b/src/test/ui/generics/issue-80512-param-reordering-with-defaults.stderr
new file mode 100644 (file)
index 0000000..119b1a0
--- /dev/null
@@ -0,0 +1,8 @@
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/issue-80512-param-reordering-with-defaults.rs:3:18
+   |
+LL | struct S<T = (), 'a>(&'a T);
+   |         ---------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, T = ()>`
+
+error: aborting due to previous error
+
index 2cc1c7a2e7269bec6d6ceb6d1570e6b17e1c2019..d2b3b1c2aa0e5c6c6e0f1e8b4fc4110eb5732827 100644 (file)
@@ -2,15 +2,17 @@ error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/issue-58451.rs:12:9
    |
 LL |     f(&[f()]);
-   |         ^-- supplied 0 arguments
-   |         |
-   |         expected 1 argument
+   |         ^-- an argument is missing
    |
 note: function defined here
   --> $DIR/issue-58451.rs:5:4
    |
 LL | fn f<I>(i: I)
    |    ^    ----
+help: provide the argument
+   |
+LL |     f(&[f({_})]);
+   |         ~~~~~~
 
 error: aborting due to previous error
 
index 90522a885ab90d3df8c8d0f0a905e94645a68dbf..0b7d3f1e851e385785915daa7eee142e45e1bea0 100644 (file)
@@ -2,9 +2,13 @@ error[E0726]: implicit elided lifetime not allowed here
   --> $DIR/path-elided.rs:7:18
    |
 LL | impl MyTrait for Foo {
-   |                  ^^^- help: indicate the anonymous lifetime: `<'_>`
+   |                  ^^^ expected lifetime parameter
    |
    = note: assuming a `'static` lifetime...
+help: indicate the anonymous lifetime
+   |
+LL | impl MyTrait for Foo<'_> {
+   |                     ++++
 
 error: aborting due to previous error
 
index 102d259b0c87ab5e9976df924dce3951c6448e77..c3e76d9cb5a030d3a5fa557df3ae1d6dfdb061ff 100644 (file)
@@ -1,9 +1,8 @@
 #![allow(warnings)]
 
-trait MyTrait<'a> { }
+trait MyTrait<'a> {}
 
-impl MyTrait for u32 {
-    //~^ ERROR implicit elided lifetime not allowed here
-}
+impl MyTrait for u32 {}
+//~^ ERROR implicit elided lifetime not allowed here
 
 fn main() {}
index 15bc3f106b9c48169fed5d56eb8af8fe6307fff0..412bba6be7167a2af0c5ca8cf1d8c7a9daa8b0fb 100644 (file)
@@ -1,10 +1,14 @@
 error[E0726]: implicit elided lifetime not allowed here
   --> $DIR/trait-elided.rs:5:6
    |
-LL | impl MyTrait for u32 {
-   |      ^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
+LL | impl MyTrait for u32 {}
+   |      ^^^^^^^ expected lifetime parameter
    |
    = note: assuming a `'static` lifetime...
+help: indicate the anonymous lifetime
+   |
+LL | impl MyTrait<'_> for u32 {}
+   |             ++++
 
 error: aborting due to previous error
 
index 6e02a6b2b87b4c71d6abb2010b1ebf2a97a56a23..0f855ef57927ad55856780dd5f0a212df309318e 100644 (file)
@@ -5,7 +5,9 @@ LL |   type Closure = impl Fn() -> u64;
    |                  ---------------- the expected opaque type
 ...
 LL |       Anonymous(|| {
-   |  _______________^
+   |  _____---------_^
+   | |     |
+   | |     arguments to this struct are incorrect
 LL | |         3
 LL | |     })
    | |_____^ expected closure, found a different closure
@@ -14,6 +16,11 @@ LL | |     })
                   found closure `[closure@$DIR/issue-74282.rs:8:15: 10:6]`
    = note: no two closures, even if identical, have the same type
    = help: consider boxing your closure and/or using it as a trait object
+note: tuple struct defined here
+  --> $DIR/issue-74282.rs:4:8
+   |
+LL | struct Anonymous(Closure);
+   |        ^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-74282.rs:8:5
index 9589b69491e251c19138f26223031e35b32eb66c..0059f729bae2fcb947bf9a84733533a4eeca270d 100644 (file)
@@ -82,10 +82,11 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/must_outlive_least_region_or_bound.rs:41:5
    |
+LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
+   |                                 -- help: consider adding an explicit lifetime bound...: `T: 'static +`
+...
 LL |     x
-   |     ^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
+   |     ^ ...so that the type `T` will meet its required lifetime bounds
 
 error: aborting due to 9 previous errors
 
index b1175a5952e592a7a575da8413050c2e18f3d29f..5328b077993c5ae2056c4c447e222467b492a56d 100644 (file)
@@ -1,10 +1,11 @@
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/type_parameters_captured.rs:10:5
    |
+LL | fn foo<T>(x: T) -> impl Any + 'static {
+   |        - help: consider adding an explicit lifetime bound...: `T: 'static`
+...
 LL |     x
-   |     ^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
+   |     ^ ...so that the type `T` will meet its required lifetime bounds
 
 error: aborting due to previous error
 
index dae11a702fb73aa62d3ff5a8aef4960c7ebd8684..a9adff4faded9e5f4913e204002ae3e218202ab4 100644 (file)
@@ -12,12 +12,15 @@ error[E0308]: mismatched types
   --> $DIR/indexing-requires-a-uint.rs:12:18
    |
 LL |     bar::<isize>(i);  // i should not be re-coerced back to an isize
-   |                  ^ expected `isize`, found `usize`
+   |     ------------ ^ expected `isize`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
    |
-help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit
+note: function defined here
+  --> $DIR/indexing-requires-a-uint.rs:5:8
    |
-LL |     bar::<isize>(i.try_into().unwrap());  // i should not be re-coerced back to an isize
-   |                   ++++++++++++++++++++
+LL |     fn bar<T>(_: T) {}
+   |        ^^^    ----
 
 error: aborting due to 2 previous errors
 
index 28c9afaa52c2299dbe987b84268e7e12628e5719..8ba9dacb4b21d35e6b167d62726b51c9b1326dc2 100644 (file)
@@ -2,16 +2,30 @@ error[E0308]: mismatched types
   --> $DIR/deref-suggestion.rs:8:9
    |
 LL |     foo(s);
-   |         ^- help: try using a conversion method: `.to_string()`
-   |         |
-   |         expected struct `String`, found `&String`
+   |     --- ^- help: try using a conversion method: `.to_string()`
+   |     |   |
+   |     |   expected struct `String`, found `&String`
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/deref-suggestion.rs:5:4
+   |
+LL | fn foo(_: String) {}
+   |    ^^^ ---------
 
 error[E0308]: mismatched types
   --> $DIR/deref-suggestion.rs:14:10
    |
 LL |     foo3(u);
-   |          ^ expected `u32`, found `&u32`
+   |     ---- ^ expected `u32`, found `&u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/deref-suggestion.rs:12:4
    |
+LL | fn foo3(_: u32) {}
+   |    ^^^^ ------
 help: consider dereferencing the borrow
    |
 LL |     foo3(*u);
@@ -21,8 +35,15 @@ error[E0308]: mismatched types
   --> $DIR/deref-suggestion.rs:30:9
    |
 LL |     foo(&"aaa".to_owned());
-   |         ^^^^^^^^^^^^^^^^^ expected struct `String`, found `&String`
+   |     --- ^^^^^^^^^^^^^^^^^ expected struct `String`, found `&String`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/deref-suggestion.rs:5:4
+   |
+LL | fn foo(_: String) {}
+   |    ^^^ ---------
 help: consider removing the borrow
    |
 LL -     foo(&"aaa".to_owned());
@@ -33,8 +54,15 @@ error[E0308]: mismatched types
   --> $DIR/deref-suggestion.rs:32:9
    |
 LL |     foo(&mut "aaa".to_owned());
-   |         ^^^^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&mut String`
+   |     --- ^^^^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&mut String`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/deref-suggestion.rs:5:4
    |
+LL | fn foo(_: String) {}
+   |    ^^^ ---------
 help: consider removing the borrow
    |
 LL -     foo(&mut "aaa".to_owned());
@@ -48,8 +76,15 @@ LL |     ($x:expr) => { &$x }
    |                    ^^^ expected `u32`, found `&{integer}`
 ...
 LL |     foo3(borrow!(0));
-   |          ---------- in this macro invocation
+   |     ---- ---------- in this macro invocation
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/deref-suggestion.rs:12:4
    |
+LL | fn foo3(_: u32) {}
+   |    ^^^^ ------
    = note: this error originates in the macro `borrow` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0308]: mismatched types
index fbfbffbd24e2ff79892d16733d827015a408355a..d83a1367dbfae87816981dfeeeaa02edd2d9aa67 100644 (file)
@@ -2,8 +2,15 @@ error[E0308]: mismatched types
   --> $DIR/tutorial-suffix-inference-test.rs:9:18
    |
 LL |     identity_u16(x);
-   |                  ^ expected `u16`, found `u8`
+   |     ------------ ^ expected `u16`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/tutorial-suffix-inference-test.rs:6:8
+   |
+LL |     fn identity_u16(n: u16) -> u16 { n }
+   |        ^^^^^^^^^^^^ ------
 help: you can convert a `u8` to a `u16`
    |
 LL |     identity_u16(x.into());
@@ -13,8 +20,15 @@ error[E0308]: mismatched types
   --> $DIR/tutorial-suffix-inference-test.rs:12:18
    |
 LL |     identity_u16(y);
-   |                  ^ expected `u16`, found `i32`
+   |     ------------ ^ expected `u16`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/tutorial-suffix-inference-test.rs:6:8
    |
+LL |     fn identity_u16(n: u16) -> u16 { n }
+   |        ^^^^^^^^^^^^ ------
 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());
@@ -24,8 +38,15 @@ error[E0308]: mismatched types
   --> $DIR/tutorial-suffix-inference-test.rs:21:18
    |
 LL |     identity_u16(a);
-   |                  ^ expected `u16`, found `isize`
+   |     ------------ ^ expected `u16`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/tutorial-suffix-inference-test.rs:6:8
    |
+LL |     fn identity_u16(n: u16) -> u16 { n }
+   |        ^^^^^^^^^^^^ ------
 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());
index 020585136856bd35070624c7a0e54bcb44a019fe..0de170161b514a06b0a3576a2ab9c309be34c7a3 100644 (file)
@@ -1,16 +1,20 @@
-trait Serializable<'self, T> { //~ ERROR lifetimes cannot use keyword names
-    fn serialize(val : &'self T) -> Vec<u8>; //~ ERROR lifetimes cannot use keyword names
-    fn deserialize(repr : &[u8]) -> &'self T; //~ ERROR lifetimes cannot use keyword names
+trait Serializable<'self, T> {
+    //~^ ERROR lifetimes cannot use keyword names
+    fn serialize(val: &'self T) -> Vec<u8>; //~ ERROR lifetimes cannot use keyword names
+    fn deserialize(repr: &[u8]) -> &'self T; //~ ERROR lifetimes cannot use keyword names
 }
 
-impl<'self> Serializable<str> for &'self str { //~ ERROR lifetimes cannot use keyword names
+impl<'self> Serializable<str> for &'self str {
     //~^ ERROR lifetimes cannot use keyword names
+    //~| ERROR lifetimes cannot use keyword names
     //~| ERROR implicit elided lifetime not allowed here
-    //~| ERROR the size for values of type `str` cannot be known at compilation time
-    fn serialize(val : &'self str) -> Vec<u8> { //~ ERROR lifetimes cannot use keyword names
+    //~| ERROR the size for values of type `str` cannot be known at compilation time [E0277]
+    fn serialize(val: &'self str) -> Vec<u8> {
+        //~^ ERROR lifetimes cannot use keyword names
         vec![1]
     }
-    fn deserialize(repr: &[u8]) -> &'self str { //~ ERROR lifetimes cannot use keyword names
+    fn deserialize(repr: &[u8]) -> &'self str {
+        //~^ ERROR lifetimes cannot use keyword names
         "hi"
     }
 }
index a91b3c90ebb25e3328e26e51faab9e56d3dca5f6..46b9fd541adfa59f07df1d46b90611b4cd2594c1 100644 (file)
@@ -5,51 +5,55 @@ LL | trait Serializable<'self, T> {
    |                    ^^^^^
 
 error: lifetimes cannot use keyword names
-  --> $DIR/issue-10412.rs:2:25
+  --> $DIR/issue-10412.rs:3:24
    |
-LL |     fn serialize(val : &'self T) -> Vec<u8>;
-   |                         ^^^^^
+LL |     fn serialize(val: &'self T) -> Vec<u8>;
+   |                        ^^^^^
 
 error: lifetimes cannot use keyword names
-  --> $DIR/issue-10412.rs:3:38
+  --> $DIR/issue-10412.rs:4:37
    |
-LL |     fn deserialize(repr : &[u8]) -> &'self T;
-   |                                      ^^^^^
+LL |     fn deserialize(repr: &[u8]) -> &'self T;
+   |                                     ^^^^^
 
 error: lifetimes cannot use keyword names
-  --> $DIR/issue-10412.rs:6:6
+  --> $DIR/issue-10412.rs:7:6
    |
 LL | impl<'self> Serializable<str> for &'self str {
    |      ^^^^^
 
 error: lifetimes cannot use keyword names
-  --> $DIR/issue-10412.rs:6:36
+  --> $DIR/issue-10412.rs:7:36
    |
 LL | impl<'self> Serializable<str> for &'self str {
    |                                    ^^^^^
 
 error: lifetimes cannot use keyword names
-  --> $DIR/issue-10412.rs:10:25
+  --> $DIR/issue-10412.rs:12:24
    |
-LL |     fn serialize(val : &'self str) -> Vec<u8> {
-   |                         ^^^^^
+LL |     fn serialize(val: &'self str) -> Vec<u8> {
+   |                        ^^^^^
 
 error: lifetimes cannot use keyword names
-  --> $DIR/issue-10412.rs:13:37
+  --> $DIR/issue-10412.rs:16:37
    |
 LL |     fn deserialize(repr: &[u8]) -> &'self str {
    |                                     ^^^^^
 
 error[E0726]: implicit elided lifetime not allowed here
-  --> $DIR/issue-10412.rs:6:13
+  --> $DIR/issue-10412.rs:7:13
    |
 LL | impl<'self> Serializable<str> for &'self str {
-   |             ^^^^^^^^^^^^^^^^^ help: indicate the anonymous lifetime: `Serializable<'_, str>`
+   |             ^^^^^^^^^^^^^^^^^ expected lifetime parameter
    |
    = note: assuming a `'static` lifetime...
+help: indicate the anonymous lifetime
+   |
+LL | impl<'self> Serializable<'_, str> for &'self str {
+   |                          +++
 
 error[E0277]: the size for values of type `str` cannot be known at compilation time
-  --> $DIR/issue-10412.rs:6:13
+  --> $DIR/issue-10412.rs:7:13
    |
 LL | impl<'self> Serializable<str> for &'self str {
    |             ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
index b0bafc9942ee96dd73259ac93d5e7f1f251fe021..4d8a85a139715c8b52477ae56057f036d72e57da 100644 (file)
@@ -2,10 +2,17 @@ error[E0308]: mismatched types
   --> $DIR/issue-10764.rs:4:15
    |
 LL | fn main() { f(bar) }
-   |               ^^^ expected "Rust" fn, found "C" fn
+   |             - ^^^ expected "Rust" fn, found "C" fn
+   |             |
+   |             arguments to this function are incorrect
    |
    = note: expected fn pointer `fn()`
                  found fn item `extern "C" fn() {bar}`
+note: function defined here
+  --> $DIR/issue-10764.rs:1:4
+   |
+LL | fn f(_: extern "Rust" fn()) {}
+   |    ^ ---------------------
 
 error: aborting due to previous error
 
index d6a3e758de84a61da2de5847ef67130339504d29..3a1d43310e2fc30d3b8b5992e45392d233191ca7 100644 (file)
@@ -2,13 +2,19 @@ error[E0308]: mismatched types
   --> $DIR/issue-11374.rs:26:15
    |
 LL |     c.read_to(v);
-   |               ^
-   |               |
-   |               expected `&mut [u8]`, found struct `Vec`
-   |               help: consider mutably borrowing here: `&mut v`
+   |       ------- ^
+   |       |       |
+   |       |       expected `&mut [u8]`, found struct `Vec`
+   |       |       help: consider mutably borrowing here: `&mut v`
+   |       arguments to this function are incorrect
    |
    = note: expected mutable reference `&mut [u8]`
                          found struct `Vec<_>`
+note: associated function defined here
+  --> $DIR/issue-11374.rs:13:12
+   |
+LL |     pub fn read_to(&mut self, vec: &mut [u8]) {
+   |            ^^^^^^^ ---------  --------------
 
 error: aborting due to previous error
 
index 3b89e8bc451518b1714dfd14df5a1c5603977b25..2a3d0e3457b031ca24c92378fa01b94a6054a7d1 100644 (file)
@@ -4,8 +4,16 @@ error[E0308]: mismatched types
 LL | #[bench]
    | -------- in this procedural macro expansion
 LL | fn bar(x: isize) { }
-   | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `&mut Bencher`
+   | ^^^^^^^^^^^^^^^^^^^^
+   | |
+   | expected `isize`, found `&mut Bencher`
+   | arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/issue-12997-2.rs:8:4
+   |
+LL | fn bar(x: isize) { }
+   |    ^^^ --------
    = note: this error originates in the attribute macro `bench` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index 075c92e65de820cb4c42e713e45ada488e7e7897..db6283ea11f506577305f91eabc5d5f56bec2423 100644 (file)
@@ -2,23 +2,29 @@ error[E0308]: mismatched types
   --> $DIR/issue-13359.rs:6:9
    |
 LL |     foo(1*(1 as isize));
-   |         ^^^^^^^^^^^^^^ expected `i16`, found `isize`
+   |     --- ^^^^^^^^^^^^^^ expected `i16`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
    |
-help: you can convert an `isize` to an `i16` and panic if the converted value doesn't fit
+note: function defined here
+  --> $DIR/issue-13359.rs:1:4
    |
-LL |     foo((1*(1 as isize)).try_into().unwrap());
-   |         +              +++++++++++++++++++++
+LL | fn foo(_s: i16) { }
+   |    ^^^ -------
 
 error[E0308]: mismatched types
   --> $DIR/issue-13359.rs:10:9
    |
 LL |     bar(1*(1 as usize));
-   |         ^^^^^^^^^^^^^^ expected `u32`, found `usize`
+   |     --- ^^^^^^^^^^^^^^ expected `u32`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
    |
-help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
+note: function defined here
+  --> $DIR/issue-13359.rs:3:4
    |
-LL |     bar((1*(1 as usize)).try_into().unwrap());
-   |         +              +++++++++++++++++++++
+LL | fn bar(_s: u32) { }
+   |    ^^^ -------
 
 error: aborting due to 2 previous errors
 
index 527e0225eb9761317649b3c05d619fd323e9b277..657bda5f62b3f2605ec329981c7f442a10ea130f 100644 (file)
@@ -20,13 +20,19 @@ error[E0308]: mismatched types
   --> $DIR/issue-13853.rs:37:13
    |
 LL |     iterate(graph);
-   |             ^^^^^
-   |             |
-   |             expected reference, found struct `Vec`
-   |             help: consider borrowing here: `&graph`
+   |     ------- ^^^^^
+   |     |       |
+   |     |       expected reference, found struct `Vec`
+   |     |       help: consider borrowing here: `&graph`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `Vec<Stuff>`
+note: function defined here
+  --> $DIR/issue-13853.rs:26:4
+   |
+LL | fn iterate<N: Node, G: Graph<N>>(graph: &G) {
+   |    ^^^^^^^                       ---------
 
 error: aborting due to 3 previous errors
 
index da44566d075c4c5530a9414189ea8e2cea537e2c..203dd92c9fb022953fee9b9de1825ed4da0d3e01 100644 (file)
@@ -2,8 +2,15 @@ error[E0308]: mismatched types
   --> $DIR/issue-1448-2.rs:6:24
    |
 LL |     println!("{}", foo(10i32));
-   |                        ^^^^^ expected `u32`, found `i32`
+   |                    --- ^^^^^ expected `u32`, found `i32`
+   |                    |
+   |                    arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/issue-1448-2.rs:3:4
+   |
+LL | fn foo(a: u32) -> u32 { a }
+   |    ^^^ ------
 help: change the type of the numeric literal from `i32` to `u32`
    |
 LL |     println!("{}", foo(10u32));
index 0b09751676e9c5dfb128386cc9e9bf401d938bad..660dfe9ed3d51bc7617b139fd900ba1b773f3137 100644 (file)
@@ -2,10 +2,17 @@ error[E0308]: mismatched types
   --> $DIR/issue-15783.rs:8:19
    |
 LL |     let msg = foo(x);
-   |                   ^ expected slice `[&str]`, found array `[&str; 1]`
+   |               --- ^ expected slice `[&str]`, found array `[&str; 1]`
+   |               |
+   |               arguments to this function are incorrect
    |
    = note: expected enum `Option<&[&str]>`
               found enum `Option<&[&str; 1]>`
+note: function defined here
+  --> $DIR/issue-15783.rs:1:8
+   |
+LL | pub fn foo(params: Option<&[&str]>) -> usize {
+   |        ^^^ -----------------------
 
 error: aborting due to previous error
 
index 8e4237039fad742c4b7b448238cc1da91f6e08af..294524f0b6148de09fbe98c04247f78f4dc0ad71 100644 (file)
@@ -2,15 +2,17 @@ error[E0057]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/issue-16939.rs:5:9
    |
 LL |     |t| f(t);
-   |         ^ - supplied 1 argument
-   |         |
-   |         expected 0 arguments
+   |         ^ - argument unexpected
    |
 note: associated function defined here
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
 LL |     extern "rust-call" fn call(&self, args: Args) -> Self::Output;
    |                           ^^^^
+help: remove the extra argument
+   |
+LL |     |t| f();
+   |         ~~~
 
 error: aborting due to previous error
 
index 518fc30142c9421be62eaafa861f0b3a3a5cb4bf..f26bee5ff45d0154a37873367afe0c8d3ed46a1f 100644 (file)
@@ -2,10 +2,11 @@ error[E0308]: mismatched types
   --> $DIR/issue-17033.rs:2:10
    |
 LL |     (*p)(())
-   |          ^^
-   |          |
-   |          expected `&mut ()`, found `()`
-   |          help: consider mutably borrowing here: `&mut ()`
+   |     ---- ^^
+   |     |    |
+   |     |    expected `&mut ()`, found `()`
+   |     |    help: consider mutably borrowing here: `&mut ()`
+   |     arguments to this function are incorrect
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-1866.rs b/src/test/ui/issues/issue-1866.rs
deleted file mode 100644 (file)
index caac0c5..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-// build-pass
-#![allow(dead_code)]
-#![allow(non_camel_case_types)]
-#![warn(clashing_extern_declarations)]
-
-// pretty-expanded FIXME #23616
-
-mod a {
-    pub type rust_task = usize;
-    pub mod rustrt {
-        use super::rust_task;
-        extern "C" {
-            pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
-        }
-    }
-}
-
-mod b {
-    pub type rust_task = bool;
-    pub mod rustrt {
-        use super::rust_task;
-        extern "C" {
-            pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
-        //~^ WARN `rust_task_is_unwinding` redeclared with a different signature
-        }
-    }
-}
-
-pub fn main() {}
diff --git a/src/test/ui/issues/issue-1866.stderr b/src/test/ui/issues/issue-1866.stderr
deleted file mode 100644 (file)
index 5edae48..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-warning: `rust_task_is_unwinding` redeclared with a different signature
-  --> $DIR/issue-1866.rs:23:13
-   |
-LL |             pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
-   |             ------------------------------------------------------------ `rust_task_is_unwinding` previously declared here
-...
-LL |             pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
-   |
-note: the lint level is defined here
-  --> $DIR/issue-1866.rs:4:9
-   |
-LL | #![warn(clashing_extern_declarations)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected `unsafe extern "C" fn(*const usize) -> bool`
-              found `unsafe extern "C" fn(*const bool) -> bool`
-
-warning: 1 warning emitted
-
index b10d26abe348584260c9a3c2052d1dcbbe2685e9..db228fded6e409f14a816d4390d41de561d82569 100644 (file)
@@ -2,15 +2,26 @@ error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/issue-18819.rs:16:5
    |
 LL |     print_x(X);
-   |     ^^^^^^^ - supplied 1 argument
-   |     |
-   |     expected 2 arguments
+   |     ^^^^^^^---
+   |            ||
+   |            |expected reference, found struct `X`
+   |            an argument of type `&str` is missing
    |
+   = note: expected reference `&dyn Foo<Item = bool>`
+                 found struct `X`
 note: function defined here
   --> $DIR/issue-18819.rs:11:4
    |
 LL | fn print_x(_: &dyn Foo<Item=bool>, extra: &str) {
    |    ^^^^^^^ ----------------------  -----------
+help: consider borrowing here
+   |
+LL |     print_x(&X);
+   |             ~~
+help: provide the argument
+   |
+LL |     print_x({&dyn Foo<Item = bool>}, {&str});
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-20343.rs b/src/test/ui/issues/issue-20343.rs
deleted file mode 100644 (file)
index 000b639..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// run-pass
-#![allow(unused_variables)]
-// Regression test for Issue #20343.
-
-// pretty-expanded FIXME #23616
-
-#![deny(dead_code)]
-
-struct B { b: u32 }
-struct C;
-struct D;
-
-trait T<A> { fn dummy(&self, a: A) { } }
-impl<A> T<A> for () {}
-
-impl B {
-    // test for unused code in arguments
-    fn foo(B { b }: B) -> u32 { b }
-
-    // test for unused code in return type
-    fn bar() -> C { unsafe { ::std::mem::transmute(()) } }
-
-    // test for unused code in generics
-    fn baz<A: T<D>>() {}
-}
-
-pub fn main() {
-    let b = B { b: 3 };
-    B::foo(b);
-    B::bar();
-    B::baz::<()>();
-}
index 2f931e59d594257e5ad09b7e44f84fb761b8cd9e..982a11fef80e896fd4683c5ec6d3d2111570c84d 100644 (file)
@@ -2,10 +2,17 @@ error[E0308]: mismatched types
   --> $DIR/issue-24819.rs:5:9
    |
 LL |     foo(&mut v);
-   |         ^^^^^^ expected struct `HashSet`, found struct `Vec`
+   |     --- ^^^^^^ expected struct `HashSet`, found struct `Vec`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected mutable reference `&mut HashSet<u32>`
               found mutable reference `&mut Vec<_>`
+note: function defined here
+  --> $DIR/issue-24819.rs:10:4
+   |
+LL | fn foo(h: &mut HashSet<u32>) {
+   |    ^^^ --------------------
 
 error: aborting due to previous error
 
index 78fb0491d82ddd6a548d50f4fc9d66134814a1f8..981c3abb4bae0379ab83f451f423d7f18823b389 100644 (file)
@@ -1,6 +1,6 @@
 macro_rules! some_macro {
     ($other: expr) => ({
-        $other(None) //~ NOTE supplied 1 argument
+        $other(None) //~ NOTE argument unexpected
     })
 }
 
@@ -9,5 +9,5 @@ fn some_function() {} //~ NOTE defined here
 fn main() {
     some_macro!(some_function);
     //~^ ERROR this function takes 0 arguments but 1 argument was supplied
-    //~| NOTE expected 0 arguments
+    //~| NOTE in this expansion of some_macro!
 }
index a6f1ac9286cdac1d343358bb4a1f19df10ae198a..1013518e1dad3f6b5161a1f3e446de848cf99c35 100644 (file)
@@ -2,16 +2,20 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/issue-26094.rs:10:17
    |
 LL |         $other(None)
-   |                ---- supplied 1 argument
+   |                ---- argument unexpected
 ...
 LL |     some_macro!(some_function);
-   |                 ^^^^^^^^^^^^^ expected 0 arguments
+   |                 ^^^^^^^^^^^^^
    |
 note: function defined here
   --> $DIR/issue-26094.rs:7:4
    |
 LL | fn some_function() {}
    |    ^^^^^^^^^^^^^
+help: remove the extra argument
+   |
+LL |         some_function()
+   |         ~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-29488.rs b/src/test/ui/issues/issue-29488.rs
deleted file mode 100644 (file)
index 3c9a6a8..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// run-pass
-// ignore-emscripten no threads support
-
-use std::thread;
-
-struct Foo;
-
-impl Drop for Foo {
-    fn drop(&mut self) {
-        println!("test2");
-    }
-}
-
-thread_local!(static FOO: Foo = Foo);
-
-fn main() {
-    // Off the main thread due to #28129, be sure to initialize FOO first before
-    // calling `println!`
-    thread::spawn(|| {
-        FOO.with(|_| {});
-        println!("test1");
-    }).join().unwrap();
-}
index 81d76a90eb0ac42ab2f63936e838b418dfd8ec76..7363cae8370ab26981fb163ed3d7c9de6f0ceb15 100644 (file)
@@ -2,5 +2,6 @@ fn main() {
     let needlesArr: Vec<char> = vec!['a', 'f'];
     needlesArr.iter().fold(|x, y| {
     });
-    //~^^ ERROR this function takes 2 arguments but 1 argument was supplied
+    //~^^ ERROR mismatched types
+    //~| ERROR this function takes 2 arguments but 1 argument was supplied
 }
index b93aeade95e42d37e1fba71104252081c6e74724..5bb07cfda214286eeb8b8d99877166f84d26c09d 100644 (file)
@@ -1,19 +1,34 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-3044.rs:3:35
+   |
+LL |       needlesArr.iter().fold(|x, y| {
+   |  ___________________________________^
+LL | |     });
+   | |_____^ expected closure, found `()`
+   |
+   = note: expected closure `[closure@$DIR/issue-3044.rs:3:28: 4:6]`
+            found unit type `()`
+
 error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/issue-3044.rs:3:23
    |
 LL |       needlesArr.iter().fold(|x, y| {
-   |  _______________________^^^^_-
-   | |                       |
-   | |                       expected 2 arguments
+   |  _______________________^^^^-
 LL | |     });
-   | |_____- supplied 1 argument
+   | |______- an argument is missing
    |
 note: associated function defined here
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
    |
 LL |     fn fold<B, F>(mut self, init: B, mut f: F) -> B
    |        ^^^^
+help: provide the argument
+   |
+LL ~     needlesArr.iter().fold(|x, y| {
+LL ~     }, {_});
+   |
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0061`.
+Some errors have detailed explanations: E0061, E0308.
+For more information about an error, try `rustc --explain E0061`.
diff --git a/src/test/ui/issues/issue-41776.rs b/src/test/ui/issues/issue-41776.rs
deleted file mode 100644 (file)
index 24696d8..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-fn main() {
-    include!(line!()); //~ ERROR argument must be a string literal
-}
diff --git a/src/test/ui/issues/issue-41776.stderr b/src/test/ui/issues/issue-41776.stderr
deleted file mode 100644 (file)
index e06873b..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: argument must be a string literal
-  --> $DIR/issue-41776.rs:2:14
-   |
-LL |     include!(line!());
-   |              ^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-43132.rs b/src/test/ui/issues/issue-43132.rs
deleted file mode 100644 (file)
index c886f4b..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-// run-pass
-#![allow(unused)]
-
-fn main() {
-}
-
-fn foo() {
-    let b = mk::<
-        Forward<(Box<dyn Future<Error = u32>>,)>,
-    >();
-    b.map_err(|_| ()).join();
-}
-
-fn mk<T>() -> T {
-    loop {}
-}
-
-impl<I: Future<Error = E>, E> Future for (I,) {
-    type Error = E;
-}
-
-struct Forward<T: Future> {
-    _a: T,
-}
-
-impl<T: Future> Future for Forward<T>
-where
-    T::Error: From<u32>,
-{
-    type Error = T::Error;
-}
-
-trait Future {
-    type Error;
-
-    fn map_err<F, E>(self, _: F) -> (Self, F)
-    where
-        F: FnOnce(Self::Error) -> E,
-        Self: Sized,
-    {
-        loop {}
-    }
-
-    fn join(self) -> (MaybeDone<Self>, ())
-    where
-        Self: Sized,
-    {
-        loop {}
-    }
-}
-
-impl<S: ?Sized + Future> Future for Box<S> {
-    type Error = S::Error;
-}
-
-enum MaybeDone<A: Future> {
-    _Done(A::Error),
-}
-
-impl<U, A: Future, F> Future for (A, F)
-where
-    F: FnOnce(A::Error) -> U,
-{
-    type Error = U;
-}
index 77d52f6ecab115cbe662bad998e0ac39d6d03a35..58fd1121a6b99df48ba8ede83f2735c86a66a465 100644 (file)
@@ -2,10 +2,17 @@ error[E0308]: mismatched types
   --> $DIR/issue-43420-no-over-suggest.rs:8:9
    |
 LL |     foo(&a);
-   |         ^^ expected slice `[u16]`, found struct `Vec`
+   |     --- ^^ expected slice `[u16]`, found struct `Vec`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&[u16]`
               found reference `&Vec<u8>`
+note: function defined here
+  --> $DIR/issue-43420-no-over-suggest.rs:4:4
+   |
+LL | fn foo(b: &[u16]) {}
+   |    ^^^ ---------
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-44127.rs b/src/test/ui/issues/issue-44127.rs
deleted file mode 100644 (file)
index 21b2e68..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// run-pass
-
-#![feature(decl_macro)]
-
-pub struct Foo {
-    bar: u32,
-}
-pub macro pattern($a:pat) {
-    Foo { bar: $a }
-}
-
-fn main() {
-    match (Foo { bar: 3 }) {
-        pattern!(3) => println!("Test OK"),
-        _ => unreachable!(),
-    }
-}
index 1ae97b69c6caca66254d01bc944bf79c267dc92d..70b4ca5ec496b2c49a5a150f9e74dadc6ea5dbbc 100644 (file)
@@ -2,7 +2,15 @@ error[E0308]: mismatched types
   --> $DIR/issue-4517.rs:5:9
    |
 LL |     bar(foo);
-   |         ^^^ expected `usize`, found array `[u8; 4]`
+   |     --- ^^^ expected `usize`, found array `[u8; 4]`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/issue-4517.rs:1:4
+   |
+LL | fn bar(int_param: usize) {}
+   |    ^^^ ----------------
 
 error: aborting due to previous error
 
index 2d666e2b66c25ca05e546d33b5b6f58f42e1842d..e874ded8ec54e2699d1708e6601432c19800d9a7 100644 (file)
@@ -2,19 +2,33 @@ error[E0308]: mismatched types
   --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:12:42
    |
 LL |     light_flows_our_war_of_mocking_words(behold as usize);
-   |                                          ^^^^^^^^^^^^^^^
-   |                                          |
-   |                                          expected `&usize`, found `usize`
-   |                                          help: consider borrowing here: `&(behold as usize)`
+   |     ------------------------------------ ^^^^^^^^^^^^^^^
+   |     |                                    |
+   |     |                                    expected `&usize`, found `usize`
+   |     |                                    help: consider borrowing here: `&(behold as usize)`
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:5:4
+   |
+LL | fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize {
+   |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:14:42
    |
 LL |     light_flows_our_war_of_mocking_words(with_tears + 4);
-   |                                          ^^^^^^^^^^^^^^
-   |                                          |
-   |                                          expected `&usize`, found `usize`
-   |                                          help: consider borrowing here: `&(with_tears + 4)`
+   |     ------------------------------------ ^^^^^^^^^^^^^^
+   |     |                                    |
+   |     |                                    expected `&usize`, found `usize`
+   |     |                                    help: consider borrowing here: `&(with_tears + 4)`
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:5:4
+   |
+LL | fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize {
+   |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------
 
 error: aborting due to 2 previous errors
 
index 37a42d2382d6be7b5bbd02c22a03fe01c9cf0fb7..7fd36676df8c17c15d84ab81d3609bd13661f8bb 100644 (file)
@@ -2,10 +2,17 @@ error[E0308]: mismatched types
   --> $DIR/issue-48364.rs:2:21
    |
 LL |     b"".starts_with(stringify!(foo))
-   |                     ^^^^^^^^^^^^^^^ expected slice `[u8]`, found `str`
+   |         ----------- ^^^^^^^^^^^^^^^ expected slice `[u8]`, found `str`
+   |         |
+   |         arguments to this function are incorrect
    |
    = note: expected reference `&[u8]`
               found reference `&'static str`
+note: associated function defined here
+  --> $SRC_DIR/core/src/slice/mod.rs:LL:COL
+   |
+LL |     pub fn starts_with(&self, needle: &[T]) -> bool
+   |            ^^^^^^^^^^^
    = note: this error originates in the macro `stringify` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index 03b9b91edefb2e61a582ebb2db3bf37fa03ab491..b4cebe2a68b5756d9f55805cf457c5b59e89a5c8 100644 (file)
@@ -2,15 +2,17 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/issue-4935.rs:5:13
    |
 LL | fn main() { foo(5, 6) }
-   |             ^^^ -  - supplied 2 arguments
-   |             |
-   |             expected 1 argument
+   |             ^^^    - argument unexpected
    |
 note: function defined here
   --> $DIR/issue-4935.rs:3:4
    |
 LL | fn foo(a: usize) {}
    |    ^^^ --------
+help: remove the extra argument
+   |
+LL | fn main() { foo(5) }
+   |             ~~~~~~
 
 error: aborting due to previous error
 
index 3c3428f3096a8d282912dc512fe28bd1db9c2646..f2cbc3e6feb78d761f305a63b27de263003bbf5c 100644 (file)
@@ -4,11 +4,18 @@ error[E0308]: mismatched types
 LL | fn foo<F: FnMut()>() {
    |        - this type parameter
 LL |     let _: Box<F> = Box::new(|| ());
-   |                              ^^^^^ expected type parameter `F`, found closure
+   |                     -------- ^^^^^ expected type parameter `F`, found closure
+   |                     |
+   |                     arguments to this function are incorrect
    |
    = note: expected type parameter `F`
                      found closure `[closure@$DIR/issue-51154.rs:2:30: 2:35]`
    = help: every closure has a distinct type and so could not always match the caller-chosen type of parameter `F`
+note: associated function defined here
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+   |
+LL |     pub fn new(x: T) -> Self {
+   |            ^^^
 
 error: aborting due to previous error
 
index 29c95e4fb62b89f4206e0ccf144549423b43ec29..1afff28f0b4e1dc16349d3e2ac52347908024bcd 100644 (file)
@@ -2,10 +2,17 @@ error[E0308]: mismatched types
   --> $DIR/issue-5216.rs:3:21
    |
 LL | pub static C: S = S(f);
-   |                     ^ expected struct `Box`, found fn item
+   |                   - ^ expected struct `Box`, found fn item
+   |                   |
+   |                   arguments to this struct are incorrect
    |
    = note: expected struct `Box<(dyn FnMut() + Sync + 'static)>`
              found fn item `fn() {f}`
+note: tuple struct defined here
+  --> $DIR/issue-5216.rs:2:8
+   |
+LL | struct S(Box<dyn FnMut() + Sync>);
+   |        ^
 
 error[E0308]: mismatched types
   --> $DIR/issue-5216.rs:8:19
diff --git a/src/test/ui/issues/issue-53692.rs b/src/test/ui/issues/issue-53692.rs
deleted file mode 100644 (file)
index 30f344e..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-fn main() {
-        let items = vec![1, 2, 3];
-        let ref_items: &[i32] = &items;
-        let items_clone: Vec<i32> = ref_items.clone();
-//~^ ERROR mismatched types
-
-        // in that case no suggestion will be triggered
-        let items_clone_2:Vec<i32> = items.clone();
-
-        let s = "hi";
-        let string: String = s.clone();
-//~^ ERROR mismatched types
-
-        // in that case no suggestion will be triggered
-        let s2 = "hi";
-        let string_2: String = s2.to_string();
-}
diff --git a/src/test/ui/issues/issue-53692.stderr b/src/test/ui/issues/issue-53692.stderr
deleted file mode 100644 (file)
index 09c78da..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-53692.rs:4:37
-   |
-LL |         let items_clone: Vec<i32> = ref_items.clone();
-   |                          --------   ^^^^^^^^^^^^^^^^^
-   |                          |          |
-   |                          |          expected struct `Vec`, found `&[i32]`
-   |                          |          help: try using a conversion method: `ref_items.to_vec()`
-   |                          expected due to this
-   |
-   = note: expected struct `Vec<i32>`
-           found reference `&[i32]`
-
-error[E0308]: mismatched types
-  --> $DIR/issue-53692.rs:11:30
-   |
-LL |         let string: String = s.clone();
-   |                     ------   ^^^^^^^^^
-   |                     |        |
-   |                     |        expected struct `String`, found `&str`
-   |                     |        help: try using a conversion method: `s.to_string()`
-   |                     expected due to this
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
index 2d841d28ee26d8aa478d7fb38592f77df71cdf30..2bc09234116b1171e2465b4492771242473480bc 100644 (file)
@@ -2,10 +2,17 @@ error[E0308]: mismatched types
   --> $DIR/issue-61106.rs:3:9
    |
 LL |     foo(x.clone());
-   |         ^^^^^^^^^
-   |         |
-   |         expected `&str`, found struct `String`
-   |         help: consider borrowing here: `&x`
+   |     --- ^^^^^^^^^
+   |     |   |
+   |     |   expected `&str`, found struct `String`
+   |     |   help: consider borrowing here: `&x`
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/issue-61106.rs:6:4
+   |
+LL | fn foo(_: &str) {}
+   |    ^^^ -------
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-61858.rs b/src/test/ui/issues/issue-61858.rs
deleted file mode 100644 (file)
index 6c3b565..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-fn main() {
-    (if foobar) //~ ERROR expected `{`, found `)`
-}
diff --git a/src/test/ui/issues/issue-61858.stderr b/src/test/ui/issues/issue-61858.stderr
deleted file mode 100644 (file)
index 8b95d9c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-error: expected `{`, found `)`
-  --> $DIR/issue-61858.rs:2:15
-   |
-LL |     (if foobar)
-   |      --       ^ expected `{`
-   |      |
-   |      this `if` expression has a condition, but no block
-
-error: aborting due to previous error
-
index 58e85ec700d2df9ef2f93a20fe4846e456d885e5..61ec5d3180cc3ea96f449bd5f5a6bf9e1be36008 100644 (file)
@@ -4,10 +4,17 @@ error[E0308]: mismatched types
 LL | impl<T> S0<T> {
    |      - this type parameter
 LL |     const C: S0<u8> = Self(0);
-   |                            ^ expected type parameter `T`, found integer
+   |                       ---- ^ expected type parameter `T`, found integer
+   |                       |
+   |                       arguments to this function are incorrect
    |
    = note: expected type parameter `T`
                         found type `{integer}`
+note: tuple struct defined here
+  --> $DIR/issue-69306.rs:3:8
+   |
+LL | struct S0<T>(T);
+   |        ^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-69306.rs:5:23
@@ -27,10 +34,17 @@ LL | impl<T> S0<T> {
    |      - this type parameter
 ...
 LL |         Self(0);
-   |              ^ expected type parameter `T`, found integer
+   |         ---- ^ expected type parameter `T`, found integer
+   |         |
+   |         arguments to this function are incorrect
    |
    = note: expected type parameter `T`
                         found type `{integer}`
+note: tuple struct defined here
+  --> $DIR/issue-69306.rs:3:8
+   |
+LL | struct S0<T>(T);
+   |        ^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-69306.rs:27:14
@@ -39,10 +53,17 @@ LL | impl<T> Foo<T> for <S0<T> as Fun>::Out {
    |      - this type parameter
 LL |     fn foo() {
 LL |         Self(0);
-   |              ^ expected type parameter `T`, found integer
+   |         ---- ^ expected type parameter `T`, found integer
+   |         |
+   |         arguments to this function are incorrect
    |
    = note: expected type parameter `T`
                         found type `{integer}`
+note: tuple struct defined here
+  --> $DIR/issue-69306.rs:3:8
+   |
+LL | struct S0<T>(T);
+   |        ^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-69306.rs:33:32
@@ -50,10 +71,17 @@ error[E0308]: mismatched types
 LL | impl<T> S1<T, u8> {
    |      - this type parameter
 LL |     const C: S1<u8, u8> = Self(0, 1);
-   |                                ^ expected type parameter `T`, found integer
+   |                           ---- ^ expected type parameter `T`, found integer
+   |                           |
+   |                           arguments to this function are incorrect
    |
    = note: expected type parameter `T`
                         found type `{integer}`
+note: tuple struct defined here
+  --> $DIR/issue-69306.rs:31:8
+   |
+LL | struct S1<T, U>(T, U);
+   |        ^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-69306.rs:33:27
@@ -74,12 +102,19 @@ LL | impl<T> S2<T> {
 LL |     fn map<U>(x: U) -> S2<U> {
    |            - found type parameter
 LL |         Self(x)
-   |              ^ expected type parameter `T`, found type parameter `U`
+   |         ---- ^ expected type parameter `T`, found type parameter `U`
+   |         |
+   |         arguments to this function are incorrect
    |
    = note: expected type parameter `T`
               found type parameter `U`
    = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
    = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
+note: tuple struct defined here
+  --> $DIR/issue-69306.rs:38:8
+   |
+LL | struct S2<T>(T);
+   |        ^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-69306.rs:41:9
diff --git a/src/test/ui/issues/issue-71036.rs b/src/test/ui/issues/issue-71036.rs
deleted file mode 100644 (file)
index 3d2df6f..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#![feature(unsize, dispatch_from_dyn)]
-
-use std::marker::Unsize;
-use std::ops::DispatchFromDyn;
-
-#[allow(unused)]
-struct Foo<'a, T: ?Sized> {
-    _inner: &'a &'a T,
-}
-
-impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> {}
-//~^ ERROR the trait bound `&'a T: Unsize<&'a U>` is not satisfied
-//~| NOTE the trait `Unsize<&'a U>` is not implemented for `&'a T`
-//~| NOTE all implementations of `Unsize` are provided automatically by the compiler
-//~| NOTE required because of the requirements on the impl
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-71036.stderr b/src/test/ui/issues/issue-71036.stderr
deleted file mode 100644 (file)
index db1f694..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0277]: the trait bound `&'a T: Unsize<&'a U>` is not satisfied
-  --> $DIR/issue-71036.rs:11:1
-   |
-LL | impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unsize<&'a U>` is not implemented for `&'a T`
-   |
-   = note: all implementations of `Unsize` are provided automatically by the compiler, see <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> for more information
-   = note: required because of the requirements on the impl of `DispatchFromDyn<&'a &'a U>` for `&'a &'a T`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-80512-param-reordering-with-defaults.rs b/src/test/ui/issues/issue-80512-param-reordering-with-defaults.rs
deleted file mode 100644 (file)
index fe3e4fb..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#![crate_type = "lib"]
-
-struct S<T = (), 'a>(&'a T);
-//~^ ERROR lifetime parameters must be declared prior to type parameters
diff --git a/src/test/ui/issues/issue-80512-param-reordering-with-defaults.stderr b/src/test/ui/issues/issue-80512-param-reordering-with-defaults.stderr
deleted file mode 100644 (file)
index 119b1a0..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: lifetime parameters must be declared prior to type parameters
-  --> $DIR/issue-80512-param-reordering-with-defaults.rs:3:18
-   |
-LL | struct S<T = (), 'a>(&'a T);
-   |         ---------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, T = ()>`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.rs b/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.rs
new file mode 100644 (file)
index 0000000..89387e0
--- /dev/null
@@ -0,0 +1,54 @@
+// normalize-stderr-test "pref: Align \{\n *pow2: [1-3],\n *\}" -> "pref: $$PREF_ALIGN"
+#![crate_type = "lib"]
+#![feature(rustc_attrs)]
+
+use std::mem::MaybeUninit;
+
+enum HasNiche {
+    A,
+    B,
+    C,
+}
+
+// This should result in ScalarPair(Initialized, Union),
+// since the u8 payload will be uninit for `None`.
+#[rustc_layout(debug)]
+pub enum MissingPayloadField { //~ ERROR: layout_of
+    Some(u8),
+    None
+}
+
+// This should result in ScalarPair(Initialized, Initialized),
+// since the u8 field is present in all variants,
+// and hence will always be initialized.
+#[rustc_layout(debug)]
+pub enum CommonPayloadField { //~ ERROR: layout_of
+    A(u8),
+    B(u8),
+}
+
+// This should result in ScalarPair(Initialized, Union),
+// since, though a u8-sized field is present in all variants, it might be uninit.
+#[rustc_layout(debug)]
+pub enum CommonPayloadFieldIsMaybeUninit { //~ ERROR: layout_of
+    A(u8),
+    B(MaybeUninit<u8>),
+}
+
+// This should result in ScalarPair(Initialized, Union),
+// since only the niche field (used for the tag) is guaranteed to be initialized.
+#[rustc_layout(debug)]
+pub enum NicheFirst { //~ ERROR: layout_of
+    A(HasNiche, u8),
+    B,
+    C
+}
+
+// This should result in ScalarPair(Union, Initialized),
+// since only the niche field (used for the tag) is guaranteed to be initialized.
+#[rustc_layout(debug)]
+pub enum NicheSecond { //~ ERROR: layout_of
+    A(u8, HasNiche),
+    B,
+    C,
+}
diff --git a/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr
new file mode 100644 (file)
index 0000000..46187aa
--- /dev/null
@@ -0,0 +1,720 @@
+error: layout_of(MissingPayloadField) = Layout {
+           fields: Arbitrary {
+               offsets: [
+                   Size {
+                       raw: 0,
+                   },
+               ],
+               memory_index: [
+                   0,
+               ],
+           },
+           variants: Multiple {
+               tag: Initialized {
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=1,
+               },
+               tag_encoding: Direct,
+               tag_field: 0,
+               variants: [
+                   Layout {
+                       fields: Arbitrary {
+                           offsets: [
+                               Size {
+                                   raw: 1,
+                               },
+                           ],
+                           memory_index: [
+                               0,
+                           ],
+                       },
+                       variants: Single {
+                           index: 0,
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
+                       largest_niche: None,
+                       align: AbiAndPrefAlign {
+                           abi: Align {
+                               pow2: 0,
+                           },
+                           pref: $PREF_ALIGN,
+                       },
+                       size: Size {
+                           raw: 2,
+                       },
+                   },
+                   Layout {
+                       fields: Arbitrary {
+                           offsets: [],
+                           memory_index: [],
+                       },
+                       variants: Single {
+                           index: 1,
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
+                       largest_niche: None,
+                       align: AbiAndPrefAlign {
+                           abi: Align {
+                               pow2: 0,
+                           },
+                           pref: $PREF_ALIGN,
+                       },
+                       size: Size {
+                           raw: 1,
+                       },
+                   },
+               ],
+           },
+           abi: ScalarPair(
+               Initialized {
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=1,
+               },
+               Union {
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+               },
+           ),
+           largest_niche: Some(
+               Niche {
+                   offset: Size {
+                       raw: 0,
+                   },
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=1,
+               },
+           ),
+           align: AbiAndPrefAlign {
+               abi: Align {
+                   pow2: 0,
+               },
+               pref: $PREF_ALIGN,
+           },
+           size: Size {
+               raw: 2,
+           },
+       }
+  --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:16:1
+   |
+LL | / pub enum MissingPayloadField {
+LL | |     Some(u8),
+LL | |     None
+LL | | }
+   | |_^
+
+error: layout_of(CommonPayloadField) = Layout {
+           fields: Arbitrary {
+               offsets: [
+                   Size {
+                       raw: 0,
+                   },
+               ],
+               memory_index: [
+                   0,
+               ],
+           },
+           variants: Multiple {
+               tag: Initialized {
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=1,
+               },
+               tag_encoding: Direct,
+               tag_field: 0,
+               variants: [
+                   Layout {
+                       fields: Arbitrary {
+                           offsets: [
+                               Size {
+                                   raw: 1,
+                               },
+                           ],
+                           memory_index: [
+                               0,
+                           ],
+                       },
+                       variants: Single {
+                           index: 0,
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
+                       largest_niche: None,
+                       align: AbiAndPrefAlign {
+                           abi: Align {
+                               pow2: 0,
+                           },
+                           pref: $PREF_ALIGN,
+                       },
+                       size: Size {
+                           raw: 2,
+                       },
+                   },
+                   Layout {
+                       fields: Arbitrary {
+                           offsets: [
+                               Size {
+                                   raw: 1,
+                               },
+                           ],
+                           memory_index: [
+                               0,
+                           ],
+                       },
+                       variants: Single {
+                           index: 1,
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
+                       largest_niche: None,
+                       align: AbiAndPrefAlign {
+                           abi: Align {
+                               pow2: 0,
+                           },
+                           pref: $PREF_ALIGN,
+                       },
+                       size: Size {
+                           raw: 2,
+                       },
+                   },
+               ],
+           },
+           abi: ScalarPair(
+               Initialized {
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=1,
+               },
+               Initialized {
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=255,
+               },
+           ),
+           largest_niche: Some(
+               Niche {
+                   offset: Size {
+                       raw: 0,
+                   },
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=1,
+               },
+           ),
+           align: AbiAndPrefAlign {
+               abi: Align {
+                   pow2: 0,
+               },
+               pref: $PREF_ALIGN,
+           },
+           size: Size {
+               raw: 2,
+           },
+       }
+  --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:25:1
+   |
+LL | / pub enum CommonPayloadField {
+LL | |     A(u8),
+LL | |     B(u8),
+LL | | }
+   | |_^
+
+error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout {
+           fields: Arbitrary {
+               offsets: [
+                   Size {
+                       raw: 0,
+                   },
+               ],
+               memory_index: [
+                   0,
+               ],
+           },
+           variants: Multiple {
+               tag: Initialized {
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=1,
+               },
+               tag_encoding: Direct,
+               tag_field: 0,
+               variants: [
+                   Layout {
+                       fields: Arbitrary {
+                           offsets: [
+                               Size {
+                                   raw: 1,
+                               },
+                           ],
+                           memory_index: [
+                               0,
+                           ],
+                       },
+                       variants: Single {
+                           index: 0,
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
+                       largest_niche: None,
+                       align: AbiAndPrefAlign {
+                           abi: Align {
+                               pow2: 0,
+                           },
+                           pref: $PREF_ALIGN,
+                       },
+                       size: Size {
+                           raw: 2,
+                       },
+                   },
+                   Layout {
+                       fields: Arbitrary {
+                           offsets: [
+                               Size {
+                                   raw: 1,
+                               },
+                           ],
+                           memory_index: [
+                               0,
+                           ],
+                       },
+                       variants: Single {
+                           index: 1,
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
+                       largest_niche: None,
+                       align: AbiAndPrefAlign {
+                           abi: Align {
+                               pow2: 0,
+                           },
+                           pref: $PREF_ALIGN,
+                       },
+                       size: Size {
+                           raw: 2,
+                       },
+                   },
+               ],
+           },
+           abi: ScalarPair(
+               Initialized {
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=1,
+               },
+               Union {
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+               },
+           ),
+           largest_niche: Some(
+               Niche {
+                   offset: Size {
+                       raw: 0,
+                   },
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=1,
+               },
+           ),
+           align: AbiAndPrefAlign {
+               abi: Align {
+                   pow2: 0,
+               },
+               pref: $PREF_ALIGN,
+           },
+           size: Size {
+               raw: 2,
+           },
+       }
+  --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:33:1
+   |
+LL | / pub enum CommonPayloadFieldIsMaybeUninit {
+LL | |     A(u8),
+LL | |     B(MaybeUninit<u8>),
+LL | | }
+   | |_^
+
+error: layout_of(NicheFirst) = Layout {
+           fields: Arbitrary {
+               offsets: [
+                   Size {
+                       raw: 0,
+                   },
+               ],
+               memory_index: [
+                   0,
+               ],
+           },
+           variants: Multiple {
+               tag: Initialized {
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=4,
+               },
+               tag_encoding: Niche {
+                   dataful_variant: 0,
+                   niche_variants: 1..=2,
+                   niche_start: 3,
+               },
+               tag_field: 0,
+               variants: [
+                   Layout {
+                       fields: Arbitrary {
+                           offsets: [
+                               Size {
+                                   raw: 0,
+                               },
+                               Size {
+                                   raw: 1,
+                               },
+                           ],
+                           memory_index: [
+                               0,
+                               1,
+                           ],
+                       },
+                       variants: Single {
+                           index: 0,
+                       },
+                       abi: ScalarPair(
+                           Initialized {
+                               value: Int(
+                                   I8,
+                                   false,
+                               ),
+                               valid_range: 0..=2,
+                           },
+                           Initialized {
+                               value: Int(
+                                   I8,
+                                   false,
+                               ),
+                               valid_range: 0..=255,
+                           },
+                       ),
+                       largest_niche: Some(
+                           Niche {
+                               offset: Size {
+                                   raw: 0,
+                               },
+                               value: Int(
+                                   I8,
+                                   false,
+                               ),
+                               valid_range: 0..=2,
+                           },
+                       ),
+                       align: AbiAndPrefAlign {
+                           abi: Align {
+                               pow2: 0,
+                           },
+                           pref: $PREF_ALIGN,
+                       },
+                       size: Size {
+                           raw: 2,
+                       },
+                   },
+                   Layout {
+                       fields: Arbitrary {
+                           offsets: [],
+                           memory_index: [],
+                       },
+                       variants: Single {
+                           index: 1,
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
+                       largest_niche: None,
+                       align: AbiAndPrefAlign {
+                           abi: Align {
+                               pow2: 0,
+                           },
+                           pref: $PREF_ALIGN,
+                       },
+                       size: Size {
+                           raw: 0,
+                       },
+                   },
+                   Layout {
+                       fields: Arbitrary {
+                           offsets: [],
+                           memory_index: [],
+                       },
+                       variants: Single {
+                           index: 2,
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
+                       largest_niche: None,
+                       align: AbiAndPrefAlign {
+                           abi: Align {
+                               pow2: 0,
+                           },
+                           pref: $PREF_ALIGN,
+                       },
+                       size: Size {
+                           raw: 0,
+                       },
+                   },
+               ],
+           },
+           abi: ScalarPair(
+               Initialized {
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=4,
+               },
+               Union {
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+               },
+           ),
+           largest_niche: Some(
+               Niche {
+                   offset: Size {
+                       raw: 0,
+                   },
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=4,
+               },
+           ),
+           align: AbiAndPrefAlign {
+               abi: Align {
+                   pow2: 0,
+               },
+               pref: $PREF_ALIGN,
+           },
+           size: Size {
+               raw: 2,
+           },
+       }
+  --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:41:1
+   |
+LL | / pub enum NicheFirst {
+LL | |     A(HasNiche, u8),
+LL | |     B,
+LL | |     C
+LL | | }
+   | |_^
+
+error: layout_of(NicheSecond) = Layout {
+           fields: Arbitrary {
+               offsets: [
+                   Size {
+                       raw: 1,
+                   },
+               ],
+               memory_index: [
+                   0,
+               ],
+           },
+           variants: Multiple {
+               tag: Initialized {
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=4,
+               },
+               tag_encoding: Niche {
+                   dataful_variant: 0,
+                   niche_variants: 1..=2,
+                   niche_start: 3,
+               },
+               tag_field: 0,
+               variants: [
+                   Layout {
+                       fields: Arbitrary {
+                           offsets: [
+                               Size {
+                                   raw: 0,
+                               },
+                               Size {
+                                   raw: 1,
+                               },
+                           ],
+                           memory_index: [
+                               0,
+                               1,
+                           ],
+                       },
+                       variants: Single {
+                           index: 0,
+                       },
+                       abi: ScalarPair(
+                           Initialized {
+                               value: Int(
+                                   I8,
+                                   false,
+                               ),
+                               valid_range: 0..=255,
+                           },
+                           Initialized {
+                               value: Int(
+                                   I8,
+                                   false,
+                               ),
+                               valid_range: 0..=2,
+                           },
+                       ),
+                       largest_niche: Some(
+                           Niche {
+                               offset: Size {
+                                   raw: 1,
+                               },
+                               value: Int(
+                                   I8,
+                                   false,
+                               ),
+                               valid_range: 0..=2,
+                           },
+                       ),
+                       align: AbiAndPrefAlign {
+                           abi: Align {
+                               pow2: 0,
+                           },
+                           pref: $PREF_ALIGN,
+                       },
+                       size: Size {
+                           raw: 2,
+                       },
+                   },
+                   Layout {
+                       fields: Arbitrary {
+                           offsets: [],
+                           memory_index: [],
+                       },
+                       variants: Single {
+                           index: 1,
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
+                       largest_niche: None,
+                       align: AbiAndPrefAlign {
+                           abi: Align {
+                               pow2: 0,
+                           },
+                           pref: $PREF_ALIGN,
+                       },
+                       size: Size {
+                           raw: 0,
+                       },
+                   },
+                   Layout {
+                       fields: Arbitrary {
+                           offsets: [],
+                           memory_index: [],
+                       },
+                       variants: Single {
+                           index: 2,
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
+                       largest_niche: None,
+                       align: AbiAndPrefAlign {
+                           abi: Align {
+                               pow2: 0,
+                           },
+                           pref: $PREF_ALIGN,
+                       },
+                       size: Size {
+                           raw: 0,
+                       },
+                   },
+               ],
+           },
+           abi: ScalarPair(
+               Union {
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+               },
+               Initialized {
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=4,
+               },
+           ),
+           largest_niche: Some(
+               Niche {
+                   offset: Size {
+                       raw: 1,
+                   },
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=4,
+               },
+           ),
+           align: AbiAndPrefAlign {
+               abi: Align {
+                   pow2: 0,
+               },
+               pref: $PREF_ALIGN,
+           },
+           size: Size {
+               raw: 2,
+           },
+       }
+  --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:50:1
+   |
+LL | / pub enum NicheSecond {
+LL | |     A(u8, HasNiche),
+LL | |     B,
+LL | |     C,
+LL | | }
+   | |_^
+
+error: aborting due to 5 previous errors
+
index 1b1912c8e4544d8c03d168914fb4e72cccef0e9b..6ccf008c003e4182b2f0adbd14d5084392e5ce40 100644 (file)
@@ -2,13 +2,17 @@ error: hidden lifetime parameters in types are deprecated
   --> $DIR/issue-91763.rs:8:20
    |
 LL | fn f() -> Ptr<Thing>;
-   |                    ^ expected named lifetime parameter
+   |                    ^ expected lifetime parameter
    |
 note: the lint level is defined here
   --> $DIR/issue-91763.rs:3:9
    |
 LL | #![deny(elided_lifetimes_in_paths)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+help: indicate the anonymous lifetime
+   |
+LL | fn f() -> Ptr<Thing><'_>;
+   |                     ++++
 
 error: aborting due to previous error
 
index 5509226cb1cdd83c5c8eebcc6cae3673e52a9e53..422673b361a95b2ebcdd73de1a64b8f20b83033f 100644 (file)
@@ -1,10 +1,10 @@
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/issue_74400.rs:12:5
    |
+LL | fn g<T>(data: &[T]) {
+   |      - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     f(data, identity)
-   |     ^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
+   |     ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0308]: mismatched types
   --> $DIR/issue_74400.rs:12:5
index cb459f31cd243fd14eb0683812b1c1b2847ee2b2..0d6ade41511fdcbd8766581e7b922090d1c75079 100644 (file)
@@ -9,6 +9,8 @@ LL |     a: &'b str,
 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 {
    |            - help: consider introducing lifetime `'b` here: `<'b>`
 LL |     a: &'b str,
@@ -22,12 +24,12 @@ LL |     fn foo(&'b self) {}
    |
 help: consider introducing lifetime `'b` here
    |
-LL | impl<'b> T for Test {
-   |     ++++
-help: consider introducing lifetime `'b` here
-   |
 LL |     fn foo<'b>(&'b self) {}
    |           ++++
+help: consider introducing lifetime `'b` here
+   |
+LL | impl<'b> T for Test {
+   |     ++++
 
 error: aborting due to 3 previous errors
 
index f5e8b41b1634e5e2b7046af4aab722a0f5c6fefd..ac98b5896ca7bfade498e1ebc03b64a7d1154565 100644 (file)
@@ -2,13 +2,13 @@ warning: hidden lifetime parameters in types are deprecated
   --> $DIR/allowed-by-default-lint.rs:9:12
    |
 LL | fn foo(x: &Foo) {}
-   |            ^^^ expected named lifetime parameter
+   |            ^^^ expected lifetime parameter
    |
    = note: requested on the command line with `--force-warn elided-lifetimes-in-paths`
-help: consider using the `'_` lifetime
+help: indicate the anonymous lifetime
    |
 LL | fn foo(x: &Foo<'_>) {}
-   |            ~~~~~~~
+   |               ++++
 
 warning: 1 warning emitted
 
diff --git a/src/test/ui/lint/issue-1866.rs b/src/test/ui/lint/issue-1866.rs
new file mode 100644 (file)
index 0000000..caac0c5
--- /dev/null
@@ -0,0 +1,29 @@
+// build-pass
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+#![warn(clashing_extern_declarations)]
+
+// pretty-expanded FIXME #23616
+
+mod a {
+    pub type rust_task = usize;
+    pub mod rustrt {
+        use super::rust_task;
+        extern "C" {
+            pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
+        }
+    }
+}
+
+mod b {
+    pub type rust_task = bool;
+    pub mod rustrt {
+        use super::rust_task;
+        extern "C" {
+            pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
+        //~^ WARN `rust_task_is_unwinding` redeclared with a different signature
+        }
+    }
+}
+
+pub fn main() {}
diff --git a/src/test/ui/lint/issue-1866.stderr b/src/test/ui/lint/issue-1866.stderr
new file mode 100644 (file)
index 0000000..5edae48
--- /dev/null
@@ -0,0 +1,19 @@
+warning: `rust_task_is_unwinding` redeclared with a different signature
+  --> $DIR/issue-1866.rs:23:13
+   |
+LL |             pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
+   |             ------------------------------------------------------------ `rust_task_is_unwinding` previously declared here
+...
+LL |             pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
+   |
+note: the lint level is defined here
+  --> $DIR/issue-1866.rs:4:9
+   |
+LL | #![warn(clashing_extern_declarations)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: expected `unsafe extern "C" fn(*const usize) -> bool`
+              found `unsafe extern "C" fn(*const bool) -> bool`
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/issue-20343.rs b/src/test/ui/lint/issue-20343.rs
new file mode 100644 (file)
index 0000000..000b639
--- /dev/null
@@ -0,0 +1,32 @@
+// run-pass
+#![allow(unused_variables)]
+// Regression test for Issue #20343.
+
+// pretty-expanded FIXME #23616
+
+#![deny(dead_code)]
+
+struct B { b: u32 }
+struct C;
+struct D;
+
+trait T<A> { fn dummy(&self, a: A) { } }
+impl<A> T<A> for () {}
+
+impl B {
+    // test for unused code in arguments
+    fn foo(B { b }: B) -> u32 { b }
+
+    // test for unused code in return type
+    fn bar() -> C { unsafe { ::std::mem::transmute(()) } }
+
+    // test for unused code in generics
+    fn baz<A: T<D>>() {}
+}
+
+pub fn main() {
+    let b = B { b: 3 };
+    B::foo(b);
+    B::bar();
+    B::baz::<()>();
+}
index d7f947aa0f3bc2d433d7d3a78cf8b223379f7e54..7c20608059398d6c3477476b7b41ccd895ab2a9d 100644 (file)
@@ -67,7 +67,6 @@ union TransparentUnion<T: Copy> {
    fn option_fn(x: Option<extern "C" fn()>);
    fn nonnull(x: Option<std::ptr::NonNull<u8>>);
    fn unique(x: Option<std::ptr::Unique<u8>>);
-   //~^ ERROR `extern` block uses type `Option<Unique<u8>>`
    fn nonzero_u8(x: Option<num::NonZeroU8>);
    fn nonzero_u16(x: Option<num::NonZeroU16>);
    fn nonzero_u32(x: Option<num::NonZeroU32>);
index f3991ab417752a9326d651199f77b4a496d6d376..1601bd9d62927f4fe9fa202d8c8247f43bd43115 100644 (file)
@@ -54,17 +54,8 @@ LL | |     G,
 LL | | }
    | |_^
 
-error: `extern` block uses type `Option<Unique<u8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:69:17
-   |
-LL |    fn unique(x: Option<std::ptr::Unique<u8>>);
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
-   |
-   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
-   = note: enum has no representation hint
-
 error: `extern` block uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:75:23
+  --> $DIR/lint-ctypes-enum.rs:74:23
    |
 LL |    fn nonzero_u128(x: Option<num::NonZeroU128>);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -72,7 +63,7 @@ LL |    fn nonzero_u128(x: Option<num::NonZeroU128>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:82:23
+  --> $DIR/lint-ctypes-enum.rs:81:23
    |
 LL |    fn nonzero_i128(x: Option<num::NonZeroI128>);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -80,7 +71,7 @@ LL |    fn nonzero_i128(x: Option<num::NonZeroI128>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `Option<TransparentUnion<NonZeroU8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:87:28
+  --> $DIR/lint-ctypes-enum.rs:86:28
    |
 LL |    fn transparent_union(x: Option<TransparentUnion<num::NonZeroU8>>);
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -89,7 +80,7 @@ LL |    fn transparent_union(x: Option<TransparentUnion<num::NonZeroU8>>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `Option<Rust<NonZeroU8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:89:20
+  --> $DIR/lint-ctypes-enum.rs:88:20
    |
 LL |    fn repr_rust(x: Option<Rust<num::NonZeroU8>>);
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -98,7 +89,7 @@ LL |    fn repr_rust(x: Option<Rust<num::NonZeroU8>>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<(), NonZeroI32>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:90:20
+  --> $DIR/lint-ctypes-enum.rs:89:20
    |
 LL |    fn no_result(x: Result<(), num::NonZeroI32>);
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -106,5 +97,5 @@ LL |    fn no_result(x: Result<(), num::NonZeroI32>);
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 
-error: aborting due to 9 previous errors
+error: aborting due to 8 previous errors
 
index e50d243b6ad6db566de4cae586a49cb47d3261e2..c85934aa3ba153f0f1f22dbc91c2bc2afeb61029 100644 (file)
@@ -13,7 +13,7 @@ LL | #![deny(fuzzy_provenance_casts)]
 help: use `.with_addr()` to adjust a valid pointer in the same allocation, to this address
    |
 LL |     let dangling = (...).with_addr(16_usize);
-   |                    ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++        ~
 
 error: aborting due to previous error
 
index 3690fbc904d9933927825de609ffba6f6c8b74ee..9799a05375682729832a496ced23d7957a0800a6 100644 (file)
@@ -8,4 +8,11 @@ fn main() {
 
     let addr_32bit = &x as *const u8 as u32;
     //~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
+
+    // don't add unnecessary parens in the suggestion
+    let ptr = &x as *const u8;
+    let ptr_addr = ptr as usize;
+    //~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize`
+    let ptr_addr_32bit = ptr as u32;
+    //~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
 }
index e7a6c1837bd5664112e39e568ddf11f54393f93e..05178b34b11462738b2df489f468f90d683f0b32 100644 (file)
@@ -2,7 +2,7 @@ error: under strict provenance it is considered bad style to cast pointer `*cons
   --> $DIR/lint-strict-provenance-lossy-casts.rs:6:23
    |
 LL |     let addr: usize = &x as *const u8 as usize;
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.addr()` to obtain the address of a pointer: `(&x as *const u8).addr()`
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/lint-strict-provenance-lossy-casts.rs:2:9
@@ -10,14 +10,42 @@ note: the lint level is defined here
 LL | #![deny(lossy_provenance_casts)]
    |         ^^^^^^^^^^^^^^^^^^^^^^
    = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
+help: use `.addr()` to obtain the address of a pointer
+   |
+LL |     let addr: usize = (&x as *const u8).addr();
+   |                       +               ~~~~~~~~
 
 error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
   --> $DIR/lint-strict-provenance-lossy-casts.rs:9:22
    |
 LL |     let addr_32bit = &x as *const u8 as u32;
-   |                      ^^^^^^^^^^^^^^^^^^^^^^ help: use `.addr()` to obtain the address of a pointer: `(&x as *const u8).addr() as u32`
+   |                      ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
+help: use `.addr()` to obtain the address of a pointer
+   |
+LL |     let addr_32bit = (&x as *const u8).addr() as u32;
+   |                      +               ~~~~~~~~~~~~~~~
+
+error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize`
+  --> $DIR/lint-strict-provenance-lossy-casts.rs:14:20
+   |
+LL |     let ptr_addr = ptr as usize;
+   |                    ^^^---------
+   |                       |
+   |                       help: use `.addr()` to obtain the address of a pointer: `.addr()`
+   |
+   = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
+
+error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
+  --> $DIR/lint-strict-provenance-lossy-casts.rs:16:26
+   |
+LL |     let ptr_addr_32bit = ptr as u32;
+   |                          ^^^-------
+   |                             |
+   |                             help: use `.addr()` to obtain the address of a pointer: `.addr() as u32`
    |
    = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
index b1792e2e9cbf862a1b645cc78d83ebe9d377211a..da1c740c4a3448830b1b634edbb7d61e8537235c 100644 (file)
@@ -19,9 +19,9 @@ pub struct CheaterDetectionMechanism {}
 impl fmt::Debug for CheaterDetectionMechanism {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         //~^ WARN hidden lifetime parameters in types are deprecated
-        //~| NOTE expected named lifetime parameter
+        //~| NOTE expected lifetime parameter
         //~| NOTE explicit anonymous lifetimes aid
-        //~| HELP consider using the `'_` lifetime
+        //~| HELP indicate the anonymous lifetime
         fmt.debug_struct("CheaterDetectionMechanism").finish()
     }
 }
index a692d6af703ea6104c2281f42d68cc5e4928b647..cd8412153f101475ef168d61d5c47a2755249164 100644 (file)
@@ -2,7 +2,9 @@ warning: hidden lifetime parameters in types are deprecated
   --> $DIR/reasons.rs:20:34
    |
 LL |     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-   |                                  ^^^^^^^^^ expected named lifetime parameter
+   |                             -----^^^^^^^^^
+   |                             |
+   |                             expected lifetime parameter
    |
    = note: explicit anonymous lifetimes aid reasoning about ownership
 note: the lint level is defined here
@@ -10,10 +12,10 @@ note: the lint level is defined here
    |
 LL | #![warn(elided_lifetimes_in_paths,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
-help: consider using the `'_` lifetime
+help: indicate the anonymous lifetime
    |
 LL |     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-   |                                  ~~~~~~~~~~~~~
+   |                                           ++++
 
 warning: variable `Social_exchange_psychology` should have a snake case name
   --> $DIR/reasons.rs:30:9
index 53c9380fb7efbda5d3b9ddd464208b2c39407984..ed5dd2ec0118160fc835573aa46af434791e118f 100644 (file)
@@ -82,3 +82,122 @@ LL |         let _ = &packed2.x;
 
 error: aborting due to 7 previous errors
 
+Future incompatibility report: Future breakage diagnostic:
+error: reference to packed field is unaligned
+  --> $DIR/unaligned_references.rs:22:17
+   |
+LL |         let _ = &good.ptr;
+   |                 ^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/unaligned_references.rs:1:9
+   |
+LL | #![deny(unaligned_references)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+  --> $DIR/unaligned_references.rs:24:17
+   |
+LL |         let _ = &good.data;
+   |                 ^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/unaligned_references.rs:1:9
+   |
+LL | #![deny(unaligned_references)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+  --> $DIR/unaligned_references.rs:27:17
+   |
+LL |         let _ = &good.data as *const _;
+   |                 ^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/unaligned_references.rs:1:9
+   |
+LL | #![deny(unaligned_references)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+  --> $DIR/unaligned_references.rs:29:27
+   |
+LL |         let _: *const _ = &good.data;
+   |                           ^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/unaligned_references.rs:1:9
+   |
+LL | #![deny(unaligned_references)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+  --> $DIR/unaligned_references.rs:32:17
+   |
+LL |         let _ = good.data.clone();
+   |                 ^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/unaligned_references.rs:1:9
+   |
+LL | #![deny(unaligned_references)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+  --> $DIR/unaligned_references.rs:35:17
+   |
+LL |         let _ = &good.data2[0];
+   |                 ^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/unaligned_references.rs:1:9
+   |
+LL | #![deny(unaligned_references)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+  --> $DIR/unaligned_references.rs:45:17
+   |
+LL |         let _ = &packed2.x;
+   |                 ^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/unaligned_references.rs:1:9
+   |
+LL | #![deny(unaligned_references)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
index 01e2395049df43a1353c637509448cd04c6c09f3..1262c21ee78e236381a39fecc4c703ce90f6089b 100644 (file)
@@ -29,3 +29,33 @@ LL | | }
 
 error: aborting due to previous error
 
+Future incompatibility report: Future breakage diagnostic:
+error: reference to packed field is unaligned
+  --> $DIR/unaligned_references_external_macro.rs:5:1
+   |
+LL | / unaligned_references_external_crate::mac! {
+LL | |
+LL | |     #[repr(packed)]
+LL | |     pub struct X {
+LL | |         pub field: u16
+LL | |     }
+LL | | }
+   | |_^
+   |
+note: the lint level is defined here
+  --> $DIR/unaligned_references_external_macro.rs:5:1
+   |
+LL | / unaligned_references_external_crate::mac! {
+LL | |
+LL | |     #[repr(packed)]
+LL | |     pub struct X {
+LL | |         pub field: u16
+LL | |     }
+LL | | }
+   | |_^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+   = note: this error originates in the macro `unaligned_references_external_crate::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
+
index 27c31c22311ab7736f1f5aea7a1debc7156dc271..4dc951985ae4d14a398d223b9ade6a4eb71f9bfb 100644 (file)
@@ -26,6 +26,11 @@ impl Hydrogen {
         pub fn count_neutrons(&self) -> usize { self.neutrons } //~ WARNING unreachable_pub
         pub(crate) fn count_electrons(&self) -> usize { self.electrons }
     }
+    impl Clone for Hydrogen {
+        fn clone(&self) -> Hydrogen {
+            Hydrogen { neutrons: self.neutrons, electrons: self.electrons }
+        }
+    }
 
     pub enum Helium {} //~ WARNING unreachable_pub
     pub union Lithium { c1: usize, c2: u8 } //~ WARNING unreachable_pub
index f284db80ff90fcce1bddbfeec401b80791bfdaca..6c05a030138bc04bdd72ba4b85eccc720a7d3e1f 100644 (file)
@@ -50,7 +50,7 @@ LL |         pub fn count_neutrons(&self) -> usize { self.neutrons }
    |         help: consider restricting its visibility: `pub(crate)`
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub-pub_crate.rs:30:5
+  --> $DIR/unreachable_pub-pub_crate.rs:35:5
    |
 LL |     pub enum Helium {}
    |     ---^^^^^^^^^^^^
@@ -60,7 +60,7 @@ LL |     pub enum Helium {}
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub-pub_crate.rs:31:5
+  --> $DIR/unreachable_pub-pub_crate.rs:36:5
    |
 LL |     pub union Lithium { c1: usize, c2: u8 }
    |     ---^^^^^^^^^^^^^^
@@ -70,7 +70,7 @@ LL |     pub union Lithium { c1: usize, c2: u8 }
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub-pub_crate.rs:32:5
+  --> $DIR/unreachable_pub-pub_crate.rs:37:5
    |
 LL |     pub fn beryllium() {}
    |     ---^^^^^^^^^^^^^^^
@@ -80,7 +80,7 @@ LL |     pub fn beryllium() {}
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub-pub_crate.rs:33:5
+  --> $DIR/unreachable_pub-pub_crate.rs:38:5
    |
 LL |     pub trait Boron {}
    |     ---^^^^^^^^^^^^
@@ -90,7 +90,7 @@ LL |     pub trait Boron {}
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub-pub_crate.rs:34:5
+  --> $DIR/unreachable_pub-pub_crate.rs:39:5
    |
 LL |     pub const CARBON: usize = 1;
    |     ---^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -100,7 +100,7 @@ LL |     pub const CARBON: usize = 1;
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub-pub_crate.rs:35:5
+  --> $DIR/unreachable_pub-pub_crate.rs:40:5
    |
 LL |     pub static NITROGEN: usize = 2;
    |     ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -110,7 +110,7 @@ LL |     pub static NITROGEN: usize = 2;
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub-pub_crate.rs:36:5
+  --> $DIR/unreachable_pub-pub_crate.rs:41:5
    |
 LL |     pub type Oxygen = bool;
    |     ---^^^^^^^^^^^^^^^^^^^^
@@ -120,7 +120,7 @@ LL |     pub type Oxygen = bool;
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub-pub_crate.rs:39:47
+  --> $DIR/unreachable_pub-pub_crate.rs:44:47
    |
 LL |         ($visibility: vis, $name: ident) => { $visibility struct $name {} }
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -135,7 +135,7 @@ LL |     define_empty_struct_with_visibility!(pub, Fluorine);
    = note: this warning originates in the macro `define_empty_struct_with_visibility` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub-pub_crate.rs:45:9
+  --> $DIR/unreachable_pub-pub_crate.rs:50:9
    |
 LL |         pub fn catalyze() -> bool;
    |         ---^^^^^^^^^^^^^^^^^^^^^^^
index 6bfec0ec5e8b04ef73456a6352f67a3c1180f98c..39e2b5961563087de4d246cdcf8234d19609002d 100644 (file)
@@ -22,6 +22,11 @@ impl Hydrogen {
         pub fn count_neutrons(&self) -> usize { self.neutrons } //~ WARNING unreachable_pub
         crate fn count_electrons(&self) -> usize { self.electrons }
     }
+    impl Clone for Hydrogen {
+        fn clone(&self) -> Hydrogen {
+            Hydrogen { neutrons: self.neutrons, electrons: self.electrons }
+        }
+    }
 
     pub enum Helium {} //~ WARNING unreachable_pub
     pub union Lithium { c1: usize, c2: u8 } //~ WARNING unreachable_pub
index 61c9582287c015ff13372a40eb6e8eee8c59adb8..e8e55be5a478007c9f5b22373203f9820daa20cc 100644 (file)
@@ -50,7 +50,7 @@ LL |         pub fn count_neutrons(&self) -> usize { self.neutrons }
    |         help: consider restricting its visibility: `crate`
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:26:5
+  --> $DIR/unreachable_pub.rs:31:5
    |
 LL |     pub enum Helium {}
    |     ---^^^^^^^^^^^^
@@ -60,7 +60,7 @@ LL |     pub enum Helium {}
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:27:5
+  --> $DIR/unreachable_pub.rs:32:5
    |
 LL |     pub union Lithium { c1: usize, c2: u8 }
    |     ---^^^^^^^^^^^^^^
@@ -70,7 +70,7 @@ LL |     pub union Lithium { c1: usize, c2: u8 }
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:28:5
+  --> $DIR/unreachable_pub.rs:33:5
    |
 LL |     pub fn beryllium() {}
    |     ---^^^^^^^^^^^^^^^
@@ -80,7 +80,7 @@ LL |     pub fn beryllium() {}
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:29:5
+  --> $DIR/unreachable_pub.rs:34:5
    |
 LL |     pub trait Boron {}
    |     ---^^^^^^^^^^^^
@@ -90,7 +90,7 @@ LL |     pub trait Boron {}
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:30:5
+  --> $DIR/unreachable_pub.rs:35:5
    |
 LL |     pub const CARBON: usize = 1;
    |     ---^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -100,7 +100,7 @@ LL |     pub const CARBON: usize = 1;
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:31:5
+  --> $DIR/unreachable_pub.rs:36:5
    |
 LL |     pub static NITROGEN: usize = 2;
    |     ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -110,7 +110,7 @@ LL |     pub static NITROGEN: usize = 2;
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:32:5
+  --> $DIR/unreachable_pub.rs:37:5
    |
 LL |     pub type Oxygen = bool;
    |     ---^^^^^^^^^^^^^^^^^^^^
@@ -120,7 +120,7 @@ LL |     pub type Oxygen = bool;
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:35:47
+  --> $DIR/unreachable_pub.rs:40:47
    |
 LL |         ($visibility: vis, $name: ident) => { $visibility struct $name {} }
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -135,7 +135,7 @@ LL |     define_empty_struct_with_visibility!(pub, Fluorine);
    = note: this warning originates in the macro `define_empty_struct_with_visibility` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:41:9
+  --> $DIR/unreachable_pub.rs:46:9
    |
 LL |         pub fn catalyze() -> bool;
    |         ---^^^^^^^^^^^^^^^^^^^^^^^
index a973e23e29e4c93e716fead16c726b718e8aebff..f83e192130bdb207d950b7c17b20e24db8df8805 100644 (file)
@@ -2,11 +2,21 @@ error[E0308]: mismatched types
   --> $DIR/issue-29084.rs:4:13
    |
 LL |         bar(&mut $d);
-   |             ^^^^^^^ expected `u8`, found `&mut u8`
+   |         --- ^^^^^^^ expected `u8`, found `&mut u8`
+   |         |
+   |         arguments to this function are incorrect
 ...
 LL |     foo!(0u8);
    |     --------- in this macro invocation
    |
+note: function defined here
+  --> $DIR/issue-29084.rs:3:12
+   |
+LL |         fn bar(d: u8) { }
+   |            ^^^ -----
+...
+LL |     foo!(0u8);
+   |     --------- in this macro invocation
    = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
diff --git a/src/test/ui/macros/issue-41776.rs b/src/test/ui/macros/issue-41776.rs
new file mode 100644 (file)
index 0000000..24696d8
--- /dev/null
@@ -0,0 +1,3 @@
+fn main() {
+    include!(line!()); //~ ERROR argument must be a string literal
+}
diff --git a/src/test/ui/macros/issue-41776.stderr b/src/test/ui/macros/issue-41776.stderr
new file mode 100644 (file)
index 0000000..e06873b
--- /dev/null
@@ -0,0 +1,8 @@
+error: argument must be a string literal
+  --> $DIR/issue-41776.rs:2:14
+   |
+LL |     include!(line!());
+   |              ^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/issue-44127.rs b/src/test/ui/macros/issue-44127.rs
new file mode 100644 (file)
index 0000000..21b2e68
--- /dev/null
@@ -0,0 +1,17 @@
+// run-pass
+
+#![feature(decl_macro)]
+
+pub struct Foo {
+    bar: u32,
+}
+pub macro pattern($a:pat) {
+    Foo { bar: $a }
+}
+
+fn main() {
+    match (Foo { bar: 3 }) {
+        pattern!(3) => println!("Test OK"),
+        _ => unreachable!(),
+    }
+}
index bcab76b7c6b692620ac26809ff9deff472a7a794..ffe730743241d2824c94b848c839f812b3db11e5 100644 (file)
@@ -6,7 +6,7 @@ extern crate std;
 // compile-flags: -Zunpretty=hir,typed
 // check-pass
 
-pub fn main() ({
+fn main() ({
         (if (true as bool)
                 ({ } as
                     ()) else if (let Some(a) =
diff --git a/src/test/ui/methods/issues/issue-90315.rs b/src/test/ui/methods/issues/issue-90315.rs
new file mode 100644 (file)
index 0000000..01bf9f4
--- /dev/null
@@ -0,0 +1,7 @@
+fn main() {
+  let arr = &[0,1,2,3];
+  for _i in 0..arr.len().rev() { //~ERROR not an iterator
+     // The above error used to say “the method `rev` exists for type `usize`”.
+     // This regression test ensures it doesn't say that any more.
+  }
+}
diff --git a/src/test/ui/methods/issues/issue-90315.stderr b/src/test/ui/methods/issues/issue-90315.stderr
new file mode 100644 (file)
index 0000000..c6a76c9
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0599]: `usize` is not an iterator
+  --> $DIR/issue-90315.rs:3:26
+   |
+LL |   for _i in 0..arr.len().rev() {
+   |                          ^^^ `usize` is not an iterator
+   |
+   = note: the following trait bounds were not satisfied:
+           `usize: Iterator`
+           which is required by `&mut usize: Iterator`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
index c410e076dde2655babda04452050473b7cdc44d2..53e582f7f13a4ecb819c2d81ee4879aec4b4cd1d 100644 (file)
@@ -2,43 +2,49 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/method-call-err-msg.rs:13:7
    |
 LL |     x.zero(0)
-   |       ^^^^ - supplied 1 argument
-   |       |
-   |       expected 0 arguments
+   |       ^^^^ - argument unexpected
    |
 note: associated function defined here
   --> $DIR/method-call-err-msg.rs:5:8
    |
 LL |     fn zero(self) -> Foo { self }
    |        ^^^^ ----
+help: remove the extra argument
+   |
+LL |     x.zero()
+   |       ~~~~~~
 
 error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/method-call-err-msg.rs:14:7
    |
 LL |      .one()
-   |       ^^^- supplied 0 arguments
-   |       |
-   |       expected 1 argument
+   |       ^^^-- an argument of type `isize` is missing
    |
 note: associated function defined here
   --> $DIR/method-call-err-msg.rs:6:8
    |
 LL |     fn one(self, _: isize) -> Foo { self }
    |        ^^^ ----  --------
+help: provide the argument
+   |
+LL |      .one({isize})
+   |       ~~~~~~~~~~~~
 
 error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/method-call-err-msg.rs:15:7
    |
 LL |      .two(0);
-   |       ^^^ - supplied 1 argument
-   |       |
-   |       expected 2 arguments
+   |       ^^^--- an argument of type `isize` is missing
    |
 note: associated function defined here
   --> $DIR/method-call-err-msg.rs:7:8
    |
 LL |     fn two(self, _: isize, _: isize) -> Foo { self }
    |        ^^^ ----  --------  --------
+help: provide the argument
+   |
+LL |      .two(0, {isize});
+   |       ~~~~~~~~~~~~~~~
 
 error[E0599]: `Foo` is not an iterator
   --> $DIR/method-call-err-msg.rs:19:7
@@ -74,15 +80,17 @@ error[E0061]: this function takes 3 arguments but 0 arguments were supplied
   --> $DIR/method-call-err-msg.rs:21:7
    |
 LL |     y.three::<usize>();
-   |       ^^^^^--------- supplied 0 arguments
-   |       |
-   |       expected 3 arguments
+   |       ^^^^^^^^^^^^^^-- three arguments of type `usize`, `usize`, and `usize` are missing
    |
 note: associated function defined here
   --> $DIR/method-call-err-msg.rs:8:8
    |
 LL |     fn three<T>(self, _: T, _: T, _: T) -> Foo { self }
    |        ^^^^^    ----  ----  ----  ----
+help: provide the arguments
+   |
+LL |     y.three::<usize>({usize}, {usize}, {usize});
+   |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 5 previous errors
 
index d16ba3df47b63de0fa78d120adab7aa840d5b8cd..ba7231070a0f428697d74e17a9b7bf1eda0a0a3e 100644 (file)
@@ -1,3 +1,6 @@
 fn main() {
-    0.clone::<'a>(); //~ ERROR use of undeclared lifetime name `'a`
+    0.clone::<'a>();
+    //~^ ERROR use of undeclared lifetime name `'a`
+    //~| WARN cannot specify lifetime arguments explicitly if late bound
+    //~| WARN this was previously accepted by the compiler
 }
index c9f235c4f7df7509b14b4aa93e065ec2670e2dc6..78af19586a1b7751168243c4883e2bdf735310a2 100644 (file)
@@ -6,6 +6,21 @@ LL | fn main() {
 LL |     0.clone::<'a>();
    |               ^^ undeclared lifetime
 
-error: aborting due to previous error
+warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-unresolved.rs:2:15
+   |
+LL |     0.clone::<'a>();
+   |               ^^
+   |
+  ::: $SRC_DIR/core/src/clone.rs:LL:COL
+   |
+LL |     fn clone(&self) -> Self;
+   |              - the late bound lifetime parameter is introduced here
+   |
+   = note: `#[warn(late_bound_lifetime_arguments)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0261`.
index 17ea61fc4bddb5de20986d94d26c54273c074d4f..01fec6fcaaeece48207829be7ef86e1ea118c0d4 100644 (file)
@@ -2,19 +2,33 @@ error[E0308]: mismatched types
   --> $DIR/method-self-arg-1.rs:11:14
    |
 LL |     Foo::bar(x);
-   |              ^
-   |              |
-   |              expected `&Foo`, found struct `Foo`
-   |              help: consider borrowing here: `&x`
+   |     -------- ^
+   |     |        |
+   |     |        expected `&Foo`, found struct `Foo`
+   |     |        help: consider borrowing here: `&x`
+   |     arguments to this function are incorrect
+   |
+note: associated function defined here
+  --> $DIR/method-self-arg-1.rs:6:8
+   |
+LL |     fn bar(&self) {}
+   |        ^^^ -----
 
 error[E0308]: mismatched types
   --> $DIR/method-self-arg-1.rs:13:14
    |
 LL |     Foo::bar(&42);
-   |              ^^^ expected struct `Foo`, found integer
+   |     -------- ^^^ expected struct `Foo`, found integer
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&Foo`
               found reference `&{integer}`
+note: associated function defined here
+  --> $DIR/method-self-arg-1.rs:6:8
+   |
+LL |     fn bar(&self) {}
+   |        ^^^ -----
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/mir/issue-95978-validator-lifetime-comparison.rs b/src/test/ui/mir/issue-95978-validator-lifetime-comparison.rs
new file mode 100644 (file)
index 0000000..cd6c5bf
--- /dev/null
@@ -0,0 +1,10 @@
+// check-pass
+// compile-flags: -Zvalidate-mir
+
+fn foo(_a: &str) {}
+
+fn main() {
+    let x = foo as fn(&'static str);
+
+    let _ = x == foo;
+}
index da8a976daaf1a77f4037e1b8b35f981f51aabe2e..579a5b7ecb98ceec6f58c6b28aa1e726b38a7532 100644 (file)
@@ -1,17 +1,20 @@
 error[E0308]: mismatched types
   --> $DIR/issue-26480.rs:16:19
    |
+LL |             write(stdout, $arr.as_ptr() as *const i8,
+   |             ----- arguments to this function are incorrect
 LL |                   $arr.len() * size_of($arr[0]));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found `usize`
 ...
 LL |     write!(hello);
    |     ------------- in this macro invocation
    |
-   = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit
+note: function defined here
+  --> $DIR/issue-26480.rs:2:8
    |
-LL |                   ($arr.len() * size_of($arr[0])).try_into().unwrap());
-   |                   +                             +++++++++++++++++++++
+LL |     fn write(fildes: i32, buf: *const i8, nbyte: u64) -> i64;
+   |        ^^^^^
+   = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0605]: non-primitive cast: `{integer}` as `()`
   --> $DIR/issue-26480.rs:22:19
index 9f4e4398984aed92cd5507aafdb11c567b9f0964..f0dea75001c2ce7cca6ffd46cfd5bc822a8f8323 100644 (file)
@@ -5,7 +5,9 @@ LL | impl<bool> Parser<bool> for bool {
    |      ---- this type parameter
 LL |     fn parse(text: &str) -> Option<bool> {
 LL |         Some(true)
-   |              ^^^^ expected type parameter `bool`, found `bool`
+   |         ---- ^^^^ expected type parameter `bool`, found `bool`
+   |         |
+   |         arguments to this enum variant are incorrect
    |
    = note: expected type parameter `bool` (type parameter `bool`)
                         found type `bool` (`bool`)
index 55e45a8f1625a6aa2d0d2b66e36f1e37038bc3f9..fcf3eccbcba2be9b2cbcd90bf2c36149bf369667 100644 (file)
@@ -2,8 +2,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-literal-cast.rs:6:9
    |
 LL |     foo(1u8);
-   |         ^^^ expected `u16`, found `u8`
+   |     --- ^^^ expected `u16`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-literal-cast.rs:1:4
+   |
+LL | fn foo(_: u16) {}
+   |    ^^^ ------
 help: change the type of the numeric literal from `u8` to `u16`
    |
 LL |     foo(1u16);
@@ -13,8 +20,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-literal-cast.rs:8:10
    |
 LL |     foo1(2f32);
-   |          ^^^^ expected `f64`, found `f32`
+   |     ---- ^^^^ expected `f64`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-literal-cast.rs:2:4
    |
+LL | fn foo1(_: f64) {}
+   |    ^^^^ ------
 help: change the type of the numeric literal from `f32` to `f64`
    |
 LL |     foo1(2f64);
@@ -24,8 +38,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-literal-cast.rs:10:10
    |
 LL |     foo2(3i16);
-   |          ^^^^ expected `i32`, found `i16`
+   |     ---- ^^^^ expected `i32`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-literal-cast.rs:3:4
    |
+LL | fn foo2(_: i32) {}
+   |    ^^^^ ------
 help: change the type of the numeric literal from `i16` to `i32`
    |
 LL |     foo2(3i32);
index d62625faaaa083b1bf6a907ecfb645c72768c263..902a6ec81d60b9cd87d328c50e1a3c89f6495382 100644 (file)
@@ -30,5 +30,4 @@ fn main() {
     //~^ ERROR this function takes 1 argument but 0 arguments were supplied
     let ans = s("burma", "shave");
     //~^ ERROR this function takes 1 argument but 2 arguments were supplied
-    //~| ERROR mismatched types
 }
index 9ae9c474162d94c4c221b4b312260253a781af40..a5742d6fe8c36e9e9ef85f90e76c28d906b3764b 100644 (file)
@@ -2,43 +2,51 @@ error[E0308]: mismatched types
   --> $DIR/overloaded-calls-bad.rs:28:17
    |
 LL |     let ans = s("what");
-   |                 ^^^^^^ expected `isize`, found `&str`
+   |               - ^^^^^^ expected `isize`, found `&str`
+   |               |
+   |               arguments to this function are incorrect
+   |
+note: associated function defined here
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL |     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
+   |                           ^^^^^^^^
 
 error[E0057]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/overloaded-calls-bad.rs:29:15
    |
 LL |     let ans = s();
-   |               ^-- supplied 0 arguments
-   |               |
-   |               expected 1 argument
+   |               ^-- an argument of type `isize` is missing
    |
 note: associated function defined here
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
 LL |     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
    |                           ^^^^^^^^
-
-error[E0308]: mismatched types
-  --> $DIR/overloaded-calls-bad.rs:31:17
+help: provide the argument
    |
-LL |     let ans = s("burma", "shave");
-   |                 ^^^^^^^ expected `isize`, found `&str`
+LL |     let ans = s({isize});
+   |               ~~~~~~~~~~
 
 error[E0057]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/overloaded-calls-bad.rs:31:15
    |
 LL |     let ans = s("burma", "shave");
-   |               ^ -------  ------- supplied 2 arguments
-   |               |
-   |               expected 1 argument
+   |               ^ -------  ------- argument unexpected
+   |                 |
+   |                 expected `isize`, found `&str`
    |
 note: associated function defined here
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
 LL |     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
    |                           ^^^^^^^^
+help: remove the extra argument
+   |
+LL |     let ans = s({isize});
+   |               ~~~~~~~~~~
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0057, E0308.
 For more information about an error, try `rustc --explain E0057`.
index 485fae6d4d9ff36c731df41a3c65b3af965db222..80aef7fcbe8e2fcd785f219e9a857e52961b7d2d 100644 (file)
@@ -2,10 +2,17 @@ error[E0308]: mismatched types
   --> $DIR/trait-bounds-cant-coerce.rs:13:7
    |
 LL |     a(x);
-   |       ^ expected trait `Foo + Send`, found trait `Foo`
+   |     - ^ expected trait `Foo + Send`, found trait `Foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Box<(dyn Foo + Send + 'static)>`
               found struct `Box<(dyn Foo + 'static)>`
+note: function defined here
+  --> $DIR/trait-bounds-cant-coerce.rs:5:4
+   |
+LL | fn a(_x: Box<dyn Foo + Send>) {
+   |    ^ -----------------------
 
 error: aborting due to previous error
 
index b77813f8af0b4a5b590401bb6e80b5f1316db9d1..ee739d6286a51d632330f3d7275a1e8c4a8e8b64 100644 (file)
@@ -2,13 +2,19 @@ error[E0308]: mismatched types
   --> $DIR/mut-cross-borrowing.rs:7:7
    |
 LL |     f(x)
-   |       ^
-   |       |
-   |       expected `&mut isize`, found struct `Box`
-   |       help: consider mutably borrowing here: `&mut x`
+   |     - ^
+   |     | |
+   |     | expected `&mut isize`, found struct `Box`
+   |     | help: consider mutably borrowing here: `&mut x`
+   |     arguments to this function are incorrect
    |
    = note: expected mutable reference `&mut isize`
                          found struct `Box<{integer}>`
+note: function defined here
+  --> $DIR/mut-cross-borrowing.rs:1:4
+   |
+LL | fn f(_: &mut isize) {}
+   |    ^ -------------
 
 error: aborting due to previous error
 
index eacef1dc3302d1facfca65bfafd225ba632fa782..fa3db33c9606f1d38aafd0c47c40ed0abd754ca4 100644 (file)
@@ -2,10 +2,17 @@ error[E0308]: mismatched types
   --> $DIR/call-fn-never-arg-wrong-type.rs:10:9
    |
 LL |     foo("wow");
-   |         ^^^^^ expected `!`, found `&str`
+   |     --- ^^^^^ expected `!`, found `&str`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note:   expected type `!`
            found reference `&'static str`
+note: function defined here
+  --> $DIR/call-fn-never-arg-wrong-type.rs:5:4
+   |
+LL | fn foo(x: !) -> ! {
+   |    ^^^ ----
 
 error: aborting due to previous error
 
index 8c1755205f0253b82f6026b5d05f2508c4d831f0..c2079a19d0a58059b03637f4d7009c7292d42808 100644 (file)
@@ -47,8 +47,8 @@ LL |     [(); { for _ in 0usize.. {}; 0}];
 note: impl defined here, but it is not `const`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    |
-LL | impl<I: Iterator> IntoIterator for I {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<I: ~const Iterator> const IntoIterator for I {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
 error[E0658]: mutable references are not allowed in constants
index 4b860a55057b641bba925136020285f983717b74..b6856089a84f9f18abde1af4766d301da898b536 100644 (file)
@@ -36,6 +36,9 @@ LL | | }
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/propagate-from-trait-match.rs:32:36
    |
+LL |   fn supply<'a, T>(value: T)
+   |                 - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
 LL |       establish_relationships(value, |value| {
    |  ____________________________________^
 LL | |
@@ -44,9 +47,7 @@ LL | |         // This function call requires that
 ...  |
 LL | |         require(value);
 LL | |     });
-   | |_____^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
+   | |_____^ ...so that the type `T` will meet its required lifetime bounds
 
 error: aborting due to previous error
 
index 31ee540cce9f70ccf63bcd4f9baed4e8f5276ae7..3d4cfc1610a6690757a8768e2e3249b11974756d 100644 (file)
@@ -1,18 +1,20 @@
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/impl-trait-outlives.rs:11:5
    |
+LL | fn no_region<'a, T>(x: Box<T>) -> impl Debug + 'a
+   |                  - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
 LL |     x
-   |     ^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
+   |     ^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/impl-trait-outlives.rs:26:5
    |
+LL | fn wrong_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a
+   |                         - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
 LL |     x
-   |     ^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
+   |     ^ ...so that the type `T` will meet its required lifetime bounds
 
 error: aborting due to 2 previous errors
 
index 9f0c60c1e1705a34424e546f32cc55a44bdb440f..cc5aa1eb11ec039c74e920ef179154efb7f0ca3c 100644 (file)
@@ -1,10 +1,10 @@
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/projection-implied-bounds.rs:30:18
    |
+LL | fn generic2<T: Iterator>(value: T) {
+   |             -- help: consider adding an explicit lifetime bound...: `T: 'static +`
 LL |     twice(value, |value_ref, item| invoke2(value_ref, item));
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error: aborting due to previous error
 
index 983d6a06afada75c7edffd8500d13cacbf15bc7b..8fe25181da1a035c8a7572ee0cebd352861123f7 100644 (file)
@@ -33,6 +33,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
+   = note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
 
 note: external requirements
   --> $DIR/projection-no-regions-closure.rs:34:23
@@ -96,6 +97,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
+   = note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
 
 note: external requirements
   --> $DIR/projection-no-regions-closure.rs:52:23
index c4df04b99b525723d345fab4a41d07f694370a53..e0ff544fe471333a384714d69ea6b372a1c765c3 100644 (file)
@@ -5,6 +5,7 @@ LL |     Box::new(x.next())
    |     ^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
+   = note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
 
 error[E0309]: the associated type `<T as Iterator>::Item` may not live long enough
   --> $DIR/projection-no-regions-fn.rs:28:5
@@ -13,6 +14,7 @@ LL |     Box::new(x.next())
    |     ^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
+   = note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
 
 error: aborting due to 2 previous errors
 
index 2513b0bfccbf188d3ffbb2a71b47e4f8a1cca0fb..62db6dd845a28165709c3960c5f6540ae74cdbe5 100644 (file)
@@ -31,10 +31,11 @@ LL | | }
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/projection-one-region-closure.rs:45:29
    |
+LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+   |                                  - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error: lifetime may not live long enough
   --> $DIR/projection-one-region-closure.rs:45:39
@@ -81,10 +82,11 @@ LL | | }
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/projection-one-region-closure.rs:56:29
    |
+LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+   |                                   - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error: lifetime may not live long enough
   --> $DIR/projection-one-region-closure.rs:56:39
index 4e0155bdf2cd0388280d8d990de511180657d498..1ee788b40ab9ea296f965e32b8d523dc5801c150 100644 (file)
@@ -34,6 +34,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType: 'a`...
+   = note: ...so that the type `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType` will meet its required lifetime bounds
 
 note: external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:48:29
@@ -70,6 +71,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType: 'a`...
+   = note: ...so that the type `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType` will meet its required lifetime bounds
 
 note: external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:61:29
index 3a84cbfbedc09b7b306697fb491a742834e09b3d..b4435fe06bccca5de87f1d50a99492fd9468cb19 100644 (file)
@@ -5,6 +5,7 @@ LL |     bar::<T::Output>()
    |     ^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as MyTrait<'_>>::Output: 'a`...
+   = note: ...so that the type `<T as MyTrait<'_>>::Output` will meet its required lifetime bounds
 
 error: aborting due to previous error
 
index 58bfb600452e036a48745130134eda0278982757..ddeaf3c1f9e8ca7947add0d32df76dcd5c13bcb2 100644 (file)
@@ -5,6 +5,7 @@ LL |     bar::<<T as MyTrait<'a>>::Output>()
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as MyTrait<'_>>::Output: 'a`...
+   = note: ...so that the type `<T as MyTrait<'_>>::Output` will meet its required lifetime bounds
 
 error: aborting due to previous error
 
index 8175c302155a580446476e2b5b17de0d4104366e..c51edb7868d7a8ef880c72ab02a77532cdae021f 100644 (file)
@@ -1,10 +1,11 @@
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/projection-where-clause-none.rs:16:5
    |
+LL | fn foo<'a, T>() -> &'a ()
+   |            - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
 LL |     bar::<T::Output>()
-   |     ^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
+   |     ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error: aborting due to previous error
 
index baf223b786b080709fd7ba3629f507d1f96f3d36..3e5e4868341edf613f176f1cf973fde0c61d3527 100644 (file)
@@ -52,10 +52,10 @@ LL | | }
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:24
    |
+LL | fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) {
+   |                     - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     twice(cell, value, |a, b| invoke(a, b));
-   |                        ^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
+   |                        ^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error: aborting due to previous error
 
index 88d73e7a729a92f5826d545af0bcf947c986f650..dc2f23b4fc8a33b8bcd4f4357b00fd5110334995 100644 (file)
@@ -29,18 +29,20 @@ LL | | }
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:23
    |
+LL | fn no_region<'a, T>(x: Box<T>) -> Box<dyn Debug + 'a>
+   |                  - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
 LL |     with_signature(x, |y| y)
-   |                       ^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
+   |                       ^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/ty-param-closure-outlives-from-return-type.rs:41:5
    |
+LL | fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a>
+   |                         - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
 LL |     x
-   |     ^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
+   |     ^ ...so that the type `T` will meet its required lifetime bounds
 
 error: aborting due to 2 previous errors
 
index 5b175aac1e1cb774de1787b5ca8cdac6abbb2fd8..e9f728c77b34b9d0420906052b5b6650c56bf6ed 100644 (file)
@@ -37,6 +37,8 @@ LL | | }
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:27:26
    |
+LL |   fn no_region<'a, T>(a: Cell<&'a ()>, b: T) {
+   |                    - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |       with_signature(a, b, |x, y| {
    |  __________________________^
 LL | |
@@ -45,9 +47,7 @@ LL | |         // See `correct_region`, which explains the point of this
 ...  |
 LL | |         require(&x, &y)
 LL | |     })
-   | |_____^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
+   | |_____^ ...so that the type `T` will meet its required lifetime bounds
 
 note: external requirements
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:43:26
@@ -121,15 +121,16 @@ LL | | }
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26
    |
+LL |   fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
+   |                           - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
 LL |       with_signature(a, b, |x, y| {
    |  __________________________^
 LL | |
 LL | |         // See `correct_region`
 LL | |         require(&x, &y)
 LL | |     })
-   | |_____^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
+   | |_____^ ...so that the type `T` will meet its required lifetime bounds
 
 note: external requirements
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:77:26
index 9a023a0e58e5f061efe3a2f517dbe947378ad663..a2e6a5d57cd6278891798e1640c6fd3f43268774 100644 (file)
@@ -1,10 +1,10 @@
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/ty-param-fn-body.rs:19:5
    |
+LL | fn region_static<'a, T>(cell: Cell<&'a usize>, t: T) {
+   |                      - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     outlives(cell, t)
-   |     ^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
+   |     ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error: aborting due to previous error
 
index 8c8529620d57fd401b23b7e54693b49a7b9546d7..fce360dd54bfb28d84ca2f2efc7bd9525c1eea90 100644 (file)
@@ -1,18 +1,20 @@
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/ty-param-fn.rs:11:5
    |
+LL | fn no_region<'a, T>(x: Box<T>) -> Box<Debug + 'a>
+   |                  - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
 LL |     x
-   |     ^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
+   |     ^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/ty-param-fn.rs:26:5
    |
+LL | fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a>
+   |                         - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
 LL |     x
-   |     ^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
+   |     ^ ...so that the type `T` will meet its required lifetime bounds
 
 error: aborting due to 2 previous errors
 
index df957837241489ce4d36a2356c85b1b9bc674d1e..4f502acc95cbe654face1516b30ad294f8cd6881 100644 (file)
@@ -2,23 +2,23 @@ error[E0061]: this function takes 4 arguments but 3 arguments were supplied
   --> $DIR/not-enough-arguments.rs:27:3
    |
 LL |   foo(1, 2, 3);
-   |   ^^^ -  -  - supplied 3 arguments
-   |   |
-   |   expected 4 arguments
+   |   ^^^--------- an argument of type `isize` is missing
    |
 note: function defined here
   --> $DIR/not-enough-arguments.rs:5:4
    |
 LL | fn foo(a: isize, b: isize, c: isize, d:isize) {
    |    ^^^ --------  --------  --------  -------
+help: provide the argument
+   |
+LL |   foo(1, 2, 3, {isize});
+   |   ~~~~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 6 arguments but 3 arguments were supplied
   --> $DIR/not-enough-arguments.rs:29:3
    |
 LL |   bar(1, 2, 3);
-   |   ^^^ -  -  - supplied 3 arguments
-   |   |
-   |   expected 6 arguments
+   |   ^^^--------- three arguments of type `i32`, `i32`, and `i32` are missing
    |
 note: function defined here
   --> $DIR/not-enough-arguments.rs:10:4
@@ -37,6 +37,10 @@ LL |     e: i32,
    |     ------
 LL |     f: i32,
    |     ------
+help: provide the arguments
+   |
+LL |   bar(1, 2, 3, {i32}, {i32}, {i32});
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
index 4c29c4a1cb05c6af7160603f4c854000470f7c15..5045f584c8977886ac002c53e385c9e1067af8d1 100644 (file)
@@ -2,8 +2,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:38:11
    |
 LL |     id_i8(a16);
-   |           ^^^ expected `i8`, found `i16`
+   |     ----- ^^^ expected `i8`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:15:8
+   |
+LL |     fn id_i8(n: i8) -> i8 { n }
+   |        ^^^^^ -----
 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());
@@ -13,8 +20,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:41:11
    |
 LL |     id_i8(a32);
-   |           ^^^ expected `i8`, found `i32`
+   |     ----- ^^^ expected `i8`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:15:8
    |
+LL |     fn id_i8(n: i8) -> i8 { n }
+   |        ^^^^^ -----
 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());
@@ -24,8 +38,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:44:11
    |
 LL |     id_i8(a64);
-   |           ^^^ expected `i8`, found `i64`
+   |     ----- ^^^ expected `i8`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:15:8
+   |
+LL |     fn id_i8(n: i8) -> i8 { n }
+   |        ^^^^^ -----
 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());
@@ -35,8 +56,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:47:11
    |
 LL |     id_i8(asize);
-   |           ^^^^^ expected `i8`, found `isize`
+   |     ----- ^^^^^ expected `i8`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:15:8
    |
+LL |     fn id_i8(n: i8) -> i8 { n }
+   |        ^^^^^ -----
 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());
@@ -46,8 +74,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:51:12
    |
 LL |     id_i16(a8);
-   |            ^^ expected `i16`, found `i8`
+   |     ------ ^^ expected `i16`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:16:8
+   |
+LL |     fn id_i16(n: i16) -> i16 { n }
+   |        ^^^^^^ ------
 help: you can convert an `i8` to an `i16`
    |
 LL |     id_i16(a8.into());
@@ -57,8 +92,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:55:12
    |
 LL |     id_i16(a32);
-   |            ^^^ expected `i16`, found `i32`
+   |     ------ ^^^ expected `i16`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:16:8
    |
+LL |     fn id_i16(n: i16) -> i16 { n }
+   |        ^^^^^^ ------
 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());
@@ -68,8 +110,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:58:12
    |
 LL |     id_i16(a64);
-   |            ^^^ expected `i16`, found `i64`
+   |     ------ ^^^ expected `i16`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:16:8
    |
+LL |     fn id_i16(n: i16) -> i16 { n }
+   |        ^^^^^^ ------
 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());
@@ -79,8 +128,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:61:12
    |
 LL |     id_i16(asize);
-   |            ^^^^^ expected `i16`, found `isize`
+   |     ------ ^^^^^ expected `i16`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:16:8
+   |
+LL |     fn id_i16(n: i16) -> i16 { n }
+   |        ^^^^^^ ------
 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());
@@ -90,8 +146,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:65:12
    |
 LL |     id_i32(a8);
-   |            ^^ expected `i32`, found `i8`
+   |     ------ ^^ expected `i32`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:17:8
    |
+LL |     fn id_i32(n: i32) -> i32 { n }
+   |        ^^^^^^ ------
 help: you can convert an `i8` to an `i32`
    |
 LL |     id_i32(a8.into());
@@ -101,8 +164,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:68:12
    |
 LL |     id_i32(a16);
-   |            ^^^ expected `i32`, found `i16`
+   |     ------ ^^^ expected `i32`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:17:8
    |
+LL |     fn id_i32(n: i32) -> i32 { n }
+   |        ^^^^^^ ------
 help: you can convert an `i16` to an `i32`
    |
 LL |     id_i32(a16.into());
@@ -112,8 +182,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:72:12
    |
 LL |     id_i32(a64);
-   |            ^^^ expected `i32`, found `i64`
+   |     ------ ^^^ expected `i32`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:17:8
+   |
+LL |     fn id_i32(n: i32) -> i32 { n }
+   |        ^^^^^^ ------
 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());
@@ -123,8 +200,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:75:12
    |
 LL |     id_i32(asize);
-   |            ^^^^^ expected `i32`, found `isize`
+   |     ------ ^^^^^ expected `i32`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:17:8
    |
+LL |     fn id_i32(n: i32) -> i32 { n }
+   |        ^^^^^^ ------
 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());
@@ -134,8 +218,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:79:12
    |
 LL |     id_i64(a8);
-   |            ^^ expected `i64`, found `i8`
+   |     ------ ^^ expected `i64`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:18:8
    |
+LL |     fn id_i64(n: i64) -> i64 { n }
+   |        ^^^^^^ ------
 help: you can convert an `i8` to an `i64`
    |
 LL |     id_i64(a8.into());
@@ -145,8 +236,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:82:12
    |
 LL |     id_i64(a16);
-   |            ^^^ expected `i64`, found `i16`
+   |     ------ ^^^ expected `i64`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:18:8
+   |
+LL |     fn id_i64(n: i64) -> i64 { n }
+   |        ^^^^^^ ------
 help: you can convert an `i16` to an `i64`
    |
 LL |     id_i64(a16.into());
@@ -156,8 +254,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:85:12
    |
 LL |     id_i64(a32);
-   |            ^^^ expected `i64`, found `i32`
+   |     ------ ^^^ expected `i64`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:18:8
    |
+LL |     fn id_i64(n: i64) -> i64 { n }
+   |        ^^^^^^ ------
 help: you can convert an `i32` to an `i64`
    |
 LL |     id_i64(a32.into());
@@ -167,8 +272,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:89:12
    |
 LL |     id_i64(asize);
-   |            ^^^^^ expected `i64`, found `isize`
+   |     ------ ^^^^^ expected `i64`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:18:8
+   |
+LL |     fn id_i64(n: i64) -> i64 { n }
+   |        ^^^^^^ ------
 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());
@@ -178,8 +290,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:93:14
    |
 LL |     id_isize(a8);
-   |              ^^ expected `isize`, found `i8`
+   |     -------- ^^ expected `isize`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:19:8
    |
+LL |     fn id_isize(n: isize) -> isize { n }
+   |        ^^^^^^^^ --------
 help: you can convert an `i8` to an `isize`
    |
 LL |     id_isize(a8.into());
@@ -189,8 +308,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:96:14
    |
 LL |     id_isize(a16);
-   |              ^^^ expected `isize`, found `i16`
+   |     -------- ^^^ expected `isize`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:19:8
+   |
+LL |     fn id_isize(n: isize) -> isize { n }
+   |        ^^^^^^^^ --------
 help: you can convert an `i16` to an `isize`
    |
 LL |     id_isize(a16.into());
@@ -200,8 +326,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:99:14
    |
 LL |     id_isize(a32);
-   |              ^^^ expected `isize`, found `i32`
+   |     -------- ^^^ expected `isize`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:19:8
    |
+LL |     fn id_isize(n: isize) -> isize { n }
+   |        ^^^^^^^^ --------
 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());
@@ -211,8 +344,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:102:14
    |
 LL |     id_isize(a64);
-   |              ^^^ expected `isize`, found `i64`
+   |     -------- ^^^ expected `isize`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:19:8
    |
+LL |     fn id_isize(n: isize) -> isize { n }
+   |        ^^^^^^^^ --------
 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());
@@ -222,8 +362,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:108:11
    |
 LL |     id_i8(c16);
-   |           ^^^ expected `i8`, found `i16`
+   |     ----- ^^^ expected `i8`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:15:8
+   |
+LL |     fn id_i8(n: i8) -> i8 { n }
+   |        ^^^^^ -----
 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());
@@ -233,8 +380,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:111:11
    |
 LL |     id_i8(c32);
-   |           ^^^ expected `i8`, found `i32`
+   |     ----- ^^^ expected `i8`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:15:8
    |
+LL |     fn id_i8(n: i8) -> i8 { n }
+   |        ^^^^^ -----
 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());
@@ -244,8 +398,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:114:11
    |
 LL |     id_i8(c64);
-   |           ^^^ expected `i8`, found `i64`
+   |     ----- ^^^ expected `i8`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:15:8
    |
+LL |     fn id_i8(n: i8) -> i8 { n }
+   |        ^^^^^ -----
 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());
@@ -255,8 +416,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:118:12
    |
 LL |     id_i16(c8);
-   |            ^^ expected `i16`, found `i8`
+   |     ------ ^^ expected `i16`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:16:8
+   |
+LL |     fn id_i16(n: i16) -> i16 { n }
+   |        ^^^^^^ ------
 help: you can convert an `i8` to an `i16`
    |
 LL |     id_i16(c8.into());
@@ -266,8 +434,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:122:12
    |
 LL |     id_i16(c32);
-   |            ^^^ expected `i16`, found `i32`
+   |     ------ ^^^ expected `i16`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:16:8
    |
+LL |     fn id_i16(n: i16) -> i16 { n }
+   |        ^^^^^^ ------
 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());
@@ -277,8 +452,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:125:12
    |
 LL |     id_i16(c64);
-   |            ^^^ expected `i16`, found `i64`
+   |     ------ ^^^ expected `i16`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:16:8
    |
+LL |     fn id_i16(n: i16) -> i16 { n }
+   |        ^^^^^^ ------
 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());
@@ -288,8 +470,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:129:12
    |
 LL |     id_i32(c8);
-   |            ^^ expected `i32`, found `i8`
+   |     ------ ^^ expected `i32`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:17:8
+   |
+LL |     fn id_i32(n: i32) -> i32 { n }
+   |        ^^^^^^ ------
 help: you can convert an `i8` to an `i32`
    |
 LL |     id_i32(c8.into());
@@ -299,8 +488,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:132:12
    |
 LL |     id_i32(c16);
-   |            ^^^ expected `i32`, found `i16`
+   |     ------ ^^^ expected `i32`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:17:8
    |
+LL |     fn id_i32(n: i32) -> i32 { n }
+   |        ^^^^^^ ------
 help: you can convert an `i16` to an `i32`
    |
 LL |     id_i32(c16.into());
@@ -310,8 +506,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:136:12
    |
 LL |     id_i32(c64);
-   |            ^^^ expected `i32`, found `i64`
+   |     ------ ^^^ expected `i32`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:17:8
+   |
+LL |     fn id_i32(n: i32) -> i32 { n }
+   |        ^^^^^^ ------
 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());
@@ -321,8 +524,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:140:12
    |
 LL |     id_i64(a8);
-   |            ^^ expected `i64`, found `i8`
+   |     ------ ^^ expected `i64`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:18:8
    |
+LL |     fn id_i64(n: i64) -> i64 { n }
+   |        ^^^^^^ ------
 help: you can convert an `i8` to an `i64`
    |
 LL |     id_i64(a8.into());
@@ -332,8 +542,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:143:12
    |
 LL |     id_i64(a16);
-   |            ^^^ expected `i64`, found `i16`
+   |     ------ ^^^ expected `i64`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:18:8
+   |
+LL |     fn id_i64(n: i64) -> i64 { n }
+   |        ^^^^^^ ------
 help: you can convert an `i16` to an `i64`
    |
 LL |     id_i64(a16.into());
@@ -343,8 +560,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:146:12
    |
 LL |     id_i64(a32);
-   |            ^^^ expected `i64`, found `i32`
+   |     ------ ^^^ expected `i64`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:18:8
    |
+LL |     fn id_i64(n: i64) -> i64 { n }
+   |        ^^^^^^ ------
 help: you can convert an `i32` to an `i64`
    |
 LL |     id_i64(a32.into());
@@ -354,8 +578,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:152:11
    |
 LL |     id_u8(b16);
-   |           ^^^ expected `u8`, found `u16`
+   |     ----- ^^^ expected `u8`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:27:8
    |
+LL |     fn id_u8(n: u8) -> u8 { n }
+   |        ^^^^^ -----
 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());
@@ -365,8 +596,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:155:11
    |
 LL |     id_u8(b32);
-   |           ^^^ expected `u8`, found `u32`
+   |     ----- ^^^ expected `u8`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:27:8
+   |
+LL |     fn id_u8(n: u8) -> u8 { n }
+   |        ^^^^^ -----
 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());
@@ -376,8 +614,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:158:11
    |
 LL |     id_u8(b64);
-   |           ^^^ expected `u8`, found `u64`
+   |     ----- ^^^ expected `u8`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:27:8
    |
+LL |     fn id_u8(n: u8) -> u8 { n }
+   |        ^^^^^ -----
 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());
@@ -387,8 +632,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:161:11
    |
 LL |     id_u8(bsize);
-   |           ^^^^^ expected `u8`, found `usize`
+   |     ----- ^^^^^ expected `u8`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:27:8
    |
+LL |     fn id_u8(n: u8) -> u8 { n }
+   |        ^^^^^ -----
 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());
@@ -398,8 +650,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:165:12
    |
 LL |     id_u16(b8);
-   |            ^^ expected `u16`, found `u8`
+   |     ------ ^^ expected `u16`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:28:8
+   |
+LL |     fn id_u16(n: u16) -> u16 { n }
+   |        ^^^^^^ ------
 help: you can convert a `u8` to a `u16`
    |
 LL |     id_u16(b8.into());
@@ -409,8 +668,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:169:12
    |
 LL |     id_u16(b32);
-   |            ^^^ expected `u16`, found `u32`
+   |     ------ ^^^ expected `u16`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:28:8
    |
+LL |     fn id_u16(n: u16) -> u16 { n }
+   |        ^^^^^^ ------
 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());
@@ -420,8 +686,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:172:12
    |
 LL |     id_u16(b64);
-   |            ^^^ expected `u16`, found `u64`
+   |     ------ ^^^ expected `u16`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:28:8
    |
+LL |     fn id_u16(n: u16) -> u16 { n }
+   |        ^^^^^^ ------
 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());
@@ -431,8 +704,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:175:12
    |
 LL |     id_u16(bsize);
-   |            ^^^^^ expected `u16`, found `usize`
+   |     ------ ^^^^^ expected `u16`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:28:8
+   |
+LL |     fn id_u16(n: u16) -> u16 { n }
+   |        ^^^^^^ ------
 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());
@@ -442,8 +722,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:179:12
    |
 LL |     id_u32(b8);
-   |            ^^ expected `u32`, found `u8`
+   |     ------ ^^ expected `u32`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:29:8
    |
+LL |     fn id_u32(n: u32) -> u32 { n }
+   |        ^^^^^^ ------
 help: you can convert a `u8` to a `u32`
    |
 LL |     id_u32(b8.into());
@@ -453,8 +740,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:182:12
    |
 LL |     id_u32(b16);
-   |            ^^^ expected `u32`, found `u16`
+   |     ------ ^^^ expected `u32`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:29:8
+   |
+LL |     fn id_u32(n: u32) -> u32 { n }
+   |        ^^^^^^ ------
 help: you can convert a `u16` to a `u32`
    |
 LL |     id_u32(b16.into());
@@ -464,8 +758,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:186:12
    |
 LL |     id_u32(b64);
-   |            ^^^ expected `u32`, found `u64`
+   |     ------ ^^^ expected `u32`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:29:8
    |
+LL |     fn id_u32(n: u32) -> u32 { n }
+   |        ^^^^^^ ------
 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());
@@ -475,8 +776,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:189:12
    |
 LL |     id_u32(bsize);
-   |            ^^^^^ expected `u32`, found `usize`
+   |     ------ ^^^^^ expected `u32`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:29:8
+   |
+LL |     fn id_u32(n: u32) -> u32 { n }
+   |        ^^^^^^ ------
 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());
@@ -486,8 +794,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:193:12
    |
 LL |     id_u64(b8);
-   |            ^^ expected `u64`, found `u8`
+   |     ------ ^^ expected `u64`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:30:8
    |
+LL |     fn id_u64(n: u64) -> u64 { n }
+   |        ^^^^^^ ------
 help: you can convert a `u8` to a `u64`
    |
 LL |     id_u64(b8.into());
@@ -497,8 +812,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:196:12
    |
 LL |     id_u64(b16);
-   |            ^^^ expected `u64`, found `u16`
+   |     ------ ^^^ expected `u64`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:30:8
    |
+LL |     fn id_u64(n: u64) -> u64 { n }
+   |        ^^^^^^ ------
 help: you can convert a `u16` to a `u64`
    |
 LL |     id_u64(b16.into());
@@ -508,8 +830,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:199:12
    |
 LL |     id_u64(b32);
-   |            ^^^ expected `u64`, found `u32`
+   |     ------ ^^^ expected `u64`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:30:8
+   |
+LL |     fn id_u64(n: u64) -> u64 { n }
+   |        ^^^^^^ ------
 help: you can convert a `u32` to a `u64`
    |
 LL |     id_u64(b32.into());
@@ -519,8 +848,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:203:12
    |
 LL |     id_u64(bsize);
-   |            ^^^^^ expected `u64`, found `usize`
+   |     ------ ^^^^^ expected `u64`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:30:8
    |
+LL |     fn id_u64(n: u64) -> u64 { n }
+   |        ^^^^^^ ------
 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());
@@ -530,8 +866,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:207:14
    |
 LL |     id_usize(b8);
-   |              ^^ expected `usize`, found `u8`
+   |     -------- ^^ expected `usize`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:31:8
    |
+LL |     fn id_usize(n: usize) -> usize { n }
+   |        ^^^^^^^^ --------
 help: you can convert a `u8` to a `usize`
    |
 LL |     id_usize(b8.into());
@@ -541,8 +884,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:210:14
    |
 LL |     id_usize(b16);
-   |              ^^^ expected `usize`, found `u16`
+   |     -------- ^^^ expected `usize`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:31:8
+   |
+LL |     fn id_usize(n: usize) -> usize { n }
+   |        ^^^^^^^^ --------
 help: you can convert a `u16` to a `usize`
    |
 LL |     id_usize(b16.into());
@@ -552,8 +902,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:213:14
    |
 LL |     id_usize(b32);
-   |              ^^^ expected `usize`, found `u32`
+   |     -------- ^^^ expected `usize`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:31:8
    |
+LL |     fn id_usize(n: usize) -> usize { n }
+   |        ^^^^^^^^ --------
 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());
@@ -563,8 +920,15 @@ error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:216:14
    |
 LL |     id_usize(b64);
-   |              ^^^ expected `usize`, found `u64`
+   |     -------- ^^^ expected `usize`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/integer-literal-suffix-inference.rs:31:8
    |
+LL |     fn id_usize(n: usize) -> usize { n }
+   |        ^^^^^^^^ --------
 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());
index 6319c1ead24eec010e171885528287437653288b..55a61b5e443792e395e7c7627afc40e5f37689c6 100644 (file)
@@ -2,8 +2,15 @@ error[E0308]: mismatched types
   --> $DIR/len.rs:3:10
    |
 LL |     test(array.len());
-   |          ^^^^^^^^^^^ expected `u32`, found `usize`
+   |     ---- ^^^^^^^^^^^ expected `u32`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/len.rs:6:4
+   |
+LL | fn test(length: u32) {
+   |    ^^^^ -----------
 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());
index a96518a34342d43b6c88fde7c9ddc4477c6b4ef9..581b548abcac4e83795b20289bc4c268d369fb55 100644 (file)
@@ -2,127 +2,295 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-without-suggestion.rs:17:18
    |
 LL |     foo::<usize>(x_f64);
-   |                  ^^^^^ expected `usize`, found `f64`
+   |     ------------ ^^^^^ expected `usize`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast-without-suggestion.rs:1:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-without-suggestion.rs:18:18
    |
 LL |     foo::<usize>(x_f32);
-   |                  ^^^^^ expected `usize`, found `f32`
+   |     ------------ ^^^^^ expected `usize`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast-without-suggestion.rs:1:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-without-suggestion.rs:19:18
    |
 LL |     foo::<isize>(x_f64);
-   |                  ^^^^^ expected `isize`, found `f64`
+   |     ------------ ^^^^^ expected `isize`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast-without-suggestion.rs:1:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-without-suggestion.rs:20:18
    |
 LL |     foo::<isize>(x_f32);
-   |                  ^^^^^ expected `isize`, found `f32`
+   |     ------------ ^^^^^ expected `isize`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast-without-suggestion.rs:1:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-without-suggestion.rs:21:16
    |
 LL |     foo::<u64>(x_f64);
-   |                ^^^^^ expected `u64`, found `f64`
+   |     ---------- ^^^^^ expected `u64`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast-without-suggestion.rs:1:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-without-suggestion.rs:22:16
    |
 LL |     foo::<u64>(x_f32);
-   |                ^^^^^ expected `u64`, found `f32`
+   |     ---------- ^^^^^ expected `u64`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast-without-suggestion.rs:1:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-without-suggestion.rs:23:16
    |
 LL |     foo::<i64>(x_f64);
-   |                ^^^^^ expected `i64`, found `f64`
+   |     ---------- ^^^^^ expected `i64`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast-without-suggestion.rs:1:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-without-suggestion.rs:24:16
    |
 LL |     foo::<i64>(x_f32);
-   |                ^^^^^ expected `i64`, found `f32`
+   |     ---------- ^^^^^ expected `i64`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast-without-suggestion.rs:1:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-without-suggestion.rs:25:16
    |
 LL |     foo::<u32>(x_f64);
-   |                ^^^^^ expected `u32`, found `f64`
+   |     ---------- ^^^^^ expected `u32`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast-without-suggestion.rs:1:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-without-suggestion.rs:26:16
    |
 LL |     foo::<u32>(x_f32);
-   |                ^^^^^ expected `u32`, found `f32`
+   |     ---------- ^^^^^ expected `u32`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast-without-suggestion.rs:1:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-without-suggestion.rs:27:16
    |
 LL |     foo::<i32>(x_f64);
-   |                ^^^^^ expected `i32`, found `f64`
+   |     ---------- ^^^^^ expected `i32`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast-without-suggestion.rs:1:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-without-suggestion.rs:28:16
    |
 LL |     foo::<i32>(x_f32);
-   |                ^^^^^ expected `i32`, found `f32`
+   |     ---------- ^^^^^ expected `i32`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast-without-suggestion.rs:1:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-without-suggestion.rs:29:16
    |
 LL |     foo::<u16>(x_f64);
-   |                ^^^^^ expected `u16`, found `f64`
+   |     ---------- ^^^^^ expected `u16`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast-without-suggestion.rs:1:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-without-suggestion.rs:30:16
    |
 LL |     foo::<u16>(x_f32);
-   |                ^^^^^ expected `u16`, found `f32`
+   |     ---------- ^^^^^ expected `u16`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast-without-suggestion.rs:1:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-without-suggestion.rs:31:16
    |
 LL |     foo::<i16>(x_f64);
-   |                ^^^^^ expected `i16`, found `f64`
+   |     ---------- ^^^^^ expected `i16`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast-without-suggestion.rs:1:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-without-suggestion.rs:32:16
    |
 LL |     foo::<i16>(x_f32);
-   |                ^^^^^ expected `i16`, found `f32`
+   |     ---------- ^^^^^ expected `i16`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast-without-suggestion.rs:1:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-without-suggestion.rs:33:15
    |
 LL |     foo::<u8>(x_f64);
-   |               ^^^^^ expected `u8`, found `f64`
+   |     --------- ^^^^^ expected `u8`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast-without-suggestion.rs:1:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-without-suggestion.rs:34:15
    |
 LL |     foo::<u8>(x_f32);
-   |               ^^^^^ expected `u8`, found `f32`
+   |     --------- ^^^^^ expected `u8`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast-without-suggestion.rs:1:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-without-suggestion.rs:35:15
    |
 LL |     foo::<i8>(x_f64);
-   |               ^^^^^ expected `i8`, found `f64`
+   |     --------- ^^^^^ expected `i8`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast-without-suggestion.rs:1:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-without-suggestion.rs:36:15
    |
 LL |     foo::<i8>(x_f32);
-   |               ^^^^^ expected `i8`, found `f32`
+   |     --------- ^^^^^ expected `i8`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast-without-suggestion.rs:1:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-without-suggestion.rs:37:16
    |
 LL |     foo::<f32>(x_f64);
-   |                ^^^^^ expected `f32`, found `f64`
+   |     ---------- ^^^^^ expected `f32`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast-without-suggestion.rs:1:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 
 error: aborting due to 21 previous errors
 
index b8f2d88ab4957e9fb246700d708eab9f34528959..d347875d5a947df9231cc54cb60b3a642b69efa9 100644 (file)
@@ -2,8 +2,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:23:18
    |
 LL |     foo::<usize>(x_u64);
-   |                  ^^^^^ expected `usize`, found `u64`
+   |     ------------ ^^^^^ expected `usize`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -13,8 +20,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:25:18
    |
 LL |     foo::<usize>(x_u32);
-   |                  ^^^^^ expected `usize`, found `u32`
+   |     ------------ ^^^^^ expected `usize`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -24,8 +38,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:27:18
    |
 LL |     foo::<usize>(x_u16);
-   |                  ^^^^^ expected `usize`, found `u16`
+   |     ------------ ^^^^^ expected `usize`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert a `u16` to a `usize`
    |
 LL |     foo::<usize>(x_u16.into());
@@ -35,8 +56,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:29:18
    |
 LL |     foo::<usize>(x_u8);
-   |                  ^^^^ expected `usize`, found `u8`
+   |     ------------ ^^^^ expected `usize`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert a `u8` to a `usize`
    |
 LL |     foo::<usize>(x_u8.into());
@@ -46,8 +74,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:31:18
    |
 LL |     foo::<usize>(x_isize);
-   |                  ^^^^^^^ expected `usize`, found `isize`
+   |     ------------ ^^^^^^^ expected `usize`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -57,8 +92,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:33:18
    |
 LL |     foo::<usize>(x_i64);
-   |                  ^^^^^ expected `usize`, found `i64`
+   |     ------------ ^^^^^ expected `usize`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -68,8 +110,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:35:18
    |
 LL |     foo::<usize>(x_i32);
-   |                  ^^^^^ expected `usize`, found `i32`
+   |     ------------ ^^^^^ expected `usize`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -79,8 +128,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:37:18
    |
 LL |     foo::<usize>(x_i16);
-   |                  ^^^^^ expected `usize`, found `i16`
+   |     ------------ ^^^^^ expected `usize`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -90,8 +146,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:39:18
    |
 LL |     foo::<usize>(x_i8);
-   |                  ^^^^ expected `usize`, found `i8`
+   |     ------------ ^^^^ expected `usize`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -101,8 +164,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:44:18
    |
 LL |     foo::<isize>(x_usize);
-   |                  ^^^^^^^ expected `isize`, found `usize`
+   |     ------------ ^^^^^^^ expected `isize`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -112,8 +182,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:46:18
    |
 LL |     foo::<isize>(x_u64);
-   |                  ^^^^^ expected `isize`, found `u64`
+   |     ------------ ^^^^^ expected `isize`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -123,8 +200,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:48:18
    |
 LL |     foo::<isize>(x_u32);
-   |                  ^^^^^ expected `isize`, found `u32`
+   |     ------------ ^^^^^ expected `isize`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -134,8 +218,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:50:18
    |
 LL |     foo::<isize>(x_u16);
-   |                  ^^^^^ expected `isize`, found `u16`
+   |     ------------ ^^^^^ expected `isize`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -145,8 +236,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:52:18
    |
 LL |     foo::<isize>(x_u8);
-   |                  ^^^^ expected `isize`, found `u8`
+   |     ------------ ^^^^ expected `isize`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert a `u8` to an `isize`
    |
 LL |     foo::<isize>(x_u8.into());
@@ -156,8 +254,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:55:18
    |
 LL |     foo::<isize>(x_i64);
-   |                  ^^^^^ expected `isize`, found `i64`
+   |     ------------ ^^^^^ expected `isize`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -167,8 +272,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:57:18
    |
 LL |     foo::<isize>(x_i32);
-   |                  ^^^^^ expected `isize`, found `i32`
+   |     ------------ ^^^^^ expected `isize`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -178,8 +290,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:59:18
    |
 LL |     foo::<isize>(x_i16);
-   |                  ^^^^^ expected `isize`, found `i16`
+   |     ------------ ^^^^^ expected `isize`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert an `i16` to an `isize`
    |
 LL |     foo::<isize>(x_i16.into());
@@ -189,8 +308,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:61:18
    |
 LL |     foo::<isize>(x_i8);
-   |                  ^^^^ expected `isize`, found `i8`
+   |     ------------ ^^^^ expected `isize`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert an `i8` to an `isize`
    |
 LL |     foo::<isize>(x_i8.into());
@@ -200,8 +326,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:66:16
    |
 LL |     foo::<u64>(x_usize);
-   |                ^^^^^^^ expected `u64`, found `usize`
+   |     ---------- ^^^^^^^ expected `u64`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -211,8 +344,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:69:16
    |
 LL |     foo::<u64>(x_u32);
-   |                ^^^^^ expected `u64`, found `u32`
+   |     ---------- ^^^^^ expected `u64`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert a `u32` to a `u64`
    |
 LL |     foo::<u64>(x_u32.into());
@@ -222,8 +362,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:71:16
    |
 LL |     foo::<u64>(x_u16);
-   |                ^^^^^ expected `u64`, found `u16`
+   |     ---------- ^^^^^ expected `u64`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert a `u16` to a `u64`
    |
 LL |     foo::<u64>(x_u16.into());
@@ -233,8 +380,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:73:16
    |
 LL |     foo::<u64>(x_u8);
-   |                ^^^^ expected `u64`, found `u8`
+   |     ---------- ^^^^ expected `u64`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert a `u8` to a `u64`
    |
 LL |     foo::<u64>(x_u8.into());
@@ -244,8 +398,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:75:16
    |
 LL |     foo::<u64>(x_isize);
-   |                ^^^^^^^ expected `u64`, found `isize`
+   |     ---------- ^^^^^^^ expected `u64`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -255,8 +416,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:77:16
    |
 LL |     foo::<u64>(x_i64);
-   |                ^^^^^ expected `u64`, found `i64`
+   |     ---------- ^^^^^ expected `u64`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -266,8 +434,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:79:16
    |
 LL |     foo::<u64>(x_i32);
-   |                ^^^^^ expected `u64`, found `i32`
+   |     ---------- ^^^^^ expected `u64`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -277,8 +452,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:81:16
    |
 LL |     foo::<u64>(x_i16);
-   |                ^^^^^ expected `u64`, found `i16`
+   |     ---------- ^^^^^ expected `u64`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -288,8 +470,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:83:16
    |
 LL |     foo::<u64>(x_i8);
-   |                ^^^^ expected `u64`, found `i8`
+   |     ---------- ^^^^ expected `u64`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -299,8 +488,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:88:16
    |
 LL |     foo::<i64>(x_usize);
-   |                ^^^^^^^ expected `i64`, found `usize`
+   |     ---------- ^^^^^^^ expected `i64`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -310,8 +506,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:90:16
    |
 LL |     foo::<i64>(x_u64);
-   |                ^^^^^ expected `i64`, found `u64`
+   |     ---------- ^^^^^ expected `i64`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -321,8 +524,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:92:16
    |
 LL |     foo::<i64>(x_u32);
-   |                ^^^^^ expected `i64`, found `u32`
+   |     ---------- ^^^^^ expected `i64`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert a `u32` to an `i64`
    |
 LL |     foo::<i64>(x_u32.into());
@@ -332,8 +542,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:94:16
    |
 LL |     foo::<i64>(x_u16);
-   |                ^^^^^ expected `i64`, found `u16`
+   |     ---------- ^^^^^ expected `i64`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert a `u16` to an `i64`
    |
 LL |     foo::<i64>(x_u16.into());
@@ -343,8 +560,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:96:16
    |
 LL |     foo::<i64>(x_u8);
-   |                ^^^^ expected `i64`, found `u8`
+   |     ---------- ^^^^ expected `i64`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert a `u8` to an `i64`
    |
 LL |     foo::<i64>(x_u8.into());
@@ -354,8 +578,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:98:16
    |
 LL |     foo::<i64>(x_isize);
-   |                ^^^^^^^ expected `i64`, found `isize`
+   |     ---------- ^^^^^^^ expected `i64`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -365,8 +596,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:101:16
    |
 LL |     foo::<i64>(x_i32);
-   |                ^^^^^ expected `i64`, found `i32`
+   |     ---------- ^^^^^ expected `i64`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert an `i32` to an `i64`
    |
 LL |     foo::<i64>(x_i32.into());
@@ -376,8 +614,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:103:16
    |
 LL |     foo::<i64>(x_i16);
-   |                ^^^^^ expected `i64`, found `i16`
+   |     ---------- ^^^^^ expected `i64`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert an `i16` to an `i64`
    |
 LL |     foo::<i64>(x_i16.into());
@@ -387,8 +632,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:105:16
    |
 LL |     foo::<i64>(x_i8);
-   |                ^^^^ expected `i64`, found `i8`
+   |     ---------- ^^^^ expected `i64`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert an `i8` to an `i64`
    |
 LL |     foo::<i64>(x_i8.into());
@@ -398,8 +650,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:110:16
    |
 LL |     foo::<u32>(x_usize);
-   |                ^^^^^^^ expected `u32`, found `usize`
+   |     ---------- ^^^^^^^ expected `u32`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -409,8 +668,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:112:16
    |
 LL |     foo::<u32>(x_u64);
-   |                ^^^^^ expected `u32`, found `u64`
+   |     ---------- ^^^^^ expected `u32`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -420,8 +686,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:115:16
    |
 LL |     foo::<u32>(x_u16);
-   |                ^^^^^ expected `u32`, found `u16`
+   |     ---------- ^^^^^ expected `u32`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert a `u16` to a `u32`
    |
 LL |     foo::<u32>(x_u16.into());
@@ -431,8 +704,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:117:16
    |
 LL |     foo::<u32>(x_u8);
-   |                ^^^^ expected `u32`, found `u8`
+   |     ---------- ^^^^ expected `u32`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert a `u8` to a `u32`
    |
 LL |     foo::<u32>(x_u8.into());
@@ -442,8 +722,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:119:16
    |
 LL |     foo::<u32>(x_isize);
-   |                ^^^^^^^ expected `u32`, found `isize`
+   |     ---------- ^^^^^^^ expected `u32`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -453,8 +740,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:121:16
    |
 LL |     foo::<u32>(x_i64);
-   |                ^^^^^ expected `u32`, found `i64`
+   |     ---------- ^^^^^ expected `u32`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -464,8 +758,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:123:16
    |
 LL |     foo::<u32>(x_i32);
-   |                ^^^^^ expected `u32`, found `i32`
+   |     ---------- ^^^^^ expected `u32`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -475,8 +776,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:125:16
    |
 LL |     foo::<u32>(x_i16);
-   |                ^^^^^ expected `u32`, found `i16`
+   |     ---------- ^^^^^ expected `u32`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -486,8 +794,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:127:16
    |
 LL |     foo::<u32>(x_i8);
-   |                ^^^^ expected `u32`, found `i8`
+   |     ---------- ^^^^ expected `u32`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -497,8 +812,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:132:16
    |
 LL |     foo::<i32>(x_usize);
-   |                ^^^^^^^ expected `i32`, found `usize`
+   |     ---------- ^^^^^^^ expected `i32`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -508,8 +830,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:134:16
    |
 LL |     foo::<i32>(x_u64);
-   |                ^^^^^ expected `i32`, found `u64`
+   |     ---------- ^^^^^ expected `i32`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -519,8 +848,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:136:16
    |
 LL |     foo::<i32>(x_u32);
-   |                ^^^^^ expected `i32`, found `u32`
+   |     ---------- ^^^^^ expected `i32`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -530,8 +866,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:138:16
    |
 LL |     foo::<i32>(x_u16);
-   |                ^^^^^ expected `i32`, found `u16`
+   |     ---------- ^^^^^ expected `i32`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert a `u16` to an `i32`
    |
 LL |     foo::<i32>(x_u16.into());
@@ -541,8 +884,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:140:16
    |
 LL |     foo::<i32>(x_u8);
-   |                ^^^^ expected `i32`, found `u8`
+   |     ---------- ^^^^ expected `i32`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert a `u8` to an `i32`
    |
 LL |     foo::<i32>(x_u8.into());
@@ -552,8 +902,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:142:16
    |
 LL |     foo::<i32>(x_isize);
-   |                ^^^^^^^ expected `i32`, found `isize`
+   |     ---------- ^^^^^^^ expected `i32`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -563,8 +920,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:144:16
    |
 LL |     foo::<i32>(x_i64);
-   |                ^^^^^ expected `i32`, found `i64`
+   |     ---------- ^^^^^ expected `i32`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -574,8 +938,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:147:16
    |
 LL |     foo::<i32>(x_i16);
-   |                ^^^^^ expected `i32`, found `i16`
+   |     ---------- ^^^^^ expected `i32`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert an `i16` to an `i32`
    |
 LL |     foo::<i32>(x_i16.into());
@@ -585,8 +956,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:149:16
    |
 LL |     foo::<i32>(x_i8);
-   |                ^^^^ expected `i32`, found `i8`
+   |     ---------- ^^^^ expected `i32`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert an `i8` to an `i32`
    |
 LL |     foo::<i32>(x_i8.into());
@@ -596,8 +974,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:154:16
    |
 LL |     foo::<u16>(x_usize);
-   |                ^^^^^^^ expected `u16`, found `usize`
+   |     ---------- ^^^^^^^ expected `u16`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -607,8 +992,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:156:16
    |
 LL |     foo::<u16>(x_u64);
-   |                ^^^^^ expected `u16`, found `u64`
+   |     ---------- ^^^^^ expected `u16`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -618,8 +1010,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:158:16
    |
 LL |     foo::<u16>(x_u32);
-   |                ^^^^^ expected `u16`, found `u32`
+   |     ---------- ^^^^^ expected `u16`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -629,8 +1028,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:161:16
    |
 LL |     foo::<u16>(x_u8);
-   |                ^^^^ expected `u16`, found `u8`
+   |     ---------- ^^^^ expected `u16`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert a `u8` to a `u16`
    |
 LL |     foo::<u16>(x_u8.into());
@@ -640,8 +1046,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:163:16
    |
 LL |     foo::<u16>(x_isize);
-   |                ^^^^^^^ expected `u16`, found `isize`
+   |     ---------- ^^^^^^^ expected `u16`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -651,8 +1064,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:165:16
    |
 LL |     foo::<u16>(x_i64);
-   |                ^^^^^ expected `u16`, found `i64`
+   |     ---------- ^^^^^ expected `u16`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -662,8 +1082,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:167:16
    |
 LL |     foo::<u16>(x_i32);
-   |                ^^^^^ expected `u16`, found `i32`
+   |     ---------- ^^^^^ expected `u16`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -673,8 +1100,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:169:16
    |
 LL |     foo::<u16>(x_i16);
-   |                ^^^^^ expected `u16`, found `i16`
+   |     ---------- ^^^^^ expected `u16`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -684,8 +1118,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:171:16
    |
 LL |     foo::<u16>(x_i8);
-   |                ^^^^ expected `u16`, found `i8`
+   |     ---------- ^^^^ expected `u16`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -695,8 +1136,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:176:16
    |
 LL |     foo::<i16>(x_usize);
-   |                ^^^^^^^ expected `i16`, found `usize`
+   |     ---------- ^^^^^^^ expected `i16`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -706,8 +1154,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:178:16
    |
 LL |     foo::<i16>(x_u64);
-   |                ^^^^^ expected `i16`, found `u64`
+   |     ---------- ^^^^^ expected `i16`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -717,8 +1172,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:180:16
    |
 LL |     foo::<i16>(x_u32);
-   |                ^^^^^ expected `i16`, found `u32`
+   |     ---------- ^^^^^ expected `i16`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -728,8 +1190,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:182:16
    |
 LL |     foo::<i16>(x_u16);
-   |                ^^^^^ expected `i16`, found `u16`
+   |     ---------- ^^^^^ expected `i16`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -739,8 +1208,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:184:16
    |
 LL |     foo::<i16>(x_u8);
-   |                ^^^^ expected `i16`, found `u8`
+   |     ---------- ^^^^ expected `i16`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert a `u8` to an `i16`
    |
 LL |     foo::<i16>(x_u8.into());
@@ -750,8 +1226,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:186:16
    |
 LL |     foo::<i16>(x_isize);
-   |                ^^^^^^^ expected `i16`, found `isize`
+   |     ---------- ^^^^^^^ expected `i16`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -761,8 +1244,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:188:16
    |
 LL |     foo::<i16>(x_i64);
-   |                ^^^^^ expected `i16`, found `i64`
+   |     ---------- ^^^^^ expected `i16`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -772,8 +1262,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:190:16
    |
 LL |     foo::<i16>(x_i32);
-   |                ^^^^^ expected `i16`, found `i32`
+   |     ---------- ^^^^^ expected `i16`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -783,8 +1280,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:193:16
    |
 LL |     foo::<i16>(x_i8);
-   |                ^^^^ expected `i16`, found `i8`
+   |     ---------- ^^^^ expected `i16`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert an `i8` to an `i16`
    |
 LL |     foo::<i16>(x_i8.into());
@@ -794,8 +1298,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:198:15
    |
 LL |     foo::<u8>(x_usize);
-   |               ^^^^^^^ expected `u8`, found `usize`
+   |     --------- ^^^^^^^ expected `u8`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -805,8 +1316,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:200:15
    |
 LL |     foo::<u8>(x_u64);
-   |               ^^^^^ expected `u8`, found `u64`
+   |     --------- ^^^^^ expected `u8`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -816,8 +1334,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:202:15
    |
 LL |     foo::<u8>(x_u32);
-   |               ^^^^^ expected `u8`, found `u32`
+   |     --------- ^^^^^ expected `u8`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -827,8 +1352,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:204:15
    |
 LL |     foo::<u8>(x_u16);
-   |               ^^^^^ expected `u8`, found `u16`
+   |     --------- ^^^^^ expected `u8`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -838,8 +1370,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:207:15
    |
 LL |     foo::<u8>(x_isize);
-   |               ^^^^^^^ expected `u8`, found `isize`
+   |     --------- ^^^^^^^ expected `u8`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -849,8 +1388,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:209:15
    |
 LL |     foo::<u8>(x_i64);
-   |               ^^^^^ expected `u8`, found `i64`
+   |     --------- ^^^^^ expected `u8`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -860,8 +1406,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:211:15
    |
 LL |     foo::<u8>(x_i32);
-   |               ^^^^^ expected `u8`, found `i32`
+   |     --------- ^^^^^ expected `u8`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -871,8 +1424,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:213:15
    |
 LL |     foo::<u8>(x_i16);
-   |               ^^^^^ expected `u8`, found `i16`
+   |     --------- ^^^^^ expected `u8`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -882,8 +1442,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:215:15
    |
 LL |     foo::<u8>(x_i8);
-   |               ^^^^ expected `u8`, found `i8`
+   |     --------- ^^^^ expected `u8`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -893,8 +1460,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:220:15
    |
 LL |     foo::<i8>(x_usize);
-   |               ^^^^^^^ expected `i8`, found `usize`
+   |     --------- ^^^^^^^ expected `i8`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -904,8 +1478,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:222:15
    |
 LL |     foo::<i8>(x_u64);
-   |               ^^^^^ expected `i8`, found `u64`
+   |     --------- ^^^^^ expected `i8`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -915,8 +1496,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:224:15
    |
 LL |     foo::<i8>(x_u32);
-   |               ^^^^^ expected `i8`, found `u32`
+   |     --------- ^^^^^ expected `i8`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -926,8 +1514,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:226:15
    |
 LL |     foo::<i8>(x_u16);
-   |               ^^^^^ expected `i8`, found `u16`
+   |     --------- ^^^^^ expected `i8`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -937,8 +1532,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:228:15
    |
 LL |     foo::<i8>(x_u8);
-   |               ^^^^ expected `i8`, found `u8`
+   |     --------- ^^^^ expected `i8`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -948,8 +1550,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:230:15
    |
 LL |     foo::<i8>(x_isize);
-   |               ^^^^^^^ expected `i8`, found `isize`
+   |     --------- ^^^^^^^ expected `i8`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -959,8 +1568,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:232:15
    |
 LL |     foo::<i8>(x_i64);
-   |               ^^^^^ expected `i8`, found `i64`
+   |     --------- ^^^^^ expected `i8`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -970,8 +1586,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:234:15
    |
 LL |     foo::<i8>(x_i32);
-   |               ^^^^^ expected `i8`, found `i32`
+   |     --------- ^^^^^ expected `i8`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -981,8 +1604,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:236:15
    |
 LL |     foo::<i8>(x_i16);
-   |               ^^^^^ expected `i8`, found `i16`
+   |     --------- ^^^^^ expected `i8`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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());
@@ -992,8 +1622,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:242:16
    |
 LL |     foo::<f64>(x_usize);
-   |                ^^^^^^^ expected `f64`, found `usize`
+   |     ---------- ^^^^^^^ expected `f64`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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);
@@ -1003,8 +1640,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:244:16
    |
 LL |     foo::<f64>(x_u64);
-   |                ^^^^^ expected `f64`, found `u64`
+   |     ---------- ^^^^^ expected `f64`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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);
@@ -1014,8 +1658,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:246:16
    |
 LL |     foo::<f64>(x_u32);
-   |                ^^^^^ expected `f64`, found `u32`
+   |     ---------- ^^^^^ expected `f64`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert a `u32` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(x_u32.into());
@@ -1025,8 +1676,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:248:16
    |
 LL |     foo::<f64>(x_u16);
-   |                ^^^^^ expected `f64`, found `u16`
+   |     ---------- ^^^^^ expected `f64`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert a `u16` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(x_u16.into());
@@ -1036,8 +1694,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:250:16
    |
 LL |     foo::<f64>(x_u8);
-   |                ^^^^ expected `f64`, found `u8`
+   |     ---------- ^^^^ expected `f64`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert a `u8` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(x_u8.into());
@@ -1047,8 +1712,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:252:16
    |
 LL |     foo::<f64>(x_isize);
-   |                ^^^^^^^ expected `f64`, found `isize`
+   |     ---------- ^^^^^^^ expected `f64`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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);
@@ -1058,8 +1730,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:254:16
    |
 LL |     foo::<f64>(x_i64);
-   |                ^^^^^ expected `f64`, found `i64`
+   |     ---------- ^^^^^ expected `f64`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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);
@@ -1069,8 +1748,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:256:16
    |
 LL |     foo::<f64>(x_i32);
-   |                ^^^^^ expected `f64`, found `i32`
+   |     ---------- ^^^^^ expected `f64`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert an `i32` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(x_i32.into());
@@ -1080,8 +1766,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:258:16
    |
 LL |     foo::<f64>(x_i16);
-   |                ^^^^^ expected `f64`, found `i16`
+   |     ---------- ^^^^^ expected `f64`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert an `i16` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(x_i16.into());
@@ -1091,8 +1784,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:260:16
    |
 LL |     foo::<f64>(x_i8);
-   |                ^^^^ expected `f64`, found `i8`
+   |     ---------- ^^^^ expected `f64`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert an `i8` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(x_i8.into());
@@ -1102,8 +1802,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:263:16
    |
 LL |     foo::<f64>(x_f32);
-   |                ^^^^^ expected `f64`, found `f32`
+   |     ---------- ^^^^^ expected `f64`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert an `f32` to an `f64`
    |
 LL |     foo::<f64>(x_f32.into());
@@ -1113,8 +1820,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:266:16
    |
 LL |     foo::<f32>(x_usize);
-   |                ^^^^^^^ expected `f32`, found `usize`
+   |     ---------- ^^^^^^^ expected `f32`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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);
@@ -1124,8 +1838,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:268:16
    |
 LL |     foo::<f32>(x_u64);
-   |                ^^^^^ expected `f32`, found `u64`
+   |     ---------- ^^^^^ expected `f32`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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);
@@ -1135,8 +1856,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:270:16
    |
 LL |     foo::<f32>(x_u32);
-   |                ^^^^^ expected `f32`, found `u32`
+   |     ---------- ^^^^^ expected `f32`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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);
@@ -1146,8 +1874,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:272:16
    |
 LL |     foo::<f32>(x_u16);
-   |                ^^^^^ expected `f32`, found `u16`
+   |     ---------- ^^^^^ expected `f32`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert a `u16` to an `f32`, producing the floating point representation of the integer
    |
 LL |     foo::<f32>(x_u16.into());
@@ -1157,8 +1892,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:274:16
    |
 LL |     foo::<f32>(x_u8);
-   |                ^^^^ expected `f32`, found `u8`
+   |     ---------- ^^^^ expected `f32`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert a `u8` to an `f32`, producing the floating point representation of the integer
    |
 LL |     foo::<f32>(x_u8.into());
@@ -1168,8 +1910,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:276:16
    |
 LL |     foo::<f32>(x_isize);
-   |                ^^^^^^^ expected `f32`, found `isize`
+   |     ---------- ^^^^^^^ expected `f32`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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);
@@ -1179,8 +1928,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:278:16
    |
 LL |     foo::<f32>(x_i64);
-   |                ^^^^^ expected `f32`, found `i64`
+   |     ---------- ^^^^^ expected `f32`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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);
@@ -1190,8 +1946,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:280:16
    |
 LL |     foo::<f32>(x_i32);
-   |                ^^^^^ expected `f32`, found `i32`
+   |     ---------- ^^^^^ expected `f32`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 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);
@@ -1201,8 +1964,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:282:16
    |
 LL |     foo::<f32>(x_i16);
-   |                ^^^^^ expected `f32`, found `i16`
+   |     ---------- ^^^^^ expected `f32`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert an `i16` to an `f32`, producing the floating point representation of the integer
    |
 LL |     foo::<f32>(x_i16.into());
@@ -1212,8 +1982,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:284:16
    |
 LL |     foo::<f32>(x_i8);
-   |                ^^^^ expected `f32`, found `i8`
+   |     ---------- ^^^^ expected `f32`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert an `i8` to an `f32`, producing the floating point representation of the integer
    |
 LL |     foo::<f32>(x_i8.into());
@@ -1223,8 +2000,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:289:16
    |
 LL |     foo::<u32>(x_u8 as u16);
-   |                ^^^^^^^^^^^ expected `u32`, found `u16`
+   |     ---------- ^^^^^^^^^^^ expected `u32`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert a `u16` to a `u32`
    |
 LL |     foo::<u32>((x_u8 as u16).into());
@@ -1234,8 +2018,15 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:291:16
    |
 LL |     foo::<i32>(-x_i8);
-   |                ^^^^^ expected `i32`, found `i8`
+   |     ---------- ^^^^^ expected `i32`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-cast.rs:6:4
    |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
 help: you can convert an `i8` to an `i32`
    |
 LL |     foo::<i32>((-x_i8).into());
diff --git a/src/test/ui/numeric/numeric-suffix.fixed b/src/test/ui/numeric/numeric-suffix.fixed
deleted file mode 100644 (file)
index 53c5fe0..0000000
+++ /dev/null
@@ -1,298 +0,0 @@
-// run-rustfix
-
-fn foo<N>(_x: N) {}
-
-fn main() {
-    foo::<usize>(42_usize);
-    foo::<usize>(42_usize);
-    //~^ ERROR mismatched types
-    foo::<usize>(42_usize);
-    //~^ ERROR mismatched types
-    foo::<usize>(42_usize);
-    //~^ ERROR mismatched types
-    foo::<usize>(42_usize);
-    //~^ ERROR mismatched types
-    foo::<usize>(42_usize);
-    //~^ ERROR mismatched types
-    foo::<usize>(42_usize);
-    //~^ ERROR mismatched types
-    foo::<usize>(42_usize);
-    //~^ ERROR mismatched types
-    foo::<usize>(42_usize);
-    //~^ ERROR mismatched types
-    foo::<usize>(42_usize);
-    //~^ ERROR mismatched types
-    foo::<usize>(42usize);
-    //~^ ERROR mismatched types
-    foo::<usize>(42usize);
-    //~^ ERROR mismatched types
-
-    foo::<isize>(42_isize);
-    //~^ ERROR mismatched types
-    foo::<isize>(42_isize);
-    //~^ ERROR mismatched types
-    foo::<isize>(42_isize);
-    //~^ ERROR mismatched types
-    foo::<isize>(42_isize);
-    //~^ ERROR mismatched types
-    foo::<isize>(42_isize);
-    //~^ ERROR mismatched types
-    foo::<isize>(42_isize);
-    foo::<isize>(42_isize);
-    //~^ ERROR mismatched types
-    foo::<isize>(42_isize);
-    //~^ ERROR mismatched types
-    foo::<isize>(42_isize);
-    //~^ ERROR mismatched types
-    foo::<isize>(42_isize);
-    //~^ ERROR mismatched types
-    foo::<isize>(42isize);
-    //~^ ERROR mismatched types
-    foo::<isize>(42isize);
-    //~^ ERROR mismatched types
-
-    foo::<u64>(42_u64);
-    //~^ ERROR mismatched types
-    foo::<u64>(42_u64);
-    foo::<u64>(42_u64);
-    //~^ ERROR mismatched types
-    foo::<u64>(42_u64);
-    //~^ ERROR mismatched types
-    foo::<u64>(42_u64);
-    //~^ ERROR mismatched types
-    foo::<u64>(42_u64);
-    //~^ ERROR mismatched types
-    foo::<u64>(42_u64);
-    //~^ ERROR mismatched types
-    foo::<u64>(42_u64);
-    //~^ ERROR mismatched types
-    foo::<u64>(42_u64);
-    //~^ ERROR mismatched types
-    foo::<u64>(42_u64);
-    //~^ ERROR mismatched types
-    foo::<u64>(42u64);
-    //~^ ERROR mismatched types
-    foo::<u64>(42u64);
-    //~^ ERROR mismatched types
-
-    foo::<i64>(42_i64);
-    //~^ ERROR mismatched types
-    foo::<i64>(42_i64);
-    //~^ ERROR mismatched types
-    foo::<i64>(42_i64);
-    //~^ ERROR mismatched types
-    foo::<i64>(42_i64);
-    //~^ ERROR mismatched types
-    foo::<i64>(42_i64);
-    //~^ ERROR mismatched types
-    foo::<i64>(42_i64);
-    //~^ ERROR mismatched types
-    foo::<i64>(42_i64);
-    foo::<i64>(42_i64);
-    //~^ ERROR mismatched types
-    foo::<i64>(42_i64);
-    //~^ ERROR mismatched types
-    foo::<i64>(42_i64);
-    //~^ ERROR mismatched types
-    foo::<i64>(42i64);
-    //~^ ERROR mismatched types
-    foo::<i64>(42i64);
-    //~^ ERROR mismatched types
-
-    foo::<u32>(42_u32);
-    //~^ ERROR mismatched types
-    foo::<u32>(42_u32);
-    //~^ ERROR mismatched types
-    foo::<u32>(42_u32);
-    foo::<u32>(42_u32);
-    //~^ ERROR mismatched types
-    foo::<u32>(42_u32);
-    //~^ ERROR mismatched types
-    foo::<u32>(42_u32);
-    //~^ ERROR mismatched types
-    foo::<u32>(42_u32);
-    //~^ ERROR mismatched types
-    foo::<u32>(42_u32);
-    //~^ ERROR mismatched types
-    foo::<u32>(42_u32);
-    //~^ ERROR mismatched types
-    foo::<u32>(42_u32);
-    //~^ ERROR mismatched types
-    foo::<u32>(42u32);
-    //~^ ERROR mismatched types
-    foo::<u32>(42u32);
-    //~^ ERROR mismatched types
-
-    foo::<i32>(42_i32);
-    //~^ ERROR mismatched types
-    foo::<i32>(42_i32);
-    //~^ ERROR mismatched types
-    foo::<i32>(42_i32);
-    //~^ ERROR mismatched types
-    foo::<i32>(42_i32);
-    //~^ ERROR mismatched types
-    foo::<i32>(42_i32);
-    //~^ ERROR mismatched types
-    foo::<i32>(42_i32);
-    //~^ ERROR mismatched types
-    foo::<i32>(42_i32);
-    //~^ ERROR mismatched types
-    foo::<i32>(42_i32);
-    foo::<i32>(42_i32);
-    //~^ ERROR mismatched types
-    foo::<i32>(42_i32);
-    //~^ ERROR mismatched types
-    foo::<i32>(42i32);
-    //~^ ERROR mismatched types
-    foo::<i32>(42i32);
-    //~^ ERROR mismatched types
-
-    foo::<u16>(42_u16);
-    //~^ ERROR mismatched types
-    foo::<u16>(42_u16);
-    //~^ ERROR mismatched types
-    foo::<u16>(42_u16);
-    //~^ ERROR mismatched types
-    foo::<u16>(42_u16);
-    foo::<u16>(42_u16);
-    //~^ ERROR mismatched types
-    foo::<u16>(42_u16);
-    //~^ ERROR mismatched types
-    foo::<u16>(42_u16);
-    //~^ ERROR mismatched types
-    foo::<u16>(42_u16);
-    //~^ ERROR mismatched types
-    foo::<u16>(42_u16);
-    //~^ ERROR mismatched types
-    foo::<u16>(42_u16);
-    //~^ ERROR mismatched types
-    foo::<u16>(42u16);
-    //~^ ERROR mismatched types
-    foo::<u16>(42u16);
-    //~^ ERROR mismatched types
-
-    foo::<i16>(42_i16);
-    //~^ ERROR mismatched types
-    foo::<i16>(42_i16);
-    //~^ ERROR mismatched types
-    foo::<i16>(42_i16);
-    //~^ ERROR mismatched types
-    foo::<i16>(42_i16);
-    //~^ ERROR mismatched types
-    foo::<i16>(42_i16);
-    //~^ ERROR mismatched types
-    foo::<i16>(42_i16);
-    //~^ ERROR mismatched types
-    foo::<i16>(42_i16);
-    //~^ ERROR mismatched types
-    foo::<i16>(42_i16);
-    //~^ ERROR mismatched types
-    foo::<i16>(42_i16);
-    foo::<i16>(42_i16);
-    //~^ ERROR mismatched types
-    foo::<i16>(42i16);
-    //~^ ERROR mismatched types
-    foo::<i16>(42i16);
-    //~^ ERROR mismatched types
-
-    foo::<u8>(42_u8);
-    //~^ ERROR mismatched types
-    foo::<u8>(42_u8);
-    //~^ ERROR mismatched types
-    foo::<u8>(42_u8);
-    //~^ ERROR mismatched types
-    foo::<u8>(42_u8);
-    //~^ ERROR mismatched types
-    foo::<u8>(42_u8);
-    foo::<u8>(42_u8);
-    //~^ ERROR mismatched types
-    foo::<u8>(42_u8);
-    //~^ ERROR mismatched types
-    foo::<u8>(42_u8);
-    //~^ ERROR mismatched types
-    foo::<u8>(42_u8);
-    //~^ ERROR mismatched types
-    foo::<u8>(42_u8);
-    //~^ ERROR mismatched types
-    foo::<u8>(42u8);
-    //~^ ERROR mismatched types
-    foo::<u8>(42u8);
-    //~^ ERROR mismatched types
-
-    foo::<i8>(42_i8);
-    //~^ ERROR mismatched types
-    foo::<i8>(42_i8);
-    //~^ ERROR mismatched types
-    foo::<i8>(42_i8);
-    //~^ ERROR mismatched types
-    foo::<i8>(42_i8);
-    //~^ ERROR mismatched types
-    foo::<i8>(42_i8);
-    //~^ ERROR mismatched types
-    foo::<i8>(42_i8);
-    //~^ ERROR mismatched types
-    foo::<i8>(42_i8);
-    //~^ ERROR mismatched types
-    foo::<i8>(42_i8);
-    //~^ ERROR mismatched types
-    foo::<i8>(42_i8);
-    //~^ ERROR mismatched types
-    foo::<i8>(42_i8);
-    foo::<i8>(42i8);
-    //~^ ERROR mismatched types
-    foo::<i8>(42i8);
-    //~^ ERROR mismatched types
-
-    foo::<f64>(42_f64);
-    //~^ ERROR mismatched types
-    foo::<f64>(42_f64);
-    //~^ ERROR mismatched types
-    foo::<f64>(42_u32.into());
-    //~^ ERROR mismatched types
-    foo::<f64>(42_u16.into());
-    //~^ ERROR mismatched types
-    foo::<f64>(42_u8.into());
-    //~^ ERROR mismatched types
-    foo::<f64>(42_f64);
-    //~^ ERROR mismatched types
-    foo::<f64>(42_f64);
-    //~^ ERROR mismatched types
-    foo::<f64>(42_i32.into());
-    //~^ ERROR mismatched types
-    foo::<f64>(42_i16.into());
-    //~^ ERROR mismatched types
-    foo::<f64>(42_i8.into());
-    //~^ ERROR mismatched types
-    foo::<f64>(42.0_f64);
-    foo::<f64>(42.0_f64);
-    //~^ ERROR mismatched types
-
-    foo::<f32>(42_f32);
-    //~^ ERROR mismatched types
-    foo::<f32>(42_f32);
-    //~^ ERROR mismatched types
-    foo::<f32>(42_f32);
-    //~^ ERROR mismatched types
-    foo::<f32>(42_u16.into());
-    //~^ ERROR mismatched types
-    foo::<f32>(42_u8.into());
-    //~^ ERROR mismatched types
-    foo::<f32>(42_f32);
-    //~^ ERROR mismatched types
-    foo::<f32>(42_f32);
-    //~^ ERROR mismatched types
-    foo::<f32>(42_f32);
-    //~^ ERROR mismatched types
-    foo::<f32>(42_i16.into());
-    //~^ ERROR mismatched types
-    foo::<f32>(42_i8.into());
-    //~^ ERROR mismatched types
-    foo::<f32>(42.0_f32);
-    //~^ ERROR mismatched types
-    foo::<f32>(42.0_f32);
-
-    foo::<u32>((42_u8 as u16).into());
-    //~^ ERROR mismatched types
-    foo::<i32>((-42_i8).into());
-    //~^ ERROR mismatched types
-}
diff --git a/src/test/ui/numeric/numeric-suffix.rs b/src/test/ui/numeric/numeric-suffix.rs
deleted file mode 100644 (file)
index ca38ed8..0000000
+++ /dev/null
@@ -1,298 +0,0 @@
-// run-rustfix
-
-fn foo<N>(_x: N) {}
-
-fn main() {
-    foo::<usize>(42_usize);
-    foo::<usize>(42_u64);
-    //~^ ERROR mismatched types
-    foo::<usize>(42_u32);
-    //~^ ERROR mismatched types
-    foo::<usize>(42_u16);
-    //~^ ERROR mismatched types
-    foo::<usize>(42_u8);
-    //~^ ERROR mismatched types
-    foo::<usize>(42_isize);
-    //~^ ERROR mismatched types
-    foo::<usize>(42_i64);
-    //~^ ERROR mismatched types
-    foo::<usize>(42_i32);
-    //~^ ERROR mismatched types
-    foo::<usize>(42_i16);
-    //~^ ERROR mismatched types
-    foo::<usize>(42_i8);
-    //~^ ERROR mismatched types
-    foo::<usize>(42.0_f64);
-    //~^ ERROR mismatched types
-    foo::<usize>(42.0_f32);
-    //~^ ERROR mismatched types
-
-    foo::<isize>(42_usize);
-    //~^ ERROR mismatched types
-    foo::<isize>(42_u64);
-    //~^ ERROR mismatched types
-    foo::<isize>(42_u32);
-    //~^ ERROR mismatched types
-    foo::<isize>(42_u16);
-    //~^ ERROR mismatched types
-    foo::<isize>(42_u8);
-    //~^ ERROR mismatched types
-    foo::<isize>(42_isize);
-    foo::<isize>(42_i64);
-    //~^ ERROR mismatched types
-    foo::<isize>(42_i32);
-    //~^ ERROR mismatched types
-    foo::<isize>(42_i16);
-    //~^ ERROR mismatched types
-    foo::<isize>(42_i8);
-    //~^ ERROR mismatched types
-    foo::<isize>(42.0_f64);
-    //~^ ERROR mismatched types
-    foo::<isize>(42.0_f32);
-    //~^ ERROR mismatched types
-
-    foo::<u64>(42_usize);
-    //~^ ERROR mismatched types
-    foo::<u64>(42_u64);
-    foo::<u64>(42_u32);
-    //~^ ERROR mismatched types
-    foo::<u64>(42_u16);
-    //~^ ERROR mismatched types
-    foo::<u64>(42_u8);
-    //~^ ERROR mismatched types
-    foo::<u64>(42_isize);
-    //~^ ERROR mismatched types
-    foo::<u64>(42_i64);
-    //~^ ERROR mismatched types
-    foo::<u64>(42_i32);
-    //~^ ERROR mismatched types
-    foo::<u64>(42_i16);
-    //~^ ERROR mismatched types
-    foo::<u64>(42_i8);
-    //~^ ERROR mismatched types
-    foo::<u64>(42.0_f64);
-    //~^ ERROR mismatched types
-    foo::<u64>(42.0_f32);
-    //~^ ERROR mismatched types
-
-    foo::<i64>(42_usize);
-    //~^ ERROR mismatched types
-    foo::<i64>(42_u64);
-    //~^ ERROR mismatched types
-    foo::<i64>(42_u32);
-    //~^ ERROR mismatched types
-    foo::<i64>(42_u16);
-    //~^ ERROR mismatched types
-    foo::<i64>(42_u8);
-    //~^ ERROR mismatched types
-    foo::<i64>(42_isize);
-    //~^ ERROR mismatched types
-    foo::<i64>(42_i64);
-    foo::<i64>(42_i32);
-    //~^ ERROR mismatched types
-    foo::<i64>(42_i16);
-    //~^ ERROR mismatched types
-    foo::<i64>(42_i8);
-    //~^ ERROR mismatched types
-    foo::<i64>(42.0_f64);
-    //~^ ERROR mismatched types
-    foo::<i64>(42.0_f32);
-    //~^ ERROR mismatched types
-
-    foo::<u32>(42_usize);
-    //~^ ERROR mismatched types
-    foo::<u32>(42_u64);
-    //~^ ERROR mismatched types
-    foo::<u32>(42_u32);
-    foo::<u32>(42_u16);
-    //~^ ERROR mismatched types
-    foo::<u32>(42_u8);
-    //~^ ERROR mismatched types
-    foo::<u32>(42_isize);
-    //~^ ERROR mismatched types
-    foo::<u32>(42_i64);
-    //~^ ERROR mismatched types
-    foo::<u32>(42_i32);
-    //~^ ERROR mismatched types
-    foo::<u32>(42_i16);
-    //~^ ERROR mismatched types
-    foo::<u32>(42_i8);
-    //~^ ERROR mismatched types
-    foo::<u32>(42.0_f64);
-    //~^ ERROR mismatched types
-    foo::<u32>(42.0_f32);
-    //~^ ERROR mismatched types
-
-    foo::<i32>(42_usize);
-    //~^ ERROR mismatched types
-    foo::<i32>(42_u64);
-    //~^ ERROR mismatched types
-    foo::<i32>(42_u32);
-    //~^ ERROR mismatched types
-    foo::<i32>(42_u16);
-    //~^ ERROR mismatched types
-    foo::<i32>(42_u8);
-    //~^ ERROR mismatched types
-    foo::<i32>(42_isize);
-    //~^ ERROR mismatched types
-    foo::<i32>(42_i64);
-    //~^ ERROR mismatched types
-    foo::<i32>(42_i32);
-    foo::<i32>(42_i16);
-    //~^ ERROR mismatched types
-    foo::<i32>(42_i8);
-    //~^ ERROR mismatched types
-    foo::<i32>(42.0_f64);
-    //~^ ERROR mismatched types
-    foo::<i32>(42.0_f32);
-    //~^ ERROR mismatched types
-
-    foo::<u16>(42_usize);
-    //~^ ERROR mismatched types
-    foo::<u16>(42_u64);
-    //~^ ERROR mismatched types
-    foo::<u16>(42_u32);
-    //~^ ERROR mismatched types
-    foo::<u16>(42_u16);
-    foo::<u16>(42_u8);
-    //~^ ERROR mismatched types
-    foo::<u16>(42_isize);
-    //~^ ERROR mismatched types
-    foo::<u16>(42_i64);
-    //~^ ERROR mismatched types
-    foo::<u16>(42_i32);
-    //~^ ERROR mismatched types
-    foo::<u16>(42_i16);
-    //~^ ERROR mismatched types
-    foo::<u16>(42_i8);
-    //~^ ERROR mismatched types
-    foo::<u16>(42.0_f64);
-    //~^ ERROR mismatched types
-    foo::<u16>(42.0_f32);
-    //~^ ERROR mismatched types
-
-    foo::<i16>(42_usize);
-    //~^ ERROR mismatched types
-    foo::<i16>(42_u64);
-    //~^ ERROR mismatched types
-    foo::<i16>(42_u32);
-    //~^ ERROR mismatched types
-    foo::<i16>(42_u16);
-    //~^ ERROR mismatched types
-    foo::<i16>(42_u8);
-    //~^ ERROR mismatched types
-    foo::<i16>(42_isize);
-    //~^ ERROR mismatched types
-    foo::<i16>(42_i64);
-    //~^ ERROR mismatched types
-    foo::<i16>(42_i32);
-    //~^ ERROR mismatched types
-    foo::<i16>(42_i16);
-    foo::<i16>(42_i8);
-    //~^ ERROR mismatched types
-    foo::<i16>(42.0_f64);
-    //~^ ERROR mismatched types
-    foo::<i16>(42.0_f32);
-    //~^ ERROR mismatched types
-
-    foo::<u8>(42_usize);
-    //~^ ERROR mismatched types
-    foo::<u8>(42_u64);
-    //~^ ERROR mismatched types
-    foo::<u8>(42_u32);
-    //~^ ERROR mismatched types
-    foo::<u8>(42_u16);
-    //~^ ERROR mismatched types
-    foo::<u8>(42_u8);
-    foo::<u8>(42_isize);
-    //~^ ERROR mismatched types
-    foo::<u8>(42_i64);
-    //~^ ERROR mismatched types
-    foo::<u8>(42_i32);
-    //~^ ERROR mismatched types
-    foo::<u8>(42_i16);
-    //~^ ERROR mismatched types
-    foo::<u8>(42_i8);
-    //~^ ERROR mismatched types
-    foo::<u8>(42.0_f64);
-    //~^ ERROR mismatched types
-    foo::<u8>(42.0_f32);
-    //~^ ERROR mismatched types
-
-    foo::<i8>(42_usize);
-    //~^ ERROR mismatched types
-    foo::<i8>(42_u64);
-    //~^ ERROR mismatched types
-    foo::<i8>(42_u32);
-    //~^ ERROR mismatched types
-    foo::<i8>(42_u16);
-    //~^ ERROR mismatched types
-    foo::<i8>(42_u8);
-    //~^ ERROR mismatched types
-    foo::<i8>(42_isize);
-    //~^ ERROR mismatched types
-    foo::<i8>(42_i64);
-    //~^ ERROR mismatched types
-    foo::<i8>(42_i32);
-    //~^ ERROR mismatched types
-    foo::<i8>(42_i16);
-    //~^ ERROR mismatched types
-    foo::<i8>(42_i8);
-    foo::<i8>(42.0_f64);
-    //~^ ERROR mismatched types
-    foo::<i8>(42.0_f32);
-    //~^ ERROR mismatched types
-
-    foo::<f64>(42_usize);
-    //~^ ERROR mismatched types
-    foo::<f64>(42_u64);
-    //~^ ERROR mismatched types
-    foo::<f64>(42_u32);
-    //~^ ERROR mismatched types
-    foo::<f64>(42_u16);
-    //~^ ERROR mismatched types
-    foo::<f64>(42_u8);
-    //~^ ERROR mismatched types
-    foo::<f64>(42_isize);
-    //~^ ERROR mismatched types
-    foo::<f64>(42_i64);
-    //~^ ERROR mismatched types
-    foo::<f64>(42_i32);
-    //~^ ERROR mismatched types
-    foo::<f64>(42_i16);
-    //~^ ERROR mismatched types
-    foo::<f64>(42_i8);
-    //~^ ERROR mismatched types
-    foo::<f64>(42.0_f64);
-    foo::<f64>(42.0_f32);
-    //~^ ERROR mismatched types
-
-    foo::<f32>(42_usize);
-    //~^ ERROR mismatched types
-    foo::<f32>(42_u64);
-    //~^ ERROR mismatched types
-    foo::<f32>(42_u32);
-    //~^ ERROR mismatched types
-    foo::<f32>(42_u16);
-    //~^ ERROR mismatched types
-    foo::<f32>(42_u8);
-    //~^ ERROR mismatched types
-    foo::<f32>(42_isize);
-    //~^ ERROR mismatched types
-    foo::<f32>(42_i64);
-    //~^ ERROR mismatched types
-    foo::<f32>(42_i32);
-    //~^ ERROR mismatched types
-    foo::<f32>(42_i16);
-    //~^ ERROR mismatched types
-    foo::<f32>(42_i8);
-    //~^ ERROR mismatched types
-    foo::<f32>(42.0_f64);
-    //~^ ERROR mismatched types
-    foo::<f32>(42.0_f32);
-
-    foo::<u32>(42_u8 as u16);
-    //~^ ERROR mismatched types
-    foo::<i32>(-42_i8);
-    //~^ ERROR mismatched types
-}
diff --git a/src/test/ui/numeric/numeric-suffix.stderr b/src/test/ui/numeric/numeric-suffix.stderr
deleted file mode 100644 (file)
index b829946..0000000
+++ /dev/null
@@ -1,1477 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/numeric-suffix.rs:7:18
-   |
-LL |     foo::<usize>(42_u64);
-   |                  ^^^^^^ expected `usize`, found `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
-   |
-LL |     foo::<usize>(42_u32);
-   |                  ^^^^^^ expected `usize`, found `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
-   |
-LL |     foo::<usize>(42_u16);
-   |                  ^^^^^^ expected `usize`, found `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
-   |
-LL |     foo::<usize>(42_u8);
-   |                  ^^^^^ expected `usize`, found `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
-   |
-LL |     foo::<usize>(42_isize);
-   |                  ^^^^^^^^ expected `usize`, found `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
-   |
-LL |     foo::<usize>(42_i64);
-   |                  ^^^^^^ expected `usize`, found `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
-   |
-LL |     foo::<usize>(42_i32);
-   |                  ^^^^^^ expected `usize`, found `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
-   |
-LL |     foo::<usize>(42_i16);
-   |                  ^^^^^^ expected `usize`, found `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
-   |
-LL |     foo::<usize>(42_i8);
-   |                  ^^^^^ expected `usize`, found `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
-   |
-LL |     foo::<usize>(42.0_f64);
-   |                  ^^^^^^^^ expected `usize`, found `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
-   |
-LL |     foo::<usize>(42.0_f32);
-   |                  ^^^^^^^^ expected `usize`, found `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
-   |
-LL |     foo::<isize>(42_usize);
-   |                  ^^^^^^^^ expected `isize`, found `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
-   |
-LL |     foo::<isize>(42_u64);
-   |                  ^^^^^^ expected `isize`, found `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
-   |
-LL |     foo::<isize>(42_u32);
-   |                  ^^^^^^ expected `isize`, found `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
-   |
-LL |     foo::<isize>(42_u16);
-   |                  ^^^^^^ expected `isize`, found `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
-   |
-LL |     foo::<isize>(42_u8);
-   |                  ^^^^^ expected `isize`, found `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
-   |
-LL |     foo::<isize>(42_i64);
-   |                  ^^^^^^ expected `isize`, found `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
-   |
-LL |     foo::<isize>(42_i32);
-   |                  ^^^^^^ expected `isize`, found `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
-   |
-LL |     foo::<isize>(42_i16);
-   |                  ^^^^^^ expected `isize`, found `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
-   |
-LL |     foo::<isize>(42_i8);
-   |                  ^^^^^ expected `isize`, found `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
-   |
-LL |     foo::<isize>(42.0_f64);
-   |                  ^^^^^^^^ expected `isize`, found `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
-   |
-LL |     foo::<isize>(42.0_f32);
-   |                  ^^^^^^^^ expected `isize`, found `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
-   |
-LL |     foo::<u64>(42_usize);
-   |                ^^^^^^^^ expected `u64`, found `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
-   |
-LL |     foo::<u64>(42_u32);
-   |                ^^^^^^ expected `u64`, found `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
-   |
-LL |     foo::<u64>(42_u16);
-   |                ^^^^^^ expected `u64`, found `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
-   |
-LL |     foo::<u64>(42_u8);
-   |                ^^^^^ expected `u64`, found `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
-   |
-LL |     foo::<u64>(42_isize);
-   |                ^^^^^^^^ expected `u64`, found `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
-   |
-LL |     foo::<u64>(42_i64);
-   |                ^^^^^^ expected `u64`, found `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
-   |
-LL |     foo::<u64>(42_i32);
-   |                ^^^^^^ expected `u64`, found `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
-   |
-LL |     foo::<u64>(42_i16);
-   |                ^^^^^^ expected `u64`, found `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
-   |
-LL |     foo::<u64>(42_i8);
-   |                ^^^^^ expected `u64`, found `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
-   |
-LL |     foo::<u64>(42.0_f64);
-   |                ^^^^^^^^ expected `u64`, found `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
-   |
-LL |     foo::<u64>(42.0_f32);
-   |                ^^^^^^^^ expected `u64`, found `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
-   |
-LL |     foo::<i64>(42_usize);
-   |                ^^^^^^^^ expected `i64`, found `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
-   |
-LL |     foo::<i64>(42_u64);
-   |                ^^^^^^ expected `i64`, found `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
-   |
-LL |     foo::<i64>(42_u32);
-   |                ^^^^^^ expected `i64`, found `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
-   |
-LL |     foo::<i64>(42_u16);
-   |                ^^^^^^ expected `i64`, found `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
-   |
-LL |     foo::<i64>(42_u8);
-   |                ^^^^^ expected `i64`, found `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
-   |
-LL |     foo::<i64>(42_isize);
-   |                ^^^^^^^^ expected `i64`, found `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
-   |
-LL |     foo::<i64>(42_i32);
-   |                ^^^^^^ expected `i64`, found `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
-   |
-LL |     foo::<i64>(42_i16);
-   |                ^^^^^^ expected `i64`, found `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
-   |
-LL |     foo::<i64>(42_i8);
-   |                ^^^^^ expected `i64`, found `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
-   |
-LL |     foo::<i64>(42.0_f64);
-   |                ^^^^^^^^ expected `i64`, found `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
-   |
-LL |     foo::<i64>(42.0_f32);
-   |                ^^^^^^^^ expected `i64`, found `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
-   |
-LL |     foo::<u32>(42_usize);
-   |                ^^^^^^^^ expected `u32`, found `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
-   |
-LL |     foo::<u32>(42_u64);
-   |                ^^^^^^ expected `u32`, found `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
-   |
-LL |     foo::<u32>(42_u16);
-   |                ^^^^^^ expected `u32`, found `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
-   |
-LL |     foo::<u32>(42_u8);
-   |                ^^^^^ expected `u32`, found `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
-   |
-LL |     foo::<u32>(42_isize);
-   |                ^^^^^^^^ expected `u32`, found `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
-   |
-LL |     foo::<u32>(42_i64);
-   |                ^^^^^^ expected `u32`, found `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
-   |
-LL |     foo::<u32>(42_i32);
-   |                ^^^^^^ expected `u32`, found `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
-   |
-LL |     foo::<u32>(42_i16);
-   |                ^^^^^^ expected `u32`, found `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
-   |
-LL |     foo::<u32>(42_i8);
-   |                ^^^^^ expected `u32`, found `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
-   |
-LL |     foo::<u32>(42.0_f64);
-   |                ^^^^^^^^ expected `u32`, found `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
-   |
-LL |     foo::<u32>(42.0_f32);
-   |                ^^^^^^^^ expected `u32`, found `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
-   |
-LL |     foo::<i32>(42_usize);
-   |                ^^^^^^^^ expected `i32`, found `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
-   |
-LL |     foo::<i32>(42_u64);
-   |                ^^^^^^ expected `i32`, found `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
-   |
-LL |     foo::<i32>(42_u32);
-   |                ^^^^^^ expected `i32`, found `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
-   |
-LL |     foo::<i32>(42_u16);
-   |                ^^^^^^ expected `i32`, found `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
-   |
-LL |     foo::<i32>(42_u8);
-   |                ^^^^^ expected `i32`, found `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
-   |
-LL |     foo::<i32>(42_isize);
-   |                ^^^^^^^^ expected `i32`, found `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
-   |
-LL |     foo::<i32>(42_i64);
-   |                ^^^^^^ expected `i32`, found `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
-   |
-LL |     foo::<i32>(42_i16);
-   |                ^^^^^^ expected `i32`, found `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
-   |
-LL |     foo::<i32>(42_i8);
-   |                ^^^^^ expected `i32`, found `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
-   |
-LL |     foo::<i32>(42.0_f64);
-   |                ^^^^^^^^ expected `i32`, found `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
-   |
-LL |     foo::<i32>(42.0_f32);
-   |                ^^^^^^^^ expected `i32`, found `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
-   |
-LL |     foo::<u16>(42_usize);
-   |                ^^^^^^^^ expected `u16`, found `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
-   |
-LL |     foo::<u16>(42_u64);
-   |                ^^^^^^ expected `u16`, found `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
-   |
-LL |     foo::<u16>(42_u32);
-   |                ^^^^^^ expected `u16`, found `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
-   |
-LL |     foo::<u16>(42_u8);
-   |                ^^^^^ expected `u16`, found `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
-   |
-LL |     foo::<u16>(42_isize);
-   |                ^^^^^^^^ expected `u16`, found `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
-   |
-LL |     foo::<u16>(42_i64);
-   |                ^^^^^^ expected `u16`, found `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
-   |
-LL |     foo::<u16>(42_i32);
-   |                ^^^^^^ expected `u16`, found `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
-   |
-LL |     foo::<u16>(42_i16);
-   |                ^^^^^^ expected `u16`, found `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
-   |
-LL |     foo::<u16>(42_i8);
-   |                ^^^^^ expected `u16`, found `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
-   |
-LL |     foo::<u16>(42.0_f64);
-   |                ^^^^^^^^ expected `u16`, found `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
-   |
-LL |     foo::<u16>(42.0_f32);
-   |                ^^^^^^^^ expected `u16`, found `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
-   |
-LL |     foo::<i16>(42_usize);
-   |                ^^^^^^^^ expected `i16`, found `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
-   |
-LL |     foo::<i16>(42_u64);
-   |                ^^^^^^ expected `i16`, found `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
-   |
-LL |     foo::<i16>(42_u32);
-   |                ^^^^^^ expected `i16`, found `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
-   |
-LL |     foo::<i16>(42_u16);
-   |                ^^^^^^ expected `i16`, found `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
-   |
-LL |     foo::<i16>(42_u8);
-   |                ^^^^^ expected `i16`, found `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
-   |
-LL |     foo::<i16>(42_isize);
-   |                ^^^^^^^^ expected `i16`, found `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
-   |
-LL |     foo::<i16>(42_i64);
-   |                ^^^^^^ expected `i16`, found `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
-   |
-LL |     foo::<i16>(42_i32);
-   |                ^^^^^^ expected `i16`, found `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
-   |
-LL |     foo::<i16>(42_i8);
-   |                ^^^^^ expected `i16`, found `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
-   |
-LL |     foo::<i16>(42.0_f64);
-   |                ^^^^^^^^ expected `i16`, found `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
-   |
-LL |     foo::<i16>(42.0_f32);
-   |                ^^^^^^^^ expected `i16`, found `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
-   |
-LL |     foo::<u8>(42_usize);
-   |               ^^^^^^^^ expected `u8`, found `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
-   |
-LL |     foo::<u8>(42_u64);
-   |               ^^^^^^ expected `u8`, found `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
-   |
-LL |     foo::<u8>(42_u32);
-   |               ^^^^^^ expected `u8`, found `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
-   |
-LL |     foo::<u8>(42_u16);
-   |               ^^^^^^ expected `u8`, found `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
-   |
-LL |     foo::<u8>(42_isize);
-   |               ^^^^^^^^ expected `u8`, found `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
-   |
-LL |     foo::<u8>(42_i64);
-   |               ^^^^^^ expected `u8`, found `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
-   |
-LL |     foo::<u8>(42_i32);
-   |               ^^^^^^ expected `u8`, found `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
-   |
-LL |     foo::<u8>(42_i16);
-   |               ^^^^^^ expected `u8`, found `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
-   |
-LL |     foo::<u8>(42_i8);
-   |               ^^^^^ expected `u8`, found `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
-   |
-LL |     foo::<u8>(42.0_f64);
-   |               ^^^^^^^^ expected `u8`, found `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
-   |
-LL |     foo::<u8>(42.0_f32);
-   |               ^^^^^^^^ expected `u8`, found `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
-   |
-LL |     foo::<i8>(42_usize);
-   |               ^^^^^^^^ expected `i8`, found `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
-   |
-LL |     foo::<i8>(42_u64);
-   |               ^^^^^^ expected `i8`, found `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
-   |
-LL |     foo::<i8>(42_u32);
-   |               ^^^^^^ expected `i8`, found `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
-   |
-LL |     foo::<i8>(42_u16);
-   |               ^^^^^^ expected `i8`, found `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
-   |
-LL |     foo::<i8>(42_u8);
-   |               ^^^^^ expected `i8`, found `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
-   |
-LL |     foo::<i8>(42_isize);
-   |               ^^^^^^^^ expected `i8`, found `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
-   |
-LL |     foo::<i8>(42_i64);
-   |               ^^^^^^ expected `i8`, found `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
-   |
-LL |     foo::<i8>(42_i32);
-   |               ^^^^^^ expected `i8`, found `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
-   |
-LL |     foo::<i8>(42_i16);
-   |               ^^^^^^ expected `i8`, found `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
-   |
-LL |     foo::<i8>(42.0_f64);
-   |               ^^^^^^^^ expected `i8`, found `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
-   |
-LL |     foo::<i8>(42.0_f32);
-   |               ^^^^^^^^ expected `i8`, found `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
-   |
-LL |     foo::<f64>(42_usize);
-   |                ^^^^^^^^ expected `f64`, found `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
-   |
-LL |     foo::<f64>(42_u64);
-   |                ^^^^^^ expected `f64`, found `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
-   |
-LL |     foo::<f64>(42_u32);
-   |                ^^^^^^ expected `f64`, found `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
-   |
-LL |     foo::<f64>(42_u16);
-   |                ^^^^^^ expected `f64`, found `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
-   |
-LL |     foo::<f64>(42_u8);
-   |                ^^^^^ expected `f64`, found `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
-   |
-LL |     foo::<f64>(42_isize);
-   |                ^^^^^^^^ expected `f64`, found `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
-   |
-LL |     foo::<f64>(42_i64);
-   |                ^^^^^^ expected `f64`, found `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
-   |
-LL |     foo::<f64>(42_i32);
-   |                ^^^^^^ expected `f64`, found `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
-   |
-LL |     foo::<f64>(42_i16);
-   |                ^^^^^^ expected `f64`, found `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
-   |
-LL |     foo::<f64>(42_i8);
-   |                ^^^^^ expected `f64`, found `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
-   |
-LL |     foo::<f64>(42.0_f32);
-   |                ^^^^^^^^ expected `f64`, found `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
-   |
-LL |     foo::<f32>(42_usize);
-   |                ^^^^^^^^ expected `f32`, found `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
-   |
-LL |     foo::<f32>(42_u64);
-   |                ^^^^^^ expected `f32`, found `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
-   |
-LL |     foo::<f32>(42_u32);
-   |                ^^^^^^ expected `f32`, found `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
-   |
-LL |     foo::<f32>(42_u16);
-   |                ^^^^^^ expected `f32`, found `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
-   |
-LL |     foo::<f32>(42_u8);
-   |                ^^^^^ expected `f32`, found `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
-   |
-LL |     foo::<f32>(42_isize);
-   |                ^^^^^^^^ expected `f32`, found `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
-   |
-LL |     foo::<f32>(42_i64);
-   |                ^^^^^^ expected `f32`, found `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
-   |
-LL |     foo::<f32>(42_i32);
-   |                ^^^^^^ expected `f32`, found `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
-   |
-LL |     foo::<f32>(42_i16);
-   |                ^^^^^^ expected `f32`, found `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
-   |
-LL |     foo::<f32>(42_i8);
-   |                ^^^^^ expected `f32`, found `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
-   |
-LL |     foo::<f32>(42.0_f64);
-   |                ^^^^^^^^ expected `f32`, found `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`
-   |
-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`
-   |
-LL |     foo::<i32>((-42_i8).into());
-   |                +      ++++++++
-
-error: aborting due to 134 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/numeric/numeric-suffix/numeric-suffix-i32.fixed b/src/test/ui/numeric/numeric-suffix/numeric-suffix-i32.fixed
new file mode 100644 (file)
index 0000000..6e8c54d
--- /dev/null
@@ -0,0 +1,73 @@
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+    foo::<i32>(42_i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>(42_i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>(42_i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>(42_i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>(42_i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>(42_i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>(42_i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>(42_i32);
+    foo::<i32>(42_i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>(42_i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>(42i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>(42i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+}
diff --git a/src/test/ui/numeric/numeric-suffix/numeric-suffix-i32.rs b/src/test/ui/numeric/numeric-suffix/numeric-suffix-i32.rs
new file mode 100644 (file)
index 0000000..b47b0ed
--- /dev/null
@@ -0,0 +1,73 @@
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+    foo::<i32>(42_usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>(42_u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>(42_u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>(42_u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>(42_u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>(42_isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>(42_i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>(42_i32);
+    foo::<i32>(42_i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>(42_i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>(42.0_f64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>(42.0_f32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+}
diff --git a/src/test/ui/numeric/numeric-suffix/numeric-suffix-i32.stderr b/src/test/ui/numeric/numeric-suffix/numeric-suffix-i32.stderr
new file mode 100644 (file)
index 0000000..f4fb14e
--- /dev/null
@@ -0,0 +1,201 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i32.rs:28:16
+   |
+LL |     foo::<i32>(42_usize);
+   |     ---------- ^^^^^^^^ expected `i32`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `usize` to `i32`
+   |
+LL |     foo::<i32>(42_i32);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i32.rs:32:16
+   |
+LL |     foo::<i32>(42_u64);
+   |     ---------- ^^^^^^ expected `i32`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u64` to `i32`
+   |
+LL |     foo::<i32>(42_i32);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i32.rs:36:16
+   |
+LL |     foo::<i32>(42_u32);
+   |     ---------- ^^^^^^ expected `i32`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u32` to `i32`
+   |
+LL |     foo::<i32>(42_i32);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i32.rs:40:16
+   |
+LL |     foo::<i32>(42_u16);
+   |     ---------- ^^^^^^ expected `i32`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u16` to `i32`
+   |
+LL |     foo::<i32>(42_i32);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i32.rs:44:16
+   |
+LL |     foo::<i32>(42_u8);
+   |     ---------- ^^^^^ expected `i32`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u8` to `i32`
+   |
+LL |     foo::<i32>(42_i32);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i32.rs:48:16
+   |
+LL |     foo::<i32>(42_isize);
+   |     ---------- ^^^^^^^^ expected `i32`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `isize` to `i32`
+   |
+LL |     foo::<i32>(42_i32);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i32.rs:52:16
+   |
+LL |     foo::<i32>(42_i64);
+   |     ---------- ^^^^^^ expected `i32`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i64` to `i32`
+   |
+LL |     foo::<i32>(42_i32);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i32.rs:57:16
+   |
+LL |     foo::<i32>(42_i16);
+   |     ---------- ^^^^^^ expected `i32`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i16` to `i32`
+   |
+LL |     foo::<i32>(42_i32);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i32.rs:61:16
+   |
+LL |     foo::<i32>(42_i8);
+   |     ---------- ^^^^^ expected `i32`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i8` to `i32`
+   |
+LL |     foo::<i32>(42_i32);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i32.rs:65:16
+   |
+LL |     foo::<i32>(42.0_f64);
+   |     ---------- ^^^^^^^^ expected `i32`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `f64` to `i32`
+   |
+LL |     foo::<i32>(42i32);
+   |                  ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i32.rs:69:16
+   |
+LL |     foo::<i32>(42.0_f32);
+   |     ---------- ^^^^^^^^ expected `i32`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `f32` to `i32`
+   |
+LL |     foo::<i32>(42i32);
+   |                  ~~~
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/numeric/numeric-suffix/numeric-suffix-i64.fixed b/src/test/ui/numeric/numeric-suffix/numeric-suffix-i64.fixed
new file mode 100644 (file)
index 0000000..03821cd
--- /dev/null
@@ -0,0 +1,73 @@
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+    foo::<i64>(42_i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i64>(42_i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i64>(42_i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i64>(42_i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i64>(42_i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i64>(42_i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i64>(42_i64);
+    foo::<i64>(42_i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i64>(42_i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i64>(42_i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i64>(42i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i64>(42i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+}
diff --git a/src/test/ui/numeric/numeric-suffix/numeric-suffix-i64.rs b/src/test/ui/numeric/numeric-suffix/numeric-suffix-i64.rs
new file mode 100644 (file)
index 0000000..629fe7e
--- /dev/null
@@ -0,0 +1,73 @@
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+    foo::<i64>(42_usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i64>(42_u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i64>(42_u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i64>(42_u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i64>(42_u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i64>(42_isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i64>(42_i64);
+    foo::<i64>(42_i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i64>(42_i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i64>(42_i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i64>(42.0_f64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i64>(42.0_f32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+}
diff --git a/src/test/ui/numeric/numeric-suffix/numeric-suffix-i64.stderr b/src/test/ui/numeric/numeric-suffix/numeric-suffix-i64.stderr
new file mode 100644 (file)
index 0000000..47efe9f
--- /dev/null
@@ -0,0 +1,201 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i64.rs:28:16
+   |
+LL |     foo::<i64>(42_usize);
+   |     ---------- ^^^^^^^^ expected `i64`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `usize` to `i64`
+   |
+LL |     foo::<i64>(42_i64);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i64.rs:32:16
+   |
+LL |     foo::<i64>(42_u64);
+   |     ---------- ^^^^^^ expected `i64`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u64` to `i64`
+   |
+LL |     foo::<i64>(42_i64);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i64.rs:36:16
+   |
+LL |     foo::<i64>(42_u32);
+   |     ---------- ^^^^^^ expected `i64`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u32` to `i64`
+   |
+LL |     foo::<i64>(42_i64);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i64.rs:40:16
+   |
+LL |     foo::<i64>(42_u16);
+   |     ---------- ^^^^^^ expected `i64`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u16` to `i64`
+   |
+LL |     foo::<i64>(42_i64);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i64.rs:44:16
+   |
+LL |     foo::<i64>(42_u8);
+   |     ---------- ^^^^^ expected `i64`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u8` to `i64`
+   |
+LL |     foo::<i64>(42_i64);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i64.rs:48:16
+   |
+LL |     foo::<i64>(42_isize);
+   |     ---------- ^^^^^^^^ expected `i64`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `isize` to `i64`
+   |
+LL |     foo::<i64>(42_i64);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i64.rs:53:16
+   |
+LL |     foo::<i64>(42_i32);
+   |     ---------- ^^^^^^ expected `i64`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i32` to `i64`
+   |
+LL |     foo::<i64>(42_i64);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i64.rs:57:16
+   |
+LL |     foo::<i64>(42_i16);
+   |     ---------- ^^^^^^ expected `i64`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i16` to `i64`
+   |
+LL |     foo::<i64>(42_i64);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i64.rs:61:16
+   |
+LL |     foo::<i64>(42_i8);
+   |     ---------- ^^^^^ expected `i64`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i8` to `i64`
+   |
+LL |     foo::<i64>(42_i64);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i64.rs:65:16
+   |
+LL |     foo::<i64>(42.0_f64);
+   |     ---------- ^^^^^^^^ expected `i64`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `f64` to `i64`
+   |
+LL |     foo::<i64>(42i64);
+   |                  ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-i64.rs:69:16
+   |
+LL |     foo::<i64>(42.0_f32);
+   |     ---------- ^^^^^^^^ expected `i64`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-i64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `f32` to `i64`
+   |
+LL |     foo::<i64>(42i64);
+   |                  ~~~
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/numeric/numeric-suffix/numeric-suffix-isize.fixed b/src/test/ui/numeric/numeric-suffix/numeric-suffix-isize.fixed
new file mode 100644 (file)
index 0000000..faed65c
--- /dev/null
@@ -0,0 +1,73 @@
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+    foo::<isize>(42_isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<isize>(42_isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<isize>(42_isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<isize>(42_isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<isize>(42_isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<isize>(42_isize);
+    foo::<isize>(42_isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<isize>(42_isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<isize>(42_isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<isize>(42_isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<isize>(42isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<isize>(42isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+}
diff --git a/src/test/ui/numeric/numeric-suffix/numeric-suffix-isize.rs b/src/test/ui/numeric/numeric-suffix/numeric-suffix-isize.rs
new file mode 100644 (file)
index 0000000..df0b4cb
--- /dev/null
@@ -0,0 +1,73 @@
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+    foo::<isize>(42_usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<isize>(42_u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<isize>(42_u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<isize>(42_u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<isize>(42_u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<isize>(42_isize);
+    foo::<isize>(42_i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<isize>(42_i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<isize>(42_i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<isize>(42_i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<isize>(42.0_f64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<isize>(42.0_f32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+}
diff --git a/src/test/ui/numeric/numeric-suffix/numeric-suffix-isize.stderr b/src/test/ui/numeric/numeric-suffix/numeric-suffix-isize.stderr
new file mode 100644 (file)
index 0000000..28b7941
--- /dev/null
@@ -0,0 +1,201 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-isize.rs:28:18
+   |
+LL |     foo::<isize>(42_usize);
+   |     ------------ ^^^^^^^^ expected `isize`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-isize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `usize` to `isize`
+   |
+LL |     foo::<isize>(42_isize);
+   |                     ~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-isize.rs:32:18
+   |
+LL |     foo::<isize>(42_u64);
+   |     ------------ ^^^^^^ expected `isize`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-isize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u64` to `isize`
+   |
+LL |     foo::<isize>(42_isize);
+   |                     ~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-isize.rs:36:18
+   |
+LL |     foo::<isize>(42_u32);
+   |     ------------ ^^^^^^ expected `isize`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-isize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u32` to `isize`
+   |
+LL |     foo::<isize>(42_isize);
+   |                     ~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-isize.rs:40:18
+   |
+LL |     foo::<isize>(42_u16);
+   |     ------------ ^^^^^^ expected `isize`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-isize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u16` to `isize`
+   |
+LL |     foo::<isize>(42_isize);
+   |                     ~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-isize.rs:44:18
+   |
+LL |     foo::<isize>(42_u8);
+   |     ------------ ^^^^^ expected `isize`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-isize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u8` to `isize`
+   |
+LL |     foo::<isize>(42_isize);
+   |                     ~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-isize.rs:49:18
+   |
+LL |     foo::<isize>(42_i64);
+   |     ------------ ^^^^^^ expected `isize`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-isize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i64` to `isize`
+   |
+LL |     foo::<isize>(42_isize);
+   |                     ~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-isize.rs:53:18
+   |
+LL |     foo::<isize>(42_i32);
+   |     ------------ ^^^^^^ expected `isize`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-isize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i32` to `isize`
+   |
+LL |     foo::<isize>(42_isize);
+   |                     ~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-isize.rs:57:18
+   |
+LL |     foo::<isize>(42_i16);
+   |     ------------ ^^^^^^ expected `isize`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-isize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i16` to `isize`
+   |
+LL |     foo::<isize>(42_isize);
+   |                     ~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-isize.rs:61:18
+   |
+LL |     foo::<isize>(42_i8);
+   |     ------------ ^^^^^ expected `isize`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-isize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i8` to `isize`
+   |
+LL |     foo::<isize>(42_isize);
+   |                     ~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-isize.rs:65:18
+   |
+LL |     foo::<isize>(42.0_f64);
+   |     ------------ ^^^^^^^^ expected `isize`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-isize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `f64` to `isize`
+   |
+LL |     foo::<isize>(42isize);
+   |                    ~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-isize.rs:69:18
+   |
+LL |     foo::<isize>(42.0_f32);
+   |     ------------ ^^^^^^^^ expected `isize`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-isize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `f32` to `isize`
+   |
+LL |     foo::<isize>(42isize);
+   |                    ~~~~~
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/numeric/numeric-suffix/numeric-suffix-u32.fixed b/src/test/ui/numeric/numeric-suffix/numeric-suffix-u32.fixed
new file mode 100644 (file)
index 0000000..5955829
--- /dev/null
@@ -0,0 +1,73 @@
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+    foo::<u32>(42_u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u32>(42_u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u32>(42_u32);
+    foo::<u32>(42_u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u32>(42_u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u32>(42_u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u32>(42_u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u32>(42_u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u32>(42_u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u32>(42_u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u32>(42u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u32>(42u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+}
diff --git a/src/test/ui/numeric/numeric-suffix/numeric-suffix-u32.rs b/src/test/ui/numeric/numeric-suffix/numeric-suffix-u32.rs
new file mode 100644 (file)
index 0000000..5c30303
--- /dev/null
@@ -0,0 +1,73 @@
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+    foo::<u32>(42_usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u32>(42_u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u32>(42_u32);
+    foo::<u32>(42_u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u32>(42_u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u32>(42_isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u32>(42_i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u32>(42_i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u32>(42_i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u32>(42_i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u32>(42.0_f64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u32>(42.0_f32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+}
diff --git a/src/test/ui/numeric/numeric-suffix/numeric-suffix-u32.stderr b/src/test/ui/numeric/numeric-suffix/numeric-suffix-u32.stderr
new file mode 100644 (file)
index 0000000..d966893
--- /dev/null
@@ -0,0 +1,201 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u32.rs:28:16
+   |
+LL |     foo::<u32>(42_usize);
+   |     ---------- ^^^^^^^^ expected `u32`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `usize` to `u32`
+   |
+LL |     foo::<u32>(42_u32);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u32.rs:32:16
+   |
+LL |     foo::<u32>(42_u64);
+   |     ---------- ^^^^^^ expected `u32`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u64` to `u32`
+   |
+LL |     foo::<u32>(42_u32);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u32.rs:37:16
+   |
+LL |     foo::<u32>(42_u16);
+   |     ---------- ^^^^^^ expected `u32`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u16` to `u32`
+   |
+LL |     foo::<u32>(42_u32);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u32.rs:41:16
+   |
+LL |     foo::<u32>(42_u8);
+   |     ---------- ^^^^^ expected `u32`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u8` to `u32`
+   |
+LL |     foo::<u32>(42_u32);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u32.rs:45:16
+   |
+LL |     foo::<u32>(42_isize);
+   |     ---------- ^^^^^^^^ expected `u32`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `isize` to `u32`
+   |
+LL |     foo::<u32>(42_u32);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u32.rs:49:16
+   |
+LL |     foo::<u32>(42_i64);
+   |     ---------- ^^^^^^ expected `u32`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i64` to `u32`
+   |
+LL |     foo::<u32>(42_u32);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u32.rs:53:16
+   |
+LL |     foo::<u32>(42_i32);
+   |     ---------- ^^^^^^ expected `u32`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i32` to `u32`
+   |
+LL |     foo::<u32>(42_u32);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u32.rs:57:16
+   |
+LL |     foo::<u32>(42_i16);
+   |     ---------- ^^^^^^ expected `u32`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i16` to `u32`
+   |
+LL |     foo::<u32>(42_u32);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u32.rs:61:16
+   |
+LL |     foo::<u32>(42_i8);
+   |     ---------- ^^^^^ expected `u32`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i8` to `u32`
+   |
+LL |     foo::<u32>(42_u32);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u32.rs:65:16
+   |
+LL |     foo::<u32>(42.0_f64);
+   |     ---------- ^^^^^^^^ expected `u32`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `f64` to `u32`
+   |
+LL |     foo::<u32>(42u32);
+   |                  ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u32.rs:69:16
+   |
+LL |     foo::<u32>(42.0_f32);
+   |     ---------- ^^^^^^^^ expected `u32`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u32.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `f32` to `u32`
+   |
+LL |     foo::<u32>(42u32);
+   |                  ~~~
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/numeric/numeric-suffix/numeric-suffix-u64.fixed b/src/test/ui/numeric/numeric-suffix/numeric-suffix-u64.fixed
new file mode 100644 (file)
index 0000000..4623c21
--- /dev/null
@@ -0,0 +1,73 @@
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+    foo::<u64>(42_u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u64>(42_u64);
+    foo::<u64>(42_u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u64>(42_u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u64>(42_u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u64>(42_u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u64>(42_u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u64>(42_u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u64>(42_u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u64>(42_u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u64>(42u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u64>(42u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+}
diff --git a/src/test/ui/numeric/numeric-suffix/numeric-suffix-u64.rs b/src/test/ui/numeric/numeric-suffix/numeric-suffix-u64.rs
new file mode 100644 (file)
index 0000000..3e9995c
--- /dev/null
@@ -0,0 +1,73 @@
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+    foo::<u64>(42_usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u64>(42_u64);
+    foo::<u64>(42_u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u64>(42_u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u64>(42_u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u64>(42_isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u64>(42_i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u64>(42_i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u64>(42_i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u64>(42_i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u64>(42.0_f64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u64>(42.0_f32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+}
diff --git a/src/test/ui/numeric/numeric-suffix/numeric-suffix-u64.stderr b/src/test/ui/numeric/numeric-suffix/numeric-suffix-u64.stderr
new file mode 100644 (file)
index 0000000..ff332fa
--- /dev/null
@@ -0,0 +1,201 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u64.rs:28:16
+   |
+LL |     foo::<u64>(42_usize);
+   |     ---------- ^^^^^^^^ expected `u64`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `usize` to `u64`
+   |
+LL |     foo::<u64>(42_u64);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u64.rs:33:16
+   |
+LL |     foo::<u64>(42_u32);
+   |     ---------- ^^^^^^ expected `u64`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u32` to `u64`
+   |
+LL |     foo::<u64>(42_u64);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u64.rs:37:16
+   |
+LL |     foo::<u64>(42_u16);
+   |     ---------- ^^^^^^ expected `u64`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u16` to `u64`
+   |
+LL |     foo::<u64>(42_u64);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u64.rs:41:16
+   |
+LL |     foo::<u64>(42_u8);
+   |     ---------- ^^^^^ expected `u64`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u8` to `u64`
+   |
+LL |     foo::<u64>(42_u64);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u64.rs:45:16
+   |
+LL |     foo::<u64>(42_isize);
+   |     ---------- ^^^^^^^^ expected `u64`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `isize` to `u64`
+   |
+LL |     foo::<u64>(42_u64);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u64.rs:49:16
+   |
+LL |     foo::<u64>(42_i64);
+   |     ---------- ^^^^^^ expected `u64`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i64` to `u64`
+   |
+LL |     foo::<u64>(42_u64);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u64.rs:53:16
+   |
+LL |     foo::<u64>(42_i32);
+   |     ---------- ^^^^^^ expected `u64`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i32` to `u64`
+   |
+LL |     foo::<u64>(42_u64);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u64.rs:57:16
+   |
+LL |     foo::<u64>(42_i16);
+   |     ---------- ^^^^^^ expected `u64`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i16` to `u64`
+   |
+LL |     foo::<u64>(42_u64);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u64.rs:61:16
+   |
+LL |     foo::<u64>(42_i8);
+   |     ---------- ^^^^^ expected `u64`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i8` to `u64`
+   |
+LL |     foo::<u64>(42_u64);
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u64.rs:65:16
+   |
+LL |     foo::<u64>(42.0_f64);
+   |     ---------- ^^^^^^^^ expected `u64`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `f64` to `u64`
+   |
+LL |     foo::<u64>(42u64);
+   |                  ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-u64.rs:69:16
+   |
+LL |     foo::<u64>(42.0_f32);
+   |     ---------- ^^^^^^^^ expected `u64`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-u64.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `f32` to `u64`
+   |
+LL |     foo::<u64>(42u64);
+   |                  ~~~
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/numeric/numeric-suffix/numeric-suffix-usize.fixed b/src/test/ui/numeric/numeric-suffix/numeric-suffix-usize.fixed
new file mode 100644 (file)
index 0000000..6cb5243
--- /dev/null
@@ -0,0 +1,73 @@
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+    foo::<usize>(42_usize);
+    foo::<usize>(42_usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<usize>(42_usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<usize>(42_usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<usize>(42_usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<usize>(42_usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<usize>(42_usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<usize>(42_usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<usize>(42_usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<usize>(42_usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<usize>(42usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<usize>(42usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+}
diff --git a/src/test/ui/numeric/numeric-suffix/numeric-suffix-usize.rs b/src/test/ui/numeric/numeric-suffix/numeric-suffix-usize.rs
new file mode 100644 (file)
index 0000000..a2304ba
--- /dev/null
@@ -0,0 +1,73 @@
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+    foo::<usize>(42_usize);
+    foo::<usize>(42_u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<usize>(42_u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<usize>(42_u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<usize>(42_u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<usize>(42_isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<usize>(42_i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<usize>(42_i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<usize>(42_i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<usize>(42_i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<usize>(42.0_f64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<usize>(42.0_f32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+}
diff --git a/src/test/ui/numeric/numeric-suffix/numeric-suffix-usize.stderr b/src/test/ui/numeric/numeric-suffix/numeric-suffix-usize.stderr
new file mode 100644 (file)
index 0000000..4889abe
--- /dev/null
@@ -0,0 +1,201 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-usize.rs:29:18
+   |
+LL |     foo::<usize>(42_u64);
+   |     ------------ ^^^^^^ expected `usize`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-usize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u64` to `usize`
+   |
+LL |     foo::<usize>(42_usize);
+   |                     ~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-usize.rs:33:18
+   |
+LL |     foo::<usize>(42_u32);
+   |     ------------ ^^^^^^ expected `usize`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-usize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u32` to `usize`
+   |
+LL |     foo::<usize>(42_usize);
+   |                     ~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-usize.rs:37:18
+   |
+LL |     foo::<usize>(42_u16);
+   |     ------------ ^^^^^^ expected `usize`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-usize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u16` to `usize`
+   |
+LL |     foo::<usize>(42_usize);
+   |                     ~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-usize.rs:41:18
+   |
+LL |     foo::<usize>(42_u8);
+   |     ------------ ^^^^^ expected `usize`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-usize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `u8` to `usize`
+   |
+LL |     foo::<usize>(42_usize);
+   |                     ~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-usize.rs:45:18
+   |
+LL |     foo::<usize>(42_isize);
+   |     ------------ ^^^^^^^^ expected `usize`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-usize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `isize` to `usize`
+   |
+LL |     foo::<usize>(42_usize);
+   |                     ~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-usize.rs:49:18
+   |
+LL |     foo::<usize>(42_i64);
+   |     ------------ ^^^^^^ expected `usize`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-usize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i64` to `usize`
+   |
+LL |     foo::<usize>(42_usize);
+   |                     ~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-usize.rs:53:18
+   |
+LL |     foo::<usize>(42_i32);
+   |     ------------ ^^^^^^ expected `usize`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-usize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i32` to `usize`
+   |
+LL |     foo::<usize>(42_usize);
+   |                     ~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-usize.rs:57:18
+   |
+LL |     foo::<usize>(42_i16);
+   |     ------------ ^^^^^^ expected `usize`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-usize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i16` to `usize`
+   |
+LL |     foo::<usize>(42_usize);
+   |                     ~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-usize.rs:61:18
+   |
+LL |     foo::<usize>(42_i8);
+   |     ------------ ^^^^^ expected `usize`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-usize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `i8` to `usize`
+   |
+LL |     foo::<usize>(42_usize);
+   |                     ~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-usize.rs:65:18
+   |
+LL |     foo::<usize>(42.0_f64);
+   |     ------------ ^^^^^^^^ expected `usize`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-usize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `f64` to `usize`
+   |
+LL |     foo::<usize>(42usize);
+   |                    ~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix-usize.rs:69:18
+   |
+LL |     foo::<usize>(42.0_f32);
+   |     ------------ ^^^^^^^^ expected `usize`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix-usize.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `f32` to `usize`
+   |
+LL |     foo::<usize>(42usize);
+   |                    ~~~~~
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/numeric/numeric-suffix/numeric-suffix.fixed b/src/test/ui/numeric/numeric-suffix/numeric-suffix.fixed
new file mode 100644 (file)
index 0000000..69934db
--- /dev/null
@@ -0,0 +1,427 @@
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+
+fn main() {
+    foo::<u16>(42_u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u16>(42_u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u16>(42_u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u16>(42_u16);
+    foo::<u16>(42_u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u16>(42_u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u16>(42_u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u16>(42_u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u16>(42_u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u16>(42_u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u16>(42u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u16>(42u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+
+    foo::<i16>(42_i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i16>(42_i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i16>(42_i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i16>(42_i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i16>(42_i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i16>(42_i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i16>(42_i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i16>(42_i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i16>(42_i16);
+    foo::<i16>(42_i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i16>(42i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i16>(42i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+
+    foo::<u8>(42_u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u8>(42_u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u8>(42_u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u8>(42_u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u8>(42_u8);
+    foo::<u8>(42_u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u8>(42_u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u8>(42_u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u8>(42_u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u8>(42_u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u8>(42u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u8>(42u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+
+    foo::<i8>(42_i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i8>(42_i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i8>(42_i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i8>(42_i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i8>(42_i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i8>(42_i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i8>(42_i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i8>(42_i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i8>(42_i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i8>(42_i8);
+    foo::<i8>(42i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i8>(42i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+
+    foo::<f64>(42_f64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f64>(42_f64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f64>(42_u32.into());
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f64>(42_u16.into());
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f64>(42_u8.into());
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f64>(42_f64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f64>(42_f64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f64>(42_i32.into());
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f64>(42_i16.into());
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f64>(42_i8.into());
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f64>(42.0_f64);
+    foo::<f64>(42.0_f64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+
+    foo::<f32>(42_f32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42_f32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42_f32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42_u16.into());
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42_u8.into());
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42_f32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42_f32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42_f32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42_i16.into());
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42_i8.into());
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42.0_f32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42.0_f32);
+
+    foo::<u32>((42_u8 as u16).into());
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>((-42_i8).into());
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+}
diff --git a/src/test/ui/numeric/numeric-suffix/numeric-suffix.rs b/src/test/ui/numeric/numeric-suffix/numeric-suffix.rs
new file mode 100644 (file)
index 0000000..dabf43f
--- /dev/null
@@ -0,0 +1,427 @@
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+
+fn main() {
+    foo::<u16>(42_usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u16>(42_u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u16>(42_u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u16>(42_u16);
+    foo::<u16>(42_u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u16>(42_isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u16>(42_i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u16>(42_i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u16>(42_i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u16>(42_i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u16>(42.0_f64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u16>(42.0_f32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+
+    foo::<i16>(42_usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i16>(42_u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i16>(42_u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i16>(42_u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i16>(42_u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i16>(42_isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i16>(42_i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i16>(42_i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i16>(42_i16);
+    foo::<i16>(42_i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i16>(42.0_f64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i16>(42.0_f32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+
+    foo::<u8>(42_usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u8>(42_u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u8>(42_u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u8>(42_u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u8>(42_u8);
+    foo::<u8>(42_isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u8>(42_i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u8>(42_i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u8>(42_i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u8>(42_i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u8>(42.0_f64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<u8>(42.0_f32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+
+    foo::<i8>(42_usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i8>(42_u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i8>(42_u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i8>(42_u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i8>(42_u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i8>(42_isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i8>(42_i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i8>(42_i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i8>(42_i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i8>(42_i8);
+    foo::<i8>(42.0_f64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i8>(42.0_f32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+
+    foo::<f64>(42_usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f64>(42_u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f64>(42_u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f64>(42_u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f64>(42_u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f64>(42_isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f64>(42_i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f64>(42_i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f64>(42_i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f64>(42_i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f64>(42.0_f64);
+    foo::<f64>(42.0_f32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+
+    foo::<f32>(42_usize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42_u64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42_u32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42_u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42_u8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42_isize);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42_i64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42_i32);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42_i16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42_i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42.0_f64);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<f32>(42.0_f32);
+
+    foo::<u32>(42_u8 as u16);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+    foo::<i32>(-42_i8);
+    //~^ ERROR mismatched types
+    //~| NOTE expected
+    //~| NOTE arguments
+}
diff --git a/src/test/ui/numeric/numeric-suffix/numeric-suffix.stderr b/src/test/ui/numeric/numeric-suffix/numeric-suffix.stderr
new file mode 100644 (file)
index 0000000..e05913b
--- /dev/null
@@ -0,0 +1,1227 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix.rs:143:16
+   |
+LL |     foo::<u16>(42_usize);
+   |     ---------- ^^^^^^^^ expected `u16`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:147:16
+   |
+LL |     foo::<u16>(42_u64);
+   |     ---------- ^^^^^^ expected `u16`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:151:16
+   |
+LL |     foo::<u16>(42_u32);
+   |     ---------- ^^^^^^ expected `u16`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:156:16
+   |
+LL |     foo::<u16>(42_u8);
+   |     ---------- ^^^^^ expected `u16`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:160:16
+   |
+LL |     foo::<u16>(42_isize);
+   |     ---------- ^^^^^^^^ expected `u16`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:164:16
+   |
+LL |     foo::<u16>(42_i64);
+   |     ---------- ^^^^^^ expected `u16`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:168:16
+   |
+LL |     foo::<u16>(42_i32);
+   |     ---------- ^^^^^^ expected `u16`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:172:16
+   |
+LL |     foo::<u16>(42_i16);
+   |     ---------- ^^^^^^ expected `u16`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:176:16
+   |
+LL |     foo::<u16>(42_i8);
+   |     ---------- ^^^^^ expected `u16`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:180:16
+   |
+LL |     foo::<u16>(42.0_f64);
+   |     ---------- ^^^^^^^^ expected `u16`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `f64` to `u16`
+   |
+LL |     foo::<u16>(42u16);
+   |                  ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix.rs:184:16
+   |
+LL |     foo::<u16>(42.0_f32);
+   |     ---------- ^^^^^^^^ expected `u16`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `f32` to `u16`
+   |
+LL |     foo::<u16>(42u16);
+   |                  ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix.rs:189:16
+   |
+LL |     foo::<i16>(42_usize);
+   |     ---------- ^^^^^^^^ expected `i16`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:193:16
+   |
+LL |     foo::<i16>(42_u64);
+   |     ---------- ^^^^^^ expected `i16`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:197:16
+   |
+LL |     foo::<i16>(42_u32);
+   |     ---------- ^^^^^^ expected `i16`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:201:16
+   |
+LL |     foo::<i16>(42_u16);
+   |     ---------- ^^^^^^ expected `i16`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:205:16
+   |
+LL |     foo::<i16>(42_u8);
+   |     ---------- ^^^^^ expected `i16`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:209:16
+   |
+LL |     foo::<i16>(42_isize);
+   |     ---------- ^^^^^^^^ expected `i16`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:213:16
+   |
+LL |     foo::<i16>(42_i64);
+   |     ---------- ^^^^^^ expected `i16`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:217:16
+   |
+LL |     foo::<i16>(42_i32);
+   |     ---------- ^^^^^^ expected `i16`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:222:16
+   |
+LL |     foo::<i16>(42_i8);
+   |     ---------- ^^^^^ expected `i16`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:226:16
+   |
+LL |     foo::<i16>(42.0_f64);
+   |     ---------- ^^^^^^^^ expected `i16`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `f64` to `i16`
+   |
+LL |     foo::<i16>(42i16);
+   |                  ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix.rs:230:16
+   |
+LL |     foo::<i16>(42.0_f32);
+   |     ---------- ^^^^^^^^ expected `i16`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `f32` to `i16`
+   |
+LL |     foo::<i16>(42i16);
+   |                  ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix.rs:235:15
+   |
+LL |     foo::<u8>(42_usize);
+   |     --------- ^^^^^^^^ expected `u8`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:239:15
+   |
+LL |     foo::<u8>(42_u64);
+   |     --------- ^^^^^^ expected `u8`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:243:15
+   |
+LL |     foo::<u8>(42_u32);
+   |     --------- ^^^^^^ expected `u8`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:247:15
+   |
+LL |     foo::<u8>(42_u16);
+   |     --------- ^^^^^^ expected `u8`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:252:15
+   |
+LL |     foo::<u8>(42_isize);
+   |     --------- ^^^^^^^^ expected `u8`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:256:15
+   |
+LL |     foo::<u8>(42_i64);
+   |     --------- ^^^^^^ expected `u8`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:260:15
+   |
+LL |     foo::<u8>(42_i32);
+   |     --------- ^^^^^^ expected `u8`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:264:15
+   |
+LL |     foo::<u8>(42_i16);
+   |     --------- ^^^^^^ expected `u8`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:268:15
+   |
+LL |     foo::<u8>(42_i8);
+   |     --------- ^^^^^ expected `u8`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:272:15
+   |
+LL |     foo::<u8>(42.0_f64);
+   |     --------- ^^^^^^^^ expected `u8`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `f64` to `u8`
+   |
+LL |     foo::<u8>(42u8);
+   |                 ~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix.rs:276:15
+   |
+LL |     foo::<u8>(42.0_f32);
+   |     --------- ^^^^^^^^ expected `u8`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `f32` to `u8`
+   |
+LL |     foo::<u8>(42u8);
+   |                 ~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix.rs:281:15
+   |
+LL |     foo::<i8>(42_usize);
+   |     --------- ^^^^^^^^ expected `i8`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:285:15
+   |
+LL |     foo::<i8>(42_u64);
+   |     --------- ^^^^^^ expected `i8`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:289:15
+   |
+LL |     foo::<i8>(42_u32);
+   |     --------- ^^^^^^ expected `i8`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:293:15
+   |
+LL |     foo::<i8>(42_u16);
+   |     --------- ^^^^^^ expected `i8`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:297:15
+   |
+LL |     foo::<i8>(42_u8);
+   |     --------- ^^^^^ expected `i8`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:301:15
+   |
+LL |     foo::<i8>(42_isize);
+   |     --------- ^^^^^^^^ expected `i8`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:305:15
+   |
+LL |     foo::<i8>(42_i64);
+   |     --------- ^^^^^^ expected `i8`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:309:15
+   |
+LL |     foo::<i8>(42_i32);
+   |     --------- ^^^^^^ expected `i8`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:313:15
+   |
+LL |     foo::<i8>(42_i16);
+   |     --------- ^^^^^^ expected `i8`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:318:15
+   |
+LL |     foo::<i8>(42.0_f64);
+   |     --------- ^^^^^^^^ expected `i8`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `f64` to `i8`
+   |
+LL |     foo::<i8>(42i8);
+   |                 ~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix.rs:322:15
+   |
+LL |     foo::<i8>(42.0_f32);
+   |     --------- ^^^^^^^^ expected `i8`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: change the type of the numeric literal from `f32` to `i8`
+   |
+LL |     foo::<i8>(42i8);
+   |                 ~~
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-suffix.rs:327:16
+   |
+LL |     foo::<f64>(42_usize);
+   |     ---------- ^^^^^^^^ expected `f64`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:331:16
+   |
+LL |     foo::<f64>(42_u64);
+   |     ---------- ^^^^^^ expected `f64`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:335:16
+   |
+LL |     foo::<f64>(42_u32);
+   |     ---------- ^^^^^^ expected `f64`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:339:16
+   |
+LL |     foo::<f64>(42_u16);
+   |     ---------- ^^^^^^ expected `f64`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:343:16
+   |
+LL |     foo::<f64>(42_u8);
+   |     ---------- ^^^^^ expected `f64`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:347:16
+   |
+LL |     foo::<f64>(42_isize);
+   |     ---------- ^^^^^^^^ expected `f64`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:351:16
+   |
+LL |     foo::<f64>(42_i64);
+   |     ---------- ^^^^^^ expected `f64`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:355:16
+   |
+LL |     foo::<f64>(42_i32);
+   |     ---------- ^^^^^^ expected `f64`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:359:16
+   |
+LL |     foo::<f64>(42_i16);
+   |     ---------- ^^^^^^ expected `f64`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:363:16
+   |
+LL |     foo::<f64>(42_i8);
+   |     ---------- ^^^^^ expected `f64`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:368:16
+   |
+LL |     foo::<f64>(42.0_f32);
+   |     ---------- ^^^^^^^^ expected `f64`, found `f32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:373:16
+   |
+LL |     foo::<f32>(42_usize);
+   |     ---------- ^^^^^^^^ expected `f32`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:377:16
+   |
+LL |     foo::<f32>(42_u64);
+   |     ---------- ^^^^^^ expected `f32`, found `u64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:381:16
+   |
+LL |     foo::<f32>(42_u32);
+   |     ---------- ^^^^^^ expected `f32`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:385:16
+   |
+LL |     foo::<f32>(42_u16);
+   |     ---------- ^^^^^^ expected `f32`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:389:16
+   |
+LL |     foo::<f32>(42_u8);
+   |     ---------- ^^^^^ expected `f32`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:393:16
+   |
+LL |     foo::<f32>(42_isize);
+   |     ---------- ^^^^^^^^ expected `f32`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:397:16
+   |
+LL |     foo::<f32>(42_i64);
+   |     ---------- ^^^^^^ expected `f32`, found `i64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:401:16
+   |
+LL |     foo::<f32>(42_i32);
+   |     ---------- ^^^^^^ expected `f32`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:405:16
+   |
+LL |     foo::<f32>(42_i16);
+   |     ---------- ^^^^^^ expected `f32`, found `i16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:409:16
+   |
+LL |     foo::<f32>(42_i8);
+   |     ---------- ^^^^^ expected `f32`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:413:16
+   |
+LL |     foo::<f32>(42.0_f64);
+   |     ---------- ^^^^^^^^ expected `f32`, found `f64`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:419:16
+   |
+LL |     foo::<u32>(42_u8 as u16);
+   |     ---------- ^^^^^^^^^^^^ expected `u32`, found `u16`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+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:423:16
+   |
+LL |     foo::<i32>(-42_i8);
+   |     ---------- ^^^^^^ expected `i32`, found `i8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/numeric-suffix.rs:3:4
+   |
+LL | fn foo<N>(_x: N) {}
+   |    ^^^    -----
+help: you can convert an `i8` to an `i32`
+   |
+LL |     foo::<i32>((-42_i8).into());
+   |                +      ++++++++
+
+error: aborting due to 68 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/packed/issue-27060-rpass.stderr b/src/test/ui/packed/issue-27060-rpass.stderr
new file mode 100644 (file)
index 0000000..667b70a
--- /dev/null
@@ -0,0 +1,68 @@
+Future incompatibility report: Future breakage diagnostic:
+warning: reference to packed field is unaligned
+  --> $DIR/issue-27060-rpass.rs:15:13
+   |
+LL |     let _ = &good.data; // ok
+   |             ^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-27060-rpass.rs:11:9
+   |
+LL | #[allow(unaligned_references)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+warning: reference to packed field is unaligned
+  --> $DIR/issue-27060-rpass.rs:16:13
+   |
+LL |     let _ = &good.data2[0]; // ok
+   |             ^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-27060-rpass.rs:11:9
+   |
+LL | #[allow(unaligned_references)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+warning: reference to packed field is unaligned
+  --> $DIR/issue-27060-rpass.rs:18:13
+   |
+LL |     let _ = &good.data;
+   |             ^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-27060-rpass.rs:11:9
+   |
+LL | #[allow(unaligned_references)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+warning: reference to packed field is unaligned
+  --> $DIR/issue-27060-rpass.rs:19:13
+   |
+LL |     let _ = &good.data2[0];
+   |             ^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-27060-rpass.rs:11:9
+   |
+LL | #[allow(unaligned_references)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
index 5317a61671945b8ebffac9abb0cd73512b068cd9..886a00239f98c5165d80b6ac40d32c75f3b9d661 100644 (file)
@@ -5,7 +5,6 @@ pub struct Good {
     aligned: [u8; 32],
 }
 
-#[deny(unaligned_references)]
 fn main() {
     let good = Good {
         data: &0,
index bba056d59f831a246422d6f59662b2598dc9c589..1bab16e6ddaa38047dba17032d8787d926356c60 100644 (file)
@@ -1,21 +1,17 @@
 error: reference to packed field is unaligned
-  --> $DIR/issue-27060.rs:16:13
+  --> $DIR/issue-27060.rs:15:13
    |
 LL |     let _ = &good.data;
    |             ^^^^^^^^^^
    |
-note: the lint level is defined here
-  --> $DIR/issue-27060.rs:8:8
-   |
-LL | #[deny(unaligned_references)]
-   |        ^^^^^^^^^^^^^^^^^^^^
+   = note: `#[deny(unaligned_references)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
    = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
 
 error: reference to packed field is unaligned
-  --> $DIR/issue-27060.rs:18:13
+  --> $DIR/issue-27060.rs:17:13
    |
 LL |     let _ = &good.data2[0];
    |             ^^^^^^^^^^^^^^
@@ -26,7 +22,7 @@ LL |     let _ = &good.data2[0];
    = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
 
 error: reference to packed field is unaligned
-  --> $DIR/issue-27060.rs:21:13
+  --> $DIR/issue-27060.rs:20:13
    |
 LL |     let _ = &good.data;
    |             ^^^^^^^^^^
@@ -37,7 +33,7 @@ LL |     let _ = &good.data;
    = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
 
 error: reference to packed field is unaligned
-  --> $DIR/issue-27060.rs:23:13
+  --> $DIR/issue-27060.rs:22:13
    |
 LL |     let _ = &good.data2[0];
    |             ^^^^^^^^^^^^^^
@@ -49,3 +45,55 @@ LL |     let _ = &good.data2[0];
 
 error: aborting due to 4 previous errors
 
+Future incompatibility report: Future breakage diagnostic:
+error: reference to packed field is unaligned
+  --> $DIR/issue-27060.rs:15:13
+   |
+LL |     let _ = &good.data;
+   |             ^^^^^^^^^^
+   |
+   = note: `#[deny(unaligned_references)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+  --> $DIR/issue-27060.rs:17:13
+   |
+LL |     let _ = &good.data2[0];
+   |             ^^^^^^^^^^^^^^
+   |
+   = note: `#[deny(unaligned_references)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+  --> $DIR/issue-27060.rs:20:13
+   |
+LL |     let _ = &good.data;
+   |             ^^^^^^^^^^
+   |
+   = note: `#[deny(unaligned_references)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+  --> $DIR/issue-27060.rs:22:13
+   |
+LL |     let _ = &good.data2[0];
+   |             ^^^^^^^^^^^^^^
+   |
+   = note: `#[deny(unaligned_references)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
index fb3875e680496f9fb4adaf3d18a8cd97c961e6cf..d86698cbf3848d50e86ee6d2abfb6673794df0d0 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 #![allow(dead_code)]
-#![deny(unaligned_references)]
 #![feature(raw_ref_op)]
 // ignore-emscripten weird assertion?
 
index ad932fdcd01c47fe5d132bcaa3ff06d775cb1b80..00bddfe40b25b7ae3a4e6a00e473f0608cb308cc 100644 (file)
@@ -9,6 +9,7 @@ struct Foo4C {
     baz: usize
 }
 
+#[warn(unaligned_references)]
 pub fn main() {
     let foo = Foo4C { bar: 1, baz: 2 };
     let brw = &foo.baz; //~WARN reference to packed field is unaligned
index 04585b499862be41d06877ff91a1607ad788753d..dcd1c19fa16a8344eb9c6638116a665f8adf3962 100644 (file)
@@ -1,10 +1,14 @@
 warning: reference to packed field is unaligned
-  --> $DIR/packed-struct-borrow-element-64bit.rs:14:15
+  --> $DIR/packed-struct-borrow-element-64bit.rs:15:15
    |
 LL |     let brw = &foo.baz;
    |               ^^^^^^^^
    |
-   = note: `#[warn(unaligned_references)]` on by default
+note: the lint level is defined here
+  --> $DIR/packed-struct-borrow-element-64bit.rs:12:8
+   |
+LL | #[warn(unaligned_references)]
+   |        ^^^^^^^^^^^^^^^^^^^^
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
@@ -12,3 +16,20 @@ LL |     let brw = &foo.baz;
 
 warning: 1 warning emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: reference to packed field is unaligned
+  --> $DIR/packed-struct-borrow-element-64bit.rs:15:15
+   |
+LL |     let brw = &foo.baz;
+   |               ^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/packed-struct-borrow-element-64bit.rs:12:8
+   |
+LL | #[warn(unaligned_references)]
+   |        ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
index fb6c9c11d56944a7407c4805cb9cdf55c1646e6b..a6ee90cef44f055abd58354860efc8cc443e741d 100644 (file)
@@ -20,6 +20,7 @@ struct Foo4C {
     baz: usize
 }
 
+#[warn(unaligned_references)]
 pub fn main() {
     let foo = Foo1 { bar: 1, baz: 2 };
     let brw = &foo.baz; //~WARN reference to packed field is unaligned
index a50b130200151ef1dc543db30803b837a9396441..fb483227e20c124b78bac182246933bccaf44bf0 100644 (file)
@@ -1,17 +1,21 @@
 warning: reference to packed field is unaligned
-  --> $DIR/packed-struct-borrow-element.rs:25:15
+  --> $DIR/packed-struct-borrow-element.rs:26:15
    |
 LL |     let brw = &foo.baz;
    |               ^^^^^^^^
    |
-   = note: `#[warn(unaligned_references)]` on by default
+note: the lint level is defined here
+  --> $DIR/packed-struct-borrow-element.rs:23:8
+   |
+LL | #[warn(unaligned_references)]
+   |        ^^^^^^^^^^^^^^^^^^^^
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
    = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
 
 warning: reference to packed field is unaligned
-  --> $DIR/packed-struct-borrow-element.rs:30:15
+  --> $DIR/packed-struct-borrow-element.rs:31:15
    |
 LL |     let brw = &foo.baz;
    |               ^^^^^^^^
@@ -23,3 +27,37 @@ LL |     let brw = &foo.baz;
 
 warning: 2 warnings emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: reference to packed field is unaligned
+  --> $DIR/packed-struct-borrow-element.rs:26:15
+   |
+LL |     let brw = &foo.baz;
+   |               ^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/packed-struct-borrow-element.rs:23:8
+   |
+LL | #[warn(unaligned_references)]
+   |        ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+warning: reference to packed field is unaligned
+  --> $DIR/packed-struct-borrow-element.rs:31:15
+   |
+LL |     let brw = &foo.baz;
+   |               ^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/packed-struct-borrow-element.rs:23:8
+   |
+LL | #[warn(unaligned_references)]
+   |        ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
index 2d1554183ccccb8b9693cd7b12fcfccb0fa91764..21d753ad037253c09ba0fc1176bc643a1cd6b619 100644 (file)
@@ -1,26 +1,30 @@
-pub fn f(
+pub fn f( //~ NOTE function defined here
     /// Comment
     //~^ ERROR documentation comments cannot be applied to function parameters
     //~| NOTE doc comments are not allowed here
+    //~| NOTE
     id: u8,
     /// Other
     //~^ ERROR documentation comments cannot be applied to function parameters
     //~| NOTE doc comments are not allowed here
+    //~| NOTE
     a: u8,
 ) {}
 
 fn bar(id: #[allow(dead_code)] i32) {}
 //~^ ERROR attributes cannot be applied to a function parameter's type
 //~| NOTE attributes are not allowed here
+//~| NOTE function defined here
+//~| NOTE
 
 fn main() {
     // verify that the parser recovered and properly typechecked the args
     f("", "");
-    //~^ ERROR mismatched types
+    //~^ ERROR arguments to this function are incorrect
     //~| NOTE expected `u8`, found `&str`
-    //~| ERROR mismatched types
     //~| NOTE expected `u8`, found `&str`
     bar("");
     //~^ ERROR mismatched types
+    //~| NOTE arguments to this function are incorrect
     //~| NOTE expected `i32`, found `&str`
 }
index 41f2c080b9465532d553f9d2febab3c791f8fb1d..c8d7e2efe799d5c876f76ebbed08e36c12239781 100644 (file)
@@ -1,5 +1,5 @@
 error: attributes cannot be applied to a function parameter's type
-  --> $DIR/fn-arg-doc-comment.rs:12:12
+  --> $DIR/fn-arg-doc-comment.rs:14:12
    |
 LL | fn bar(id: #[allow(dead_code)] i32) {}
    |            ^^^^^^^^^^^^^^^^^^^ attributes are not allowed here
@@ -11,29 +11,51 @@ LL |     /// Comment
    |     ^^^^^^^^^^^ doc comments are not allowed here
 
 error: documentation comments cannot be applied to function parameters
-  --> $DIR/fn-arg-doc-comment.rs:6:5
+  --> $DIR/fn-arg-doc-comment.rs:7:5
    |
 LL |     /// Other
    |     ^^^^^^^^^ doc comments are not allowed here
 
-error[E0308]: mismatched types
-  --> $DIR/fn-arg-doc-comment.rs:18:7
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/fn-arg-doc-comment.rs:22:5
    |
 LL |     f("", "");
-   |       ^^ expected `u8`, found `&str`
-
-error[E0308]: mismatched types
-  --> $DIR/fn-arg-doc-comment.rs:18:11
+   |     ^ --  -- expected `u8`, found `&str`
+   |       |
+   |       expected `u8`, found `&str`
    |
-LL |     f("", "");
-   |           ^^ expected `u8`, found `&str`
+note: function defined here
+  --> $DIR/fn-arg-doc-comment.rs:1:8
+   |
+LL |   pub fn f(
+   |          ^
+LL | /     /// Comment
+LL | |
+LL | |
+LL | |
+LL | |     id: u8,
+   | |__________-
+LL | /     /// Other
+LL | |
+LL | |
+LL | |
+LL | |     a: u8,
+   | |_________-
 
 error[E0308]: mismatched types
-  --> $DIR/fn-arg-doc-comment.rs:23:9
+  --> $DIR/fn-arg-doc-comment.rs:26:9
    |
 LL |     bar("");
-   |         ^^ expected `i32`, found `&str`
+   |     --- ^^ expected `i32`, found `&str`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/fn-arg-doc-comment.rs:14:4
+   |
+LL | fn bar(id: #[allow(dead_code)] i32) {}
+   |    ^^^ ---------------------------
 
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/issue-61858.rs b/src/test/ui/parser/issue-61858.rs
new file mode 100644 (file)
index 0000000..6c3b565
--- /dev/null
@@ -0,0 +1,3 @@
+fn main() {
+    (if foobar) //~ ERROR expected `{`, found `)`
+}
diff --git a/src/test/ui/parser/issue-61858.stderr b/src/test/ui/parser/issue-61858.stderr
new file mode 100644 (file)
index 0000000..8b95d9c
--- /dev/null
@@ -0,0 +1,10 @@
+error: expected `{`, found `)`
+  --> $DIR/issue-61858.rs:2:15
+   |
+LL |     (if foobar)
+   |      --       ^ expected `{`
+   |      |
+   |      this `if` expression has a condition, but no block
+
+error: aborting due to previous error
+
index c800afdae2afb4ef205fbfdce14a090139c75504..4c2eff63ab5e839b277ef317b3b7a31b0c138ba7 100644 (file)
@@ -46,7 +46,15 @@ error[E0308]: mismatched types
   --> $DIR/pattern-error-continue.rs:28:7
    |
 LL |     f(true);
-   |       ^^^^ expected `char`, found `bool`
+   |     - ^^^^ expected `char`, found `bool`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/pattern-error-continue.rs:13:4
+   |
+LL | fn f(_c: char) {}
+   |    ^ --------
 
 error: aborting due to 5 previous errors
 
index 80a459c41257fab71d9309952db32d518c857f08..262a64acc544c20e60b22e1af0e493f7cd8e560a 100644 (file)
@@ -9,6 +9,11 @@ LL | | }
    |
    = note: expected fn pointer `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
                  found fn item `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
+note: associated function defined here
+  --> $SRC_DIR/proc_macro/src/bridge/client.rs:LL:COL
+   |
+LL |     pub const fn custom_derive(
+   |                  ^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 065e16a8227ca1e313f99f2f07a3637c716d3754..4cbf8869d0c59b4723857e55a21c45fd4adbbb96 100644 (file)
@@ -2,145 +2,217 @@ error[E0308]: mismatched types
   --> $DIR/issue-54505-no-literals.rs:16:16
    |
 LL |     take_range(std::ops::Range { start: 0, end: 1 });
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                |
-   |                expected reference, found struct `std::ops::Range`
-   |                help: consider borrowing here: `&std::ops::Range { start: 0, end: 1 }`
+   |     ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |          |
+   |     |          expected reference, found struct `std::ops::Range`
+   |     |          help: consider borrowing here: `&std::ops::Range { start: 0, end: 1 }`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `std::ops::Range<{integer}>`
+note: function defined here
+  --> $DIR/issue-54505-no-literals.rs:12:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-54505-no-literals.rs:21:16
    |
 LL |     take_range(::std::ops::Range { start: 0, end: 1 });
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                |
-   |                expected reference, found struct `std::ops::Range`
-   |                help: consider borrowing here: `&::std::ops::Range { start: 0, end: 1 }`
+   |     ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |          |
+   |     |          expected reference, found struct `std::ops::Range`
+   |     |          help: consider borrowing here: `&::std::ops::Range { start: 0, end: 1 }`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `std::ops::Range<{integer}>`
+note: function defined here
+  --> $DIR/issue-54505-no-literals.rs:12:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-54505-no-literals.rs:26:16
    |
 LL |     take_range(std::ops::RangeFrom { start: 1 });
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                |
-   |                expected reference, found struct `RangeFrom`
-   |                help: consider borrowing here: `&std::ops::RangeFrom { start: 1 }`
+   |     ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |          |
+   |     |          expected reference, found struct `RangeFrom`
+   |     |          help: consider borrowing here: `&std::ops::RangeFrom { start: 1 }`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `RangeFrom<{integer}>`
+note: function defined here
+  --> $DIR/issue-54505-no-literals.rs:12:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-54505-no-literals.rs:31:16
    |
 LL |     take_range(::std::ops::RangeFrom { start: 1 });
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                |
-   |                expected reference, found struct `RangeFrom`
-   |                help: consider borrowing here: `&::std::ops::RangeFrom { start: 1 }`
+   |     ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |          |
+   |     |          expected reference, found struct `RangeFrom`
+   |     |          help: consider borrowing here: `&::std::ops::RangeFrom { start: 1 }`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `RangeFrom<{integer}>`
+note: function defined here
+  --> $DIR/issue-54505-no-literals.rs:12:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-54505-no-literals.rs:36:16
    |
 LL |     take_range(std::ops::RangeFull {});
-   |                ^^^^^^^^^^^^^^^^^^^^^^
-   |                |
-   |                expected reference, found struct `RangeFull`
-   |                help: consider borrowing here: `&std::ops::RangeFull {}`
+   |     ---------- ^^^^^^^^^^^^^^^^^^^^^^
+   |     |          |
+   |     |          expected reference, found struct `RangeFull`
+   |     |          help: consider borrowing here: `&std::ops::RangeFull {}`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `RangeFull`
+note: function defined here
+  --> $DIR/issue-54505-no-literals.rs:12:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-54505-no-literals.rs:41:16
    |
 LL |     take_range(::std::ops::RangeFull {});
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^
-   |                |
-   |                expected reference, found struct `RangeFull`
-   |                help: consider borrowing here: `&::std::ops::RangeFull {}`
+   |     ---------- ^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |          |
+   |     |          expected reference, found struct `RangeFull`
+   |     |          help: consider borrowing here: `&::std::ops::RangeFull {}`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `RangeFull`
+note: function defined here
+  --> $DIR/issue-54505-no-literals.rs:12:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-54505-no-literals.rs:46:16
    |
 LL |     take_range(std::ops::RangeInclusive::new(0, 1));
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                |
-   |                expected reference, found struct `RangeInclusive`
-   |                help: consider borrowing here: `&std::ops::RangeInclusive::new(0, 1)`
+   |     ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |          |
+   |     |          expected reference, found struct `RangeInclusive`
+   |     |          help: consider borrowing here: `&std::ops::RangeInclusive::new(0, 1)`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `RangeInclusive<{integer}>`
+note: function defined here
+  --> $DIR/issue-54505-no-literals.rs:12:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-54505-no-literals.rs:51:16
    |
 LL |     take_range(::std::ops::RangeInclusive::new(0, 1));
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                |
-   |                expected reference, found struct `RangeInclusive`
-   |                help: consider borrowing here: `&::std::ops::RangeInclusive::new(0, 1)`
+   |     ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |          |
+   |     |          expected reference, found struct `RangeInclusive`
+   |     |          help: consider borrowing here: `&::std::ops::RangeInclusive::new(0, 1)`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `RangeInclusive<{integer}>`
+note: function defined here
+  --> $DIR/issue-54505-no-literals.rs:12:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-54505-no-literals.rs:56:16
    |
 LL |     take_range(std::ops::RangeTo { end: 5 });
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                |
-   |                expected reference, found struct `RangeTo`
-   |                help: consider borrowing here: `&std::ops::RangeTo { end: 5 }`
+   |     ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |          |
+   |     |          expected reference, found struct `RangeTo`
+   |     |          help: consider borrowing here: `&std::ops::RangeTo { end: 5 }`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `RangeTo<{integer}>`
+note: function defined here
+  --> $DIR/issue-54505-no-literals.rs:12:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-54505-no-literals.rs:61:16
    |
 LL |     take_range(::std::ops::RangeTo { end: 5 });
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                |
-   |                expected reference, found struct `RangeTo`
-   |                help: consider borrowing here: `&::std::ops::RangeTo { end: 5 }`
+   |     ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |          |
+   |     |          expected reference, found struct `RangeTo`
+   |     |          help: consider borrowing here: `&::std::ops::RangeTo { end: 5 }`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `RangeTo<{integer}>`
+note: function defined here
+  --> $DIR/issue-54505-no-literals.rs:12:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-54505-no-literals.rs:66:16
    |
 LL |     take_range(std::ops::RangeToInclusive { end: 5 });
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                |
-   |                expected reference, found struct `RangeToInclusive`
-   |                help: consider borrowing here: `&std::ops::RangeToInclusive { end: 5 }`
+   |     ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |          |
+   |     |          expected reference, found struct `RangeToInclusive`
+   |     |          help: consider borrowing here: `&std::ops::RangeToInclusive { end: 5 }`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `RangeToInclusive<{integer}>`
+note: function defined here
+  --> $DIR/issue-54505-no-literals.rs:12:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-54505-no-literals.rs:71:16
    |
 LL |     take_range(::std::ops::RangeToInclusive { end: 5 });
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                |
-   |                expected reference, found struct `RangeToInclusive`
-   |                help: consider borrowing here: `&::std::ops::RangeToInclusive { end: 5 }`
+   |     ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |          |
+   |     |          expected reference, found struct `RangeToInclusive`
+   |     |          help: consider borrowing here: `&::std::ops::RangeToInclusive { end: 5 }`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `RangeToInclusive<{integer}>`
+note: function defined here
+  --> $DIR/issue-54505-no-literals.rs:12:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error: aborting due to 12 previous errors
 
index 73507f4836b23ade84fff3cc55f3edc206ec4156..c4e36b0b159507a862352fe620ade1ca136419f8 100644 (file)
@@ -4,73 +4,109 @@ error[E0308]: mismatched types
   --> $DIR/issue-54505-no-std.rs:27:16
    |
 LL |     take_range(0..1);
-   |                ^^^^
-   |                |
-   |                expected reference, found struct `Range`
-   |                help: consider borrowing here: `&(0..1)`
+   |     ---------- ^^^^
+   |     |          |
+   |     |          expected reference, found struct `Range`
+   |     |          help: consider borrowing here: `&(0..1)`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `Range<{integer}>`
+note: function defined here
+  --> $DIR/issue-54505-no-std.rs:23:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-54505-no-std.rs:32:16
    |
 LL |     take_range(1..);
-   |                ^^^
-   |                |
-   |                expected reference, found struct `RangeFrom`
-   |                help: consider borrowing here: `&(1..)`
+   |     ---------- ^^^
+   |     |          |
+   |     |          expected reference, found struct `RangeFrom`
+   |     |          help: consider borrowing here: `&(1..)`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `RangeFrom<{integer}>`
+note: function defined here
+  --> $DIR/issue-54505-no-std.rs:23:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-54505-no-std.rs:37:16
    |
 LL |     take_range(..);
-   |                ^^
-   |                |
-   |                expected reference, found struct `RangeFull`
-   |                help: consider borrowing here: `&(..)`
+   |     ---------- ^^
+   |     |          |
+   |     |          expected reference, found struct `RangeFull`
+   |     |          help: consider borrowing here: `&(..)`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `RangeFull`
+note: function defined here
+  --> $DIR/issue-54505-no-std.rs:23:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-54505-no-std.rs:42:16
    |
 LL |     take_range(0..=1);
-   |                ^^^^^
-   |                |
-   |                expected reference, found struct `RangeInclusive`
-   |                help: consider borrowing here: `&(0..=1)`
+   |     ---------- ^^^^^
+   |     |          |
+   |     |          expected reference, found struct `RangeInclusive`
+   |     |          help: consider borrowing here: `&(0..=1)`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `RangeInclusive<{integer}>`
+note: function defined here
+  --> $DIR/issue-54505-no-std.rs:23:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-54505-no-std.rs:47:16
    |
 LL |     take_range(..5);
-   |                ^^^
-   |                |
-   |                expected reference, found struct `RangeTo`
-   |                help: consider borrowing here: `&(..5)`
+   |     ---------- ^^^
+   |     |          |
+   |     |          expected reference, found struct `RangeTo`
+   |     |          help: consider borrowing here: `&(..5)`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `RangeTo<{integer}>`
+note: function defined here
+  --> $DIR/issue-54505-no-std.rs:23:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-54505-no-std.rs:52:16
    |
 LL |     take_range(..=42);
-   |                ^^^^^
-   |                |
-   |                expected reference, found struct `RangeToInclusive`
-   |                help: consider borrowing here: `&(..=42)`
+   |     ---------- ^^^^^
+   |     |          |
+   |     |          expected reference, found struct `RangeToInclusive`
+   |     |          help: consider borrowing here: `&(..=42)`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `RangeToInclusive<{integer}>`
+note: function defined here
+  --> $DIR/issue-54505-no-std.rs:23:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error: aborting due to 7 previous errors
 
index 121af29834d87b2be6623fdba986a984e7dea555..38df6e14496a626ef873498e4ae32f756c25cd3c 100644 (file)
@@ -2,73 +2,109 @@ error[E0308]: mismatched types
   --> $DIR/issue-54505.rs:14:16
    |
 LL |     take_range(0..1);
-   |                ^^^^
-   |                |
-   |                expected reference, found struct `std::ops::Range`
-   |                help: consider borrowing here: `&(0..1)`
+   |     ---------- ^^^^
+   |     |          |
+   |     |          expected reference, found struct `std::ops::Range`
+   |     |          help: consider borrowing here: `&(0..1)`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `std::ops::Range<{integer}>`
+note: function defined here
+  --> $DIR/issue-54505.rs:10:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-54505.rs:19:16
    |
 LL |     take_range(1..);
-   |                ^^^
-   |                |
-   |                expected reference, found struct `RangeFrom`
-   |                help: consider borrowing here: `&(1..)`
+   |     ---------- ^^^
+   |     |          |
+   |     |          expected reference, found struct `RangeFrom`
+   |     |          help: consider borrowing here: `&(1..)`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `RangeFrom<{integer}>`
+note: function defined here
+  --> $DIR/issue-54505.rs:10:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-54505.rs:24:16
    |
 LL |     take_range(..);
-   |                ^^
-   |                |
-   |                expected reference, found struct `RangeFull`
-   |                help: consider borrowing here: `&(..)`
+   |     ---------- ^^
+   |     |          |
+   |     |          expected reference, found struct `RangeFull`
+   |     |          help: consider borrowing here: `&(..)`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `RangeFull`
+note: function defined here
+  --> $DIR/issue-54505.rs:10:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-54505.rs:29:16
    |
 LL |     take_range(0..=1);
-   |                ^^^^^
-   |                |
-   |                expected reference, found struct `RangeInclusive`
-   |                help: consider borrowing here: `&(0..=1)`
+   |     ---------- ^^^^^
+   |     |          |
+   |     |          expected reference, found struct `RangeInclusive`
+   |     |          help: consider borrowing here: `&(0..=1)`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `RangeInclusive<{integer}>`
+note: function defined here
+  --> $DIR/issue-54505.rs:10:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-54505.rs:34:16
    |
 LL |     take_range(..5);
-   |                ^^^
-   |                |
-   |                expected reference, found struct `RangeTo`
-   |                help: consider borrowing here: `&(..5)`
+   |     ---------- ^^^
+   |     |          |
+   |     |          expected reference, found struct `RangeTo`
+   |     |          help: consider borrowing here: `&(..5)`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `RangeTo<{integer}>`
+note: function defined here
+  --> $DIR/issue-54505.rs:10:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error[E0308]: mismatched types
   --> $DIR/issue-54505.rs:39:16
    |
 LL |     take_range(..=42);
-   |                ^^^^^
-   |                |
-   |                expected reference, found struct `RangeToInclusive`
-   |                help: consider borrowing here: `&(..=42)`
+   |     ---------- ^^^^^
+   |     |          |
+   |     |          expected reference, found struct `RangeToInclusive`
+   |     |          help: consider borrowing here: `&(..=42)`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
                  found struct `RangeToInclusive<{integer}>`
+note: function defined here
+  --> $DIR/issue-54505.rs:10:4
+   |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+   |    ^^^^^^^^^^ -------------------------
 
 error: aborting due to 6 previous errors
 
index 5167b87fd27b82e7a6fc35e1c2ea74fa51065ad9..6badd998f9617ab4af6e8306e4f8199218f60d4d 100644 (file)
@@ -2,25 +2,37 @@ error[E0308]: mismatched types
   --> $DIR/issue-73553-misinterp-range-literal.rs:12:10
    |
 LL |     demo(tell(1)..tell(10));
-   |          ^^^^^^^^^^^^^^^^^
-   |          |
-   |          expected reference, found struct `std::ops::Range`
-   |          help: consider borrowing here: `&(tell(1)..tell(10))`
+   |     ---- ^^^^^^^^^^^^^^^^^
+   |     |    |
+   |     |    expected reference, found struct `std::ops::Range`
+   |     |    help: consider borrowing here: `&(tell(1)..tell(10))`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&std::ops::Range<usize>`
                  found struct `std::ops::Range<usize>`
+note: function defined here
+  --> $DIR/issue-73553-misinterp-range-literal.rs:3:4
+   |
+LL | fn demo(r: &Range) {
+   |    ^^^^ ---------
 
 error[E0308]: mismatched types
   --> $DIR/issue-73553-misinterp-range-literal.rs:14:10
    |
 LL |     demo(1..10);
-   |          ^^^^^
-   |          |
-   |          expected reference, found struct `std::ops::Range`
-   |          help: consider borrowing here: `&(1..10)`
+   |     ---- ^^^^^
+   |     |    |
+   |     |    expected reference, found struct `std::ops::Range`
+   |     |    help: consider borrowing here: `&(1..10)`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&std::ops::Range<usize>`
                  found struct `std::ops::Range<{integer}>`
+note: function defined here
+  --> $DIR/issue-73553-misinterp-range-literal.rs:3:4
+   |
+LL | fn demo(r: &Range) {
+   |    ^^^^ ---------
 
 error: aborting due to 2 previous errors
 
index 92c4956da02d26c0eebb0f3df84f631b215a3591..f7dcaa9d97e7c83abfeacdd45494e64c036bda98 100644 (file)
@@ -5,6 +5,7 @@ LL |     Box::new(item)
    |     ^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'static`...
+   = note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
 
 error[E0310]: the associated type `<T as Iter>::Item` may not live long enough
   --> $DIR/regions-close-associated-type-into-object.rs:22:5
@@ -13,6 +14,7 @@ LL |     Box::new(item)
    |     ^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'static`...
+   = note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
 
 error[E0309]: the associated type `<T as Iter>::Item` may not live long enough
   --> $DIR/regions-close-associated-type-into-object.rs:28:5
@@ -21,6 +23,7 @@ LL |     Box::new(item)
    |     ^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'a`...
+   = note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
 
 error[E0309]: the associated type `<T as Iter>::Item` may not live long enough
   --> $DIR/regions-close-associated-type-into-object.rs:35:5
@@ -29,6 +32,7 @@ LL |     Box::new(item)
    |     ^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'a`...
+   = note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
 
 error: aborting due to 4 previous errors
 
index b30626830ad6bbbe5d345ce7eb183be51ecb9cf4..6a2429e51ecdad24b7f61046a63ca6f5cc9578b5 100644 (file)
@@ -1,26 +1,26 @@
 error[E0310]: the parameter type `U` may not live long enough
   --> $DIR/regions-close-object-into-object-4.rs:9:5
    |
+LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
+   |             - help: consider adding an explicit lifetime bound...: `U: 'static`
 LL |     Box::new(B(&*v)) as Box<dyn X>
-   |     ^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `U: 'static`...
+   |     ^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds
 
 error[E0310]: the parameter type `U` may not live long enough
   --> $DIR/regions-close-object-into-object-4.rs:9:5
    |
+LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
+   |             - help: consider adding an explicit lifetime bound...: `U: 'static`
 LL |     Box::new(B(&*v)) as Box<dyn X>
-   |     ^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `U: 'static`...
+   |     ^^^^^^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds
 
 error[E0310]: the parameter type `U` may not live long enough
   --> $DIR/regions-close-object-into-object-4.rs:9:5
    |
+LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
+   |             - help: consider adding an explicit lifetime bound...: `U: 'static`
 LL |     Box::new(B(&*v)) as Box<dyn X>
-   |     ^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `U: 'static`...
+   |     ^^^^^^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds
 
 error: lifetime may not live long enough
   --> $DIR/regions-close-object-into-object-4.rs:9:5
@@ -42,10 +42,10 @@ LL |     Box::new(B(&*v)) as Box<dyn X>
 error[E0310]: the parameter type `U` may not live long enough
   --> $DIR/regions-close-object-into-object-4.rs:9:14
    |
+LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
+   |             - help: consider adding an explicit lifetime bound...: `U: 'static`
 LL |     Box::new(B(&*v)) as Box<dyn X>
-   |              ^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `U: 'static`...
+   |              ^^^^^^ ...so that the type `U` will meet its required lifetime bounds
 
 error: aborting due to 6 previous errors
 
index 7486e73e66ab31122bda6f9b0af5301668a2cc94..54302cc6dca2243a9234c667ab70db41d8144b29 100644 (file)
@@ -1,26 +1,29 @@
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/regions-close-object-into-object-5.rs:17:5
    |
+LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
+   |          - help: consider adding an explicit lifetime bound...: `T: 'static`
+LL |     // oh dear!
 LL |     Box::new(B(&*v)) as Box<dyn X>
-   |     ^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
+   |     ^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/regions-close-object-into-object-5.rs:17:5
    |
+LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
+   |          - help: consider adding an explicit lifetime bound...: `T: 'static`
+LL |     // oh dear!
 LL |     Box::new(B(&*v)) as Box<dyn X>
-   |     ^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
+   |     ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/regions-close-object-into-object-5.rs:17:5
    |
+LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
+   |          - help: consider adding an explicit lifetime bound...: `T: 'static`
+LL |     // oh dear!
 LL |     Box::new(B(&*v)) as Box<dyn X>
-   |     ^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
+   |     ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0515]: cannot return value referencing local data `*v`
   --> $DIR/regions-close-object-into-object-5.rs:17:5
@@ -34,10 +37,11 @@ LL |     Box::new(B(&*v)) as Box<dyn X>
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/regions-close-object-into-object-5.rs:17:14
    |
+LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
+   |          - help: consider adding an explicit lifetime bound...: `T: 'static`
+LL |     // oh dear!
 LL |     Box::new(B(&*v)) as Box<dyn X>
-   |              ^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
+   |              ^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error: aborting due to 5 previous errors
 
index b576ae87011377d25a1a6f8c53a1554ef63fdc81..063c3b19a19cccc5bb96ea39e08196eb838a6295 100644 (file)
@@ -1,18 +1,18 @@
 error[E0310]: the parameter type `A` may not live long enough
   --> $DIR/regions-close-over-type-parameter-1.rs:12:5
    |
+LL | fn make_object1<A: SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
+   |                 -- help: consider adding an explicit lifetime bound...: `A: 'static +`
 LL |     Box::new(v) as Box<dyn SomeTrait + 'static>
-   |     ^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `A: 'static`...
+   |     ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `A` may not live long enough
   --> $DIR/regions-close-over-type-parameter-1.rs:21:5
    |
+LL | fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box<dyn SomeTrait + 'b> {
+   |                         -- help: consider adding an explicit lifetime bound...: `A: 'b +`
 LL |     Box::new(v) as Box<dyn SomeTrait + 'b>
-   |     ^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `A: 'b`...
+   |     ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
 
 error: aborting due to 2 previous errors
 
index 7bd7824f00a462ccebf0da80ebbc0aa95c385ccc..f0464e299bbec169dcafab57725ae04f9742efc0 100644 (file)
@@ -1,34 +1,38 @@
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/regions-close-param-into-object.rs:6:5
    |
+LL | fn p1<T>(v: T) -> Box<dyn X + 'static>
+   |       - help: consider adding an explicit lifetime bound...: `T: 'static`
+...
 LL |     Box::new(v)
-   |     ^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
+   |     ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/regions-close-param-into-object.rs:12:5
    |
+LL | fn p2<T>(v: Box<T>) -> Box<dyn X + 'static>
+   |       - help: consider adding an explicit lifetime bound...: `T: 'static`
+...
 LL |     Box::new(v)
-   |     ^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
+   |     ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/regions-close-param-into-object.rs:18:5
    |
+LL | fn p3<'a,T>(v: T) -> Box<dyn X + 'a>
+   |          - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
 LL |     Box::new(v)
-   |     ^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
+   |     ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/regions-close-param-into-object.rs:24:5
    |
+LL | fn p4<'a,T>(v: Box<T>) -> Box<dyn X + 'a>
+   |          - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
 LL |     Box::new(v)
-   |     ^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
+   |     ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error: aborting due to 4 previous errors
 
index 0f0f86dfcdd693c4221cd7010e357ac243282870..0e1db8acf1fae7dc80f65f14306d13a585b007fb 100644 (file)
@@ -1,10 +1,11 @@
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/regions-implied-bounds-projection-gap-1.rs:16:5
    |
+LL | fn func<'x, T:Trait1<'x>>(t: &'x T::Foo)
+   |             -- help: consider adding an explicit lifetime bound...: `T: 'x +`
+LL | {
 LL |     wf::<&'x T>();
-   |     ^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'x`...
+   |     ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error: aborting due to previous error
 
index 0651e305cde35031b160e9c609b5ab1d491e802b..e88f79a3a8c54c2d5dbb0b6f35832528a9ebf1b3 100644 (file)
@@ -5,6 +5,7 @@ LL |         check_bound(x, self)
    |         ^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `Self: 'a`...
+   = note: ...so that the type `Self` will meet its required lifetime bounds
 
 error: aborting due to previous error
 
index 1f7b34fc69962937095054765c206c8fed2dc255..fe077499544048eb0399611dfc431ed06ffc3f81 100644 (file)
@@ -1,18 +1,18 @@
 error[E0309]: the parameter type `A` may not live long enough
   --> $DIR/regions-infer-bound-from-trait.rs:33:5
    |
+LL | fn bar1<'a,A>(x: Inv<'a>, a: A) {
+   |            - help: consider adding an explicit lifetime bound...: `A: 'a`
 LL |     check_bound(x, a)
-   |     ^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `A: 'a`...
+   |     ^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `A` may not live long enough
   --> $DIR/regions-infer-bound-from-trait.rs:37:5
    |
+LL | fn bar2<'a,'b,A:Is<'b>>(x: Inv<'a>, y: Inv<'b>, a: A) {
+   |               -- help: consider adding an explicit lifetime bound...: `A: 'a +`
 LL |     check_bound(x, a)
-   |     ^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `A: 'a`...
+   |     ^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
 
 error: aborting due to 2 previous errors
 
index 730fd99aa68c29c92c2320b3196da7c7a4db019d..da316c6ef5e435c82b61b25b19bfa1ebb9505e08 100644 (file)
@@ -1,5 +1,6 @@
-struct Foo<'static> { //~ ERROR invalid lifetime parameter name: `'static`
-    x: &'static isize
+struct Foo<'static> {
+    //~^ ERROR invalid lifetime parameter name: `'static`
+    x: &'static isize,
 }
 
 fn main() {}
index b8f50a40c45237cdd552f134d68e0b9871e0ad68..7b6ede19341b4953f141faa58f48252bc3f6d3c2 100644 (file)
@@ -23,14 +23,14 @@ fn bar<'a>(x: &'a isize) {
     let y: &'a isize = x;
 
     // &'a is not visible to *items*:
-    type X = Option<&'a isize>; //~ ERROR undeclared lifetime
+    type X = Option<&'a isize>; //~ ERROR can't use generic parameters from outer item
     enum E {
-        E1(&'a isize) //~ ERROR undeclared lifetime
+        E1(&'a isize) //~ ERROR can't use generic parameters from outer item
     }
     struct S {
-        f: &'a isize //~ ERROR undeclared lifetime
+        f: &'a isize //~ ERROR can't use generic parameters from outer item
     }
-    fn f(a: &'a isize) { } //~ ERROR undeclared lifetime
+    fn f(a: &'a isize) { } //~ ERROR can't use generic parameters from outer item
 
     // &'a CAN be declared on functions and used then:
     fn g<'a>(a: &'a isize) { } // OK
index 4399263f716edca6daa667f35237d58778e1af44..532603de5f783f2b8d4939b2977d9f09be01fff7 100644 (file)
@@ -1,19 +1,3 @@
-error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/regions-name-undeclared.rs:28:13
-   |
-LL |     enum E {
-   |           - help: consider introducing lifetime `'a` here: `<'a>`
-LL |         E1(&'a isize)
-   |             ^^ undeclared lifetime
-
-error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/regions-name-undeclared.rs:31:13
-   |
-LL |     struct S {
-   |             - help: consider introducing lifetime `'a` here: `<'a>`
-LL |         f: &'a isize
-   |             ^^ undeclared lifetime
-
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/regions-name-undeclared.rs:16:24
    |
@@ -22,12 +6,12 @@ LL |     fn m4(&self, arg: &'b isize) { }
    |
 help: consider introducing lifetime `'b` here
    |
-LL | impl<'b, 'a> Foo<'a> {
-   |      +++
-help: consider introducing lifetime `'b` here
-   |
 LL |     fn m4<'b>(&self, arg: &'b isize) { }
    |          ++++
+help: consider introducing lifetime `'b` here
+   |
+LL | impl<'b, 'a> Foo<'a> {
+   |      +++
 
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/regions-name-undeclared.rs:17:12
@@ -37,12 +21,12 @@ LL |     fn m5(&'b self) { }
    |
 help: consider introducing lifetime `'b` here
    |
-LL | impl<'b, 'a> Foo<'a> {
-   |      +++
-help: consider introducing lifetime `'b` here
-   |
 LL |     fn m5<'b>(&'b self) { }
    |          ++++
+help: consider introducing lifetime `'b` here
+   |
+LL | impl<'b, 'a> Foo<'a> {
+   |      +++
 
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/regions-name-undeclared.rs:18:27
@@ -52,26 +36,54 @@ LL |     fn m6(&self, arg: Foo<'b>) { }
    |
 help: consider introducing lifetime `'b` here
    |
-LL | impl<'b, 'a> Foo<'a> {
-   |      +++
-help: consider introducing lifetime `'b` here
-   |
 LL |     fn m6<'b>(&self, arg: Foo<'b>) { }
    |          ++++
+help: consider introducing lifetime `'b` here
+   |
+LL | impl<'b, 'a> Foo<'a> {
+   |      +++
 
-error[E0261]: use of undeclared lifetime name `'a`
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/regions-name-undeclared.rs:26:22
    |
+LL | fn bar<'a>(x: &'a isize) {
+   |        -- lifetime parameter from outer item
+...
 LL |     type X = Option<&'a isize>;
-   |           -          ^^ undeclared lifetime
+   |           -          ^^ use of generic parameter from outer item
    |           |
    |           help: consider introducing lifetime `'a` here: `<'a>`
 
-error[E0261]: use of undeclared lifetime name `'a`
+error[E0401]: can't use generic parameters from outer item
+  --> $DIR/regions-name-undeclared.rs:28:13
+   |
+LL | fn bar<'a>(x: &'a isize) {
+   |        -- lifetime parameter from outer item
+...
+LL |     enum E {
+   |           - help: consider introducing lifetime `'a` here: `<'a>`
+LL |         E1(&'a isize)
+   |             ^^ use of generic parameter from outer item
+
+error[E0401]: can't use generic parameters from outer item
+  --> $DIR/regions-name-undeclared.rs:31:13
+   |
+LL | fn bar<'a>(x: &'a isize) {
+   |        -- lifetime parameter from outer item
+...
+LL |     struct S {
+   |             - help: consider introducing lifetime `'a` here: `<'a>`
+LL |         f: &'a isize
+   |             ^^ use of generic parameter from outer item
+
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/regions-name-undeclared.rs:33:14
    |
+LL | fn bar<'a>(x: &'a isize) {
+   |        -- lifetime parameter from outer item
+...
 LL |     fn f(a: &'a isize) { }
-   |         -    ^^ undeclared lifetime
+   |         -    ^^ use of generic parameter from outer item
    |         |
    |         help: consider introducing lifetime `'a` here: `<'a>`
 
@@ -90,14 +102,14 @@ LL | ...                   &'b isize,
    |                        ^^ undeclared lifetime
    |
    = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+   |
+LL |             b: Box<dyn for<'b, 'a> FnOnce(&'a isize,
+   |                            +++
 help: consider introducing lifetime `'b` here
    |
 LL | fn fn_types<'b>(a: &'a isize,
    |            ++++
-help: consider making the bound lifetime-generic with a new `'b` lifetime
-   |
-LL |             b: Box<dyn for<'a, 'b> FnOnce(&'a isize,
-   |                              ++++
 
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/regions-name-undeclared.rs:46:36
@@ -105,15 +117,14 @@ error[E0261]: use of undeclared lifetime name `'b`
 LL | ...                   &'b isize)>,
    |                        ^^ undeclared lifetime
    |
-   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+   |
+LL |             b: Box<dyn for<'b, 'a> FnOnce(&'a isize,
+   |                            +++
 help: consider introducing lifetime `'b` here
    |
 LL | fn fn_types<'b>(a: &'a isize,
    |            ++++
-help: consider making the bound lifetime-generic with a new `'b` lifetime
-   |
-LL |             b: Box<dyn for<'a, 'b> FnOnce(&'a isize,
-   |                              ++++
 
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/regions-name-undeclared.rs:47:17
@@ -132,13 +143,14 @@ LL |     async fn buggy(&self) -> &'a str {
    |
 help: consider introducing lifetime `'a` here
    |
-LL | impl<'a> Bug {
-   |     ++++
-help: consider introducing lifetime `'a` here
-   |
 LL |     async fn buggy<'a>(&self) -> &'a str {
    |                   ++++
+help: consider introducing lifetime `'a` here
+   |
+LL | impl<'a> Bug {
+   |     ++++
 
 error: aborting due to 12 previous errors
 
-For more information about this error, try `rustc --explain E0261`.
+Some errors have detailed explanations: E0261, E0401.
+For more information about an error, try `rustc --explain E0261`.
index 5af0aefe22b8c8e4766a5a1a82354b4587524e9f..44631f954df33c9ad295651fd35d031f7a93d64d 100644 (file)
@@ -19,15 +19,17 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/resolve-primitive-fallback.rs:3:5
    |
 LL |     std::mem::size_of(u16);
-   |     ^^^^^^^^^^^^^^^^^ --- supplied 1 argument
-   |     |
-   |     expected 0 arguments
+   |     ^^^^^^^^^^^^^^^^^ --- argument unexpected
    |
 note: function defined here
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
    |
 LL | pub const fn size_of<T>() -> usize {
    |              ^^^^^^^
+help: remove the extra argument
+   |
+LL |     std::mem::size_of();
+   |     ~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 3 previous errors
 
index 961968186de24a520918bcee881ed1344de12c46..dd5099317667307c38ebaac6edae56e645610fd4 100644 (file)
@@ -3,7 +3,7 @@
 pub struct Int(i32);
 
 impl const std::ops::Add for i32 { //~ ERROR type annotations needed
-    //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types
+    //~^ ERROR only traits defined in the current crate can be implemented for primitive types
     type Output = Self;
 
     fn add(self, rhs: Self) -> Self {
index 154a6a35a44efdcb25233065f4ef9811b0e9596d..9fd82196e79c11836cdd70352ced3100d967f50b 100644 (file)
@@ -1,4 +1,4 @@
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
   --> $DIR/const-and-non-const-impl.rs:5:1
    |
 LL | impl const std::ops::Add for i32 {
index 6d389a1317a9fa2f4efa45870520388a9cc4b80d..364c8c8f7069e9e7a98b621ef5719bccde8c45d1 100644 (file)
@@ -1,5 +1,5 @@
 error: implementation of `FnOnce` is not general enough
-  --> $DIR/rfc1623.rs:36:8
+  --> $DIR/rfc1623.rs:32:8
    |
 LL |     f: &id,
    |        ^^^ implementation of `FnOnce` is not general enough
index f85b6ff8ff75b2a0431d8e43e50ce0fe97a4bb55..2eff4708547d80acac58f3492a104d421b1f7818 100644 (file)
@@ -1,63 +1,35 @@
 error[E0308]: mismatched types
-  --> $DIR/rfc1623.rs:29:35
+  --> $DIR/rfc1623.rs:32:8
    |
-LL |   static SOME_STRUCT: &SomeStruct = &SomeStruct {
-   |  ___________________________________^
-LL | |
-LL | |
-LL | |
-...  |
-LL | |
-LL | | };
-   | |_^ one type is more general than the other
+LL |     f: &id,
+   |        ^^^ one type is more general than the other
    |
    = note: expected type `for<'a, 'b> Fn<(&'a Foo<'b>,)>`
               found type `Fn<(&Foo<'_>,)>`
 
 error[E0308]: mismatched types
-  --> $DIR/rfc1623.rs:29:35
+  --> $DIR/rfc1623.rs:32:8
    |
-LL |   static SOME_STRUCT: &SomeStruct = &SomeStruct {
-   |  ___________________________________^
-LL | |
-LL | |
-LL | |
-...  |
-LL | |
-LL | | };
-   | |_^ one type is more general than the other
+LL |     f: &id,
+   |        ^^^ one type is more general than the other
    |
    = note: expected type `for<'a, 'b> Fn<(&'a Foo<'b>,)>`
               found type `Fn<(&Foo<'_>,)>`
 
 error: implementation of `FnOnce` is not general enough
-  --> $DIR/rfc1623.rs:29:35
+  --> $DIR/rfc1623.rs:32:8
    |
-LL |   static SOME_STRUCT: &SomeStruct = &SomeStruct {
-   |  ___________________________________^
-LL | |
-LL | |
-LL | |
-...  |
-LL | |
-LL | | };
-   | |_^ implementation of `FnOnce` is not general enough
+LL |     f: &id,
+   |        ^^^ implementation of `FnOnce` is not general enough
    |
    = note: `fn(&'2 Foo<'_>) -> &'2 Foo<'_> {id::<&'2 Foo<'_>>}` must implement `FnOnce<(&'1 Foo<'b>,)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&'2 Foo<'_>,)>`, for some specific lifetime `'2`
 
 error: implementation of `FnOnce` is not general enough
-  --> $DIR/rfc1623.rs:29:35
+  --> $DIR/rfc1623.rs:32:8
    |
-LL |   static SOME_STRUCT: &SomeStruct = &SomeStruct {
-   |  ___________________________________^
-LL | |
-LL | |
-LL | |
-...  |
-LL | |
-LL | | };
-   | |_^ implementation of `FnOnce` is not general enough
+LL |     f: &id,
+   |        ^^^ implementation of `FnOnce` is not general enough
    |
    = note: `fn(&Foo<'2>) -> &Foo<'2> {id::<&Foo<'2>>}` must implement `FnOnce<(&'a Foo<'1>,)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&Foo<'2>,)>`, for some specific lifetime `'2`
index 0e9d2140324256dbdcccab92e0fb3c9837ba5335..443da0aa955f982755b4300fc2732719984713ab 100644 (file)
@@ -27,14 +27,14 @@ fn id<T>(t: T) -> T {
 }
 
 static SOME_STRUCT: &SomeStruct = &SomeStruct {
-    //[nll]~^ ERROR mismatched types
-    //[nll]~| ERROR mismatched types
-    //[nll]~| ERROR implementation of `FnOnce` is not general enough
-    //[nll]~| ERROR implementation of `FnOnce` is not general enough
     foo: &Foo { bools: &[false, true] },
     bar: &Bar { bools: &[true, true] },
     f: &id,
     //[base]~^ ERROR implementation of `FnOnce` is not general enough
+    //[nll]~^^ ERROR mismatched types
+    //[nll]~| ERROR mismatched types
+    //[nll]~| ERROR implementation of `FnOnce` is not general enough
+    //[nll]~| ERROR implementation of `FnOnce` is not general enough
 };
 
 // very simple test for a 'static static with default lifetime
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.base.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.base.stderr
new file mode 100644 (file)
index 0000000..7985bf2
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:52
+   |
+LL |     async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
+   |                                    ----     ----   ^ ...but data from `f` is returned here
+   |                                    |
+   |                                    this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:15:82
+   |
+LL |     async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
+   |                                     ----              -----------------          ^ ...but data from `f` is returned here
+   |                                     |
+   |                                     this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:22:64
+   |
+LL |     async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
+   |                                               ------     ---   ^^^ ...but data from `arg` is returned here
+   |                                               |
+   |                                               this parameter and the return type are declared with different lifetimes...
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
index 57374b7e3bb277d9e9c1bfe9010935e8bf57f43a..8a55a7c34d77ba44ef7a4f50b2489cbb14148878 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:52
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:52
    |
 LL |     async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
    |                          -         -               ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
@@ -8,7 +8,7 @@ LL |     async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
    |                          let's call the lifetime of this reference `'2`
 
 error: lifetime may not live long enough
-  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:75
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:15:75
    |
 LL |     async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
    |                          -          -                                     ^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
@@ -17,7 +17,7 @@ LL |     async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (
    |                          let's call the lifetime of this reference `'2`
 
 error: lifetime may not live long enough
-  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:64
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:22:64
    |
 LL |     async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
    |                  --              -                             ^^^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
index f42337d53406216a492778bf9691a8c4306b8b17..c54f7963c231c8223d09bd65eb096cbee6b55a86 100644 (file)
@@ -1,4 +1,7 @@
 // edition:2018
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
 
 use std::pin::Pin;
 
@@ -6,15 +9,19 @@
 
 impl Foo {
     async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
-    //~^ ERROR lifetime mismatch
+    //[base]~^ ERROR lifetime mismatch
+    //[nll]~^^ lifetime may not live long enough
 
     async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
-    //~^ ERROR lifetime mismatch
+    //[base]~^ ERROR lifetime mismatch
+    //[nll]~^^ lifetime may not live long enough
 }
 
 type Alias<T> = Pin<T>;
 impl Foo {
-    async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } //~ ERROR E0623
+    async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
+    //[base]~^ ERROR E0623
+    //[nll]~^^ lifetime may not live long enough
 }
 
 fn main() {}
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr
deleted file mode 100644 (file)
index 299a2d2..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-error[E0623]: lifetime mismatch
-  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:52
-   |
-LL |     async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
-   |                                    ----     ----   ^ ...but data from `f` is returned here
-   |                                    |
-   |                                    this parameter and the return type are declared with different lifetimes...
-
-error[E0623]: lifetime mismatch
-  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:82
-   |
-LL |     async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
-   |                                     ----              -----------------          ^ ...but data from `f` is returned here
-   |                                     |
-   |                                     this parameter and the return type are declared with different lifetimes...
-
-error[E0623]: lifetime mismatch
-  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:64
-   |
-LL |     async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
-   |                                               ------     ---   ^^^ ...but data from `arg` is returned here
-   |                                               |
-   |                                               this parameter and the return type are declared with different lifetimes...
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.base.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.base.stderr
new file mode 100644 (file)
index 0000000..c0e2f0b
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:10:46
+   |
+LL |     fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
+   |                              ----     ----   ^ ...but data from `f` is returned here
+   |                              |
+   |                              this parameter and the return type are declared with different lifetimes...
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn a<'a>(self: Pin<&'a Foo>, f: &'a Foo) -> &Foo { f }
+   |         ++++            ++           ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:14:76
+   |
+LL |     fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
+   |                               ----              -----------------          ^ ...but data from `f` is returned here
+   |                               |
+   |                               this parameter and the return type are declared with different lifetimes...
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn c<'a>(self: Pin<&'a Self>, f: &'a Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
+   |         ++++            ++            ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:21:58
+   |
+LL |     fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
+   |                                         ------     ---   ^^^ ...but data from `arg` is returned here
+   |                                         |
+   |                                         this parameter and the return type are declared with different lifetimes...
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
index 92241b2fb2dc1a0730c99bf5b1ac18af6c00e08b..b06ebf70477378344d4afc6c50ebca9dada1940f 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:6:46
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:10:46
    |
 LL |     fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
    |                    -         -               ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
@@ -8,7 +8,7 @@ LL |     fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
    |                    let's call the lifetime of this reference `'2`
 
 error: lifetime may not live long enough
-  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:8:69
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:14:69
    |
 LL |     fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
    |                    -          -                                     ^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
@@ -17,7 +17,7 @@ LL |     fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self,
    |                    let's call the lifetime of this reference `'2`
 
 error: lifetime may not live long enough
-  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:13:58
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:21:58
    |
 LL |     fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
    |            --  ---- has type `Pin<&'1 Foo>`              ^^^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
index 8291e44080b37dc4993e1971a4ab8f5a38477b92..34b08b364fb5db9d0be509f1a07e9cfb08051d6b 100644 (file)
@@ -1,16 +1,26 @@
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
+
 use std::pin::Pin;
 
 struct Foo;
 
 impl Foo {
-    fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } //~ ERROR E0623
+    fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
+    //[base]~^ ERROR E0623
+    //[nll]~^^ lifetime may not live long enough
 
-    fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } //~ ERROR E0623
+    fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
+    //[base]~^ ERROR E0623
+    //[nll]~^^ lifetime may not live long enough
 }
 
 type Alias<T> = Pin<T>;
 impl Foo {
-    fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } //~ ERROR E0623
+    fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
+    //[base]~^ ERROR E0623
+    //[nll]~^^ lifetime may not live long enough
 }
 
 fn main() {}
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr
deleted file mode 100644 (file)
index 64a5746..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-error[E0623]: lifetime mismatch
-  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:6:46
-   |
-LL |     fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
-   |                              ----     ----   ^ ...but data from `f` is returned here
-   |                              |
-   |                              this parameter and the return type are declared with different lifetimes...
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn a<'a>(self: Pin<&'a Foo>, f: &'a Foo) -> &Foo { f }
-   |         ++++            ++           ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:8:76
-   |
-LL |     fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
-   |                               ----              -----------------          ^ ...but data from `f` is returned here
-   |                               |
-   |                               this parameter and the return type are declared with different lifetimes...
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn c<'a>(self: Pin<&'a Self>, f: &'a Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
-   |         ++++            ++            ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:13:58
-   |
-LL |     fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
-   |                                         ------     ---   ^^^ ...but data from `arg` is returned here
-   |                                         |
-   |                                         this parameter and the return type are declared with different lifetimes...
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/self/elision/lt-ref-self-async.base.stderr b/src/test/ui/self/elision/lt-ref-self-async.base.stderr
new file mode 100644 (file)
index 0000000..b438549
--- /dev/null
@@ -0,0 +1,63 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self-async.rs:16:9
+   |
+LL |     async fn ref_self(&self, f: &u32) -> &u32 {
+   |                                 ----     ----
+   |                                 |
+   |                                 this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self-async.rs:24:9
+   |
+LL |     async fn ref_Self(self: &Self, f: &u32) -> &u32 {
+   |                                       ----     ----
+   |                                       |
+   |                                       this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self-async.rs:30:9
+   |
+LL |     async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+   |                                                ----     ----
+   |                                                |
+   |                                                this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self-async.rs:36:9
+   |
+LL |     async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+   |                                                ----     ----
+   |                                                |
+   |                                                this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self-async.rs:42:9
+   |
+LL |     async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+   |                                                         ----     ----
+   |                                                         |
+   |                                                         this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self-async.rs:48:9
+   |
+LL |     async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+   |                                                     ----     ----
+   |                                                     |
+   |                                                     this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
index c10b8824e6d63d6d36114d92016d1dab9f5025f2..2ba9a6596f62d8249e5db98c48b7eae77a806d47 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/lt-ref-self-async.rs:13:9
+  --> $DIR/lt-ref-self-async.rs:16:9
    |
 LL |     async fn ref_self(&self, f: &u32) -> &u32 {
    |                       -         - let's call the lifetime of this reference `'1`
@@ -9,7 +9,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/lt-ref-self-async.rs:19:9
+  --> $DIR/lt-ref-self-async.rs:24:9
    |
 LL |     async fn ref_Self(self: &Self, f: &u32) -> &u32 {
    |                             -         - let's call the lifetime of this reference `'1`
@@ -19,7 +19,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/lt-ref-self-async.rs:23:9
+  --> $DIR/lt-ref-self-async.rs:30:9
    |
 LL |     async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
    |                                     -          - let's call the lifetime of this reference `'1`
@@ -29,7 +29,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/lt-ref-self-async.rs:27:9
+  --> $DIR/lt-ref-self-async.rs:36:9
    |
 LL |     async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
    |                                     -          - let's call the lifetime of this reference `'1`
@@ -39,7 +39,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/lt-ref-self-async.rs:31:9
+  --> $DIR/lt-ref-self-async.rs:42:9
    |
 LL |     async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
    |                                             -           - let's call the lifetime of this reference `'1`
@@ -49,7 +49,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/lt-ref-self-async.rs:35:9
+  --> $DIR/lt-ref-self-async.rs:48:9
    |
 LL |     async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
    |                                         -           - let's call the lifetime of this reference `'1`
index ef6cbe7772c276cb7960840beda83782113b09f3..24482b3a2787b19a4b5445a6fe5718037c5305b4 100644 (file)
@@ -1,4 +1,7 @@
 // edition:2018
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
 
 #![allow(non_snake_case)]
 
@@ -10,29 +13,41 @@ impl<'a> Struct<'a> {
     // Test using `&self` sugar:
 
     async fn ref_self(&self, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     // Test using `&Self` explicitly:
 
     async fn ref_Self(self: &Self, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 }
 
diff --git a/src/test/ui/self/elision/lt-ref-self-async.stderr b/src/test/ui/self/elision/lt-ref-self-async.stderr
deleted file mode 100644 (file)
index 7448e84..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-error[E0623]: lifetime mismatch
-  --> $DIR/lt-ref-self-async.rs:13:9
-   |
-LL |     async fn ref_self(&self, f: &u32) -> &u32 {
-   |                                 ----     ----
-   |                                 |
-   |                                 this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/lt-ref-self-async.rs:19:9
-   |
-LL |     async fn ref_Self(self: &Self, f: &u32) -> &u32 {
-   |                                       ----     ----
-   |                                       |
-   |                                       this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/lt-ref-self-async.rs:23:9
-   |
-LL |     async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
-   |                                                ----     ----
-   |                                                |
-   |                                                this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/lt-ref-self-async.rs:27:9
-   |
-LL |     async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
-   |                                                ----     ----
-   |                                                |
-   |                                                this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/lt-ref-self-async.rs:31:9
-   |
-LL |     async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
-   |                                                         ----     ----
-   |                                                         |
-   |                                                         this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/lt-ref-self-async.rs:35:9
-   |
-LL |     async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
-   |                                                     ----     ----
-   |                                                     |
-   |                                                     this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/self/elision/lt-ref-self.base.stderr b/src/test/ui/self/elision/lt-ref-self.base.stderr
new file mode 100644 (file)
index 0000000..0f5cd6f
--- /dev/null
@@ -0,0 +1,99 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self.rs:15:9
+   |
+LL |     fn ref_self(&self, f: &u32) -> &u32 {
+   |                           ----     ----
+   |                           |
+   |                           this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 {
+   |                ++++  ++           ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self.rs:23:9
+   |
+LL |     fn ref_Self(self: &Self, f: &u32) -> &u32 {
+   |                                 ----     ----
+   |                                 |
+   |                                 this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 {
+   |                ++++        ++           ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self.rs:29:9
+   |
+LL |     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+   |                                          ----     ----
+   |                                          |
+   |                                          this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 {
+   |                    ++++            ++            ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self.rs:35:9
+   |
+LL |     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+   |                                          ----     ----
+   |                                          |
+   |                                          this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 {
+   |                    ++++            ++            ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self.rs:41:9
+   |
+LL |     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+   |                                                   ----     ----
+   |                                                   |
+   |                                                   this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 {
+   |                        ++++                ++             ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self.rs:47:9
+   |
+LL |     fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+   |                                               ----     ----
+   |                                               |
+   |                                               this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_pin_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 {
+   |                    ++++                ++             ++
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
index e2de743b8f63eb1aaf7f08432d56b33e9dd4b9f4..1934207527b9cd9e56c5e066b9b8db08dd6d8d14 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/lt-ref-self.rs:11:9
+  --> $DIR/lt-ref-self.rs:15:9
    |
 LL |     fn ref_self(&self, f: &u32) -> &u32 {
    |                 -         - let's call the lifetime of this reference `'1`
@@ -9,7 +9,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/lt-ref-self.rs:17:9
+  --> $DIR/lt-ref-self.rs:23:9
    |
 LL |     fn ref_Self(self: &Self, f: &u32) -> &u32 {
    |                       -         - let's call the lifetime of this reference `'1`
@@ -19,7 +19,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/lt-ref-self.rs:21:9
+  --> $DIR/lt-ref-self.rs:29:9
    |
 LL |     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
    |                               -          - let's call the lifetime of this reference `'1`
@@ -29,7 +29,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/lt-ref-self.rs:25:9
+  --> $DIR/lt-ref-self.rs:35:9
    |
 LL |     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
    |                               -          - let's call the lifetime of this reference `'1`
@@ -39,7 +39,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/lt-ref-self.rs:29:9
+  --> $DIR/lt-ref-self.rs:41:9
    |
 LL |     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
    |                                       -           - let's call the lifetime of this reference `'1`
@@ -49,7 +49,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/lt-ref-self.rs:33:9
+  --> $DIR/lt-ref-self.rs:47:9
    |
 LL |     fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
    |                                   -           - let's call the lifetime of this reference `'1`
index 423c7d5822df7389ba8fbf39210a39672caa30d9..62bdb13dc0f95dd1e5ab2ad7a4f9b326c39a0601 100644 (file)
@@ -1,3 +1,7 @@
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
+
 #![allow(non_snake_case)]
 
 use std::pin::Pin;
@@ -8,29 +12,41 @@ impl<'a> Struct<'a> {
     // Test using `&self` sugar:
 
     fn ref_self(&self, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     // Test using `&Self` explicitly:
 
     fn ref_Self(self: &Self, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 }
 
diff --git a/src/test/ui/self/elision/lt-ref-self.stderr b/src/test/ui/self/elision/lt-ref-self.stderr
deleted file mode 100644 (file)
index 5764ab0..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-error[E0623]: lifetime mismatch
-  --> $DIR/lt-ref-self.rs:11:9
-   |
-LL |     fn ref_self(&self, f: &u32) -> &u32 {
-   |                           ----     ----
-   |                           |
-   |                           this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 {
-   |                ++++  ++           ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/lt-ref-self.rs:17:9
-   |
-LL |     fn ref_Self(self: &Self, f: &u32) -> &u32 {
-   |                                 ----     ----
-   |                                 |
-   |                                 this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 {
-   |                ++++        ++           ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/lt-ref-self.rs:21:9
-   |
-LL |     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
-   |                                          ----     ----
-   |                                          |
-   |                                          this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 {
-   |                    ++++            ++            ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/lt-ref-self.rs:25:9
-   |
-LL |     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
-   |                                          ----     ----
-   |                                          |
-   |                                          this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 {
-   |                    ++++            ++            ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/lt-ref-self.rs:29:9
-   |
-LL |     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
-   |                                                   ----     ----
-   |                                                   |
-   |                                                   this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 {
-   |                        ++++                ++             ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/lt-ref-self.rs:33:9
-   |
-LL |     fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
-   |                                               ----     ----
-   |                                               |
-   |                                               this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn box_pin_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 {
-   |                    ++++                ++             ++
-
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/self/elision/ref-mut-self-async.base.stderr b/src/test/ui/self/elision/ref-mut-self-async.base.stderr
new file mode 100644 (file)
index 0000000..8513375
--- /dev/null
@@ -0,0 +1,63 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self-async.rs:16:9
+   |
+LL |     async fn ref_self(&mut self, f: &u32) -> &u32 {
+   |                                     ----     ----
+   |                                     |
+   |                                     this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self-async.rs:24:9
+   |
+LL |     async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
+   |                                           ----     ----
+   |                                           |
+   |                                           this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self-async.rs:30:9
+   |
+LL |     async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
+   |                                                    ----     ----
+   |                                                    |
+   |                                                    this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self-async.rs:36:9
+   |
+LL |     async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
+   |                                                    ----     ----
+   |                                                    |
+   |                                                    this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self-async.rs:42:9
+   |
+LL |     async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
+   |                                                             ----     ----
+   |                                                             |
+   |                                                             this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self-async.rs:48:9
+   |
+LL |     async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
+   |                                                             ----     ----
+   |                                                             |
+   |                                                             this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
index 19496a5ef6d326eaf10b8e28f00e12615cdf88be..cdd464039cda0501162c7a8f20439f4e9bebbbf6 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-self-async.rs:13:9
+  --> $DIR/ref-mut-self-async.rs:16:9
    |
 LL |     async fn ref_self(&mut self, f: &u32) -> &u32 {
    |                       -             - let's call the lifetime of this reference `'1`
@@ -9,7 +9,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-self-async.rs:19:9
+  --> $DIR/ref-mut-self-async.rs:24:9
    |
 LL |     async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
    |                             -             - let's call the lifetime of this reference `'1`
@@ -19,7 +19,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-self-async.rs:23:9
+  --> $DIR/ref-mut-self-async.rs:30:9
    |
 LL |     async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
    |                                     -              - let's call the lifetime of this reference `'1`
@@ -29,7 +29,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-self-async.rs:27:9
+  --> $DIR/ref-mut-self-async.rs:36:9
    |
 LL |     async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
    |                                     -              - let's call the lifetime of this reference `'1`
@@ -39,7 +39,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-self-async.rs:31:9
+  --> $DIR/ref-mut-self-async.rs:42:9
    |
 LL |     async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
    |                                             -               - let's call the lifetime of this reference `'1`
@@ -49,7 +49,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-self-async.rs:35:9
+  --> $DIR/ref-mut-self-async.rs:48:9
    |
 LL |     async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
    |                                             -               - let's call the lifetime of this reference `'1`
index 1e65605036d6f0b12ed49876184fc1886cbbb510..59b41f364f9a1bf7dd9110d6cbfbda0a1e113f2d 100644 (file)
@@ -1,4 +1,7 @@
 // edition:2018
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
 
 #![allow(non_snake_case)]
 
@@ -10,29 +13,41 @@ impl Struct {
     // Test using `&mut self` sugar:
 
     async fn ref_self(&mut self, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     // Test using `&mut Self` explicitly:
 
     async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 }
 
diff --git a/src/test/ui/self/elision/ref-mut-self-async.stderr b/src/test/ui/self/elision/ref-mut-self-async.stderr
deleted file mode 100644 (file)
index 6056cc4..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-self-async.rs:13:9
-   |
-LL |     async fn ref_self(&mut self, f: &u32) -> &u32 {
-   |                                     ----     ----
-   |                                     |
-   |                                     this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-self-async.rs:19:9
-   |
-LL |     async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
-   |                                           ----     ----
-   |                                           |
-   |                                           this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-self-async.rs:23:9
-   |
-LL |     async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
-   |                                                    ----     ----
-   |                                                    |
-   |                                                    this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-self-async.rs:27:9
-   |
-LL |     async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
-   |                                                    ----     ----
-   |                                                    |
-   |                                                    this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-self-async.rs:31:9
-   |
-LL |     async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
-   |                                                             ----     ----
-   |                                                             |
-   |                                                             this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-self-async.rs:35:9
-   |
-LL |     async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
-   |                                                             ----     ----
-   |                                                             |
-   |                                                             this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/self/elision/ref-mut-self.base.stderr b/src/test/ui/self/elision/ref-mut-self.base.stderr
new file mode 100644 (file)
index 0000000..fcedddd
--- /dev/null
@@ -0,0 +1,99 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self.rs:15:9
+   |
+LL |     fn ref_self(&mut self, f: &u32) -> &u32 {
+   |                               ----     ----
+   |                               |
+   |                               this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_self<'a>(&'a mut self, f: &'a u32) -> &u32 {
+   |                ++++  ++               ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self.rs:23:9
+   |
+LL |     fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
+   |                                     ----     ----
+   |                                     |
+   |                                     this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_Self<'a>(self: &'a mut Self, f: &'a u32) -> &u32 {
+   |                ++++        ++               ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self.rs:29:9
+   |
+LL |     fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
+   |                                              ----     ----
+   |                                              |
+   |                                              this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_ref_Self<'a>(self: Box<&'a mut Self>, f: &'a u32) -> &u32 {
+   |                    ++++            ++                ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self.rs:35:9
+   |
+LL |     fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
+   |                                              ----     ----
+   |                                              |
+   |                                              this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn pin_ref_Self<'a>(self: Pin<&'a mut Self>, f: &'a u32) -> &u32 {
+   |                    ++++            ++                ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self.rs:41:9
+   |
+LL |     fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
+   |                                                       ----     ----
+   |                                                       |
+   |                                                       this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_box_ref_Self<'a>(self: Box<Box<&'a mut Self>>, f: &'a u32) -> &u32 {
+   |                        ++++                ++                 ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self.rs:47:9
+   |
+LL |     fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
+   |                                                       ----     ----
+   |                                                       |
+   |                                                       this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_pin_ref_Self<'a>(self: Box<Pin<&'a mut Self>>, f: &'a u32) -> &u32 {
+   |                        ++++                ++                 ++
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
index 94bfc5f4a818693776b35b4fc60e72b399d87f85..f1f4d341b2bd8ac45b464f39bffde6380271ae99 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-self.rs:11:9
+  --> $DIR/ref-mut-self.rs:15:9
    |
 LL |     fn ref_self(&mut self, f: &u32) -> &u32 {
    |                 -             - let's call the lifetime of this reference `'1`
@@ -9,7 +9,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-self.rs:17:9
+  --> $DIR/ref-mut-self.rs:23:9
    |
 LL |     fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
    |                       -             - let's call the lifetime of this reference `'1`
@@ -19,7 +19,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-self.rs:21:9
+  --> $DIR/ref-mut-self.rs:29:9
    |
 LL |     fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
    |                               -              - let's call the lifetime of this reference `'1`
@@ -29,7 +29,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-self.rs:25:9
+  --> $DIR/ref-mut-self.rs:35:9
    |
 LL |     fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
    |                               -              - let's call the lifetime of this reference `'1`
@@ -39,7 +39,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-self.rs:29:9
+  --> $DIR/ref-mut-self.rs:41:9
    |
 LL |     fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
    |                                       -               - let's call the lifetime of this reference `'1`
@@ -49,7 +49,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-self.rs:33:9
+  --> $DIR/ref-mut-self.rs:47:9
    |
 LL |     fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
    |                                       -               - let's call the lifetime of this reference `'1`
index 8d9359dbd94b571c369a8cc34c20c1df2b514b67..81bd279129d2b0160f934bb672d38a3b2002879a 100644 (file)
@@ -1,3 +1,7 @@
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
+
 #![allow(non_snake_case)]
 
 use std::pin::Pin;
@@ -8,29 +12,41 @@ impl Struct {
     // Test using `&mut self` sugar:
 
     fn ref_self(&mut self, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     // Test using `&mut Self` explicitly:
 
     fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 }
 
diff --git a/src/test/ui/self/elision/ref-mut-self.stderr b/src/test/ui/self/elision/ref-mut-self.stderr
deleted file mode 100644 (file)
index 416719a..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-self.rs:11:9
-   |
-LL |     fn ref_self(&mut self, f: &u32) -> &u32 {
-   |                               ----     ----
-   |                               |
-   |                               this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn ref_self<'a>(&'a mut self, f: &'a u32) -> &u32 {
-   |                ++++  ++               ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-self.rs:17:9
-   |
-LL |     fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
-   |                                     ----     ----
-   |                                     |
-   |                                     this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn ref_Self<'a>(self: &'a mut Self, f: &'a u32) -> &u32 {
-   |                ++++        ++               ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-self.rs:21:9
-   |
-LL |     fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
-   |                                              ----     ----
-   |                                              |
-   |                                              this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn box_ref_Self<'a>(self: Box<&'a mut Self>, f: &'a u32) -> &u32 {
-   |                    ++++            ++                ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-self.rs:25:9
-   |
-LL |     fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
-   |                                              ----     ----
-   |                                              |
-   |                                              this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn pin_ref_Self<'a>(self: Pin<&'a mut Self>, f: &'a u32) -> &u32 {
-   |                    ++++            ++                ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-self.rs:29:9
-   |
-LL |     fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
-   |                                                       ----     ----
-   |                                                       |
-   |                                                       this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn box_box_ref_Self<'a>(self: Box<Box<&'a mut Self>>, f: &'a u32) -> &u32 {
-   |                        ++++                ++                 ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-self.rs:33:9
-   |
-LL |     fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
-   |                                                       ----     ----
-   |                                                       |
-   |                                                       this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn box_pin_ref_Self<'a>(self: Box<Pin<&'a mut Self>>, f: &'a u32) -> &u32 {
-   |                        ++++                ++                 ++
-
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/self/elision/ref-mut-struct-async.base.stderr b/src/test/ui/self/elision/ref-mut-struct-async.base.stderr
new file mode 100644 (file)
index 0000000..0de11c2
--- /dev/null
@@ -0,0 +1,53 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-struct-async.rs:16:9
+   |
+LL |     async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
+   |                                               ----     ----
+   |                                               |
+   |                                               this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-struct-async.rs:22:9
+   |
+LL |     async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
+   |                                                        ----     ----
+   |                                                        |
+   |                                                        this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-struct-async.rs:28:9
+   |
+LL |     async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
+   |                                                        ----     ----
+   |                                                        |
+   |                                                        this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-struct-async.rs:34:9
+   |
+LL |     async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
+   |                                                                 ----     ----
+   |                                                                 |
+   |                                                                 this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-struct-async.rs:40:9
+   |
+LL |     async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
+   |                                                                 ----     ----
+   |                                                                 |
+   |                                                                 this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
index 94671c7c87a5e516113ea7a986bf366ba70f3130..0ef410c8df1eb1c0479b10f3bd543026310e25bf 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-struct-async.rs:13:9
+  --> $DIR/ref-mut-struct-async.rs:16:9
    |
 LL |     async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
    |                               -               - let's call the lifetime of this reference `'1`
@@ -9,7 +9,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-struct-async.rs:17:9
+  --> $DIR/ref-mut-struct-async.rs:22:9
    |
 LL |     async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
    |                                       -                - let's call the lifetime of this reference `'1`
@@ -19,7 +19,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-struct-async.rs:21:9
+  --> $DIR/ref-mut-struct-async.rs:28:9
    |
 LL |     async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
    |                                       -                - let's call the lifetime of this reference `'1`
@@ -29,7 +29,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-struct-async.rs:25:9
+  --> $DIR/ref-mut-struct-async.rs:34:9
    |
 LL |     async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
    |                                               -                 - let's call the lifetime of this reference `'1`
@@ -39,7 +39,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-struct-async.rs:29:9
+  --> $DIR/ref-mut-struct-async.rs:40:9
    |
 LL |     async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
    |                                               -                 - let's call the lifetime of this reference `'1`
index 990f485907f8ec70cc9b534e13463af17c7b810b..7448988355c9ef6bb1d63614e7da9c01d66a5c0a 100644 (file)
@@ -1,4 +1,7 @@
 // edition:2018
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
 
 #![allow(non_snake_case)]
 
@@ -10,23 +13,33 @@ impl Struct {
     // Test using `&mut Struct` explicitly:
 
     async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 }
 
diff --git a/src/test/ui/self/elision/ref-mut-struct-async.stderr b/src/test/ui/self/elision/ref-mut-struct-async.stderr
deleted file mode 100644 (file)
index 61034ae..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-struct-async.rs:13:9
-   |
-LL |     async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
-   |                                               ----     ----
-   |                                               |
-   |                                               this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-struct-async.rs:17:9
-   |
-LL |     async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
-   |                                                        ----     ----
-   |                                                        |
-   |                                                        this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-struct-async.rs:21:9
-   |
-LL |     async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
-   |                                                        ----     ----
-   |                                                        |
-   |                                                        this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-struct-async.rs:25:9
-   |
-LL |     async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
-   |                                                                 ----     ----
-   |                                                                 |
-   |                                                                 this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-struct-async.rs:29:9
-   |
-LL |     async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
-   |                                                                 ----     ----
-   |                                                                 |
-   |                                                                 this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/self/elision/ref-mut-struct.base.stderr b/src/test/ui/self/elision/ref-mut-struct.base.stderr
new file mode 100644 (file)
index 0000000..a01492f
--- /dev/null
@@ -0,0 +1,83 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-struct.rs:15:9
+   |
+LL |     fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
+   |                                         ----     ----
+   |                                         |
+   |                                         this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_Struct<'a>(self: &'a mut Struct, f: &'a u32) -> &u32 {
+   |                  ++++        ++                 ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-struct.rs:21:9
+   |
+LL |     fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
+   |                                                  ----     ----
+   |                                                  |
+   |                                                  this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_ref_Struct<'a>(self: Box<&'a mut Struct>, f: &'a u32) -> &u32 {
+   |                      ++++            ++                  ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-struct.rs:27:9
+   |
+LL |     fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
+   |                                                  ----     ----
+   |                                                  |
+   |                                                  this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn pin_ref_Struct<'a>(self: Pin<&'a mut Struct>, f: &'a u32) -> &u32 {
+   |                      ++++            ++                  ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-struct.rs:33:9
+   |
+LL |     fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
+   |                                                           ----     ----
+   |                                                           |
+   |                                                           this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_box_ref_Struct<'a>(self: Box<Box<&'a mut Struct>>, f: &'a u32) -> &u32 {
+   |                          ++++                ++                   ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-struct.rs:39:9
+   |
+LL |     fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
+   |                                                           ----     ----
+   |                                                           |
+   |                                                           this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_pin_ref_Struct<'a>(self: Box<Pin<&'a mut Struct>>, f: &'a u32) -> &u32 {
+   |                          ++++                ++                   ++
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
index c9e7479ea5dff46a2154088e44e1c877a74837c5..de7eb02d7a7fe38e82f341d056cf512d08ffa806 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-struct.rs:11:9
+  --> $DIR/ref-mut-struct.rs:15:9
    |
 LL |     fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
    |                         -               - let's call the lifetime of this reference `'1`
@@ -9,7 +9,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-struct.rs:15:9
+  --> $DIR/ref-mut-struct.rs:21:9
    |
 LL |     fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
    |                                 -                - let's call the lifetime of this reference `'1`
@@ -19,7 +19,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-struct.rs:19:9
+  --> $DIR/ref-mut-struct.rs:27:9
    |
 LL |     fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
    |                                 -                - let's call the lifetime of this reference `'1`
@@ -29,7 +29,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-struct.rs:23:9
+  --> $DIR/ref-mut-struct.rs:33:9
    |
 LL |     fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
    |                                         -                 - let's call the lifetime of this reference `'1`
@@ -39,7 +39,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-struct.rs:27:9
+  --> $DIR/ref-mut-struct.rs:39:9
    |
 LL |     fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
    |                                         -                 - let's call the lifetime of this reference `'1`
index 05e275b19e4c414d6cb422eed2a4db9ff9c769b6..72674bd65b66a8fd53ce042f7debb3a8f9a06280 100644 (file)
@@ -1,3 +1,7 @@
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
+
 #![allow(non_snake_case)]
 
 use std::pin::Pin;
@@ -8,23 +12,33 @@ impl Struct {
     // Test using `&mut Struct` explicitly:
 
     fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 }
 
diff --git a/src/test/ui/self/elision/ref-mut-struct.stderr b/src/test/ui/self/elision/ref-mut-struct.stderr
deleted file mode 100644 (file)
index 6ca9ab1..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-struct.rs:11:9
-   |
-LL |     fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
-   |                                         ----     ----
-   |                                         |
-   |                                         this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn ref_Struct<'a>(self: &'a mut Struct, f: &'a u32) -> &u32 {
-   |                  ++++        ++                 ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-struct.rs:15:9
-   |
-LL |     fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
-   |                                                  ----     ----
-   |                                                  |
-   |                                                  this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn box_ref_Struct<'a>(self: Box<&'a mut Struct>, f: &'a u32) -> &u32 {
-   |                      ++++            ++                  ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-struct.rs:19:9
-   |
-LL |     fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
-   |                                                  ----     ----
-   |                                                  |
-   |                                                  this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn pin_ref_Struct<'a>(self: Pin<&'a mut Struct>, f: &'a u32) -> &u32 {
-   |                      ++++            ++                  ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-struct.rs:23:9
-   |
-LL |     fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
-   |                                                           ----     ----
-   |                                                           |
-   |                                                           this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn box_box_ref_Struct<'a>(self: Box<Box<&'a mut Struct>>, f: &'a u32) -> &u32 {
-   |                          ++++                ++                   ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-mut-struct.rs:27:9
-   |
-LL |     fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
-   |                                                           ----     ----
-   |                                                           |
-   |                                                           this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn box_pin_ref_Struct<'a>(self: Box<Pin<&'a mut Struct>>, f: &'a u32) -> &u32 {
-   |                          ++++                ++                   ++
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/self/elision/ref-self-async.base.stderr b/src/test/ui/self/elision/ref-self-async.base.stderr
new file mode 100644 (file)
index 0000000..fa13b69
--- /dev/null
@@ -0,0 +1,73 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self-async.rs:26:9
+   |
+LL |     async fn ref_self(&self, f: &u32) -> &u32 {
+   |                                 ----     ----
+   |                                 |
+   |                                 this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self-async.rs:34:9
+   |
+LL |     async fn ref_Self(self: &Self, f: &u32) -> &u32 {
+   |                                       ----     ----
+   |                                       |
+   |                                       this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self-async.rs:40:9
+   |
+LL |     async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+   |                                                ----     ----
+   |                                                |
+   |                                                this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self-async.rs:46:9
+   |
+LL |     async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+   |                                                ----     ----
+   |                                                |
+   |                                                this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self-async.rs:52:9
+   |
+LL |     async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+   |                                                         ----     ----
+   |                                                         |
+   |                                                         this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self-async.rs:58:9
+   |
+LL |     async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+   |                                                         ----     ----
+   |                                                         |
+   |                                                         this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self-async.rs:64:9
+   |
+LL |     async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
+   |                                                             ---     ---
+   |                                                             |
+   |                                                             this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
index bd1f80811b5425748ffe18cf90ff1e3c70f5136a..77faaa866505fb1ae5d8e74ab9a88faa6390b901 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/ref-self-async.rs:23:9
+  --> $DIR/ref-self-async.rs:26:9
    |
 LL |     async fn ref_self(&self, f: &u32) -> &u32 {
    |                       -         - let's call the lifetime of this reference `'1`
@@ -9,7 +9,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self-async.rs:29:9
+  --> $DIR/ref-self-async.rs:34:9
    |
 LL |     async fn ref_Self(self: &Self, f: &u32) -> &u32 {
    |                             -         - let's call the lifetime of this reference `'1`
@@ -19,7 +19,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self-async.rs:33:9
+  --> $DIR/ref-self-async.rs:40:9
    |
 LL |     async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
    |                                     -          - let's call the lifetime of this reference `'1`
@@ -29,7 +29,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self-async.rs:37:9
+  --> $DIR/ref-self-async.rs:46:9
    |
 LL |     async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
    |                                     -          - let's call the lifetime of this reference `'1`
@@ -39,7 +39,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self-async.rs:41:9
+  --> $DIR/ref-self-async.rs:52:9
    |
 LL |     async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
    |                                             -           - let's call the lifetime of this reference `'1`
@@ -49,7 +49,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self-async.rs:45:9
+  --> $DIR/ref-self-async.rs:58:9
    |
 LL |     async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
    |                                             -           - let's call the lifetime of this reference `'1`
@@ -59,7 +59,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self-async.rs:49:9
+  --> $DIR/ref-self-async.rs:64:9
    |
 LL |     async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
    |                                            -                - let's call the lifetime of this reference `'1`
index 0fbbd95c975d6afb2ea35b35033a5480eabeba99..afe5fe100e36ca10c92c0e75bc320c9ea219dc75 100644 (file)
@@ -1,4 +1,7 @@
 // edition:2018
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
 
 #![allow(non_snake_case)]
 #![feature(arbitrary_self_types)]
@@ -20,33 +23,47 @@ impl Struct {
     // Test using `&self` sugar:
 
     async fn ref_self(&self, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     // Test using `&Self` explicitly:
 
     async fn ref_Self(self: &Self, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 }
 
diff --git a/src/test/ui/self/elision/ref-self-async.stderr b/src/test/ui/self/elision/ref-self-async.stderr
deleted file mode 100644 (file)
index 0eab16e..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-self-async.rs:23:9
-   |
-LL |     async fn ref_self(&self, f: &u32) -> &u32 {
-   |                                 ----     ----
-   |                                 |
-   |                                 this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-self-async.rs:29:9
-   |
-LL |     async fn ref_Self(self: &Self, f: &u32) -> &u32 {
-   |                                       ----     ----
-   |                                       |
-   |                                       this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-self-async.rs:33:9
-   |
-LL |     async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
-   |                                                ----     ----
-   |                                                |
-   |                                                this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-self-async.rs:37:9
-   |
-LL |     async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
-   |                                                ----     ----
-   |                                                |
-   |                                                this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-self-async.rs:41:9
-   |
-LL |     async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
-   |                                                         ----     ----
-   |                                                         |
-   |                                                         this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-self-async.rs:45:9
-   |
-LL |     async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
-   |                                                         ----     ----
-   |                                                         |
-   |                                                         this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-self-async.rs:49:9
-   |
-LL |     async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
-   |                                                             ---     ---
-   |                                                             |
-   |                                                             this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error: aborting due to 7 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/self/elision/ref-self.base.stderr b/src/test/ui/self/elision/ref-self.base.stderr
new file mode 100644 (file)
index 0000000..8bd194d
--- /dev/null
@@ -0,0 +1,115 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self.rs:25:9
+   |
+LL |     fn ref_self(&self, f: &u32) -> &u32 {
+   |                           ----     ----
+   |                           |
+   |                           this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 {
+   |                ++++  ++           ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self.rs:33:9
+   |
+LL |     fn ref_Self(self: &Self, f: &u32) -> &u32 {
+   |                                 ----     ----
+   |                                 |
+   |                                 this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 {
+   |                ++++        ++           ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self.rs:39:9
+   |
+LL |     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+   |                                          ----     ----
+   |                                          |
+   |                                          this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 {
+   |                    ++++            ++            ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self.rs:45:9
+   |
+LL |     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+   |                                          ----     ----
+   |                                          |
+   |                                          this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 {
+   |                    ++++            ++            ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self.rs:51:9
+   |
+LL |     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+   |                                                   ----     ----
+   |                                                   |
+   |                                                   this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 {
+   |                        ++++                ++             ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self.rs:57:9
+   |
+LL |     fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+   |                                                   ----     ----
+   |                                                   |
+   |                                                   this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_pin_ref_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 {
+   |                        ++++                ++             ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self.rs:63:9
+   |
+LL |     fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
+   |                                                       ---     ---
+   |                                                       |
+   |                                                       this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn wrap_ref_Self_Self<'a>(self: Wrap<&'a Self, Self>, f: &'a u8) -> &u8 {
+   |                          ++++             ++                  ++
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
index d1fd209102e6952454549b03a34501e1b54ca321..f2b7b0ad019570965bfae7026292e79d121ac51c 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/ref-self.rs:21:9
+  --> $DIR/ref-self.rs:25:9
    |
 LL |     fn ref_self(&self, f: &u32) -> &u32 {
    |                 -         - let's call the lifetime of this reference `'1`
@@ -9,7 +9,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self.rs:27:9
+  --> $DIR/ref-self.rs:33:9
    |
 LL |     fn ref_Self(self: &Self, f: &u32) -> &u32 {
    |                       -         - let's call the lifetime of this reference `'1`
@@ -19,7 +19,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self.rs:31:9
+  --> $DIR/ref-self.rs:39:9
    |
 LL |     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
    |                               -          - let's call the lifetime of this reference `'1`
@@ -29,7 +29,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self.rs:35:9
+  --> $DIR/ref-self.rs:45:9
    |
 LL |     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
    |                               -          - let's call the lifetime of this reference `'1`
@@ -39,7 +39,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self.rs:39:9
+  --> $DIR/ref-self.rs:51:9
    |
 LL |     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
    |                                       -           - let's call the lifetime of this reference `'1`
@@ -49,7 +49,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self.rs:43:9
+  --> $DIR/ref-self.rs:57:9
    |
 LL |     fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
    |                                       -           - let's call the lifetime of this reference `'1`
@@ -59,7 +59,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self.rs:47:9
+  --> $DIR/ref-self.rs:63:9
    |
 LL |     fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
    |                                      -                - let's call the lifetime of this reference `'1`
index e389d8518ada4f6a375e4d48c8cba91324aed168..34df3da4505e81cefb725f7aa91c86bb280025a9 100644 (file)
@@ -1,3 +1,7 @@
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
+
 #![feature(arbitrary_self_types)]
 #![allow(non_snake_case)]
 
@@ -18,33 +22,47 @@ impl Struct {
     // Test using `&self` sugar:
 
     fn ref_self(&self, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     // Test using `&Self` explicitly:
 
     fn ref_Self(self: &Self, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 }
 
diff --git a/src/test/ui/self/elision/ref-self.stderr b/src/test/ui/self/elision/ref-self.stderr
deleted file mode 100644 (file)
index 955222f..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-self.rs:21:9
-   |
-LL |     fn ref_self(&self, f: &u32) -> &u32 {
-   |                           ----     ----
-   |                           |
-   |                           this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 {
-   |                ++++  ++           ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-self.rs:27:9
-   |
-LL |     fn ref_Self(self: &Self, f: &u32) -> &u32 {
-   |                                 ----     ----
-   |                                 |
-   |                                 this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 {
-   |                ++++        ++           ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-self.rs:31:9
-   |
-LL |     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
-   |                                          ----     ----
-   |                                          |
-   |                                          this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 {
-   |                    ++++            ++            ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-self.rs:35:9
-   |
-LL |     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
-   |                                          ----     ----
-   |                                          |
-   |                                          this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 {
-   |                    ++++            ++            ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-self.rs:39:9
-   |
-LL |     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
-   |                                                   ----     ----
-   |                                                   |
-   |                                                   this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 {
-   |                        ++++                ++             ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-self.rs:43:9
-   |
-LL |     fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
-   |                                                   ----     ----
-   |                                                   |
-   |                                                   this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn box_pin_ref_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 {
-   |                        ++++                ++             ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-self.rs:47:9
-   |
-LL |     fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
-   |                                                       ---     ---
-   |                                                       |
-   |                                                       this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn wrap_ref_Self_Self<'a>(self: Wrap<&'a Self, Self>, f: &'a u8) -> &u8 {
-   |                          ++++             ++                  ++
-
-error: aborting due to 7 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/self/elision/ref-struct-async.base.stderr b/src/test/ui/self/elision/ref-struct-async.base.stderr
new file mode 100644 (file)
index 0000000..8da673d
--- /dev/null
@@ -0,0 +1,53 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-struct-async.rs:16:9
+   |
+LL |     async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+   |                                           ----     ----
+   |                                           |
+   |                                           this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-struct-async.rs:22:9
+   |
+LL |     async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
+   |                                                    ----     ----
+   |                                                    |
+   |                                                    this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-struct-async.rs:28:9
+   |
+LL |     async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
+   |                                                    ----     ----
+   |                                                    |
+   |                                                    this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-struct-async.rs:34:9
+   |
+LL |     async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
+   |                                                             ----     ----
+   |                                                             |
+   |                                                             this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-struct-async.rs:40:9
+   |
+LL |     async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
+   |                                                         ----     ----
+   |                                                         |
+   |                                                         this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
index 9361b6f3f81f429eb20393248016a3fcee3e6c9b..ad07c70df87783e1808328de3eb89e9d4ab6f2ff 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/ref-struct-async.rs:13:9
+  --> $DIR/ref-struct-async.rs:16:9
    |
 LL |     async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    |                               -           - let's call the lifetime of this reference `'1`
@@ -9,7 +9,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-struct-async.rs:17:9
+  --> $DIR/ref-struct-async.rs:22:9
    |
 LL |     async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
    |                                       -            - let's call the lifetime of this reference `'1`
@@ -19,7 +19,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-struct-async.rs:21:9
+  --> $DIR/ref-struct-async.rs:28:9
    |
 LL |     async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
    |                                       -            - let's call the lifetime of this reference `'1`
@@ -29,7 +29,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-struct-async.rs:25:9
+  --> $DIR/ref-struct-async.rs:34:9
    |
 LL |     async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
    |                                               -             - let's call the lifetime of this reference `'1`
@@ -39,7 +39,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-struct-async.rs:29:9
+  --> $DIR/ref-struct-async.rs:40:9
    |
 LL |     async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
    |                                           -             - let's call the lifetime of this reference `'1`
index e6bd5418c8d92b8b6986e41aecd277c12159ef22..12f8f6faf1b9c361750ea4d6ccd7497a52714129 100644 (file)
@@ -1,4 +1,7 @@
 // edition:2018
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
 
 #![allow(non_snake_case)]
 
@@ -10,23 +13,33 @@ impl Struct {
     // Test using `&Struct` explicitly:
 
     async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 }
 
diff --git a/src/test/ui/self/elision/ref-struct-async.stderr b/src/test/ui/self/elision/ref-struct-async.stderr
deleted file mode 100644 (file)
index aa1d745..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-struct-async.rs:13:9
-   |
-LL |     async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
-   |                                           ----     ----
-   |                                           |
-   |                                           this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-struct-async.rs:17:9
-   |
-LL |     async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
-   |                                                    ----     ----
-   |                                                    |
-   |                                                    this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-struct-async.rs:21:9
-   |
-LL |     async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
-   |                                                    ----     ----
-   |                                                    |
-   |                                                    this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-struct-async.rs:25:9
-   |
-LL |     async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
-   |                                                             ----     ----
-   |                                                             |
-   |                                                             this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-struct-async.rs:29:9
-   |
-LL |     async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
-   |                                                         ----     ----
-   |                                                         |
-   |                                                         this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/self/elision/ref-struct.base.stderr b/src/test/ui/self/elision/ref-struct.base.stderr
new file mode 100644 (file)
index 0000000..5650b37
--- /dev/null
@@ -0,0 +1,83 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-struct.rs:15:9
+   |
+LL |     fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+   |                                     ----     ----
+   |                                     |
+   |                                     this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_Struct<'a>(self: &'a Struct, f: &'a u32) -> &u32 {
+   |                  ++++        ++             ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-struct.rs:21:9
+   |
+LL |     fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
+   |                                              ----     ----
+   |                                              |
+   |                                              this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_ref_Struct<'a>(self: Box<&'a Struct>, f: &'a u32) -> &u32 {
+   |                      ++++            ++              ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-struct.rs:27:9
+   |
+LL |     fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
+   |                                              ----     ----
+   |                                              |
+   |                                              this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn pin_ref_Struct<'a>(self: Pin<&'a Struct>, f: &'a u32) -> &u32 {
+   |                      ++++            ++              ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-struct.rs:33:9
+   |
+LL |     fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
+   |                                                       ----     ----
+   |                                                       |
+   |                                                       this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_box_ref_Struct<'a>(self: Box<Box<&'a Struct>>, f: &'a u32) -> &u32 {
+   |                          ++++                ++               ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-struct.rs:39:9
+   |
+LL |     fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
+   |                                                   ----     ----
+   |                                                   |
+   |                                                   this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_pin_Struct<'a>(self: Box<Pin<&'a Struct>>, f: &'a u32) -> &u32 {
+   |                      ++++                ++               ++
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
index e1cc38b7c952f949b95ed227592ac40214e43e0d..70453b0ddfc71ab2b8b951ee5420a5711680e387 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/ref-struct.rs:11:9
+  --> $DIR/ref-struct.rs:15:9
    |
 LL |     fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    |                         -           - let's call the lifetime of this reference `'1`
@@ -9,7 +9,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-struct.rs:15:9
+  --> $DIR/ref-struct.rs:21:9
    |
 LL |     fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
    |                                 -            - let's call the lifetime of this reference `'1`
@@ -19,7 +19,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-struct.rs:19:9
+  --> $DIR/ref-struct.rs:27:9
    |
 LL |     fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
    |                                 -            - let's call the lifetime of this reference `'1`
@@ -29,7 +29,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-struct.rs:23:9
+  --> $DIR/ref-struct.rs:33:9
    |
 LL |     fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
    |                                         -             - let's call the lifetime of this reference `'1`
@@ -39,7 +39,7 @@ LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/ref-struct.rs:27:9
+  --> $DIR/ref-struct.rs:39:9
    |
 LL |     fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
    |                                     -             - let's call the lifetime of this reference `'1`
index 73711a7feead3a8dfab0e6c3968c0647063b94b4..0ffe72793d731c4d29d1283fb812faefe4876b98 100644 (file)
@@ -1,3 +1,7 @@
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
+
 #![allow(non_snake_case)]
 
 use std::pin::Pin;
@@ -8,23 +12,33 @@ impl Struct {
     // Test using `&Struct` explicitly:
 
     fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 
     fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
-        f //~ ERROR lifetime mismatch
+        f
+        //[base]~^ ERROR lifetime mismatch
+        //[nll]~^^ ERROR lifetime may not live long enough
     }
 }
 
diff --git a/src/test/ui/self/elision/ref-struct.stderr b/src/test/ui/self/elision/ref-struct.stderr
deleted file mode 100644 (file)
index c80993f..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-struct.rs:11:9
-   |
-LL |     fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
-   |                                     ----     ----
-   |                                     |
-   |                                     this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn ref_Struct<'a>(self: &'a Struct, f: &'a u32) -> &u32 {
-   |                  ++++        ++             ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-struct.rs:15:9
-   |
-LL |     fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
-   |                                              ----     ----
-   |                                              |
-   |                                              this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn box_ref_Struct<'a>(self: Box<&'a Struct>, f: &'a u32) -> &u32 {
-   |                      ++++            ++              ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-struct.rs:19:9
-   |
-LL |     fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
-   |                                              ----     ----
-   |                                              |
-   |                                              this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn pin_ref_Struct<'a>(self: Pin<&'a Struct>, f: &'a u32) -> &u32 {
-   |                      ++++            ++              ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-struct.rs:23:9
-   |
-LL |     fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
-   |                                                       ----     ----
-   |                                                       |
-   |                                                       this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn box_box_ref_Struct<'a>(self: Box<Box<&'a Struct>>, f: &'a u32) -> &u32 {
-   |                          ++++                ++               ++
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ref-struct.rs:27:9
-   |
-LL |     fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
-   |                                                   ----     ----
-   |                                                   |
-   |                                                   this parameter and the return type are declared with different lifetimes...
-LL |         f
-   |         ^ ...but data from `f` is returned here
-   |
-   = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
-   |
-LL |     fn box_pin_Struct<'a>(self: Box<Pin<&'a Struct>>, f: &'a u32) -> &u32 {
-   |                      ++++                ++               ++
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
index 09ffe8e64b1b16962be4e5872952056db8f6288f..dd7194dc2e840b897db177c1473e1ddbdec5b199 100644 (file)
@@ -2,7 +2,15 @@ error[E0308]: mismatched types
   --> $DIR/issue-61882.rs:4:27
    |
 LL |     const B: A<u8> = Self(0);
-   |                           ^ expected `bool`, found integer
+   |                      ---- ^ expected `bool`, found integer
+   |                      |
+   |                      arguments to this function are incorrect
+   |
+note: tuple struct defined here
+  --> $DIR/issue-61882.rs:1:8
+   |
+LL | struct A<T>(T);
+   |        ^
 
 error[E0308]: mismatched types
   --> $DIR/issue-61882.rs:4:22
diff --git a/src/test/ui/span/E0057.rs b/src/test/ui/span/E0057.rs
new file mode 100644 (file)
index 0000000..83f941f
--- /dev/null
@@ -0,0 +1,6 @@
+fn main() {
+    let f = |x| x * 3;
+    let a = f(); //~ ERROR E0057
+    let b = f(4);
+    let c = f(2, 3); //~ ERROR E0057
+}
diff --git a/src/test/ui/span/E0057.stderr b/src/test/ui/span/E0057.stderr
new file mode 100644 (file)
index 0000000..a151b20
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0057]: this function takes 1 argument but 0 arguments were supplied
+  --> $DIR/E0057.rs:3:13
+   |
+LL |     let a = f();
+   |             ^-- an argument is missing
+   |
+help: provide the argument
+   |
+LL |     let a = f({_});
+   |             ~~~~~~
+
+error[E0057]: this function takes 1 argument but 2 arguments were supplied
+  --> $DIR/E0057.rs:5:13
+   |
+LL |     let c = f(2, 3);
+   |             ^    - argument unexpected
+   |
+help: remove the extra argument
+   |
+LL |     let c = f(2);
+   |             ~~~~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0057`.
index 5a964c5d5cc6693e1667e60a7e1f647b42da75be..db784d5fe6cfc8be856bba650d3c73e750f2b061 100644 (file)
@@ -20,19 +20,33 @@ error[E0308]: mismatched types
   --> $DIR/coerce-suggestions.rs:12:10
    |
 LL |     test(&y);
-   |          ^^ types differ in mutability
+   |     ---- ^^ types differ in mutability
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected mutable reference `&mut String`
                       found reference `&String`
+note: function defined here
+  --> $DIR/coerce-suggestions.rs:1:4
+   |
+LL | fn test(_x: &mut String) {}
+   |    ^^^^ ---------------
 
 error[E0308]: mismatched types
   --> $DIR/coerce-suggestions.rs:14:11
    |
 LL |     test2(&y);
-   |           ^^ types differ in mutability
+   |     ----- ^^ types differ in mutability
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected mutable reference `&mut i32`
                       found reference `&String`
+note: function defined here
+  --> $DIR/coerce-suggestions.rs:3:4
+   |
+LL | fn test2(_x: &mut i32) {}
+   |    ^^^^^ ------------
 
 error[E0308]: mismatched types
   --> $DIR/coerce-suggestions.rs:17:9
index 8d26ca4ac7a743096d8c0225dc73e07dffa32ddc..68da9f0dc88ba2f7f8923092a0cfdc3a1da61182 100644 (file)
@@ -54,35 +54,47 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/issue-34264.rs:7:5
    |
 LL |     foo(Some(42), 2, "");
-   |     ^^^ --------  -  -- supplied 3 arguments
-   |     |
-   |     expected 2 arguments
+   |     ^^^              -- argument unexpected
    |
 note: function defined here
   --> $DIR/issue-34264.rs:1:4
    |
 LL | fn foo(Option<i32>, String) {}
    |    ^^^ -----------  ------
+help: remove the extra argument
+   |
+LL |     foo(Some(42), 2);
+   |     ~~~~~~~~~~~~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/issue-34264.rs:8:13
    |
 LL |     bar("", "");
-   |             ^^ expected `usize`, found `&str`
+   |     ---     ^^ expected `usize`, found `&str`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/issue-34264.rs:3:4
+   |
+LL | fn bar(x, y: usize) {}
+   |    ^^^ -  --------
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/issue-34264.rs:10:5
    |
 LL |     bar(1, 2, 3);
-   |     ^^^ -  -  - supplied 3 arguments
-   |     |
-   |     expected 2 arguments
+   |     ^^^       - argument unexpected
    |
 note: function defined here
   --> $DIR/issue-34264.rs:3:4
    |
 LL | fn bar(x, y: usize) {}
    |    ^^^ -  --------
+help: remove the extra argument
+   |
+LL |     bar(1, 2);
+   |     ~~~~~~~~~
 
 error: aborting due to 6 previous errors
 
index 99c57322d865141092e157d1d25bdee15833ae53..c8e1a23288751a912fce8bb67605cab9419da7d9 100644 (file)
@@ -2,88 +2,92 @@ error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:11:33
    |
 LL |     let _: Result<(), String> = Ok();
-   |                                 ^^-- supplied 0 arguments
+   |                                 ^^-- an argument of type `()` is missing
    |
-help: expected the unit value `()`; create it with empty parentheses
+help: provide the argument
    |
 LL |     let _: Result<(), String> = Ok(());
-   |                                    ++
+   |                                 ~~~~~~
 
 error[E0061]: this function takes 2 arguments but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:12:5
    |
 LL |     foo();
-   |     ^^^-- supplied 0 arguments
-   |     |
-   |     expected 2 arguments
+   |     ^^^-- two arguments of type `()` and `()` are missing
    |
 note: function defined here
   --> $DIR/missing-unit-argument.rs:1:4
    |
 LL | fn foo(():(), ():()) {}
    |    ^^^ -----  -----
+help: provide the arguments
+   |
+LL |     foo((), ());
+   |     ~~~~~~~~~~~
 
 error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/missing-unit-argument.rs:13:5
    |
 LL |     foo(());
-   |     ^^^ -- supplied 1 argument
-   |     |
-   |     expected 2 arguments
+   |     ^^^---- an argument of type `()` is missing
    |
 note: function defined here
   --> $DIR/missing-unit-argument.rs:1:4
    |
 LL | fn foo(():(), ():()) {}
    |    ^^^ -----  -----
+help: provide the argument
+   |
+LL |     foo((), ());
+   |     ~~~~~~~~~~~
 
 error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:14:5
    |
 LL |     bar();
-   |     ^^^-- supplied 0 arguments
+   |     ^^^-- an argument of type `()` is missing
    |
 note: function defined here
   --> $DIR/missing-unit-argument.rs:2:4
    |
 LL | fn bar(():()) {}
    |    ^^^ -----
-help: expected the unit value `()`; create it with empty parentheses
+help: provide the argument
    |
 LL |     bar(());
-   |         ++
+   |     ~~~~~~~
 
 error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:15:7
    |
 LL |     S.baz();
-   |       ^^^- supplied 0 arguments
+   |       ^^^-- an argument of type `()` is missing
    |
 note: associated function defined here
   --> $DIR/missing-unit-argument.rs:6:8
    |
 LL |     fn baz(self, (): ()) { }
    |        ^^^ ----  ------
-help: expected the unit value `()`; create it with empty parentheses
+help: provide the argument
    |
 LL |     S.baz(());
-   |           ++
+   |       ~~~~~~~
 
 error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:16:7
    |
 LL |     S.generic::<()>();
-   |       ^^^^^^^------ supplied 0 arguments
+   |       ^^^^^^^^^^^^^-- an argument of type `()` is missing
    |
 note: associated function defined here
   --> $DIR/missing-unit-argument.rs:7:8
    |
 LL |     fn generic<T>(self, _: T) { }
    |        ^^^^^^^    ----  ----
-help: expected the unit value `()`; create it with empty parentheses
+help: provide the argument
    |
 LL |     S.generic::<()>(());
-   |                     ++
+   |       ~~~~~~~~~~~~~~~~~
 
 error: aborting due to 6 previous errors
 
index d5645474891062e2a43bddacdcf8fbe0ab450e7f..f5c6f444317feb7cbc643dbb43b15e1647ec6f8b 100644 (file)
@@ -11,11 +11,11 @@ enum Void {}
 
 static VOID2: Void = unsafe { std::mem::transmute(()) }; //~ ERROR static of uninhabited type
 //~| WARN: previously accepted
-//~| ERROR undefined behavior to use this value
+//~| ERROR could not evaluate static initializer
 //~| WARN: type `Void` does not permit zero-initialization
 static NEVER2: Void = unsafe { std::mem::transmute(()) }; //~ ERROR static of uninhabited type
 //~| WARN: previously accepted
-//~| ERROR undefined behavior to use this value
+//~| ERROR could not evaluate static initializer
 //~| WARN: type `Void` does not permit zero-initialization
 
 fn main() {}
index c38cf10d6e648bfad53cb16009a3d2c4c5759329..1e0becb7d5aa87662c33250585821911f2962a78 100644 (file)
@@ -43,23 +43,17 @@ LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
    = note: for more information, see issue #74840 <https://github.com/rust-lang/rust/issues/74840>
    = note: uninhabited statics cannot be initialized, and any access would be an immediate error
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/uninhabited-static.rs:12:1
+error[E0080]: could not evaluate static initializer
+  --> $DIR/uninhabited-static.rs:12:31
    |
 LL | static VOID2: Void = unsafe { std::mem::transmute(()) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Void
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 0, align: 1) {}
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/uninhabited-static.rs:16:1
+error[E0080]: could not evaluate static initializer
+  --> $DIR/uninhabited-static.rs:16:32
    |
 LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Void
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 0, align: 1) {}
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
 
 warning: the type `Void` does not permit zero-initialization
   --> $DIR/uninhabited-static.rs:12:31
index ddcdfb1c3b34413be0a3bc9e6504cbb75db0897a..991dde30629e93539f9ebf167cef79901ba384cf 100644 (file)
@@ -2,37 +2,55 @@ error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied
   --> $DIR/args-instead-of-tuple-errors.rs:6:34
    |
 LL |     let _: Option<(i32, bool)> = Some(1, 2);
-   |                                  ^^^^ -  - supplied 2 arguments
-   |                                  |
-   |                                  expected 1 argument
+   |                                  ^^^^ -  - argument unexpected
+   |                                       |
+   |                                       expected tuple, found integer
+   |
+   = note: expected tuple `(i32, bool)`
+               found type `{integer}`
+help: remove the extra argument
+   |
+LL |     let _: Option<(i32, bool)> = Some({(i32, bool)});
+   |                                  ~~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/args-instead-of-tuple-errors.rs:8:5
    |
 LL |     int_bool(1, 2);
-   |     ^^^^^^^^ -  - supplied 2 arguments
-   |     |
-   |     expected 1 argument
+   |     ^^^^^^^^ -  - argument unexpected
+   |              |
+   |              expected tuple, found integer
    |
+   = note: expected tuple `(i32, bool)`
+               found type `{integer}`
 note: function defined here
   --> $DIR/args-instead-of-tuple-errors.rs:21:4
    |
 LL | fn int_bool(_: (i32, bool)) {
    |    ^^^^^^^^ --------------
+help: remove the extra argument
+   |
+LL |     int_bool({(i32, bool)});
+   |     ~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
   --> $DIR/args-instead-of-tuple-errors.rs:11:28
    |
 LL |     let _: Option<(i8,)> = Some();
-   |                            ^^^^-- supplied 0 arguments
-   |                            |
-   |                            expected 1 argument
+   |                            ^^^^-- an argument of type `(i8,)` is missing
+   |
+help: provide the argument
+   |
+LL |     let _: Option<(i8,)> = Some({(i8,)});
+   |                            ~~~~~~~~~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/args-instead-of-tuple-errors.rs:14:34
    |
 LL |     let _: Option<(i32,)> = Some(5_usize);
-   |                                  ^^^^^^^ expected tuple, found `usize`
+   |                             ---- ^^^^^^^ expected tuple, found `usize`
+   |                             |
+   |                             arguments to this enum variant are incorrect
    |
    = note: expected tuple `(i32,)`
                found type `usize`
@@ -41,7 +59,9 @@ error[E0308]: mismatched types
   --> $DIR/args-instead-of-tuple-errors.rs:17:34
    |
 LL |     let _: Option<(i32,)> = Some((5_usize));
-   |                                  ^^^^^^^^^ expected tuple, found `usize`
+   |                             ---- ^^^^^^^^^ expected tuple, found `usize`
+   |                             |
+   |                             arguments to this enum variant are incorrect
    |
    = note: expected tuple `(i32,)`
                found type `usize`
index 6a7602c9d0f45cc3742ad56b50a52b0b5719e1c1..7ec10e88142c11c76f5b8b21746bd6457f85d518 100644 (file)
@@ -2,7 +2,7 @@ error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied
   --> $DIR/args-instead-of-tuple.rs:7:36
    |
 LL |     let _: Result<(i32, i8), ()> = Ok(1, 2);
-   |                                    ^^ -  - supplied 2 arguments
+   |                                    ^^
    |
 help: use parentheses to construct a tuple
    |
@@ -13,7 +13,7 @@ error[E0061]: this enum variant takes 1 argument but 3 arguments were supplied
   --> $DIR/args-instead-of-tuple.rs:9:46
    |
 LL |     let _: Option<(i32, i8, &'static str)> = Some(1, 2, "hi");
-   |                                              ^^^^ -  -  ---- supplied 3 arguments
+   |                                              ^^^^
    |
 help: use parentheses to construct a tuple
    |
@@ -24,18 +24,20 @@ error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
   --> $DIR/args-instead-of-tuple.rs:11:25
    |
 LL |     let _: Option<()> = Some();
-   |                         ^^^^-- supplied 0 arguments
+   |                         ^^^^-- an argument of type `()` is missing
    |
-help: expected the unit value `()`; create it with empty parentheses
+help: provide the argument
    |
 LL |     let _: Option<()> = Some(());
-   |                              ++
+   |                         ~~~~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/args-instead-of-tuple.rs:14:34
    |
 LL |     let _: Option<(i32,)> = Some(3);
-   |                                  ^ expected tuple, found integer
+   |                             ---- ^ expected tuple, found integer
+   |                             |
+   |                             arguments to this enum variant are incorrect
    |
    = note: expected tuple `(i32,)`
                found type `{integer}`
@@ -48,7 +50,9 @@ error[E0308]: mismatched types
   --> $DIR/args-instead-of-tuple.rs:17:34
    |
 LL |     let _: Option<(i32,)> = Some((3));
-   |                                  ^^^ expected tuple, found integer
+   |                             ---- ^^^ expected tuple, found integer
+   |                             |
+   |                             arguments to this enum variant are incorrect
    |
    = note: expected tuple `(i32,)`
                found type `{integer}`
@@ -61,7 +65,7 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/args-instead-of-tuple.rs:20:5
    |
 LL |     two_ints(1, 2);
-   |     ^^^^^^^^ -  - supplied 2 arguments
+   |     ^^^^^^^^
    |
 note: function defined here
   --> $DIR/args-instead-of-tuple.rs:25:4
@@ -77,7 +81,7 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/args-instead-of-tuple.rs:22:5
    |
 LL |     with_generic(3, 4);
-   |     ^^^^^^^^^^^^ -  - supplied 2 arguments
+   |     ^^^^^^^^^^^^
    |
 note: function defined here
   --> $DIR/args-instead-of-tuple.rs:28:4
@@ -93,7 +97,7 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/args-instead-of-tuple.rs:31:9
    |
 LL |         with_generic(a, b);
-   |         ^^^^^^^^^^^^ -  - supplied 2 arguments
+   |         ^^^^^^^^^^^^
    |
 note: function defined here
   --> $DIR/args-instead-of-tuple.rs:28:4
index 8d93ac50796671182b44d57b07901d7448d80643..1efd1b317b7da25de6b895f0b7ee4a981734bc87 100644 (file)
@@ -2,33 +2,61 @@ error[E0308]: mismatched types
   --> $DIR/as-ref.rs:7:29
    |
 LL |     opt.map(|arg| takes_ref(arg));
-   |         ---                 ^^^ expected `&Foo`, found struct `Foo`
-   |         |
+   |         ---       --------- ^^^ expected `&Foo`, found struct `Foo`
+   |         |         |
+   |         |         arguments to this function are incorrect
    |         help: consider using `as_ref` instead: `as_ref().map`
+   |
+note: function defined here
+  --> $DIR/as-ref.rs:3:4
+   |
+LL | fn takes_ref(_: &Foo) {}
+   |    ^^^^^^^^^ -------
 
 error[E0308]: mismatched types
   --> $DIR/as-ref.rs:8:39
    |
 LL |     opt.and_then(|arg| Some(takes_ref(arg)));
-   |         --------                      ^^^ expected `&Foo`, found struct `Foo`
-   |         |
+   |         --------            --------- ^^^ expected `&Foo`, found struct `Foo`
+   |         |                   |
+   |         |                   arguments to this function are incorrect
    |         help: consider using `as_ref` instead: `as_ref().and_then`
+   |
+note: function defined here
+  --> $DIR/as-ref.rs:3:4
+   |
+LL | fn takes_ref(_: &Foo) {}
+   |    ^^^^^^^^^ -------
 
 error[E0308]: mismatched types
   --> $DIR/as-ref.rs:10:29
    |
 LL |     opt.map(|arg| takes_ref(arg));
-   |         ---                 ^^^ expected `&Foo`, found struct `Foo`
-   |         |
+   |         ---       --------- ^^^ expected `&Foo`, found struct `Foo`
+   |         |         |
+   |         |         arguments to this function are incorrect
    |         help: consider using `as_ref` instead: `as_ref().map`
+   |
+note: function defined here
+  --> $DIR/as-ref.rs:3:4
+   |
+LL | fn takes_ref(_: &Foo) {}
+   |    ^^^^^^^^^ -------
 
 error[E0308]: mismatched types
   --> $DIR/as-ref.rs:11:37
    |
 LL |     opt.and_then(|arg| Ok(takes_ref(arg)));
-   |         --------                    ^^^ expected `&Foo`, found struct `Foo`
-   |         |
+   |         --------          --------- ^^^ expected `&Foo`, found struct `Foo`
+   |         |                 |
+   |         |                 arguments to this function are incorrect
    |         help: consider using `as_ref` instead: `as_ref().and_then`
+   |
+note: function defined here
+  --> $DIR/as-ref.rs:3:4
+   |
+LL | fn takes_ref(_: &Foo) {}
+   |    ^^^^^^^^^ -------
 
 error[E0308]: mismatched types
   --> $DIR/as-ref.rs:13:29
index 9a31dc89197e36209a295f4c8e319761ee1448c9..6dfb73480a2b88b7e30fbd9280cb6cbf760acea1 100644 (file)
@@ -2,10 +2,17 @@ error[E0308]: mismatched types
   --> $DIR/boxed-variant-field.rs:9:31
    |
 LL |         Ty::List(elem) => foo(elem),
-   |                               ^^^^ expected enum `Ty`, found struct `Box`
+   |                           --- ^^^^ expected enum `Ty`, found struct `Box`
+   |                           |
+   |                           arguments to this function are incorrect
    |
    = note: expected enum `Ty`
             found struct `Box<Ty>`
+note: function defined here
+  --> $DIR/boxed-variant-field.rs:6:4
+   |
+LL | fn foo(x: Ty) -> Ty {
+   |    ^^^ -----
 help: consider unboxing the value
    |
 LL |         Ty::List(elem) => foo(*elem),
index 7ef4895249cec7218f08a5836b9dd9edc0d817c2..71facf57e8d659122dda5452473f0e0231d90021 100644 (file)
@@ -34,10 +34,16 @@ LL | fn baz<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static,
 LL |     Pin::new(x)
    |     -------- ^ expected struct `Box`, found type parameter `F`
    |     |
+   |     arguments to this function are incorrect
    |     help: use `Box::pin` to pin and box this expression: `Box::pin`
    |
    = note:      expected struct `Box<dyn Future<Output = i32> + Send>`
            found type parameter `F`
+note: associated function defined here
+  --> $SRC_DIR/core/src/pin.rs:LL:COL
+   |
+LL |     pub const fn new(pointer: P) -> Pin<P> {
+   |                  ^^^
 
 error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned
   --> $DIR/expected-boxed-future-isnt-pinned.rs:19:5
index 7c0f8d199a965b111a9c9be6479f379988499391..a761ec5916745d5a5df8bcdd450159165eed0abb 100644 (file)
@@ -5,14 +5,14 @@ LL | struct S1<F: Fn(&i32, &i32) -> &'a i32>(F);
    |                                 ^^ undeclared lifetime
    |
    = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
-help: consider introducing lifetime `'a` here
-   |
-LL | struct S1<'a, F: Fn(&i32, &i32) -> &'a i32>(F);
-   |           +++
 help: consider making the bound lifetime-generic with a new `'a` lifetime
    |
 LL | struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
    |              +++++++
+help: consider introducing lifetime `'a` here
+   |
+LL | struct S1<'a, F: Fn(&i32, &i32) -> &'a i32>(F);
+   |           +++
 
 error[E0106]: missing lifetime specifier
   --> $DIR/fn-missing-lifetime-in-item.rs:2:32
diff --git a/src/test/ui/suggestions/issue-53692.rs b/src/test/ui/suggestions/issue-53692.rs
new file mode 100644 (file)
index 0000000..30f344e
--- /dev/null
@@ -0,0 +1,17 @@
+fn main() {
+        let items = vec![1, 2, 3];
+        let ref_items: &[i32] = &items;
+        let items_clone: Vec<i32> = ref_items.clone();
+//~^ ERROR mismatched types
+
+        // in that case no suggestion will be triggered
+        let items_clone_2:Vec<i32> = items.clone();
+
+        let s = "hi";
+        let string: String = s.clone();
+//~^ ERROR mismatched types
+
+        // in that case no suggestion will be triggered
+        let s2 = "hi";
+        let string_2: String = s2.to_string();
+}
diff --git a/src/test/ui/suggestions/issue-53692.stderr b/src/test/ui/suggestions/issue-53692.stderr
new file mode 100644 (file)
index 0000000..09c78da
--- /dev/null
@@ -0,0 +1,26 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-53692.rs:4:37
+   |
+LL |         let items_clone: Vec<i32> = ref_items.clone();
+   |                          --------   ^^^^^^^^^^^^^^^^^
+   |                          |          |
+   |                          |          expected struct `Vec`, found `&[i32]`
+   |                          |          help: try using a conversion method: `ref_items.to_vec()`
+   |                          expected due to this
+   |
+   = note: expected struct `Vec<i32>`
+           found reference `&[i32]`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-53692.rs:11:30
+   |
+LL |         let string: String = s.clone();
+   |                     ------   ^^^^^^^^^
+   |                     |        |
+   |                     |        expected struct `String`, found `&str`
+   |                     |        help: try using a conversion method: `s.to_string()`
+   |                     expected due to this
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index 0016f19284250eae33697601612bed322883c80c..8c9a41a202767813306bf508a328f785ad74e45c 100644 (file)
@@ -17,10 +17,17 @@ error[E0308]: mismatched types
   --> $DIR/issue-86100-tuple-paren-comma.rs:13:9
    |
 LL |     foo((Some(3)));
-   |         ^^^^^^^^^ expected tuple, found enum `Option`
+   |     --- ^^^^^^^^^ expected tuple, found enum `Option`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected tuple `(_,)`
                found enum `Option<{integer}>`
+note: function defined here
+  --> $DIR/issue-86100-tuple-paren-comma.rs:5:4
+   |
+LL | fn foo<T>(_t: (T,)) {}
+   |    ^^^    --------
 help: use a trailing comma to create a tuple with one element
    |
 LL |     foo((Some(3),));
index c15b772b79ca4364f9087215341de116a6a0d64a..611f7d5ddda78574c68501208dccfc49580af855 100644 (file)
@@ -2,11 +2,18 @@ error[E0308]: mismatched types
   --> $DIR/issue-90213-expected-boxfuture-self-ice.rs:9:19
    |
 LL |         Self::foo(None)
-   |                   ^^^^ expected struct `Box`, found enum `Option`
+   |         --------- ^^^^ expected struct `Box`, found enum `Option`
+   |         |
+   |         arguments to this function are incorrect
    |
    = note: expected struct `Box<Option<S>>`
                 found enum `Option<_>`
    = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+note: associated function defined here
+  --> $DIR/issue-90213-expected-boxfuture-self-ice.rs:7:8
+   |
+LL |     fn foo(_: Box<Option<S>>) {}
+   |        ^^^ -----------------
 help: store this in the heap by calling `Box::new`
    |
 LL |         Self::foo(Box::new(None))
index 536494c73445ceeaf3a6113d0bbda805afd51626..d38d66c08853c44c3c5e40ac4971016ce5b92ebd 100644 (file)
@@ -1,6 +1,8 @@
 error[E0311]: the parameter type `T` may not live long enough
   --> $DIR/missing-lifetimes-in-signature-2.rs:20:5
    |
+LL |   fn func<T: Test>(foo: &Foo, t: T) {
+   |           -- help: consider adding an explicit lifetime bound...: `T: 'a +`
 LL | /     foo.bar(move |_| {
 LL | |
 LL | |         t.test();
@@ -12,6 +14,14 @@ note: the parameter type `T` must be valid for the anonymous lifetime defined he
    |
 LL | fn func<T: Test>(foo: &Foo, t: T) {
    |                        ^^^
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/missing-lifetimes-in-signature-2.rs:20:5
+   |
+LL | /     foo.bar(move |_| {
+LL | |
+LL | |         t.test();
+LL | |     });
+   | |______^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr
new file mode 100644 (file)
index 0000000..4a18e0a
--- /dev/null
@@ -0,0 +1,147 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/missing-lifetimes-in-signature.rs:38:11
+   |
+LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |        -  ^^ undeclared lifetime
+   |        |
+   |        help: consider introducing lifetime `'a` here: `'a,`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/missing-lifetimes-in-signature.rs:19:5
+   |
+LL |   fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
+   |                            ------ hidden type `[closure@$DIR/missing-lifetimes-in-signature.rs:19:5: 22:6]` captures the anonymous lifetime defined here
+...
+LL | /     move || {
+LL | |
+LL | |         *dest = g.get();
+LL | |     }
+   | |_____^
+   |
+help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
+   |
+LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |                                                   ++++
+
+error[E0311]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:32:5
+   |
+LL |   fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |          - help: consider adding an explicit lifetime bound...: `G: 'a`
+...
+LL | /     move || {
+LL | |         *dest = g.get();
+LL | |     }
+   | |_____^
+   |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+  --> $DIR/missing-lifetimes-in-signature.rs:26:26
+   |
+LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |                          ^^^^^^
+note: ...so that the type `G` will meet its required lifetime bounds
+  --> $DIR/missing-lifetimes-in-signature.rs:32:5
+   |
+LL | /     move || {
+LL | |         *dest = g.get();
+LL | |     }
+   | |_____^
+
+error[E0311]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:55:5
+   |
+LL |   fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |              -- help: consider adding an explicit lifetime bound...: `G: 'b +`
+...
+LL | /     move || {
+LL | |         *dest = g.get();
+LL | |     }
+   | |_____^
+   |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+  --> $DIR/missing-lifetimes-in-signature.rs:49:34
+   |
+LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |                                  ^^^^^^
+note: ...so that the type `G` will meet its required lifetime bounds
+  --> $DIR/missing-lifetimes-in-signature.rs:55:5
+   |
+LL | /     move || {
+LL | |         *dest = g.get();
+LL | |     }
+   | |_____^
+
+error[E0311]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:65:9
+   |
+LL |       fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+   |                  -- help: consider adding an explicit lifetime bound...: `G: 'c +`
+...
+LL | /         move || {
+LL | |             *dest = g.get();
+LL | |         }
+   | |_________^
+   |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+  --> $DIR/missing-lifetimes-in-signature.rs:62:47
+   |
+LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+   |                                               ^^^^^^
+note: ...so that the type `G` will meet its required lifetime bounds
+  --> $DIR/missing-lifetimes-in-signature.rs:65:9
+   |
+LL | /         move || {
+LL | |             *dest = g.get();
+LL | |         }
+   | |_________^
+
+error[E0311]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:77:5
+   |
+LL |   fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+   |              -- help: consider adding an explicit lifetime bound...: `G: 'b +`
+...
+LL | /     move || {
+LL | |         *dest = g.get();
+LL | |     }
+   | |_____^
+   |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+  --> $DIR/missing-lifetimes-in-signature.rs:72:34
+   |
+LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+   |                                  ^^^^^^
+note: ...so that the type `G` will meet its required lifetime bounds
+  --> $DIR/missing-lifetimes-in-signature.rs:77:5
+   |
+LL | /     move || {
+LL | |         *dest = g.get();
+LL | |     }
+   | |_____^
+
+error[E0621]: explicit lifetime required in the type of `dest`
+  --> $DIR/missing-lifetimes-in-signature.rs:77:5
+   |
+LL |   fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+   |                                    ------ help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T`
+...
+LL | /     move || {
+LL | |         *dest = g.get();
+LL | |     }
+   | |_____^ lifetime `'a` required
+
+error[E0309]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:89:5
+   |
+LL |   fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
+   |              - help: consider adding an explicit lifetime bound...: `G: 'a`
+...
+LL | /     move || {
+LL | |         *dest = g.get();
+LL | |     }
+   | |_____^ ...so that the type `G` will meet its required lifetime bounds
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0261, E0309, E0621, E0700.
+For more information about an error, try `rustc --explain E0261`.
index dd434ea5318781753c9ec94bbf55a6ada781a323..647b343fe06947c43727e39ec7b84c87a1ad5e73 100644 (file)
@@ -14,28 +14,31 @@ fn get(self) -> usize {
 
 fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
 where
-    G: Get<T>
+    G: Get<T>,
 {
     move || {
+        //~^ ERROR hidden type for `impl Trait` captures lifetime
         *dest = g.get();
     }
 }
 
 // After applying suggestion for `foo`:
 fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+//~^ ERROR the parameter type `G` may not live long enough
 where
-    G: Get<T>
+    G: Get<T>,
 {
+    //~^ ERROR the parameter type `G` may not live long enough
     move || {
         *dest = g.get();
     }
 }
 
-
 // After applying suggestion for `bar`:
-fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ //~ ERROR undeclared lifetime
+fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+//~^ ERROR undeclared lifetime name `'a`
 where
-    G: Get<T>
+    G: Get<T>,
 {
     move || {
         *dest = g.get();
@@ -44,9 +47,11 @@ fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ //~ ERROR undeclared
 
 // After applying suggestion for `baz`:
 fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+//~^ ERROR the parameter type `G` may not live long enough
 where
-    G: Get<T>
+    G: Get<T>,
 {
+    //~^ ERROR the parameter type `G` may not live long enough
     move || {
         *dest = g.get();
     }
@@ -55,6 +60,8 @@ fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
 // Same as above, but show that we pay attention to lifetime names from parent item
 impl<'a> Foo {
     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+        //~^ ERROR the parameter type `G` may not live long enough
+        //~| ERROR the parameter type `G` may not live long enough
         move || {
             *dest = g.get();
         }
@@ -63,8 +70,9 @@ fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
 
 // After applying suggestion for `qux`:
 fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+//~^ ERROR explicit lifetime required in the type of `dest`
 where
-    G: Get<T>
+    G: Get<T>,
 {
     move || {
         *dest = g.get();
@@ -73,19 +81,20 @@ fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
 
 // Potential incorrect attempt:
 fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
+//~^ ERROR the parameter type `G` may not live long enough
 where
-    G: Get<T>
+    G: Get<T>,
 {
+    //~^ ERROR the parameter type `G` may not live long enough
     move || {
         *dest = g.get();
     }
 }
 
-
 // We need to tie the lifetime of `G` with the lifetime of `&mut T` and the returned closure:
 fn ok<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
 where
-    G: Get<T>
+    G: Get<T>,
 {
     move || {
         *dest = g.get();
@@ -95,7 +104,7 @@ fn ok<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
 // This also works. The `'_` isn't necessary but it's where we arrive to following the suggestions:
 fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a
 where
-    G: Get<T>
+    G: Get<T>,
 {
     move || {
         *dest = g.get();
index 916a6c2bf12af6277f3affdfbb205a216295f3dc..6d538dfd609a80b47df0c180df5646e31308b387 100644 (file)
 error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/missing-lifetimes-in-signature.rs:36:11
+  --> $DIR/missing-lifetimes-in-signature.rs:38:11
    |
 LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
    |        -  ^^ undeclared lifetime
    |        |
    |        help: consider introducing lifetime `'a` here: `'a,`
 
-error: aborting due to previous error
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/missing-lifetimes-in-signature.rs:19:5
+   |
+LL |   fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
+   |                            ------ hidden type `[closure@$DIR/missing-lifetimes-in-signature.rs:19:5: 22:6]` captures the anonymous lifetime defined here
+...
+LL | /     move || {
+LL | |
+LL | |         *dest = g.get();
+LL | |     }
+   | |_____^
+   |
+help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
+   |
+LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |                                                   ++++
+
+error[E0311]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:26:37
+   |
+LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |                                     ^^^^^^^^^^^^^^^^^^
+   |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+  --> $DIR/missing-lifetimes-in-signature.rs:26:26
+   |
+LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |                          ^^^^^^
+note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:32:5: 34:6]` will meet its required lifetime bounds
+  --> $DIR/missing-lifetimes-in-signature.rs:26:37
+   |
+LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |                                     ^^^^^^^^^^^^^^^^^^
+help: consider introducing an explicit lifetime bound
+   |
+LL | fn bar<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+   |        ~~~~~                                                   ++++
+
+error[E0311]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:30:1
+   |
+LL | / {
+LL | |
+LL | |     move || {
+LL | |         *dest = g.get();
+LL | |     }
+LL | | }
+   | |_^
+   |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+  --> $DIR/missing-lifetimes-in-signature.rs:26:26
+   |
+LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |                          ^^^^^^
+note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:32:5: 34:6]` will meet its required lifetime bounds
+  --> $DIR/missing-lifetimes-in-signature.rs:30:1
+   |
+LL | / {
+LL | |
+LL | |     move || {
+LL | |         *dest = g.get();
+LL | |     }
+LL | | }
+   | |_^
+help: consider introducing an explicit lifetime bound
+   |
+LL ~ fn bar<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+LL |
+LL | where
+LL |     G: Get<T>,
+LL | {
+LL |
+ ...
+
+error[E0311]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:49:45
+   |
+LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |                                             ^^^^^^^^^^^^^^^^^^
+   |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+  --> $DIR/missing-lifetimes-in-signature.rs:49:34
+   |
+LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |                                  ^^^^^^
+note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:55:5: 57:6]` will meet its required lifetime bounds
+  --> $DIR/missing-lifetimes-in-signature.rs:49:45
+   |
+LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |                                             ^^^^^^^^^^^^^^^^^^
+help: consider introducing an explicit lifetime bound
+   |
+LL | fn qux<'b, 'a, G: 'b + 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'b
+   |        +++     ~~~~~~~                                                  ++++
+
+error[E0311]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:53:1
+   |
+LL | / {
+LL | |
+LL | |     move || {
+LL | |         *dest = g.get();
+LL | |     }
+LL | | }
+   | |_^
+   |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+  --> $DIR/missing-lifetimes-in-signature.rs:49:34
+   |
+LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |                                  ^^^^^^
+note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:55:5: 57:6]` will meet its required lifetime bounds
+  --> $DIR/missing-lifetimes-in-signature.rs:53:1
+   |
+LL | / {
+LL | |
+LL | |     move || {
+LL | |         *dest = g.get();
+LL | |     }
+LL | | }
+   | |_^
+help: consider introducing an explicit lifetime bound
+   |
+LL ~ fn qux<'b, 'a, G: 'b + 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+LL |
+LL | where
+LL |     G: Get<T>,
+LL | {
+LL |
+ ...
+
+error[E0311]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:62:58
+   |
+LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+   |                                                          ^^^^^^^^^^^^^^^^^^
+   |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+  --> $DIR/missing-lifetimes-in-signature.rs:62:47
+   |
+LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+   |                                               ^^^^^^
+note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:65:9: 67:10]` will meet its required lifetime bounds
+  --> $DIR/missing-lifetimes-in-signature.rs:62:58
+   |
+LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+   |                                                          ^^^^^^^^^^^^^^^^^^
+help: consider introducing an explicit lifetime bound
+   |
+LL |     fn qux<'c, 'b, G: 'c + Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'c {
+   |            +++     ~~~~~~~                                                           ++++
+
+error[E0311]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:62:77
+   |
+LL |       fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+   |  _____________________________________________________________________________^
+LL | |
+LL | |
+LL | |         move || {
+LL | |             *dest = g.get();
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+  --> $DIR/missing-lifetimes-in-signature.rs:62:47
+   |
+LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+   |                                               ^^^^^^
+note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:65:9: 67:10]` will meet its required lifetime bounds
+  --> $DIR/missing-lifetimes-in-signature.rs:62:77
+   |
+LL |       fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+   |  _____________________________________________________________________________^
+LL | |
+LL | |
+LL | |         move || {
+LL | |             *dest = g.get();
+LL | |         }
+LL | |     }
+   | |_____^
+help: consider introducing an explicit lifetime bound
+   |
+LL ~     fn qux<'c, 'b, G: 'c + Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+LL |
+LL |
+LL |         move || {
+LL |             *dest = g.get();
+LL |         }
+ ...
+
+error[E0621]: explicit lifetime required in the type of `dest`
+  --> $DIR/missing-lifetimes-in-signature.rs:72:45
+   |
+LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+   |                                  ------     ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required
+   |                                  |
+   |                                  help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T`
+
+error[E0309]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:83:44
+   |
+LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
+   |            -                               ^^^^^^^^^^^^^^^^^^ ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:89:5: 91:6]` will meet its required lifetime bounds
+   |            |
+   |            help: consider adding an explicit lifetime bound...: `G: 'a`
+
+error[E0309]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:87:1
+   |
+LL |   fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
+   |              - help: consider adding an explicit lifetime bound...: `G: 'a`
+...
+LL | / {
+LL | |
+LL | |     move || {
+LL | |         *dest = g.get();
+LL | |     }
+LL | | }
+   | |_^ ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:89:5: 91:6]` will meet its required lifetime bounds
+
+error: aborting due to 11 previous errors
 
-For more information about this error, try `rustc --explain E0261`.
+Some errors have detailed explanations: E0261, E0309, E0621, E0700.
+For more information about an error, try `rustc --explain E0261`.
diff --git a/src/test/ui/suggestions/pattern-struct-with-slice-vec-field.rs b/src/test/ui/suggestions/pattern-struct-with-slice-vec-field.rs
new file mode 100644 (file)
index 0000000..5b223a9
--- /dev/null
@@ -0,0 +1,35 @@
+use std::ops::Deref;
+
+struct Foo {
+    v: Vec<u32>,
+}
+
+struct Bar {
+    v: Vec<u32>,
+}
+
+impl Deref for Bar {
+    type Target = Vec<u32>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.v
+    }
+}
+
+fn f(foo: &Foo) {
+    match foo {
+        Foo { v: [1, 2] } => {}
+        //~^ ERROR expected an array or slice, found `Vec<u32>
+        _ => {}
+    }
+}
+
+fn bar(bar: &Bar) {
+    match bar {
+        Bar { v: [1, 2] } => {}
+        //~^ ERROR expected an array or slice, found `Vec<u32>
+        _ => {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/pattern-struct-with-slice-vec-field.stderr b/src/test/ui/suggestions/pattern-struct-with-slice-vec-field.stderr
new file mode 100644 (file)
index 0000000..5b48a8b
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0529]: expected an array or slice, found `Vec<u32>`
+  --> $DIR/pattern-struct-with-slice-vec-field.rs:21:18
+   |
+LL |         Foo { v: [1, 2] } => {}
+   |                  ^^^^^^ pattern cannot match with input type `Vec<u32>`
+
+error[E0529]: expected an array or slice, found `Vec<u32>`
+  --> $DIR/pattern-struct-with-slice-vec-field.rs:29:18
+   |
+LL |         Bar { v: [1, 2] } => {}
+   |                  ^^^^^^ pattern cannot match with input type `Vec<u32>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0529`.
index aa621111c00c5cd29ee330bba64f8f576cd3b4a3..9588eedc98b4ae35b9f2020b5c0ff2b2b50d09ae 100644 (file)
@@ -38,7 +38,15 @@ error[E0308]: mismatched types
   --> $DIR/recover-from-semicolon-trailing-item.rs:14:9
    |
 LL |     foo("");
-   |         ^^ expected `usize`, found `&str`
+   |     --- ^^ expected `usize`, found `&str`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/recover-from-semicolon-trailing-item.rs:6:4
+   |
+LL | fn foo(a: usize) {};
+   |    ^^^ --------
 
 error: aborting due to 6 previous errors
 
index f4eb9813c1ac77f3fe19621fecfe149db2659b95..72354eaaee14722238109e763ec54448bcef449f 100644 (file)
@@ -1,10 +1,11 @@
 error[E0310]: the parameter type `impl Debug` may not live long enough
   --> $DIR/suggest-impl-trait-lifetime.rs:7:5
    |
+LL | fn foo(d: impl Debug) {
+   |           ---------- help: consider adding an explicit lifetime bound...: `impl Debug + 'static`
+LL |
 LL |     bar(d);
-   |     ^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `impl Debug: 'static`...
+   |     ^^^^^^ ...so that the type `impl Debug` will meet its required lifetime bounds
 
 error: aborting due to previous error
 
index 5c05810e5868d83c35793fa8d8330846eb29ae94..b0ac770c06f0fcc295a3687835cbfee208adcf8d 100644 (file)
@@ -2,31 +2,60 @@ error[E0308]: mismatched types
   --> $DIR/suggest-ref-macro.rs:15:11
    |
 LL |         x(123);
-   |           ^^^
-   |           |
-   |           expected `&mut i32`, found integer
-   |           help: consider mutably borrowing here: `&mut 123`
+   |         - ^^^
+   |         | |
+   |         | expected `&mut i32`, found integer
+   |         | help: consider mutably borrowing here: `&mut 123`
+   |         arguments to this function are incorrect
 ...
 LL |     bla!();
    |     ------ in this macro invocation
    |
+note: function defined here
+  --> $DIR/suggest-ref-macro.rs:11:4
+   |
+LL | fn x(_: &mut i32) {}
+   |    ^ -----------
    = note: this error originates in the macro `bla` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0308]: mismatched types
   --> $DIR/suggest-ref-macro.rs:26:10
    |
+LL |         x($v)
+   |         - arguments to this function are incorrect
+...
 LL |     bla!(456);
    |          ^^^
    |          |
    |          expected `&mut i32`, found integer
    |          help: consider mutably borrowing here: `&mut 456`
+   |
+note: function defined here
+  --> $DIR/suggest-ref-macro.rs:11:4
+   |
+LL | fn x(_: &mut i32) {}
+   |    ^ -----------
 
 error[E0308]: mismatched types
   --> $DIR/suggest-ref-macro.rs:8:1
    |
 LL | #[hello]
-   | ^^^^^^^^ expected `&mut i32`, found integer
+   | ^^^^^^^^
+   | |
+   | expected `&mut i32`, found integer
+   | arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/suggest-ref-macro.rs:8:1
    |
+LL |   #[hello]
+   |  _-^^^^^^^
+LL | | fn abc() {}
+LL | |
+LL | | fn x(_: &mut i32) {}
+LL | |
+LL | | macro_rules! bla {
+   | |_____________-
    = note: this error originates in the attribute macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 3 previous errors
index 19fc772544d59883cc9f1c65ea996dc496e53796..ac839ff7eb966c3869ebb6b192b0309ac2a95e0e 100644 (file)
@@ -2,10 +2,17 @@ error[E0308]: mismatched types
   --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:13:13
    |
 LL |         qux(x.func())
-   |             ^^^^^^^^ expected `usize`, found associated type
+   |         --- ^^^^^^^^ expected `usize`, found associated type
+   |         |
+   |         arguments to this function are incorrect
    |
    = note:         expected type `usize`
            found associated type `<impl Trait as Trait>::A`
+note: function defined here
+  --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4
+   |
+LL | fn qux(_: usize) {}
+   |    ^^^ --------
 help: consider constraining the associated type `<impl Trait as Trait>::A` to `usize`
    |
 LL |     fn foo<'a, T: Trait + 'a>(&self, _: impl Trait, x: impl Trait<A = usize>, _: T) {
@@ -15,10 +22,17 @@ error[E0308]: mismatched types
   --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:17:13
    |
 LL |         qux(x.func())
-   |             ^^^^^^^^ expected `usize`, found associated type
+   |         --- ^^^^^^^^ expected `usize`, found associated type
+   |         |
+   |         arguments to this function are incorrect
    |
    = note:         expected type `usize`
            found associated type `<T as Trait>::A`
+note: function defined here
+  --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4
+   |
+LL | fn qux(_: usize) {}
+   |    ^^^ --------
 help: consider constraining the associated type `<T as Trait>::A` to `usize`
    |
 LL |     fn ban<T>(x: T) where T: Trait<A = usize> {
@@ -28,10 +42,17 @@ error[E0308]: mismatched types
   --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:22:9
    |
 LL |     qux(x.func())
-   |         ^^^^^^^^ expected `usize`, found associated type
+   |     --- ^^^^^^^^ expected `usize`, found associated type
+   |     |
+   |     arguments to this function are incorrect
    |
    = note:         expected type `usize`
            found associated type `<impl Trait as Trait>::A`
+note: function defined here
+  --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4
+   |
+LL | fn qux(_: usize) {}
+   |    ^^^ --------
 help: consider constraining the associated type `<impl Trait as Trait>::A` to `usize`
    |
 LL | fn foo<'a, T: Trait + 'a>(_: impl Trait, x: impl Trait<A = usize>, _: T) {
@@ -41,10 +62,17 @@ error[E0308]: mismatched types
   --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:26:9
    |
 LL |     qux(x.func())
-   |         ^^^^^^^^ expected `usize`, found associated type
+   |     --- ^^^^^^^^ expected `usize`, found associated type
+   |     |
+   |     arguments to this function are incorrect
    |
    = note:         expected type `usize`
            found associated type `<T as Trait>::A`
+note: function defined here
+  --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4
+   |
+LL | fn qux(_: usize) {}
+   |    ^^^ --------
 help: consider constraining the associated type `<T as Trait>::A` to `usize`
    |
 LL | fn bar<T: Trait<A = usize>>(x: T) {
@@ -54,10 +82,17 @@ error[E0308]: mismatched types
   --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:30:9
    |
 LL |     qux(x.func())
-   |         ^^^^^^^^ expected `usize`, found associated type
+   |     --- ^^^^^^^^ expected `usize`, found associated type
+   |     |
+   |     arguments to this function are incorrect
    |
    = note:         expected type `usize`
            found associated type `<impl Trait<i32> as Trait<i32>>::A`
+note: function defined here
+  --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4
+   |
+LL | fn qux(_: usize) {}
+   |    ^^^ --------
 help: consider constraining the associated type `<impl Trait<i32> as Trait<i32>>::A` to `usize`
    |
 LL | fn foo2(x: impl Trait<i32, A = usize>) {
@@ -67,10 +102,17 @@ error[E0308]: mismatched types
   --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:34:9
    |
 LL |     qux(x.func())
-   |         ^^^^^^^^ expected `usize`, found associated type
+   |     --- ^^^^^^^^ expected `usize`, found associated type
+   |     |
+   |     arguments to this function are incorrect
    |
    = note:         expected type `usize`
            found associated type `<T as Trait<i32>>::A`
+note: function defined here
+  --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4
+   |
+LL | fn qux(_: usize) {}
+   |    ^^^ --------
 help: consider constraining the associated type `<T as Trait<i32>>::A` to `usize`
    |
 LL | fn bar2<T: Trait<i32, A = usize>>(x: T) {
@@ -80,10 +122,17 @@ error[E0308]: mismatched types
   --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:38:9
    |
 LL |     qux(x.func())
-   |         ^^^^^^^^ expected `usize`, found associated type
+   |     --- ^^^^^^^^ expected `usize`, found associated type
+   |     |
+   |     arguments to this function are incorrect
    |
    = note:         expected type `usize`
            found associated type `<T as Trait>::A`
+note: function defined here
+  --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4
+   |
+LL | fn qux(_: usize) {}
+   |    ^^^ --------
 help: consider constraining the associated type `<T as Trait>::A` to `usize`
    |
 LL | fn ban<T>(x: T) where T: Trait<A = usize> {
index 943cbcbc81a22f06f4d47b9d35cf5a9a847df7e8..7583c875a1a37a667d483998e6d7242d5d142a6e 100644 (file)
@@ -16,10 +16,17 @@ error[E0308]: mismatched types
   --> $DIR/trait-with-missing-associated-type-restriction.rs:14:9
    |
 LL |     qux(x.func())
-   |         ^^^^^^^^ expected `usize`, found associated type
+   |     --- ^^^^^^^^ expected `usize`, found associated type
+   |     |
+   |     arguments to this function are incorrect
    |
    = note:         expected type `usize`
            found associated type `<impl Trait as Trait>::A`
+note: function defined here
+  --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4
+   |
+LL | fn qux(_: usize) {}
+   |    ^^^ --------
 help: consider constraining the associated type `<impl Trait as Trait>::A` to `usize`
    |
 LL | fn foo(_: impl Trait, x: impl Trait<A = usize>) {
@@ -29,10 +36,17 @@ error[E0308]: mismatched types
   --> $DIR/trait-with-missing-associated-type-restriction.rs:18:9
    |
 LL |     qux(x.func())
-   |         ^^^^^^^^ expected `usize`, found associated type
+   |     --- ^^^^^^^^ expected `usize`, found associated type
+   |     |
+   |     arguments to this function are incorrect
    |
    = note:         expected type `usize`
            found associated type `<T as Trait>::A`
+note: function defined here
+  --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4
+   |
+LL | fn qux(_: usize) {}
+   |    ^^^ --------
 help: consider constraining the associated type `<T as Trait>::A` to `usize`
    |
 LL | fn bar<T: Trait<A = usize>>(x: T) {
@@ -42,10 +56,17 @@ error[E0308]: mismatched types
   --> $DIR/trait-with-missing-associated-type-restriction.rs:22:9
    |
 LL |     qux(x.func())
-   |         ^^^^^^^^ expected `usize`, found associated type
+   |     --- ^^^^^^^^ expected `usize`, found associated type
+   |     |
+   |     arguments to this function are incorrect
    |
    = note:         expected type `usize`
            found associated type `<impl Trait<i32> as Trait<i32>>::A`
+note: function defined here
+  --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4
+   |
+LL | fn qux(_: usize) {}
+   |    ^^^ --------
 help: consider constraining the associated type `<impl Trait<i32> as Trait<i32>>::A` to `usize`
    |
 LL | fn foo2(x: impl Trait<i32, A = usize>) {
@@ -55,7 +76,9 @@ error[E0308]: mismatched types
   --> $DIR/trait-with-missing-associated-type-restriction.rs:26:12
    |
 LL |     x.funk(3);
-   |            ^ expected associated type, found integer
+   |       ---- ^ expected associated type, found integer
+   |       |
+   |       arguments to this function are incorrect
    |
    = note: expected associated type `<T as Trait<i32>>::A`
                          found type `{integer}`
@@ -67,6 +90,11 @@ LL |     fn func(&self) -> Self::A;
 LL |     fn funk(&self, _: Self::A);
 LL |     fn funq(&self) -> Self::A {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ consider calling `Trait::funq`
+note: associated function defined here
+  --> $DIR/trait-with-missing-associated-type-restriction.rs:9:8
+   |
+LL |     fn funk(&self, _: Self::A);
+   |        ^^^^
 help: consider constraining the associated type `<T as Trait<i32>>::A` to `{integer}`
    |
 LL | fn bar2<T: Trait<i32, A = {integer}>>(x: T) {
@@ -76,10 +104,17 @@ error[E0308]: mismatched types
   --> $DIR/trait-with-missing-associated-type-restriction.rs:27:9
    |
 LL |     qux(x.func())
-   |         ^^^^^^^^ expected `usize`, found associated type
+   |     --- ^^^^^^^^ expected `usize`, found associated type
+   |     |
+   |     arguments to this function are incorrect
    |
    = note:         expected type `usize`
            found associated type `<T as Trait<i32>>::A`
+note: function defined here
+  --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4
+   |
+LL | fn qux(_: usize) {}
+   |    ^^^ --------
 help: consider constraining the associated type `<T as Trait<i32>>::A` to `usize`
    |
 LL | fn bar2<T: Trait<i32, A = usize>>(x: T) {
@@ -91,25 +126,47 @@ error[E0308]: mismatched types
 LL | fn baz<D: std::fmt::Debug, T: Trait<A = D>>(x: T) {
    |        - this type parameter
 LL |     qux(x.func())
-   |         ^^^^^^^^ expected `usize`, found type parameter `D`
+   |     --- ^^^^^^^^ expected `usize`, found type parameter `D`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note:        expected type `usize`
            found type parameter `D`
+note: function defined here
+  --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4
+   |
+LL | fn qux(_: usize) {}
+   |    ^^^ --------
 
 error[E0308]: mismatched types
   --> $DIR/trait-with-missing-associated-type-restriction.rs:35:9
    |
 LL |     qux(x.func())
-   |         ^^^^^^^^ expected `usize`, found `()`
+   |     --- ^^^^^^^^ expected `usize`, found `()`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4
+   |
+LL | fn qux(_: usize) {}
+   |    ^^^ --------
 
 error[E0308]: mismatched types
   --> $DIR/trait-with-missing-associated-type-restriction.rs:39:9
    |
 LL |     qux(x.func())
-   |         ^^^^^^^^ expected `usize`, found associated type
+   |     --- ^^^^^^^^ expected `usize`, found associated type
+   |     |
+   |     arguments to this function are incorrect
    |
    = note:         expected type `usize`
            found associated type `<T as Trait>::A`
+note: function defined here
+  --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4
+   |
+LL | fn qux(_: usize) {}
+   |    ^^^ --------
 help: consider constraining the associated type `<T as Trait>::A` to `usize`
    |
 LL | fn ban<T>(x: T) where T: Trait<A = usize> {
index 5a158e5876a069a23049d6872a15ee22ca3a47ba..5409e32c436fbd9ff1e26dc88901e133362c55f3 100644 (file)
@@ -2,15 +2,17 @@ error[E0107]: this trait takes 2 generic arguments but 4 generic arguments were
   --> $DIR/use-type-argument-instead-of-assoc-type.rs:7:16
    |
 LL |     i: Box<dyn T<usize, usize, usize, usize, B=usize>>,
-   |                ^               ------------ help: remove these generic arguments
-   |                |
-   |                expected 2 generic arguments
+   |                ^ expected 2 generic arguments
    |
 note: trait defined here, with 2 generic parameters: `X`, `Y`
   --> $DIR/use-type-argument-instead-of-assoc-type.rs:1:11
    |
 LL | pub trait T<X, Y> {
    |           ^ -  -
+help: replace the generic bounds with the associated types
+   |
+LL |     i: Box<dyn T<usize, usize, A = usize, C = usize, B=usize>>,
+   |                                ~~~~~~~~~  ~~~~~~~~~
 
 error[E0191]: the value of the associated types `A` (from trait `T`), `C` (from trait `T`) must be specified
   --> $DIR/use-type-argument-instead-of-assoc-type.rs:7:16
@@ -23,11 +25,6 @@ LL |     type C;
 ...
 LL |     i: Box<dyn T<usize, usize, usize, usize, B=usize>>,
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated types `A`, `C` must be specified
-   |
-help: specify the associated types
-   |
-LL |     i: Box<dyn T<usize, usize, A = usize, C = usize, B=usize>>,
-   |                                ~~~~~~~~~  ~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
index eabdc59ddedd548ccdcb96982a43266fe1cc6abf..3d2530e204b3336943d618c880414612be503df2 100644 (file)
@@ -5,5 +5,5 @@
 
 fn main() {
     let _: () = 42;
-    //~^ ERROR mismatched types
+    //~^ ERROR arguments to this function are incorrect
 }
index 5c6859a0efe98a353db191d68ea39f93010dd1b4..d2fda09c0767f5d6db0d8fa906983d7a99454875 100644 (file)
@@ -2,7 +2,15 @@ error[E0308]: mismatched types
   --> $DIR/terr-in-field.rs:13:14
    |
 LL |     want_foo(b);
-   |              ^ expected struct `Foo`, found struct `Bar`
+   |     -------- ^ expected struct `Foo`, found struct `Bar`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/terr-in-field.rs:11:4
+   |
+LL | fn want_foo(f: Foo) {}
+   |    ^^^^^^^^ ------
 
 error: aborting due to previous error
 
index 34d4d9eaded8ac167dc6bcbc7ec23c415dc37e68..5a61a2fab12658fe91122d636899345189423670 100644 (file)
@@ -2,10 +2,17 @@ error[E0308]: mismatched types
   --> $DIR/terr-sorts.rs:10:14
    |
 LL |     want_foo(b);
-   |              ^ expected struct `Foo`, found struct `Box`
+   |     -------- ^ expected struct `Foo`, found struct `Box`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo`
               found struct `Box<Foo>`
+note: function defined here
+  --> $DIR/terr-sorts.rs:8:4
+   |
+LL | fn want_foo(f: Foo) {}
+   |    ^^^^^^^^ ------
 help: consider unboxing the value
    |
 LL |     want_foo(*b);
diff --git a/src/test/ui/thread-local/non-static.rs b/src/test/ui/thread-local/non-static.rs
new file mode 100644 (file)
index 0000000..f1c4273
--- /dev/null
@@ -0,0 +1,30 @@
+// Check that #[thread_local] attribute is rejected on non-static items.
+#![feature(thread_local)]
+
+#[thread_local]
+//~^ ERROR attribute should be applied to a static
+const A: u32 = 0;
+
+#[thread_local]
+//~^ ERROR attribute should be applied to a static
+fn main() {
+    #[thread_local] || {};
+    //~^ ERROR attribute should be applied to a static
+}
+
+struct S {
+    #[thread_local]
+    //~^ ERROR attribute should be applied to a static
+    a: String,
+    b: String,
+}
+
+#[thread_local]
+// Static. OK.
+static B: u32 = 0;
+
+extern "C" {
+    #[thread_local]
+    // Foreign static. OK.
+    static C: u32;
+}
diff --git a/src/test/ui/thread-local/non-static.stderr b/src/test/ui/thread-local/non-static.stderr
new file mode 100644 (file)
index 0000000..09a1618
--- /dev/null
@@ -0,0 +1,38 @@
+error: attribute should be applied to a static
+  --> $DIR/non-static.rs:4:1
+   |
+LL | #[thread_local]
+   | ^^^^^^^^^^^^^^^
+LL |
+LL | const A: u32 = 0;
+   | ----------------- not a static
+
+error: attribute should be applied to a static
+  --> $DIR/non-static.rs:8:1
+   |
+LL |   #[thread_local]
+   |   ^^^^^^^^^^^^^^^
+LL |
+LL | / fn main() {
+LL | |     #[thread_local] || {};
+LL | |
+LL | | }
+   | |_- not a static
+
+error: attribute should be applied to a static
+  --> $DIR/non-static.rs:11:5
+   |
+LL |     #[thread_local] || {};
+   |     ^^^^^^^^^^^^^^^ ----- not a static
+
+error: attribute should be applied to a static
+  --> $DIR/non-static.rs:16:5
+   |
+LL |     #[thread_local]
+   |     ^^^^^^^^^^^^^^^
+LL |
+LL |     a: String,
+   |     --------- not a static
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/threads-sendsync/issue-29488.rs b/src/test/ui/threads-sendsync/issue-29488.rs
new file mode 100644 (file)
index 0000000..3c9a6a8
--- /dev/null
@@ -0,0 +1,23 @@
+// run-pass
+// ignore-emscripten no threads support
+
+use std::thread;
+
+struct Foo;
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        println!("test2");
+    }
+}
+
+thread_local!(static FOO: Foo = Foo);
+
+fn main() {
+    // Off the main thread due to #28129, be sure to initialize FOO first before
+    // calling `println!`
+    thread::spawn(|| {
+        FOO.with(|_| {});
+        println!("test1");
+    }).join().unwrap();
+}
index feb0c73a09d3d6335abf01036e14fc4dd108e81c..b67648c7b04da6b60d04f58add32f3e6cb26d767 100644 (file)
@@ -2,10 +2,17 @@ error[E0308]: mismatched types
   --> $DIR/sugar.rs:12:7
    |
 LL |     a(x);
-   |       ^ expected trait `Foo + Send`, found trait `Foo + Sync`
+   |     - ^ expected trait `Foo + Send`, found trait `Foo + Sync`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Box<(dyn Foo + Send + 'static)>`
               found struct `Box<(dyn Foo + Sync + 'static)>`
+note: function defined here
+  --> $DIR/sugar.rs:5:4
+   |
+LL | fn a(_x: Box<dyn Foo + Send>) {
+   |    ^ -----------------------
 
 error: aborting due to previous error
 
index 9452e11e302e318eca4fc884087be42ec4837f0d..859403f202f5167552c8272af20651d7aabca665 100644 (file)
@@ -4,7 +4,7 @@ error[E0275]: overflow evaluating the requirement `SalsaStorage: RefUnwindSafe`
 LL |     _parse: <ParseQuery as Query<RootDatabase>>::Data,
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: required because it appears within the type `*const SalsaStorage`
+   = note: required because it appears within the type `PhantomData<SalsaStorage>`
    = note: required because it appears within the type `Unique<SalsaStorage>`
    = note: required because it appears within the type `Box<SalsaStorage>`
 note: required because it appears within the type `Runtime<RootDatabase>`
diff --git a/src/test/ui/traits/issue-43132.rs b/src/test/ui/traits/issue-43132.rs
new file mode 100644 (file)
index 0000000..c886f4b
--- /dev/null
@@ -0,0 +1,65 @@
+// run-pass
+#![allow(unused)]
+
+fn main() {
+}
+
+fn foo() {
+    let b = mk::<
+        Forward<(Box<dyn Future<Error = u32>>,)>,
+    >();
+    b.map_err(|_| ()).join();
+}
+
+fn mk<T>() -> T {
+    loop {}
+}
+
+impl<I: Future<Error = E>, E> Future for (I,) {
+    type Error = E;
+}
+
+struct Forward<T: Future> {
+    _a: T,
+}
+
+impl<T: Future> Future for Forward<T>
+where
+    T::Error: From<u32>,
+{
+    type Error = T::Error;
+}
+
+trait Future {
+    type Error;
+
+    fn map_err<F, E>(self, _: F) -> (Self, F)
+    where
+        F: FnOnce(Self::Error) -> E,
+        Self: Sized,
+    {
+        loop {}
+    }
+
+    fn join(self) -> (MaybeDone<Self>, ())
+    where
+        Self: Sized,
+    {
+        loop {}
+    }
+}
+
+impl<S: ?Sized + Future> Future for Box<S> {
+    type Error = S::Error;
+}
+
+enum MaybeDone<A: Future> {
+    _Done(A::Error),
+}
+
+impl<U, A: Future, F> Future for (A, F)
+where
+    F: FnOnce(A::Error) -> U,
+{
+    type Error = U;
+}
index bf732e2491566f9f51386560f3fb1ffce2788525..f0c718c7a16db853d7538fe0577eb602c9de73c8 100644 (file)
@@ -5,10 +5,17 @@ LL | impl<F, Name, P> AddClass<Name, F> for Class<P>
    |      - this type parameter
 ...
 LL |         builder.push(output);
-   |                      ^^^^^^ expected type parameter `F`, found struct `Class`
+   |                 ---- ^^^^^^ expected type parameter `F`, found struct `Class`
+   |                 |
+   |                 arguments to this function are incorrect
    |
-   = note: expected type parameter `F`
-                      found struct `Class<P>`
+   = note: expected type `F`
+            found struct `Class<P>`
+note: associated function defined here
+  --> $DIR/issue-52893.rs:11:8
+   |
+LL |     fn push(self, other: T) -> Self::PushRes;
+   |        ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/issue-71036.rs b/src/test/ui/traits/issue-71036.rs
new file mode 100644 (file)
index 0000000..3d2df6f
--- /dev/null
@@ -0,0 +1,17 @@
+#![feature(unsize, dispatch_from_dyn)]
+
+use std::marker::Unsize;
+use std::ops::DispatchFromDyn;
+
+#[allow(unused)]
+struct Foo<'a, T: ?Sized> {
+    _inner: &'a &'a T,
+}
+
+impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> {}
+//~^ ERROR the trait bound `&'a T: Unsize<&'a U>` is not satisfied
+//~| NOTE the trait `Unsize<&'a U>` is not implemented for `&'a T`
+//~| NOTE all implementations of `Unsize` are provided automatically by the compiler
+//~| NOTE required because of the requirements on the impl
+
+fn main() {}
diff --git a/src/test/ui/traits/issue-71036.stderr b/src/test/ui/traits/issue-71036.stderr
new file mode 100644 (file)
index 0000000..db1f694
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `&'a T: Unsize<&'a U>` is not satisfied
+  --> $DIR/issue-71036.rs:11:1
+   |
+LL | impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unsize<&'a U>` is not implemented for `&'a T`
+   |
+   = note: all implementations of `Unsize` are provided automatically by the compiler, see <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> for more information
+   = note: required because of the requirements on the impl of `DispatchFromDyn<&'a &'a U>` for `&'a &'a T`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index 6caa23d8f4997ef4e97a81f31ab69b98d52cafef..8b6e610067be1f1d23dc44dbcb23ea2c1fc6d8f9 100644 (file)
@@ -2,8 +2,15 @@ error[E0308]: mismatched types
   --> $DIR/multidispatch-bad.rs:19:17
    |
 LL |     test(22i32, 44i32);
-   |                 ^^^^^ expected `u32`, found `i32`
+   |     ----        ^^^^^ expected `u32`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: function defined here
+  --> $DIR/multidispatch-bad.rs:13:4
+   |
+LL | fn test<T,U>(_: T, _: U)
+   |    ^^^^      ----  ----
 help: change the type of the numeric literal from `i32` to `u32`
    |
 LL |     test(22i32, 44u32);
index 10bcedaf4aa9ac06f1453825225d83769c2e4db9..fff7be987f2e8c57e669181aeeddb3e144902ffe 100644 (file)
@@ -2,19 +2,33 @@ error[E0308]: mismatched types
   --> $DIR/tuple-arity-mismatch.rs:6:20
    |
 LL |     let y = first ((1,2.0,3));
-   |                    ^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements
+   |             -----  ^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements
+   |             |
+   |             arguments to this function are incorrect
    |
    = note: expected tuple `(isize, f64)`
               found tuple `(isize, f64, {integer})`
+note: function defined here
+  --> $DIR/tuple-arity-mismatch.rs:3:4
+   |
+LL | fn first((value, _): (isize, f64)) -> isize { value }
+   |    ^^^^^ ------------------------
 
 error[E0308]: mismatched types
   --> $DIR/tuple-arity-mismatch.rs:12:20
    |
 LL |     let y = first ((1,));
-   |                    ^^^^ expected a tuple with 2 elements, found one with 1 element
+   |             -----  ^^^^ expected a tuple with 2 elements, found one with 1 element
+   |             |
+   |             arguments to this function are incorrect
    |
    = note: expected tuple `(isize, f64)`
               found tuple `(isize,)`
+note: function defined here
+  --> $DIR/tuple-arity-mismatch.rs:3:4
+   |
+LL | fn first((value, _): (isize, f64)) -> isize { value }
+   |    ^^^^^ ------------------------
 
 error: aborting due to 2 previous errors
 
index ddafc9763e79a6db7fcac23f37b9201b40def36a..c704ae9934b1c5602647f8faebf07ef1ae18e445 100644 (file)
@@ -2,7 +2,7 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/wrong_argument_ice-2.rs:13:5
    |
 LL |     test(x.qux(), x.qux());
-   |     ^^^^ -------  ------- supplied 2 arguments
+   |     ^^^^
    |
 note: function defined here
   --> $DIR/wrong_argument_ice-2.rs:1:4
index f0d64d2a4e18db63f927ed26293637e408c4534e..6ea6e670fd600998b5c6f7723bd269e60784de68 100644 (file)
@@ -2,15 +2,21 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/wrong_argument_ice-3.rs:9:16
    |
 LL |         groups.push(new_group, vec![process]);
-   |                ^^^^ ---------  ------------- supplied 2 arguments
-   |                |
-   |                expected 1 argument
+   |                ^^^^ ---------  ------------- argument unexpected
+   |                     |
+   |                     expected tuple, found struct `Vec`
    |
+   = note: expected tuple `(Vec<String>, Vec<Process>)`
+             found struct `Vec<String>`
 note: associated function defined here
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
    |
 LL |     pub fn push(&mut self, value: T) {
    |            ^^^^
+help: remove the extra argument
+   |
+LL |         groups.push({(Vec<String>, Vec<Process>)});
+   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
index fef5dca856db36592aad666b9a3cde8b603a3ffb..0c25b6801dc8efff0e11bf11f848cb420676cf45 100644 (file)
@@ -3,12 +3,15 @@ error[E0057]: this function takes 0 arguments but 1 argument was supplied
    |
 LL |       (|| {})(|| {
    |  _____^^^^^^^_-
-   | |     |
-   | |     expected 0 arguments
 LL | |
 LL | |         let b = 1;
 LL | |     });
-   | |_____- supplied 1 argument
+   | |_____- argument unexpected
+   |
+help: remove the extra argument
+   |
+LL |     (|| {})();
+   |     ~~~~~~~~~
 
 error: aborting due to previous error
 
index e96a957350b2fdb231116bf4ffe3895ca20e0a7c..2b4cb669f5c7d7f04f9484ddfa33c59950972962 100644 (file)
@@ -2,7 +2,7 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/wrong_argument_ice.rs:11:18
    |
 LL |         self.acc.push_back(self.current_provides, self.current_requires);
-   |                  ^^^^^^^^^ ---------------------  --------------------- supplied 2 arguments
+   |                  ^^^^^^^^^
    |
 note: associated function defined here
   --> $SRC_DIR/alloc/src/collections/vec_deque/mod.rs:LL:COL
index a384d5f561c940e9d1d1b01d87443aec5c2d4e65..115ecb013766dd2e9bcd5fd60cd668c9577dfea8 100644 (file)
@@ -5,10 +5,17 @@ LL | impl<T> Enum<T> {
    |      - this type parameter
 LL |     fn ts_variant() {
 LL |         Self::TSVariant(());
-   |                         ^^ expected type parameter `T`, found `()`
+   |         --------------- ^^ expected type parameter `T`, found `()`
+   |         |
+   |         arguments to this function are incorrect
    |
    = note: expected type parameter `T`
                    found unit type `()`
+note: tuple variant defined here
+  --> $DIR/enum-variant-generic-args.rs:7:16
+   |
+LL | enum Enum<T> { TSVariant(T), SVariant { v: T }, UVariant }
+   |                ^^^^^^^^^
 
 error[E0109]: type arguments are not allowed for this type
   --> $DIR/enum-variant-generic-args.rs:15:27
@@ -29,10 +36,17 @@ LL | impl<T> Enum<T> {
    |      - this type parameter
 ...
 LL |         Self::<()>::TSVariant(());
-   |                               ^^ expected type parameter `T`, found `()`
+   |         --------------------- ^^ expected type parameter `T`, found `()`
+   |         |
+   |         arguments to this function are incorrect
    |
    = note: expected type parameter `T`
                    found unit type `()`
+note: tuple variant defined here
+  --> $DIR/enum-variant-generic-args.rs:7:16
+   |
+LL | enum Enum<T> { TSVariant(T), SVariant { v: T }, UVariant }
+   |                ^^^^^^^^^
 
 error[E0109]: type arguments are not allowed for this type
   --> $DIR/enum-variant-generic-args.rs:20:16
index 37543c137f66f861d4dbf23e8d50afa15c09b35a..3fc5a3594d852bd45f20da3df669c8aae9ee28e5 100644 (file)
@@ -2,15 +2,17 @@ error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:21:5
    |
 LL |     <E>::V();
-   |     ^^^^^^-- supplied 0 arguments
-   |     |
-   |     expected 1 argument
+   |     ^^^^^^-- an argument of type `u8` is missing
    |
 note: tuple variant defined here
   --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:5:5
    |
 LL |     V(u8)
    |     ^
+help: provide the argument
+   |
+LL |     <E>::V({u8});
+   |     ~~~~~~~~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:22:17
index db771d211322c8f53776a358d3e67c210c140468..a3b410c2cfb8c4946c53b40be46e6e828b4bf979 100644 (file)
@@ -19,10 +19,10 @@ LL | type WrongGeneric<T> = impl 'static;
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/generic_type_does_not_live_long_enough.rs:18:5
    |
+LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
+   |                  - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     t
-   |     ^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
+   |     ^ ...so that the type `T` will meet its required lifetime bounds
 
 error: aborting due to 3 previous errors
 
index a46047d91743d899d83ca79db0bc1e75553de94d..5b3d7375de0e3ef1b21a700b7d8ea81b778a1134 100644 (file)
@@ -10,5 +10,5 @@ extern crate std;
 trait Animal { }
 
 fn main() {
-        pub type ServeFut = /*impl Trait*/;
+        type ServeFut = /*impl Trait*/;
     }
index 6732902c09a504d7aef29f1291d36a998cfe3a8e..b0de8bf6aa4f267d578e319fff1bf448dac14d9d 100644 (file)
@@ -18,5 +18,7 @@ impl<T> WithAssoc<T> for () {
 //~^ ERROR use of undeclared lifetime name `'a`
 
 fn my_fun() -> Return<()> {}
+//~^ ERROR non-defining opaque type use in defining scope
+//~| ERROR non-defining opaque type use in defining scope
 
 fn main() {}
index fe45e39d938f009e1b340cd155fbc6fb322cbe0b..d038fbbe1b40a191fc35a9da4cccccc9f95293f7 100644 (file)
@@ -2,10 +2,42 @@ error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:17:65
    |
 LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
-   |             -                                                   ^^ undeclared lifetime
-   |             |
-   |             help: consider introducing lifetime `'a` here: `'a,`
+   |                                                                 ^^ undeclared lifetime
+   |
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'a` lifetime
+   |
+LL | type Return<A> = impl for<'a> WithAssoc<A, AssocType = impl SomeTrait + 'a>;
+   |                       +++++++
+help: consider introducing lifetime `'a` here
+   |
+LL | type Return<'a, A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
+   |             +++
+
+error: non-defining opaque type use in defining scope
+  --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:20:27
+   |
+LL | fn my_fun() -> Return<()> {}
+   |                           ^^
+   |
+note: used non-generic type `()` for generic parameter
+  --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:17:13
+   |
+LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
+   |             ^
+
+error: non-defining opaque type use in defining scope
+  --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:20:27
+   |
+LL | fn my_fun() -> Return<()> {}
+   |                           ^^
+   |
+note: used non-generic type `()` for generic parameter
+  --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:17:13
+   |
+LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
+   |             ^
 
-error: aborting due to previous error
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0261`.
index e5666d4fe4f4b3eb3d18674f01ac8119627274cb..18ed4986f89312ba9aee248d56e623683ac3d051 100644 (file)
@@ -11,15 +11,17 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/type-ascription-instead-of-initializer.rs:2:12
    |
 LL |     let x: Vec::with_capacity(10, 20);
-   |            ^^^^^^^^^^^^^^^^^^ --  -- supplied 2 arguments
-   |            |
-   |            expected 1 argument
+   |            ^^^^^^^^^^^^^^^^^^     -- argument unexpected
    |
 note: associated function defined here
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
    |
 LL |     pub fn with_capacity(capacity: usize) -> Self {
    |            ^^^^^^^^^^^^^
+help: remove the extra argument
+   |
+LL |     let x: Vec::with_capacity(10);
+   |            ~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
index 49d40ebed130c517b602cf86ae3989cd37d79486..783f747fa6db68beb62f48e54bcdc1c3542b7a08 100644 (file)
@@ -2,19 +2,33 @@ error[E0308]: mismatched types
   --> $DIR/type-mismatch-same-crate-name.rs:16:20
    |
 LL |         a::try_foo(foo2);
-   |                    ^^^^ expected struct `main::a::Foo`, found a different struct `main::a::Foo`
+   |         ---------- ^^^^ expected struct `main::a::Foo`, found a different struct `main::a::Foo`
+   |         |
+   |         arguments to this function are incorrect
    |
    = note: perhaps two different versions of crate `crate_a1` are being used?
+note: function defined here
+  --> $DIR/auxiliary/crate_a1.rs:10:8
+   |
+LL | pub fn try_foo(x: Foo){}
+   |        ^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch-same-crate-name.rs:20:20
    |
 LL |         a::try_bar(bar2);
-   |                    ^^^^ expected trait `main::a::Bar`, found a different trait `main::a::Bar`
+   |         ---------- ^^^^ expected trait `main::a::Bar`, found a different trait `main::a::Bar`
+   |         |
+   |         arguments to this function are incorrect
    |
    = note: expected struct `Box<(dyn main::a::Bar + 'static)>`
               found struct `Box<dyn main::a::Bar>`
    = note: perhaps two different versions of crate `crate_a1` are being used?
+note: function defined here
+  --> $DIR/auxiliary/crate_a1.rs:11:8
+   |
+LL | pub fn try_bar(x: Box<Bar>){}
+   |        ^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 24c71c63103d3e79ec06a6cdf880129253e5fc80..6c187bad0725c7d525acf6db17b4acd32982c410 100644 (file)
@@ -2,418 +2,749 @@ error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:17:17
    |
 LL |     want::<foo>(f);
-   |                 ^ expected struct `foo`, found `usize`
+   |     ----------- ^ expected struct `foo`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:18:17
    |
 LL |     want::<bar>(f);
-   |                 ^ expected struct `bar`, found `usize`
+   |     ----------- ^ expected struct `bar`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:19:24
    |
 LL |     want::<Foo<usize>>(f);
-   |                        ^ expected struct `Foo`, found `usize`
+   |     ------------------ ^ expected struct `Foo`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<usize>`
                 found type `usize`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:20:27
    |
 LL |     want::<Foo<usize, B>>(f);
-   |                           ^ expected struct `Foo`, found `usize`
+   |     --------------------- ^ expected struct `Foo`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<usize, B>`
                 found type `usize`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:21:22
    |
 LL |     want::<Foo<foo>>(f);
-   |                      ^ expected struct `Foo`, found `usize`
+   |     ---------------- ^ expected struct `Foo`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<foo>`
                 found type `usize`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:22:25
    |
 LL |     want::<Foo<foo, B>>(f);
-   |                         ^ expected struct `Foo`, found `usize`
+   |     ------------------- ^ expected struct `Foo`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<foo, B>`
                 found type `usize`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:23:22
    |
 LL |     want::<Foo<bar>>(f);
-   |                      ^ expected struct `Foo`, found `usize`
+   |     ---------------- ^ expected struct `Foo`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<bar>`
                 found type `usize`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:24:25
    |
 LL |     want::<Foo<bar, B>>(f);
-   |                         ^ expected struct `Foo`, found `usize`
+   |     ------------------- ^ expected struct `Foo`, found `usize`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<bar, B>`
                 found type `usize`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:28:19
    |
 LL |     want::<usize>(f);
-   |                   ^ expected `usize`, found struct `foo`
+   |     ------------- ^ expected `usize`, found struct `foo`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:29:17
    |
 LL |     want::<bar>(f);
-   |                 ^ expected struct `bar`, found struct `foo`
+   |     ----------- ^ expected struct `bar`, found struct `foo`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:30:24
    |
 LL |     want::<Foo<usize>>(f);
-   |                        ^ expected struct `Foo`, found struct `foo`
+   |     ------------------ ^ expected struct `Foo`, found struct `foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<usize>`
               found struct `foo`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:31:27
    |
 LL |     want::<Foo<usize, B>>(f);
-   |                           ^ expected struct `Foo`, found struct `foo`
+   |     --------------------- ^ expected struct `Foo`, found struct `foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<usize, B>`
               found struct `foo`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:32:22
    |
 LL |     want::<Foo<foo>>(f);
-   |                      ^ expected struct `Foo`, found struct `foo`
+   |     ---------------- ^ expected struct `Foo`, found struct `foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<foo>`
               found struct `foo`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:33:25
    |
 LL |     want::<Foo<foo, B>>(f);
-   |                         ^ expected struct `Foo`, found struct `foo`
+   |     ------------------- ^ expected struct `Foo`, found struct `foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<foo, B>`
               found struct `foo`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:34:22
    |
 LL |     want::<Foo<bar>>(f);
-   |                      ^ expected struct `Foo`, found struct `foo`
+   |     ---------------- ^ expected struct `Foo`, found struct `foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<bar>`
               found struct `foo`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:35:25
    |
 LL |     want::<Foo<bar, B>>(f);
-   |                         ^ expected struct `Foo`, found struct `foo`
+   |     ------------------- ^ expected struct `Foo`, found struct `foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<bar, B>`
               found struct `foo`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:39:19
    |
 LL |     want::<usize>(f);
-   |                   ^ expected `usize`, found struct `Foo`
+   |     ------------- ^ expected `usize`, found struct `Foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected type `usize`
             found struct `Foo<foo>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:40:17
    |
 LL |     want::<foo>(f);
-   |                 ^ expected struct `foo`, found struct `Foo`
+   |     ----------- ^ expected struct `foo`, found struct `Foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `foo`
               found struct `Foo<foo>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:41:17
    |
 LL |     want::<bar>(f);
-   |                 ^ expected struct `bar`, found struct `Foo`
+   |     ----------- ^ expected struct `bar`, found struct `Foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `bar`
               found struct `Foo<foo>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:42:24
    |
 LL |     want::<Foo<usize>>(f);
-   |                        ^ expected `usize`, found struct `foo`
+   |     ------------------ ^ expected `usize`, found struct `foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<usize>`
               found struct `Foo<foo>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:43:27
    |
 LL |     want::<Foo<usize, B>>(f);
-   |                           ^ expected `usize`, found struct `foo`
+   |     --------------------- ^ expected `usize`, found struct `foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<usize, B>`
               found struct `Foo<foo, A>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:44:25
    |
 LL |     want::<Foo<foo, B>>(f);
-   |                         ^ expected struct `B`, found struct `A`
+   |     ------------------- ^ expected struct `B`, found struct `A`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<_, B>`
               found struct `Foo<_, A>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:45:22
    |
 LL |     want::<Foo<bar>>(f);
-   |                      ^ expected struct `bar`, found struct `foo`
+   |     ---------------- ^ expected struct `bar`, found struct `foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<bar>`
               found struct `Foo<foo>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:46:25
    |
 LL |     want::<Foo<bar, B>>(f);
-   |                         ^ expected struct `bar`, found struct `foo`
+   |     ------------------- ^ expected struct `bar`, found struct `foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<bar, B>`
               found struct `Foo<foo, A>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:47:23
    |
 LL |     want::<&Foo<foo>>(f);
-   |                       ^
-   |                       |
-   |                       expected `&Foo<foo>`, found struct `Foo`
-   |                       help: consider borrowing here: `&f`
+   |     ----------------- ^
+   |     |                 |
+   |     |                 expected `&Foo<foo>`, found struct `Foo`
+   |     |                 help: consider borrowing here: `&f`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&Foo<foo>`
                  found struct `Foo<foo>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:48:26
    |
 LL |     want::<&Foo<foo, B>>(f);
-   |                          ^ expected `&Foo<foo, B>`, found struct `Foo`
+   |     -------------------- ^ expected `&Foo<foo, B>`, found struct `Foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&Foo<foo, B>`
                  found struct `Foo<foo>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:52:19
    |
 LL |     want::<usize>(f);
-   |                   ^ expected `usize`, found struct `Foo`
+   |     ------------- ^ expected `usize`, found struct `Foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected type `usize`
             found struct `Foo<foo, B>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:53:17
    |
 LL |     want::<foo>(f);
-   |                 ^ expected struct `foo`, found struct `Foo`
+   |     ----------- ^ expected struct `foo`, found struct `Foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `foo`
               found struct `Foo<foo, B>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:54:17
    |
 LL |     want::<bar>(f);
-   |                 ^ expected struct `bar`, found struct `Foo`
+   |     ----------- ^ expected struct `bar`, found struct `Foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `bar`
               found struct `Foo<foo, B>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:55:24
    |
 LL |     want::<Foo<usize>>(f);
-   |                        ^ expected `usize`, found struct `foo`
+   |     ------------------ ^ expected `usize`, found struct `foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<usize, A>`
               found struct `Foo<foo, B>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:56:27
    |
 LL |     want::<Foo<usize, B>>(f);
-   |                           ^ expected `usize`, found struct `foo`
+   |     --------------------- ^ expected `usize`, found struct `foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<usize, _>`
               found struct `Foo<foo, _>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:57:22
    |
 LL |     want::<Foo<foo>>(f);
-   |                      ^ expected struct `A`, found struct `B`
+   |     ---------------- ^ expected struct `A`, found struct `B`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<_, A>`
               found struct `Foo<_, B>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:58:22
    |
 LL |     want::<Foo<bar>>(f);
-   |                      ^ expected struct `bar`, found struct `foo`
+   |     ---------------- ^ expected struct `bar`, found struct `foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<bar, A>`
               found struct `Foo<foo, B>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:59:25
    |
 LL |     want::<Foo<bar, B>>(f);
-   |                         ^ expected struct `bar`, found struct `foo`
+   |     ------------------- ^ expected struct `bar`, found struct `foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<bar, _>`
               found struct `Foo<foo, _>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:60:23
    |
 LL |     want::<&Foo<foo>>(f);
-   |                       ^ expected `&Foo<foo>`, found struct `Foo`
+   |     ----------------- ^ expected `&Foo<foo>`, found struct `Foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&Foo<foo>`
                  found struct `Foo<foo, B>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:61:26
    |
 LL |     want::<&Foo<foo, B>>(f);
-   |                          ^
-   |                          |
-   |                          expected `&Foo<foo, B>`, found struct `Foo`
-   |                          help: consider borrowing here: `&f`
+   |     -------------------- ^
+   |     |                    |
+   |     |                    expected `&Foo<foo, B>`, found struct `Foo`
+   |     |                    help: consider borrowing here: `&f`
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&Foo<foo, B>`
                  found struct `Foo<foo, B>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:65:19
    |
 LL |     want::<usize>(f);
-   |                   ^ expected `usize`, found struct `Foo`
+   |     ------------- ^ expected `usize`, found struct `Foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected type `usize`
             found struct `Foo<foo, B, A>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:66:17
    |
 LL |     want::<foo>(f);
-   |                 ^ expected struct `foo`, found struct `Foo`
+   |     ----------- ^ expected struct `foo`, found struct `Foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `foo`
               found struct `Foo<foo, B, A>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:67:17
    |
 LL |     want::<bar>(f);
-   |                 ^ expected struct `bar`, found struct `Foo`
+   |     ----------- ^ expected struct `bar`, found struct `Foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `bar`
               found struct `Foo<foo, B, A>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:68:24
    |
 LL |     want::<Foo<usize>>(f);
-   |                        ^ expected `usize`, found struct `foo`
+   |     ------------------ ^ expected `usize`, found struct `foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<usize, A, B>`
               found struct `Foo<foo, B, A>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:69:27
    |
 LL |     want::<Foo<usize, B>>(f);
-   |                           ^ expected `usize`, found struct `foo`
+   |     --------------------- ^ expected `usize`, found struct `foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<usize, _, B>`
               found struct `Foo<foo, _, A>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:70:22
    |
 LL |     want::<Foo<foo>>(f);
-   |                      ^ expected struct `A`, found struct `B`
+   |     ---------------- ^ expected struct `A`, found struct `B`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<_, A, B>`
               found struct `Foo<_, B, A>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:71:25
    |
 LL |     want::<Foo<foo, B>>(f);
-   |                         ^ expected struct `B`, found struct `A`
+   |     ------------------- ^ expected struct `B`, found struct `A`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<_, _, B>`
               found struct `Foo<_, _, A>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:72:22
    |
 LL |     want::<Foo<bar>>(f);
-   |                      ^ expected struct `bar`, found struct `foo`
+   |     ---------------- ^ expected struct `bar`, found struct `foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<bar, A, B>`
               found struct `Foo<foo, B, A>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:73:25
    |
 LL |     want::<Foo<bar, B>>(f);
-   |                         ^ expected struct `bar`, found struct `foo`
+   |     ------------------- ^ expected struct `bar`, found struct `foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected struct `Foo<bar, _, B>`
               found struct `Foo<foo, _, A>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:74:23
    |
 LL |     want::<&Foo<foo>>(f);
-   |                       ^ expected `&Foo<foo>`, found struct `Foo`
+   |     ----------------- ^ expected `&Foo<foo>`, found struct `Foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&Foo<foo>`
                  found struct `Foo<foo, B, A>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch.rs:75:26
    |
 LL |     want::<&Foo<foo, B>>(f);
-   |                          ^ expected `&Foo<foo, B>`, found struct `Foo`
+   |     -------------------- ^ expected `&Foo<foo, B>`, found struct `Foo`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected reference `&Foo<foo, B>`
                  found struct `Foo<foo, B, A>`
+note: function defined here
+  --> $DIR/type-mismatch.rs:14:4
+   |
+LL | fn want<T>(t: T) {}
+   |    ^^^^    ----
 
 error: aborting due to 47 previous errors
 
index 39bff88e7f81a3624cbbf3ec0aa5bc3bc2e26122..9346150750128c4b61fdd256e71d081a0d086df4 100644 (file)
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/issue-46112.rs:9:21
    |
 LL | fn main() { test(Ok(())); }
-   |                     ^^ expected enum `Option`, found `()`
+   |                  -- ^^ expected enum `Option`, found `()`
+   |                  |
+   |                  arguments to this enum variant are incorrect
    |
    = note:   expected enum `Option<()>`
            found unit type `()`
index 0a79d539ea96246da68fc42f57b0fb72155e1c41..04dc0e36520b4e7e9b5033f746c8270b3abeedce 100644 (file)
@@ -8,10 +8,17 @@ error[E0308]: mismatched types
   --> $DIR/issue-84768.rs:7:42
    |
 LL |     <F as FnOnce(&mut u8)>::call_once(f, 1)
-   |                                          ^ expected tuple, found integer
+   |     ---------------------------------    ^ expected tuple, found integer
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected tuple `(&mut u8,)`
                found type `{integer}`
+note: associated function defined here
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL |     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+   |                           ^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 4cb46a34a07a11b76b93c7cbc4b0f3014077bf9a..5fa1ae1a54f722591a341779584652c702b3aef2 100644 (file)
@@ -2,10 +2,17 @@ error[E0308]: mismatched types
   --> $DIR/issue-89856.rs:6:20
    |
 LL |     take_str_maybe(option);
-   |                    ^^^^^^ expected `str`, found struct `String`
+   |     -------------- ^^^^^^ expected `str`, found struct `String`
+   |     |
+   |     arguments to this function are incorrect
    |
    = note: expected enum `Option<&str>`
               found enum `Option<&String>`
+note: function defined here
+  --> $DIR/issue-89856.rs:1:4
+   |
+LL | fn take_str_maybe(x: Option<&str>) -> Option<&str> { None }
+   |    ^^^^^^^^^^^^^^ ---------------
 help: try converting the passed type into a `&str`
    |
 LL |     take_str_maybe(option.map(|x| &**x));
index 6e99feed33f9c9d99c43ceeb17961e0c319aee5d..721b2c821efec8b185b68d0d3918795a960c9647 100644 (file)
@@ -2,95 +2,116 @@ error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:6:13
    |
 LL |     let _ = Some(3, 2);
-   |             ^^^^ -  - supplied 2 arguments
-   |             |
-   |             expected 1 argument
+   |             ^^^^    - argument unexpected
+   |
+help: remove the extra argument
+   |
+LL |     let _ = Some(3);
+   |             ~~~~~~~
 
 error[E0061]: this enum variant takes 1 argument but 3 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:7:13
    |
 LL |     let _ = Ok(3, 6, 2);
-   |             ^^ -  -  - supplied 3 arguments
-   |             |
-   |             expected 1 argument
+   |             ^^    -  - argument unexpected
+   |                   |
+   |                   argument unexpected
+   |
+help: remove the extra arguments
+   |
+LL |     let _ = Ok(3);
+   |             ~~~~~
 
 error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:8:13
    |
 LL |     let _ = Ok();
-   |             ^^-- supplied 0 arguments
-   |             |
-   |             expected 1 argument
+   |             ^^-- an argument is missing
+   |
+help: provide the argument
+   |
+LL |     let _ = Ok({_});
+   |             ~~~~~~~
 
 error[E0061]: this struct takes 1 argument but 0 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:9:13
    |
 LL |     let _ = Wrapper();
-   |             ^^^^^^^-- supplied 0 arguments
-   |             |
-   |             expected 1 argument
+   |             ^^^^^^^-- an argument of type `i32` is missing
    |
 note: tuple struct defined here
   --> $DIR/struct-enum-wrong-args.rs:2:8
    |
 LL | struct Wrapper(i32);
    |        ^^^^^^^
+help: provide the argument
+   |
+LL |     let _ = Wrapper({i32});
+   |             ~~~~~~~~~~~~~~
 
 error[E0061]: this struct takes 1 argument but 2 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:10:13
    |
 LL |     let _ = Wrapper(5, 2);
-   |             ^^^^^^^ -  - supplied 2 arguments
-   |             |
-   |             expected 1 argument
+   |             ^^^^^^^    - argument unexpected
    |
 note: tuple struct defined here
   --> $DIR/struct-enum-wrong-args.rs:2:8
    |
 LL | struct Wrapper(i32);
    |        ^^^^^^^
+help: remove the extra argument
+   |
+LL |     let _ = Wrapper(5);
+   |             ~~~~~~~~~~
 
 error[E0061]: this struct takes 2 arguments but 0 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:11:13
    |
 LL |     let _ = DoubleWrapper();
-   |             ^^^^^^^^^^^^^-- supplied 0 arguments
-   |             |
-   |             expected 2 arguments
+   |             ^^^^^^^^^^^^^-- two arguments of type `i32` and `i32` are missing
    |
 note: tuple struct defined here
   --> $DIR/struct-enum-wrong-args.rs:3:8
    |
 LL | struct DoubleWrapper(i32, i32);
    |        ^^^^^^^^^^^^^
+help: provide the arguments
+   |
+LL |     let _ = DoubleWrapper({i32}, {i32});
+   |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this struct takes 2 arguments but 1 argument was supplied
   --> $DIR/struct-enum-wrong-args.rs:12:13
    |
 LL |     let _ = DoubleWrapper(5);
-   |             ^^^^^^^^^^^^^ - supplied 1 argument
-   |             |
-   |             expected 2 arguments
+   |             ^^^^^^^^^^^^^--- an argument of type `i32` is missing
    |
 note: tuple struct defined here
   --> $DIR/struct-enum-wrong-args.rs:3:8
    |
 LL | struct DoubleWrapper(i32, i32);
    |        ^^^^^^^^^^^^^
+help: provide the argument
+   |
+LL |     let _ = DoubleWrapper(5, {i32});
+   |             ~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this struct takes 2 arguments but 3 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:13:13
    |
 LL |     let _ = DoubleWrapper(5, 2, 7);
-   |             ^^^^^^^^^^^^^ -  -  - supplied 3 arguments
-   |             |
-   |             expected 2 arguments
+   |             ^^^^^^^^^^^^^       - argument unexpected
    |
 note: tuple struct defined here
   --> $DIR/struct-enum-wrong-args.rs:3:8
    |
 LL | struct DoubleWrapper(i32, i32);
    |        ^^^^^^^^^^^^^
+help: remove the extra argument
+   |
+LL |     let _ = DoubleWrapper(5, 2);
+   |             ~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 8 previous errors
 
index cf5c15df7051cee43b705213b501dd19fdea6d8d..fc3778b796745283c6a11c7928efc1f232047b06 100644 (file)
@@ -26,7 +26,7 @@ error[E0321]: cross-crate traits with a default impl, like `DefaultedTrait`, can
 LL | impl DefaultedTrait for Box<C> { }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait for type in another crate
 
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
   --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:22:1
    |
 LL | impl DefaultedTrait for lib::Something<C> { }
index ca0876be58df9909d111e16ac6cea7d8272bb3f4..22fedb22d66c6b9b2fe96046bbd9706889062493 100644 (file)
@@ -57,7 +57,7 @@ unsafe fn test12(x: *const usize) -> *const *const _ {
 
 impl Clone for Test9 {
     fn clone(&self) -> _ { Test9 }
-    //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
+    //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
 
     fn clone_from(&mut self, other: _) { *self = Test9; }
     //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
@@ -113,7 +113,7 @@ fn fn_test10(&self, _x : _) { }
 
     impl Clone for FnTest9 {
         fn clone(&self) -> _ { FnTest9 }
-        //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
+        //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
 
         fn clone_from(&mut self, other: _) { *self = FnTest9; }
         //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
index c07b96f9a977ae325e2a2cc527f7719ff949d7a3..3ea317dfb1a5d329a07c14569935f854b1a32861 100644 (file)
@@ -545,14 +545,16 @@ help: use type parameters instead
 LL |     fn test10<T>(&self, _x : T) { }
    |              +++             ~
 
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:59:24
    |
 LL |     fn clone(&self) -> _ { Test9 }
-   |                        ^
-   |                        |
-   |                        not allowed in type signatures
-   |                        help: replace with the correct return type: `Test9`
+   |                        ^ not allowed in type signatures
+   |
+help: try replacing `_` with the type in the corresponding trait method signature
+   |
+LL |     fn clone(&self) -> Test9 { Test9 }
+   |                        ~~~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:62:37
@@ -560,10 +562,10 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
 LL |     fn clone_from(&mut self, other: _) { *self = Test9; }
    |                                     ^ not allowed in type signatures
    |
-help: use type parameters instead
+help: try replacing `_` with the type in the corresponding trait method signature
    |
-LL |     fn clone_from<T>(&mut self, other: T) { *self = Test9; }
-   |                  +++                   ~
+LL |     fn clone_from(&mut self, other: &Test9) { *self = Test9; }
+   |                                     ~~~~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/typeck_type_placeholder_item.rs:107:31
@@ -585,14 +587,16 @@ help: use type parameters instead
 LL |         fn fn_test10<T>(&self, _x : T) { }
    |                     +++             ~
 
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:115:28
    |
 LL |         fn clone(&self) -> _ { FnTest9 }
-   |                            ^
-   |                            |
-   |                            not allowed in type signatures
-   |                            help: replace with the correct return type: `FnTest9`
+   |                            ^ not allowed in type signatures
+   |
+help: try replacing `_` with the type in the corresponding trait method signature
+   |
+LL |         fn clone(&self) -> FnTest9 { FnTest9 }
+   |                            ~~~~~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:118:41
@@ -600,10 +604,10 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
 LL |         fn clone_from(&mut self, other: _) { *self = FnTest9; }
    |                                         ^ not allowed in type signatures
    |
-help: use type parameters instead
+help: try replacing `_` with the type in the corresponding trait method signature
    |
-LL |         fn clone_from<T>(&mut self, other: T) { *self = FnTest9; }
-   |                      +++                   ~
+LL |         fn clone_from(&mut self, other: &FnTest9) { *self = FnTest9; }
+   |                                         ~~~~~~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
   --> $DIR/typeck_type_placeholder_item.rs:201:14
index 74766d9fdd1b12559e50bda4cf02579761cddc48..c6f9b3661a232a84efb7c90365134c266866aa3c 100644 (file)
@@ -20,8 +20,15 @@ error[E0308]: mismatched types
   --> $DIR/ufcs-qpath-self-mismatch.rs:6:28
    |
 LL |     <i32 as Add<i32>>::add(1u32, 2);
-   |                            ^^^^ expected `i32`, found `u32`
+   |     ---------------------- ^^^^ expected `i32`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
    |
+note: associated function defined here
+  --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
+   |
+LL |     fn add(self, rhs: Rhs) -> Self::Output;
+   |        ^^^
 help: change the type of the numeric literal from `u32` to `i32`
    |
 LL |     <i32 as Add<i32>>::add(1i32, 2);
@@ -31,8 +38,15 @@ error[E0308]: mismatched types
   --> $DIR/ufcs-qpath-self-mismatch.rs:8:31
    |
 LL |     <i32 as Add<i32>>::add(1, 2u32);
-   |                               ^^^^ expected `i32`, found `u32`
+   |     ----------------------    ^^^^ expected `i32`, found `u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: associated function defined here
+  --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
    |
+LL |     fn add(self, rhs: Rhs) -> Self::Output;
+   |        ^^^
 help: change the type of the numeric literal from `u32` to `i32`
    |
 LL |     <i32 as Add<i32>>::add(1, 2i32);
index f791ea62ceb65f50ca68d90891bb18aebbc68bce..ea1ca380b1c7a853c20c2b15e007f85f325649e6 100644 (file)
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/unboxed-closures-type-mismatch.rs:5:15
    |
 LL |     let z = f(1_usize, 2);
-   |               ^^^^^^^ expected `isize`, found `usize`
+   |             - ^^^^^^^ expected `isize`, found `usize`
+   |             |
+   |             arguments to this function are incorrect
    |
 help: change the type of the numeric literal from `usize` to `isize`
    |
index e4ee5e8cb2741e8b5cf49a0cc4e32c17d3c43763..74dc331b00a5ce797c70091012def3c127f39ea9 100644 (file)
@@ -10,22 +10,22 @@ impl<'_> IceCube<'_> {}
 //~^ ERROR `'_` cannot be used here
 
 struct Struct<'_> {
-//~^ ERROR `'_` cannot be used here
+    //~^ ERROR `'_` cannot be used here
     v: Vec<&'static char>
 }
 
 enum Enum<'_> {
-//~^ ERROR `'_` cannot be used here
+    //~^ ERROR `'_` cannot be used here
     Variant
 }
 
 union Union<'_> {
-//~^ ERROR `'_` cannot be used here
+    //~^ ERROR `'_` cannot be used here
     a: u32
 }
 
 trait Trait<'_> {
-//~^ ERROR `'_` cannot be used here
+    //~^ ERROR `'_` cannot be used here
 }
 
 fn foo<'_>() {
diff --git a/src/test/ui/uninhabited/privately-uninhabited-mir-call.rs b/src/test/ui/uninhabited/privately-uninhabited-mir-call.rs
new file mode 100644 (file)
index 0000000..b37ec26
--- /dev/null
@@ -0,0 +1,29 @@
+// Verifies that MIR building for a call expression respects
+// privacy when checking if a call return type is uninhabited.
+
+pub mod widget {
+    enum Unimplemented {}
+    pub struct Widget(Unimplemented);
+
+    impl Widget {
+        pub fn new() -> Widget {
+            todo!();
+        }
+    }
+
+    pub fn f() {
+        let x: &mut u32;
+        Widget::new();
+        // Ok. Widget type returned from new is known to be uninhabited
+        // and the following code is considered unreachable.
+        *x = 1;
+    }
+}
+
+fn main() {
+    let y: &mut u32;
+    widget::Widget::new();
+    // Error. Widget type is not known to be uninhabited here,
+    // so the following code is considered reachable.
+    *y = 2; //~ ERROR use of possibly-uninitialized variable
+}
diff --git a/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr b/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr
new file mode 100644 (file)
index 0000000..fb19534
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly-uninitialized variable: `y`
+  --> $DIR/privately-uninhabited-mir-call.rs:28:5
+   |
+LL |     *y = 2;
+   |     ^^^^^^ use of possibly-uninitialized `y`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
index 33f762ccf63016a0f1f9a94c5bd3ec1614b18e7a..e7960960774fcdf54641b50b5c913cc4482f57bc 100644 (file)
@@ -1,11 +1,27 @@
 error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
-  --> $DIR/issue-45087-unreachable-unsafe.rs:6:5
+  --> $DIR/issue-45087-unreachable-unsafe.rs:7:5
    |
 LL |     *(1 as *mut u32) = 42;
    |     ^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer
    |
    = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
-error: aborting due to previous error
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/issue-45087-unreachable-unsafe.rs:17:5
+   |
+LL |     *a = 1;
+   |     ^^^^^^ dereference of raw pointer
+   |
+   = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/issue-45087-unreachable-unsafe.rs:29:5
+   |
+LL |     *b = 1;
+   |     ^^^^^^ dereference of raw pointer
+   |
+   = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0133`.
index 071cea8fbd78bd905a4f9cfea5951de842ad05a7..3e3da667c0b0883bb0636cc460c6e4dd0e8c4acc 100644 (file)
@@ -1,3 +1,4 @@
+// Verify that unreachable code undergoes unsafety checks.
 // revisions: mir thir
 // [thir]compile-flags: -Z thir-unsafeck
 
@@ -6,3 +7,25 @@ fn main() {
     *(1 as *mut u32) = 42;
     //~^ ERROR dereference of raw pointer is unsafe
 }
+
+fn panic() -> ! {
+    panic!();
+}
+
+fn f(a: *mut u32) {
+    panic();
+    *a = 1;
+    //~^ ERROR dereference of raw pointer is unsafe
+}
+
+enum Void {}
+
+fn uninhabited() -> Void {
+    panic!();
+}
+
+fn g(b: *mut u32) {
+    uninhabited();
+    *b = 1;
+    //~^ ERROR dereference of raw pointer is unsafe
+}
index 73a113652b8338b02f0388078f46b82beba22fca..e81adad45075054682737061ac3c3d64999b478a 100644 (file)
@@ -1,11 +1,27 @@
 error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
-  --> $DIR/issue-45087-unreachable-unsafe.rs:6:5
+  --> $DIR/issue-45087-unreachable-unsafe.rs:7:5
    |
 LL |     *(1 as *mut u32) = 42;
    |     ^^^^^^^^^^^^^^^^ dereference of raw pointer
    |
    = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
-error: aborting due to previous error
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/issue-45087-unreachable-unsafe.rs:17:5
+   |
+LL |     *a = 1;
+   |     ^^ dereference of raw pointer
+   |
+   = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/issue-45087-unreachable-unsafe.rs:29:5
+   |
+LL |     *b = 1;
+   |     ^^ dereference of raw pointer
+   |
+   = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unterminated-nested-comment.rs b/src/test/ui/unterminated-nested-comment.rs
new file mode 100644 (file)
index 0000000..db5f2f3
--- /dev/null
@@ -0,0 +1,4 @@
+/* //~ ERROR E0758
+/* */
+/*
+*/
diff --git a/src/test/ui/unterminated-nested-comment.stderr b/src/test/ui/unterminated-nested-comment.stderr
new file mode 100644 (file)
index 0000000..3653e76
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0758]: unterminated block comment
+  --> $DIR/unterminated-nested-comment.rs:1:1
+   |
+LL |   /*
+   |   ^-
+   |   |
+   |  _unterminated block comment
+   | |
+LL | | /* */
+LL | | /*
+   | | --
+   | | |
+   | | ...as last nested comment starts here, maybe you want to close this instead?
+LL | | */
+   | |_--^
+   |   |
+   |   ...and last nested comment terminates here.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0758`.
diff --git a/src/test/ui/unused-crate-deps/extern-loc-bad-loctype.rs b/src/test/ui/unused-crate-deps/extern-loc-bad-loctype.rs
deleted file mode 100644 (file)
index e69df03..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// --extern-location with bad location type
-
-// aux-crate:bar=bar.rs
-// compile-flags:--extern-location bar=badloc:in-the-test-file -Z unstable-options
-
-#![warn(unused_crate_dependencies)]
-
-fn main() {}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-bad-loctype.stderr b/src/test/ui/unused-crate-deps/extern-loc-bad-loctype.stderr
deleted file mode 100644 (file)
index 12378f1..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-error: unknown location type `badloc`: use `raw` or `json`
-
diff --git a/src/test/ui/unused-crate-deps/extern-loc-defl-json.rs b/src/test/ui/unused-crate-deps/extern-loc-defl-json.rs
deleted file mode 100644 (file)
index a023f53..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// Default extern location from name and path if one isn't specified
-
-// check-pass
-// aux-crate:bar=bar.rs
-// compile-flags:--error-format json
-
-#![warn(unused_crate_dependencies)]
-//~^ WARNING external crate `bar` unused in
-
-fn main() {}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-defl-json.stderr b/src/test/ui/unused-crate-deps/extern-loc-defl-json.stderr
deleted file mode 100644 (file)
index cee3f6c..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{"message":"external crate `bar` unused in `extern_loc_defl_json`: remove the dependency or add `use bar as _;`","code":{"code":"unused_crate_dependencies","explanation":null},"level":"warning","spans":[{"file_name":"$DIR/extern-loc-defl-json.rs","byte_start":146,"byte_end":146,"line_start":7,"line_end":7,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"#![warn(unused_crate_dependencies)]","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"the lint level is defined here","code":null,"level":"note","spans":[{"file_name":"$DIR/extern-loc-defl-json.rs","byte_start":154,"byte_end":179,"line_start":7,"line_end":7,"column_start":9,"column_end":34,"is_primary":true,"text":[{"text":"#![warn(unused_crate_dependencies)]","highlight_start":9,"highlight_end":34}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":null},{"message":"remove unnecessary dependency `bar`","code":null,"level":"help","spans":[],"children":[],"rendered":null},{"message":"json extern location","code":null,"level":"help","spans":[],"children":[],"rendered":null,"tool_metadata":{"name":"bar"}}],"rendered":"warning: external crate `bar` unused in `extern_loc_defl_json`: remove the dependency or add `use bar as _;`
-  --> $DIR/extern-loc-defl-json.rs:7:1
-   |
-LL | #![warn(unused_crate_dependencies)]
-   | ^
-   |
-note: the lint level is defined here
-  --> $DIR/extern-loc-defl-json.rs:7:9
-   |
-LL | #![warn(unused_crate_dependencies)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = help: remove unnecessary dependency `bar`
-
-"}
-{"message":"1 warning emitted","code":null,"level":"warning","spans":[],"children":[],"rendered":"warning: 1 warning emitted
-
-"}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-json-bad-json.rs b/src/test/ui/unused-crate-deps/extern-loc-json-bad-json.rs
deleted file mode 100644 (file)
index aee6233..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// --extern-location with a raw reference
-
-// aux-crate:bar=bar.rs
-// compile-flags:--extern-location bar=json:[{"malformed -Z unstable-options
-
-#![warn(unused_crate_dependencies)]
-
-fn main() {}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-json-bad-json.stderr b/src/test/ui/unused-crate-deps/extern-loc-json-bad-json.stderr
deleted file mode 100644 (file)
index 20d6063..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-error: `--extern-location`: malformed json location `[{"malformed`
-
diff --git a/src/test/ui/unused-crate-deps/extern-loc-json-json.rs b/src/test/ui/unused-crate-deps/extern-loc-json-json.rs
deleted file mode 100644 (file)
index c7988cd..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// --extern-location with a raw reference
-
-// check-pass
-// aux-crate:bar=bar.rs
-// compile-flags:--extern-location bar=json:{"key":123,"value":{}} --error-format json -Z unstable-options
-
-#![warn(unused_crate_dependencies)]
-//~^ WARNING external crate `bar` unused in
-
-fn main() {}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-json-json.stderr b/src/test/ui/unused-crate-deps/extern-loc-json-json.stderr
deleted file mode 100644 (file)
index 001ec6a..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{"message":"external crate `bar` unused in `extern_loc_json_json`: remove the dependency or add `use bar as _;`","code":{"code":"unused_crate_dependencies","explanation":null},"level":"warning","spans":[{"file_name":"$DIR/extern-loc-json-json.rs","byte_start":189,"byte_end":189,"line_start":7,"line_end":7,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"#![warn(unused_crate_dependencies)]","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"the lint level is defined here","code":null,"level":"note","spans":[{"file_name":"$DIR/extern-loc-json-json.rs","byte_start":197,"byte_end":222,"line_start":7,"line_end":7,"column_start":9,"column_end":34,"is_primary":true,"text":[{"text":"#![warn(unused_crate_dependencies)]","highlight_start":9,"highlight_end":34}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":null},{"message":"remove unnecessary dependency `bar`","code":null,"level":"help","spans":[],"children":[],"rendered":null},{"message":"json extern location","code":null,"level":"help","spans":[],"children":[],"rendered":null,"tool_metadata":{"key":123,"value":{}}}],"rendered":"warning: external crate `bar` unused in `extern_loc_json_json`: remove the dependency or add `use bar as _;`
-  --> $DIR/extern-loc-json-json.rs:7:1
-   |
-LL | #![warn(unused_crate_dependencies)]
-   | ^
-   |
-note: the lint level is defined here
-  --> $DIR/extern-loc-json-json.rs:7:9
-   |
-LL | #![warn(unused_crate_dependencies)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = help: remove unnecessary dependency `bar`
-
-"}
-{"message":"1 warning emitted","code":null,"level":"warning","spans":[],"children":[],"rendered":"warning: 1 warning emitted
-
-"}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-json.rs b/src/test/ui/unused-crate-deps/extern-loc-json.rs
deleted file mode 100644 (file)
index c0d76c8..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// --extern-location with a raw reference
-
-// check-pass
-// aux-crate:bar=bar.rs
-// compile-flags:--extern-location bar=json:{"key":123,"value":{}} -Z unstable-options
-
-#![warn(unused_crate_dependencies)]
-//~^ WARNING external crate `bar` unused in
-
-fn main() {}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-json.stderr b/src/test/ui/unused-crate-deps/extern-loc-json.stderr
deleted file mode 100644 (file)
index a6bbc0d..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-warning: external crate `bar` unused in `extern_loc_json`: remove the dependency or add `use bar as _;`
-  --> $DIR/extern-loc-json.rs:7:1
-   |
-LL | #![warn(unused_crate_dependencies)]
-   | ^
-   |
-note: the lint level is defined here
-  --> $DIR/extern-loc-json.rs:7:9
-   |
-LL | #![warn(unused_crate_dependencies)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = help: remove unnecessary dependency `bar`
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/unused-crate-deps/extern-loc-missing-loc.rs b/src/test/ui/unused-crate-deps/extern-loc-missing-loc.rs
deleted file mode 100644 (file)
index 6ac5589..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// --extern-location with a raw reference
-
-// aux-crate:bar=bar.rs
-// compile-flags:--extern-location bar -Zunstable-options
-
-#![warn(unused_crate_dependencies)]
-
-fn main() {}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-missing-loc.stderr b/src/test/ui/unused-crate-deps/extern-loc-missing-loc.stderr
deleted file mode 100644 (file)
index 4584fbf..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-error: `--extern-location`: specify location for extern crate `bar`
-
diff --git a/src/test/ui/unused-crate-deps/extern-loc-missing-loctype.rs b/src/test/ui/unused-crate-deps/extern-loc-missing-loctype.rs
deleted file mode 100644 (file)
index 3590b9c..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// --extern-location with no type
-
-// aux-crate:bar=bar.rs
-// compile-flags:--extern-location bar=missing-loc-type -Z unstable-options
-
-#![warn(unused_crate_dependencies)]
-
-fn main() {}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-missing-loctype.stderr b/src/test/ui/unused-crate-deps/extern-loc-missing-loctype.stderr
deleted file mode 100644 (file)
index d0c36eb..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-error: unknown location type `missing-loc-type`: use `raw` or `json`
-
diff --git a/src/test/ui/unused-crate-deps/extern-loc-raw-json.rs b/src/test/ui/unused-crate-deps/extern-loc-raw-json.rs
deleted file mode 100644 (file)
index 64c3d77..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// --extern-location with a raw reference
-
-// check-pass
-// aux-crate:bar=bar.rs
-// compile-flags:--extern-location bar=raw:in-the-test-file --error-format json -Z unstable-options
-
-#![warn(unused_crate_dependencies)]
-//~^ WARNING external crate `bar` unused in
-
-fn main() {}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-raw-json.stderr b/src/test/ui/unused-crate-deps/extern-loc-raw-json.stderr
deleted file mode 100644 (file)
index 4083bd5..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{"message":"external crate `bar` unused in `extern_loc_raw_json`: remove the dependency or add `use bar as _;`","code":{"code":"unused_crate_dependencies","explanation":null},"level":"warning","spans":[{"file_name":"$DIR/extern-loc-raw-json.rs","byte_start":182,"byte_end":182,"line_start":7,"line_end":7,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"#![warn(unused_crate_dependencies)]","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"the lint level is defined here","code":null,"level":"note","spans":[{"file_name":"$DIR/extern-loc-raw-json.rs","byte_start":190,"byte_end":215,"line_start":7,"line_end":7,"column_start":9,"column_end":34,"is_primary":true,"text":[{"text":"#![warn(unused_crate_dependencies)]","highlight_start":9,"highlight_end":34}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":null},{"message":"remove unnecessary dependency `bar` at `in-the-test-file`","code":null,"level":"help","spans":[],"children":[],"rendered":null},{"message":"raw extern location","code":null,"level":"help","spans":[{"file_name":"$DIR/extern-loc-raw-json.rs","byte_start":0,"byte_end":0,"line_start":1,"line_end":1,"column_start":1,"column_end":1,"is_primary":true,"text":[],"label":null,"suggested_replacement":"in-the-test-file","suggestion_applicability":"Unspecified","expansion":null}],"children":[],"rendered":null},{"message":"json extern location","code":null,"level":"help","spans":[],"children":[],"rendered":null,"tool_metadata":"in-the-test-file"}],"rendered":"warning: external crate `bar` unused in `extern_loc_raw_json`: remove the dependency or add `use bar as _;`
-  --> $DIR/extern-loc-raw-json.rs:7:1
-   |
-LL | #![warn(unused_crate_dependencies)]
-   | ^
-   |
-note: the lint level is defined here
-  --> $DIR/extern-loc-raw-json.rs:7:9
-   |
-LL | #![warn(unused_crate_dependencies)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = help: remove unnecessary dependency `bar` at `in-the-test-file`
-
-"}
-{"message":"1 warning emitted","code":null,"level":"warning","spans":[],"children":[],"rendered":"warning: 1 warning emitted
-
-"}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-raw-missing-loc.rs b/src/test/ui/unused-crate-deps/extern-loc-raw-missing-loc.rs
deleted file mode 100644 (file)
index a9e7afb..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// --extern-location with a raw reference
-
-// aux-crate:bar=bar.rs
-// compile-flags:--extern-location bar=raw -Z unstable-options
-
-#![warn(unused_crate_dependencies)]
-
-fn main() {}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-raw-missing-loc.stderr b/src/test/ui/unused-crate-deps/extern-loc-raw-missing-loc.stderr
deleted file mode 100644 (file)
index 4b51266..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-error: `--extern-location`: missing `raw` location
-
diff --git a/src/test/ui/unused-crate-deps/extern-loc-raw.rs b/src/test/ui/unused-crate-deps/extern-loc-raw.rs
deleted file mode 100644 (file)
index 27d0975..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// --extern-location with a raw reference
-
-// check-pass
-// aux-crate:bar=bar.rs
-// compile-flags:--extern-location bar=raw:in-the-test-file -Z unstable-options
-
-#![warn(unused_crate_dependencies)]
-//~^ WARNING external crate `bar` unused in
-
-fn main() {}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-raw.stderr b/src/test/ui/unused-crate-deps/extern-loc-raw.stderr
deleted file mode 100644 (file)
index 2cdd005..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-warning: external crate `bar` unused in `extern_loc_raw`: remove the dependency or add `use bar as _;`
-  --> $DIR/extern-loc-raw.rs:7:1
-   |
-LL | #![warn(unused_crate_dependencies)]
-   | ^
-   |
-note: the lint level is defined here
-  --> $DIR/extern-loc-raw.rs:7:9
-   |
-LL | #![warn(unused_crate_dependencies)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = help: remove unnecessary dependency `bar` at `in-the-test-file`
-
-warning: 1 warning emitted
-
index 479f51bff464d61f1ee8aa324d4426d520e3d699..15833126bd6201ddda75e3b529eb26f8dc08473c 100644 (file)
@@ -5,7 +5,6 @@ LL | pub fn fib(n: u32) -> Vec<u32> {
    | ^
    |
    = note: requested on the command line with `-W unused-crate-dependencies`
-   = help: remove unnecessary dependency `bar`
 
 warning: 1 warning emitted
 
index 1142d156d0e96e507d863f77532d7f710075309c..c8c6c4507b0c51427136d656ba9de8cdbdcd3a43 100644 (file)
@@ -9,7 +9,6 @@ note: the lint level is defined here
    |
 LL | #![warn(unused_crate_dependencies)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = help: remove unnecessary dependency `barbar`
 
 warning: 1 warning emitted
 
index 29667d9525cb4b266fc00b7783416079b9fd91cd..0d38315704b11fb25e6bc7be22774c0714d4f4d4 100644 (file)
@@ -9,7 +9,6 @@ note: the lint level is defined here
    |
 LL | #![warn(unused_crate_dependencies)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = help: remove unnecessary dependency `bar`
 
 warning: 1 warning emitted
 
index 2c0c9215129866c593193ebfce314d02946ecea1..65956461d643928fa5a319c7ae533f3dc7e15ded 100644 (file)
@@ -5,7 +5,6 @@ LL | fn main() {}
    | ^
    |
    = note: requested on the command line with `-W unused-crate-dependencies`
-   = help: remove unnecessary dependency `bar`
 
 warning: 1 warning emitted
 
index 2cd49218f5ad85728a314ac64aebf715c5a1f4bd..ea675ba9a1eb184560f8379ea4571e2d2b1e9ec4 100644 (file)
@@ -5,7 +5,6 @@ LL | fn main() {}
    | ^
    |
    = note: requested on the command line with `-W unused-crate-dependencies`
-   = help: remove unnecessary dependency `bar`
 
 warning: 1 warning emitted
 
index 27a4a653b49039a5ae0b1e9169644a0145ddeadc..64bfd14b7e7da346cf24751455fd9933adf70efd 100644 (file)
@@ -9,7 +9,7 @@ mod foo {
 
     pub fn g() {
         use ::super::main; //~ ERROR global paths cannot start with `super`
-        main(); //~ ERROR cannot find function `main` in this scope
+        main();
     }
 }
 
index edde26c1fc15d77e3ec7a9ad212c3cb5205894e1..7014a12e9ddd26202c7766baba8c9e19234cba75 100644 (file)
@@ -16,18 +16,6 @@ error[E0433]: failed to resolve: global paths cannot start with `super`
 LL |         use ::super::main;
    |               ^^^^^ global paths cannot start with `super`
 
-error[E0425]: cannot find function `main` in this scope
-  --> $DIR/use-super-global-path.rs:12:9
-   |
-LL |         main();
-   |         ^^^^ not found in this scope
-   |
-help: consider importing this function
-   |
-LL |     use main;
-   |
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0425, E0433.
-For more information about an error, try `rustc --explain E0425`.
+For more information about this error, try `rustc --explain E0433`.
index ba624507c21f0d332f13adb8259c7d786fedf2ab..16d198725523e0436817ef0c5144e3a3a3fa1311 100644 (file)
@@ -2,9 +2,13 @@ error[E0726]: implicit elided lifetime not allowed here
   --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:13:16
    |
 LL | impl Trait for Ref {}
-   |                ^^^- help: indicate the anonymous lifetime: `<'_>`
+   |                ^^^ expected lifetime parameter
    |
    = note: assuming a `'static` lifetime...
+help: indicate the anonymous lifetime
+   |
+LL | impl Trait for Ref<'_> {}
+   |                   ++++
 
 error: incompatible lifetime on type
   --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:21
index 6c52664154bbf333667287e087c21af0396527b6..e8df02fbad62f3590c792544a85d29c697414904 100644 (file)
@@ -1,20 +1,41 @@
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/where-lifetime-resolution.rs:6:38
    |
-LL | fn f() where
-   |     - help: consider introducing lifetime `'a` here: `<'a>`
-LL |     for<'a> dyn Trait1<'a>: Trait1<'a>, // OK
 LL |     (dyn for<'a> Trait1<'a>): Trait1<'a>,
    |                                      ^^ undeclared lifetime
+   |
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'a` lifetime
+   |
+LL |     (dyn for<'a> Trait1<'a>): for<'a> Trait1<'a>,
+   |                               +++++++
+help: consider making the bound lifetime-generic with a new `'a` lifetime
+   |
+LL |     for<'a> (dyn for<'a> Trait1<'a>): Trait1<'a>,
+   |     +++++++
+help: consider introducing lifetime `'a` here
+   |
+LL | fn f<'a>() where
+   |     ++++
 
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/where-lifetime-resolution.rs:8:52
    |
-LL | fn f() where
-   |     - help: consider introducing lifetime `'b` here: `<'b>`
-...
 LL |     for<'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>,
    |                                                    ^^ undeclared lifetime
+   |
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+   |
+LL |     for<'a> dyn for<'b> Trait2<'a, 'b>: for<'b> Trait2<'a, 'b>,
+   |                                         +++++++
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+   |
+LL |     for<'b, 'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>,
+   |         +++
+help: consider introducing lifetime `'b` here
+   |
+LL | fn f<'b>() where
+   |     ++++
 
 error: aborting due to 2 previous errors
 
index dba5baf4345858c591517b24801902a062c399f8..edffc4ada3d77799e5a04eeafd9b2f843d29fc23 160000 (submodule)
@@ -1 +1 @@
-Subproject commit dba5baf4345858c591517b24801902a062c399f8
+Subproject commit edffc4ada3d77799e5a04eeafd9b2f843d29fc23
index 85f952375491f213556d9f3fa606e8ad17edf044..2bf7f868905458be690ecf5d3d39e80fcd404470 100644 (file)
@@ -82,7 +82,7 @@ fn check<'tcx>(
 
         if rust_cc > self.limit.limit() {
             let fn_span = match kind {
-                FnKind::ItemFn(ident, _, _, _) | FnKind::Method(ident, _, _) => ident.span,
+                FnKind::ItemFn(ident, _, _) | FnKind::Method(ident, _) => ident.span,
                 FnKind::Closure => {
                     let header_span = body_span.with_hi(decl.output.span().lo());
                     let pos = snippet_opt(cx, header_span).and_then(|snip| {
index 1f4353fa4f72bd73a6028f80c49e71d1b552230e..346d03ca5568f0aaf7c3593a45f721999a758ea3 100644 (file)
@@ -260,7 +260,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
                     }
                     // The `module_name_repetitions` lint should only trigger if the item has the module in its
                     // name. Having the same name is accepted.
-                    if item.vis.node.is_pub() && item_camel.len() > mod_camel.len() {
+                    if cx.tcx.visibility(item.def_id).is_public() && item_camel.len() > mod_camel.len() {
                         let matching = count_match_start(mod_camel, &item_camel);
                         let rmatching = count_match_end(mod_camel, &item_camel);
                         let nchars = mod_camel.chars().count();
index b0f50b5c144bbe45a6487cee425aa3501258169f..173d41b4b05060b7794a9cbac5432ace09c817c0 100644 (file)
@@ -78,7 +78,10 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
             if !attrs.iter().any(|a| a.has_name(sym::non_exhaustive));
             then {
                 let (lint, msg) = if let ItemKind::Struct(ref v, ..) = item.kind {
-                    if v.fields().iter().any(|f| !f.vis.node.is_pub()) {
+                    if v.fields().iter().any(|f| {
+                        let def_id = cx.tcx.hir().local_def_id(f.hir_id);
+                        !cx.tcx.visibility(def_id).is_public()
+                    }) {
                         // skip structs with private fields
                         return;
                     }
index 830e3b32cfa2fac80d26726df67d353a835ea145..565a1c871d7580458b633285ea8a84aa913e0410 100644 (file)
@@ -17,8 +17,8 @@ pub(super) fn check_fn<'tcx>(
     hir_id: hir::HirId,
 ) {
     let unsafety = match kind {
-        intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }, _) => unsafety,
-        intravisit::FnKind::Method(_, sig, _) => sig.header.unsafety,
+        intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }) => unsafety,
+        intravisit::FnKind::Method(_, sig) => sig.header.unsafety,
         intravisit::FnKind::Closure => return,
     };
 
index 3af960491ed01d5872a0df98cba836829cadd303..5c8d8b8e7552c9e15f23b53a60f891a94357bf8a 100644 (file)
@@ -26,9 +26,8 @@ pub(super) fn check_fn(
                     header: hir::FnHeader { abi: Abi::Rust, .. },
                     ..
                 },
-                _,
             )
-            | intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }, _) => check_arg_number(
+            | intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }) => check_arg_number(
                 cx,
                 decl,
                 span.with_hi(decl.output.span().hi()),
index a0b2302662e64b8b6bf6a476fc4439338c6bd95d..9ba9642fcc833691fabcd4489b206e6ddb16a37a 100644 (file)
@@ -169,13 +169,14 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
             .iter()
             .map(|(o, _)| match o {
                 InlineAsmOperand::In { expr, .. }
-                | InlineAsmOperand::InOut { expr, .. }
-                | InlineAsmOperand::Sym { expr } => never_loop_expr(expr, main_loop_id),
+                | InlineAsmOperand::InOut { expr, .. } => never_loop_expr(expr, main_loop_id),
                 InlineAsmOperand::Out { expr, .. } => never_loop_expr_all(&mut expr.iter(), main_loop_id),
                 InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
                     never_loop_expr_all(&mut once(in_expr).chain(out_expr.iter()), main_loop_id)
                 },
-                InlineAsmOperand::Const { .. } => NeverLoopResult::Otherwise,
+                InlineAsmOperand::Const { .. }
+                | InlineAsmOperand::SymFn { .. }
+                | InlineAsmOperand::SymStatic { .. } => NeverLoopResult::Otherwise,
             })
             .fold(NeverLoopResult::Otherwise, combine_both),
         ExprKind::Struct(_, _, None)
index fc0483a929a7a1e93c3cded4003f6b2835ec2985..5816a95dcebffe63aa2a9410940e4c372a83260d 100644 (file)
@@ -10,7 +10,7 @@
 use rustc_ast::ast;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::ty;
+use rustc_middle::ty::{self, DefIdTree};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::def_id::CRATE_DEF_ID;
 use rustc_span::source_map::Span;
@@ -114,8 +114,8 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) {
             hir::ItemKind::Fn(..) => {
                 // ignore main()
                 if it.ident.name == sym::main {
-                    let def_key = cx.tcx.hir().def_key(it.def_id);
-                    if def_key.parent == Some(hir::def_id::CRATE_DEF_INDEX) {
+                    let at_root = cx.tcx.local_parent(it.def_id) == Some(CRATE_DEF_ID);
+                    if at_root {
                         return;
                     }
                 }
index d29d07da7b0ffdcc8aa85a28443b6d8f1623357f..9c734221ebcea4989523b48545b88bb7e7916927 100644 (file)
@@ -85,7 +85,7 @@ fn check_fn(
         }
 
         match kind {
-            FnKind::ItemFn(.., header, _) => {
+            FnKind::ItemFn(.., header) => {
                 let attrs = cx.tcx.hir().attrs(hir_id);
                 if header.abi != Abi::Rust || requires_exact_signature(attrs) {
                     return;
index d59249d7f13d32343bcb237ae44bb5afd860e0a1..9af3059a37f93c9f7137de24778a71a0cada764a 100644 (file)
@@ -251,7 +251,7 @@ fn check_fn(
         }
 
         match kind {
-            FnKind::ItemFn(.., header, _) => {
+            FnKind::ItemFn(.., header) => {
                 if header.abi != Abi::Rust {
                     return;
                 }
index 2cee3c14d7f30f89db58dc7797d8090d4fe6d3a1..e2e2400f8e267ae8e398778ed0de72ba17b1bdbb 100644 (file)
@@ -1,8 +1,10 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_errors::Applicability;
-use rustc_hir::{Item, ItemKind, VisibilityKind};
+use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::def_id::CRATE_DEF_ID;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -41,7 +43,7 @@ pub struct RedundantPubCrate {
 
 impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
-        if let VisibilityKind::Crate { .. } = item.vis.node {
+        if cx.tcx.visibility(item.def_id) == ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id()) {
             if !cx.access_levels.is_exported(item.def_id) && self.is_exported.last() == Some(&false) {
                 let span = item.span.with_hi(item.ident.span.hi());
                 let descr = cx.tcx.def_kind(item.def_id).descr(item.def_id.to_def_id());
@@ -52,7 +54,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
                     &format!("pub(crate) {} inside private module", descr),
                     |diag| {
                         diag.span_suggestion(
-                            item.vis.span,
+                            item.vis_span,
                             "consider using",
                             "pub".to_string(),
                             Applicability::MachineApplicable,
index 79f104eac0be24c9e5b55e719021af891613471a..91e5e1e8b289288ae9c2e8d653f28484bfd8db36 100644 (file)
@@ -111,7 +111,7 @@ fn check_fn(
     ) {
         if_chain! {
             // We are only interested in methods, not in functions or associated functions.
-            if matches!(kind, FnKind::Method(_, _, _));
+            if matches!(kind, FnKind::Method(_, _));
             if let Some(fn_def) = cx.tcx.hir().opt_local_def_id(hir_id);
             if let Some(impl_def) = cx.tcx.impl_of_method(fn_def.to_def_id());
             // We don't want this method to be te implementation of a trait because the
index 22b458969551272c8083bf6cf97559055947c65c..a01e2f2db3afb2ee9c52ff3e6645c37ebaef4fe6 100644 (file)
@@ -50,7 +50,12 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
     fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
         let mut map = FxHashMap::<Res, ExistingName>::default();
 
-        for item in cx.tcx.hir().items() {
+        for id in cx.tcx.hir().items() {
+            if !matches!(cx.tcx.hir().def_kind(id.def_id), DefKind::Impl) {
+                continue;
+            }
+
+            let item = cx.tcx.hir().item(id);
             if let ItemKind::Impl(Impl {
                 items,
                 of_trait,
index 2b89398ecd6ad1ea3ed6be1359814d43aa0be47c..41333bb2addf7bbf70dfffc8a4fff632993348a3 100644 (file)
@@ -67,7 +67,7 @@ fn check_fn(
         span: Span,
         hir_id: HirId,
     ) {
-        if let FnKind::ItemFn(_, _, FnHeader { asyncness, .. }, _) = &fn_kind {
+        if let FnKind::ItemFn(_, _, FnHeader { asyncness, .. }) = &fn_kind {
             if matches!(asyncness, IsAsync::Async) {
                 let mut visitor = AsyncFnVisitor { cx, found_await: false };
                 walk_fn(&mut visitor, fn_kind, fn_decl, body.id(), span, hir_id);
index dc48ea3f4f99d77612cfcb3a4e48fab6dabf8f5a..37b114a0cfbc2239b4d539789daf80d638bba804 100644 (file)
@@ -4,6 +4,7 @@
 use rustc_ast::ast::{Attribute, InlineAsmTemplatePiece};
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::ty;
 use rustc_session::Session;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -45,14 +46,16 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<
             return;
         }
         println!("impl item `{}`", item.ident.name);
-        match item.vis.node {
-            hir::VisibilityKind::Public => println!("public"),
-            hir::VisibilityKind::Crate(_) => println!("visible crate wide"),
-            hir::VisibilityKind::Restricted { path, .. } => println!(
-                "visible in module `{}`",
-                rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(path, false))
-            ),
-            hir::VisibilityKind::Inherited => println!("visibility inherited from outer item"),
+        match cx.tcx.visibility(item.def_id) {
+            ty::Visibility::Public => println!("public"),
+            ty::Visibility::Restricted(def_id) => {
+                if def_id.is_top_level_module() {
+                    println!("visible crate wide")
+                } else {
+                    println!("visible in module `{}`", cx.tcx.def_path_str(def_id))
+                }
+            },
+            ty::Visibility::Invisible => println!("invisible"),
         }
         match item.kind {
             hir::ImplItemKind::Const(_, body_id) => {
@@ -281,8 +284,9 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
             for (op, _op_sp) in asm.operands {
                 match op {
                     hir::InlineAsmOperand::In { expr, .. }
-                    | hir::InlineAsmOperand::InOut { expr, .. }
-                    | hir::InlineAsmOperand::Sym { expr } => print_expr(cx, expr, indent + 1),
+                    | hir::InlineAsmOperand::InOut { expr, .. } => {
+                        print_expr(cx, expr, indent + 1);
+                    }
                     hir::InlineAsmOperand::Out { expr, .. } => {
                         if let Some(expr) = expr {
                             print_expr(cx, expr, indent + 1);
@@ -294,10 +298,26 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
                             print_expr(cx, out_expr, indent + 1);
                         }
                     },
-                    hir::InlineAsmOperand::Const { anon_const } => {
+                    hir::InlineAsmOperand::Const { anon_const }
+                    | hir::InlineAsmOperand::SymFn { anon_const } => {
                         println!("{}anon_const:", ind);
                         print_expr(cx, &cx.tcx.hir().body(anon_const.body).value, indent + 1);
                     },
+                    hir::InlineAsmOperand::SymStatic { path, .. } => {
+                        match path {
+                            hir::QPath::Resolved(ref ty, path) => {
+                                println!("{}Resolved Path, {:?}", ind, ty);
+                                println!("{}path: {:?}", ind, path);
+                            },
+                            hir::QPath::TypeRelative(ty, seg) => {
+                                println!("{}Relative Path, {:?}", ind, ty);
+                                println!("{}seg: {:?}", ind, seg);
+                            },
+                            hir::QPath::LangItem(lang_item, ..) => {
+                                println!("{}Lang Item Path, {:?}", ind, lang_item.name());
+                            },
+                        }
+                    }
                 }
             }
         },
@@ -343,14 +363,16 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
 fn print_item(cx: &LateContext<'_>, item: &hir::Item<'_>) {
     let did = item.def_id;
     println!("item `{}`", item.ident.name);
-    match item.vis.node {
-        hir::VisibilityKind::Public => println!("public"),
-        hir::VisibilityKind::Crate(_) => println!("visible crate wide"),
-        hir::VisibilityKind::Restricted { path, .. } => println!(
-            "visible in module `{}`",
-            rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(path, false))
-        ),
-        hir::VisibilityKind::Inherited => println!("visibility inherited from outer item"),
+    match cx.tcx.visibility(item.def_id) {
+        ty::Visibility::Public => println!("public"),
+        ty::Visibility::Restricted(def_id) => {
+            if def_id.is_top_level_module() {
+                println!("visible crate wide")
+            } else {
+                println!("visible in module `{}`", cx.tcx.def_path_str(def_id))
+            }
+        },
+        ty::Visibility::Invisible => println!("invisible"),
     }
     match item.kind {
         hir::ItemKind::ExternCrate(ref _renamed_from) => {
index 832da66a53695c55287ddda2eb3dc1343cab1b0a..2f74eaf3cf5c319a9fff3f2bc0e06d06e24da1e3 100644 (file)
@@ -8,6 +8,7 @@
     Item, ItemKind, PathSegment, UseKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::kw;
 use rustc_span::{sym, BytePos};
@@ -115,7 +116,8 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
         if is_test_module_or_function(cx.tcx, item) {
             self.test_modules_deep = self.test_modules_deep.saturating_add(1);
         }
-        if item.vis.node.is_pub() || item.vis.node.is_pub_restricted() {
+        let module = cx.tcx.parent_module_from_def_id(item.def_id);
+        if cx.tcx.visibility(item.def_id) != ty::Visibility::Restricted(module.to_def_id()) {
             return;
         }
         if_chain! {
index 00594f4d42addb594875349a2e6e2e031e24423a..c05317f59b716ad60f0fdd92689ee1167fbe914e 100644 (file)
@@ -675,7 +675,8 @@ pub fn hash_expr(&mut self, e: &Expr<'_>) {
                             }
                         },
                         InlineAsmOperand::Const { anon_const } => self.hash_body(anon_const.body),
-                        InlineAsmOperand::Sym { expr } => self.hash_expr(expr),
+                        InlineAsmOperand::SymFn { anon_const } => self.hash_body(anon_const.body),
+                        InlineAsmOperand::SymStatic { path, def_id: _ } => self.hash_qpath(path),
                     }
                 }
             },
index a275bac4ce63dc5436ea18d4677f8c219c50488c..74978720424d46e3f64f6970383b53c11c724e53 100644 (file)
@@ -1690,7 +1690,7 @@ pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>,
 
 /// Checks if the given function kind is an async function.
 pub fn is_async_fn(kind: FnKind<'_>) -> bool {
-    matches!(kind, FnKind::ItemFn(_, _, header, _) if header.asyncness == IsAsync::Async)
+    matches!(kind, FnKind::ItemFn(_, _, header) if header.asyncness == IsAsync::Async)
 }
 
 /// Peels away all the compiler generated code surrounding the body of an async function,
index c32c3dd9880f6af59f7578462a76149179560f54..cf06eb32e0c7fc041738d367cd6e6c19a4c31b85 100644 (file)
@@ -11,6 +11,19 @@ note: existing `foo` defined here
 LL |             fn foo() {}
    |             ^^^^^^^^^^^
 
+error: method's name is the same as an existing method in a trait
+  --> $DIR/same_name_method.rs:34:13
+   |
+LL |             fn clone() {}
+   |             ^^^^^^^^^^^^^
+   |
+note: existing `clone` defined here
+  --> $DIR/same_name_method.rs:30:18
+   |
+LL |         #[derive(Clone)]
+   |                  ^^^^^
+   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+
 error: method's name is the same as an existing method in a trait
   --> $DIR/same_name_method.rs:44:13
    |
@@ -47,18 +60,5 @@ note: existing `foo` defined here
 LL |         impl T1 for S {}
    |         ^^^^^^^^^^^^^^^^
 
-error: method's name is the same as an existing method in a trait
-  --> $DIR/same_name_method.rs:34:13
-   |
-LL |             fn clone() {}
-   |             ^^^^^^^^^^^^^
-   |
-note: existing `clone` defined here
-  --> $DIR/same_name_method.rs:30:18
-   |
-LL |         #[derive(Clone)]
-   |                  ^^^^^
-   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-
 error: aborting due to 5 previous errors
 
index 02038b5fb6b5a7ed56ce688bdf1e01834d0a68c6..0d2cb77855be1198a45f9ee31bb930a56312e151 100644 (file)
@@ -1,8 +1,8 @@
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:19:28
+  --> $DIR/unused_unit.rs:19:58
    |
 LL |     pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
-   |                            ^^^^^^ help: remove the `-> ()`
+   |                                                          ^^^^^^ help: remove the `-> ()`
    |
 note: the lint level is defined here
   --> $DIR/unused_unit.rs:12:9
@@ -11,16 +11,16 @@ LL | #![deny(clippy::unused_unit)]
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:20:18
+  --> $DIR/unused_unit.rs:19:28
    |
-LL |     where G: Fn() -> () {
-   |                  ^^^^^^ help: remove the `-> ()`
+LL |     pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
+   |                            ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:19:58
+  --> $DIR/unused_unit.rs:20:18
    |
-LL |     pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
-   |                                                          ^^^^^^ help: remove the `-> ()`
+LL |     where G: Fn() -> () {
+   |                  ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
   --> $DIR/unused_unit.rs:21:26
index 1bf6e6d011e5c125a2be7e7f64c5c3c54cbc15e5..2cb368c6881887cd6042740739bdfcbeb2c58fcd 100644 (file)
@@ -198,11 +198,8 @@ pub struct Config {
     /// The rust-demangler executable.
     pub rust_demangler_path: Option<PathBuf>,
 
-    /// The Python executable to use for LLDB.
-    pub lldb_python: String,
-
-    /// The Python executable to use for htmldocck.
-    pub docck_python: String,
+    /// The Python executable to use for LLDB and htmldocck.
+    pub python: String,
 
     /// The jsondocck executable.
     pub jsondocck_path: Option<String>,
index 858a576dcb4745a1ac37b8fbead9445259ef244a..e6f058569dbd8cf816823a087cf6c3b646fc9a1f 100644 (file)
@@ -157,6 +157,8 @@ pub struct TestProps {
     pub should_ice: bool,
     // If true, the stderr is expected to be different across bit-widths.
     pub stderr_per_bitwidth: bool,
+    // The MIR opt to unit test, if any
+    pub mir_unit_test: Option<String>,
 }
 
 mod directives {
@@ -189,6 +191,7 @@ mod directives {
     pub const STDERR_PER_BITWIDTH: &'static str = "stderr-per-bitwidth";
     pub const INCREMENTAL: &'static str = "incremental";
     pub const KNOWN_BUG: &'static str = "known-bug";
+    pub const MIR_UNIT_TEST: &'static str = "unit-test";
     // This isn't a real directive, just one that is probably mistyped often
     pub const INCORRECT_COMPILER_FLAGS: &'static str = "compiler-flags";
 }
@@ -232,6 +235,7 @@ pub fn new() -> Self {
             assembly_output: None,
             should_ice: false,
             stderr_per_bitwidth: false,
+            mir_unit_test: None,
         }
     }
 
@@ -392,6 +396,9 @@ fn load_from(&mut self, testfile: &Path, cfg: Option<&str>, config: &Config) {
                 config.set_name_directive(ln, STDERR_PER_BITWIDTH, &mut self.stderr_per_bitwidth);
                 config.set_name_directive(ln, INCREMENTAL, &mut self.incremental);
                 config.set_name_directive(ln, KNOWN_BUG, &mut self.known_bug);
+                config.set_name_value_directive(ln, MIR_UNIT_TEST, &mut self.mir_unit_test, |s| {
+                    s.trim().to_string()
+                });
             });
         }
 
index 5b144a1020f4c3e0f9baeb51299b3875c8e0a0af..a8fd4880f078250191547ae4c743c12e35f6630f 100644 (file)
@@ -43,8 +43,7 @@ fn config() -> Config {
         "--compile-lib-path=",
         "--run-lib-path=",
         "--rustc-path=",
-        "--lldb-python=",
-        "--docck-python=",
+        "--python=",
         "--jsondocck-path=",
         "--src-base=",
         "--build-base=",
index 8c1f28f14076887dcb110c0064beca87a8350c2b..f4e6c2a2bb288818bbad52cd3eaa7f4a89756dd1 100644 (file)
@@ -61,8 +61,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
         .reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH")
         .optopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH")
         .optopt("", "rust-demangler-path", "path to rust-demangler to use in tests", "PATH")
-        .reqopt("", "lldb-python", "path to python to use for doc tests", "PATH")
-        .reqopt("", "docck-python", "path to python to use for doc tests", "PATH")
+        .reqopt("", "python", "path to python to use for doc tests", "PATH")
         .optopt("", "jsondocck-path", "path to jsondocck to use for doc tests", "PATH")
         .optopt("", "valgrind-path", "path to Valgrind executable for Valgrind tests", "PROGRAM")
         .optflag("", "force-valgrind", "fail if Valgrind tests cannot be run under Valgrind")
@@ -222,8 +221,7 @@ fn make_absolute(path: PathBuf) -> PathBuf {
         rustc_path: opt_path(matches, "rustc-path"),
         rustdoc_path: matches.opt_str("rustdoc-path").map(PathBuf::from),
         rust_demangler_path: matches.opt_str("rust-demangler-path").map(PathBuf::from),
-        lldb_python: matches.opt_str("lldb-python").unwrap(),
-        docck_python: matches.opt_str("docck-python").unwrap(),
+        python: matches.opt_str("python").unwrap(),
         jsondocck_path: matches.opt_str("jsondocck-path"),
         valgrind_path: matches.opt_str("valgrind-path"),
         force_valgrind: matches.opt_present("force-valgrind"),
index 6b27d1ecbf550038f2846a3d1e2c4c289d1f27ff..6d94fe3ebb9cb53b76480ba6561e31dd203fe075 100644 (file)
@@ -179,7 +179,7 @@ pub fn compute_stamp_hash(config: &Config) -> String {
         }
 
         Some(Debugger::Lldb) => {
-            config.lldb_python.hash(&mut hash);
+            config.python.hash(&mut hash);
             config.lldb_python_dir.hash(&mut hash);
             env::var_os("PATH").hash(&mut hash);
             env::var_os("PYTHONPATH").hash(&mut hash);
@@ -1141,7 +1141,7 @@ fn run_lldb(
         // Prepare the lldb_batchmode which executes the debugger script
         let lldb_script_path = rust_src_root.join("src/etc/lldb_batchmode.py");
         self.cmd2procres(
-            Command::new(&self.config.lldb_python)
+            Command::new(&self.config.python)
                 .arg(&lldb_script_path)
                 .arg(test_executable)
                 .arg(debugger_script)
@@ -1856,10 +1856,14 @@ fn make_compile_args(
                 rustc.args(&[
                     "-Copt-level=1",
                     "-Zdump-mir=all",
-                    "-Zmir-opt-level=4",
                     "-Zvalidate-mir",
                     "-Zdump-mir-exclude-pass-number",
                 ]);
+                if let Some(pass) = &self.props.mir_unit_test {
+                    rustc.args(&["-Zmir-opt-level=0", &format!("-Zmir-enable-passes=+{}", pass)]);
+                } else {
+                    rustc.arg("-Zmir-opt-level=4");
+                }
 
                 let mir_dump_dir = self.get_mir_dump_dir();
                 let _ = fs::remove_dir_all(&mir_dump_dir);
@@ -2256,7 +2260,7 @@ fn run_rustdoc_test(&self) {
             self.check_rustdoc_test_option(proc_res);
         } else {
             let root = self.config.find_rust_src_root().unwrap();
-            let mut cmd = Command::new(&self.config.docck_python);
+            let mut cmd = Command::new(&self.config.python);
             cmd.arg(root.join("src/etc/htmldocck.py")).arg(&out_dir).arg(&self.testpaths.file);
             if self.config.bless {
                 cmd.arg("--bless");
@@ -2457,7 +2461,7 @@ fn run_rustdoc_json_test(&self) {
         let mut json_out = out_dir.join(self.testpaths.file.file_stem().unwrap());
         json_out.set_extension("json");
         let res = self.cmd2procres(
-            Command::new(&self.config.docck_python)
+            Command::new(&self.config.python)
                 .arg(root.join("src/etc/check_missing_items.py"))
                 .arg(&json_out),
         );
@@ -2852,7 +2856,7 @@ fn run_rmake_test(&self) {
             .stdout(Stdio::piped())
             .stderr(Stdio::piped())
             .env("TARGET", &self.config.target)
-            .env("PYTHON", &self.config.docck_python)
+            .env("PYTHON", &self.config.python)
             .env("S", src_root)
             .env("RUST_BUILD_STAGE", &self.config.stage_id)
             .env("RUSTC", cwd.join(&self.config.rustc_path))
index c568f32f165d86aba51ec544756c3c833acbabd7..edd4858846003dc96020a0de07a1499e3224e633 160000 (submodule)
@@ -1 +1 @@
-Subproject commit c568f32f165d86aba51ec544756c3c833acbabd7
+Subproject commit edd4858846003dc96020a0de07a1499e3224e633
index 46d7ee68f26285db26b2640f2c07d6332380c756..24cf957627d5ede1b395f92ff871fd7a281d49a4 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 46d7ee68f26285db26b2640f2c07d6332380c756
+Subproject commit 24cf957627d5ede1b395f92ff871fd7a281d49a4
index b8c67de26230b076666647e808401645e9174931..f074eb941dca2388e15a26d49a66b60b094de92c 100644 (file)
@@ -9,6 +9,6 @@ clap = "2.25.0"
 env_logger = "0.7.1"
 
 [dependencies.mdbook]
-version = "0.4.14"
+version = "0.4.18"
 default-features = false
 features = ["search"]
index dbf5cf9650c5f4f16098a2d11979b1bf423531c3..1736233835529a260525228f3dab6411be275fc5 100644 (file)
@@ -58,7 +58,8 @@ function extractFunction(content, functionName) {
                 } while (pos < content.length && content[pos] !== '/' && content[pos - 1] !== '*');
 
             // Eat quoted strings
-            } else if (content[pos] === '"' || content[pos] === "'" || content[pos] === "`") {
+            } else if ((content[pos] === '"' || content[pos] === "'" || content[pos] === "`") &&
+                       (pos === 0 || content[pos - 1] !== '/')) {
                 stop = content[pos];
                 do {
                     if (content[pos] === '\\') {
@@ -269,8 +270,13 @@ function loadSearchJsAndIndex(searchJs, searchIndex, storageJs, crate) {
     // execQuery last parameter is built in buildIndex.
     // buildIndex requires the hashmap from search-index.
     var functionsToLoad = ["buildHrefAndPath", "pathSplitter", "levenshtein", "validateResult",
-                           "handleAliases", "getQuery", "buildIndex", "execQuery", "execSearch",
-                           "removeEmptyStringsFromArray"];
+                           "buildIndex", "execQuery", "parseQuery", "createQueryResults",
+                           "isWhitespace", "isSpecialStartCharacter", "isStopCharacter",
+                           "parseInput", "getItemsBefore", "getNextElem", "createQueryElement",
+                           "isReturnArrow", "isPathStart", "getStringElem", "newParsedQuery",
+                           "itemTypeFromName", "isEndCharacter", "isErrorCharacter",
+                           "isIdentCharacter", "isSeparatorCharacter", "getIdentEndPosition",
+                           "checkExtraTypeFilterCharacters", "isWhitespaceCharacter"];
 
     const functions = ["hasOwnPropertyRustdoc", "onEach"];
     ALIASES = {};
@@ -286,12 +292,99 @@ function loadSearchJsAndIndex(searchJs, searchIndex, storageJs, crate) {
     return [loaded, index];
 }
 
+// This function checks if `expected` has all the required fields needed for the checks.
+function checkNeededFields(fullPath, expected, error_text, queryName, position) {
+    let fieldsToCheck;
+    if (fullPath.length === 0) {
+        fieldsToCheck = [
+            "foundElems",
+            "original",
+            "returned",
+            "typeFilter",
+            "userQuery",
+            "error",
+        ];
+    } else if (fullPath.endsWith("elems") || fullPath.endsWith("generics")) {
+        fieldsToCheck = [
+            "name",
+            "fullPath",
+            "pathWithoutLast",
+            "pathLast",
+            "generics",
+        ];
+    } else {
+        fieldsToCheck = [];
+    }
+    for (var i = 0; i < fieldsToCheck.length; ++i) {
+        const field = fieldsToCheck[i];
+        if (!expected.hasOwnProperty(field)) {
+            let text = `${queryName}==> Mandatory key \`${field}\` is not present`;
+            if (fullPath.length > 0) {
+                text += ` in field \`${fullPath}\``;
+                if (position != null) {
+                    text += ` (position ${position})`;
+                }
+            }
+            error_text.push(text);
+        }
+    }
+}
+
+function valueCheck(fullPath, expected, result, error_text, queryName) {
+    if (Array.isArray(expected)) {
+        for (var i = 0; i < expected.length; ++i) {
+            checkNeededFields(fullPath, expected[i], error_text, queryName, i);
+            if (i >= result.length) {
+                error_text.push(`${queryName}==> EXPECTED has extra value in array from field ` +
+                    `\`${fullPath}\` (position ${i}): \`${JSON.stringify(expected[i])}\``);
+            } else {
+                valueCheck(fullPath + '[' + i + ']', expected[i], result[i], error_text, queryName);
+            }
+        }
+        for (; i < result.length; ++i) {
+            error_text.push(`${queryName}==> RESULT has extra value in array from field ` +
+                `\`${fullPath}\` (position ${i}): \`${JSON.stringify(result[i])}\` ` +
+                'compared to EXPECTED');
+        }
+    } else if (expected !== null && typeof expected !== "undefined" &&
+               expected.constructor == Object)
+    {
+        for (const key in expected) {
+            if (!expected.hasOwnProperty(key)) {
+                continue;
+            }
+            if (!result.hasOwnProperty(key)) {
+                error_text.push('==> Unknown key "' + key + '"');
+                break;
+            }
+            const obj_path = fullPath + (fullPath.length > 0 ? '.' : '') + key;
+            valueCheck(obj_path, expected[key], result[key], error_text, queryName);
+        }
+    } else {
+        expectedValue = JSON.stringify(expected);
+        resultValue = JSON.stringify(result);
+        if (expectedValue != resultValue) {
+            error_text.push(`${queryName}==> Different values for field \`${fullPath}\`:\n` +
+                `EXPECTED: \`${expectedValue}\`\nRESULT:   \`${resultValue}\``);
+        }
+    }
+}
+
+function runParser(query, expected, loaded, loadedFile, queryName) {
+    var error_text = [];
+    checkNeededFields("", expected, error_text, queryName, null);
+    if (error_text.length === 0) {
+        valueCheck('', expected, loaded.parseQuery(query), error_text, queryName);
+    }
+    return error_text;
+}
+
 function runSearch(query, expected, index, loaded, loadedFile, queryName) {
     const filter_crate = loadedFile.FILTER_CRATE;
     const ignore_order = loadedFile.ignore_order;
     const exact_check = loadedFile.exact_check;
 
-    var results = loaded.execSearch(loaded.getQuery(query), index, filter_crate);
+    var results = loaded.execQuery(loaded.parseQuery(query), index, filter_crate);
     var error_text = [];
 
     for (var key in expected) {
@@ -353,40 +446,75 @@ function checkResult(error_text, loadedFile, displaySuccess) {
     return 1;
 }
 
-function runChecks(testFile, loaded, index) {
-    var testFileContent = readFile(testFile) + 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;';
-    if (testFileContent.indexOf("FILTER_CRATE") !== -1) {
-        testFileContent += "exports.FILTER_CRATE = FILTER_CRATE;";
-    } else {
-        testFileContent += "exports.FILTER_CRATE = null;";
-    }
-    var loadedFile = loadContent(testFileContent);
-
-    const expected = loadedFile.EXPECTED;
+function runCheck(loadedFile, key, callback) {
+    const expected = loadedFile[key];
     const query = loadedFile.QUERY;
 
     if (Array.isArray(query)) {
         if (!Array.isArray(expected)) {
             console.log("FAILED");
-            console.log("==> If QUERY variable is an array, EXPECTED should be an array too");
+            console.log(`==> If QUERY variable is an array, ${key} should be an array too`);
             return 1;
         } else if (query.length !== expected.length) {
             console.log("FAILED");
-            console.log("==> QUERY variable should have the same length as EXPECTED");
+            console.log(`==> QUERY variable should have the same length as ${key}`);
             return 1;
         }
         for (var i = 0; i < query.length; ++i) {
-            var error_text = runSearch(query[i], expected[i], index, loaded, loadedFile,
-                "[ query `" + query[i] + "`]");
+            var error_text = callback(query[i], expected[i], "[ query `" + query[i] + "`]");
             if (checkResult(error_text, loadedFile, false) !== 0) {
                 return 1;
             }
         }
         console.log("OK");
-        return 0;
+    } else {
+        var error_text = callback(query, expected, "");
+        if (checkResult(error_text, loadedFile, true) !== 0) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+function runChecks(testFile, loaded, index) {
+    var checkExpected = false;
+    var checkParsed = false;
+    var testFileContent = readFile(testFile) + 'exports.QUERY = QUERY;';
+
+    if (testFileContent.indexOf("FILTER_CRATE") !== -1) {
+        testFileContent += "exports.FILTER_CRATE = FILTER_CRATE;";
+    } else {
+        testFileContent += "exports.FILTER_CRATE = null;";
+    }
+
+    if (testFileContent.indexOf("\nconst EXPECTED") !== -1) {
+        testFileContent += 'exports.EXPECTED = EXPECTED;';
+        checkExpected = true;
+    }
+    if (testFileContent.indexOf("\nconst PARSED") !== -1) {
+        testFileContent += 'exports.PARSED = PARSED;';
+        checkParsed = true;
+    }
+    if (!checkParsed && !checkExpected) {
+        console.log("FAILED");
+        console.log("==> At least `PARSED` or `EXPECTED` is needed!");
+        return 1;
+    }
+
+    const loadedFile = loadContent(testFileContent);
+    var res = 0;
+
+    if (checkExpected) {
+        res += runCheck(loadedFile, "EXPECTED", (query, expected, text) => {
+            return runSearch(query, expected, index, loaded, loadedFile, text);
+        });
+    }
+    if (checkParsed) {
+        res += runCheck(loadedFile, "PARSED", (query, expected, text) => {
+            return runParser(query, expected, loaded, loadedFile, text);
+        });
     }
-    var error_text = runSearch(query, expected, index, loaded, loadedFile, "");
-    return checkResult(error_text, loadedFile, true);
+    return res;
 }
 
 function load_files(doc_folder, resource_suffix, crate) {
index 92f423bbb6275d647e6116a5ca6f6d1c48e8693d..ad2502b041840ca04036fe025f2b299532f6292c 100644 (file)
@@ -204,12 +204,11 @@ pub(crate) fn from_method_sig(
 
     pub(crate) fn from_fn_kind(
         fn_kind: &'a visit::FnKind<'_>,
-        generics: &'a ast::Generics,
         decl: &'a ast::FnDecl,
         defaultness: ast::Defaultness,
     ) -> FnSig<'a> {
         match *fn_kind {
-            visit::FnKind::Fn(fn_ctxt, _, fn_sig, vis, _) => match fn_ctxt {
+            visit::FnKind::Fn(fn_ctxt, _, fn_sig, vis, generics, _) => match fn_ctxt {
                 visit::FnCtxt::Assoc(..) => {
                     let mut fn_sig = FnSig::from_method_sig(fn_sig, generics, vis);
                     fn_sig.defaultness = defaultness;
@@ -3180,8 +3179,14 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                     let inner_attrs = inner_attributes(&self.attrs);
                     let fn_ctxt = visit::FnCtxt::Foreign;
                     visitor.visit_fn(
-                        visit::FnKind::Fn(fn_ctxt, self.ident, sig, &self.vis, Some(body)),
-                        generics,
+                        visit::FnKind::Fn(
+                            fn_ctxt,
+                            self.ident,
+                            sig,
+                            &self.vis,
+                            generics,
+                            Some(body),
+                        ),
                         &sig.decl,
                         self.span,
                         defaultness,
index 3ebfa551d1cbc2e17ca5eac859328fdddb8e3421..1621eb406b10f35514e24ae78cdc466fbd92d662 100644 (file)
@@ -382,7 +382,6 @@ fn unindent_comment_on_closing_brace(&self, b: &ast::Block) -> bool {
     pub(crate) fn visit_fn(
         &mut self,
         fk: visit::FnKind<'_>,
-        generics: &ast::Generics,
         fd: &ast::FnDecl,
         s: Span,
         defaultness: ast::Defaultness,
@@ -391,12 +390,12 @@ pub(crate) fn visit_fn(
         let indent = self.block_indent;
         let block;
         let rewrite = match fk {
-            visit::FnKind::Fn(_, ident, _, _, Some(ref b)) => {
+            visit::FnKind::Fn(_, ident, _, _, _, Some(ref b)) => {
                 block = b;
                 self.rewrite_fn_before_block(
                     indent,
                     ident,
-                    &FnSig::from_fn_kind(&fk, generics, fd, defaultness),
+                    &FnSig::from_fn_kind(&fk, fd, defaultness),
                     mk_sp(s.lo(), b.span.lo()),
                 )
             }
@@ -552,8 +551,14 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) {
                             _ => visit::FnCtxt::Foreign,
                         };
                         self.visit_fn(
-                            visit::FnKind::Fn(fn_ctxt, item.ident, sig, &item.vis, Some(body)),
-                            generics,
+                            visit::FnKind::Fn(
+                                fn_ctxt,
+                                item.ident,
+                                sig,
+                                &item.vis,
+                                generics,
+                                Some(body),
+                            ),
                             &sig.decl,
                             item.span,
                             defaultness,
@@ -642,8 +647,7 @@ fn visit_assoc_item(&mut self, visitor_kind: &ItemVisitorKind<'_>) {
                     let inner_attrs = inner_attributes(&ai.attrs);
                     let fn_ctxt = visit::FnCtxt::Assoc(assoc_ctxt);
                     self.visit_fn(
-                        visit::FnKind::Fn(fn_ctxt, ai.ident, sig, &ai.vis, Some(body)),
-                        generics,
+                        visit::FnKind::Fn(fn_ctxt, ai.ident, sig, &ai.vis, generics, Some(body)),
                         &sig.decl,
                         ai.span,
                         defaultness,
index ea6e01e577c6bfd3fa56740ce8d72c1a9a1a42ef..3f776b70b14c771fdb1b36008b3850d50d478769 100644 (file)
@@ -42,6 +42,9 @@
     ("self_cell", "Apache-2.0"),      // rustc (fluent translations)
     // FIXME: this dependency violates the documentation comment above:
     ("fortanix-sgx-abi", "MPL-2.0"), // libstd but only for `sgx` target
+    ("dunce", "CC0-1.0"),            // cargo (dev dependency)
+    ("similar", "Apache-2.0"),       // cargo (dev dependency)
+    ("normalize-line-endings", "Apache-2.0"), // cargo (dev dependency)
 ];
 
 const EXCEPTIONS_CRANELIFT: &[(&str, &str)] = &[
index 63a8909c6627ab6b7fa97f1f6c7252b826b6828d..d823b412c5992518ee98d5b434e43201582a9a3c 100644 (file)
@@ -8,7 +8,7 @@
 const ENTRY_LIMIT: usize = 1000;
 // FIXME: The following limits should be reduced eventually.
 const ROOT_ENTRY_LIMIT: usize = 986;
-const ISSUES_ENTRY_LIMIT: usize = 2310;
+const ISSUES_ENTRY_LIMIT: usize = 2292;
 
 fn check_entries(path: &Path, bad: &mut bool) {
     let dirs = walkdir::WalkDir::new(&path.join("test/ui"))