]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #78086 - poliorcetics:as-placeholder, r=Mark-Simulacrum
authorJonas Schievink <jonasschievink@gmail.com>
Sat, 28 Nov 2020 14:58:13 +0000 (15:58 +0100)
committerGitHub <noreply@github.com>
Sat, 28 Nov 2020 14:58:13 +0000 (15:58 +0100)
Improve doc for 'as _'

Fix #78042.

`@rustbot` modify labels: A-coercions T-doc

1162 files changed:
.gitattributes
.mailmap
Cargo.lock
compiler/rustc_arena/src/lib.rs
compiler/rustc_ast/src/ast.rs
compiler/rustc_ast/src/lib.rs
compiler/rustc_ast/src/mut_visit.rs
compiler/rustc_ast/src/token.rs
compiler/rustc_ast/src/tokenstream.rs
compiler/rustc_ast/src/util/lev_distance.rs [deleted file]
compiler/rustc_ast/src/util/lev_distance/tests.rs [deleted file]
compiler/rustc_ast/src/visit.rs
compiler/rustc_ast_lowering/src/expr.rs
compiler/rustc_ast_lowering/src/item.rs
compiler/rustc_ast_lowering/src/lib.rs
compiler/rustc_ast_passes/src/ast_validation.rs
compiler/rustc_ast_passes/src/feature_gate.rs
compiler/rustc_ast_passes/src/lib.rs
compiler/rustc_attr/src/builtin.rs
compiler/rustc_builtin_macros/src/assert.rs
compiler/rustc_builtin_macros/src/cfg_accessible.rs
compiler/rustc_builtin_macros/src/deriving/debug.rs
compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
compiler/rustc_builtin_macros/src/deriving/mod.rs
compiler/rustc_builtin_macros/src/format_foreign.rs
compiler/rustc_builtin_macros/src/global_allocator.rs
compiler/rustc_builtin_macros/src/test.rs
compiler/rustc_codegen_cranelift/build_sysroot/alloc_system/lib.rs
compiler/rustc_codegen_cranelift/example/mini_core.rs
compiler/rustc_codegen_llvm/src/abi.rs
compiler/rustc_codegen_llvm/src/attributes.rs
compiler/rustc_codegen_llvm/src/back/write.rs
compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
compiler/rustc_codegen_llvm/src/llvm/ffi.rs
compiler/rustc_codegen_llvm/src/llvm/mod.rs
compiler/rustc_codegen_ssa/src/back/link.rs
compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs
compiler/rustc_codegen_ssa/src/mir/block.rs
compiler/rustc_data_structures/src/fingerprint.rs
compiler/rustc_data_structures/src/graph/scc/mod.rs
compiler/rustc_data_structures/src/graph/scc/tests.rs
compiler/rustc_data_structures/src/lib.rs
compiler/rustc_driver/src/lib.rs
compiler/rustc_error_codes/src/error_codes/E0198.md
compiler/rustc_error_codes/src/error_codes/E0321.md
compiler/rustc_error_codes/src/error_codes/E0567.md
compiler/rustc_error_codes/src/error_codes/E0568.md
compiler/rustc_expand/src/base.rs
compiler/rustc_expand/src/build.rs
compiler/rustc_expand/src/config.rs
compiler/rustc_expand/src/expand.rs
compiler/rustc_expand/src/mbe/macro_rules.rs
compiler/rustc_expand/src/placeholders.rs
compiler/rustc_expand/src/proc_macro.rs
compiler/rustc_feature/src/active.rs
compiler/rustc_feature/src/removed.rs
compiler/rustc_hir/src/arena.rs
compiler/rustc_hir/src/def.rs
compiler/rustc_hir/src/hir.rs
compiler/rustc_hir/src/intravisit.rs
compiler/rustc_hir/src/itemlikevisit.rs
compiler/rustc_hir/src/stable_hash_impls.rs
compiler/rustc_hir/src/target.rs
compiler/rustc_hir_pretty/src/lib.rs
compiler/rustc_incremental/src/persist/dirty_clean.rs
compiler/rustc_incremental/src/persist/load.rs
compiler/rustc_index/src/lib.rs
compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
compiler/rustc_infer/src/traits/util.rs
compiler/rustc_interface/Cargo.toml
compiler/rustc_interface/src/interface.rs
compiler/rustc_interface/src/passes.rs
compiler/rustc_interface/src/proc_macro_decls.rs
compiler/rustc_interface/src/tests.rs
compiler/rustc_interface/src/util.rs
compiler/rustc_lint/Cargo.toml
compiler/rustc_lint/src/builtin.rs
compiler/rustc_lint/src/context.rs
compiler/rustc_lint/src/lib.rs
compiler/rustc_lint/src/nonstandard_style.rs
compiler/rustc_lint/src/panic_fmt.rs [new file with mode: 0644]
compiler/rustc_lint/src/redundant_semicolon.rs
compiler/rustc_lint/src/types.rs
compiler/rustc_lint/src/unused.rs
compiler/rustc_lint_defs/src/builtin.rs
compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
compiler/rustc_macros/src/query.rs
compiler/rustc_metadata/src/foreign_modules.rs
compiler/rustc_metadata/src/lib.rs
compiler/rustc_metadata/src/link_args.rs
compiler/rustc_metadata/src/native_libs.rs
compiler/rustc_metadata/src/rmeta/decoder.rs
compiler/rustc_metadata/src/rmeta/encoder.rs
compiler/rustc_metadata/src/rmeta/mod.rs
compiler/rustc_middle/src/dep_graph/dep_node.rs
compiler/rustc_middle/src/dep_graph/mod.rs
compiler/rustc_middle/src/hir/map/collector.rs
compiler/rustc_middle/src/hir/map/mod.rs
compiler/rustc_middle/src/mir/coverage.rs
compiler/rustc_middle/src/mir/mod.rs
compiler/rustc_middle/src/mir/visit.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/traits/mod.rs
compiler/rustc_middle/src/traits/select.rs
compiler/rustc_middle/src/traits/structural_impls.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/instance.rs
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_middle/src/ty/query/plumbing.rs
compiler/rustc_middle/src/ty/sty.rs
compiler/rustc_mir/src/interpret/intrinsics.rs
compiler/rustc_mir/src/interpret/util.rs
compiler/rustc_mir/src/monomorphize/collector.rs
compiler/rustc_mir/src/shim.rs
compiler/rustc_mir/src/transform/check_consts/validation.rs
compiler/rustc_mir/src/transform/const_prop.rs
compiler/rustc_mir/src/transform/coverage/debug.rs
compiler/rustc_mir/src/transform/early_otherwise_branch.rs
compiler/rustc_mir/src/transform/inline.rs
compiler/rustc_mir/src/transform/instcombine.rs
compiler/rustc_mir/src/transform/lower_intrinsics.rs
compiler/rustc_mir/src/transform/match_branches.rs
compiler/rustc_mir/src/transform/multiple_return_terminators.rs
compiler/rustc_mir/src/transform/nrvo.rs
compiler/rustc_mir/src/transform/remove_unneeded_drops.rs
compiler/rustc_mir/src/transform/unreachable_prop.rs
compiler/rustc_mir/src/transform/validate.rs
compiler/rustc_mir_build/src/build/expr/as_place.rs
compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
compiler/rustc_mir_build/src/build/expr/category.rs
compiler/rustc_mir_build/src/build/expr/into.rs
compiler/rustc_mir_build/src/thir/cx/expr.rs
compiler/rustc_mir_build/src/thir/cx/mod.rs
compiler/rustc_mir_build/src/thir/mod.rs
compiler/rustc_mir_build/src/thir/pattern/_match.rs [deleted file]
compiler/rustc_mir_build/src/thir/pattern/check_match.rs
compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs [new file with mode: 0644]
compiler/rustc_mir_build/src/thir/pattern/mod.rs
compiler/rustc_mir_build/src/thir/pattern/usefulness.rs [new file with mode: 0644]
compiler/rustc_parse/src/lexer/mod.rs
compiler/rustc_parse/src/lib.rs
compiler/rustc_parse/src/parser/attr.rs
compiler/rustc_parse/src/parser/diagnostics.rs
compiler/rustc_parse/src/parser/mod.rs
compiler/rustc_parse/src/parser/nonterminal.rs
compiler/rustc_parse/src/parser/path.rs
compiler/rustc_parse/src/parser/stmt.rs
compiler/rustc_passes/src/check_attr.rs
compiler/rustc_passes/src/dead.rs
compiler/rustc_passes/src/diagnostic_items.rs
compiler/rustc_passes/src/entry.rs
compiler/rustc_passes/src/hir_id_validator.rs
compiler/rustc_passes/src/lang_items.rs
compiler/rustc_passes/src/layout_test.rs
compiler/rustc_passes/src/lib.rs
compiler/rustc_passes/src/naked_functions.rs [new file with mode: 0644]
compiler/rustc_passes/src/reachable.rs
compiler/rustc_passes/src/stability.rs
compiler/rustc_plugin_impl/src/build.rs
compiler/rustc_privacy/src/lib.rs
compiler/rustc_query_system/src/dep_graph/dep_node.rs
compiler/rustc_query_system/src/dep_graph/graph.rs
compiler/rustc_query_system/src/query/job.rs
compiler/rustc_resolve/src/build_reduced_graph.rs
compiler/rustc_resolve/src/diagnostics.rs
compiler/rustc_resolve/src/imports.rs
compiler/rustc_resolve/src/late/diagnostics.rs
compiler/rustc_resolve/src/late/lifetimes.rs
compiler/rustc_resolve/src/lib.rs
compiler/rustc_resolve/src/macros.rs
compiler/rustc_save_analysis/src/sig.rs
compiler/rustc_session/src/options.rs
compiler/rustc_session/src/session.rs
compiler/rustc_span/src/lev_distance.rs [new file with mode: 0644]
compiler/rustc_span/src/lev_distance/tests.rs [new file with mode: 0644]
compiler/rustc_span/src/lib.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_symbol_mangling/src/test.rs
compiler/rustc_target/src/abi/call/mips64.rs
compiler/rustc_target/src/abi/call/mod.rs
compiler/rustc_target/src/abi/call/riscv.rs
compiler/rustc_target/src/abi/call/x86.rs
compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs [new file with mode: 0644]
compiler/rustc_target/src/spec/aarch64_unknown_cloudabi.rs [deleted file]
compiler/rustc_target/src/spec/apple_sdk_base.rs
compiler/rustc_target/src/spec/armv7_unknown_cloudabi_eabihf.rs [deleted file]
compiler/rustc_target/src/spec/cloudabi_base.rs [deleted file]
compiler/rustc_target/src/spec/i686_unknown_cloudabi.rs [deleted file]
compiler/rustc_target/src/spec/mod.rs
compiler/rustc_target/src/spec/x86_64_unknown_cloudabi.rs [deleted file]
compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
compiler/rustc_trait_selection/src/traits/project.rs
compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
compiler/rustc_trait_selection/src/traits/select/confirmation.rs
compiler/rustc_trait_selection/src/traits/select/mod.rs
compiler/rustc_trait_selection/src/traits/specialize/mod.rs
compiler/rustc_trait_selection/src/traits/util.rs
compiler/rustc_trait_selection/src/traits/wf.rs
compiler/rustc_ty/Cargo.toml [deleted file]
compiler/rustc_ty/src/common_traits.rs [deleted file]
compiler/rustc_ty/src/instance.rs [deleted file]
compiler/rustc_ty/src/lib.rs [deleted file]
compiler/rustc_ty/src/needs_drop.rs [deleted file]
compiler/rustc_ty/src/ty.rs [deleted file]
compiler/rustc_ty_utils/Cargo.toml [new file with mode: 0644]
compiler/rustc_ty_utils/src/common_traits.rs [new file with mode: 0644]
compiler/rustc_ty_utils/src/instance.rs [new file with mode: 0644]
compiler/rustc_ty_utils/src/lib.rs [new file with mode: 0644]
compiler/rustc_ty_utils/src/needs_drop.rs [new file with mode: 0644]
compiler/rustc_ty_utils/src/ty.rs [new file with mode: 0644]
compiler/rustc_typeck/src/astconv/errors.rs
compiler/rustc_typeck/src/astconv/mod.rs
compiler/rustc_typeck/src/check/check.rs
compiler/rustc_typeck/src/check/demand.rs
compiler/rustc_typeck/src/check/expr.rs
compiler/rustc_typeck/src/check/method/probe.rs
compiler/rustc_typeck/src/check/method/suggest.rs
compiler/rustc_typeck/src/check/mod.rs
compiler/rustc_typeck/src/check/pat.rs
compiler/rustc_typeck/src/check/wfcheck.rs
compiler/rustc_typeck/src/check/writeback.rs
compiler/rustc_typeck/src/check_unused.rs
compiler/rustc_typeck/src/coherence/inherent_impls.rs
compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs
compiler/rustc_typeck/src/coherence/orphan.rs
compiler/rustc_typeck/src/coherence/unsafety.rs
compiler/rustc_typeck/src/collect.rs
compiler/rustc_typeck/src/collect/type_of.rs
compiler/rustc_typeck/src/impl_wf_check.rs
compiler/rustc_typeck/src/outlives/implicit_infer.rs
compiler/rustc_typeck/src/outlives/test.rs
compiler/rustc_typeck/src/variance/constraints.rs
compiler/rustc_typeck/src/variance/terms.rs
compiler/rustc_typeck/src/variance/test.rs
config.toml.example
library/alloc/src/alloc.rs
library/alloc/src/boxed.rs
library/alloc/src/collections/btree/append.rs
library/alloc/src/collections/btree/map.rs
library/alloc/src/collections/btree/map/entry.rs
library/alloc/src/collections/btree/map/tests.rs
library/alloc/src/collections/btree/map/tests/ord_chaos.rs
library/alloc/src/collections/btree/node.rs
library/alloc/src/collections/btree/node/tests.rs
library/alloc/src/collections/btree/search.rs
library/alloc/src/collections/btree/set.rs
library/alloc/src/collections/btree/set/tests.rs
library/alloc/src/collections/btree/split.rs
library/alloc/src/collections/vec_deque/mod.rs
library/alloc/src/lib.rs
library/alloc/src/raw_vec.rs
library/alloc/src/slice.rs
library/alloc/src/vec.rs
library/alloc/tests/vec.rs
library/backtrace
library/core/src/alloc/layout.rs
library/core/src/array/iter.rs
library/core/src/bool.rs
library/core/src/cell.rs
library/core/src/cmp.rs
library/core/src/fmt/mod.rs
library/core/src/future/poll_fn.rs
library/core/src/intrinsics.rs
library/core/src/iter/adapters/chain.rs
library/core/src/iter/adapters/cloned.rs [new file with mode: 0644]
library/core/src/iter/adapters/copied.rs [new file with mode: 0644]
library/core/src/iter/adapters/cycle.rs [new file with mode: 0644]
library/core/src/iter/adapters/enumerate.rs [new file with mode: 0644]
library/core/src/iter/adapters/filter.rs [new file with mode: 0644]
library/core/src/iter/adapters/filter_map.rs [new file with mode: 0644]
library/core/src/iter/adapters/flatten.rs
library/core/src/iter/adapters/fuse.rs
library/core/src/iter/adapters/inspect.rs [new file with mode: 0644]
library/core/src/iter/adapters/map.rs [new file with mode: 0644]
library/core/src/iter/adapters/map_while.rs [new file with mode: 0644]
library/core/src/iter/adapters/mod.rs
library/core/src/iter/adapters/peekable.rs [new file with mode: 0644]
library/core/src/iter/adapters/rev.rs [new file with mode: 0644]
library/core/src/iter/adapters/scan.rs [new file with mode: 0644]
library/core/src/iter/adapters/skip.rs [new file with mode: 0644]
library/core/src/iter/adapters/skip_while.rs [new file with mode: 0644]
library/core/src/iter/adapters/step_by.rs [new file with mode: 0644]
library/core/src/iter/adapters/take.rs [new file with mode: 0644]
library/core/src/iter/adapters/take_while.rs [new file with mode: 0644]
library/core/src/iter/adapters/zip.rs
library/core/src/iter/mod.rs
library/core/src/iter/sources.rs
library/core/src/iter/sources/empty.rs [new file with mode: 0644]
library/core/src/iter/sources/from_fn.rs [new file with mode: 0644]
library/core/src/iter/sources/once.rs [new file with mode: 0644]
library/core/src/iter/sources/once_with.rs [new file with mode: 0644]
library/core/src/iter/sources/repeat.rs [new file with mode: 0644]
library/core/src/iter/sources/repeat_with.rs [new file with mode: 0644]
library/core/src/iter/sources/successors.rs [new file with mode: 0644]
library/core/src/lib.rs
library/core/src/macros/mod.rs
library/core/src/marker.rs
library/core/src/mem/maybe_uninit.rs
library/core/src/num/f32.rs
library/core/src/num/f64.rs
library/core/src/num/int_macros.rs
library/core/src/num/uint_macros.rs
library/core/src/ops/index.rs
library/core/src/panicking.rs
library/core/src/ptr/mod.rs
library/core/src/slice/memchr.rs
library/core/src/slice/mod.rs
library/core/src/str/converts.rs
library/core/src/str/mod.rs
library/core/src/str/validations.rs
library/core/src/sync/atomic.rs
library/core/src/task/wake.rs
library/core/tests/iter.rs
library/core/tests/lib.rs
library/core/tests/nonzero.rs
library/core/tests/num/i128.rs [new file with mode: 0644]
library/core/tests/num/int_macros.rs
library/core/tests/num/mod.rs
library/core/tests/num/u128.rs [new file with mode: 0644]
library/core/tests/num/uint_macros.rs
library/core/tests/ptr.rs
library/panic_abort/src/lib.rs
library/panic_unwind/src/lib.rs
library/proc_macro/src/bridge/client.rs
library/proc_macro/src/bridge/scoped_cell.rs
library/proc_macro/src/lib.rs
library/proc_macro/tests/test.rs
library/rtstartup/rsbegin.rs
library/rtstartup/rsend.rs
library/std/Cargo.toml
library/std/build.rs
library/std/src/f32.rs
library/std/src/f64.rs
library/std/src/ffi/c_str.rs
library/std/src/fs.rs
library/std/src/keyword_docs.rs
library/std/src/lib.rs
library/std/src/macros.rs
library/std/src/net/ip.rs
library/std/src/net/tcp.rs
library/std/src/net/udp.rs
library/std/src/num/tests.rs
library/std/src/process.rs
library/std/src/sys/cloudabi/abi/bitflags.rs [deleted file]
library/std/src/sys/cloudabi/abi/cloudabi.rs [deleted file]
library/std/src/sys/cloudabi/abi/mod.rs [deleted file]
library/std/src/sys/cloudabi/args.rs [deleted file]
library/std/src/sys/cloudabi/condvar.rs [deleted file]
library/std/src/sys/cloudabi/io.rs [deleted file]
library/std/src/sys/cloudabi/mod.rs [deleted file]
library/std/src/sys/cloudabi/mutex.rs [deleted file]
library/std/src/sys/cloudabi/os.rs [deleted file]
library/std/src/sys/cloudabi/rwlock.rs [deleted file]
library/std/src/sys/cloudabi/shims/args.rs [deleted file]
library/std/src/sys/cloudabi/shims/env.rs [deleted file]
library/std/src/sys/cloudabi/shims/fs.rs [deleted file]
library/std/src/sys/cloudabi/shims/mod.rs [deleted file]
library/std/src/sys/cloudabi/shims/net.rs [deleted file]
library/std/src/sys/cloudabi/shims/os.rs [deleted file]
library/std/src/sys/cloudabi/shims/pipe.rs [deleted file]
library/std/src/sys/cloudabi/shims/process.rs [deleted file]
library/std/src/sys/cloudabi/stack_overflow.rs [deleted file]
library/std/src/sys/cloudabi/stdio.rs [deleted file]
library/std/src/sys/cloudabi/thread.rs [deleted file]
library/std/src/sys/cloudabi/time.rs [deleted file]
library/std/src/sys/hermit/fs.rs
library/std/src/sys/mod.rs
library/std/src/sys/sgx/ext/io.rs
library/std/src/sys/sgx/net.rs
library/std/src/sys/unix/ext/fs.rs
library/std/src/sys/unix/fs.rs
library/std/src/sys/unix/weak.rs
library/std/src/sys/unsupported/fs.rs
library/std/src/sys/wasi/fs.rs
library/std/src/sys/windows/compat.rs
library/std/src/sys/windows/ext/fs.rs
library/std/src/sys/windows/fs.rs
library/std/src/sys_common/mod.rs
library/std/src/thread/available_concurrency.rs
library/std/src/time.rs
library/test/Cargo.toml
library/test/src/lib.rs
library/unwind/build.rs
library/unwind/src/lib.rs
rustfmt.toml
src/bootstrap/bootstrap.py
src/bootstrap/config.rs
src/bootstrap/configure.py
src/bootstrap/lib.rs
src/bootstrap/test.rs
src/ci/docker/host-x86_64/dist-powerpc64le-linux/build-powerpc64le-toolchain.sh
src/ci/docker/host-x86_64/dist-various-2/build-cloudabi-toolchain.sh [deleted file]
src/doc/rustc/src/SUMMARY.md
src/doc/rustc/src/exploit-mitigations.md [new file with mode: 0644]
src/doc/rustc/src/images/image1.png [new file with mode: 0644]
src/doc/rustc/src/images/image2.png [new file with mode: 0644]
src/doc/rustc/src/images/image3.png [new file with mode: 0644]
src/doc/rustc/src/platform-support.md
src/doc/unstable-book/src/language-features/auto-traits.md [new file with mode: 0644]
src/doc/unstable-book/src/language-features/optin-builtin-traits.md [deleted file]
src/etc/gdb_providers.py
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/clean/utils.rs
src/librustdoc/core.rs
src/librustdoc/doctest.rs
src/librustdoc/doctree.rs
src/librustdoc/fold.rs
src/librustdoc/formats/cache.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/render/mod.rs
src/librustdoc/html/sources.rs
src/librustdoc/html/static/main.js
src/librustdoc/html/static/rustdoc.css
src/librustdoc/lib.rs
src/librustdoc/passes/calculate_doc_coverage.rs
src/librustdoc/passes/check_code_block_syntax.rs
src/librustdoc/passes/collapse_docs.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/passes/collect_trait_impls.rs
src/librustdoc/passes/doc_test_lints.rs
src/librustdoc/passes/html_tags.rs
src/librustdoc/passes/non_autolinks.rs
src/librustdoc/passes/propagate_doc_cfg.rs
src/librustdoc/passes/strip_hidden.rs
src/librustdoc/passes/stripper.rs
src/librustdoc/passes/unindent_comments.rs
src/librustdoc/visit_ast.rs
src/stage0.txt
src/test/codegen/dllimports/main.rs
src/test/codegen/fewer-names.rs [new file with mode: 0644]
src/test/codegen/naked-functions.rs
src/test/codegen/naked-noinline.rs [new file with mode: 0644]
src/test/codegen/panic-abort-windows.rs
src/test/codegen/to_vec.rs [new file with mode: 0644]
src/test/debuginfo/pretty-std-collections.rs
src/test/debuginfo/pretty-std.rs
src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs
src/test/incremental/change_add_field/struct_point.rs
src/test/incremental/change_private_impl_method/struct_point.rs
src/test/incremental/change_pub_inherent_method_body/struct_point.rs
src/test/incremental/change_pub_inherent_method_sig/struct_point.rs
src/test/incremental/hashes/extern_mods.rs
src/test/incremental/issue-49595/issue-49595.rs
src/test/mir-opt/inst_combine_deref.do_not_miscompile.InstCombine.diff
src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff
src/test/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff [new file with mode: 0644]
src/test/mir-opt/lower_intrinsics.rs
src/test/pretty/auto-trait.rs
src/test/run-make-fulldeps/coverage-llvmir-base/Makefile
src/test/run-make-fulldeps/coverage-llvmir-base/filecheck.testprog.txt
src/test/run-make-fulldeps/coverage-reports-base/Makefile
src/test/run-make-fulldeps/coverage-spanview-base/Makefile
src/test/run-make-fulldeps/coverage/coverage_tools.mk
src/test/run-make-fulldeps/simd-ffi/simd.rs
src/test/run-make-fulldeps/target-specs/foo.rs
src/test/run-pass-valgrind/exit-flushes.rs
src/test/rustdoc-js/doc-alias-filter-out.rs
src/test/rustdoc-js/doc-alias-filter.rs
src/test/rustdoc-js/doc-alias-whitespace.rs
src/test/rustdoc-js/doc-alias.rs
src/test/rustdoc-ui/check-doc-alias-attr-location.rs
src/test/rustdoc-ui/check-doc-alias-attr-location.stderr
src/test/rustdoc-ui/check-doc-alias-attr.rs
src/test/rustdoc-ui/check-doc-alias-attr.stderr
src/test/rustdoc-ui/coverage/exotic.stdout
src/test/rustdoc-ui/doc-alias-assoc-const.rs
src/test/rustdoc-ui/doc-alias-assoc-const.stderr
src/test/rustdoc-ui/doc-test-doctest-feature.rs
src/test/rustdoc-ui/doc-test-doctest-feature.stdout
src/test/rustdoc-ui/doc-without-codeblock.stderr
src/test/rustdoc-ui/intra-link-errors.stderr
src/test/rustdoc-ui/intra-links-ambiguity.stderr
src/test/rustdoc-ui/intra-links-warning.stderr
src/test/rustdoc-ui/lint-missing-doc-code-example.stderr
src/test/rustdoc/auto-traits.rs
src/test/rustdoc/auto_aliases.rs
src/test/rustdoc/auxiliary/auto-traits.rs
src/test/rustdoc/auxiliary/normalize-assoc-item.rs [new file with mode: 0644]
src/test/rustdoc/auxiliary/rustdoc-default-impl.rs
src/test/rustdoc/auxiliary/rustdoc-impl-parts-crosscrate.rs
src/test/rustdoc/deprecated-future.rs
src/test/rustdoc/deprecated.rs
src/test/rustdoc/impl-parts-crosscrate.rs
src/test/rustdoc/impl-parts.rs
src/test/rustdoc/inline_cross/impl_trait.rs
src/test/rustdoc/intra-doc-link-generic-params.rs
src/test/rustdoc/intra-link-extern-type.rs [new file with mode: 0644]
src/test/rustdoc/issue-76501.rs
src/test/rustdoc/normalize-assoc-item.rs [new file with mode: 0644]
src/test/rustdoc/redirect-rename.rs
src/test/rustdoc/synthetic_auto/crate-local.rs
src/test/rustdoc/trait-src-link.rs [new file with mode: 0644]
src/test/ui/abi/issues/issue-22565-rust-call.rs [new file with mode: 0644]
src/test/ui/abi/issues/issue-22565-rust-call.stderr [new file with mode: 0644]
src/test/ui/abi/rustcall-generic.rs [new file with mode: 0644]
src/test/ui/abi/segfault-no-out-of-stack.rs
src/test/ui/abi/stack-probes-lto.rs
src/test/ui/abi/stack-probes.rs
src/test/ui/allocator/no_std-alloc-error-handler-custom.rs
src/test/ui/allocator/no_std-alloc-error-handler-default.rs
src/test/ui/asm/naked-invalid-attr.rs [new file with mode: 0644]
src/test/ui/asm/naked-invalid-attr.stderr [new file with mode: 0644]
src/test/ui/asm/naked-params.rs [new file with mode: 0644]
src/test/ui/asm/naked-params.stderr [new file with mode: 0644]
src/test/ui/associated-type-bounds/dyn-impl-trait-type.rs
src/test/ui/associated-type-bounds/dyn-lcsit.rs
src/test/ui/associated-type-bounds/dyn-rpit-and-let.rs
src/test/ui/associated-type-bounds/lcsit.rs
src/test/ui/associated-type-bounds/rpit.rs
src/test/ui/associated-type-bounds/trait-alias-impl-trait.rs
src/test/ui/associated-types/defaults-wf.stderr
src/test/ui/async-await/issue-64130-3-other.rs
src/test/ui/atomic-print.rs
src/test/ui/attrs-resolution-errors.rs
src/test/ui/attrs-resolution-errors.stderr
src/test/ui/auto-traits/auto-trait-validation.rs
src/test/ui/auto-traits/auto-traits.rs
src/test/ui/auto-traits/issue-23080-2.rs
src/test/ui/auto-traits/issue-23080.rs
src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs
src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.rs
src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.rs
src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types.rs
src/test/ui/auto-traits/typeck-default-trait-impl-negation.rs
src/test/ui/auto-traits/typeck-default-trait-impl-precedence.rs
src/test/ui/auxiliary/fancy-panic.rs [new file with mode: 0644]
src/test/ui/backtrace-debuginfo.rs
src/test/ui/backtrace.rs
src/test/ui/bad/bad-sized.stderr
src/test/ui/cfg/cfg-family.rs
src/test/ui/cfg/cfg-target-family.rs
src/test/ui/cleanup-shortcircuit.rs
src/test/ui/coherence/coherence-default-trait-impl.rs
src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs
src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs
src/test/ui/command/command-argv0-debug.rs
src/test/ui/command/command-argv0.rs
src/test/ui/command/command-exec.rs
src/test/ui/command/command-pre-exec.rs
src/test/ui/command/command-uid-gid.rs
src/test/ui/conditional-compilation/cfg-generic-params.stderr
src/test/ui/conditional-compilation/cfg_accessible-stuck.rs
src/test/ui/conditional-compilation/cfg_accessible-stuck.stderr
src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr
src/test/ui/const-generics/const-arg-in-const-arg.min.stderr
src/test/ui/const-generics/const-argument-if-length.min.stderr
src/test/ui/const-generics/const-param-before-other-params.min.stderr
src/test/ui/const-generics/const-param-elided-lifetime.min.stderr
src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr
src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.min.stderr
src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr
src/test/ui/const-generics/const_evaluatable_checked/simple_fail.min.stderr
src/test/ui/const-generics/different_byref.min.stderr
src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr
src/test/ui/const-generics/generic-function-call-in-array-length.min.stderr
src/test/ui/const-generics/generic-sum-in-array-length.min.stderr
src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr
src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr
src/test/ui/const-generics/infer/issue-77092.stderr
src/test/ui/const-generics/infer/method-chain.full.stderr
src/test/ui/const-generics/infer/method-chain.min.stderr
src/test/ui/const-generics/infer/one-param-uninferred.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/infer/one-param-uninferred.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/infer/one-param-uninferred.rs [new file with mode: 0644]
src/test/ui/const-generics/infer/uninferred-consts.full.stderr
src/test/ui/const-generics/infer/uninferred-consts.min.stderr
src/test/ui/const-generics/infer/uninferred-consts.rs
src/test/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr
src/test/ui/const-generics/invalid-constant-in-args.rs
src/test/ui/const-generics/invalid-constant-in-args.stderr
src/test/ui/const-generics/issue-61522-array-len-succ.min.stderr
src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr
src/test/ui/const-generics/issue-67375.min.stderr
src/test/ui/const-generics/issue-67945-1.min.stderr
src/test/ui/const-generics/issue-67945-2.min.stderr
src/test/ui/const-generics/issues/issue-61747.min.stderr
src/test/ui/const-generics/issues/issue-61935.min.stderr
src/test/ui/const-generics/issues/issue-62220.min.stderr
src/test/ui/const-generics/issues/issue-62456.min.stderr
src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr
src/test/ui/const-generics/issues/issue-62878.min.stderr
src/test/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr
src/test/ui/const-generics/issues/issue-64494.min.stderr
src/test/ui/const-generics/issues/issue-66205.min.stderr
src/test/ui/const-generics/issues/issue-68366.min.stderr
src/test/ui/const-generics/issues/issue-68615-adt.min.stderr
src/test/ui/const-generics/issues/issue-68615-array.min.stderr
src/test/ui/const-generics/issues/issue-68977.min.stderr
src/test/ui/const-generics/issues/issue-71169.min.stderr
src/test/ui/const-generics/issues/issue-72787.min.stderr
src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.min.stderr
src/test/ui/const-generics/issues/issue-73491.min.stderr
src/test/ui/const-generics/issues/issue-74101.min.stderr
src/test/ui/const-generics/issues/issue-74255.min.stderr
src/test/ui/const-generics/issues/issue-74950.min.stderr
src/test/ui/const-generics/issues/issue-75047.min.stderr
src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.min.stderr
src/test/ui/const-generics/macro_rules-braces.full.stderr
src/test/ui/const-generics/macro_rules-braces.min.stderr
src/test/ui/const-generics/macro_rules-braces.rs
src/test/ui/const-generics/min_const_generics/complex-expression.stderr
src/test/ui/const-generics/min_const_generics/complex-types.stderr
src/test/ui/const-generics/min_const_generics/macro.rs
src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr
src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.stderr
src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.stderr
src/test/ui/const-generics/nested-type.min.stderr
src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr
src/test/ui/const-generics/slice-const-param-mismatch.min.stderr
src/test/ui/const-generics/slice-const-param.min.stderr
src/test/ui/const-generics/std/const-generics-range.min.stderr
src/test/ui/const-generics/type-dependent/issue-71348.min.stderr
src/test/ui/const-generics/wf-misc.min.stderr
src/test/ui/consts/const-int-pow-rpass.rs
src/test/ui/consts/issue-79137-monomorphic.rs [new file with mode: 0644]
src/test/ui/consts/issue-79137-toogeneric.rs [new file with mode: 0644]
src/test/ui/consts/issue-79137-toogeneric.stderr [new file with mode: 0644]
src/test/ui/consts/issue-79152-const-array-index.rs [new file with mode: 0644]
src/test/ui/consts/std/net/ip.rs [new file with mode: 0644]
src/test/ui/core-run-destroy.rs
src/test/ui/default-alloc-error-hook.rs
src/test/ui/destructuring-assignment/drop-order.rs [new file with mode: 0644]
src/test/ui/env-args-reverse-iterator.rs
src/test/ui/env-funky-keys.rs
src/test/ui/env-home-dir.rs
src/test/ui/env-vars.rs
src/test/ui/error-codes/E0275.stderr
src/test/ui/error-codes/E0277.rs
src/test/ui/error-codes/E0277.stderr
src/test/ui/exec-env.rs
src/test/ui/expr/compound-assignment/eval-order.rs [new file with mode: 0644]
src/test/ui/fds-are-cloexec.rs
src/test/ui/feature-gate/issue-43106-gating-of-test.rs
src/test/ui/feature-gate/issue-43106-gating-of-test.stderr
src/test/ui/feature-gates/feature-gate-abi.rs
src/test/ui/feature-gates/feature-gate-abi.stderr
src/test/ui/feature-gates/feature-gate-auto-traits.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-auto-traits.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr
src/test/ui/feature-gates/feature-gate-optin-builtin-traits.rs [deleted file]
src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr [deleted file]
src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.rs
src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr
src/test/ui/fmt/format-args-capture.rs
src/test/ui/generator/auto-trait-regions.rs
src/test/ui/generic-associated-types/parse/trait-path-expected-token.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/parse/trait-path-expected-token.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/parse/trait-path-expressions.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/parse/trait-path-segments.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/parse/trait-path-segments.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/parse/trait-path-types.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/parse/trait-path-types.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/parse/trait-path-unimplemented.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/parse/trait-path-unimplemented.stderr [new file with mode: 0644]
src/test/ui/hygiene/no_implicit_prelude.rs
src/test/ui/hygiene/no_implicit_prelude.stderr
src/test/ui/impl-trait/issues/issue-78721.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-78721.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-78722.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-78722.stderr [new file with mode: 0644]
src/test/ui/intrinsics/intrinsic-alignment.rs
src/test/ui/issues/issue-10626.rs
src/test/ui/issues/issue-10767.rs
src/test/ui/issues/issue-12116.rs [deleted file]
src/test/ui/issues/issue-12116.stderr [deleted file]
src/test/ui/issues/issue-12133-3.rs
src/test/ui/issues/issue-12369.rs [deleted file]
src/test/ui/issues/issue-12369.stderr [deleted file]
src/test/ui/issues/issue-13304.rs
src/test/ui/issues/issue-13727.rs [deleted file]
src/test/ui/issues/issue-13727.stderr [deleted file]
src/test/ui/issues/issue-14456.rs
src/test/ui/issues/issue-14940.rs
src/test/ui/issues/issue-15129.rs [deleted file]
src/test/ui/issues/issue-15129.stderr [deleted file]
src/test/ui/issues/issue-16272.rs
src/test/ui/issues/issue-17121.rs
src/test/ui/issues/issue-18400.stderr
src/test/ui/issues/issue-20091.rs
src/test/ui/issues/issue-20413.rs
src/test/ui/issues/issue-20413.stderr
src/test/ui/issues/issue-20433.stderr
src/test/ui/issues/issue-20616-2.rs
src/test/ui/issues/issue-20616-2.stderr
src/test/ui/issues/issue-20616-3.rs
src/test/ui/issues/issue-20616-3.stderr
src/test/ui/issues/issue-20616-4.rs
src/test/ui/issues/issue-20616-4.stderr
src/test/ui/issues/issue-20616-5.rs
src/test/ui/issues/issue-20616-5.stderr
src/test/ui/issues/issue-20616-6.rs
src/test/ui/issues/issue-20616-6.stderr
src/test/ui/issues/issue-20616-7.rs
src/test/ui/issues/issue-20616-7.stderr
src/test/ui/issues/issue-20644.rs
src/test/ui/issues/issue-2074.rs
src/test/ui/issues/issue-20797.rs
src/test/ui/issues/issue-2111.rs [deleted file]
src/test/ui/issues/issue-2111.stderr [deleted file]
src/test/ui/issues/issue-2214.rs
src/test/ui/issues/issue-22577.rs
src/test/ui/issues/issue-23036.rs
src/test/ui/issues/issue-23649-2.rs
src/test/ui/issues/issue-24313.rs
src/test/ui/issues/issue-27859.rs
src/test/ui/issues/issue-28134.rs
src/test/ui/issues/issue-28134.stderr
src/test/ui/issues/issue-29516.rs
src/test/ui/issues/issue-30240-b.rs [deleted file]
src/test/ui/issues/issue-30240-b.stderr [deleted file]
src/test/ui/issues/issue-30240-rpass.rs [deleted file]
src/test/ui/issues/issue-30240.rs [deleted file]
src/test/ui/issues/issue-30240.stderr [deleted file]
src/test/ui/issues/issue-30490.rs
src/test/ui/issues/issue-3096-1.rs [deleted file]
src/test/ui/issues/issue-3096-1.stderr [deleted file]
src/test/ui/issues/issue-3096-2.rs [deleted file]
src/test/ui/issues/issue-3096-2.stderr [deleted file]
src/test/ui/issues/issue-31173.stderr
src/test/ui/issues/issue-31221.rs [deleted file]
src/test/ui/issues/issue-31221.stderr [deleted file]
src/test/ui/issues/issue-31561.rs [deleted file]
src/test/ui/issues/issue-31561.stderr [deleted file]
src/test/ui/issues/issue-33770.rs
src/test/ui/issues/issue-34334.rs
src/test/ui/issues/issue-34334.stderr
src/test/ui/issues/issue-3601.rs [deleted file]
src/test/ui/issues/issue-3601.stderr [deleted file]
src/test/ui/issues/issue-36617.rs
src/test/ui/issues/issue-36617.stderr
src/test/ui/issues/issue-37665.rs
src/test/ui/issues/issue-37665.stderr
src/test/ui/issues/issue-39175.rs
src/test/ui/issues/issue-39175.stderr
src/test/ui/issues/issue-39362.rs [deleted file]
src/test/ui/issues/issue-39362.stderr [deleted file]
src/test/ui/issues/issue-40845.stderr
src/test/ui/issues/issue-4321.rs [deleted file]
src/test/ui/issues/issue-4321.stderr [deleted file]
src/test/ui/issues/issue-4541.rs
src/test/ui/issues/issue-4542.rs
src/test/ui/issues/issue-46576.rs
src/test/ui/issues/issue-46576.stderr
src/test/ui/issues/issue-49934-errors.rs
src/test/ui/issues/issue-49934-errors.stderr
src/test/ui/issues/issue-50865-private-impl-trait/auxiliary/lib.rs
src/test/ui/issues/issue-57472.rs [deleted file]
src/test/ui/issues/issue-57472.stderr [deleted file]
src/test/ui/issues/issue-73899.rs [new file with mode: 0644]
src/test/ui/iterators/iter-count-overflow-ndebug.rs
src/test/ui/iterators/iter-position-overflow-ndebug.rs
src/test/ui/lint/inline-trait-and-foreign-items.stderr
src/test/ui/lint/redundant-semicolon/item-stmt-semi.rs [new file with mode: 0644]
src/test/ui/lint/special-upper-lower-cases.rs [new file with mode: 0644]
src/test/ui/lint/special-upper-lower-cases.stderr [new file with mode: 0644]
src/test/ui/lint/use_suggestion_json.rs
src/test/ui/lint/use_suggestion_json.stderr
src/test/ui/lint/warn-unused-inline-on-fn-prototypes.stderr
src/test/ui/macros/issue-78333.rs [new file with mode: 0644]
src/test/ui/macros/macro-2.rs
src/test/ui/macros/macro-comma-behavior-rpass.rs
src/test/ui/macros/macro-path.rs
src/test/ui/malformed/issue-69341-malformed-derive-inert.rs
src/test/ui/malformed/issue-69341-malformed-derive-inert.stderr
src/test/ui/match/issue-50900.rs [deleted file]
src/test/ui/match/issue-50900.stderr [deleted file]
src/test/ui/match/type_polymorphic_byte_str_literals.rs [deleted file]
src/test/ui/match/type_polymorphic_byte_str_literals.stderr [deleted file]
src/test/ui/mir/issue-77911.rs
src/test/ui/mir/mir-inlining/array-clone-with-generic-size.rs [new file with mode: 0644]
src/test/ui/mir/mir-inlining/ice-issue-77306-1.rs
src/test/ui/mir/mir_dynamic_drops_1.rs
src/test/ui/mir/mir_dynamic_drops_2.rs
src/test/ui/mir/mir_dynamic_drops_3.rs
src/test/ui/mismatched_types/issue-36053-2.stderr
src/test/ui/mismatched_types/recovered-block.rs
src/test/ui/mismatched_types/recovered-block.stderr
src/test/ui/missing/missing-items/issue-40221.rs [deleted file]
src/test/ui/missing/missing-items/issue-40221.stderr [deleted file]
src/test/ui/multi-panic.rs
src/test/ui/never_type/auto-traits.rs
src/test/ui/never_type/issue-13352.rs
src/test/ui/never_type/issue-13352.stderr
src/test/ui/no-stdio.rs
src/test/ui/out-of-stack.rs
src/test/ui/overloaded-calls-nontuple.rs
src/test/ui/overloaded-calls-nontuple.stderr
src/test/ui/panic-brace.rs [new file with mode: 0644]
src/test/ui/panic-brace.stderr [new file with mode: 0644]
src/test/ui/panic-runtime/abort-link-to-unwind-dylib.rs
src/test/ui/panic-runtime/abort-link-to-unwinding-crates.rs
src/test/ui/panic-runtime/abort.rs
src/test/ui/panic-runtime/lto-abort.rs
src/test/ui/panic-runtime/lto-unwind.rs
src/test/ui/panics/abort-on-panic.rs
src/test/ui/panics/issue-47429-short-backtraces.rs
src/test/ui/panics/issue-47429-short-backtraces.run.stderr
src/test/ui/parser/default-unmatched-assoc.stderr
src/test/ui/parser/fn-header-semantic-fail.stderr
src/test/ui/parser/issue-62660.rs
src/test/ui/parser/issue-62660.stderr
src/test/ui/parser/issue-63116.stderr
src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.stderr
src/test/ui/parser/lifetime-semicolon.rs
src/test/ui/parser/lifetime-semicolon.stderr
src/test/ui/parser/no-const-fn-in-extern-block.stderr
src/test/ui/parser/removed-syntax-closure-lifetime.rs
src/test/ui/parser/removed-syntax-closure-lifetime.stderr
src/test/ui/parser/trait-object-bad-parens.rs
src/test/ui/paths-containing-nul.rs
src/test/ui/pattern/const-pat-ice.rs [deleted file]
src/test/ui/pattern/deny-irrefutable-let-patterns.rs [deleted file]
src/test/ui/pattern/deny-irrefutable-let-patterns.stderr [deleted file]
src/test/ui/pattern/integer-range-binding.rs [new file with mode: 0644]
src/test/ui/pattern/irrefutable-let-patterns.rs [deleted file]
src/test/ui/pattern/issue-66501.rs [deleted file]
src/test/ui/pattern/usefulness/const-pat-ice.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/exhaustive_integer_patterns.rs [deleted file]
src/test/ui/pattern/usefulness/exhaustive_integer_patterns.stderr [deleted file]
src/test/ui/pattern/usefulness/floats.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/floats.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/guards-not-exhaustive.rs [deleted file]
src/test/ui/pattern/usefulness/guards.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/guards.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-allow.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-allow.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-deny.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-deny.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/integer-ranges/reachability.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/irrefutable-exhaustive-integer-binding.rs [deleted file]
src/test/ui/pattern/usefulness/irrefutable-let-patterns.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-12116.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-12116.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-12369.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-12369.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-13727.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-13727.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-15129.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-15129.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-2111.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-2111.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-30240-b.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-30240-b.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-30240-rpass.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-30240.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-30240.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-3096-1.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-3096-1.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-3096-2.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-3096-2.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-31221.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-31221.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-31561.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-31561.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-3601.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-3601.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-39362.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-39362.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-40221.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-40221.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-4321.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-4321.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-43253.rs [deleted file]
src/test/ui/pattern/usefulness/issue-43253.stderr [deleted file]
src/test/ui/pattern/usefulness/issue-50900.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-50900.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-57472.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-57472.stderr [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-66501.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/match-range-fail-dominate.rs [deleted file]
src/test/ui/pattern/usefulness/match-range-fail-dominate.stderr [deleted file]
src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.rs [deleted file]
src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.stderr [deleted file]
src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.rs [deleted file]
src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.stderr [deleted file]
src/test/ui/pattern/usefulness/type_polymorphic_byte_str_literals.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/type_polymorphic_byte_str_literals.stderr [new file with mode: 0644]
src/test/ui/phantom-auto-trait.rs [new file with mode: 0644]
src/test/ui/phantom-auto-trait.stderr [new file with mode: 0644]
src/test/ui/phantom-oibit.rs [deleted file]
src/test/ui/phantom-oibit.stderr [deleted file]
src/test/ui/precise_pointer_size_matching.rs [deleted file]
src/test/ui/precise_pointer_size_matching.stderr [deleted file]
src/test/ui/print-fuel/print-fuel.rs
src/test/ui/print-stdout-eprint-stderr.rs
src/test/ui/privacy/private-in-public-non-principal-2.rs
src/test/ui/privacy/private-in-public-non-principal.rs
src/test/ui/proc-macro/allowed-attr-stmt-expr.rs [new file with mode: 0644]
src/test/ui/proc-macro/allowed-attr-stmt-expr.stdout [new file with mode: 0644]
src/test/ui/proc-macro/attr-stmt-expr.rs
src/test/ui/proc-macro/attr-stmt-expr.stderr
src/test/ui/proc-macro/attr-stmt-expr.stdout [new file with mode: 0644]
src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs
src/test/ui/proc-macro/auxiliary/issue-79242.rs [new file with mode: 0644]
src/test/ui/proc-macro/issue-79242-slow-retokenize-check.rs [new file with mode: 0644]
src/test/ui/proc-macro/keep-expr-tokens.rs
src/test/ui/proc-macro/keep-expr-tokens.stderr
src/test/ui/proc-macro/keep-expr-tokens.stdout [new file with mode: 0644]
src/test/ui/proc-macro/proc-macro-gates.rs
src/test/ui/proc-macro/proc-macro-gates.stderr
src/test/ui/proc-macro/proc-macro-gates2.rs
src/test/ui/proc-macro/proc-macro-gates2.stderr
src/test/ui/process/process-envs.rs
src/test/ui/process/process-exit.rs
src/test/ui/process/process-remove-from-env.rs
src/test/ui/process/process-sigpipe.rs
src/test/ui/process/process-spawn-nonexistent.rs
src/test/ui/process/process-spawn-with-unicode-params.rs
src/test/ui/process/process-status-inherits-stdin.rs
src/test/ui/process/tls-exit-status.rs
src/test/ui/resolve/macro-determinacy-non-module.rs [new file with mode: 0644]
src/test/ui/resolve/token-error-correct-3.rs
src/test/ui/resolve/token-error-correct-3.stderr
src/test/ui/resolve/use_suggestion_placement.rs
src/test/ui/resolve/use_suggestion_placement.stderr
src/test/ui/rfc-2091-track-caller/error-with-naked.rs
src/test/ui/rfc-2091-track-caller/error-with-naked.stderr
src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs
src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr
src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs
src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-opt-out.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs [new file with mode: 0644]
src/test/ui/rfcs/rfc-1014.rs
src/test/ui/running-with-no-runtime.rs
src/test/ui/signal-alternate-stack-cleanup.rs
src/test/ui/signal-exit-status.rs
src/test/ui/sigpipe-should-be-ignored.rs
src/test/ui/span/issue-33884.rs
src/test/ui/span/issue-33884.stderr
src/test/ui/span/issue-36530.rs
src/test/ui/span/issue-36530.stderr
src/test/ui/span/issue-43927-non-ADT-derive.rs
src/test/ui/span/issue-43927-non-ADT-derive.stderr
src/test/ui/specialization/specialization-polarity.rs
src/test/ui/sse2.rs
src/test/ui/std-backtrace.rs
src/test/ui/stdio-is-blocking.rs
src/test/ui/structs-enums/nested-enum-same-names.rs
src/test/ui/structs-enums/rec-align-u64.rs
src/test/ui/symbol-names/impl1.rs
src/test/ui/tcp-stress.rs
src/test/ui/threads-sendsync/sync-send-in-std.rs
src/test/ui/traits/traits-inductive-overflow-supertrait-auto-trait.rs [new file with mode: 0644]
src/test/ui/traits/traits-inductive-overflow-supertrait-auto-trait.stderr [new file with mode: 0644]
src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.rs [deleted file]
src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr [deleted file]
src/test/ui/try-is-identifier-edition2015.rs
src/test/ui/try-operator-on-main.rs
src/test/ui/try-operator-on-main.stderr
src/test/ui/try-operator.rs
src/test/ui/try-wait.rs
src/test/ui/type/ascription/issue-34255-1.rs
src/test/ui/type/ascription/issue-34255-1.stderr
src/test/ui/typeck/auxiliary/tdticc_coherence_lib.rs
src/test/ui/wait-forked-but-failed-child.rs
src/test/ui/x86stdcall.rs
src/test/ui/zero-sized/zero-size-type-destructors.rs
src/tools/build-manifest/src/main.rs
src/tools/cargo
src/tools/clippy/.github/PULL_REQUEST_TEMPLATE.md
src/tools/clippy/CHANGELOG.md
src/tools/clippy/README.md
src/tools/clippy/clippy_dev/src/update_lints.rs
src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
src/tools/clippy/clippy_lints/src/attrs.rs
src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs
src/tools/clippy/clippy_lints/src/deprecated_lints.rs
src/tools/clippy/clippy_lints/src/future_not_send.rs
src/tools/clippy/clippy_lints/src/len_zero.rs
src/tools/clippy/clippy_lints/src/let_underscore.rs
src/tools/clippy/clippy_lints/src/lib.rs
src/tools/clippy/clippy_lints/src/loops.rs
src/tools/clippy/clippy_lints/src/manual_async_fn.rs
src/tools/clippy/clippy_lints/src/map_clone.rs
src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
src/tools/clippy/clippy_lints/src/methods/mod.rs
src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
src/tools/clippy/clippy_lints/src/missing_doc.rs
src/tools/clippy/clippy_lints/src/missing_inline.rs
src/tools/clippy/clippy_lints/src/mut_key.rs
src/tools/clippy/clippy_lints/src/non_copy_const.rs
src/tools/clippy/clippy_lints/src/non_expressive_names.rs
src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
src/tools/clippy/clippy_lints/src/ranges.rs
src/tools/clippy/clippy_lints/src/redundant_clone.rs
src/tools/clippy/clippy_lints/src/reference.rs
src/tools/clippy/clippy_lints/src/regex.rs
src/tools/clippy/clippy_lints/src/strings.rs
src/tools/clippy/clippy_lints/src/try_err.rs
src/tools/clippy/clippy_lints/src/types.rs
src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/unused_unit.rs
src/tools/clippy/clippy_lints/src/useless_conversion.rs
src/tools/clippy/clippy_lints/src/utils/ast_utils.rs
src/tools/clippy/clippy_lints/src/utils/eager_or_lazy.rs
src/tools/clippy/clippy_lints/src/utils/inspector.rs
src/tools/clippy/clippy_lints/src/utils/mod.rs
src/tools/clippy/clippy_lints/src/utils/paths.rs
src/tools/clippy/clippy_lints/src/utils/visitors.rs [new file with mode: 0644]
src/tools/clippy/doc/changelog_update.md
src/tools/clippy/src/driver.rs
src/tools/clippy/src/lintlist/lint.rs [deleted file]
src/tools/clippy/src/lintlist/mod.rs [deleted file]
src/tools/clippy/tests/ui/borrow_interior_mutable_const.rs [deleted file]
src/tools/clippy/tests/ui/borrow_interior_mutable_const.stderr [deleted file]
src/tools/clippy/tests/ui/borrow_interior_mutable_const/auxiliary/helper.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/crashes/ice-360.stderr
src/tools/clippy/tests/ui/crashes/ice-6332.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/crashes/implements-trait.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/declare_interior_mutable_const.rs [deleted file]
src/tools/clippy/tests/ui/declare_interior_mutable_const.stderr [deleted file]
src/tools/clippy/tests/ui/declare_interior_mutable_const/enums.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/declare_interior_mutable_const/enums.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/declare_interior_mutable_const/others.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/deprecated.rs
src/tools/clippy/tests/ui/deprecated.stderr
src/tools/clippy/tests/ui/deref_addrof.fixed
src/tools/clippy/tests/ui/deref_addrof.rs
src/tools/clippy/tests/ui/deref_addrof.stderr
src/tools/clippy/tests/ui/derive_ord_xor_partial_ord.rs
src/tools/clippy/tests/ui/derive_ord_xor_partial_ord.stderr
src/tools/clippy/tests/ui/doc_errors.rs
src/tools/clippy/tests/ui/doc_errors.stderr
src/tools/clippy/tests/ui/drop_ref.rs
src/tools/clippy/tests/ui/drop_ref.stderr
src/tools/clippy/tests/ui/empty_loop.stderr
src/tools/clippy/tests/ui/empty_loop_no_std.rs
src/tools/clippy/tests/ui/empty_loop_no_std.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/filter_methods.rs
src/tools/clippy/tests/ui/filter_methods.stderr
src/tools/clippy/tests/ui/forget_ref.rs
src/tools/clippy/tests/ui/forget_ref.stderr
src/tools/clippy/tests/ui/let_underscore_drop.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/let_underscore_drop.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/let_underscore_must_use.rs
src/tools/clippy/tests/ui/let_underscore_must_use.stderr
src/tools/clippy/tests/ui/logic_bug.rs
src/tools/clippy/tests/ui/manual_async_fn.fixed
src/tools/clippy/tests/ui/manual_async_fn.rs
src/tools/clippy/tests/ui/manual_async_fn.stderr
src/tools/clippy/tests/ui/manual_ok_or.fixed
src/tools/clippy/tests/ui/manual_ok_or.rs
src/tools/clippy/tests/ui/manual_unwrap_or.fixed
src/tools/clippy/tests/ui/manual_unwrap_or.rs
src/tools/clippy/tests/ui/map_clone.fixed
src/tools/clippy/tests/ui/map_clone.rs
src/tools/clippy/tests/ui/map_clone.stderr
src/tools/clippy/tests/ui/map_err.rs
src/tools/clippy/tests/ui/map_err.stderr
src/tools/clippy/tests/ui/map_flatten.fixed
src/tools/clippy/tests/ui/map_flatten.rs
src/tools/clippy/tests/ui/map_flatten.stderr
src/tools/clippy/tests/ui/methods.rs
src/tools/clippy/tests/ui/methods.stderr
src/tools/clippy/tests/ui/mismatched_target_os_non_unix.fixed
src/tools/clippy/tests/ui/mismatched_target_os_non_unix.rs
src/tools/clippy/tests/ui/mismatched_target_os_non_unix.stderr
src/tools/clippy/tests/ui/needless_lifetimes.rs
src/tools/clippy/tests/ui/nonminimal_bool.rs
src/tools/clippy/tests/ui/nonminimal_bool_methods.rs
src/tools/clippy/tests/ui/option_map_unit_fn_fixable.fixed
src/tools/clippy/tests/ui/option_map_unit_fn_fixable.rs
src/tools/clippy/tests/ui/option_map_unit_fn_fixable.stderr
src/tools/clippy/tests/ui/option_option.rs
src/tools/clippy/tests/ui/option_option.stderr
src/tools/clippy/tests/ui/or_fun_call.fixed
src/tools/clippy/tests/ui/or_fun_call.rs
src/tools/clippy/tests/ui/or_fun_call.stderr
src/tools/clippy/tests/ui/panic.rs [deleted file]
src/tools/clippy/tests/ui/panic.stderr [deleted file]
src/tools/clippy/tests/ui/panic_in_result_fn.rs
src/tools/clippy/tests/ui/panic_in_result_fn.stderr
src/tools/clippy/tests/ui/question_mark.fixed
src/tools/clippy/tests/ui/question_mark.rs
src/tools/clippy/tests/ui/question_mark.stderr
src/tools/clippy/tests/ui/range_contains.fixed
src/tools/clippy/tests/ui/range_contains.rs
src/tools/clippy/tests/ui/range_contains.stderr
src/tools/clippy/tests/ui/redundant_pattern_matching.fixed
src/tools/clippy/tests/ui/redundant_pattern_matching.rs
src/tools/clippy/tests/ui/redundant_pattern_matching.stderr
src/tools/clippy/tests/ui/result_unit_error.rs
src/tools/clippy/tests/ui/result_unit_error.stderr
src/tools/clippy/tests/ui/search_is_some.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/search_is_some.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/search_is_some_fixable.fixed [new file with mode: 0644]
src/tools/clippy/tests/ui/search_is_some_fixable.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/search_is_some_fixable.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/string_from_utf8_as_bytes.fixed [new file with mode: 0644]
src/tools/clippy/tests/ui/string_from_utf8_as_bytes.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/string_from_utf8_as_bytes.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/try_err.fixed
src/tools/clippy/tests/ui/try_err.rs
src/tools/clippy/tests/ui/try_err.stderr
src/tools/clippy/tests/ui/unit_arg.rs
src/tools/clippy/tests/ui/unit_arg.stderr
src/tools/clippy/tests/ui/unnecessary_clone.rs
src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/unnecessary_wraps.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/unnecessary_wraps.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/useless_conversion.fixed
src/tools/clippy/tests/ui/useless_conversion.rs
src/tools/clippy/tests/ui/useless_conversion.stderr
src/tools/clippy/tests/ui/vec_box_sized.fixed
src/tools/clippy/tests/ui/vec_box_sized.rs
src/tools/clippy/tests/ui/vec_box_sized.stderr
src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed
src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs
src/tools/clippy/tests/ui/wildcard_imports.fixed
src/tools/clippy/tests/ui/wildcard_imports.rs
src/tools/clippy/tests/ui/wildcard_imports.stderr
src/tools/compiletest/src/json.rs
src/tools/compiletest/src/main.rs
src/tools/compiletest/src/runtest.rs
src/tools/compiletest/src/util.rs
src/tools/miri
src/tools/tidy/src/style.rs
src/tools/tidy/src/unit_tests.rs

index 2c5c37007d5bc1c2dc03adaeff3ba6399ba67fa1..ac0a71232efc9457b434da02d25cd232394d3785 100644 (file)
@@ -5,6 +5,7 @@
 *.h rust
 *.rs rust diff=rust
 *.fixed linguist-language=Rust
+*.mir linguist-language=Rust
 src/etc/installer/gfx/* binary
 *.woff binary
 src/vendor/** -text
index f476926832158d715f4e474f581655b8ff99f740..94f2938f11c269258c95fce8375e9f522d418450 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -148,6 +148,7 @@ Jorge Aparicio <japaric@linux.com> <japaricious@gmail.com>
 Joseph Martin <pythoner6@gmail.com>
 Joseph T. Lyons <JosephTLyons@gmail.com> <josephtlyons@gmail.com>
 Joseph T. Lyons <JosephTLyons@gmail.com> <JosephTLyons@users.noreply.github.com>
+Joshua Nelson <jyn514@gmail.com> <joshua@yottadb.com>
 jumbatm <jumbatm@gmail.com> <30644300+jumbatm@users.noreply.github.com>
 Junyoung Cho <june0.cho@samsung.com>
 Jyun-Yan You <jyyou.tw@gmail.com> <jyyou@cs.nctu.edu.tw>
@@ -229,6 +230,7 @@ Phil Dawes <phil@phildawes.net> Phil Dawes <pdawes@drw.com>
 Philipp Brüschweiler <blei42@gmail.com> <blei42@gmail.com>
 Philipp Brüschweiler <blei42@gmail.com> <bruphili@student.ethz.ch>
 Philipp Krones <hello@philkrones.com> flip1995 <hello@philkrones.com>
+Philipp Krones <hello@philkrones.com> <philipp.krones@embecosm.com>
 Philipp Matthias Schäfer <philipp.matthias.schaefer@posteo.de>
 Przemysław Wesołek <jest@go.art.pl> Przemek Wesołek <jest@go.art.pl>
 Rafael Ávila de Espíndola <respindola@mozilla.com> Rafael Avila de Espindola <espindola@dream.(none)>
index 928d19b1e2c3f36b4c7aaf7d1a8a29dc28135042..b3e6e7bae7c47340a073078cf37a6579d8d5509a 100644 (file)
@@ -2,9 +2,9 @@
 # It is not intended for manual editing.
 [[package]]
 name = "addr2line"
-version = "0.13.0"
+version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072"
+checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423"
 dependencies = [
  "compiler_builtins",
  "gimli",
@@ -132,13 +132,13 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
 
 [[package]]
 name = "backtrace"
-version = "0.3.53"
+version = "0.3.55"
 dependencies = [
  "addr2line",
  "cfg-if 1.0.0",
  "libc",
  "miniz_oxide",
- "object 0.21.1",
+ "object",
  "rustc-demangle",
 ]
 
@@ -295,7 +295,7 @@ checksum = "81a18687293a1546b67c246452202bbbf143d239cb43494cc163da14979082da"
 
 [[package]]
 name = "cargo"
-version = "0.50.0"
+version = "0.51.0"
 dependencies = [
  "anyhow",
  "atty",
@@ -1292,9 +1292,9 @@ dependencies = [
 
 [[package]]
 name = "gimli"
-version = "0.22.0"
+version = "0.23.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724"
+checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-alloc",
@@ -2181,21 +2181,15 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.20.0"
+version = "0.22.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5"
+checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-alloc",
  "rustc-std-workspace-core",
 ]
 
-[[package]]
-name = "object"
-version = "0.21.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37fd5004feb2ce328a52b0b3d01dbf4ffff72583493900ed15f22d4111c51693"
-
 [[package]]
 name = "once_cell"
 version = "1.4.1"
@@ -3802,7 +3796,7 @@ dependencies = [
  "rustc_target",
  "rustc_trait_selection",
  "rustc_traits",
- "rustc_ty",
+ "rustc_ty_utils",
  "rustc_typeck",
  "smallvec 1.4.2",
  "tempfile",
@@ -3831,6 +3825,7 @@ dependencies = [
  "rustc_hir",
  "rustc_index",
  "rustc_middle",
+ "rustc_parse_format",
  "rustc_session",
  "rustc_span",
  "rustc_target",
@@ -4240,7 +4235,7 @@ dependencies = [
 ]
 
 [[package]]
-name = "rustc_ty"
+name = "rustc_ty_utils"
 version = "0.0.0"
 dependencies = [
  "rustc_data_structures",
@@ -4667,7 +4662,7 @@ dependencies = [
  "hermit-abi",
  "libc",
  "miniz_oxide",
- "object 0.20.0",
+ "object",
  "panic_abort",
  "panic_unwind",
  "profiler_builtins",
@@ -5261,7 +5256,7 @@ dependencies = [
  "chrono",
  "lazy_static",
  "matchers",
- "parking_lot 0.9.0",
+ "parking_lot 0.11.0",
  "regex",
  "serde",
  "serde_json",
index b76e1e7ce65e00ade7e035f890ba3b9b9e5650aa..f468bad635a9baca66df23ecf507e3a409d783da 100644 (file)
     html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
     test(no_crate_inject, attr(deny(warnings)))
 )]
+#![feature(array_value_iter_slice)]
 #![feature(dropck_eyepatch)]
 #![feature(new_uninit)]
 #![feature(maybe_uninit_slice)]
+#![feature(array_value_iter)]
+#![feature(min_const_generics)]
+#![feature(min_specialization)]
 #![cfg_attr(test, feature(test))]
 
 use smallvec::SmallVec;
@@ -114,6 +118,72 @@ fn default() -> TypedArena<T> {
     }
 }
 
+trait IterExt<T> {
+    fn alloc_from_iter(self, arena: &TypedArena<T>) -> &mut [T];
+}
+
+impl<I, T> IterExt<T> for I
+where
+    I: IntoIterator<Item = T>,
+{
+    #[inline]
+    default fn alloc_from_iter(self, arena: &TypedArena<T>) -> &mut [T] {
+        let vec: SmallVec<[_; 8]> = self.into_iter().collect();
+        vec.alloc_from_iter(arena)
+    }
+}
+
+impl<T, const N: usize> IterExt<T> for std::array::IntoIter<T, N> {
+    #[inline]
+    fn alloc_from_iter(self, arena: &TypedArena<T>) -> &mut [T] {
+        let len = self.len();
+        if len == 0 {
+            return &mut [];
+        }
+        // Move the content to the arena by copying and then forgetting it
+        unsafe {
+            let start_ptr = arena.alloc_raw_slice(len);
+            self.as_slice().as_ptr().copy_to_nonoverlapping(start_ptr, len);
+            mem::forget(self);
+            slice::from_raw_parts_mut(start_ptr, len)
+        }
+    }
+}
+
+impl<T> IterExt<T> for Vec<T> {
+    #[inline]
+    fn alloc_from_iter(mut self, arena: &TypedArena<T>) -> &mut [T] {
+        let len = self.len();
+        if len == 0 {
+            return &mut [];
+        }
+        // Move the content to the arena by copying and then forgetting it
+        unsafe {
+            let start_ptr = arena.alloc_raw_slice(len);
+            self.as_ptr().copy_to_nonoverlapping(start_ptr, len);
+            self.set_len(0);
+            slice::from_raw_parts_mut(start_ptr, len)
+        }
+    }
+}
+
+impl<A: smallvec::Array> IterExt<A::Item> for SmallVec<A> {
+    #[inline]
+    fn alloc_from_iter(mut self, arena: &TypedArena<A::Item>) -> &mut [A::Item] {
+        let len = self.len();
+        if len == 0 {
+            return &mut [];
+        }
+        // Move the content to the arena by copying and then forgetting it
+        unsafe {
+            let start_ptr = arena.alloc_raw_slice(len);
+            self.as_ptr().copy_to_nonoverlapping(start_ptr, len);
+            self.set_len(0);
+            slice::from_raw_parts_mut(start_ptr, len)
+        }
+    }
+}
+
 impl<T> TypedArena<T> {
     /// Allocates an object in the `TypedArena`, returning a reference to it.
     #[inline]
@@ -191,19 +261,7 @@ pub fn alloc_slice(&self, slice: &[T]) -> &mut [T]
     #[inline]
     pub fn alloc_from_iter<I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] {
         assert!(mem::size_of::<T>() != 0);
-        let mut vec: SmallVec<[_; 8]> = iter.into_iter().collect();
-        if vec.is_empty() {
-            return &mut [];
-        }
-        // Move the content to the arena by copying it and then forgetting
-        // the content of the SmallVec
-        unsafe {
-            let len = vec.len();
-            let start_ptr = self.alloc_raw_slice(len);
-            vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
-            vec.set_len(0);
-            slice::from_raw_parts_mut(start_ptr, len)
-        }
+        iter.alloc_from_iter(self)
     }
 
     /// Grows the arena.
index 328086af183d6076b171fcd270f4a5b5aae446b1..9d6ee65049ab258589456471bbf3fe90ace3ab68 100644 (file)
@@ -901,10 +901,39 @@ pub struct Stmt {
     pub id: NodeId,
     pub kind: StmtKind,
     pub span: Span,
-    pub tokens: Option<LazyTokenStream>,
 }
 
 impl Stmt {
+    pub fn tokens(&self) -> Option<&LazyTokenStream> {
+        match self.kind {
+            StmtKind::Local(ref local) => local.tokens.as_ref(),
+            StmtKind::Item(ref item) => item.tokens.as_ref(),
+            StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.tokens.as_ref(),
+            StmtKind::Empty => None,
+            StmtKind::MacCall(ref mac) => mac.tokens.as_ref(),
+        }
+    }
+
+    pub fn tokens_mut(&mut self) -> Option<&mut LazyTokenStream> {
+        match self.kind {
+            StmtKind::Local(ref mut local) => local.tokens.as_mut(),
+            StmtKind::Item(ref mut item) => item.tokens.as_mut(),
+            StmtKind::Expr(ref mut expr) | StmtKind::Semi(ref mut expr) => expr.tokens.as_mut(),
+            StmtKind::Empty => None,
+            StmtKind::MacCall(ref mut mac) => mac.tokens.as_mut(),
+        }
+    }
+
+    pub fn set_tokens(&mut self, tokens: Option<LazyTokenStream>) {
+        match self.kind {
+            StmtKind::Local(ref mut local) => local.tokens = tokens,
+            StmtKind::Item(ref mut item) => item.tokens = tokens,
+            StmtKind::Expr(ref mut expr) | StmtKind::Semi(ref mut expr) => expr.tokens = tokens,
+            StmtKind::Empty => {}
+            StmtKind::MacCall(ref mut mac) => mac.tokens = tokens,
+        }
+    }
+
     pub fn has_trailing_semicolon(&self) -> bool {
         match &self.kind {
             StmtKind::Semi(_) => true,
@@ -912,18 +941,25 @@ pub fn has_trailing_semicolon(&self) -> bool {
             _ => false,
         }
     }
+
+    /// Converts a parsed `Stmt` to a `Stmt` with
+    /// a trailing semicolon.
+    ///
+    /// This only modifies the parsed AST struct, not the attached
+    /// `LazyTokenStream`. The parser is responsible for calling
+    /// `CreateTokenStream::add_trailing_semi` when there is actually
+    /// a semicolon in the tokenstream.
     pub fn add_trailing_semicolon(mut self) -> Self {
         self.kind = match self.kind {
             StmtKind::Expr(expr) => StmtKind::Semi(expr),
             StmtKind::MacCall(mac) => {
-                StmtKind::MacCall(mac.map(|MacCallStmt { mac, style: _, attrs }| MacCallStmt {
-                    mac,
-                    style: MacStmtStyle::Semicolon,
-                    attrs,
+                StmtKind::MacCall(mac.map(|MacCallStmt { mac, style: _, attrs, tokens }| {
+                    MacCallStmt { mac, style: MacStmtStyle::Semicolon, attrs, tokens }
                 }))
             }
             kind => kind,
         };
+
         self
     }
 
@@ -963,6 +999,7 @@ pub struct MacCallStmt {
     pub mac: MacCall,
     pub style: MacStmtStyle,
     pub attrs: AttrVec,
+    pub tokens: Option<LazyTokenStream>,
 }
 
 #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug)]
@@ -988,6 +1025,7 @@ pub struct Local {
     pub init: Option<P<Expr>>,
     pub span: Span,
     pub attrs: AttrVec,
+    pub tokens: Option<LazyTokenStream>,
 }
 
 /// An arm of a 'match'.
@@ -1845,6 +1883,7 @@ pub fn normalize(&self, target_width: u32) -> Self {
 pub struct AssocTyConstraint {
     pub id: NodeId,
     pub ident: Ident,
+    pub gen_args: Option<GenericArgs>,
     pub kind: AssocTyConstraintKind,
     pub span: Span,
 }
index 6e47ff7d740810bde946274239b707f571f8b3d4..8a20dd796859034b226135d9ddd913db84ef2721 100644 (file)
@@ -34,7 +34,6 @@ macro_rules! unwrap_or {
 pub mod util {
     pub mod classify;
     pub mod comments;
-    pub mod lev_distance;
     pub mod literal;
     pub mod parser;
 }
index ddae0ab03e40497dddbf5147e14492559138a9d6..c4e92a9f6d17fd12cb83d36382c70605f8de255c 100644 (file)
@@ -441,11 +441,14 @@ pub fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
 }
 
 pub fn noop_visit_ty_constraint<T: MutVisitor>(
-    AssocTyConstraint { id, ident, kind, span }: &mut AssocTyConstraint,
+    AssocTyConstraint { id, ident, gen_args, kind, span }: &mut AssocTyConstraint,
     vis: &mut T,
 ) {
     vis.visit_id(id);
     vis.visit_ident(ident);
+    if let Some(ref mut gen_args) = gen_args {
+        vis.visit_generic_args(gen_args);
+    }
     match kind {
         AssocTyConstraintKind::Equality { ref mut ty } => {
             vis.visit_ty(ty);
@@ -576,13 +579,14 @@ pub fn noop_visit_parenthesized_parameter_data<T: MutVisitor>(
 }
 
 pub fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
-    let Local { id, pat, ty, init, span, attrs } = local.deref_mut();
+    let Local { id, pat, ty, init, span, attrs, tokens } = local.deref_mut();
     vis.visit_id(id);
     vis.visit_pat(pat);
     visit_opt(ty, |ty| vis.visit_ty(ty));
     visit_opt(init, |init| vis.visit_expr(init));
     vis.visit_span(span);
     visit_thin_attrs(attrs, vis);
+    visit_lazy_tts(tokens, vis);
 }
 
 pub fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
@@ -1325,16 +1329,12 @@ pub fn noop_filter_map_expr<T: MutVisitor>(mut e: P<Expr>, vis: &mut T) -> Optio
 }
 
 pub fn noop_flat_map_stmt<T: MutVisitor>(
-    Stmt { kind, mut span, mut id, mut tokens }: Stmt,
+    Stmt { kind, mut span, mut id }: Stmt,
     vis: &mut T,
 ) -> SmallVec<[Stmt; 1]> {
     vis.visit_id(&mut id);
     vis.visit_span(&mut span);
-    visit_lazy_tts(&mut tokens, vis);
-    noop_flat_map_stmt_kind(kind, vis)
-        .into_iter()
-        .map(|kind| Stmt { id, kind, span, tokens: tokens.clone() })
-        .collect()
+    noop_flat_map_stmt_kind(kind, vis).into_iter().map(|kind| Stmt { id, kind, span }).collect()
 }
 
 pub fn noop_flat_map_stmt_kind<T: MutVisitor>(
@@ -1351,9 +1351,10 @@ pub fn noop_flat_map_stmt_kind<T: MutVisitor>(
         StmtKind::Semi(expr) => vis.filter_map_expr(expr).into_iter().map(StmtKind::Semi).collect(),
         StmtKind::Empty => smallvec![StmtKind::Empty],
         StmtKind::MacCall(mut mac) => {
-            let MacCallStmt { mac: mac_, style: _, attrs } = mac.deref_mut();
+            let MacCallStmt { mac: mac_, style: _, attrs, tokens } = mac.deref_mut();
             vis.visit_mac_call(mac_);
             visit_thin_attrs(attrs, vis);
+            visit_lazy_tts(tokens, vis);
             smallvec![StmtKind::MacCall(mac)]
         }
     }
index 2bba7e618c0503890393498a0d948a683e56c2cf..f583825fbb3c5070aa4d38d3620de70bb3eadb5f 100644 (file)
@@ -785,13 +785,20 @@ fn span(&self) -> Span {
     /// See issue #73345 for more details.
     /// FIXME(#73933): Remove this eventually.
     pub fn pretty_printing_compatibility_hack(&self) -> bool {
-        if let NtItem(item) = self {
-            let name = item.ident.name;
-            if name == sym::ProceduralMasqueradeDummyType || name == sym::ProcMacroHack {
-                if let ast::ItemKind::Enum(enum_def, _) = &item.kind {
-                    if let [variant] = &*enum_def.variants {
-                        return variant.ident.name == sym::Input;
-                    }
+        let item = match self {
+            NtItem(item) => item,
+            NtStmt(stmt) => match &stmt.kind {
+                ast::StmtKind::Item(item) => item,
+                _ => return false,
+            },
+            _ => return false,
+        };
+
+        let name = item.ident.name;
+        if name == sym::ProceduralMasqueradeDummyType || name == sym::ProcMacroHack {
+            if let ast::ItemKind::Enum(enum_def, _) = &item.kind {
+                if let [variant] = &*enum_def.variants {
+                    return variant.ident.name == sym::Input;
                 }
             }
         }
index fe67b905bf30f01a9b3eead31fc7cd2f5472c3ce..b2207f22816205f0c11dc16fa5ae7c21da3a65aa 100644 (file)
@@ -121,10 +121,14 @@ fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
 }
 
 pub trait CreateTokenStream: sync::Send + sync::Sync {
+    fn add_trailing_semi(&self) -> Box<dyn CreateTokenStream>;
     fn create_token_stream(&self) -> TokenStream;
 }
 
 impl CreateTokenStream for TokenStream {
+    fn add_trailing_semi(&self) -> Box<dyn CreateTokenStream> {
+        panic!("Cannot call `add_trailing_semi` on a `TokenStream`!");
+    }
     fn create_token_stream(&self) -> TokenStream {
         self.clone()
     }
@@ -141,6 +145,13 @@ pub fn new(inner: impl CreateTokenStream + 'static) -> LazyTokenStream {
         LazyTokenStream(Lrc::new(Box::new(inner)))
     }
 
+    /// Extends the captured stream by one token,
+    /// which must be a trailing semicolon. This
+    /// affects the `TokenStream` created by `make_tokenstream`.
+    pub fn add_trailing_semi(&self) -> LazyTokenStream {
+        LazyTokenStream(Lrc::new(self.0.add_trailing_semi()))
+    }
+
     pub fn create_token_stream(&self) -> TokenStream {
         self.0.create_token_stream()
     }
diff --git a/compiler/rustc_ast/src/util/lev_distance.rs b/compiler/rustc_ast/src/util/lev_distance.rs
deleted file mode 100644 (file)
index 21c2c92..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-// FIXME(Centril): Move to rustc_span?
-
-use rustc_span::symbol::Symbol;
-use std::cmp;
-
-#[cfg(test)]
-mod tests;
-
-/// Finds the Levenshtein distance between two strings
-pub fn lev_distance(a: &str, b: &str) -> usize {
-    // cases which don't require further computation
-    if a.is_empty() {
-        return b.chars().count();
-    } else if b.is_empty() {
-        return a.chars().count();
-    }
-
-    let mut dcol: Vec<_> = (0..=b.len()).collect();
-    let mut t_last = 0;
-
-    for (i, sc) in a.chars().enumerate() {
-        let mut current = i;
-        dcol[0] = current + 1;
-
-        for (j, tc) in b.chars().enumerate() {
-            let next = dcol[j + 1];
-            if sc == tc {
-                dcol[j + 1] = current;
-            } else {
-                dcol[j + 1] = cmp::min(current, next);
-                dcol[j + 1] = cmp::min(dcol[j + 1], dcol[j]) + 1;
-            }
-            current = next;
-            t_last = j;
-        }
-    }
-    dcol[t_last + 1]
-}
-
-/// Finds the best match for a given word in the given iterator
-///
-/// As a loose rule to avoid the obviously incorrect suggestions, it takes
-/// an optional limit for the maximum allowable edit distance, which defaults
-/// to one-third of the given word.
-///
-/// Besides Levenshtein, we use case insensitive comparison to improve accuracy on an edge case with
-/// a lower(upper)case letters mismatch.
-pub fn find_best_match_for_name<'a, T>(
-    iter_names: T,
-    lookup: Symbol,
-    dist: Option<usize>,
-) -> Option<Symbol>
-where
-    T: Iterator<Item = &'a Symbol>,
-{
-    let lookup = &lookup.as_str();
-    let max_dist = dist.unwrap_or_else(|| cmp::max(lookup.len(), 3) / 3);
-    let name_vec: Vec<&Symbol> = iter_names.collect();
-
-    let (case_insensitive_match, levenshtein_match) = name_vec
-        .iter()
-        .filter_map(|&name| {
-            let dist = lev_distance(lookup, &name.as_str());
-            if dist <= max_dist { Some((name, dist)) } else { None }
-        })
-        // Here we are collecting the next structure:
-        // (case_insensitive_match, (levenshtein_match, levenshtein_distance))
-        .fold((None, None), |result, (candidate, dist)| {
-            (
-                if candidate.as_str().to_uppercase() == lookup.to_uppercase() {
-                    Some(candidate)
-                } else {
-                    result.0
-                },
-                match result.1 {
-                    None => Some((candidate, dist)),
-                    Some((c, d)) => Some(if dist < d { (candidate, dist) } else { (c, d) }),
-                },
-            )
-        });
-    // Priority of matches:
-    // 1. Exact case insensitive match
-    // 2. Levenshtein distance match
-    // 3. Sorted word match
-    if let Some(candidate) = case_insensitive_match {
-        Some(*candidate)
-    } else if levenshtein_match.is_some() {
-        levenshtein_match.map(|(candidate, _)| *candidate)
-    } else {
-        find_match_by_sorted_words(name_vec, lookup)
-    }
-}
-
-fn find_match_by_sorted_words<'a>(iter_names: Vec<&'a Symbol>, lookup: &str) -> Option<Symbol> {
-    iter_names.iter().fold(None, |result, candidate| {
-        if sort_by_words(&candidate.as_str()) == sort_by_words(lookup) {
-            Some(**candidate)
-        } else {
-            result
-        }
-    })
-}
-
-fn sort_by_words(name: &str) -> String {
-    let mut split_words: Vec<&str> = name.split('_').collect();
-    // We are sorting primitive &strs and can use unstable sort here
-    split_words.sort_unstable();
-    split_words.join("_")
-}
diff --git a/compiler/rustc_ast/src/util/lev_distance/tests.rs b/compiler/rustc_ast/src/util/lev_distance/tests.rs
deleted file mode 100644 (file)
index 7ebedbc..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-use super::*;
-
-#[test]
-fn test_lev_distance() {
-    use std::char::{from_u32, MAX};
-    // Test bytelength agnosticity
-    for c in (0..MAX as u32).filter_map(|i| from_u32(i)).map(|i| i.to_string()) {
-        assert_eq!(lev_distance(&c[..], &c[..]), 0);
-    }
-
-    let a = "\nMäry häd ä little lämb\n\nLittle lämb\n";
-    let b = "\nMary häd ä little lämb\n\nLittle lämb\n";
-    let c = "Mary häd ä little lämb\n\nLittle lämb\n";
-    assert_eq!(lev_distance(a, b), 1);
-    assert_eq!(lev_distance(b, a), 1);
-    assert_eq!(lev_distance(a, c), 2);
-    assert_eq!(lev_distance(c, a), 2);
-    assert_eq!(lev_distance(b, c), 1);
-    assert_eq!(lev_distance(c, b), 1);
-}
-
-#[test]
-fn test_find_best_match_for_name() {
-    use rustc_span::with_default_session_globals;
-    with_default_session_globals(|| {
-        let input = vec![Symbol::intern("aaab"), Symbol::intern("aaabc")];
-        assert_eq!(
-            find_best_match_for_name(input.iter(), Symbol::intern("aaaa"), None),
-            Some(Symbol::intern("aaab"))
-        );
-
-        assert_eq!(
-            find_best_match_for_name(input.iter(), Symbol::intern("1111111111"), None),
-            None
-        );
-
-        let input = vec![Symbol::intern("aAAA")];
-        assert_eq!(
-            find_best_match_for_name(input.iter(), Symbol::intern("AAAA"), None),
-            Some(Symbol::intern("aAAA"))
-        );
-
-        let input = vec![Symbol::intern("AAAA")];
-        // Returns None because `lev_distance > max_dist / 3`
-        assert_eq!(find_best_match_for_name(input.iter(), Symbol::intern("aaaa"), None), None);
-
-        let input = vec![Symbol::intern("AAAA")];
-        assert_eq!(
-            find_best_match_for_name(input.iter(), Symbol::intern("aaaa"), Some(4)),
-            Some(Symbol::intern("AAAA"))
-        );
-
-        let input = vec![Symbol::intern("a_longer_variable_name")];
-        assert_eq!(
-            find_best_match_for_name(input.iter(), Symbol::intern("a_variable_longer_name"), None),
-            Some(Symbol::intern("a_longer_variable_name"))
-        );
-    })
-}
index 560064182e18df54246dcf638f11db15ccaf24ea..61426a838deec62326e70bd3a3f3cc803d924774 100644 (file)
@@ -485,6 +485,9 @@ pub fn walk_assoc_ty_constraint<'a, V: Visitor<'a>>(
     constraint: &'a AssocTyConstraint,
 ) {
     visitor.visit_ident(constraint.ident);
+    if let Some(ref gen_args) = constraint.gen_args {
+        visitor.visit_generic_args(gen_args.span(), gen_args);
+    }
     match constraint.kind {
         AssocTyConstraintKind::Equality { ref ty } => {
             visitor.visit_ty(ty);
@@ -686,7 +689,7 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) {
         StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => visitor.visit_expr(expr),
         StmtKind::Empty => {}
         StmtKind::MacCall(ref mac) => {
-            let MacCallStmt { ref mac, style: _, ref attrs } = **mac;
+            let MacCallStmt { ref mac, style: _, ref attrs, tokens: _ } = **mac;
             visitor.visit_mac_call(mac);
             for attr in attrs.iter() {
                 visitor.visit_attribute(attr);
index f83fc29577bfb30e9b4614beb2ca48758fa0787b..314e5103cc2de3f5ac42868c69d76a626806d9f3 100644 (file)
@@ -353,7 +353,6 @@ fn lower_expr_if(
         let else_arm = self.arm(else_pat, else_expr);
 
         // Handle then + scrutinee:
-        let then_expr = self.lower_block_expr(then);
         let (then_pat, scrutinee, desugar) = match cond.kind {
             // `<pat> => <then>`:
             ExprKind::Let(ref pat, ref scrutinee) => {
@@ -375,6 +374,7 @@ fn lower_expr_if(
                 (pat, cond, hir::MatchSource::IfDesugar { contains_else_clause })
             }
         };
+        let then_expr = self.lower_block_expr(then);
         let then_arm = self.arm(then_pat, self.arena.alloc(then_expr));
 
         hir::ExprKind::Match(scrutinee, arena_vec![self; then_arm, else_arm], desugar)
@@ -400,7 +400,6 @@ fn lower_expr_while_in_loop_scope(
         };
 
         // Handle then + scrutinee:
-        let then_expr = self.lower_block_expr(body);
         let (then_pat, scrutinee, desugar, source) = match cond.kind {
             ExprKind::Let(ref pat, ref scrutinee) => {
                 // to:
@@ -440,6 +439,7 @@ fn lower_expr_while_in_loop_scope(
                 (pat, cond, hir::MatchSource::WhileDesugar, hir::LoopSource::While)
             }
         };
+        let then_expr = self.lower_block_expr(body);
         let then_arm = self.arm(then_pat, self.arena.alloc(then_expr));
 
         // `match <scrutinee> { ... }`
index d353bc19f7aef510d759169cc2446527bafd4ef6..eef6d38aa0584eb407b0051910258811c80384e8 100644 (file)
@@ -43,6 +43,7 @@ fn visit_mod(&mut self, m: &'a Mod, _s: Span, _attrs: &[Attribute], n: NodeId) {
                 items: BTreeSet::new(),
                 trait_items: BTreeSet::new(),
                 impl_items: BTreeSet::new(),
+                foreign_items: BTreeSet::new(),
             },
         );
 
@@ -105,6 +106,18 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
 
         visit::walk_assoc_item(self, item, ctxt);
     }
+
+    fn visit_foreign_item(&mut self, item: &'a ForeignItem) {
+        self.lctx.allocate_hir_id_counter(item.id);
+        self.lctx.with_hir_id_owner(item.id, |lctx| {
+            let hir_item = lctx.lower_foreign_item(item);
+            let id = hir::ForeignItemId { hir_id: hir_item.hir_id };
+            lctx.foreign_items.insert(id, hir_item);
+            lctx.modules.get_mut(&lctx.current_module).unwrap().foreign_items.insert(id);
+        });
+
+        visit::walk_foreign_item(self, item);
+    }
 }
 
 impl<'hir> LoweringContext<'_, 'hir> {
@@ -304,7 +317,12 @@ fn lower_item_kind(
                 })
             }
             ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)),
-            ItemKind::ForeignMod(ref nm) => hir::ItemKind::ForeignMod(self.lower_foreign_mod(nm)),
+            ItemKind::ForeignMod(ref fm) => hir::ItemKind::ForeignMod {
+                abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)),
+                items: self
+                    .arena
+                    .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
+            },
             ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)),
             ItemKind::TyAlias(_, ref gen, _, Some(ref ty)) => {
                 // We lower
@@ -704,10 +722,12 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem<'hir> {
         }
     }
 
-    fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod<'hir> {
-        hir::ForeignMod {
-            abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)),
-            items: self.arena.alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item(x))),
+    fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef<'hir> {
+        hir::ForeignItemRef {
+            id: hir::ForeignItemId { hir_id: self.lower_node_id(i.id) },
+            ident: i.ident,
+            span: i.span,
+            vis: self.lower_visibility(&i.vis, Some(i.id)),
         }
     }
 
index d93655e59050da240db12108043535b8edb7789e..2e1b5a74a7b7e03f4fd280a321d5afed3844437f 100644 (file)
@@ -101,6 +101,7 @@ struct LoweringContext<'a, 'hir: 'a> {
 
     trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem<'hir>>,
     impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem<'hir>>,
+    foreign_items: BTreeMap<hir::ForeignItemId, hir::ForeignItem<'hir>>,
     bodies: BTreeMap<hir::BodyId, hir::Body<'hir>>,
     exported_macros: Vec<hir::MacroDef<'hir>>,
     non_exported_macro_attrs: Vec<ast::Attribute>,
@@ -298,6 +299,7 @@ pub fn lower_crate<'a, 'hir>(
         items: BTreeMap::new(),
         trait_items: BTreeMap::new(),
         impl_items: BTreeMap::new(),
+        foreign_items: BTreeMap::new(),
         bodies: BTreeMap::new(),
         trait_impls: BTreeMap::new(),
         modules: BTreeMap::new(),
@@ -425,7 +427,6 @@ fn lower_crate(mut self, c: &Crate) -> hir::Crate<'hir> {
         /// declared for every type and trait definition.
         struct MiscCollector<'tcx, 'lowering, 'hir> {
             lctx: &'tcx mut LoweringContext<'lowering, 'hir>,
-            hir_id_owner: Option<NodeId>,
         }
 
         impl MiscCollector<'_, '_, '_> {
@@ -452,30 +453,9 @@ fn allocate_use_tree_hir_id_counters(&mut self, tree: &UseTree, owner: LocalDefI
                     }
                 }
             }
-
-            fn with_hir_id_owner<T>(
-                &mut self,
-                owner: Option<NodeId>,
-                f: impl FnOnce(&mut Self) -> T,
-            ) -> T {
-                let old = mem::replace(&mut self.hir_id_owner, owner);
-                let r = f(self);
-                self.hir_id_owner = old;
-                r
-            }
         }
 
         impl<'tcx> Visitor<'tcx> for MiscCollector<'tcx, '_, '_> {
-            fn visit_pat(&mut self, p: &'tcx Pat) {
-                if let PatKind::Paren(..) | PatKind::Rest = p.kind {
-                    // Doesn't generate a HIR node
-                } else if let Some(owner) = self.hir_id_owner {
-                    self.lctx.lower_node_id_with_owner(p.id, owner);
-                }
-
-                visit::walk_pat(self, p)
-            }
-
             fn visit_item(&mut self, item: &'tcx Item) {
                 let hir_id = self.lctx.allocate_hir_id_counter(item.id);
 
@@ -499,24 +479,17 @@ fn visit_item(&mut self, item: &'tcx Item) {
                     _ => {}
                 }
 
-                self.with_hir_id_owner(Some(item.id), |this| {
-                    visit::walk_item(this, item);
-                });
+                visit::walk_item(self, item);
             }
 
             fn visit_assoc_item(&mut self, item: &'tcx AssocItem, ctxt: AssocCtxt) {
                 self.lctx.allocate_hir_id_counter(item.id);
-                let owner = match (&item.kind, ctxt) {
-                    // Ignore patterns in trait methods without bodies.
-                    (AssocItemKind::Fn(_, _, _, None), AssocCtxt::Trait) => None,
-                    _ => Some(item.id),
-                };
-                self.with_hir_id_owner(owner, |this| visit::walk_assoc_item(this, item, ctxt));
+                visit::walk_assoc_item(self, item, ctxt);
             }
 
-            fn visit_foreign_item(&mut self, i: &'tcx ForeignItem) {
-                // Ignore patterns in foreign items
-                self.with_hir_id_owner(None, |this| visit::walk_foreign_item(this, i));
+            fn visit_foreign_item(&mut self, item: &'tcx ForeignItem) {
+                self.lctx.allocate_hir_id_counter(item.id);
+                visit::walk_foreign_item(self, item);
             }
 
             fn visit_ty(&mut self, t: &'tcx Ty) {
@@ -527,18 +500,14 @@ fn visit_ty(&mut self, t: &'tcx Ty) {
                         // Mirrors visit::walk_fn_decl
                         for parameter in &f.decl.inputs {
                             // We don't lower the ids of argument patterns
-                            self.with_hir_id_owner(None, |this| {
-                                this.visit_pat(&parameter.pat);
-                            });
+                            self.visit_pat(&parameter.pat);
                             self.visit_ty(&parameter.ty)
                         }
                         self.visit_fn_ret_ty(&f.decl.output)
                     }
                     TyKind::ImplTrait(def_node_id, _) => {
                         self.lctx.allocate_hir_id_counter(def_node_id);
-                        self.with_hir_id_owner(Some(def_node_id), |this| {
-                            visit::walk_ty(this, t);
-                        });
+                        visit::walk_ty(self, t);
                     }
                     _ => visit::walk_ty(self, t),
                 }
@@ -548,7 +517,7 @@ fn visit_ty(&mut self, t: &'tcx Ty) {
         self.lower_node_id(CRATE_NODE_ID);
         debug_assert!(self.node_id_to_hir_id[CRATE_NODE_ID] == Some(hir::CRATE_HIR_ID));
 
-        visit::walk_crate(&mut MiscCollector { lctx: &mut self, hir_id_owner: None }, c);
+        visit::walk_crate(&mut MiscCollector { lctx: &mut self }, c);
         visit::walk_crate(&mut item::ItemLowerer { lctx: &mut self }, c);
 
         let module = self.lower_mod(&c.module);
@@ -586,6 +555,7 @@ fn visit_ty(&mut self, t: &'tcx Ty) {
             items: self.items,
             trait_items: self.trait_items,
             impl_items: self.impl_items,
+            foreign_items: self.foreign_items,
             bodies: self.bodies,
             body_ids,
             trait_impls: self.trait_impls,
@@ -1038,6 +1008,13 @@ fn lower_assoc_ty_constraint(
     ) -> hir::TypeBinding<'hir> {
         debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx);
 
+        if let Some(ref gen_args) = constraint.gen_args {
+            self.sess.span_fatal(
+                gen_args.span(),
+                "generic associated types in trait paths are currently not implemented",
+            );
+        }
+
         let kind = match constraint.kind {
             AssocTyConstraintKind::Equality { ref ty } => {
                 hir::TypeBindingKind::Equality { ty: self.lower_ty(ty, itctx) }
index bb1d2967d6a4e2bb95954126e4f41b4c66a1219c..4ec3e39facc9f6b6b05e36f97cdc389dc7d78ca6 100644 (file)
@@ -522,7 +522,7 @@ fn check_foreign_fn_headerless(&self, ident: Ident, span: Span, header: FnHeader
             self.err_handler()
                 .struct_span_err(ident.span, "functions in `extern` blocks cannot have qualifiers")
                 .span_label(self.current_extern_span(), "in this `extern` block")
-                .span_suggestion(
+                .span_suggestion_verbose(
                     span.until(ident.span.shrink_to_lo()),
                     "remove the qualifiers",
                     "fn ".to_string(),
@@ -1372,16 +1372,18 @@ fn deny_equality_constraints(
                         if param.ident == *ident {
                             let param = ident;
                             match &full_path.segments[qself.position..] {
-                                [PathSegment { ident, .. }] => {
+                                [PathSegment { ident, args, .. }] => {
                                     // Make a new `Path` from `foo::Bar` to `Foo<Bar = RhsTy>`.
                                     let mut assoc_path = full_path.clone();
                                     // Remove `Bar` from `Foo::Bar`.
                                     assoc_path.segments.pop();
                                     let len = assoc_path.segments.len() - 1;
+                                    let gen_args = args.as_ref().map(|p| (**p).clone());
                                     // Build `<Bar = RhsTy>`.
                                     let arg = AngleBracketedArg::Constraint(AssocTyConstraint {
                                         id: rustc_ast::node_id::DUMMY_NODE_ID,
                                         ident: *ident,
+                                        gen_args,
                                         kind: AssocTyConstraintKind::Equality {
                                             ty: predicate.rhs_ty.clone(),
                                         },
index 181783441f3ff6e1678d4a8004cc9aac8d190b5e..5b75fbf339b92b07be0fc20d91e9dbfb88e1ecf6 100644 (file)
@@ -370,7 +370,7 @@ fn visit_item(&mut self, i: &'a ast::Item) {
             ast::ItemKind::Trait(ast::IsAuto::Yes, ..) => {
                 gate_feature_post!(
                     &self,
-                    optin_builtin_traits,
+                    auto_traits,
                     i.span,
                     "auto traits are experimental and possibly buggy"
                 );
index bfe304419801d5f2c7833170ceb6eaa5012ce23b..7487421e709a763705cae3a16866564056395e5a 100644 (file)
@@ -6,6 +6,7 @@
 
 #![feature(bindings_after_at)]
 #![feature(iter_is_partitioned)]
+#![recursion_limit = "256"]
 
 pub mod ast_validation;
 pub mod feature_gate;
index 2fd625c2a6c260a6fefda2f61555f3d0c2981374..364a3a1eeb5e78c39b0202ed80eea41d8d31e23b 100644 (file)
@@ -67,7 +67,7 @@ fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) {
     }
 }
 
-#[derive(Clone, PartialEq, Encodable, Decodable)]
+#[derive(Copy, Clone, PartialEq, Encodable, Decodable)]
 pub enum InlineAttr {
     None,
     Hint,
index 5bfd8a2bf561c1e9e1f13bb11dc679e933f629e5..bb6d3f6a0076cb54918c608ae35685d5ec571ab1 100644 (file)
@@ -1,8 +1,8 @@
 use rustc_errors::{Applicability, DiagnosticBuilder};
 
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, TokenKind};
-use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
+use rustc_ast::token;
+use rustc_ast::tokenstream::{DelimSpan, TokenStream};
 use rustc_ast::{self as ast, *};
 use rustc_ast_pretty::pprust;
 use rustc_expand::base::*;
@@ -26,31 +26,39 @@ pub fn expand_assert<'cx>(
     // `core::panic` and `std::panic` are different macros, so we use call-site
     // context to pick up whichever is currently in scope.
     let sp = cx.with_call_site_ctxt(sp);
-    let tokens = custom_message.unwrap_or_else(|| {
-        TokenStream::from(TokenTree::token(
-            TokenKind::lit(
-                token::Str,
+
+    let panic_call = if let Some(tokens) = custom_message {
+        // Pass the custom message to panic!().
+        cx.expr(
+            sp,
+            ExprKind::MacCall(MacCall {
+                path: Path::from_ident(Ident::new(sym::panic, sp)),
+                args: P(MacArgs::Delimited(
+                    DelimSpan::from_single(sp),
+                    MacDelimiter::Parenthesis,
+                    tokens,
+                )),
+                prior_type_ascription: None,
+            }),
+        )
+    } else {
+        // Pass our own message directly to $crate::panicking::panic(),
+        // because it might contain `{` and `}` that should always be
+        // passed literally.
+        cx.expr_call_global(
+            sp,
+            cx.std_path(&[sym::panicking, sym::panic]),
+            vec![cx.expr_str(
+                DUMMY_SP,
                 Symbol::intern(&format!(
                     "assertion failed: {}",
                     pprust::expr_to_string(&cond_expr).escape_debug()
                 )),
-                None,
-            ),
-            DUMMY_SP,
-        ))
-    });
-    let args = P(MacArgs::Delimited(DelimSpan::from_single(sp), MacDelimiter::Parenthesis, tokens));
-    let panic_call = MacCall {
-        path: Path::from_ident(Ident::new(sym::panic, sp)),
-        args,
-        prior_type_ascription: None,
+            )],
+        )
     };
-    let if_expr = cx.expr_if(
-        sp,
-        cx.expr(sp, ExprKind::Unary(UnOp::Not, cond_expr)),
-        cx.expr(sp, ExprKind::MacCall(panic_call)),
-        None,
-    );
+    let if_expr =
+        cx.expr_if(sp, cx.expr(sp, ExprKind::Unary(UnOp::Not, cond_expr)), panic_call, None);
     MacEager::expr(if_expr)
 }
 
index 75f4b077640d42e17772dd3467a7fa74d201962b..09ed1af345675befdf9ed2678922cbeeafb30153 100644 (file)
@@ -1,7 +1,7 @@
 //! Implementation of the `#[cfg_accessible(path)]` attribute macro.
 
 use rustc_ast as ast;
-use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
+use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
 use rustc_feature::AttributeTemplate;
 use rustc_parse::validate_attr;
 use rustc_span::symbol::sym;
@@ -31,7 +31,7 @@ impl MultiItemModifier for Expander {
     fn expand(
         &self,
         ecx: &mut ExtCtxt<'_>,
-        _span: Span,
+        span: Span,
         meta_item: &ast::MetaItem,
         item: Annotatable,
     ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
@@ -49,11 +49,14 @@ fn expand(
             None => return ExpandResult::Ready(Vec::new()),
         };
 
-        let failure_msg = "cannot determine whether the path is accessible or not";
         match ecx.resolver.cfg_accessible(ecx.current_expansion.id, path) {
             Ok(true) => ExpandResult::Ready(vec![item]),
             Ok(false) => ExpandResult::Ready(Vec::new()),
-            Err(_) => ExpandResult::Retry(item, failure_msg.into()),
+            Err(Indeterminate) if ecx.force_mode => {
+                ecx.span_err(span, "cannot determine whether the path is accessible or not");
+                ExpandResult::Ready(vec![item])
+            }
+            Err(Indeterminate) => ExpandResult::Retry(item),
         }
     }
 }
index 9381264f498f34938949cba477cd6c113b9d1e85..5c21329069bfc7a35fd3b24949bc47de20700931 100644 (file)
@@ -132,6 +132,7 @@ fn stmt_let_underscore(cx: &mut ExtCtxt<'_>, sp: Span, expr: P<ast::Expr>) -> as
         id: ast::DUMMY_NODE_ID,
         span: sp,
         attrs: ast::AttrVec::new(),
+        tokens: None,
     });
-    ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span: sp, tokens: None }
+    ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span: sp }
 }
index 0642edff6b67817084809fe89a9adcd0343a1ac8..a767de53dae1fcad387ff1e3dc48afbc6f24f3a1 100644 (file)
@@ -407,13 +407,7 @@ pub fn expand_ext(
                             _ => false,
                         })
                     }
-                    _ => {
-                        // Non-ADT derive is an error, but it should have been
-                        // set earlier; see
-                        // librustc_expand/expand.rs:MacroExpander::fully_expand_fragment()
-                        // librustc_expand/base.rs:Annotatable::derive_allowed()
-                        return;
-                    }
+                    _ => unreachable!(),
                 };
                 let container_id = cx.current_expansion.id.expn_data().parent;
                 let always_copy = has_no_type_params && cx.resolver.has_derive_copy(container_id);
@@ -475,12 +469,7 @@ pub fn expand_ext(
                 );
                 push(Annotatable::Item(P(ast::Item { attrs, ..(*newitem).clone() })))
             }
-            _ => {
-                // Non-Item derive is an error, but it should have been
-                // set earlier; see
-                // librustc_expand/expand.rs:MacroExpander::fully_expand_fragment()
-                // librustc_expand/base.rs:Annotatable::derive_allowed()
-            }
+            _ => unreachable!(),
         }
     }
 
index bf95093492880236c425931b1e722ef6c141e5c5..1651180817b9ddbfa2a2ea3edc94e46658e77151 100644 (file)
@@ -54,7 +54,26 @@ fn expand(
         // so we are doing it here in a centralized way.
         let span = ecx.with_def_site_ctxt(span);
         let mut items = Vec::new();
-        (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a));
+        match item {
+            Annotatable::Stmt(stmt) => {
+                if let ast::StmtKind::Item(item) = stmt.into_inner().kind {
+                    (self.0)(ecx, span, meta_item, &Annotatable::Item(item), &mut |a| {
+                        // Cannot use 'ecx.stmt_item' here, because we need to pass 'ecx'
+                        // to the function
+                        items.push(Annotatable::Stmt(P(ast::Stmt {
+                            id: ast::DUMMY_NODE_ID,
+                            kind: ast::StmtKind::Item(a.expect_item()),
+                            span,
+                        })));
+                    });
+                } else {
+                    unreachable!("should have already errored on non-item statement")
+                }
+            }
+            _ => {
+                (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a));
+            }
+        }
         ExpandResult::Ready(items)
     }
 }
@@ -98,13 +117,7 @@ fn inject_impl_of_structural_trait(
 ) {
     let item = match *item {
         Annotatable::Item(ref item) => item,
-        _ => {
-            // Non-Item derive is an error, but it should have been
-            // set earlier; see
-            // librustc_expand/expand.rs:MacroExpander::fully_expand_fragment()
-            // librustc_expand/base.rs:Annotatable::derive_allowed()
-            return;
-        }
+        _ => unreachable!(),
     };
 
     let generics = match item.kind {
index b69b00d65f2be522633d4e76112b23d059afed02..f00dfd1241fbbb6287ac8b91121874128deecc32 100644 (file)
@@ -649,17 +649,13 @@ pub struct Substitutions<'a> {
     impl<'a> Iterator for Substitutions<'a> {
         type Item = Substitution<'a>;
         fn next(&mut self) -> Option<Self::Item> {
-            match parse_next_substitution(self.s) {
-                Some((mut sub, tail)) => {
-                    self.s = tail;
-                    if let Some(InnerSpan { start, end }) = sub.position() {
-                        sub.set_position(start + self.pos, end + self.pos);
-                        self.pos += end;
-                    }
-                    Some(sub)
-                }
-                None => None,
+            let (mut sub, tail) = parse_next_substitution(self.s)?;
+            self.s = tail;
+            if let Some(InnerSpan { start, end }) = sub.position() {
+                sub.set_position(start + self.pos, end + self.pos);
+                self.pos += end;
             }
+            Some(sub)
         }
 
         fn size_hint(&self) -> (usize, Option<usize>) {
index 8478fcfbf09a6725f68f647a6c79dd226aebbc6d..e976805d9dd2070b58e3a1ee6cccfb1122602219 100644 (file)
@@ -4,7 +4,7 @@
     AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS,
 };
 use rustc_ast::ptr::P;
-use rustc_ast::{self as ast, Attribute, Expr, FnHeader, FnSig, Generics, Param};
+use rustc_ast::{self as ast, Attribute, Expr, FnHeader, FnSig, Generics, Param, StmtKind};
 use rustc_ast::{ItemKind, Mutability, Stmt, Ty, TyKind, Unsafe};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -14,7 +14,7 @@ pub fn expand(
     ecx: &mut ExtCtxt<'_>,
     _span: Span,
     meta_item: &ast::MetaItem,
-    item: Annotatable,
+    mut item: Annotatable,
 ) -> Vec<Annotatable> {
     check_builtin_macro_attribute(ecx, meta_item, sym::global_allocator);
 
@@ -22,6 +22,17 @@ pub fn expand(
         ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics");
         vec![item]
     };
+    let orig_item = item.clone();
+    let mut is_stmt = false;
+
+    // Allow using `#[global_allocator]` on an item statement
+    if let Annotatable::Stmt(stmt) = &item {
+        if let StmtKind::Item(item_) = &stmt.kind {
+            item = Annotatable::Item(item_.clone());
+            is_stmt = true;
+        }
+    }
+
     let item = match item {
         Annotatable::Item(item) => match item.kind {
             ItemKind::Static(..) => item,
@@ -41,9 +52,14 @@ pub fn expand(
     let const_ty = ecx.ty(span, TyKind::Tup(Vec::new()));
     let const_body = ecx.expr_block(ecx.block(span, stmts));
     let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
+    let const_item = if is_stmt {
+        Annotatable::Stmt(P(ecx.stmt_item(span, const_item)))
+    } else {
+        Annotatable::Item(const_item)
+    };
 
     // Return the original item and the new methods.
-    vec![Annotatable::Item(item), Annotatable::Item(const_item)]
+    vec![orig_item, const_item]
 }
 
 struct AllocFnFactory<'a, 'b> {
index 1de0b32f5196b3b27b8a5632b171cbfaf42ca88e..25d3f46da6cdc323f615c2476e29096c232a3a29 100644 (file)
@@ -4,6 +4,7 @@
 
 use rustc_ast as ast;
 use rustc_ast::attr;
+use rustc_ast::ptr::P;
 use rustc_ast_pretty::pprust;
 use rustc_expand::base::*;
 use rustc_session::Session;
@@ -78,8 +79,16 @@ pub fn expand_test_or_bench(
         return vec![];
     }
 
-    let item = match item {
-        Annotatable::Item(i) => i,
+    let (item, is_stmt) = match item {
+        Annotatable::Item(i) => (i, false),
+        Annotatable::Stmt(stmt) if matches!(stmt.kind, ast::StmtKind::Item(_)) => {
+            // FIXME: Use an 'if let' guard once they are implemented
+            if let ast::StmtKind::Item(i) = stmt.into_inner().kind {
+                (i, true)
+            } else {
+                unreachable!()
+            }
+        }
         other => {
             cx.struct_span_err(
                 other.span(),
@@ -304,14 +313,25 @@ pub fn expand_test_or_bench(
 
     tracing::debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
 
-    vec![
-        // Access to libtest under a hygienic name
-        Annotatable::Item(test_extern),
-        // The generated test case
-        Annotatable::Item(test_const),
-        // The original item
-        Annotatable::Item(item),
-    ]
+    if is_stmt {
+        vec![
+            // Access to libtest under a hygienic name
+            Annotatable::Stmt(P(cx.stmt_item(sp, test_extern))),
+            // The generated test case
+            Annotatable::Stmt(P(cx.stmt_item(sp, test_const))),
+            // The original item
+            Annotatable::Stmt(P(cx.stmt_item(sp, item))),
+        ]
+    } else {
+        vec![
+            // Access to libtest under a hygienic name
+            Annotatable::Item(test_extern),
+            // The generated test case
+            Annotatable::Item(test_const),
+            // The original item
+            Annotatable::Item(item),
+        ]
+    }
 }
 
 fn item_path(mod_path: &[Ident], item_ident: &Ident) -> String {
index ca145e4f2a52058a6fff6f2282da94b6e529e165..c832d5e5ebb9b5feb32db0cb4ec33736677536ea 100644 (file)
@@ -23,7 +23,7 @@
     all(target_arch = "wasm32", not(target_os = "emscripten")),
     feature(integer_atomics, stdsimd)
 )]
-#![cfg_attr(any(unix, target_os = "cloudabi", target_os = "redox"), feature(libc))]
+#![cfg_attr(any(unix, target_os = "redox"), feature(libc))]
 // The minimum alignment guaranteed by the architecture. This value is used to
 // add fast paths for low alignment values.
 #[cfg(all(any(target_arch = "x86",
@@ -69,7 +69,7 @@
 /// independently of the standard library’s global allocator.
 #[stable(feature = "alloc_system_type", since = "1.28.0")]
 pub struct System;
-#[cfg(any(windows, unix, target_os = "cloudabi", target_os = "redox"))]
+#[cfg(any(windows, unix, target_os = "redox"))]
 mod realloc_fallback {
     use core::alloc::{GlobalAlloc, Layout};
     use core::cmp;
@@ -89,7 +89,7 @@ pub(crate) unsafe fn realloc_fallback(&self, ptr: *mut u8, old_layout: Layout,
         }
     }
 }
-#[cfg(any(unix, target_os = "cloudabi", target_os = "redox"))]
+#[cfg(any(unix, target_os = "redox"))]
 mod platform {
     extern crate libc;
     use core::ptr;
index ce07fe83df18f2b09f663113aad431002e98e956..10cba992056292c515319787ae13bcd05e673401 100644 (file)
@@ -1,6 +1,6 @@
 #![feature(
     no_core, lang_items, intrinsics, unboxed_closures, type_ascription, extern_types,
-    untagged_unions, decl_macro, rustc_attrs, transparent_unions, optin_builtin_traits,
+    untagged_unions, decl_macro, rustc_attrs, transparent_unions, auto_traits,
     thread_local,
 )]
 #![no_core]
index 7857ccb613bf8abd7fe212b11576986f80e49c7d..915dd3d9eda1586ecef67545eb8514b309e790cb 100644 (file)
@@ -36,17 +36,17 @@ fn for_each_kind<F>(&self, mut f: F)
     where
         F: FnMut(llvm::Attribute),
     {
-        for_each_kind!(self, f, NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt, InReg)
+        for_each_kind!(self, f, NoAlias, NoCapture, NonNull, ReadOnly, InReg)
     }
 }
 
 pub trait ArgAttributesExt {
-    fn apply_llfn(&self, idx: AttributePlace, llfn: &Value, ty: Option<&Type>);
-    fn apply_callsite(&self, idx: AttributePlace, callsite: &Value, ty: Option<&Type>);
+    fn apply_attrs_to_llfn(&self, idx: AttributePlace, llfn: &Value);
+    fn apply_attrs_to_callsite(&self, idx: AttributePlace, callsite: &Value);
 }
 
 impl ArgAttributesExt for ArgAttributes {
-    fn apply_llfn(&self, idx: AttributePlace, llfn: &Value, ty: Option<&Type>) {
+    fn apply_attrs_to_llfn(&self, idx: AttributePlace, llfn: &Value) {
         let mut regular = self.regular;
         unsafe {
             let deref = self.pointee_size.bytes();
@@ -61,14 +61,20 @@ fn apply_llfn(&self, idx: AttributePlace, llfn: &Value, ty: Option<&Type>) {
             if let Some(align) = self.pointee_align {
                 llvm::LLVMRustAddAlignmentAttr(llfn, idx.as_uint(), align.bytes() as u32);
             }
-            if regular.contains(ArgAttribute::ByVal) {
-                llvm::LLVMRustAddByValAttr(llfn, idx.as_uint(), ty.unwrap());
-            }
             regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn));
+            match self.arg_ext {
+                ArgExtension::None => {}
+                ArgExtension::Zext => {
+                    llvm::Attribute::ZExt.apply_llfn(idx, llfn);
+                }
+                ArgExtension::Sext => {
+                    llvm::Attribute::SExt.apply_llfn(idx, llfn);
+                }
+            }
         }
     }
 
-    fn apply_callsite(&self, idx: AttributePlace, callsite: &Value, ty: Option<&Type>) {
+    fn apply_attrs_to_callsite(&self, idx: AttributePlace, callsite: &Value) {
         let mut regular = self.regular;
         unsafe {
             let deref = self.pointee_size.bytes();
@@ -91,10 +97,16 @@ fn apply_callsite(&self, idx: AttributePlace, callsite: &Value, ty: Option<&Type
                     align.bytes() as u32,
                 );
             }
-            if regular.contains(ArgAttribute::ByVal) {
-                llvm::LLVMRustAddByValCallSiteAttr(callsite, idx.as_uint(), ty.unwrap());
-            }
             regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite));
+            match self.arg_ext {
+                ArgExtension::None => {}
+                ArgExtension::Zext => {
+                    llvm::Attribute::ZExt.apply_callsite(idx, callsite);
+                }
+                ArgExtension::Sext => {
+                    llvm::Attribute::SExt.apply_callsite(idx, callsite);
+                }
+            }
         }
     }
 }
@@ -146,7 +158,7 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type {
             .prefix
             .iter()
             .flat_map(|option_kind| {
-                option_kind.map(|kind| Reg { kind, size: self.prefix_chunk }.llvm_type(cx))
+                option_kind.map(|kind| Reg { kind, size: self.prefix_chunk_size }.llvm_type(cx))
             })
             .chain((0..rest_count).map(|_| rest_ll_unit))
             .collect();
@@ -267,10 +279,12 @@ fn store_fn_arg(
             PassMode::Pair(..) => {
                 OperandValue::Pair(next(), next()).store(bx, dst);
             }
-            PassMode::Indirect(_, Some(_)) => {
+            PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => {
                 OperandValue::Ref(next(), Some(next()), self.layout.align.abi).store(bx, dst);
             }
-            PassMode::Direct(_) | PassMode::Indirect(_, None) | PassMode::Cast(_) => {
+            PassMode::Direct(_)
+            | PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ }
+            | PassMode::Cast(_) => {
                 let next_arg = next();
                 self.store(bx, next_arg, dst);
             }
@@ -315,14 +329,14 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
             if let PassMode::Pair(_, _) = arg.mode { 2 } else { 1 }
         ).sum();
         let mut llargument_tys = Vec::with_capacity(
-            if let PassMode::Indirect(..) = self.ret.mode { 1 } else { 0 } + args_capacity,
+            if let PassMode::Indirect { .. } = self.ret.mode { 1 } else { 0 } + args_capacity,
         );
 
         let llreturn_ty = match self.ret.mode {
             PassMode::Ignore => cx.type_void(),
             PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_llvm_type(cx),
             PassMode::Cast(cast) => cast.llvm_type(cx),
-            PassMode::Indirect(..) => {
+            PassMode::Indirect { .. } => {
                 llargument_tys.push(cx.type_ptr_to(self.ret.memory_ty(cx)));
                 cx.type_void()
             }
@@ -342,7 +356,7 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
                     llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 1, true));
                     continue;
                 }
-                PassMode::Indirect(_, Some(_)) => {
+                PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => {
                     let ptr_ty = cx.tcx.mk_mut_ptr(arg.layout.ty);
                     let ptr_layout = cx.layout_of(ptr_ty);
                     llargument_tys.push(ptr_layout.scalar_pair_element_llvm_type(cx, 0, true));
@@ -350,7 +364,9 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
                     continue;
                 }
                 PassMode::Cast(cast) => cast.llvm_type(cx),
-                PassMode::Indirect(_, None) => cx.type_ptr_to(arg.memory_ty(cx)),
+                PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => {
+                    cx.type_ptr_to(arg.memory_ty(cx))
+                }
             };
             llargument_tys.push(llarg_ty);
         }
@@ -402,35 +418,54 @@ fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) {
         }
 
         let mut i = 0;
-        let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| {
-            attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn, ty);
+        let mut apply = |attrs: &ArgAttributes| {
+            attrs.apply_attrs_to_llfn(llvm::AttributePlace::Argument(i), llfn);
             i += 1;
+            i - 1
         };
         match self.ret.mode {
             PassMode::Direct(ref attrs) => {
-                attrs.apply_llfn(llvm::AttributePlace::ReturnValue, llfn, None);
+                attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, llfn);
+            }
+            PassMode::Indirect { ref attrs, extra_attrs: _, on_stack } => {
+                assert!(!on_stack);
+                let i = apply(attrs);
+                llvm::Attribute::StructRet.apply_llfn(llvm::AttributePlace::Argument(i), llfn);
             }
-            PassMode::Indirect(ref attrs, _) => apply(attrs, Some(self.ret.layout.llvm_type(cx))),
             _ => {}
         }
         for arg in &self.args {
             if arg.pad.is_some() {
-                apply(&ArgAttributes::new(), None);
+                apply(&ArgAttributes::new());
             }
             match arg.mode {
                 PassMode::Ignore => {}
-                PassMode::Direct(ref attrs) | PassMode::Indirect(ref attrs, None) => {
-                    apply(attrs, Some(arg.layout.llvm_type(cx)))
+                PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: true } => {
+                    let i = apply(attrs);
+                    unsafe {
+                        llvm::LLVMRustAddByValAttr(
+                            llfn,
+                            llvm::AttributePlace::Argument(i).as_uint(),
+                            arg.layout.llvm_type(cx),
+                        );
+                    }
                 }
-                PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {
-                    apply(attrs, None);
-                    apply(extra_attrs, None);
+                PassMode::Direct(ref attrs)
+                | PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: false } => {
+                    apply(attrs);
+                }
+                PassMode::Indirect { ref attrs, extra_attrs: Some(ref extra_attrs), on_stack } => {
+                    assert!(!on_stack);
+                    apply(attrs);
+                    apply(extra_attrs);
                 }
                 PassMode::Pair(ref a, ref b) => {
-                    apply(a, None);
-                    apply(b, None);
+                    apply(a);
+                    apply(b);
+                }
+                PassMode::Cast(_) => {
+                    apply(&ArgAttributes::new());
                 }
-                PassMode::Cast(_) => apply(&ArgAttributes::new(), None),
             }
         }
     }
@@ -439,15 +474,21 @@ fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll V
         // FIXME(wesleywiser, eddyb): We should apply `nounwind` and `noreturn` as appropriate to this callsite.
 
         let mut i = 0;
-        let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| {
-            attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite, ty);
+        let mut apply = |attrs: &ArgAttributes| {
+            attrs.apply_attrs_to_callsite(llvm::AttributePlace::Argument(i), callsite);
             i += 1;
+            i - 1
         };
         match self.ret.mode {
             PassMode::Direct(ref attrs) => {
-                attrs.apply_callsite(llvm::AttributePlace::ReturnValue, callsite, None);
+                attrs.apply_attrs_to_callsite(llvm::AttributePlace::ReturnValue, callsite);
+            }
+            PassMode::Indirect { ref attrs, extra_attrs: _, on_stack } => {
+                assert!(!on_stack);
+                let i = apply(attrs);
+                llvm::Attribute::StructRet
+                    .apply_callsite(llvm::AttributePlace::Argument(i), callsite);
             }
-            PassMode::Indirect(ref attrs, _) => apply(attrs, Some(self.ret.layout.llvm_type(bx))),
             _ => {}
         }
         if let abi::Abi::Scalar(ref scalar) = self.ret.layout.abi {
@@ -465,22 +506,39 @@ fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll V
         }
         for arg in &self.args {
             if arg.pad.is_some() {
-                apply(&ArgAttributes::new(), None);
+                apply(&ArgAttributes::new());
             }
             match arg.mode {
                 PassMode::Ignore => {}
-                PassMode::Direct(ref attrs) | PassMode::Indirect(ref attrs, None) => {
-                    apply(attrs, Some(arg.layout.llvm_type(bx)))
+                PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: true } => {
+                    let i = apply(attrs);
+                    unsafe {
+                        llvm::LLVMRustAddByValCallSiteAttr(
+                            callsite,
+                            llvm::AttributePlace::Argument(i).as_uint(),
+                            arg.layout.llvm_type(bx),
+                        );
+                    }
                 }
-                PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {
-                    apply(attrs, None);
-                    apply(extra_attrs, None);
+                PassMode::Direct(ref attrs)
+                | PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: false } => {
+                    apply(attrs);
+                }
+                PassMode::Indirect {
+                    ref attrs,
+                    extra_attrs: Some(ref extra_attrs),
+                    on_stack: _,
+                } => {
+                    apply(attrs);
+                    apply(extra_attrs);
                 }
                 PassMode::Pair(ref a, ref b) => {
-                    apply(a, None);
-                    apply(b, None);
+                    apply(a);
+                    apply(b);
+                }
+                PassMode::Cast(_) => {
+                    apply(&ArgAttributes::new());
                 }
-                PassMode::Cast(_) => apply(&ArgAttributes::new(), None),
             }
         }
 
index 9a2fbf359ea127d71d1ae4fd0c761de053dbfb75..62a7986c194f0309b24a420dccef066e81554b54 100644 (file)
@@ -25,7 +25,7 @@
 
 /// Mark LLVM function to use provided inline heuristic.
 #[inline]
-fn inline(cx: &CodegenCx<'ll, '_>, val: &'ll Value, inline: InlineAttr, requires_inline: bool) {
+fn inline(cx: &CodegenCx<'ll, '_>, val: &'ll Value, inline: InlineAttr) {
     use self::InlineAttr::*;
     match inline {
         Hint => Attribute::InlineHint.apply_llfn(Function, val),
@@ -35,7 +35,6 @@ fn inline(cx: &CodegenCx<'ll, '_>, val: &'ll Value, inline: InlineAttr, requires
                 Attribute::NoInline.apply_llfn(Function, val);
             }
         }
-        None if requires_inline => Attribute::InlineHint.apply_llfn(Function, val),
         None => {}
     };
 }
@@ -226,7 +225,14 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::
         }
     }
 
-    inline(cx, llfn, codegen_fn_attrs.inline.clone(), instance.def.requires_inline(cx.tcx));
+    let inline_attr = if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
+        InlineAttr::Never
+    } else if codegen_fn_attrs.inline == InlineAttr::None && instance.def.requires_inline(cx.tcx) {
+        InlineAttr::Hint
+    } else {
+        codegen_fn_attrs.inline
+    };
+    inline(cx, llfn, inline_attr);
 
     // The `uwtable` attribute according to LLVM is:
     //
index 6f956c3bcc1ce5da4c405adda97e32f75a79068f..7407dfc455d84b5c19f28c3abd2aa1d24ccf58de 100644 (file)
@@ -152,7 +152,8 @@ pub fn target_machine_factory(
     let features = features.join(",");
     let features = CString::new(features).unwrap();
     let abi = SmallCStr::new(&sess.target.llvm_abiname);
-    let trap_unreachable = sess.target.trap_unreachable;
+    let trap_unreachable =
+        sess.opts.debugging_opts.trap_unreachable.unwrap_or(sess.target.trap_unreachable);
     let emit_stack_size_section = sess.opts.debugging_opts.emit_stack_sizes;
 
     let asm_comments = sess.asm_comments();
index 41827a91ba4be27c0a66b86c42813c5a473eeb0e..85aaa7e8893bfa107e4985089a0a50169a943fe2 100644 (file)
@@ -4,7 +4,7 @@
 
 use llvm::coverageinfo::CounterMappingRegion;
 use rustc_codegen_ssa::coverageinfo::map::{Counter, CounterExpression};
-use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods};
+use rustc_codegen_ssa::traits::ConstMethods;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_llvm::RustString;
 use rustc_middle::mir::coverage::CodeRegion;
@@ -15,9 +15,9 @@
 
 /// Generates and exports the Coverage Map.
 ///
-/// This Coverage Map complies with Coverage Mapping Format version 3 (zero-based encoded as 2),
-/// as defined at [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/llvmorg-8.0.0/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format)
-/// and published in Rust's current (July 2020) fork of LLVM. This version is supported by the
+/// This Coverage Map complies with Coverage Mapping Format version 4 (zero-based encoded as 3),
+/// as defined at [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format)
+/// and published in Rust's current (November 2020) fork of LLVM. This version is supported by the
 /// LLVM coverage tools (`llvm-profdata` and `llvm-cov`) bundled with Rust's fork of LLVM.
 ///
 /// Consequently, Rust's bundled version of Clang also generates Coverage Maps compliant with
 /// undocumented details in Clang's implementation (that may or may not be important) were also
 /// replicated for Rust's Coverage Map.
 pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
+    // Ensure LLVM supports Coverage Map Version 4 (encoded as a zero-based value: 3).
+    // If not, the LLVM Version must be less than 11.
+    let version = coverageinfo::mapping_version();
+    if version != 3 {
+        cx.tcx.sess.fatal("rustc option `-Z instrument-coverage` requires LLVM 11 or higher.");
+    }
+
     let function_coverage_map = match cx.coverage_context() {
         Some(ctx) => ctx.take_function_coverage_map(),
         None => return,
@@ -38,46 +45,50 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
     let mut mapgen = CoverageMapGenerator::new();
 
     // Encode coverage mappings and generate function records
-    let mut function_records = Vec::<&'ll llvm::Value>::new();
-    let coverage_mappings_buffer = llvm::build_byte_buffer(|coverage_mappings_buffer| {
-        for (instance, function_coverage) in function_coverage_map.into_iter() {
-            debug!("Generate coverage map for: {:?}", instance);
-
-            let mangled_function_name = cx.tcx.symbol_name(instance).to_string();
-            let function_source_hash = function_coverage.source_hash();
-            let (expressions, counter_regions) =
-                function_coverage.get_expressions_and_counter_regions();
-
-            let old_len = coverage_mappings_buffer.len();
-            mapgen.write_coverage_mappings(expressions, counter_regions, coverage_mappings_buffer);
-            let mapping_data_size = coverage_mappings_buffer.len() - old_len;
-            debug_assert!(
-                mapping_data_size > 0,
-                "Every `FunctionCoverage` should have at least one counter"
-            );
-
-            let function_record = mapgen.make_function_record(
-                cx,
-                mangled_function_name,
-                function_source_hash,
-                mapping_data_size,
-            );
-            function_records.push(function_record);
-        }
-    });
+    let mut function_data = Vec::new();
+    for (instance, function_coverage) in function_coverage_map {
+        debug!("Generate coverage map for: {:?}", instance);
+
+        let mangled_function_name = cx.tcx.symbol_name(instance).to_string();
+        let function_source_hash = function_coverage.source_hash();
+        let (expressions, counter_regions) =
+            function_coverage.get_expressions_and_counter_regions();
+
+        let coverage_mapping_buffer = llvm::build_byte_buffer(|coverage_mapping_buffer| {
+            mapgen.write_coverage_mapping(expressions, counter_regions, coverage_mapping_buffer);
+        });
+        debug_assert!(
+            coverage_mapping_buffer.len() > 0,
+            "Every `FunctionCoverage` should have at least one counter"
+        );
+
+        function_data.push((mangled_function_name, function_source_hash, coverage_mapping_buffer));
+    }
 
     // Encode all filenames referenced by counters/expressions in this module
     let filenames_buffer = llvm::build_byte_buffer(|filenames_buffer| {
         coverageinfo::write_filenames_section_to_buffer(&mapgen.filenames, filenames_buffer);
     });
 
+    let filenames_size = filenames_buffer.len();
+    let filenames_val = cx.const_bytes(&filenames_buffer[..]);
+    let filenames_ref = coverageinfo::hash_bytes(filenames_buffer);
+
     // Generate the LLVM IR representation of the coverage map and store it in a well-known global
-    mapgen.save_generated_coverage_map(
-        cx,
-        function_records,
-        filenames_buffer,
-        coverage_mappings_buffer,
-    );
+    let cov_data_val = mapgen.generate_coverage_map(cx, version, filenames_size, filenames_val);
+
+    for (mangled_function_name, function_source_hash, coverage_mapping_buffer) in function_data {
+        save_function_record(
+            cx,
+            mangled_function_name,
+            function_source_hash,
+            filenames_ref,
+            coverage_mapping_buffer,
+        );
+    }
+
+    // Save the coverage data value to LLVM IR
+    coverageinfo::save_cov_data_to_mod(cx, cov_data_val);
 }
 
 struct CoverageMapGenerator {
@@ -92,12 +103,12 @@ fn new() -> Self {
     /// Using the `expressions` and `counter_regions` collected for the current function, generate
     /// the `mapping_regions` and `virtual_file_mapping`, and capture any new filenames. Then use
     /// LLVM APIs to encode the `virtual_file_mapping`, `expressions`, and `mapping_regions` into
-    /// the given `coverage_mappings` byte buffer, compliant with the LLVM Coverage Mapping format.
-    fn write_coverage_mappings(
+    /// the given `coverage_mapping` byte buffer, compliant with the LLVM Coverage Mapping format.
+    fn write_coverage_mapping(
         &mut self,
         expressions: Vec<CounterExpression>,
         counter_regions: impl Iterator<Item = (Counter, &'a CodeRegion)>,
-        coverage_mappings_buffer: &RustString,
+        coverage_mapping_buffer: &RustString,
     ) {
         let mut counter_regions = counter_regions.collect::<Vec<_>>();
         if counter_regions.is_empty() {
@@ -145,89 +156,75 @@ fn write_coverage_mappings(
             virtual_file_mapping,
             expressions,
             mapping_regions,
-            coverage_mappings_buffer,
+            coverage_mapping_buffer,
         );
     }
 
-    /// Generate and return the function record `Value`
-    fn make_function_record(
-        &mut self,
-        cx: &CodegenCx<'ll, 'tcx>,
-        mangled_function_name: String,
-        function_source_hash: u64,
-        mapping_data_size: usize,
-    ) -> &'ll llvm::Value {
-        let name_ref = coverageinfo::compute_hash(&mangled_function_name);
-        let name_ref_val = cx.const_u64(name_ref);
-        let mapping_data_size_val = cx.const_u32(mapping_data_size as u32);
-        let func_hash_val = cx.const_u64(function_source_hash);
-        cx.const_struct(
-            &[name_ref_val, mapping_data_size_val, func_hash_val],
-            /*packed=*/ true,
-        )
-    }
-
-    /// Combine the filenames and coverage mappings buffers, construct coverage map header and the
-    /// array of function records, and combine everything into the complete coverage map. Save the
-    /// coverage map data into the LLVM IR as a static global using a specific, well-known section
-    /// and name.
-    fn save_generated_coverage_map(
+    /// Construct coverage map header and the array of function records, and combine them into the
+    /// coverage map. Save the coverage map data into the LLVM IR as a static global using a
+    /// specific, well-known section and name.
+    fn generate_coverage_map(
         self,
         cx: &CodegenCx<'ll, 'tcx>,
-        function_records: Vec<&'ll llvm::Value>,
-        filenames_buffer: Vec<u8>,
-        mut coverage_mappings_buffer: Vec<u8>,
-    ) {
-        // Concatenate the encoded filenames and encoded coverage mappings, and add additional zero
-        // bytes as-needed to ensure 8-byte alignment.
-        let mut coverage_size = coverage_mappings_buffer.len();
-        let filenames_size = filenames_buffer.len();
-        let remaining_bytes =
-            (filenames_size + coverage_size) % coverageinfo::COVMAP_VAR_ALIGN_BYTES;
-        if remaining_bytes > 0 {
-            let pad = coverageinfo::COVMAP_VAR_ALIGN_BYTES - remaining_bytes;
-            coverage_mappings_buffer.append(&mut [0].repeat(pad));
-            coverage_size += pad;
-        }
-        let filenames_and_coverage_mappings = [filenames_buffer, coverage_mappings_buffer].concat();
-        let filenames_and_coverage_mappings_val =
-            cx.const_bytes(&filenames_and_coverage_mappings[..]);
-
-        debug!(
-            "cov map: n_records = {}, filenames_size = {}, coverage_size = {}, 0-based version = {}",
-            function_records.len(),
-            filenames_size,
-            coverage_size,
-            coverageinfo::mapping_version()
-        );
+        version: u32,
+        filenames_size: usize,
+        filenames_val: &'ll llvm::Value,
+    ) -> &'ll llvm::Value {
+        debug!("cov map: filenames_size = {}, 0-based version = {}", filenames_size, version);
 
-        // Create the coverage data header
-        let n_records_val = cx.const_u32(function_records.len() as u32);
+        // Create the coverage data header (Note, fields 0 and 2 are now always zero,
+        // as of `llvm::coverage::CovMapVersion::Version4`.)
+        let zero_was_n_records_val = cx.const_u32(0);
         let filenames_size_val = cx.const_u32(filenames_size as u32);
-        let coverage_size_val = cx.const_u32(coverage_size as u32);
-        let version_val = cx.const_u32(coverageinfo::mapping_version());
+        let zero_was_coverage_size_val = cx.const_u32(0);
+        let version_val = cx.const_u32(version);
         let cov_data_header_val = cx.const_struct(
-            &[n_records_val, filenames_size_val, coverage_size_val, version_val],
+            &[zero_was_n_records_val, filenames_size_val, zero_was_coverage_size_val, version_val],
             /*packed=*/ false,
         );
 
-        // Create the function records array
-        let name_ref_from_u64 = cx.type_i64();
-        let mapping_data_size_from_u32 = cx.type_i32();
-        let func_hash_from_u64 = cx.type_i64();
-        let function_record_ty = cx.type_struct(
-            &[name_ref_from_u64, mapping_data_size_from_u32, func_hash_from_u64],
-            /*packed=*/ true,
-        );
-        let function_records_val = cx.const_array(function_record_ty, &function_records[..]);
-
         // Create the complete LLVM coverage data value to add to the LLVM IR
-        let cov_data_val = cx.const_struct(
-            &[cov_data_header_val, function_records_val, filenames_and_coverage_mappings_val],
-            /*packed=*/ false,
-        );
-
-        // Save the coverage data value to LLVM IR
-        coverageinfo::save_map_to_mod(cx, cov_data_val);
+        cx.const_struct(&[cov_data_header_val, filenames_val], /*packed=*/ false)
     }
 }
+
+/// Construct a function record and combine it with the function's coverage mapping data.
+/// Save the function record into the LLVM IR as a static global using a
+/// specific, well-known section and name.
+fn save_function_record(
+    cx: &CodegenCx<'ll, 'tcx>,
+    mangled_function_name: String,
+    function_source_hash: u64,
+    filenames_ref: u64,
+    coverage_mapping_buffer: Vec<u8>,
+) {
+    // Concatenate the encoded coverage mappings
+    let coverage_mapping_size = coverage_mapping_buffer.len();
+    let coverage_mapping_val = cx.const_bytes(&coverage_mapping_buffer[..]);
+
+    let func_name_hash = coverageinfo::hash_str(&mangled_function_name);
+    let func_name_hash_val = cx.const_u64(func_name_hash);
+    let coverage_mapping_size_val = cx.const_u32(coverage_mapping_size as u32);
+    let func_hash_val = cx.const_u64(function_source_hash);
+    let filenames_ref_val = cx.const_u64(filenames_ref);
+    let func_record_val = cx.const_struct(
+        &[
+            func_name_hash_val,
+            coverage_mapping_size_val,
+            func_hash_val,
+            filenames_ref_val,
+            coverage_mapping_val,
+        ],
+        /*packed=*/ true,
+    );
+
+    // At the present time, the coverage map for Rust assumes every instrumented function `is_used`.
+    // Note that Clang marks functions as "unused" in `CodeGenPGO::emitEmptyCounterMapping`. (See:
+    // https://github.com/rust-lang/llvm-project/blob/de02a75e398415bad4df27b4547c25b896c8bf3b/clang%2Flib%2FCodeGen%2FCodeGenPGO.cpp#L877-L878
+    // for example.)
+    //
+    // It's not yet clear if or how this may be applied to Rust in the future, but the `is_used`
+    // argument is available and handled similarly.
+    let is_used = true;
+    coverageinfo::save_func_record_to_mod(cx, func_name_hash, func_record_val, is_used);
+}
index e21e03822ebb3cda5a3147839a2d2345ed8307bd..e777f363eb0842ee25be12f5254eb986a7b54dea 100644 (file)
@@ -23,7 +23,7 @@
 
 pub mod mapgen;
 
-const COVMAP_VAR_ALIGN_BYTES: usize = 8;
+const VAR_ALIGN_BYTES: usize = 8;
 
 /// A context object for maintaining all state needed by the coverageinfo module.
 pub struct CrateCoverageContext<'tcx> {
@@ -177,17 +177,20 @@ pub(crate) fn write_mapping_to_buffer(
         );
     }
 }
+pub(crate) fn hash_str(strval: &str) -> u64 {
+    let strval = CString::new(strval).expect("null error converting hashable str to C string");
+    unsafe { llvm::LLVMRustCoverageHashCString(strval.as_ptr()) }
+}
 
-pub(crate) fn compute_hash(name: &str) -> u64 {
-    let name = CString::new(name).expect("null error converting hashable name to C string");
-    unsafe { llvm::LLVMRustCoverageComputeHash(name.as_ptr()) }
+pub(crate) fn hash_bytes(bytes: Vec<u8>) -> u64 {
+    unsafe { llvm::LLVMRustCoverageHashByteArray(bytes.as_ptr().cast(), bytes.len()) }
 }
 
 pub(crate) fn mapping_version() -> u32 {
     unsafe { llvm::LLVMRustCoverageMappingVersion() }
 }
 
-pub(crate) fn save_map_to_mod<'ll, 'tcx>(
+pub(crate) fn save_cov_data_to_mod<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
     cov_data_val: &'ll llvm::Value,
 ) {
@@ -198,7 +201,7 @@ pub(crate) fn save_map_to_mod<'ll, 'tcx>(
     debug!("covmap var name: {:?}", covmap_var_name);
 
     let covmap_section_name = llvm::build_string(|s| unsafe {
-        llvm::LLVMRustCoverageWriteSectionNameToString(cx.llmod, s);
+        llvm::LLVMRustCoverageWriteMapSectionNameToString(cx.llmod, s);
     })
     .expect("Rust Coverage section name failed UTF-8 conversion");
     debug!("covmap section name: {:?}", covmap_section_name);
@@ -206,8 +209,43 @@ pub(crate) fn save_map_to_mod<'ll, 'tcx>(
     let llglobal = llvm::add_global(cx.llmod, cx.val_ty(cov_data_val), &covmap_var_name);
     llvm::set_initializer(llglobal, cov_data_val);
     llvm::set_global_constant(llglobal, true);
-    llvm::set_linkage(llglobal, llvm::Linkage::InternalLinkage);
+    llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
     llvm::set_section(llglobal, &covmap_section_name);
-    llvm::set_alignment(llglobal, COVMAP_VAR_ALIGN_BYTES);
+    llvm::set_alignment(llglobal, VAR_ALIGN_BYTES);
+    cx.add_used_global(llglobal);
+}
+
+pub(crate) fn save_func_record_to_mod<'ll, 'tcx>(
+    cx: &CodegenCx<'ll, 'tcx>,
+    func_name_hash: u64,
+    func_record_val: &'ll llvm::Value,
+    is_used: bool,
+) {
+    // Assign a name to the function record. This is used to merge duplicates.
+    //
+    // In LLVM, a "translation unit" (effectively, a `Crate` in Rust) can describe functions that
+    // are included-but-not-used. If (or when) Rust generates functions that are
+    // included-but-not-used, note that a dummy description for a function included-but-not-used
+    // in a Crate can be replaced by full description provided by a different Crate. The two kinds
+    // of descriptions play distinct roles in LLVM IR; therefore, assign them different names (by
+    // appending "u" to the end of the function record var name, to prevent `linkonce_odr` merging.
+    let func_record_var_name =
+        format!("__covrec_{:X}{}", func_name_hash, if is_used { "u" } else { "" });
+    debug!("function record var name: {:?}", func_record_var_name);
+
+    let func_record_section_name = llvm::build_string(|s| unsafe {
+        llvm::LLVMRustCoverageWriteFuncSectionNameToString(cx.llmod, s);
+    })
+    .expect("Rust Coverage function record section name failed UTF-8 conversion");
+    debug!("function record section name: {:?}", func_record_section_name);
+
+    let llglobal = llvm::add_global(cx.llmod, cx.val_ty(func_record_val), &func_record_var_name);
+    llvm::set_initializer(llglobal, func_record_val);
+    llvm::set_global_constant(llglobal, true);
+    llvm::set_linkage(llglobal, llvm::Linkage::LinkOnceODRLinkage);
+    llvm::set_visibility(llglobal, llvm::Visibility::Hidden);
+    llvm::set_section(llglobal, &func_record_section_name);
+    llvm::set_alignment(llglobal, VAR_ALIGN_BYTES);
+    llvm::set_comdat(cx.llmod, llglobal, &func_record_var_name);
     cx.add_used_global(llglobal);
 }
index 5e8ff14f0aaa622f85167a7e30cab6406bcbab9f..96484034da7cd7102384d361d20c46472c83731c 100644 (file)
@@ -1152,10 +1152,7 @@ fn into_metadata(
                 self.size.bits(),
                 self.align.bits() as u32,
                 self.offset.bits(),
-                match self.discriminant {
-                    None => None,
-                    Some(value) => Some(cx.const_u64(value)),
-                },
+                self.discriminant.map(|v| cx.const_u64(v)),
                 self.flags,
                 self.type_metadata,
             )
index 8b15c8b0eb6075d02623ee5574d028d694d489cc..41482d18946ad7f9ebbeacc625f7049b01ed6c47 100644 (file)
@@ -642,7 +642,7 @@ struct InvariantOpaque<'a> {
 pub mod coverageinfo {
     use super::coverage_map;
 
-    /// Aligns with [llvm::coverage::CounterMappingRegion::RegionKind](https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-05-05/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L205-L221)
+    /// Aligns with [llvm::coverage::CounterMappingRegion::RegionKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L206-L222)
     #[derive(Copy, Clone, Debug)]
     #[repr(C)]
     pub enum RegionKind {
@@ -665,13 +665,13 @@ pub enum RegionKind {
 
     /// This struct provides LLVM's representation of a "CoverageMappingRegion", encoded into the
     /// coverage map, in accordance with the
-    /// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/llvmorg-8.0.0/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format).
+    /// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format).
     /// The struct composes fields representing the `Counter` type and value(s) (injected counter
     /// ID, or expression type and operands), the source file (an indirect index into a "filenames
     /// array", encoded separately), and source location (start and end positions of the represented
     /// code region).
     ///
-    /// Aligns with [llvm::coverage::CounterMappingRegion](https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-05-05/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L223-L226)
+    /// Aligns with [llvm::coverage::CounterMappingRegion](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L224-L227)
     /// Important: The Rust struct layout (order and types of fields) must match its C++
     /// counterpart.
     #[derive(Copy, Clone, Debug)]
@@ -1791,10 +1791,14 @@ pub fn LLVMRustCoverageWriteMappingToBuffer(
 
     pub fn LLVMRustCoverageCreatePGOFuncNameVar(F: &'a Value, FuncName: *const c_char)
     -> &'a Value;
-    pub fn LLVMRustCoverageComputeHash(Name: *const c_char) -> u64;
+    pub fn LLVMRustCoverageHashCString(StrVal: *const c_char) -> u64;
+    pub fn LLVMRustCoverageHashByteArray(Bytes: *const c_char, NumBytes: size_t) -> u64;
 
     #[allow(improper_ctypes)]
-    pub fn LLVMRustCoverageWriteSectionNameToString(M: &Module, Str: &RustString);
+    pub fn LLVMRustCoverageWriteMapSectionNameToString(M: &Module, Str: &RustString);
+
+    #[allow(improper_ctypes)]
+    pub fn LLVMRustCoverageWriteFuncSectionNameToString(M: &Module, Str: &RustString);
 
     #[allow(improper_ctypes)]
     pub fn LLVMRustCoverageWriteMappingVarNameToString(Str: &RustString);
index 53a404ee019444f3e531c21aae4d540160fb457b..fc40065a9664ea1c84e8917dea7da1fcfab1ca33 100644 (file)
@@ -220,12 +220,24 @@ pub fn set_linkage(llglobal: &Value, linkage: Linkage) {
     }
 }
 
+pub fn set_visibility(llglobal: &Value, visibility: Visibility) {
+    unsafe {
+        LLVMRustSetVisibility(llglobal, visibility);
+    }
+}
+
 pub fn set_alignment(llglobal: &Value, bytes: usize) {
     unsafe {
         ffi::LLVMSetAlignment(llglobal, bytes as c_uint);
     }
 }
 
+pub fn set_comdat(llmod: &Module, llglobal: &Value, name: &str) {
+    unsafe {
+        LLVMRustSetComdat(llmod, llglobal, name.as_ptr().cast(), name.len());
+    }
+}
+
 /// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
 pub fn get_param(llfn: &Value, index: c_uint) -> &Value {
     unsafe {
index 5a627a0efa364bccb97883da01b2e676acccf000..22e2aa3b5c8b426284db04eb0c8a3502c3da1781 100644 (file)
@@ -2090,9 +2090,10 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
         ("aarch64", "tvos") => "appletvos",
         ("x86_64", "tvos") => "appletvsimulator",
         ("arm", "ios") => "iphoneos",
+        ("aarch64", "ios") if llvm_target.contains("macabi") => "macosx",
         ("aarch64", "ios") => "iphoneos",
         ("x86", "ios") => "iphonesimulator",
-        ("x86_64", "ios") if llvm_target.contains("macabi") => "macosx10.15",
+        ("x86_64", "ios") if llvm_target.contains("macabi") => "macosx",
         ("x86_64", "ios") => "iphonesimulator",
         _ => {
             sess.err(&format!("unsupported arch `{}` for os `{}`", arch, os));
index bcac2c90fdc20a1c12a3486da5087d968c2f4968..af6c476292bd18c3af54e50abd6c512164882260 100644 (file)
@@ -1,6 +1,6 @@
 use rustc_middle::mir::coverage::{CounterValueReference, MappedExpressionIndex};
 
-/// Aligns with [llvm::coverage::Counter::CounterKind](https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-05-05/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L91)
+/// Aligns with [llvm::coverage::Counter::CounterKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L206-L222)
 #[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub enum CounterKind {
@@ -17,7 +17,7 @@ pub enum CounterKind {
 ///     `instrprof.increment()`)
 ///   * For `CounterKind::Expression`, `id` is the index into the coverage map's array of
 ///     counter expressions.
-/// Aligns with [llvm::coverage::Counter](https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-05-05/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L98-L99)
+/// Aligns with [llvm::coverage::Counter](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L99-L100)
 /// Important: The Rust struct layout (order and types of fields) must match its C++ counterpart.
 #[derive(Copy, Clone, Debug)]
 #[repr(C)]
@@ -41,7 +41,7 @@ pub fn expression(mapped_expression_index: MappedExpressionIndex) -> Self {
     }
 }
 
-/// Aligns with [llvm::coverage::CounterExpression::ExprKind](https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-05-05/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L146)
+/// Aligns with [llvm::coverage::CounterExpression::ExprKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L147)
 #[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub enum ExprKind {
@@ -49,7 +49,7 @@ pub enum ExprKind {
     Add = 1,
 }
 
-/// Aligns with [llvm::coverage::CounterExpression](https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-05-05/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L147-L148)
+/// Aligns with [llvm::coverage::CounterExpression](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L148-L149)
 /// Important: The Rust struct layout (order and types of fields) must match its C++
 /// counterpart.
 #[derive(Copy, Clone, Debug)]
index ee40095883ded8710a63ba1a7be8754d4684a727..e59832a8eed5f2ceb53b5f40a5b0fc46fa049d51 100644 (file)
@@ -37,12 +37,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
     /// `funclet_bb` member if it is not `None`.
     fn funclet<'b, Bx: BuilderMethods<'a, 'tcx>>(
         &self,
-        fx: &'b mut FunctionCx<'a, 'tcx, Bx>,
+        fx: &'b FunctionCx<'a, 'tcx, Bx>,
     ) -> Option<&'b Bx::Funclet> {
-        match self.funclet_bb {
-            Some(funcl) => fx.funclets[funcl].as_ref(),
-            None => None,
-        }
+        self.funclet_bb.and_then(|funcl| fx.funclets[funcl].as_ref())
     }
 
     fn lltarget<Bx: BuilderMethods<'a, 'tcx>>(
@@ -255,7 +252,7 @@ fn codegen_return_terminator(&mut self, mut bx: Bx) {
             return;
         }
         let llval = match self.fn_abi.ret.mode {
-            PassMode::Ignore | PassMode::Indirect(..) => {
+            PassMode::Ignore | PassMode::Indirect { .. } => {
                 bx.ret_void();
                 return;
             }
@@ -454,7 +451,7 @@ enum AssertIntrinsic {
             Inhabited,
             ZeroValid,
             UninitValid,
-        };
+        }
         let panic_intrinsic = intrinsic.and_then(|i| match i {
             sym::assert_inhabited => Some(AssertIntrinsic::Inhabited),
             sym::assert_zero_valid => Some(AssertIntrinsic::ZeroValid),
@@ -1101,7 +1098,7 @@ fn codegen_argument(
         // Force by-ref if we have to load through a cast pointer.
         let (mut llval, align, by_ref) = match op.val {
             Immediate(_) | Pair(..) => match arg.mode {
-                PassMode::Indirect(..) | PassMode::Cast(_) => {
+                PassMode::Indirect { .. } | PassMode::Cast(_) => {
                     let scratch = PlaceRef::alloca(bx, arg.layout);
                     op.val.store(bx, scratch);
                     (scratch.llval, scratch.align, true)
index ec2f9597b1827cc7108e2008a01c6bdc5c936e40..01efcaf6f448d8f59778dce8a3e8989bd50fd441 100644 (file)
@@ -151,8 +151,67 @@ impl<D: rustc_serialize::Decoder> FingerprintDecoder for D {
         panic!("Cannot decode `Fingerprint` with `{}`", std::any::type_name::<D>());
     }
 }
+
 impl FingerprintDecoder for opaque::Decoder<'_> {
     fn decode_fingerprint(&mut self) -> Result<Fingerprint, String> {
         Fingerprint::decode_opaque(self)
     }
 }
+
+// `PackedFingerprint` wraps a `Fingerprint`. Its purpose is to, on certain
+// architectures, behave like a `Fingerprint` without alignment requirements.
+// This behavior is only enabled on x86 and x86_64, where the impact of
+// unaligned accesses is tolerable in small doses.
+//
+// This may be preferable to use in large collections of structs containing
+// fingerprints, as it can reduce memory consumption by preventing the padding
+// that the more strictly-aligned `Fingerprint` can introduce. An application of
+// this is in the query dependency graph, which contains a large collection of
+// `DepNode`s. As of this writing, the size of a `DepNode` decreases by ~30%
+// (from 24 bytes to 17) by using the packed representation here, which
+// noticeably decreases total memory usage when compiling large crates.
+//
+// The wrapped `Fingerprint` is private to reduce the chance of a client
+// invoking undefined behavior by taking a reference to the packed field.
+#[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), repr(packed))]
+#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy, Hash)]
+pub struct PackedFingerprint(Fingerprint);
+
+impl std::fmt::Display for PackedFingerprint {
+    #[inline]
+    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        // Copy to avoid taking reference to packed field.
+        let copy = self.0;
+        copy.fmt(formatter)
+    }
+}
+
+impl<E: rustc_serialize::Encoder> Encodable<E> for PackedFingerprint {
+    #[inline]
+    fn encode(&self, s: &mut E) -> Result<(), E::Error> {
+        // Copy to avoid taking reference to packed field.
+        let copy = self.0;
+        copy.encode(s)
+    }
+}
+
+impl<D: rustc_serialize::Decoder> Decodable<D> for PackedFingerprint {
+    #[inline]
+    fn decode(d: &mut D) -> Result<Self, D::Error> {
+        Fingerprint::decode(d).map(|f| PackedFingerprint(f))
+    }
+}
+
+impl From<Fingerprint> for PackedFingerprint {
+    #[inline]
+    fn from(f: Fingerprint) -> PackedFingerprint {
+        PackedFingerprint(f)
+    }
+}
+
+impl From<PackedFingerprint> for Fingerprint {
+    #[inline]
+    fn from(f: PackedFingerprint) -> Fingerprint {
+        f.0
+    }
+}
index 486a9ba77b75feb5da7be907db31488fa32545b0..5b3d8233f3da3b960c1c2cef55edacfd49b52128 100644 (file)
@@ -231,20 +231,30 @@ fn construct(graph: &'c G) -> Sccs<G::Node, S> {
 
         let scc_indices = (0..num_nodes)
             .map(G::Node::new)
-            .map(|node| match this.walk_node(0, node) {
+            .map(|node| match this.start_walk_from(node) {
                 WalkReturn::Complete { scc_index } => scc_index,
-                WalkReturn::Cycle { min_depth } => {
-                    panic!("`walk_node(0, {:?})` returned cycle with depth {:?}", node, min_depth)
-                }
+                WalkReturn::Cycle { min_depth } => panic!(
+                    "`start_walk_node({:?})` returned cycle with depth {:?}",
+                    node, min_depth
+                ),
             })
             .collect();
 
         Sccs { scc_indices, scc_data: this.scc_data }
     }
 
-    /// Visits a node during the DFS. We first examine its current
-    /// state -- if it is not yet visited (`NotVisited`), we can push
-    /// it onto the stack and start walking its successors.
+    fn start_walk_from(&mut self, node: G::Node) -> WalkReturn<S> {
+        if let Some(result) = self.inspect_node(node) {
+            result
+        } else {
+            self.walk_unvisited_node(node)
+        }
+    }
+
+    /// Inspect a node during the DFS. We first examine its current
+    /// state -- if it is not yet visited (`NotVisited`), return `None` so
+    /// that the caller might push it onto the stack and start walking its
+    /// successors.
     ///
     /// If it is already on the DFS stack it will be in the state
     /// `BeingVisited`. In that case, we have found a cycle and we
@@ -253,20 +263,19 @@ fn construct(graph: &'c G) -> Sccs<G::Node, S> {
     /// Otherwise, we are looking at a node that has already been
     /// completely visited. We therefore return `WalkReturn::Complete`
     /// with its associated SCC index.
-    fn walk_node(&mut self, depth: usize, node: G::Node) -> WalkReturn<S> {
-        debug!("walk_node(depth = {:?}, node = {:?})", depth, node);
-        match self.find_state(node) {
+    fn inspect_node(&mut self, node: G::Node) -> Option<WalkReturn<S>> {
+        Some(match self.find_state(node) {
             NodeState::InCycle { scc_index } => WalkReturn::Complete { scc_index },
 
             NodeState::BeingVisited { depth: min_depth } => WalkReturn::Cycle { min_depth },
 
-            NodeState::NotVisited => self.walk_unvisited_node(depth, node),
+            NodeState::NotVisited => return None,
 
             NodeState::InCycleWith { parent } => panic!(
                 "`find_state` returned `InCycleWith({:?})`, which ought to be impossible",
                 parent
             ),
-        }
+        })
     }
 
     /// Fetches the state of the node `r`. If `r` is recorded as being
@@ -274,104 +283,292 @@ fn walk_node(&mut self, depth: usize, node: G::Node) -> WalkReturn<S> {
     /// of `r2` (and updates `r` to reflect current result). This is
     /// basically the "find" part of a standard union-find algorithm
     /// (with path compression).
-    fn find_state(&mut self, r: G::Node) -> NodeState<G::Node, S> {
-        debug!("find_state(r = {:?} in state {:?})", r, self.node_states[r]);
-        match self.node_states[r] {
-            NodeState::InCycle { scc_index } => NodeState::InCycle { scc_index },
-            NodeState::BeingVisited { depth } => NodeState::BeingVisited { depth },
-            NodeState::NotVisited => NodeState::NotVisited,
-            NodeState::InCycleWith { parent } => {
-                let parent_state = self.find_state(parent);
-                debug!("find_state: parent_state = {:?}", parent_state);
-                match parent_state {
-                    NodeState::InCycle { .. } => {
-                        self.node_states[r] = parent_state;
-                        parent_state
-                    }
+    fn find_state(&mut self, mut node: G::Node) -> NodeState<G::Node, S> {
+        // To avoid recursion we temporarily reuse the `parent` of each
+        // InCycleWith link to encode a downwards link while compressing
+        // the path. After we have found the root or deepest node being
+        // visited, we traverse the reverse links and correct the node
+        // states on the way.
+        //
+        // **Note**: This mutation requires that this is a leaf function
+        // or at least that none of the called functions inspects the
+        // current node states. Luckily, we are a leaf.
+
+        // Remember one previous link. The termination condition when
+        // following links downwards is then simply as soon as we have
+        // found the initial self-loop.
+        let mut previous_node = node;
+
+        // Ultimately assigned by the parent when following
+        // `InCycleWith` upwards.
+        let node_state = loop {
+            debug!("find_state(r = {:?} in state {:?})", node, self.node_states[node]);
+            match self.node_states[node] {
+                NodeState::InCycle { scc_index } => break NodeState::InCycle { scc_index },
+                NodeState::BeingVisited { depth } => break NodeState::BeingVisited { depth },
+                NodeState::NotVisited => break NodeState::NotVisited,
+                NodeState::InCycleWith { parent } => {
+                    // We test this, to be extremely sure that we never
+                    // ever break our termination condition for the
+                    // reverse iteration loop.
+                    assert!(node != parent, "Node can not be in cycle with itself");
+                    // Store the previous node as an inverted list link
+                    self.node_states[node] = NodeState::InCycleWith { parent: previous_node };
+                    // Update to parent node.
+                    previous_node = node;
+                    node = parent;
+                }
+            }
+        };
 
-                    NodeState::BeingVisited { depth } => {
-                        self.node_states[r] =
-                            NodeState::InCycleWith { parent: self.node_stack[depth] };
-                        parent_state
-                    }
+        // The states form a graph where up to one outgoing link is stored at
+        // each node. Initially in general,
+        //
+        //                                                  E
+        //                                                  ^
+        //                                                  |
+        //                                InCycleWith/BeingVisited/NotVisited
+        //                                                  |
+        //   A-InCycleWith->B-InCycleWith…>C-InCycleWith->D-+
+        //   |
+        //   = node, previous_node
+        //
+        // After the first loop, this will look like
+        //                                                  E
+        //                                                  ^
+        //                                                  |
+        //                                InCycleWith/BeingVisited/NotVisited
+        //                                                  |
+        // +>A<-InCycleWith-B<…InCycleWith-C<-InCycleWith-D-+
+        // | |                             |              |
+        // | InCycleWith                   |              = node
+        // +-+                             =previous_node
+        //
+        // Note in particular that A will be linked to itself in a self-cycle
+        // and no other self-cycles occur due to how InCycleWith is assigned in
+        // the find phase implemented by `walk_unvisited_node`.
+        //
+        // We now want to compress the path, that is assign the state of the
+        // link D-E to all other links.
+        //
+        // We can then walk backwards, starting from `previous_node`, and assign
+        // each node in the list with the updated state. The loop terminates
+        // when we reach the self-cycle.
+
+        // Move backwards until we found the node where we started. We
+        // will know when we hit the state where previous_node == node.
+        loop {
+            // Back at the beginning, we can return.
+            if previous_node == node {
+                return node_state;
+            }
+            // Update to previous node in the link.
+            match self.node_states[previous_node] {
+                NodeState::InCycleWith { parent: previous } => {
+                    node = previous_node;
+                    previous_node = previous;
+                }
+                // Only InCycleWith nodes were added to the reverse linked list.
+                other => panic!("Invalid previous link while compressing cycle: {:?}", other),
+            }
 
-                    NodeState::NotVisited | NodeState::InCycleWith { .. } => {
-                        panic!("invalid parent state: {:?}", parent_state)
-                    }
+            debug!("find_state: parent_state = {:?}", node_state);
+
+            // Update the node state from the parent state. The assigned
+            // state is actually a loop invariant but it will only be
+            // evaluated if there is at least one backlink to follow.
+            // Fully trusting llvm here to find this loop optimization.
+            match node_state {
+                // Path compression, make current node point to the same root.
+                NodeState::InCycle { .. } => {
+                    self.node_states[node] = node_state;
+                }
+                // Still visiting nodes, compress to cycle to the node
+                // at that depth.
+                NodeState::BeingVisited { depth } => {
+                    self.node_states[node] =
+                        NodeState::InCycleWith { parent: self.node_stack[depth] };
+                }
+                // These are never allowed as parent nodes. InCycleWith
+                // should have been followed to a real parent and
+                // NotVisited can not be part of a cycle since it should
+                // have instead gotten explored.
+                NodeState::NotVisited | NodeState::InCycleWith { .. } => {
+                    panic!("invalid parent state: {:?}", node_state)
                 }
             }
         }
     }
 
     /// Walks a node that has never been visited before.
-    fn walk_unvisited_node(&mut self, depth: usize, node: G::Node) -> WalkReturn<S> {
-        debug!("walk_unvisited_node(depth = {:?}, node = {:?})", depth, node);
-
-        debug_assert!(matches!(self.node_states[node], NodeState::NotVisited));
-
-        // Push `node` onto the stack.
-        self.node_states[node] = NodeState::BeingVisited { depth };
-        self.node_stack.push(node);
-
-        // Walk each successor of the node, looking to see if any of
-        // them can reach a node that is presently on the stack. If
-        // so, that means they can also reach us.
-        let mut min_depth = depth;
-        let mut min_cycle_root = node;
-        let successors_len = self.successors_stack.len();
-        for successor_node in self.graph.successors(node) {
-            debug!("walk_unvisited_node: node = {:?} successor_ode = {:?}", node, successor_node);
-            match self.walk_node(depth + 1, successor_node) {
-                WalkReturn::Cycle { min_depth: successor_min_depth } => {
-                    // Track the minimum depth we can reach.
-                    assert!(successor_min_depth <= depth);
-                    if successor_min_depth < min_depth {
+    ///
+    /// Call this method when `inspect_node` has returned `None`. Having the
+    /// caller decide avoids mutual recursion between the two methods and allows
+    /// us to maintain an allocated stack for nodes on the path between calls.
+    fn walk_unvisited_node(&mut self, initial: G::Node) -> WalkReturn<S> {
+        struct VisitingNodeFrame<G: DirectedGraph, Successors> {
+            node: G::Node,
+            iter: Option<Successors>,
+            depth: usize,
+            min_depth: usize,
+            successors_len: usize,
+            min_cycle_root: G::Node,
+            successor_node: G::Node,
+        }
+
+        // Move the stack to a local variable. We want to utilize the existing allocation and
+        // mutably borrow it without borrowing self at the same time.
+        let mut successors_stack = core::mem::take(&mut self.successors_stack);
+        debug_assert_eq!(successors_stack.len(), 0);
+
+        let mut stack: Vec<VisitingNodeFrame<G, _>> = vec![VisitingNodeFrame {
+            node: initial,
+            depth: 0,
+            min_depth: 0,
+            iter: None,
+            successors_len: 0,
+            min_cycle_root: initial,
+            successor_node: initial,
+        }];
+
+        let mut return_value = None;
+
+        'recurse: while let Some(frame) = stack.last_mut() {
+            let VisitingNodeFrame {
+                node,
+                depth,
+                iter,
+                successors_len,
+                min_depth,
+                min_cycle_root,
+                successor_node,
+            } = frame;
+
+            let node = *node;
+            let depth = *depth;
+
+            let successors = match iter {
+                Some(iter) => iter,
+                None => {
+                    // This None marks that we still have the initialize this node's frame.
+                    debug!("walk_unvisited_node(depth = {:?}, node = {:?})", depth, node);
+
+                    debug_assert!(matches!(self.node_states[node], NodeState::NotVisited));
+
+                    // Push `node` onto the stack.
+                    self.node_states[node] = NodeState::BeingVisited { depth };
+                    self.node_stack.push(node);
+
+                    // Walk each successor of the node, looking to see if any of
+                    // them can reach a node that is presently on the stack. If
+                    // so, that means they can also reach us.
+                    *successors_len = successors_stack.len();
+                    // Set and return a reference, this is currently empty.
+                    iter.get_or_insert(self.graph.successors(node))
+                }
+            };
+
+            // Now that iter is initialized, this is a constant for this frame.
+            let successors_len = *successors_len;
+
+            // Construct iterators for the nodes and walk results. There are two cases:
+            // * The walk of a successor node returned.
+            // * The remaining successor nodes.
+            let returned_walk =
+                return_value.take().into_iter().map(|walk| (*successor_node, Some(walk)));
+
+            let successor_walk = successors.by_ref().map(|successor_node| {
+                debug!(
+                    "walk_unvisited_node: node = {:?} successor_ode = {:?}",
+                    node, successor_node
+                );
+                (successor_node, self.inspect_node(successor_node))
+            });
+
+            for (successor_node, walk) in returned_walk.chain(successor_walk) {
+                match walk {
+                    Some(WalkReturn::Cycle { min_depth: successor_min_depth }) => {
+                        // Track the minimum depth we can reach.
+                        assert!(successor_min_depth <= depth);
+                        if successor_min_depth < *min_depth {
+                            debug!(
+                                "walk_unvisited_node: node = {:?} successor_min_depth = {:?}",
+                                node, successor_min_depth
+                            );
+                            *min_depth = successor_min_depth;
+                            *min_cycle_root = successor_node;
+                        }
+                    }
+
+                    Some(WalkReturn::Complete { scc_index: successor_scc_index }) => {
+                        // Push the completed SCC indices onto
+                        // the `successors_stack` for later.
                         debug!(
-                            "walk_unvisited_node: node = {:?} successor_min_depth = {:?}",
-                            node, successor_min_depth
+                            "walk_unvisited_node: node = {:?} successor_scc_index = {:?}",
+                            node, successor_scc_index
                         );
-                        min_depth = successor_min_depth;
-                        min_cycle_root = successor_node;
+                        successors_stack.push(successor_scc_index);
                     }
-                }
 
-                WalkReturn::Complete { scc_index: successor_scc_index } => {
-                    // Push the completed SCC indices onto
-                    // the `successors_stack` for later.
-                    debug!(
-                        "walk_unvisited_node: node = {:?} successor_scc_index = {:?}",
-                        node, successor_scc_index
-                    );
-                    self.successors_stack.push(successor_scc_index);
+                    None => {
+                        let depth = depth + 1;
+                        debug!("walk_node(depth = {:?}, node = {:?})", depth, successor_node);
+                        // Remember which node the return value will come from.
+                        frame.successor_node = successor_node;
+                        // Start a new stack frame the step into it.
+                        stack.push(VisitingNodeFrame {
+                            node: successor_node,
+                            depth,
+                            iter: None,
+                            successors_len: 0,
+                            min_depth: depth,
+                            min_cycle_root: successor_node,
+                            successor_node: successor_node,
+                        });
+                        continue 'recurse;
+                    }
                 }
             }
-        }
 
-        // Completed walk, remove `node` from the stack.
-        let r = self.node_stack.pop();
-        debug_assert_eq!(r, Some(node));
-
-        // If `min_depth == depth`, then we are the root of the
-        // cycle: we can't reach anyone further down the stack.
-        if min_depth == depth {
-            // Note that successor stack may have duplicates, so we
-            // want to remove those:
-            let deduplicated_successors = {
-                let duplicate_set = &mut self.duplicate_set;
-                duplicate_set.clear();
-                self.successors_stack
-                    .drain(successors_len..)
-                    .filter(move |&i| duplicate_set.insert(i))
-            };
-            let scc_index = self.scc_data.create_scc(deduplicated_successors);
-            self.node_states[node] = NodeState::InCycle { scc_index };
-            WalkReturn::Complete { scc_index }
-        } else {
-            // We are not the head of the cycle. Return back to our
-            // caller. They will take ownership of the
-            // `self.successors` data that we pushed.
-            self.node_states[node] = NodeState::InCycleWith { parent: min_cycle_root };
-            WalkReturn::Cycle { min_depth }
+            // Completed walk, remove `node` from the stack.
+            let r = self.node_stack.pop();
+            debug_assert_eq!(r, Some(node));
+
+            // Remove the frame, it's done.
+            let frame = stack.pop().unwrap();
+
+            // If `min_depth == depth`, then we are the root of the
+            // cycle: we can't reach anyone further down the stack.
+
+            // Pass the 'return value' down the stack.
+            // We return one frame at a time so there can't be another return value.
+            debug_assert!(return_value.is_none());
+            return_value = Some(if frame.min_depth == depth {
+                // Note that successor stack may have duplicates, so we
+                // want to remove those:
+                let deduplicated_successors = {
+                    let duplicate_set = &mut self.duplicate_set;
+                    duplicate_set.clear();
+                    successors_stack
+                        .drain(successors_len..)
+                        .filter(move |&i| duplicate_set.insert(i))
+                };
+                let scc_index = self.scc_data.create_scc(deduplicated_successors);
+                self.node_states[node] = NodeState::InCycle { scc_index };
+                WalkReturn::Complete { scc_index }
+            } else {
+                // We are not the head of the cycle. Return back to our
+                // caller. They will take ownership of the
+                // `self.successors` data that we pushed.
+                self.node_states[node] = NodeState::InCycleWith { parent: frame.min_cycle_root };
+                WalkReturn::Cycle { min_depth: frame.min_depth }
+            });
         }
+
+        // Keep the allocation we used for successors_stack.
+        self.successors_stack = successors_stack;
+        debug_assert_eq!(self.successors_stack.len(), 0);
+
+        return_value.unwrap()
     }
 }
index 1d5f46ebab1994176509cae2ce3516d9311b3044..364005e67e63f91f0dd5dc2a563ef7f0b465d6db 100644 (file)
@@ -1,3 +1,5 @@
+extern crate test;
+
 use super::*;
 use crate::graph::tests::TestGraph;
 
@@ -139,3 +141,73 @@ fn test_find_state_3() {
     assert_eq!(sccs.successors(0), &[]);
     assert_eq!(sccs.successors(1), &[0]);
 }
+
+#[test]
+fn test_deep_linear() {
+    /*
+    0
+    |
+    v
+    1
+    |
+    v
+    2
+    |
+    v
+    …
+     */
+    const NR_NODES: usize = 1 << 14;
+    let mut nodes = vec![];
+    for i in 1..NR_NODES {
+        nodes.push((i - 1, i));
+    }
+    let graph = TestGraph::new(0, nodes.as_slice());
+    let sccs: Sccs<_, usize> = Sccs::new(&graph);
+    assert_eq!(sccs.num_sccs(), NR_NODES);
+    assert_eq!(sccs.scc(0), NR_NODES - 1);
+    assert_eq!(sccs.scc(NR_NODES - 1), 0);
+}
+
+#[bench]
+fn bench_sccc(b: &mut test::Bencher) {
+    // Like `test_three_sccs` but each state is replaced by a group of
+    // three or four to have some amount of test data.
+    /*
+       0-3
+        |
+        v
+    +->4-6 11-14
+    |   |    |
+    |   v    |
+    +--7-10<-+
+         */
+    fn make_3_clique(slice: &mut [(usize, usize)], base: usize) {
+        slice[0] = (base + 0, base + 1);
+        slice[1] = (base + 1, base + 2);
+        slice[2] = (base + 2, base + 0);
+    }
+    // Not actually a clique but strongly connected.
+    fn make_4_clique(slice: &mut [(usize, usize)], base: usize) {
+        slice[0] = (base + 0, base + 1);
+        slice[1] = (base + 1, base + 2);
+        slice[2] = (base + 2, base + 3);
+        slice[3] = (base + 3, base + 0);
+        slice[4] = (base + 1, base + 3);
+        slice[5] = (base + 2, base + 1);
+    }
+
+    let mut graph = [(0, 0); 6 + 3 + 6 + 3 + 4];
+    make_4_clique(&mut graph[0..6], 0);
+    make_3_clique(&mut graph[6..9], 4);
+    make_4_clique(&mut graph[9..15], 7);
+    make_3_clique(&mut graph[15..18], 11);
+    graph[18] = (0, 4);
+    graph[19] = (5, 7);
+    graph[20] = (11, 10);
+    graph[21] = (7, 4);
+    let graph = TestGraph::new(0, &graph[..]);
+    b.iter(|| {
+        let sccs: Sccs<_, usize> = Sccs::new(&graph);
+        assert_eq!(sccs.num_sccs(), 3);
+    });
+}
index 6b952f20dd12b0676725c38759871e003a37d54a..d903a557c7fdf692b16702002b3727ceefd138a4 100644 (file)
@@ -15,7 +15,8 @@
 #![feature(fn_traits)]
 #![feature(int_bits_const)]
 #![feature(min_specialization)]
-#![feature(optin_builtin_traits)]
+#![cfg_attr(bootstrap, feature(optin_builtin_traits))]
+#![cfg_attr(not(bootstrap), feature(auto_traits))]
 #![feature(nll)]
 #![feature(allow_internal_unstable)]
 #![feature(hash_raw_entry)]
@@ -31,6 +32,7 @@
 #![feature(once_cell)]
 #![feature(maybe_uninit_uninit_array)]
 #![allow(rustc::default_hash_types)]
+#![deny(unaligned_references)]
 
 #[macro_use]
 extern crate tracing;
index c5447612555346fdc617bc30c56c9eb687874631..c1741bfaabad25e648f6678178c636dccee6f0e5 100644 (file)
@@ -248,11 +248,18 @@ fn run_compiler(
                 interface::run_compiler(config, |compiler| {
                     let sopts = &compiler.session().opts;
                     if sopts.describe_lints {
-                        let lint_store = rustc_lint::new_lint_store(
+                        let mut lint_store = rustc_lint::new_lint_store(
                             sopts.debugging_opts.no_interleave_lints,
                             compiler.session().unstable_options(),
                         );
-                        describe_lints(compiler.session(), &lint_store, false);
+                        let registered_lints =
+                            if let Some(register_lints) = compiler.register_lints() {
+                                register_lints(compiler.session(), &mut lint_store);
+                                true
+                            } else {
+                                false
+                            };
+                        describe_lints(compiler.session(), &lint_store, registered_lints);
                         return;
                     }
                     let should_stop = RustcDefaultCalls::print_crate_info(
@@ -954,10 +961,7 @@ fn sort_lint_groups(
 
     match (loaded_plugins, plugin.len(), plugin_groups.len()) {
         (false, 0, _) | (false, _, 0) => {
-            println!(
-                "Compiler plugins can provide additional lints and lint groups. To see a \
-                      listing of these, re-run `rustc -W help` with a crate filename."
-            );
+            println!("Lint tools like Clippy can provide additional lints and lint groups.");
         }
         (false, ..) => panic!("didn't load lint plugins but got them anyway!"),
         (true, 0, 0) => println!("This crate does not load any lint plugins or lint groups."),
@@ -1284,10 +1288,30 @@ pub fn init_env_logger(env: &str) {
         Ok(s) if s.is_empty() => return,
         Ok(_) => {}
     }
+    let color_logs = match std::env::var(String::from(env) + "_COLOR") {
+        Ok(value) => match value.as_ref() {
+            "always" => true,
+            "never" => false,
+            "auto" => stdout_isatty(),
+            _ => early_error(
+                ErrorOutputType::default(),
+                &format!(
+                    "invalid log color value '{}': expected one of always, never, or auto",
+                    value
+                ),
+            ),
+        },
+        Err(std::env::VarError::NotPresent) => stdout_isatty(),
+        Err(std::env::VarError::NotUnicode(_value)) => early_error(
+            ErrorOutputType::default(),
+            "non-Unicode log color value: expected one of always, never, or auto",
+        ),
+    };
     let filter = tracing_subscriber::EnvFilter::from_env(env);
     let layer = tracing_tree::HierarchicalLayer::default()
+        .with_writer(io::stderr)
         .with_indent_lines(true)
-        .with_ansi(true)
+        .with_ansi(color_logs)
         .with_targets(true)
         .with_wraparound(10)
         .with_verbose_exit(true)
@@ -1313,7 +1337,7 @@ pub fn main() -> ! {
                 arg.into_string().unwrap_or_else(|arg| {
                     early_error(
                         ErrorOutputType::default(),
-                        &format!("Argument {} is not valid Unicode: {:?}", i, arg),
+                        &format!("argument {} is not valid Unicode: {:?}", i, arg),
                     )
                 })
             })
index 90f1e54287496fb7f32d90af946fd1673811c4db..1238165cb88d4f4621992b99c5c9a7f9d9100751 100644 (file)
@@ -16,7 +16,7 @@ unsafe.
 This will compile:
 
 ```ignore (ignore auto_trait future compatibility warning)
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 
 struct Foo;
 
index bfcdabfe9de7a8b131e74d9eb848deee607521c4..bcfc12897c5c391762ae263fd2bf43cb10c0925c 100644 (file)
@@ -4,7 +4,7 @@ or enum type.
 Erroneous code example:
 
 ```compile_fail,E0321
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 
 struct Foo;
 
index 05cf8fed031609a3d87ba37edf7cebf4ea893019..bc13ee4c04cb2af742ea4c9b7687585bace6feb7 100644 (file)
@@ -3,7 +3,7 @@ Generics have been used on an auto trait.
 Erroneous code example:
 
 ```compile_fail,E0567
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 
 auto trait Generic<T> {} // error!
 # fn main() {}
@@ -16,7 +16,7 @@ parameters.
 To fix this issue, just remove the generics:
 
 ```
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 
 auto trait Generic {} // ok!
 # fn main() {}
index a37381f1cbd1633aceb0a7612f4d4feefb0258ad..17b3f5e31bdf91b817f5ca9603746cd0ecb9aa74 100644 (file)
@@ -3,7 +3,7 @@ A super trait has been added to an auto trait.
 Erroneous code example:
 
 ```compile_fail,E0568
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 
 auto trait Bound : Copy {} // error!
 
@@ -18,7 +18,7 @@ all the existing types could implement `Bound` because very few of them have the
 To fix this issue, just remove the super trait:
 
 ```
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 
 auto trait Bound {} // ok!
 
index b435def87ac84c7a5c98901cd39fc2871d6ba8bc..b1071bf4308512772669c8ac357495938bf15f9d 100644 (file)
@@ -234,6 +234,15 @@ pub fn expect_variant(self) -> ast::Variant {
 
     pub fn derive_allowed(&self) -> bool {
         match *self {
+            Annotatable::Stmt(ref stmt) => match stmt.kind {
+                ast::StmtKind::Item(ref item) => match item.kind {
+                    ast::ItemKind::Struct(..)
+                    | ast::ItemKind::Enum(..)
+                    | ast::ItemKind::Union(..) => true,
+                    _ => false,
+                },
+                _ => false,
+            },
             Annotatable::Item(ref item) => match item.kind {
                 ast::ItemKind::Struct(..) | ast::ItemKind::Enum(..) | ast::ItemKind::Union(..) => {
                     true
@@ -251,8 +260,7 @@ pub enum ExpandResult<T, U> {
     /// Expansion produced a result (possibly dummy).
     Ready(T),
     /// Expansion could not produce a result and needs to be retried.
-    /// The string is an explanation that will be printed if we are stuck in an infinite retry loop.
-    Retry(U, String),
+    Retry(U),
 }
 
 // `meta_item` is the attribute, and `item` is the item being modified.
@@ -366,7 +374,6 @@ macro_rules! make_stmts_default {
                 id: ast::DUMMY_NODE_ID,
                 span: e.span,
                 kind: ast::StmtKind::Expr(e),
-                tokens: None
             }]
         })
     };
@@ -609,7 +616,6 @@ fn make_pat(self: Box<DummyResult>) -> Option<P<ast::Pat>> {
             id: ast::DUMMY_NODE_ID,
             kind: ast::StmtKind::Expr(DummyResult::raw_expr(self.span, self.is_error)),
             span: self.span,
-            tokens: None
         }])
     }
 
@@ -889,8 +895,10 @@ fn resolve_macro_invocation(
     /// Some parent node that is close enough to the given macro call.
     fn lint_node_id(&mut self, expn_id: ExpnId) -> NodeId;
 
+    // Resolver interfaces for specific built-in macros.
+    /// Does `#[derive(...)]` attribute with the given `ExpnId` have built-in `Copy` inside it?
     fn has_derive_copy(&self, expn_id: ExpnId) -> bool;
-    fn add_derive_copy(&mut self, expn_id: ExpnId);
+    /// Path resolution logic for `#[cfg_accessible(path)]`.
     fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result<bool, Indeterminate>;
 }
 
@@ -919,6 +927,9 @@ pub struct ExtCtxt<'a> {
     pub root_path: PathBuf,
     pub resolver: &'a mut dyn ResolverExpand,
     pub current_expansion: ExpansionData,
+    /// Error recovery mode entered when expansion is stuck
+    /// (or during eager expansion, but that's a hack).
+    pub force_mode: bool,
     pub expansions: FxHashMap<Span, Vec<String>>,
     /// Called directly after having parsed an external `mod foo;` in expansion.
     pub(super) extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate)>,
@@ -945,6 +956,7 @@ pub fn new(
                 directory_ownership: DirectoryOwnership::Owned { relative: None },
                 prior_type_ascription: None,
             },
+            force_mode: false,
             expansions: FxHashMap::default(),
         }
     }
index 30f0fc6cddfa2cbd08d9101247bb76ef576bb396..fe67b401fccf9c4372e7b4d5ed4d9af4a1e61edd 100644 (file)
@@ -140,12 +140,7 @@ pub fn lifetime(&self, span: Span, ident: Ident) -> ast::Lifetime {
     }
 
     pub fn stmt_expr(&self, expr: P<ast::Expr>) -> ast::Stmt {
-        ast::Stmt {
-            id: ast::DUMMY_NODE_ID,
-            span: expr.span,
-            kind: ast::StmtKind::Expr(expr),
-            tokens: None,
-        }
+        ast::Stmt { id: ast::DUMMY_NODE_ID, span: expr.span, kind: ast::StmtKind::Expr(expr) }
     }
 
     pub fn stmt_let(&self, sp: Span, mutbl: bool, ident: Ident, ex: P<ast::Expr>) -> ast::Stmt {
@@ -162,13 +157,9 @@ pub fn stmt_let(&self, sp: Span, mutbl: bool, ident: Ident, ex: P<ast::Expr>) ->
             id: ast::DUMMY_NODE_ID,
             span: sp,
             attrs: AttrVec::new(),
-        });
-        ast::Stmt {
-            id: ast::DUMMY_NODE_ID,
-            kind: ast::StmtKind::Local(local),
-            span: sp,
             tokens: None,
-        }
+        });
+        ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span: sp }
     }
 
     // Generates `let _: Type;`, which is usually used for type assertions.
@@ -180,17 +171,13 @@ pub fn stmt_let_type_only(&self, span: Span, ty: P<ast::Ty>) -> ast::Stmt {
             id: ast::DUMMY_NODE_ID,
             span,
             attrs: AttrVec::new(),
+            tokens: None,
         });
-        ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span, tokens: None }
+        ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span }
     }
 
     pub fn stmt_item(&self, sp: Span, item: P<ast::Item>) -> ast::Stmt {
-        ast::Stmt {
-            id: ast::DUMMY_NODE_ID,
-            kind: ast::StmtKind::Item(item),
-            span: sp,
-            tokens: None,
-        }
+        ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Item(item), span: sp }
     }
 
     pub fn block_expr(&self, expr: P<ast::Expr>) -> P<ast::Block> {
@@ -200,7 +187,6 @@ pub fn block_expr(&self, expr: P<ast::Expr>) -> P<ast::Block> {
                 id: ast::DUMMY_NODE_ID,
                 span: expr.span,
                 kind: ast::StmtKind::Expr(expr),
-                tokens: None,
             }],
         )
     }
index cccbdf778edccdcb488d66eb9a54f21e25daeccf..563783c5b795db575cf37bf1061798d1dfbd15a9 100644 (file)
@@ -1,5 +1,7 @@
 //! Conditional compilation stripping.
 
+use crate::base::Annotatable;
+
 use rustc_ast::attr::HasAttrs;
 use rustc_ast::mut_visit::*;
 use rustc_ast::ptr::P;
@@ -496,6 +498,49 @@ pub fn configure_pat(&mut self, pat: &mut P<ast::Pat>) {
     pub fn configure_fn_decl(&mut self, fn_decl: &mut ast::FnDecl) {
         fn_decl.inputs.flat_map_in_place(|arg| self.configure(arg));
     }
+
+    pub fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
+        // Since the item itself has already been configured by the InvocationCollector,
+        // we know that fold result vector will contain exactly one element
+        match item {
+            Annotatable::Item(item) => Annotatable::Item(self.flat_map_item(item).pop().unwrap()),
+            Annotatable::TraitItem(item) => {
+                Annotatable::TraitItem(self.flat_map_trait_item(item).pop().unwrap())
+            }
+            Annotatable::ImplItem(item) => {
+                Annotatable::ImplItem(self.flat_map_impl_item(item).pop().unwrap())
+            }
+            Annotatable::ForeignItem(item) => {
+                Annotatable::ForeignItem(self.flat_map_foreign_item(item).pop().unwrap())
+            }
+            Annotatable::Stmt(stmt) => {
+                Annotatable::Stmt(stmt.map(|stmt| self.flat_map_stmt(stmt).pop().unwrap()))
+            }
+            Annotatable::Expr(mut expr) => Annotatable::Expr({
+                self.visit_expr(&mut expr);
+                expr
+            }),
+            Annotatable::Arm(arm) => Annotatable::Arm(self.flat_map_arm(arm).pop().unwrap()),
+            Annotatable::Field(field) => {
+                Annotatable::Field(self.flat_map_field(field).pop().unwrap())
+            }
+            Annotatable::FieldPat(fp) => {
+                Annotatable::FieldPat(self.flat_map_field_pattern(fp).pop().unwrap())
+            }
+            Annotatable::GenericParam(param) => {
+                Annotatable::GenericParam(self.flat_map_generic_param(param).pop().unwrap())
+            }
+            Annotatable::Param(param) => {
+                Annotatable::Param(self.flat_map_param(param).pop().unwrap())
+            }
+            Annotatable::StructField(sf) => {
+                Annotatable::StructField(self.flat_map_struct_field(sf).pop().unwrap())
+            }
+            Annotatable::Variant(v) => {
+                Annotatable::Variant(self.flat_map_variant(v).pop().unwrap())
+            }
+        }
+    }
 }
 
 impl<'a> MutVisitor for StripUnconfigured<'a> {
index 1b31bd6a30510dfe995e242ca743f8e9176e75c7..4ba75c21cf058a202d29800c5e801a7d57b334e3 100644 (file)
@@ -209,6 +209,28 @@ impl AstFragmentKind {
         self.make_from(DummyResult::any(span)).expect("couldn't create a dummy AST fragment")
     }
 
+    /// Fragment supports macro expansion and not just inert attributes, `cfg` and `cfg_attr`.
+    pub fn supports_macro_expansion(self) -> bool {
+        match self {
+            AstFragmentKind::OptExpr
+            | AstFragmentKind::Expr
+            | AstFragmentKind::Pat
+            | AstFragmentKind::Ty
+            | AstFragmentKind::Stmts
+            | AstFragmentKind::Items
+            | AstFragmentKind::TraitItems
+            | AstFragmentKind::ImplItems
+            | AstFragmentKind::ForeignItems => true,
+            AstFragmentKind::Arms
+            | AstFragmentKind::Fields
+            | AstFragmentKind::FieldPats
+            | AstFragmentKind::GenericParams
+            | AstFragmentKind::Params
+            | AstFragmentKind::StructFields
+            | AstFragmentKind::Variants => false,
+        }
+    }
+
     fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(
         self,
         items: I,
@@ -404,6 +426,7 @@ pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
     // Recursively expand all macro invocations in this AST fragment.
     pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
         let orig_expansion_data = self.cx.current_expansion.clone();
+        let orig_force_mode = self.cx.force_mode;
         self.cx.current_expansion.depth = 0;
 
         // Collect all macro invocations and replace them with placeholders.
@@ -432,6 +455,12 @@ pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragm
                 }
                 invocations = mem::take(&mut undetermined_invocations);
                 force = !mem::replace(&mut progress, false);
+                if force && self.monotonic {
+                    self.cx.sess.delay_span_bug(
+                        invocations.last().unwrap().0.span(),
+                        "expansion entered force mode without producing any errors",
+                    );
+                }
                 continue;
             };
 
@@ -460,18 +489,19 @@ pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragm
 
             let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data;
             self.cx.current_expansion = invoc.expansion_data.clone();
+            self.cx.force_mode = force;
 
             // FIXME(jseyfried): Refactor out the following logic
+            let fragment_kind = invoc.fragment_kind;
             let (expanded_fragment, new_invocations) = match res {
                 InvocationRes::Single(ext) => match self.expand_invoc(invoc, &ext.kind) {
                     ExpandResult::Ready(fragment) => self.collect_invocations(fragment, &[]),
-                    ExpandResult::Retry(invoc, explanation) => {
+                    ExpandResult::Retry(invoc) => {
                         if force {
-                            // We are stuck, stop retrying and produce a dummy fragment.
-                            let span = invoc.span();
-                            self.cx.span_err(span, &explanation);
-                            let fragment = invoc.fragment_kind.dummy(span);
-                            self.collect_invocations(fragment, &[])
+                            self.cx.span_bug(
+                                invoc.span(),
+                                "expansion entered force mode but is still stuck",
+                            );
                         } else {
                             // Cannot expand, will retry this invocation later.
                             undetermined_invocations
@@ -483,36 +513,45 @@ pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragm
                 InvocationRes::DeriveContainer(_exts) => {
                     // FIXME: Consider using the derive resolutions (`_exts`) immediately,
                     // instead of enqueuing the derives to be resolved again later.
-                    let (derives, item) = match invoc.kind {
+                    let (derives, mut item) = match invoc.kind {
                         InvocationKind::DeriveContainer { derives, item } => (derives, item),
                         _ => unreachable!(),
                     };
-                    if !item.derive_allowed() {
+                    let (item, derive_placeholders) = if !item.derive_allowed() {
                         self.error_derive_forbidden_on_non_adt(&derives, &item);
-                    }
+                        item.visit_attrs(|attrs| attrs.retain(|a| !a.has_name(sym::derive)));
+                        (item, Vec::new())
+                    } else {
+                        let mut item = StripUnconfigured {
+                            sess: self.cx.sess,
+                            features: self.cx.ecfg.features,
+                        }
+                        .fully_configure(item);
+                        item.visit_attrs(|attrs| attrs.retain(|a| !a.has_name(sym::derive)));
+
+                        invocations.reserve(derives.len());
+                        let derive_placeholders = derives
+                            .into_iter()
+                            .map(|path| {
+                                let expn_id = ExpnId::fresh(None);
+                                invocations.push((
+                                    Invocation {
+                                        kind: InvocationKind::Derive { path, item: item.clone() },
+                                        fragment_kind,
+                                        expansion_data: ExpansionData {
+                                            id: expn_id,
+                                            ..self.cx.current_expansion.clone()
+                                        },
+                                    },
+                                    None,
+                                ));
+                                NodeId::placeholder_from_expn_id(expn_id)
+                            })
+                            .collect::<Vec<_>>();
+                        (item, derive_placeholders)
+                    };
 
-                    let mut item = self.fully_configure(item);
-                    item.visit_attrs(|attrs| attrs.retain(|a| !a.has_name(sym::derive)));
-
-                    let mut derive_placeholders = Vec::with_capacity(derives.len());
-                    invocations.reserve(derives.len());
-                    for path in derives {
-                        let expn_id = ExpnId::fresh(None);
-                        derive_placeholders.push(NodeId::placeholder_from_expn_id(expn_id));
-                        invocations.push((
-                            Invocation {
-                                kind: InvocationKind::Derive { path, item: item.clone() },
-                                fragment_kind: invoc.fragment_kind,
-                                expansion_data: ExpansionData {
-                                    id: expn_id,
-                                    ..invoc.expansion_data.clone()
-                                },
-                            },
-                            None,
-                        ));
-                    }
-                    let fragment =
-                        invoc.fragment_kind.expect_from_annotatables(::std::iter::once(item));
+                    let fragment = fragment_kind.expect_from_annotatables(::std::iter::once(item));
                     self.collect_invocations(fragment, &derive_placeholders)
                 }
             };
@@ -526,6 +565,7 @@ pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragm
         }
 
         self.cx.current_expansion = orig_expansion_data;
+        self.cx.force_mode = orig_force_mode;
 
         // Finally incorporate all the expanded macros into the input AST fragment.
         let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
@@ -601,48 +641,6 @@ fn collect_invocations(
         (fragment, invocations)
     }
 
-    fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
-        let mut cfg = StripUnconfigured { sess: &self.cx.sess, features: self.cx.ecfg.features };
-        // Since the item itself has already been configured by the InvocationCollector,
-        // we know that fold result vector will contain exactly one element
-        match item {
-            Annotatable::Item(item) => Annotatable::Item(cfg.flat_map_item(item).pop().unwrap()),
-            Annotatable::TraitItem(item) => {
-                Annotatable::TraitItem(cfg.flat_map_trait_item(item).pop().unwrap())
-            }
-            Annotatable::ImplItem(item) => {
-                Annotatable::ImplItem(cfg.flat_map_impl_item(item).pop().unwrap())
-            }
-            Annotatable::ForeignItem(item) => {
-                Annotatable::ForeignItem(cfg.flat_map_foreign_item(item).pop().unwrap())
-            }
-            Annotatable::Stmt(stmt) => {
-                Annotatable::Stmt(stmt.map(|stmt| cfg.flat_map_stmt(stmt).pop().unwrap()))
-            }
-            Annotatable::Expr(mut expr) => Annotatable::Expr({
-                cfg.visit_expr(&mut expr);
-                expr
-            }),
-            Annotatable::Arm(arm) => Annotatable::Arm(cfg.flat_map_arm(arm).pop().unwrap()),
-            Annotatable::Field(field) => {
-                Annotatable::Field(cfg.flat_map_field(field).pop().unwrap())
-            }
-            Annotatable::FieldPat(fp) => {
-                Annotatable::FieldPat(cfg.flat_map_field_pattern(fp).pop().unwrap())
-            }
-            Annotatable::GenericParam(param) => {
-                Annotatable::GenericParam(cfg.flat_map_generic_param(param).pop().unwrap())
-            }
-            Annotatable::Param(param) => {
-                Annotatable::Param(cfg.flat_map_param(param).pop().unwrap())
-            }
-            Annotatable::StructField(sf) => {
-                Annotatable::StructField(cfg.flat_map_struct_field(sf).pop().unwrap())
-            }
-            Annotatable::Variant(v) => Annotatable::Variant(cfg.flat_map_variant(v).pop().unwrap()),
-        }
-    }
-
     fn error_recursion_limit_reached(&mut self) {
         let expn_data = self.cx.current_expansion.id.expn_data();
         let suggested_limit = self.cx.ecfg.recursion_limit * 2;
@@ -735,20 +733,17 @@ fn expand_invoc(
                         Ok(meta) => {
                             let items = match expander.expand(self.cx, span, &meta, item) {
                                 ExpandResult::Ready(items) => items,
-                                ExpandResult::Retry(item, explanation) => {
+                                ExpandResult::Retry(item) => {
                                     // Reassemble the original invocation for retrying.
-                                    return ExpandResult::Retry(
-                                        Invocation {
-                                            kind: InvocationKind::Attr {
-                                                attr,
-                                                item,
-                                                derives,
-                                                after_derive,
-                                            },
-                                            ..invoc
+                                    return ExpandResult::Retry(Invocation {
+                                        kind: InvocationKind::Attr {
+                                            attr,
+                                            item,
+                                            derives,
+                                            after_derive,
                                         },
-                                        explanation,
-                                    );
+                                        ..invoc
+                                    });
                                 }
                             };
                             fragment_kind.expect_from_annotatables(items)
@@ -772,24 +767,18 @@ fn expand_invoc(
             InvocationKind::Derive { path, item } => match ext {
                 SyntaxExtensionKind::Derive(expander)
                 | SyntaxExtensionKind::LegacyDerive(expander) => {
-                    if !item.derive_allowed() {
-                        return ExpandResult::Ready(fragment_kind.dummy(span));
-                    }
                     if let SyntaxExtensionKind::Derive(..) = ext {
                         self.gate_proc_macro_input(&item);
                     }
                     let meta = ast::MetaItem { kind: ast::MetaItemKind::Word, span, path };
                     let items = match expander.expand(self.cx, span, &meta, item) {
                         ExpandResult::Ready(items) => items,
-                        ExpandResult::Retry(item, explanation) => {
+                        ExpandResult::Retry(item) => {
                             // Reassemble the original invocation for retrying.
-                            return ExpandResult::Retry(
-                                Invocation {
-                                    kind: InvocationKind::Derive { path: meta.path, item },
-                                    ..invoc
-                                },
-                                explanation,
-                            );
+                            return ExpandResult::Retry(Invocation {
+                                kind: InvocationKind::Derive { path: meta.path, item },
+                                ..invoc
+                            });
                         }
                     };
                     fragment_kind.expect_from_annotatables(items)
@@ -806,7 +795,14 @@ fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
             | Annotatable::TraitItem(_)
             | Annotatable::ImplItem(_)
             | Annotatable::ForeignItem(_) => return,
-            Annotatable::Stmt(_) => "statements",
+            Annotatable::Stmt(stmt) => {
+                // Attributes are stable on item statements,
+                // but unstable on all other kinds of statements
+                if stmt.is_item() {
+                    return;
+                }
+                "statements"
+            }
             Annotatable::Expr(_) => "expressions",
             Annotatable::Arm(..)
             | Annotatable::Field(..)
@@ -1034,11 +1030,9 @@ fn collect_bang(
 
     fn collect_attr(
         &mut self,
-        attr: Option<ast::Attribute>,
-        derives: Vec<Path>,
+        (attr, derives, after_derive): (Option<ast::Attribute>, Vec<Path>, bool),
         item: Annotatable,
         kind: AstFragmentKind,
-        after_derive: bool,
     ) -> AstFragment {
         self.collect(
             kind,
@@ -1054,7 +1048,7 @@ fn find_attr_invoc(
         attrs: &mut Vec<ast::Attribute>,
         after_derive: &mut bool,
     ) -> Option<ast::Attribute> {
-        let attr = attrs
+        attrs
             .iter()
             .position(|a| {
                 if a.has_name(sym::derive) {
@@ -1062,29 +1056,14 @@ fn find_attr_invoc(
                 }
                 !self.cx.sess.is_attr_known(a) && !is_builtin_attr(a)
             })
-            .map(|i| attrs.remove(i));
-        if let Some(attr) = &attr {
-            if !self.cx.ecfg.custom_inner_attributes()
-                && attr.style == ast::AttrStyle::Inner
-                && !attr.has_name(sym::test)
-            {
-                feature_err(
-                    &self.cx.sess.parse_sess,
-                    sym::custom_inner_attributes,
-                    attr.span,
-                    "non-builtin inner attributes are unstable",
-                )
-                .emit();
-            }
-        }
-        attr
+            .map(|i| attrs.remove(i))
     }
 
     /// If `item` is an attr invocation, remove and return the macro attribute and derive traits.
-    fn classify_item(
+    fn take_first_attr(
         &mut self,
         item: &mut impl HasAttrs,
-    ) -> (Option<ast::Attribute>, Vec<Path>, /* after_derive */ bool) {
+    ) -> Option<(Option<ast::Attribute>, Vec<Path>, /* after_derive */ bool)> {
         let (mut attr, mut traits, mut after_derive) = (None, Vec::new(), false);
 
         item.visit_attrs(|mut attrs| {
@@ -1092,23 +1071,23 @@ fn classify_item(
             traits = collect_derives(&mut self.cx, &mut attrs);
         });
 
-        (attr, traits, after_derive)
+        if attr.is_some() || !traits.is_empty() { Some((attr, traits, after_derive)) } else { None }
     }
 
-    /// Alternative to `classify_item()` that ignores `#[derive]` so invocations fallthrough
+    /// Alternative to `take_first_attr()` that ignores `#[derive]` so invocations fallthrough
     /// to the unused-attributes lint (making it an error on statements and expressions
     /// is a breaking change)
-    fn classify_nonitem(
+    fn take_first_attr_no_derive(
         &mut self,
         nonitem: &mut impl HasAttrs,
-    ) -> (Option<ast::Attribute>, /* after_derive */ bool) {
+    ) -> Option<(Option<ast::Attribute>, Vec<Path>, /* after_derive */ bool)> {
         let (mut attr, mut after_derive) = (None, false);
 
         nonitem.visit_attrs(|mut attrs| {
             attr = self.find_attr_invoc(&mut attrs, &mut after_derive);
         });
 
-        (attr, after_derive)
+        attr.map(|attr| (Some(attr), Vec::new(), after_derive))
     }
 
     fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
@@ -1152,23 +1131,14 @@ fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
         visit_clobber(expr.deref_mut(), |mut expr| {
             self.cfg.configure_expr_kind(&mut expr.kind);
 
-            // ignore derives so they remain unused
-            let (attr, after_derive) = self.classify_nonitem(&mut expr);
-
-            if let Some(ref attr_value) = attr {
+            if let Some(attr) = self.take_first_attr_no_derive(&mut expr) {
                 // Collect the invoc regardless of whether or not attributes are permitted here
                 // expansion will eat the attribute so it won't error later.
-                self.cfg.maybe_emit_expr_attr_err(attr_value);
+                attr.0.as_ref().map(|attr| self.cfg.maybe_emit_expr_attr_err(attr));
 
                 // AstFragmentKind::Expr requires the macro to emit an expression.
                 return self
-                    .collect_attr(
-                        attr,
-                        vec![],
-                        Annotatable::Expr(P(expr)),
-                        AstFragmentKind::Expr,
-                        after_derive,
-                    )
+                    .collect_attr(attr, Annotatable::Expr(P(expr)), AstFragmentKind::Expr)
                     .make_expr()
                     .into_inner();
             }
@@ -1186,16 +1156,9 @@ fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
     fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
         let mut arm = configure!(self, arm);
 
-        let (attr, traits, after_derive) = self.classify_item(&mut arm);
-        if attr.is_some() || !traits.is_empty() {
+        if let Some(attr) = self.take_first_attr(&mut arm) {
             return self
-                .collect_attr(
-                    attr,
-                    traits,
-                    Annotatable::Arm(arm),
-                    AstFragmentKind::Arms,
-                    after_derive,
-                )
+                .collect_attr(attr, Annotatable::Arm(arm), AstFragmentKind::Arms)
                 .make_arms();
         }
 
@@ -1205,16 +1168,9 @@ fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
     fn flat_map_field(&mut self, field: ast::Field) -> SmallVec<[ast::Field; 1]> {
         let mut field = configure!(self, field);
 
-        let (attr, traits, after_derive) = self.classify_item(&mut field);
-        if attr.is_some() || !traits.is_empty() {
+        if let Some(attr) = self.take_first_attr(&mut field) {
             return self
-                .collect_attr(
-                    attr,
-                    traits,
-                    Annotatable::Field(field),
-                    AstFragmentKind::Fields,
-                    after_derive,
-                )
+                .collect_attr(attr, Annotatable::Field(field), AstFragmentKind::Fields)
                 .make_fields();
         }
 
@@ -1224,16 +1180,9 @@ fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
     fn flat_map_field_pattern(&mut self, fp: ast::FieldPat) -> SmallVec<[ast::FieldPat; 1]> {
         let mut fp = configure!(self, fp);
 
-        let (attr, traits, after_derive) = self.classify_item(&mut fp);
-        if attr.is_some() || !traits.is_empty() {
+        if let Some(attr) = self.take_first_attr(&mut fp) {
             return self
-                .collect_attr(
-                    attr,
-                    traits,
-                    Annotatable::FieldPat(fp),
-                    AstFragmentKind::FieldPats,
-                    after_derive,
-                )
+                .collect_attr(attr, Annotatable::FieldPat(fp), AstFragmentKind::FieldPats)
                 .make_field_patterns();
         }
 
@@ -1243,16 +1192,9 @@ fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
     fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
         let mut p = configure!(self, p);
 
-        let (attr, traits, after_derive) = self.classify_item(&mut p);
-        if attr.is_some() || !traits.is_empty() {
+        if let Some(attr) = self.take_first_attr(&mut p) {
             return self
-                .collect_attr(
-                    attr,
-                    traits,
-                    Annotatable::Param(p),
-                    AstFragmentKind::Params,
-                    after_derive,
-                )
+                .collect_attr(attr, Annotatable::Param(p), AstFragmentKind::Params)
                 .make_params();
         }
 
@@ -1262,16 +1204,9 @@ fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
     fn flat_map_struct_field(&mut self, sf: ast::StructField) -> SmallVec<[ast::StructField; 1]> {
         let mut sf = configure!(self, sf);
 
-        let (attr, traits, after_derive) = self.classify_item(&mut sf);
-        if attr.is_some() || !traits.is_empty() {
+        if let Some(attr) = self.take_first_attr(&mut sf) {
             return self
-                .collect_attr(
-                    attr,
-                    traits,
-                    Annotatable::StructField(sf),
-                    AstFragmentKind::StructFields,
-                    after_derive,
-                )
+                .collect_attr(attr, Annotatable::StructField(sf), AstFragmentKind::StructFields)
                 .make_struct_fields();
         }
 
@@ -1281,16 +1216,9 @@ fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
     fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
         let mut variant = configure!(self, variant);
 
-        let (attr, traits, after_derive) = self.classify_item(&mut variant);
-        if attr.is_some() || !traits.is_empty() {
+        if let Some(attr) = self.take_first_attr(&mut variant) {
             return self
-                .collect_attr(
-                    attr,
-                    traits,
-                    Annotatable::Variant(variant),
-                    AstFragmentKind::Variants,
-                    after_derive,
-                )
+                .collect_attr(attr, Annotatable::Variant(variant), AstFragmentKind::Variants)
                 .make_variants();
         }
 
@@ -1302,20 +1230,11 @@ fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
         expr.filter_map(|mut expr| {
             self.cfg.configure_expr_kind(&mut expr.kind);
 
-            // Ignore derives so they remain unused.
-            let (attr, after_derive) = self.classify_nonitem(&mut expr);
-
-            if let Some(ref attr_value) = attr {
-                self.cfg.maybe_emit_expr_attr_err(attr_value);
+            if let Some(attr) = self.take_first_attr_no_derive(&mut expr) {
+                attr.0.as_ref().map(|attr| self.cfg.maybe_emit_expr_attr_err(attr));
 
                 return self
-                    .collect_attr(
-                        attr,
-                        vec![],
-                        Annotatable::Expr(P(expr)),
-                        AstFragmentKind::OptExpr,
-                        after_derive,
-                    )
+                    .collect_attr(attr, Annotatable::Expr(P(expr)), AstFragmentKind::OptExpr)
                     .make_opt_expr()
                     .map(|expr| expr.into_inner());
             }
@@ -1354,31 +1273,23 @@ fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
 
         // we'll expand attributes on expressions separately
         if !stmt.is_expr() {
-            let (attr, derives, after_derive) = if stmt.is_item() {
-                // FIXME: Handle custom attributes on statements (#15701)
-                (None, vec![], false)
+            let attr = if stmt.is_item() {
+                self.take_first_attr(&mut stmt)
             } else {
-                // ignore derives on non-item statements so it falls through
-                // to the unused-attributes lint
-                let (attr, after_derive) = self.classify_nonitem(&mut stmt);
-                (attr, vec![], after_derive)
+                // Ignore derives on non-item statements for backwards compatibility.
+                // This will result in a unused attribute warning
+                self.take_first_attr_no_derive(&mut stmt)
             };
 
-            if attr.is_some() || !derives.is_empty() {
+            if let Some(attr) = attr {
                 return self
-                    .collect_attr(
-                        attr,
-                        derives,
-                        Annotatable::Stmt(P(stmt)),
-                        AstFragmentKind::Stmts,
-                        after_derive,
-                    )
+                    .collect_attr(attr, Annotatable::Stmt(P(stmt)), AstFragmentKind::Stmts)
                     .make_stmts();
             }
         }
 
         if let StmtKind::MacCall(mac) = stmt.kind {
-            let MacCallStmt { mac, style, attrs } = mac.into_inner();
+            let MacCallStmt { mac, style, attrs, tokens: _ } = mac.into_inner();
             self.check_attributes(&attrs);
             let mut placeholder =
                 self.collect_bang(mac, stmt.span, AstFragmentKind::Stmts).make_stmts();
@@ -1395,10 +1306,10 @@ fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
         }
 
         // The placeholder expander gives ids to statements, so we avoid folding the id here.
-        let ast::Stmt { id, kind, span, tokens } = stmt;
+        let ast::Stmt { id, kind, span } = stmt;
         noop_flat_map_stmt_kind(kind, self)
             .into_iter()
-            .map(|kind| ast::Stmt { id, kind, span, tokens: tokens.clone() })
+            .map(|kind| ast::Stmt { id, kind, span })
             .collect()
     }
 
@@ -1412,16 +1323,9 @@ fn visit_block(&mut self, block: &mut P<Block>) {
     fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
         let mut item = configure!(self, item);
 
-        let (attr, traits, after_derive) = self.classify_item(&mut item);
-        if attr.is_some() || !traits.is_empty() {
+        if let Some(attr) = self.take_first_attr(&mut item) {
             return self
-                .collect_attr(
-                    attr,
-                    traits,
-                    Annotatable::Item(item),
-                    AstFragmentKind::Items,
-                    after_derive,
-                )
+                .collect_attr(attr, Annotatable::Item(item), AstFragmentKind::Items)
                 .make_items();
         }
 
@@ -1515,16 +1419,9 @@ fn visit_block(&mut self, block: &mut P<Block>) {
     fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
         let mut item = configure!(self, item);
 
-        let (attr, traits, after_derive) = self.classify_item(&mut item);
-        if attr.is_some() || !traits.is_empty() {
+        if let Some(attr) = self.take_first_attr(&mut item) {
             return self
-                .collect_attr(
-                    attr,
-                    traits,
-                    Annotatable::TraitItem(item),
-                    AstFragmentKind::TraitItems,
-                    after_derive,
-                )
+                .collect_attr(attr, Annotatable::TraitItem(item), AstFragmentKind::TraitItems)
                 .make_trait_items();
         }
 
@@ -1545,16 +1442,9 @@ fn visit_block(&mut self, block: &mut P<Block>) {
     fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
         let mut item = configure!(self, item);
 
-        let (attr, traits, after_derive) = self.classify_item(&mut item);
-        if attr.is_some() || !traits.is_empty() {
+        if let Some(attr) = self.take_first_attr(&mut item) {
             return self
-                .collect_attr(
-                    attr,
-                    traits,
-                    Annotatable::ImplItem(item),
-                    AstFragmentKind::ImplItems,
-                    after_derive,
-                )
+                .collect_attr(attr, Annotatable::ImplItem(item), AstFragmentKind::ImplItems)
                 .make_impl_items();
         }
 
@@ -1595,16 +1485,12 @@ fn flat_map_foreign_item(
         &mut self,
         mut foreign_item: P<ast::ForeignItem>,
     ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
-        let (attr, traits, after_derive) = self.classify_item(&mut foreign_item);
-
-        if attr.is_some() || !traits.is_empty() {
+        if let Some(attr) = self.take_first_attr(&mut foreign_item) {
             return self
                 .collect_attr(
                     attr,
-                    traits,
                     Annotatable::ForeignItem(foreign_item),
                     AstFragmentKind::ForeignItems,
-                    after_derive,
                 )
                 .make_foreign_items();
         }
@@ -1639,15 +1525,12 @@ fn flat_map_generic_param(
     ) -> SmallVec<[ast::GenericParam; 1]> {
         let mut param = configure!(self, param);
 
-        let (attr, traits, after_derive) = self.classify_item(&mut param);
-        if attr.is_some() || !traits.is_empty() {
+        if let Some(attr) = self.take_first_attr(&mut param) {
             return self
                 .collect_attr(
                     attr,
-                    traits,
                     Annotatable::GenericParam(param),
                     AstFragmentKind::GenericParams,
-                    after_derive,
                 )
                 .make_generic_params();
         }
@@ -1830,7 +1713,4 @@ pub fn default(crate_name: String) -> ExpansionConfig<'static> {
     fn proc_macro_hygiene(&self) -> bool {
         self.features.map_or(false, |features| features.proc_macro_hygiene)
     }
-    fn custom_inner_attributes(&self) -> bool {
-        self.features.map_or(false, |features| features.custom_inner_attributes)
-    }
 }
index a074af0189a280d65ad073ba5f56505a4a45141a..66463eeb907135963b1e1453be108deb2e6349c1 100644 (file)
@@ -1173,7 +1173,8 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String {
         mbe::TokenTree::MetaVar(_, name) => format!("${}", name),
         mbe::TokenTree::MetaVarDecl(_, name, kind) => format!("${}:{}", name, kind),
         _ => panic!(
-            "unexpected mbe::TokenTree::{{Sequence or Delimited}} \
+            "{}",
+            "unexpected mbe::TokenTree::{Sequence or Delimited} \
              in follow set checker"
         ),
     }
index f0e5826f403fb9689ba32b1baa5d219d9aecde7b..ce19e813bb3a69f507490029da48ea25ee67ffca 100644 (file)
@@ -104,8 +104,9 @@ fn mac_placeholder() -> ast::MacCall {
                 mac: mac_placeholder(),
                 style: ast::MacStmtStyle::Braces,
                 attrs: ast::AttrVec::new(),
+                tokens: None,
             });
-            ast::Stmt { id, span, kind: ast::StmtKind::MacCall(mac), tokens: None }
+            ast::Stmt { id, span, kind: ast::StmtKind::MacCall(mac) }
         }]),
         AstFragmentKind::Arms => AstFragment::Arms(smallvec![ast::Arm {
             attrs: Default::default(),
@@ -331,12 +332,8 @@ fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
 
             // FIXME: We will need to preserve the original semicolon token and
             // span as part of #15701
-            let empty_stmt = ast::Stmt {
-                id: ast::DUMMY_NODE_ID,
-                kind: ast::StmtKind::Empty,
-                span: DUMMY_SP,
-                tokens: None,
-            };
+            let empty_stmt =
+                ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Empty, span: DUMMY_SP };
 
             if let Some(stmt) = stmts.pop() {
                 if stmt.has_trailing_semicolon() {
index 4c95f19b96dc69113bc9e65e3d5c3eb349e4f337..36707a1ae272da6b61bdbb3389dba5cd7302c105 100644 (file)
@@ -1,6 +1,7 @@
 use crate::base::{self, *};
 use crate::proc_macro_server;
 
+use rustc_ast::ptr::P;
 use rustc_ast::token;
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
 use rustc_ast::{self as ast, *};
@@ -74,39 +75,22 @@ fn expand(
         _meta_item: &ast::MetaItem,
         item: Annotatable,
     ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
+        // We need special handling for statement items
+        // (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`)
+        let mut is_stmt = false;
         let item = match item {
-            Annotatable::Arm(..)
-            | Annotatable::Field(..)
-            | Annotatable::FieldPat(..)
-            | Annotatable::GenericParam(..)
-            | Annotatable::Param(..)
-            | Annotatable::StructField(..)
-            | Annotatable::Variant(..) => panic!("unexpected annotatable"),
-            Annotatable::Item(item) => item,
-            Annotatable::ImplItem(_)
-            | Annotatable::TraitItem(_)
-            | Annotatable::ForeignItem(_)
-            | Annotatable::Stmt(_)
-            | Annotatable::Expr(_) => {
-                ecx.span_err(
-                    span,
-                    "proc-macro derives may only be applied to a struct, enum, or union",
-                );
-                return ExpandResult::Ready(Vec::new());
+            Annotatable::Item(item) => token::NtItem(item),
+            Annotatable::Stmt(stmt) => {
+                is_stmt = true;
+                assert!(stmt.is_item());
+
+                // A proc macro can't observe the fact that we're passing
+                // them an `NtStmt` - it can only see the underlying tokens
+                // of the wrapped item
+                token::NtStmt(stmt.into_inner())
             }
+            _ => unreachable!(),
         };
-        match item.kind {
-            ItemKind::Struct(..) | ItemKind::Enum(..) | ItemKind::Union(..) => {}
-            _ => {
-                ecx.span_err(
-                    span,
-                    "proc-macro derives may only be applied to a struct, enum, or union",
-                );
-                return ExpandResult::Ready(Vec::new());
-            }
-        }
-
-        let item = token::NtItem(item);
         let input = if item.pretty_printing_compatibility_hack() {
             TokenTree::token(token::Interpolated(Lrc::new(item)), DUMMY_SP).into()
         } else {
@@ -135,7 +119,13 @@ fn expand(
         loop {
             match parser.parse_item() {
                 Ok(None) => break,
-                Ok(Some(item)) => items.push(Annotatable::Item(item)),
+                Ok(Some(item)) => {
+                    if is_stmt {
+                        items.push(Annotatable::Stmt(P(ecx.stmt_item(span, item))));
+                    } else {
+                        items.push(Annotatable::Item(item));
+                    }
+                }
                 Err(mut err) => {
                     err.emit();
                     break;
index a035507924794cd487d469c9efa71af8799d6a21..75337634d3fda8ef90ed0697835e4551b5ecb59a 100644 (file)
@@ -149,9 +149,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Allows using the `#[linkage = ".."]` attribute.
     (active, linkage, "1.0.0", Some(29603), None),
 
-    /// Allows features specific to OIBIT (auto traits).
-    (active, optin_builtin_traits, "1.0.0", Some(13231), None),
-
     /// Allows using `box` in patterns (RFC 469).
     (active, box_patterns, "1.0.0", Some(29641), None),
 
@@ -215,6 +212,10 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// purpose as `#[allow_internal_unstable]`.
     (active, rustc_allow_const_fn_unstable, "1.49.0", Some(69399), None),
 
+    /// Allows features specific to auto traits.
+    /// Renamed from `optin_builtin_traits`.
+    (active, auto_traits, "1.50.0", Some(13231), None),
+
     // no-tracking-issue-end
 
     // -------------------------------------------------------------------------
index a480ddc7f34b1f2e41b8004b300272ac6dbe73f6..07bd1602cda325af18b5c5266af147d85befc9e1 100644 (file)
@@ -71,6 +71,10 @@ macro_rules! declare_features {
     /// Allows using custom attributes (RFC 572).
     (removed, custom_attribute, "1.0.0", Some(29642), None,
      Some("removed in favor of `#![register_tool]` and `#![register_attr]`")),
+    /// Allows features specific to OIBIT (now called auto traits).
+    /// Renamed to `auto_traits`.
+    (removed, optin_builtin_traits, "1.0.0", Some(13231), None,
+     Some("renamed to `auto_traits`")),
     (removed, pushpop_unsafe, "1.2.0", None, None, None),
     (removed, needs_allocator, "1.4.0", Some(27389), None,
      Some("subsumed by `#![feature(allocator_internals)]`")),
@@ -113,7 +117,6 @@ macro_rules! declare_features {
      Some("removed in favor of `#![feature(marker_trait_attr)]`")),
     /// Allows `#[no_debug]`.
     (removed, no_debug, "1.43.0", Some(29721), None, Some("removed due to lack of demand")),
-
     /// Allows comparing raw pointers during const eval.
     (removed, const_compare_raw_pointers, "1.46.0", Some(53020), None,
      Some("cannot be allowed in const eval in any meaningful way")),
index 85ab7906d25504658228e839b2dca9ddf0dd9e7e..44dfdcfccab9b5367e2757e01ff3b9fbe53eade5 100644 (file)
@@ -29,6 +29,7 @@ macro_rules! arena_types {
             [] field_pat: rustc_hir::FieldPat<$tcx>,
             [] fn_decl: rustc_hir::FnDecl<$tcx>,
             [] foreign_item: rustc_hir::ForeignItem<$tcx>,
+            [few] foreign_item_ref: rustc_hir::ForeignItemRef<$tcx>,
             [] impl_item_ref: rustc_hir::ImplItemRef<$tcx>,
             [few] inline_asm: rustc_hir::InlineAsm<$tcx>,
             [few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>,
index 298cfcc254c86d745c35a6d600225ea01ad987d7..4ede9d67b741f0b4841b2d4d27b17f6000ee44a5 100644 (file)
@@ -39,6 +39,9 @@ pub enum NonMacroAttrKind {
     Tool,
     /// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`).
     DeriveHelper,
+    /// Single-segment custom attribute registered by a derive macro
+    /// but used before that derive macro was expanded (deprecated).
+    DeriveHelperCompat,
     /// Single-segment custom attribute registered with `#[register_attr]`.
     Registered,
 }
@@ -370,7 +373,9 @@ pub fn descr(self) -> &'static str {
         match self {
             NonMacroAttrKind::Builtin => "built-in attribute",
             NonMacroAttrKind::Tool => "tool attribute",
-            NonMacroAttrKind::DeriveHelper => "derive helper attribute",
+            NonMacroAttrKind::DeriveHelper | NonMacroAttrKind::DeriveHelperCompat => {
+                "derive helper attribute"
+            }
             NonMacroAttrKind::Registered => "explicitly registered attribute",
         }
     }
@@ -385,7 +390,9 @@ pub fn article(self) -> &'static str {
     /// Users of some attributes cannot mark them as used, so they are considered always used.
     pub fn is_used(self) -> bool {
         match self {
-            NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper => true,
+            NonMacroAttrKind::Tool
+            | NonMacroAttrKind::DeriveHelper
+            | NonMacroAttrKind::DeriveHelperCompat => true,
             NonMacroAttrKind::Builtin | NonMacroAttrKind::Registered => false,
         }
     }
index 4497c8c0eaaa8cef1f90fb33802ac7a00a1e47b2..f01d44171056f44c724df69d592fff9bed16876d 100644 (file)
@@ -579,6 +579,7 @@ pub struct ModuleItems {
     pub items: BTreeSet<HirId>,
     pub trait_items: BTreeSet<TraitItemId>,
     pub impl_items: BTreeSet<ImplItemId>,
+    pub foreign_items: BTreeSet<ForeignItemId>,
 }
 
 /// A type representing only the top-level module.
@@ -612,6 +613,7 @@ pub struct Crate<'hir> {
 
     pub trait_items: BTreeMap<TraitItemId, TraitItem<'hir>>,
     pub impl_items: BTreeMap<ImplItemId, ImplItem<'hir>>,
+    pub foreign_items: BTreeMap<ForeignItemId, ForeignItem<'hir>>,
     pub bodies: BTreeMap<BodyId, Body<'hir>>,
     pub trait_impls: BTreeMap<DefId, Vec<HirId>>,
 
@@ -644,6 +646,10 @@ pub fn impl_item(&self, id: ImplItemId) -> &ImplItem<'hir> {
         &self.impl_items[&id]
     }
 
+    pub fn foreign_item(&self, id: ForeignItemId) -> &ForeignItem<'hir> {
+        &self.foreign_items[&id]
+    }
+
     pub fn body(&self, id: BodyId) -> &Body<'hir> {
         &self.bodies[&id]
     }
@@ -673,6 +679,10 @@ pub fn visit_all_item_likes<'hir, V>(&'hir self, visitor: &mut V)
         for impl_item in self.impl_items.values() {
             visitor.visit_impl_item(impl_item);
         }
+
+        for foreign_item in self.foreign_items.values() {
+            visitor.visit_foreign_item(foreign_item);
+        }
     }
 
     /// A parallel version of `visit_all_item_likes`.
@@ -695,6 +705,11 @@ pub fn par_visit_all_item_likes<'hir, V>(&'hir self, visitor: &V)
                 par_for_each_in(&self.impl_items, |(_, impl_item)| {
                     visitor.visit_impl_item(impl_item);
                 });
+            },
+            {
+                par_for_each_in(&self.foreign_items, |(_, foreign_item)| {
+                    visitor.visit_foreign_item(foreign_item);
+                });
             }
         );
     }
@@ -1840,7 +1855,7 @@ pub struct FnSig<'hir> {
 }
 
 // The bodies for items are stored "out of line", in a separate
-// hashmap in the `Crate`. Here we just record the node-id of the item
+// hashmap in the `Crate`. Here we just record the hir-id of the item
 // so it can fetched later.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)]
 pub struct TraitItemId {
@@ -1884,7 +1899,7 @@ pub enum TraitItemKind<'hir> {
 }
 
 // The bodies for items are stored "out of line", in a separate
-// hashmap in the `Crate`. Here we just record the node-id of the item
+// hashmap in the `Crate`. Here we just record the hir-id of the item
 // so it can fetched later.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)]
 pub struct ImplItemId {
@@ -2269,12 +2284,6 @@ pub struct Mod<'hir> {
     pub item_ids: &'hir [ItemId],
 }
 
-#[derive(Debug, HashStable_Generic)]
-pub struct ForeignMod<'hir> {
-    pub abi: Abi,
-    pub items: &'hir [ForeignItem<'hir>],
-}
-
 #[derive(Encodable, Debug, HashStable_Generic)]
 pub struct GlobalAsm {
     pub asm: Symbol,
@@ -2432,7 +2441,7 @@ pub fn ctor_hir_id(&self) -> Option<HirId> {
 }
 
 // The bodies for items are stored "out of line", in a separate
-// hashmap in the `Crate`. Here we just record the node-id of the item
+// hashmap in the `Crate`. Here we just record the hir-id of the item
 // so it can fetched later.
 #[derive(Copy, Clone, Encodable, Debug)]
 pub struct ItemId {
@@ -2521,7 +2530,7 @@ pub enum ItemKind<'hir> {
     /// A module.
     Mod(Mod<'hir>),
     /// An external module, e.g. `extern { .. }`.
-    ForeignMod(ForeignMod<'hir>),
+    ForeignMod { abi: Abi, items: &'hir [ForeignItemRef<'hir>] },
     /// Module-level inline assembly (from `global_asm!`).
     GlobalAsm(&'hir GlobalAsm),
     /// A type alias, e.g., `type Foo = Bar<u8>`.
@@ -2614,6 +2623,29 @@ pub enum AssocItemKind {
     Type,
 }
 
+// The bodies for items are stored "out of line", in a separate
+// hashmap in the `Crate`. Here we just record the hir-id of the item
+// so it can fetched later.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)]
+pub struct ForeignItemId {
+    pub hir_id: HirId,
+}
+
+/// A reference from a foreign block to one of its items. This
+/// contains the item's ID, naturally, but also the item's name and
+/// some other high-level details (like whether it is an associated
+/// type or method, and whether it is public). This allows other
+/// passes to find the impl they want without loading the ID (which
+/// means fewer edges in the incremental compilation graph).
+#[derive(Debug, HashStable_Generic)]
+pub struct ForeignItemRef<'hir> {
+    pub id: ForeignItemId,
+    #[stable_hasher(project(name))]
+    pub ident: Ident,
+    pub span: Span,
+    pub vis: Visibility<'hir>,
+}
+
 #[derive(Debug, HashStable_Generic)]
 pub struct ForeignItem<'hir> {
     #[stable_hasher(project(name))]
index 35615af0fc7dfeb3153b532cfa097c1747738360..3e8fc689acf7a83987b838055134408824dfe752 100644 (file)
@@ -64,6 +64,10 @@ fn visit_trait_item(&mut self, trait_item: &'hir TraitItem<'hir>) {
     fn visit_impl_item(&mut self, impl_item: &'hir ImplItem<'hir>) {
         self.visitor.visit_impl_item(impl_item);
     }
+
+    fn visit_foreign_item(&mut self, foreign_item: &'hir ForeignItem<'hir>) {
+        self.visitor.visit_foreign_item(foreign_item);
+    }
 }
 
 pub trait IntoVisitor<'hir> {
@@ -88,6 +92,10 @@ fn visit_trait_item(&self, trait_item: &'hir TraitItem<'hir>) {
     fn visit_impl_item(&self, impl_item: &'hir ImplItem<'hir>) {
         self.0.into_visitor().visit_impl_item(impl_item);
     }
+
+    fn visit_foreign_item(&self, foreign_item: &'hir ForeignItem<'hir>) {
+        self.0.into_visitor().visit_foreign_item(foreign_item);
+    }
 }
 
 #[derive(Copy, Clone)]
@@ -128,6 +136,7 @@ pub trait Map<'hir> {
     fn item(&self, id: HirId) -> &'hir Item<'hir>;
     fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir>;
     fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir>;
+    fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir>;
 }
 
 /// An erased version of `Map<'hir>`, using dynamic dispatch.
@@ -150,6 +159,9 @@ fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
     fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
         self.0.impl_item(id)
     }
+    fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
+        self.0.foreign_item(id)
+    }
 }
 
 /// Specifies what nested things a visitor wants to visit. The most
@@ -277,6 +289,14 @@ fn visit_nested_impl_item(&mut self, id: ImplItemId) {
         walk_list!(self, visit_impl_item, opt_item);
     }
 
+    /// Like `visit_nested_item()`, but for foreign items. See
+    /// `visit_nested_item()` for advice on when to override this
+    /// method.
+    fn visit_nested_foreign_item(&mut self, id: ForeignItemId) {
+        let opt_item = self.nested_visit_map().inter().map(|map| map.foreign_item(id));
+        walk_list!(self, visit_foreign_item, opt_item);
+    }
+
     /// Invoked to visit the body of a function, method or closure. Like
     /// visit_nested_item, does nothing by default unless you override
     /// `nested_visit_map` to return other than `None`, in which case it will walk
@@ -378,6 +398,9 @@ fn visit_trait_item_ref(&mut self, ii: &'v TraitItemRef) {
     fn visit_impl_item(&mut self, ii: &'v ImplItem<'v>) {
         walk_impl_item(self, ii)
     }
+    fn visit_foreign_item_ref(&mut self, ii: &'v ForeignItemRef<'v>) {
+        walk_foreign_item_ref(self, ii)
+    }
     fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef<'v>) {
         walk_impl_item_ref(self, ii)
     }
@@ -566,9 +589,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
             // `visit_mod()` takes care of visiting the `Item`'s `HirId`.
             visitor.visit_mod(module, item.span, item.hir_id)
         }
-        ItemKind::ForeignMod(ref foreign_module) => {
+        ItemKind::ForeignMod { abi: _, items } => {
             visitor.visit_id(item.hir_id);
-            walk_list!(visitor, visit_foreign_item, foreign_module.items);
+            walk_list!(visitor, visit_foreign_item_ref, items);
         }
         ItemKind::GlobalAsm(_) => {
             visitor.visit_id(item.hir_id);
@@ -1012,6 +1035,17 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
     }
 }
 
+pub fn walk_foreign_item_ref<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    foreign_item_ref: &'v ForeignItemRef<'v>,
+) {
+    // N.B., deliberately force a compilation error if/when new fields are added.
+    let ForeignItemRef { id, ident, span: _, ref vis } = *foreign_item_ref;
+    visitor.visit_nested_foreign_item(id);
+    visitor.visit_ident(ident);
+    visitor.visit_vis(vis);
+}
+
 pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef<'v>) {
     // N.B., deliberately force a compilation error if/when new fields are added.
     let ImplItemRef { id, ident, ref kind, span: _, ref vis, ref defaultness } = *impl_item_ref;
index 369cd49621b2dcb63687584d3f480c57b58d26a5..0db562f91a6a5499a50b8ed647fdb0326e840a1a 100644 (file)
@@ -1,4 +1,4 @@
-use super::{ImplItem, Item, TraitItem};
+use super::{ForeignItem, ImplItem, Item, TraitItem};
 
 /// The "item-like visitor" defines only the top-level methods
 /// that can be invoked by `Crate::visit_all_item_likes()`. Whether
@@ -47,6 +47,7 @@ pub trait ItemLikeVisitor<'hir> {
     fn visit_item(&mut self, item: &'hir Item<'hir>);
     fn visit_trait_item(&mut self, trait_item: &'hir TraitItem<'hir>);
     fn visit_impl_item(&mut self, impl_item: &'hir ImplItem<'hir>);
+    fn visit_foreign_item(&mut self, foreign_item: &'hir ForeignItem<'hir>);
 }
 
 /// A parallel variant of `ItemLikeVisitor`.
@@ -54,4 +55,5 @@ pub trait ParItemLikeVisitor<'hir> {
     fn visit_item(&self, item: &'hir Item<'hir>);
     fn visit_trait_item(&self, trait_item: &'hir TraitItem<'hir>);
     fn visit_impl_item(&self, impl_item: &'hir ImplItem<'hir>);
+    fn visit_foreign_item(&self, foreign_item: &'hir ForeignItem<'hir>);
 }
index 1d3f44a08993aad0cd542c6857ffc9f7e9f5b5a3..439fb88039b407585f2da510d6d59b1bd4a28d5c 100644 (file)
@@ -1,8 +1,8 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
 
 use crate::hir::{
-    BodyId, Expr, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem, TraitItemId, Ty,
-    VisibilityKind,
+    BodyId, Expr, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem, TraitItemId,
+    Ty, VisibilityKind,
 };
 use crate::hir_id::{HirId, ItemLocalId};
 use rustc_span::def_id::{DefPathHash, LocalDefId};
@@ -52,6 +52,15 @@ fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
     }
 }
 
+impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ForeignItemId {
+    type KeyType = (DefPathHash, ItemLocalId);
+
+    #[inline]
+    fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
+        self.hir_id.to_stable_hash_key(hcx)
+    }
+}
+
 impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for HirId {
     fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
         hcx.hash_hir_id(*self, hasher)
@@ -77,6 +86,12 @@ fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
     }
 }
 
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ForeignItemId {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        hcx.hash_reference_to_item(self.hir_id, hasher)
+    }
+}
+
 impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ImplItemId {
     fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
         hcx.hash_reference_to_item(self.hir_id, hasher)
index fd6a312ef3af967cfc8ba2953f39fa5758d13576..b870e4c6ead8369d613f5e19ad2a5a6186437448 100644 (file)
@@ -91,7 +91,7 @@ pub fn from_item(item: &Item<'_>) -> Target {
             ItemKind::Const(..) => Target::Const,
             ItemKind::Fn(..) => Target::Fn,
             ItemKind::Mod(..) => Target::Mod,
-            ItemKind::ForeignMod(..) => Target::ForeignMod,
+            ItemKind::ForeignMod { .. } => Target::ForeignMod,
             ItemKind::GlobalAsm(..) => Target::GlobalAsm,
             ItemKind::TyAlias(..) => Target::TyAlias,
             ItemKind::OpaqueTy(..) => Target::OpaqueTy,
index f7018ae62aa198b7e060a23c11acd5050f94ad23..25b09d76295f2951d24ccf000480652251c37372 100644 (file)
@@ -36,6 +36,7 @@ pub enum Nested {
     Item(hir::ItemId),
     TraitItem(hir::TraitItemId),
     ImplItem(hir::ImplItemId),
+    ForeignItem(hir::ForeignItemId),
     Body(hir::BodyId),
     BodyParamPat(hir::BodyId, usize),
 }
@@ -56,6 +57,7 @@ fn nested(&self, state: &mut State<'_>, nested: Nested) {
             Nested::Item(id) => state.print_item(self.item(id.id)),
             Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)),
             Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)),
+            Nested::ForeignItem(id) => state.print_foreign_item(self.foreign_item(id)),
             Nested::Body(id) => state.print_expr(&self.body(id).value),
             Nested::BodyParamPat(id, i) => state.print_pat(&self.body(id).params[i].pat),
         }
@@ -70,6 +72,7 @@ fn nested(&self, state: &mut State<'_>, nested: Nested) {
             Nested::Item(id) => state.print_item(self.item(id.id)),
             Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)),
             Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)),
+            Nested::ForeignItem(id) => state.print_foreign_item(self.foreign_item(id)),
             Nested::Body(id) => state.print_expr(&self.body(id).value),
             Nested::BodyParamPat(id, i) => state.print_pat(&self.body(id).params[i].pat),
         }
@@ -349,13 +352,6 @@ pub fn print_mod(&mut self, _mod: &hir::Mod<'_>, attrs: &[ast::Attribute]) {
         }
     }
 
-    pub fn print_foreign_mod(&mut self, nmod: &hir::ForeignMod<'_>, attrs: &[ast::Attribute]) {
-        self.print_inner_attributes(attrs);
-        for item in nmod.items {
-            self.print_foreign_item(item);
-        }
-    }
-
     pub fn print_opt_lifetime(&mut self, lifetime: &hir::Lifetime) {
         if !lifetime.is_elided() {
             self.print_lifetime(lifetime);
@@ -644,11 +640,14 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
                 self.print_mod(_mod, &item.attrs);
                 self.bclose(item.span);
             }
-            hir::ItemKind::ForeignMod(ref nmod) => {
+            hir::ItemKind::ForeignMod { abi, items } => {
                 self.head("extern");
-                self.word_nbsp(nmod.abi.to_string());
+                self.word_nbsp(abi.to_string());
                 self.bopen();
-                self.print_foreign_mod(nmod, &item.attrs);
+                self.print_inner_attributes(item.attrs);
+                for item in items {
+                    self.ann.nested(self, Nested::ForeignItem(item.id));
+                }
                 self.bclose(item.span);
             }
             hir::ItemKind::GlobalAsm(ref ga) => {
index d55813f4cc5adc455b7973788800ff60362bfc40..e1c60050d943536bfd2d141709f92836cc95e782 100644 (file)
@@ -280,7 +280,7 @@ fn auto_labels(&mut self, item_id: hir::HirId, attr: &Attribute) -> (&'static st
                     HirItem::Mod(..) => ("ItemMod", LABELS_HIR_ONLY),
 
                     // // An external module
-                    HirItem::ForeignMod(..) => ("ItemForeignMod", LABELS_HIR_ONLY),
+                    HirItem::ForeignMod { .. } => ("ItemForeignMod", LABELS_HIR_ONLY),
 
                     // Module-level inline assembly (from global_asm!)
                     HirItem::GlobalAsm(..) => ("ItemGlobalAsm", LABELS_HIR_ONLY),
@@ -460,6 +460,10 @@ fn visit_trait_item(&mut self, item: &hir::TraitItem<'_>) {
     fn visit_impl_item(&mut self, item: &hir::ImplItem<'_>) {
         self.check_item(item.hir_id, item.span);
     }
+
+    fn visit_foreign_item(&mut self, item: &hir::ForeignItem<'_>) {
+        self.check_item(item.hir_id, item.span);
+    }
 }
 
 /// Given a `#[rustc_dirty]` or `#[rustc_clean]` attribute, scan
index 578c045a2b4e5d92aeaa7a9498a2a6220b88033e..201f381f88940a124a0b20f469b021b4c50fec16 100644 (file)
@@ -199,9 +199,14 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
     }))
 }
 
-pub fn load_query_result_cache(sess: &Session) -> OnDiskCache<'_> {
+/// Attempts to load the query result cache from disk
+///
+/// If we are not in incremental compilation mode, returns `None`.
+/// Otherwise, tries to load the query result cache from disk,
+/// creating an empty cache if it could not be loaded.
+pub fn load_query_result_cache(sess: &Session) -> Option<OnDiskCache<'_>> {
     if sess.opts.incremental.is_none() {
-        return OnDiskCache::new_empty(sess.source_map());
+        return None;
     }
 
     let _prof_timer = sess.prof.generic_activity("incr_comp_load_query_result_cache");
@@ -211,7 +216,9 @@ pub fn load_query_result_cache(sess: &Session) -> OnDiskCache<'_> {
         &query_cache_path(sess),
         sess.is_nightly_build(),
     ) {
-        LoadResult::Ok { data: (bytes, start_pos) } => OnDiskCache::new(sess, bytes, start_pos),
-        _ => OnDiskCache::new_empty(sess.source_map()),
+        LoadResult::Ok { data: (bytes, start_pos) } => {
+            Some(OnDiskCache::new(sess, bytes, start_pos))
+        }
+        _ => Some(OnDiskCache::new_empty(sess.source_map())),
     }
 }
index 7ee881b0639daf53f363e82d6878fc12e0a1735c..eaef4c7b54a625d05f72ce44e88acd074481f30d 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(allow_internal_unstable)]
-#![feature(bool_to_option)]
 #![feature(const_fn)]
 #![feature(const_panic)]
 #![feature(extend_one)]
index fd8f46a6926c0e3de8eefd10b4eda04a81119683..373f0a602c0ef74ba6f0b11a0a91f5e8e1b26d14 100644 (file)
@@ -124,6 +124,11 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
                 return;
             }
         }
+
+        // FIXME(const_generics): Currently, any uninferred `const` generics arguments
+        // are handled specially, but instead they should be handled in `annotate_method_call`,
+        // which currently doesn't work because this evaluates to `false` for const arguments.
+        // See https://github.com/rust-lang/rust/pull/77758 for more details.
         if self.node_ty_contains_target(expr.hir_id).is_some() {
             match expr.kind {
                 ExprKind::Closure(..) => self.found_closure = Some(&expr),
@@ -345,11 +350,6 @@ pub fn emit_inference_failure_err(
     ) -> DiagnosticBuilder<'tcx> {
         let arg = self.resolve_vars_if_possible(arg);
         let arg_data = self.extract_inference_diagnostics_data(arg, None);
-        let kind_str = match arg.unpack() {
-            GenericArgKind::Type(_) => "type",
-            GenericArgKind::Const(_) => "the value",
-            GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
-        };
 
         let mut local_visitor = FindHirNodeVisitor::new(&self, arg, span);
         let ty_to_string = |ty: Ty<'tcx>| -> String {
@@ -618,6 +618,28 @@ pub fn emit_inference_failure_err(
             .any(|span_label| span_label.label.is_some() && span_label.span == span)
             && local_visitor.found_arg_pattern.is_none()
         {
+            let (kind_str, const_value) = match arg.unpack() {
+                GenericArgKind::Type(_) => ("type", None),
+                GenericArgKind::Const(_) => ("the value", Some(())),
+                GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
+            };
+
+            // FIXME(const_generics): we would like to handle const arguments
+            // as part of the normal diagnostics flow below, but there appear to
+            // be subtleties in doing so, so for now we special-case const args
+            // here.
+            if let Some(suggestion) = const_value
+                .and_then(|_| arg_data.parent_name.as_ref())
+                .map(|parent| format!("{}::<{}>", parent, arg_data.name))
+            {
+                err.span_suggestion_verbose(
+                    span,
+                    "consider specifying the const argument",
+                    suggestion,
+                    Applicability::MaybeIncorrect,
+                );
+            }
+
             // Avoid multiple labels pointing at `span`.
             err.span_label(
                 span,
index 8d0100440a8a51cf415e3adecdb03546515138bb..61fad8863e7c423679bd32d9cc81567370781c9b 100644 (file)
@@ -131,7 +131,7 @@ pub(super) fn future_return_type(
     }
 
     pub(super) fn asyncness(&self, local_def_id: LocalDefId) -> Option<hir::IsAsync> {
-        // similar to the asyncness fn in rustc_ty::ty
+        // similar to the asyncness fn in rustc_ty_utils::ty
         let hir_id = self.tcx().hir().local_def_id_to_hir_id(local_def_id);
         let node = self.tcx().hir().get(hir_id);
         let fn_like = rustc_middle::hir::map::blocks::FnLikeNode::from_node(node)?;
index b0b0e4372b8cdad54756290158bd598615515b44..8273c2d291d096020ede192b4f10f6c7a2e257e0 100644 (file)
@@ -309,7 +309,7 @@ impl<'tcx, I: Iterator<Item = PredicateObligation<'tcx>>> Iterator for FilterToT
     fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
         while let Some(obligation) = self.base_iterator.next() {
             if let Some(data) = obligation.predicate.to_opt_poly_trait_ref() {
-                return Some(data);
+                return Some(data.value);
             }
         }
         None
index e214493a567b80e73088572e7c45a6033fa200cc..2481a27dee7951588f552ab92e4e87f985fcf4f1 100644 (file)
@@ -41,7 +41,7 @@ rustc_plugin_impl = { path = "../rustc_plugin_impl" }
 rustc_privacy = { path = "../rustc_privacy" }
 rustc_resolve = { path = "../rustc_resolve" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
-rustc_ty = { path = "../rustc_ty" }
+rustc_ty_utils = { path = "../rustc_ty_utils" }
 tempfile = "3.0.5"
 
 [target.'cfg(windows)'.dependencies]
index 73a51ad477b22e90b886cd14288e5ae0542045a3..11dd6ec32c094b3fee96fe28c9aed10782ce7f85 100644 (file)
@@ -56,6 +56,9 @@ pub fn output_dir(&self) -> &Option<PathBuf> {
     pub fn output_file(&self) -> &Option<PathBuf> {
         &self.output_file
     }
+    pub fn register_lints(&self) -> &Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>> {
+        &self.register_lints
+    }
     pub fn build_output_filenames(
         &self,
         sess: &Session,
index 82cf4ab7f5c0864c5fdab21739d9dcb67d20b720..1f820024f77ef3edab35264f7cc0c7a68d02c96b 100644 (file)
@@ -699,7 +699,7 @@ pub fn prepare_outputs(
     rustc_passes::provide(providers);
     rustc_resolve::provide(providers);
     rustc_traits::provide(providers);
-    rustc_ty::provide(providers);
+    rustc_ty_utils::provide(providers);
     rustc_metadata::provide(providers);
     rustc_lint::provide(providers);
     rustc_symbol_mangling::provide(providers);
@@ -816,6 +816,7 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
                     let local_def_id = tcx.hir().local_def_id(module);
                     tcx.ensure().check_mod_loops(local_def_id);
                     tcx.ensure().check_mod_attrs(local_def_id);
+                    tcx.ensure().check_mod_naked_functions(local_def_id);
                     tcx.ensure().check_mod_unstable_api_usage(local_def_id);
                     tcx.ensure().check_mod_const_bodies(local_def_id);
                 });
index d56115fd6ac56b0c7681bcbab825cd696833c8ee..de08a4c8242fe4a8acb5c44252be715f252553b8 100644 (file)
@@ -33,6 +33,8 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
     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<'_>) {}
 }
 
 pub(crate) fn provide(providers: &mut Providers) {
index 1fc2d281e793536271f6fa2b1c8a0fa53572a983..2273266a3ff821b248dd954064d24121cedc923a 100644 (file)
@@ -498,7 +498,6 @@ macro_rules! untracked {
     untracked!(no_parallel_llvm, true);
     untracked!(parse_only, true);
     untracked!(perf_stats, true);
-    untracked!(polonius, true);
     // `pre_link_arg` is omitted because it just forwards to `pre_link_args`.
     untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]);
     untracked!(print_link_args, true);
@@ -547,7 +546,7 @@ macro_rules! tracked {
     tracked!(debug_macros, true);
     tracked!(dep_info_omit_d_target, true);
     tracked!(dual_proc_macros, true);
-    tracked!(fewer_names, true);
+    tracked!(fewer_names, Some(true));
     tracked!(force_overflow_checks, Some(true));
     tracked!(force_unstable_if_unmarked, true);
     tracked!(fuel, Some(("abc".to_string(), 99)));
@@ -572,6 +571,7 @@ macro_rules! tracked {
     tracked!(osx_rpath_install_name, true);
     tracked!(panic_abort_tests, true);
     tracked!(plt, Some(true));
+    tracked!(polonius, true);
     tracked!(precise_enum_drop_elaboration, false);
     tracked!(print_fuel, Some("abc".to_string()));
     tracked!(profile, true);
@@ -592,6 +592,7 @@ macro_rules! tracked {
     tracked!(thinlto, Some(true));
     tracked!(tune_cpu, Some(String::from("abc")));
     tracked!(tls_model, Some(TlsModel::GeneralDynamic));
+    tracked!(trap_unreachable, Some(false));
     tracked!(treat_err_as_bug, Some(1));
     tracked!(unleash_the_miri_inside_of_you, true);
     tracked!(use_ctors_section, Some(true));
index 20a7b47313ecf5d08e4bf16eb9b01acd260370c1..f34990a1a103757c820f7c19aa7aa18b0a0eb137 100644 (file)
@@ -1,6 +1,5 @@
 use rustc_ast::mut_visit::{visit_clobber, MutVisitor, *};
 use rustc_ast::ptr::P;
-use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_ast::{self as ast, AttrVec, BlockCheckMode};
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_data_structures::fingerprint::Fingerprint;
@@ -20,6 +19,7 @@
 use rustc_session::CrateDisambiguator;
 use rustc_session::{early_error, filesearch, output, DiagnosticOutput, Session};
 use rustc_span::edition::Edition;
+use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::source_map::FileLoader;
 use rustc_span::symbol::{sym, Symbol};
 use smallvec::SmallVec;
@@ -512,8 +512,11 @@ pub(crate) fn check_attr_crate_type(
 
                 if let ast::MetaItemKind::NameValue(spanned) = a.meta().unwrap().kind {
                     let span = spanned.span;
-                    let lev_candidate =
-                        find_best_match_for_name(CRATE_TYPES.iter().map(|(k, _)| k), n, None);
+                    let lev_candidate = find_best_match_for_name(
+                        &CRATE_TYPES.iter().map(|(k, _)| *k).collect::<Vec<_>>(),
+                        n,
+                        None,
+                    );
                     if let Some(candidate) = lev_candidate {
                         lint_buffer.buffer_lint_with_diagnostic(
                             lint::builtin::UNKNOWN_CRATE_TYPES,
@@ -807,7 +810,6 @@ fn block_to_stmt(b: ast::Block, resolver: &mut Resolver<'_>) -> ast::Stmt {
                 id: resolver.next_node_id(),
                 kind: ast::StmtKind::Expr(expr),
                 span: rustc_span::DUMMY_SP,
-                tokens: None,
             }
         }
 
@@ -824,7 +826,6 @@ fn block_to_stmt(b: ast::Block, resolver: &mut Resolver<'_>) -> ast::Stmt {
             id: self.resolver.next_node_id(),
             span: rustc_span::DUMMY_SP,
             kind: ast::StmtKind::Expr(loop_expr),
-            tokens: None,
         };
 
         if self.within_static_or_const {
index 760a8e385d680a4d8afb9cbc13b085c19790aaf3..c56eb09b63471ad96408bae68f8f65eda0c084d1 100644 (file)
@@ -20,3 +20,4 @@ rustc_feature = { path = "../rustc_feature" }
 rustc_index = { path = "../rustc_index" }
 rustc_session = { path = "../rustc_session" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
+rustc_parse_format = { path = "../rustc_parse_format" }
index c65cf65b1c7774c9c398e16f5553d25499bbf958..676c85e4afdceda21bd13b190a4895f9b472e545 100644 (file)
@@ -2345,7 +2345,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) {
         enum InitKind {
             Zeroed,
             Uninit,
-        };
+        }
 
         /// Information about why a type cannot be initialized this way.
         /// Contains an error message and optionally a span to point at.
index 4cfeb0d968b95f1ad29eb67218d9677b8e1960a3..16563d21ff133b5940eb977daa52b16e1fb5e3df 100644 (file)
@@ -19,7 +19,6 @@
 use crate::levels::LintLevelsBuilder;
 use crate::passes::{EarlyLintPassObject, LateLintPassObject};
 use rustc_ast as ast;
-use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync;
 use rustc_errors::{add_elided_lifetime_in_path_suggestion, struct_span_err, Applicability};
@@ -37,6 +36,7 @@
 use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
 use rustc_session::Session;
 use rustc_session::SessionLintStore;
+use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::{symbol::Symbol, MultiSpan, Span, DUMMY_SP};
 use rustc_target::abi::LayoutOf;
 
@@ -411,7 +411,7 @@ fn check_tool_name_for_backwards_compat(
                         self.by_name.keys().map(|name| Symbol::intern(&name)).collect::<Vec<_>>();
 
                     let suggestion = find_best_match_for_name(
-                        symbols.iter(),
+                        &symbols,
                         Symbol::intern(&lint_name.to_lowercase()),
                         None,
                     );
index 24bfdad970a1c4cb0f0d0a24b9a8ceee3346d484..81549be4b09151ca000bce483b63e3fc02f40d30 100644 (file)
@@ -55,6 +55,7 @@
 mod methods;
 mod non_ascii_idents;
 mod nonstandard_style;
+mod panic_fmt;
 mod passes;
 mod redundant_semicolon;
 mod traits;
@@ -80,6 +81,7 @@
 use methods::*;
 use non_ascii_idents::*;
 use nonstandard_style::*;
+use panic_fmt::PanicFmt;
 use redundant_semicolon::*;
 use traits::*;
 use types::*;
@@ -166,6 +168,7 @@ macro_rules! late_lint_passes {
                 ClashingExternDeclarations: ClashingExternDeclarations::new(),
                 DropTraitConstraints: DropTraitConstraints,
                 TemporaryCStringAsPtr: TemporaryCStringAsPtr,
+                PanicFmt: PanicFmt,
             ]
         );
     };
index f117ce1f80544576f45b846492b6686980b69d1c..dd2627f7bc15c3f5da14e71aa4c681a83e0c67ca 100644 (file)
@@ -127,14 +127,20 @@ fn check_case(&self, cx: &EarlyContext<'_>, sort: &str, ident: &Ident) {
         if !is_camel_case(name) {
             cx.struct_span_lint(NON_CAMEL_CASE_TYPES, ident.span, |lint| {
                 let msg = format!("{} `{}` should have an upper camel case name", sort, name);
-                lint.build(&msg)
-                    .span_suggestion(
+                let mut err = lint.build(&msg);
+                let cc = to_camel_case(name);
+                // We cannot provide meaningful suggestions
+                // if the characters are in the category of "Lowercase Letter".
+                if name.to_string() != cc {
+                    err.span_suggestion(
                         ident.span,
                         "convert the identifier to upper camel case",
                         to_camel_case(name),
                         Applicability::MaybeIncorrect,
-                    )
-                    .emit()
+                    );
+                }
+
+                err.emit();
             })
         }
     }
@@ -263,17 +269,21 @@ fn is_snake_case(ident: &str) -> bool {
                 let sc = NonSnakeCase::to_snake_case(name);
                 let msg = format!("{} `{}` should have a snake case name", sort, name);
                 let mut err = lint.build(&msg);
-                // We have a valid span in almost all cases, but we don't have one when linting a crate
-                // name provided via the command line.
-                if !ident.span.is_dummy() {
-                    err.span_suggestion(
-                        ident.span,
-                        "convert the identifier to snake case",
-                        sc,
-                        Applicability::MaybeIncorrect,
-                    );
-                } else {
-                    err.help(&format!("convert the identifier to snake case: `{}`", sc));
+                // We cannot provide meaningful suggestions
+                // if the characters are in the category of "Uppercase Letter".
+                if name.to_string() != sc {
+                    // We have a valid span in almost all cases, but we don't have one when linting a crate
+                    // name provided via the command line.
+                    if !ident.span.is_dummy() {
+                        err.span_suggestion(
+                            ident.span,
+                            "convert the identifier to snake case",
+                            sc,
+                            Applicability::MaybeIncorrect,
+                        );
+                    } else {
+                        err.help(&format!("convert the identifier to snake case: `{}`", sc));
+                    }
                 }
 
                 err.emit();
@@ -441,14 +451,20 @@ fn check_upper_case(cx: &LateContext<'_>, sort: &str, ident: &Ident) {
         if name.chars().any(|c| c.is_lowercase()) {
             cx.struct_span_lint(NON_UPPER_CASE_GLOBALS, ident.span, |lint| {
                 let uc = NonSnakeCase::to_snake_case(&name).to_uppercase();
-                lint.build(&format!("{} `{}` should have an upper case name", sort, name))
-                    .span_suggestion(
+                let mut err =
+                    lint.build(&format!("{} `{}` should have an upper case name", sort, name));
+                // We cannot provide meaningful suggestions
+                // if the characters are in the category of "Lowercase Letter".
+                if name.to_string() != uc {
+                    err.span_suggestion(
                         ident.span,
                         "convert the identifier to upper case",
                         uc,
                         Applicability::MaybeIncorrect,
-                    )
-                    .emit();
+                    );
+                }
+
+                err.emit();
             })
         }
     }
diff --git a/compiler/rustc_lint/src/panic_fmt.rs b/compiler/rustc_lint/src/panic_fmt.rs
new file mode 100644 (file)
index 0000000..0d2b209
--- /dev/null
@@ -0,0 +1,150 @@
+use crate::{LateContext, LateLintPass, LintContext};
+use rustc_ast as ast;
+use rustc_errors::{pluralize, Applicability};
+use rustc_hir as hir;
+use rustc_middle::ty;
+use rustc_parse_format::{ParseMode, Parser, Piece};
+use rustc_span::{sym, InnerSpan};
+
+declare_lint! {
+    /// The `panic_fmt` lint detects `panic!("..")` with `{` or `}` in the string literal.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,no_run
+    /// panic!("{}");
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// `panic!("{}")` panics with the message `"{}"`, as a `panic!()` invocation
+    /// with a single argument does not use `format_args!()`.
+    /// A future edition of Rust will interpret this string as format string,
+    /// which would break this.
+    PANIC_FMT,
+    Warn,
+    "detect braces in single-argument panic!() invocations",
+    report_in_external_macro
+}
+
+declare_lint_pass!(PanicFmt => [PANIC_FMT]);
+
+impl<'tcx> LateLintPass<'tcx> for PanicFmt {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
+        if let hir::ExprKind::Call(f, [arg]) = &expr.kind {
+            if let &ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(f).kind() {
+                if Some(def_id) == cx.tcx.lang_items().begin_panic_fn()
+                    || Some(def_id) == cx.tcx.lang_items().panic_fn()
+                {
+                    check_panic(cx, f, arg);
+                }
+            }
+        }
+    }
+}
+
+fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tcx hir::Expr<'tcx>) {
+    if let hir::ExprKind::Lit(lit) = &arg.kind {
+        if let ast::LitKind::Str(sym, _) = lit.node {
+            let mut expn = f.span.ctxt().outer_expn_data();
+            if let Some(id) = expn.macro_def_id {
+                if cx.tcx.is_diagnostic_item(sym::std_panic_macro, id)
+                    || cx.tcx.is_diagnostic_item(sym::core_panic_macro, id)
+                {
+                    let fmt = sym.as_str();
+                    if !fmt.contains(&['{', '}'][..]) {
+                        return;
+                    }
+
+                    let fmt_span = arg.span.source_callsite();
+
+                    let (snippet, style) =
+                        match cx.sess().parse_sess.source_map().span_to_snippet(fmt_span) {
+                            Ok(snippet) => {
+                                // Count the number of `#`s between the `r` and `"`.
+                                let style = snippet.strip_prefix('r').and_then(|s| s.find('"'));
+                                (Some(snippet), style)
+                            }
+                            Err(_) => (None, None),
+                        };
+
+                    let mut fmt_parser =
+                        Parser::new(fmt.as_ref(), style, snippet.clone(), false, ParseMode::Format);
+                    let n_arguments =
+                        (&mut fmt_parser).filter(|a| matches!(a, Piece::NextArgument(_))).count();
+
+                    // Unwrap another level of macro expansion if this panic!()
+                    // was expanded from assert!() or debug_assert!().
+                    for &assert in &[sym::assert_macro, sym::debug_assert_macro] {
+                        let parent = expn.call_site.ctxt().outer_expn_data();
+                        if parent
+                            .macro_def_id
+                            .map_or(false, |id| cx.tcx.is_diagnostic_item(assert, id))
+                        {
+                            expn = parent;
+                        }
+                    }
+
+                    if n_arguments > 0 && fmt_parser.errors.is_empty() {
+                        let arg_spans: Vec<_> = match &fmt_parser.arg_places[..] {
+                            [] => vec![fmt_span],
+                            v => v.iter().map(|span| fmt_span.from_inner(*span)).collect(),
+                        };
+                        cx.struct_span_lint(PANIC_FMT, arg_spans, |lint| {
+                            let mut l = lint.build(match n_arguments {
+                                1 => "panic message contains an unused formatting placeholder",
+                                _ => "panic message contains unused formatting placeholders",
+                            });
+                            l.note("this message is not used as a format string when given without arguments, but will be in a future Rust edition");
+                            if expn.call_site.contains(arg.span) {
+                                l.span_suggestion(
+                                    arg.span.shrink_to_hi(),
+                                    &format!("add the missing argument{}", pluralize!(n_arguments)),
+                                    ", ...".into(),
+                                    Applicability::HasPlaceholders,
+                                );
+                                l.span_suggestion(
+                                    arg.span.shrink_to_lo(),
+                                    "or add a \"{}\" format string to use the message literally",
+                                    "\"{}\", ".into(),
+                                    Applicability::MachineApplicable,
+                                );
+                            }
+                            l.emit();
+                        });
+                    } else {
+                        let brace_spans: Option<Vec<_>> = snippet
+                            .filter(|s| s.starts_with('"') || s.starts_with("r#"))
+                            .map(|s| {
+                                s.char_indices()
+                                    .filter(|&(_, c)| c == '{' || c == '}')
+                                    .map(|(i, _)| {
+                                        fmt_span.from_inner(InnerSpan { start: i, end: i + 1 })
+                                    })
+                                    .collect()
+                            });
+                        let msg = match &brace_spans {
+                            Some(v) if v.len() == 1 => "panic message contains a brace",
+                            _ => "panic message contains braces",
+                        };
+                        cx.struct_span_lint(PANIC_FMT, brace_spans.unwrap_or(vec![expn.call_site]), |lint| {
+                            let mut l = lint.build(msg);
+                            l.note("this message is not used as a format string, but will be in a future Rust edition");
+                            if expn.call_site.contains(arg.span) {
+                                l.span_suggestion(
+                                    arg.span.shrink_to_lo(),
+                                    "add a \"{}\" format string to use the message literally",
+                                    "\"{}\", ".into(),
+                                    Applicability::MachineApplicable,
+                                );
+                            }
+                            l.emit();
+                        });
+                    }
+                }
+            }
+        }
+    }
+}
index 84cc7b68d4ca9ef45bc9f14b8395b54347638fab..428198cae8917377ee7ea648b37cae10b037b207 100644 (file)
 
 impl EarlyLintPass for RedundantSemicolons {
     fn check_block(&mut self, cx: &EarlyContext<'_>, block: &Block) {
+        let mut after_item_stmt = false;
         let mut seq = None;
         for stmt in block.stmts.iter() {
             match (&stmt.kind, &mut seq) {
                 (StmtKind::Empty, None) => seq = Some((stmt.span, false)),
                 (StmtKind::Empty, Some(seq)) => *seq = (seq.0.to(stmt.span), true),
-                (_, seq) => maybe_lint_redundant_semis(cx, seq),
+                (_, seq) => {
+                    maybe_lint_redundant_semis(cx, seq, after_item_stmt);
+                    after_item_stmt = matches!(stmt.kind, StmtKind::Item(_));
+                }
             }
         }
-        maybe_lint_redundant_semis(cx, &mut seq);
+        maybe_lint_redundant_semis(cx, &mut seq, after_item_stmt);
     }
 }
 
-fn maybe_lint_redundant_semis(cx: &EarlyContext<'_>, seq: &mut Option<(Span, bool)>) {
+fn maybe_lint_redundant_semis(
+    cx: &EarlyContext<'_>,
+    seq: &mut Option<(Span, bool)>,
+    after_item_stmt: bool,
+) {
     if let Some((span, multiple)) = seq.take() {
         // FIXME: Find a better way of ignoring the trailing
         // semicolon from macro expansion
         if span == rustc_span::DUMMY_SP {
             return;
         }
+
+        // FIXME: Lint on semicolons after item statements
+        // once doing so doesn't break bootstrapping
+        if after_item_stmt {
+            return;
+        }
+
         cx.struct_span_lint(REDUNDANT_SEMICOLONS, span, |lint| {
             let (msg, rem) = if multiple {
                 ("unnecessary trailing semicolons", "remove these semicolons")
index 38c71e6e9258973a3b05ac33278f74ae13bb3c3d..9ad9d53cd0db3512205bde954f4fe049029d5718 100644 (file)
@@ -1131,7 +1131,7 @@ fn emit_ffi_unsafe_type_lint(
     fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool {
         struct ProhibitOpaqueTypes<'a, 'tcx> {
             cx: &'a LateContext<'tcx>,
-        };
+        }
 
         impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> {
             type BreakTy = Ty<'tcx>;
index 4bbc180b226a59ed104dc31f4f7f37f4f6498ed3..2a5ad5e6c98a6a10bfb9119fc077bd41817b8f3b 100644 (file)
@@ -1152,7 +1152,7 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
     /// ```rust
     /// #![feature(box_syntax)]
     /// fn main() {
-    ///     let a = (box [1,2,3]).len();
+    ///     let a = (box [1, 2, 3]).len();
     /// }
     /// ```
     ///
index 1d0d6980b7a89dea87a10e1715654c9018e4cb5b..fa82dce0ae2ed48ce3401bd16ce1df6c3c0a2619 100644 (file)
     ///
     /// impl<T: ?Sized> MyIterator for T where T: Iterator { }
     ///
-    /// let x = vec![1,2,3];
+    /// let x = vec![1, 2, 3];
     /// let _ = x.iter().is_sorted();
     /// ```
     ///
index 2b1143a4ecff54ab6b79a737a2ddf54b269b75e2..25badc3f4e17bd96cc954d6f765e5cd8ecc48cf5 100644 (file)
@@ -3,7 +3,6 @@
 #include "llvm/ProfileData/Coverage/CoverageMappingWriter.h"
 #include "llvm/ProfileData/InstrProf.h"
 #include "llvm/ADT/ArrayRef.h"
-#include "llvm/Support/LEB128.h"
 
 #include <iostream>
 
@@ -13,15 +12,14 @@ extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer(
     const char* const Filenames[],
     size_t FilenamesLen,
     RustStringRef BufferOut) {
-  // LLVM 11's CoverageFilenamesSectionWriter uses its new `Version4` format,
-  // so we're manually writing the `Version3` format ourselves.
-  RawRustStringOstream OS(BufferOut);
-  encodeULEB128(FilenamesLen, OS);
+  SmallVector<StringRef,32> FilenameRefs;
   for (size_t i = 0; i < FilenamesLen; i++) {
-    StringRef Filename(Filenames[i]);
-    encodeULEB128(Filename.size(), OS);
-    OS << Filename;
+    FilenameRefs.push_back(StringRef(Filenames[i]));
   }
+  auto FilenamesWriter = coverage::CoverageFilenamesSectionWriter(
+    makeArrayRef(FilenameRefs));
+  RawRustStringOstream OS(BufferOut);
+  FilenamesWriter.write(OS);
 }
 
 extern "C" void LLVMRustCoverageWriteMappingToBuffer(
@@ -45,20 +43,40 @@ extern "C" LLVMValueRef LLVMRustCoverageCreatePGOFuncNameVar(LLVMValueRef F, con
   return wrap(createPGOFuncNameVar(*cast<Function>(unwrap(F)), FuncNameRef));
 }
 
-extern "C" uint64_t LLVMRustCoverageComputeHash(const char *Name) {
-  StringRef NameRef(Name);
-  return IndexedInstrProf::ComputeHash(NameRef);
+extern "C" uint64_t LLVMRustCoverageHashCString(const char *StrVal) {
+  StringRef StrRef(StrVal);
+  return IndexedInstrProf::ComputeHash(StrRef);
+}
+
+extern "C" uint64_t LLVMRustCoverageHashByteArray(
+    const char *Bytes,
+    unsigned NumBytes) {
+  StringRef StrRef(Bytes, NumBytes);
+  return IndexedInstrProf::ComputeHash(StrRef);
 }
 
-extern "C" void LLVMRustCoverageWriteSectionNameToString(LLVMModuleRef M,
-                                                         RustStringRef Str) {
+static void WriteSectionNameToString(LLVMModuleRef M,
+                                     InstrProfSectKind SK,
+                                     RustStringRef Str) {
   Triple TargetTriple(unwrap(M)->getTargetTriple());
-  auto name = getInstrProfSectionName(IPSK_covmap,
-                                      TargetTriple.getObjectFormat());
+  auto name = getInstrProfSectionName(SK, TargetTriple.getObjectFormat());
   RawRustStringOstream OS(Str);
   OS << name;
 }
 
+extern "C" void LLVMRustCoverageWriteMapSectionNameToString(LLVMModuleRef M,
+                                                            RustStringRef Str) {
+  WriteSectionNameToString(M, IPSK_covmap, Str);
+}
+
+extern "C" void LLVMRustCoverageWriteFuncSectionNameToString(LLVMModuleRef M,
+                                                             RustStringRef Str) {
+#if LLVM_VERSION_GE(11, 0)
+  WriteSectionNameToString(M, IPSK_covfun, Str);
+// else do nothing; the `Version` check will abort codegen on the Rust side
+#endif
+}
+
 extern "C" void LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str) {
   auto name = getCoverageMappingVarName();
   RawRustStringOstream OS(Str);
@@ -66,5 +84,9 @@ extern "C" void LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str) {
 }
 
 extern "C" uint32_t LLVMRustCoverageMappingVersion() {
+#if LLVM_VERSION_GE(11, 0)
+  return coverage::CovMapVersion::Version4;
+#else
   return coverage::CovMapVersion::Version3;
+#endif
 }
index 9b0c176b692034bc8aaa5db7377a9fb1601e791c..e17f933932e6a0649265ff6276619990aea15426 100644 (file)
@@ -1462,7 +1462,7 @@ extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
                                   const char *Name, size_t NameLen) {
   Triple TargetTriple(unwrap(M)->getTargetTriple());
   GlobalObject *GV = unwrap<GlobalObject>(V);
-  if (!TargetTriple.isOSBinFormatMachO()) {
+  if (TargetTriple.supportsCOMDAT()) {
     StringRef NameRef(Name, NameLen);
     GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
   }
index fd85919636949ac89760c4b4270b6b94449e613a..12990ae2d94a5c18abe1adae784407df87d2698e 100644 (file)
@@ -353,7 +353,7 @@ fn try_load_from_disk(
                     tcx: TyCtxt<'tcx>,
                     id: SerializedDepNodeIndex
                 ) -> Option<Self::Value> {
-                    tcx.queries.on_disk_cache.try_load_query_result(tcx, id)
+                    tcx.queries.on_disk_cache.as_ref().and_then(|c| c.try_load_query_result(tcx, id))
                 }
             }
         };
index 8675197656a48f14f58c59b148ede9bab6b489c3..4785b6c379c228625f1c4863da9c24b9534f60c0 100644 (file)
@@ -16,13 +16,13 @@ struct Collector<'tcx> {
 
 impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
     fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
-        let fm = match it.kind {
-            hir::ItemKind::ForeignMod(ref fm) => fm,
+        let items = match it.kind {
+            hir::ItemKind::ForeignMod { items, .. } => items,
             _ => return,
         };
 
         let foreign_items =
-            fm.items.iter().map(|it| self.tcx.hir().local_def_id(it.hir_id).to_def_id()).collect();
+            items.iter().map(|it| self.tcx.hir().local_def_id(it.id.hir_id).to_def_id()).collect();
         self.modules.push(ForeignModule {
             foreign_items,
             def_id: self.tcx.hir().local_def_id(it.hir_id).to_def_id(),
@@ -31,4 +31,5 @@ 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>) {}
 }
index 77766be7397c7468306b1beb3f5a974045a3b4f3..2560cfa74624a2bede8ae22a5fea14008e9a05fc 100644 (file)
@@ -1,5 +1,4 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![feature(bool_to_option)]
 #![feature(core_intrinsics)]
 #![feature(crate_visibility_modifier)]
 #![feature(drain_filter)]
index d8f16796083f221112fefa187a5bb8f1e36ede33..d088288c507677282727e841ab403ed611e600a4 100644 (file)
@@ -26,11 +26,11 @@ struct Collector<'tcx> {
 
 impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
     fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
-        let fm = match it.kind {
-            hir::ItemKind::ForeignMod(ref fm) => fm,
+        let abi = match it.kind {
+            hir::ItemKind::ForeignMod { abi, .. } => abi,
             _ => return,
         };
-        if fm.abi == Abi::Rust || fm.abi == Abi::RustIntrinsic || fm.abi == Abi::PlatformIntrinsic {
+        if abi == Abi::Rust || abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
             return;
         }
 
@@ -45,6 +45,7 @@ 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<'tcx> Collector<'tcx> {
index 2f7c2c2c405192397eb978ae4512016716d36c33..fe29f9d177f92c1a4fb5d2b4c5b28086e86de8b4 100644 (file)
@@ -33,12 +33,12 @@ struct Collector<'tcx> {
 
 impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
     fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
-        let fm = match it.kind {
-            hir::ItemKind::ForeignMod(ref fm) => fm,
+        let abi = match it.kind {
+            hir::ItemKind::ForeignMod { abi, .. } => abi,
             _ => return,
         };
 
-        if fm.abi == Abi::Rust || fm.abi == Abi::RustIntrinsic || fm.abi == Abi::PlatformIntrinsic {
+        if abi == Abi::Rust || abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
             return;
         }
 
@@ -127,6 +127,7 @@ 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<'tcx> {
index a1df1a63fc58d3f265cbb4bd602f8ca13913b1e6..e82449f69fd8e1639aaa3c4ca160572a5f084057 100644 (file)
@@ -644,6 +644,7 @@ fn def_kind(&self) -> DefKind {
             EntryKind::TraitAlias => DefKind::TraitAlias,
             EntryKind::Enum(..) => DefKind::Enum,
             EntryKind::MacroDef(_) => DefKind::Macro(MacroKind::Bang),
+            EntryKind::ProcMacro(kind) => DefKind::Macro(kind),
             EntryKind::ForeignType => DefKind::ForeignTy,
             EntryKind::Impl(_) => DefKind::Impl,
             EntryKind::Closure => DefKind::Closure,
@@ -685,20 +686,11 @@ impl CrateRoot<'_> {
 }
 
 impl<'a, 'tcx> CrateMetadataRef<'a> {
-    fn is_proc_macro(&self, id: DefIndex) -> bool {
-        self.root
-            .proc_macro_data
-            .as_ref()
-            .and_then(|data| data.macros.decode(self).find(|x| *x == id))
-            .is_some()
-    }
-
     fn maybe_kind(&self, item_id: DefIndex) -> Option<EntryKind> {
         self.root.tables.kind.get(self, item_id).map(|k| k.decode(self))
     }
 
     fn kind(&self, item_id: DefIndex) -> EntryKind {
-        assert!(!self.is_proc_macro(item_id));
         self.maybe_kind(item_id).unwrap_or_else(|| {
             bug!(
                 "CrateMetadata::kind({:?}): id not found, in crate {:?} with number {}",
@@ -725,35 +717,24 @@ fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro {
     }
 
     fn item_ident(&self, item_index: DefIndex, sess: &Session) -> Ident {
-        if !self.is_proc_macro(item_index) {
-            let name = self
-                .def_key(item_index)
-                .disambiguated_data
-                .data
-                .get_opt_name()
-                .expect("no name in item_ident");
-            let span = self
-                .root
-                .tables
-                .ident_span
-                .get(self, item_index)
-                .map(|data| data.decode((self, sess)))
-                .unwrap_or_else(|| panic!("Missing ident span for {:?} ({:?})", name, item_index));
-            Ident::new(name, span)
-        } else {
-            Ident::new(
-                Symbol::intern(self.raw_proc_macro(item_index).name()),
-                self.get_span(item_index, sess),
-            )
-        }
+        let name = self
+            .def_key(item_index)
+            .disambiguated_data
+            .data
+            .get_opt_name()
+            .expect("no name in item_ident");
+        let span = self
+            .root
+            .tables
+            .ident_span
+            .get(self, item_index)
+            .map(|data| data.decode((self, sess)))
+            .unwrap_or_else(|| panic!("Missing ident span for {:?} ({:?})", name, item_index));
+        Ident::new(name, span)
     }
 
     fn def_kind(&self, index: DefIndex) -> DefKind {
-        if !self.is_proc_macro(index) {
-            self.kind(index).def_kind()
-        } else {
-            DefKind::Macro(macro_kind(self.raw_proc_macro(index)))
-        }
+        self.kind(index).def_kind()
     }
 
     fn get_span(&self, index: DefIndex, sess: &Session) -> Span {
@@ -947,14 +928,16 @@ fn get_generics(&self, item_id: DefIndex, sess: &Session) -> ty::Generics {
     }
 
     fn get_type(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
-        self.root.tables.ty.get(self, id).unwrap().decode((self, tcx))
+        self.root
+            .tables
+            .ty
+            .get(self, id)
+            .unwrap_or_else(|| panic!("Not a type: {:?}", id))
+            .decode((self, tcx))
     }
 
     fn get_stability(&self, id: DefIndex) -> Option<attr::Stability> {
-        match self.is_proc_macro(id) {
-            true => self.root.proc_macro_data.as_ref().unwrap().stability,
-            false => self.root.tables.stability.get(self, id).map(|stab| stab.decode(self)),
-        }
+        self.root.tables.stability.get(self, id).map(|stab| stab.decode(self))
     }
 
     fn get_const_stability(&self, id: DefIndex) -> Option<attr::ConstStability> {
@@ -962,19 +945,11 @@ fn get_const_stability(&self, id: DefIndex) -> Option<attr::ConstStability> {
     }
 
     fn get_deprecation(&self, id: DefIndex) -> Option<attr::Deprecation> {
-        self.root
-            .tables
-            .deprecation
-            .get(self, id)
-            .filter(|_| !self.is_proc_macro(id))
-            .map(|depr| depr.decode(self))
+        self.root.tables.deprecation.get(self, id).map(|depr| depr.decode(self))
     }
 
     fn get_visibility(&self, id: DefIndex) -> ty::Visibility {
-        match self.is_proc_macro(id) {
-            true => ty::Visibility::Public,
-            false => self.root.tables.visibility.get(self, id).unwrap().decode(self),
-        }
+        self.root.tables.visibility.get(self, id).unwrap().decode(self)
     }
 
     fn get_impl_data(&self, id: DefIndex) -> ImplData {
@@ -1186,7 +1161,7 @@ fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Session)
     }
 
     fn is_item_mir_available(&self, id: DefIndex) -> bool {
-        !self.is_proc_macro(id) && self.root.tables.mir.get(self, id).is_some()
+        self.root.tables.mir.get(self, id).is_some()
     }
 
     fn module_expansion(&self, id: DefIndex, sess: &Session) -> ExpnId {
@@ -1202,7 +1177,6 @@ fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> {
             .tables
             .mir
             .get(self, id)
-            .filter(|_| !self.is_proc_macro(id))
             .unwrap_or_else(|| {
                 bug!("get_optimized_mir: missing MIR for `{:?}`", self.local_def_id(id))
             })
@@ -1218,7 +1192,6 @@ fn get_mir_abstract_const(
             .tables
             .mir_abstract_consts
             .get(self, id)
-            .filter(|_| !self.is_proc_macro(id))
             .map_or(Ok(None), |v| Ok(Some(v.decode((self, tcx)))))
     }
 
@@ -1227,7 +1200,6 @@ fn get_unused_generic_params(&self, id: DefIndex) -> FiniteBitSet<u32> {
             .tables
             .unused_generic_params
             .get(self, id)
-            .filter(|_| !self.is_proc_macro(id))
             .map(|params| params.decode(self))
             .unwrap_or_default()
     }
@@ -1237,7 +1209,6 @@ fn get_promoted_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> IndexVec<Promoted
             .tables
             .promoted_mir
             .get(self, id)
-            .filter(|_| !self.is_proc_macro(id))
             .unwrap_or_else(|| {
                 bug!("get_promoted_mir: missing MIR for `{:?}`", self.local_def_id(id))
             })
@@ -1541,14 +1512,11 @@ fn fn_sig(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
 
     #[inline]
     fn def_key(&self, index: DefIndex) -> DefKey {
-        *self.def_key_cache.lock().entry(index).or_insert_with(|| {
-            let mut key = self.root.tables.def_keys.get(self, index).unwrap().decode(self);
-            if self.is_proc_macro(index) {
-                let name = self.raw_proc_macro(index).name();
-                key.disambiguated_data.data = DefPathData::MacroNs(Symbol::intern(name));
-            }
-            key
-        })
+        *self
+            .def_key_cache
+            .lock()
+            .entry(index)
+            .or_insert_with(|| self.root.tables.def_keys.get(self, index).unwrap().decode(self))
     }
 
     // Returns the path leading to the thing with this `id`.
index a7cf1079b8fe4dc95a21127f53662c218c7483cd..46dd0df65e06fa1714e82e359b41926b505239b1 100644 (file)
@@ -9,6 +9,7 @@
 use rustc_hir as hir;
 use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::definitions::DefPathData;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor};
 use rustc_hir::lang_items;
@@ -27,7 +28,7 @@
 use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
 use rustc_serialize::{opaque, Encodable, Encoder};
 use rustc_session::config::CrateType;
-use rustc_span::hygiene::{ExpnDataEncodeMode, HygieneEncodeContext};
+use rustc_span::hygiene::{ExpnDataEncodeMode, HygieneEncodeContext, MacroKind};
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SyntaxContext};
 use rustc_target::abi::VariantIdx;
@@ -1225,7 +1226,7 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) {
             hir::ItemKind::Mod(ref m) => {
                 return self.encode_info_for_mod(item.hir_id, m, &item.attrs);
             }
-            hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod,
+            hir::ItemKind::ForeignMod { .. } => EntryKind::ForeignMod,
             hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm,
             hir::ItemKind::TyAlias(..) => EntryKind::Type,
             hir::ItemKind::OpaqueTy(..) => {
@@ -1320,11 +1321,11 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) {
         record!(self.tables.expn_that_defined[def_id] <- self.tcx.expansion_that_defined(def_id));
         // FIXME(eddyb) there should be a nicer way to do this.
         match item.kind {
-            hir::ItemKind::ForeignMod(ref fm) => record!(self.tables.children[def_id] <-
-                fm.items
+            hir::ItemKind::ForeignMod { items, .. } => record!(self.tables.children[def_id] <-
+                items
                     .iter()
                     .map(|foreign_item| tcx.hir().local_def_id(
-                        foreign_item.hir_id).local_def_index)
+                        foreign_item.id.hir_id).local_def_index)
             ),
             hir::ItemKind::Enum(..) => record!(self.tables.children[def_id] <-
                 self.tcx.adt_def(def_id).variants.iter().map(|v| {
@@ -1539,12 +1540,41 @@ fn encode_proc_macros(&mut self) -> Option<ProcMacroData> {
             // so we manually encode just the information that we need
             for proc_macro in &hir.krate().proc_macros {
                 let id = proc_macro.owner.local_def_index;
-                let span = self.lazy(hir.span(*proc_macro));
+                let mut name = hir.name(*proc_macro);
+                let span = hir.span(*proc_macro);
                 // Proc-macros may have attributes like `#[allow_internal_unstable]`,
                 // so downstream crates need access to them.
-                let attrs = self.lazy(hir.attrs(*proc_macro));
-                self.tables.span.set(id, span);
-                self.tables.attributes.set(id, attrs);
+                let attrs = hir.attrs(*proc_macro);
+                let macro_kind = if tcx.sess.contains_name(attrs, sym::proc_macro) {
+                    MacroKind::Bang
+                } else if tcx.sess.contains_name(attrs, sym::proc_macro_attribute) {
+                    MacroKind::Attr
+                } else if let Some(attr) = tcx.sess.find_by_name(attrs, sym::proc_macro_derive) {
+                    // This unwrap chain should have been checked by the proc-macro harness.
+                    name = attr.meta_item_list().unwrap()[0]
+                        .meta_item()
+                        .unwrap()
+                        .ident()
+                        .unwrap()
+                        .name;
+                    MacroKind::Derive
+                } else {
+                    bug!("Unknown proc-macro type for item {:?}", id);
+                };
+
+                let mut def_key = self.tcx.hir().def_key(proc_macro.owner);
+                def_key.disambiguated_data.data = DefPathData::MacroNs(name);
+
+                let def_id = DefId::local(id);
+                record!(self.tables.kind[def_id] <- EntryKind::ProcMacro(macro_kind));
+                record!(self.tables.attributes[def_id] <- attrs);
+                record!(self.tables.def_keys[def_id] <- def_key);
+                record!(self.tables.ident_span[def_id] <- span);
+                record!(self.tables.span[def_id] <- span);
+                record!(self.tables.visibility[def_id] <- ty::Visibility::Public);
+                if let Some(stability) = stability {
+                    record!(self.tables.stability[def_id] <- stability);
+                }
             }
 
             Some(ProcMacroData { proc_macro_decls_static, stability, macros })
@@ -1836,7 +1866,7 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item<'_>) {
             | hir::ItemKind::Const(..)
             | hir::ItemKind::Fn(..)
             | hir::ItemKind::Mod(..)
-            | hir::ItemKind::ForeignMod(..)
+            | hir::ItemKind::ForeignMod { .. }
             | hir::ItemKind::GlobalAsm(..)
             | hir::ItemKind::ExternCrate(..)
             | hir::ItemKind::Use(..)
@@ -1913,6 +1943,8 @@ 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.
@@ -1977,6 +2009,11 @@ fn visit_impl_item(&self, impl_item: &'v hir::ImplItem<'v>) {
             hir::ImplItemKind::TyAlias(..) => (),
         }
     }
+
+    fn visit_foreign_item(&self, _foreign_item: &'v hir::ForeignItem<'v>) {
+        // This should be kept in sync with `encode_info_for_foreign_item`.
+        // Foreign items contain no MIR.
+    }
 }
 
 // NOTE(eddyb) The following comment was preserved for posterity, even
index 2bd2019d3cdb529b617f00d274ee4db57e7470bc..536061789096408dccbf0fc8264dc0210573aa67 100644 (file)
@@ -20,6 +20,7 @@
 use rustc_session::config::SymbolManglingVersion;
 use rustc_session::CrateDisambiguator;
 use rustc_span::edition::Edition;
+use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::{self, ExpnData, ExpnId, Span};
 use rustc_target::spec::{PanicStrategy, TargetTriple};
@@ -336,6 +337,7 @@ enum EntryKind {
     ForeignFn(Lazy<FnData>),
     Mod(Lazy<ModData>),
     MacroDef(Lazy<MacroDef>),
+    ProcMacro(MacroKind),
     Closure,
     Generator(hir::GeneratorKind),
     Trait(Lazy<TraitData>),
index a61b9af9bace43368b821c711dd4d577d520ee17..38bc3b46b0f15f69cc61a6b408f75e5c0eb9608c 100644 (file)
@@ -193,6 +193,15 @@ pub fn $variant(_tcx: TyCtxt<'_>, $(arg: $tuple_arg_ty)*) -> DepNode {
 
         pub type DepNode = rustc_query_system::dep_graph::DepNode<DepKind>;
 
+        // We keep a lot of `DepNode`s in memory during compilation. It's not
+        // required that their size stay the same, but we don't want to change
+        // it inadvertently. This assert just ensures we're aware of any change.
+        #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+        static_assert_size!(DepNode, 17);
+
+        #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
+        static_assert_size!(DepNode, 24);
+
         pub trait DepNodeExt: Sized {
             /// Construct a DepNode from the given DepKind and DefPathHash. This
             /// method will assert that the given DepKind actually requires a
@@ -227,7 +236,7 @@ fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> DepNode {
                 debug_assert!(kind.can_reconstruct_query_key() && kind.has_params());
                 DepNode {
                     kind,
-                    hash: def_path_hash.0,
+                    hash: def_path_hash.0.into(),
                 }
             }
 
@@ -243,7 +252,7 @@ fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> DepNode {
             /// has been removed.
             fn extract_def_id(&self, tcx: TyCtxt<'tcx>) -> Option<DefId> {
                 if self.kind.can_reconstruct_query_key() {
-                    let def_path_hash = DefPathHash(self.hash);
+                    let def_path_hash = DefPathHash(self.hash.into());
                     tcx.def_path_hash_to_def_id.as_ref()?.get(&def_path_hash).cloned()
                 } else {
                     None
index 6697524279874d1eabfc7ca1bed55248e50c0852..a85b66b65daacc76e26bff806f5d3cb4df06979e 100644 (file)
@@ -164,11 +164,17 @@ fn try_load_from_on_disk_cache(&self, dep_node: &DepNode) {
     }
 
     fn load_diagnostics(&self, prev_dep_node_index: SerializedDepNodeIndex) -> Vec<Diagnostic> {
-        self.queries.on_disk_cache.load_diagnostics(*self, prev_dep_node_index)
+        self.queries
+            .on_disk_cache
+            .as_ref()
+            .map(|c| c.load_diagnostics(*self, prev_dep_node_index))
+            .unwrap_or_default()
     }
 
     fn store_diagnostics(&self, dep_node_index: DepNodeIndex, diagnostics: ThinVec<Diagnostic>) {
-        self.queries.on_disk_cache.store_diagnostics(dep_node_index, diagnostics)
+        if let Some(c) = self.queries.on_disk_cache.as_ref() {
+            c.store_diagnostics(dep_node_index, diagnostics)
+        }
     }
 
     fn store_diagnostics_for_anon_node(
@@ -176,7 +182,9 @@ fn store_diagnostics_for_anon_node(
         dep_node_index: DepNodeIndex,
         diagnostics: ThinVec<Diagnostic>,
     ) {
-        self.queries.on_disk_cache.store_diagnostics_for_anon_node(dep_node_index, diagnostics)
+        if let Some(c) = self.queries.on_disk_cache.as_ref() {
+            c.store_diagnostics_for_anon_node(dep_node_index, diagnostics)
+        }
     }
 
     fn profiler(&self) -> &SelfProfilerRef {
index 516c9b6752b97afa46636b3fffe66a6896880c56..912e9672c94183918644410e2aa94cb352b94ec0 100644 (file)
@@ -112,6 +112,7 @@ pub(super) fn root(
                 items: _,
                 trait_items: _,
                 impl_items: _,
+                foreign_items: _,
                 bodies: _,
                 trait_impls: _,
                 body_ids: _,
@@ -319,6 +320,10 @@ fn visit_nested_impl_item(&mut self, item_id: ImplItemId) {
         self.visit_impl_item(self.krate.impl_item(item_id));
     }
 
+    fn visit_nested_foreign_item(&mut self, foreign_id: ForeignItemId) {
+        self.visit_foreign_item(self.krate.foreign_item(foreign_id));
+    }
+
     fn visit_nested_body(&mut self, id: BodyId) {
         self.visit_body(self.krate.body(id));
     }
@@ -351,11 +356,17 @@ fn visit_item(&mut self, i: &'hir Item<'hir>) {
         });
     }
 
-    fn visit_foreign_item(&mut self, foreign_item: &'hir ForeignItem<'hir>) {
-        self.insert(foreign_item.span, foreign_item.hir_id, Node::ForeignItem(foreign_item));
+    fn visit_foreign_item(&mut self, fi: &'hir ForeignItem<'hir>) {
+        debug_assert_eq!(
+            fi.hir_id.owner,
+            self.definitions.opt_hir_id_to_local_def_id(fi.hir_id).unwrap()
+        );
+        self.with_dep_node_owner(fi.hir_id.owner, fi, |this, hash| {
+            this.insert_with_hash(fi.span, fi.hir_id, Node::ForeignItem(fi), hash);
 
-        self.with_parent(foreign_item.hir_id, |this| {
-            intravisit::walk_foreign_item(this, foreign_item);
+            this.with_parent(fi.hir_id, |this| {
+                intravisit::walk_foreign_item(this, fi);
+            });
         });
     }
 
index 37ec3d3d1cab923b4d57aff61ffb318562131e61..5e36362ec59167640ca168663d33cfbfa28aaa1c 100644 (file)
@@ -205,7 +205,7 @@ pub fn def_kind(&self, local_def_id: LocalDefId) -> DefKind {
                 ItemKind::TraitAlias(..) => DefKind::TraitAlias,
                 ItemKind::ExternCrate(_) => DefKind::ExternCrate,
                 ItemKind::Use(..) => DefKind::Use,
-                ItemKind::ForeignMod(..) => DefKind::ForeignMod,
+                ItemKind::ForeignMod { .. } => DefKind::ForeignMod,
                 ItemKind::GlobalAsm(..) => DefKind::GlobalAsm,
                 ItemKind::Impl { .. } => DefKind::Impl,
             },
@@ -309,6 +309,13 @@ pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
         }
     }
 
+    pub fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
+        match self.find(id.hir_id).unwrap() {
+            Node::ForeignItem(item) => item,
+            _ => bug!(),
+        }
+    }
+
     pub fn body(&self, id: BodyId) -> &'hir Body<'hir> {
         self.tcx.hir_owner_nodes(id.hir_id.owner).unwrap().bodies.get(&id.hir_id.local_id).unwrap()
     }
@@ -470,6 +477,10 @@ pub fn visit_item_likes_in_module<V>(&self, module: LocalDefId, visitor: &mut V)
         for id in &module.impl_items {
             visitor.visit_impl_item(self.expect_impl_item(id.hir_id));
         }
+
+        for id in &module.foreign_items {
+            visitor.visit_foreign_item(self.expect_foreign_item(id.hir_id));
+        }
     }
 
     /// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found.
@@ -718,10 +729,11 @@ pub fn get_foreign_abi(&self, hir_id: HirId) -> Abi {
         let parent = self.get_parent_item(hir_id);
         if let Some(entry) = self.find_entry(parent) {
             if let Entry {
-                node: Node::Item(Item { kind: ItemKind::ForeignMod(ref nm), .. }), ..
+                node: Node::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }),
+                ..
             } = entry
             {
-                return nm.abi;
+                return *abi;
             }
         }
         bug!("expected foreign mod or inlined parent, found {}", self.node_to_string(parent))
@@ -937,6 +949,10 @@ fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
     fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
         self.impl_item(id)
     }
+
+    fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
+        self.foreign_item(id)
+    }
 }
 
 trait Named {
@@ -1030,7 +1046,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String {
                 ItemKind::Const(..) => "const",
                 ItemKind::Fn(..) => "fn",
                 ItemKind::Mod(..) => "mod",
-                ItemKind::ForeignMod(..) => "foreign mod",
+                ItemKind::ForeignMod { .. } => "foreign mod",
                 ItemKind::GlobalAsm(..) => "global asm",
                 ItemKind::TyAlias(..) => "ty",
                 ItemKind::OpaqueTy(..) => "opaque type",
index 6b46d7c497d3e2cee63cd25f3b76c2752fec001a..8a6bf9dff7b6fb2ecb84464d239831b1a41aea34 100644 (file)
@@ -21,9 +21,9 @@ pub struct ExpressionOperandId {
 impl ExpressionOperandId {
     /// An expression operand for a "zero counter", as described in the following references:
     ///
-    /// * <https://github.com/rust-lang/llvm-project/blob/llvmorg-8.0.0/llvm/docs/CoverageMappingFormat.rst#counter>
-    /// * <https://github.com/rust-lang/llvm-project/blob/llvmorg-8.0.0/llvm/docs/CoverageMappingFormat.rst#tag>
-    /// * <https://github.com/rust-lang/llvm-project/blob/llvmorg-8.0.0/llvm/docs/CoverageMappingFormat.rst#counter-expressions>
+    /// * <https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#counter>
+    /// * <https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#tag>
+    /// * <https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#counter-expressions>
     ///
     /// This operand can be used to count two or more separate code regions with a single counter,
     /// if they run sequentially with no branches, by injecting the `Counter` in a `BasicBlock` for
index 9289d4708de1e07fd5c21e54f9d3ea036095c803..814f91b04310f5c98dd6347701e79e5c952a5a03 100644 (file)
@@ -811,7 +811,7 @@ pub struct LocalDecl<'tcx> {
     /// after typeck.
     ///
     /// This should be sound because the drop flags are fully algebraic, and
-    /// therefore don't affect the OIBIT or outlives properties of the
+    /// therefore don't affect the auto-trait or outlives properties of the
     /// generator.
     pub internal: bool,
 
index 638dd8ce9706f355a408c8a0438ac801b06224e9..7538818b8afc33cb85ab0ab0b9f73f06273d36c0 100644 (file)
@@ -254,7 +254,7 @@ fn super_body(
                 macro_rules! basic_blocks {
                     (mut) => (body.basic_blocks_mut().iter_enumerated_mut());
                     () => (body.basic_blocks().iter_enumerated());
-                };
+                }
                 for (bb, data) in basic_blocks!($($mutability)?) {
                     self.visit_basic_block_data(bb, data);
                 }
@@ -275,7 +275,7 @@ macro_rules! basic_blocks {
                 macro_rules! type_annotations {
                     (mut) => (body.user_type_annotations.iter_enumerated_mut());
                     () => (body.user_type_annotations.iter_enumerated());
-                };
+                }
 
                 for (index, annotation) in type_annotations!($($mutability)?) {
                     self.visit_user_type_annotation(
@@ -909,7 +909,7 @@ fn visit_location(
                 macro_rules! basic_blocks {
                     (mut) => (body.basic_blocks_mut());
                     () => (body.basic_blocks());
-                };
+                }
                 let basic_block = & $($mutability)? basic_blocks!($($mutability)?)[location.block];
                 if basic_block.statements.len() == location.statement_index {
                     if let Some(ref $($mutability)? terminator) = basic_block.terminator {
@@ -1017,11 +1017,14 @@ fn super_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location:
             let mut context = context;
 
             if !place.projection.is_empty() {
-                context = if context.is_mutating_use() {
-                    PlaceContext::MutatingUse(MutatingUseContext::Projection)
-                } else {
-                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
-                };
+                if context.is_use() {
+                    // ^ Only change the context if it is a real use, not a "use" in debuginfo.
+                    context = if context.is_mutating_use() {
+                        PlaceContext::MutatingUse(MutatingUseContext::Projection)
+                    } else {
+                        PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
+                    };
+                }
             }
 
             self.visit_local(&place.local, context, location);
index 634d50368bd881223c02913435f1a415910d1c69..7822ecc2c1f76f49fccee2c372bc2c7e9cc97acf 100644 (file)
@@ -130,8 +130,8 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
             storage(ArenaCacheSelector<'tcx>)
             cache_on_disk_if { key.is_local() }
             load_cached(tcx, id) {
-                let generics: Option<ty::Generics> = tcx.queries.on_disk_cache
-                                                        .try_load_query_result(tcx, id);
+                let generics: Option<ty::Generics> = tcx.queries.on_disk_cache.as_ref()
+                                                        .and_then(|c| c.try_load_query_result(tcx, id));
                 generics
             }
         }
@@ -635,6 +635,10 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
             desc { |tcx| "checking loops in {}", describe_as_module(key, tcx) }
         }
 
+        query check_mod_naked_functions(key: LocalDefId) -> () {
+            desc { |tcx| "checking naked functions in {}", describe_as_module(key, tcx) }
+        }
+
         query check_mod_item_types(key: LocalDefId) -> () {
             desc { |tcx| "checking item types in {}", describe_as_module(key, tcx) }
         }
@@ -688,8 +692,8 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
             cache_on_disk_if { true }
             load_cached(tcx, id) {
                 let typeck_results: Option<ty::TypeckResults<'tcx>> = tcx
-                    .queries.on_disk_cache
-                    .try_load_query_result(tcx, id);
+                    .queries.on_disk_cache.as_ref()
+                    .and_then(|c| c.try_load_query_result(tcx, id));
 
                 typeck_results.map(|x| &*tcx.arena.alloc(x))
             }
index 4deb7225dcb61db4e6cb7a1b0f28181a5c8d8f4c..0a663f793aa753cc8cf84404e2d20f97d12e0708 100644 (file)
@@ -16,6 +16,7 @@
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_hir::Constness;
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
 use smallvec::SmallVec;
@@ -70,7 +71,7 @@ pub enum Reveal {
     /// be observable directly by the user, `Reveal::All`
     /// should not be used by checks which may expose
     /// type equality or type contents to the user.
-    /// There are some exceptions, e.g., around OIBITS and
+    /// There are some exceptions, e.g., around auto traits and
     /// transmute-checking, which expose some details, but
     /// not the whole concrete type of the `impl Trait`.
     All,
@@ -457,7 +458,7 @@ pub enum ImplSource<'tcx, N> {
     /// for some type parameter. The `Vec<N>` represents the
     /// obligations incurred from normalizing the where-clause (if
     /// any).
-    Param(Vec<N>),
+    Param(Vec<N>, Constness),
 
     /// Virtual calls through an object.
     Object(ImplSourceObjectData<'tcx, N>),
@@ -487,7 +488,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
     pub fn nested_obligations(self) -> Vec<N> {
         match self {
             ImplSource::UserDefined(i) => i.nested,
-            ImplSource::Param(n) => n,
+            ImplSource::Param(n, _) => n,
             ImplSource::Builtin(i) => i.nested,
             ImplSource::AutoImpl(d) => d.nested,
             ImplSource::Closure(c) => c.nested,
@@ -502,7 +503,7 @@ pub fn nested_obligations(self) -> Vec<N> {
     pub fn borrow_nested_obligations(&self) -> &[N] {
         match &self {
             ImplSource::UserDefined(i) => &i.nested[..],
-            ImplSource::Param(n) => &n[..],
+            ImplSource::Param(n, _) => &n[..],
             ImplSource::Builtin(i) => &i.nested[..],
             ImplSource::AutoImpl(d) => &d.nested[..],
             ImplSource::Closure(c) => &c.nested[..],
@@ -524,7 +525,7 @@ pub fn map<M, F>(self, f: F) -> ImplSource<'tcx, M>
                 substs: i.substs,
                 nested: i.nested.into_iter().map(f).collect(),
             }),
-            ImplSource::Param(n) => ImplSource::Param(n.into_iter().map(f).collect()),
+            ImplSource::Param(n, ct) => ImplSource::Param(n.into_iter().map(f).collect(), ct),
             ImplSource::Builtin(i) => ImplSource::Builtin(ImplSourceBuiltinData {
                 nested: i.nested.into_iter().map(f).collect(),
             }),
index c570ad3273d4e3dcbd81c12911dd908c53b93ed6..e056240f9415045ae2f18f600a9ea62f5dec8f71 100644 (file)
@@ -101,7 +101,7 @@ pub enum SelectionCandidate<'tcx> {
         /// `false` if there are no *further* obligations.
         has_nested: bool,
     },
-    ParamCandidate(ty::PolyTraitRef<'tcx>),
+    ParamCandidate(ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>),
     ImplCandidate(DefId),
     AutoImplCandidate(DefId),
 
index 194e275496e955301d0c78b3b72d19298dace916..5a17d38c73460bacbb994669ba118171ed4050d8 100644 (file)
@@ -21,7 +21,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
             super::ImplSource::Object(ref d) => write!(f, "{:?}", d),
 
-            super::ImplSource::Param(ref n) => write!(f, "ImplSourceParamData({:?})", n),
+            super::ImplSource::Param(ref n, ct) => {
+                write!(f, "ImplSourceParamData({:?}, {:?})", n, ct)
+            }
 
             super::ImplSource::Builtin(ref d) => write!(f, "{:?}", d),
 
index 36cbd36a7705f1ad21bd5dd80f9989d88860b624..7207e5a179e4f436de9c0a9814582482a0a0456e 100644 (file)
@@ -42,7 +42,9 @@
 use rustc_hir::definitions::{DefPathHash, Definitions};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
-use rustc_hir::{HirId, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet, Node, TraitCandidate};
+use rustc_hir::{
+    Constness, HirId, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet, Node, TraitCandidate,
+};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable;
 use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
@@ -1094,7 +1096,7 @@ pub fn create_global_ctxt(
         krate: &'tcx hir::Crate<'tcx>,
         definitions: &'tcx Definitions,
         dep_graph: DepGraph,
-        on_disk_query_result_cache: query::OnDiskCache<'tcx>,
+        on_disk_query_result_cache: Option<query::OnDiskCache<'tcx>>,
         crate_name: &str,
         output_filenames: &OutputFilenames,
     ) -> GlobalCtxt<'tcx> {
@@ -1343,7 +1345,7 @@ pub fn serialize_query_result_cache<E>(self, encoder: &mut E) -> Result<(), E::E
     where
         E: ty::codec::OpaqueEncoder,
     {
-        self.queries.on_disk_cache.serialize(self, encoder)
+        self.queries.on_disk_cache.as_ref().map(|c| c.serialize(self, encoder)).unwrap_or(Ok(()))
     }
 
     /// If `true`, we should use the MIR-based borrowck, but also
@@ -1635,6 +1637,8 @@ fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
 // This is the impl for `&'a InternalSubsts<'a>`.
 nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
 
+CloneLiftImpls! { for<'tcx> { Constness, } }
+
 pub mod tls {
     use super::{ptr_eq, GlobalCtxt, TyCtxt};
 
index f52466d85f890aa37323afac72fa6132fe522e31..413c9cca589d9097107c0ebb0cce9f775e1e960c 100644 (file)
@@ -540,7 +540,7 @@ fn polymorphize<'tcx>(
 
     struct PolymorphizationFolder<'tcx> {
         tcx: TyCtxt<'tcx>,
-    };
+    }
 
     impl ty::TypeFolder<'tcx> for PolymorphizationFolder<'tcx> {
         fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
index 5626c864fe175e13ded320a28d7e2b939803863d..fa0711193df487bbf72025f5e9aa7e0d514f7662 100644 (file)
@@ -15,7 +15,7 @@
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::DUMMY_SP;
 use rustc_target::abi::call::{
-    ArgAbi, ArgAttribute, ArgAttributes, Conv, FnAbi, PassMode, Reg, RegKind,
+    ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind,
 };
 use rustc_target::abi::*;
 use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy};
@@ -2619,7 +2619,7 @@ fn new_internal(
                                       is_return: bool| {
             // Booleans are always an i1 that needs to be zero-extended.
             if scalar.is_bool() {
-                attrs.set(ArgAttribute::ZExt);
+                attrs.ext(ArgExtension::Zext);
                 return;
             }
 
@@ -2801,9 +2801,6 @@ fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) {
             for arg in &mut self.args {
                 fixup(arg, false);
             }
-            if let PassMode::Indirect(ref mut attrs, _) = self.ret.mode {
-                attrs.set(ArgAttribute::StructRet);
-            }
             return;
         }
 
index 6a67935cd98fe40468dcb43dd8959ae43f90d1d9..5d8edcf70bfd3329eff91af509afa157cbf3a37a 100644 (file)
@@ -1503,9 +1503,11 @@ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
 }
 
 impl<'tcx> Predicate<'tcx> {
-    pub fn to_opt_poly_trait_ref(self) -> Option<PolyTraitRef<'tcx>> {
+    pub fn to_opt_poly_trait_ref(self) -> Option<ConstnessAnd<PolyTraitRef<'tcx>>> {
         match self.skip_binders() {
-            PredicateAtom::Trait(t, _) => Some(ty::Binder::bind(t.trait_ref)),
+            PredicateAtom::Trait(t, constness) => {
+                Some(ConstnessAnd { constness, value: ty::Binder::bind(t.trait_ref) })
+            }
             PredicateAtom::Projection(..)
             | PredicateAtom::Subtype(..)
             | PredicateAtom::RegionOutlives(..)
@@ -1947,7 +1949,7 @@ pub fn and<T: TypeFoldable<'tcx>>(self, value: T) -> ParamEnvAnd<'tcx, T> {
     }
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)]
 pub struct ConstnessAnd<T> {
     pub constness: Constness,
     pub value: T,
index d038695283c107588aa8a252da3d4061f561aeb7..d0730bd121c9815c68ccf3d9c4f1d8a06eb1ea89 100644 (file)
@@ -128,7 +128,7 @@ pub(super) fn report_cycle(
     pub fn try_print_query_stack(handler: &Handler, num_frames: Option<usize>) {
         eprintln!("query stack during panic:");
 
-        // Be careful reyling on global state here: this code is called from
+        // Be careful relying on global state here: this code is called from
         // a panic hook, which means that the global `Handler` may be in a weird
         // state if it was responsible for triggering the panic.
         let mut i = 0;
@@ -507,10 +507,11 @@ macro_rules! define_queries_struct {
     (tcx: $tcx:tt,
      input: ($(([$($modifiers:tt)*] [$($attr:tt)*] [$name:ident]))*)) => {
         pub struct Queries<$tcx> {
-            /// This provides access to the incrimental comilation on-disk cache for query results.
+            /// This provides access to the incremental compilation on-disk cache for query results.
             /// Do not access this directly. It is only meant to be used by
             /// `DepGraph::try_mark_green()` and the query infrastructure.
-            pub(crate) on_disk_cache: OnDiskCache<'tcx>,
+            /// This is `None` if we are not incremental compilation mode
+            pub(crate) on_disk_cache: Option<OnDiskCache<'tcx>>,
 
             providers: IndexVec<CrateNum, Providers>,
             fallback_extern_providers: Box<Providers>,
@@ -526,7 +527,7 @@ impl<$tcx> Queries<$tcx> {
             pub(crate) fn new(
                 providers: IndexVec<CrateNum, Providers>,
                 fallback_extern_providers: Providers,
-                on_disk_cache: OnDiskCache<'tcx>,
+                on_disk_cache: Option<OnDiskCache<'tcx>>,
             ) -> Self {
                 Queries {
                     providers,
index 4bf16436855f48b24518aaaf921b42ac3e200427..c906b8ac901a57656a929a3b380fd0169e446214 100644 (file)
@@ -1106,10 +1106,7 @@ pub fn split<U, V, F>(self, f: F) -> (Binder<U>, Binder<V>)
 
 impl<T> Binder<Option<T>> {
     pub fn transpose(self) -> Option<Binder<T>> {
-        match self.0 {
-            Some(v) => Some(Binder(v)),
-            None => None,
-        }
+        self.0.map(Binder)
     }
 }
 
index d3b6d706337edb90e445a67486b06fdef60f2453..f666a89ca56decd9af79427d36d37ed196b59af6 100644 (file)
@@ -75,13 +75,35 @@ fn numeric_intrinsic<'tcx, Tag>(
             ensure_monomorphic_enough(tcx, tp_ty)?;
             ConstValue::from_u64(tcx.type_id_hash(tp_ty))
         }
-        sym::variant_count => {
-            if let ty::Adt(ref adt, _) = tp_ty.kind() {
-                ConstValue::from_machine_usize(adt.variants.len() as u64, &tcx)
-            } else {
-                ConstValue::from_machine_usize(0u64, &tcx)
-            }
-        }
+        sym::variant_count => match tp_ty.kind() {
+            ty::Adt(ref adt, _) => ConstValue::from_machine_usize(adt.variants.len() as u64, &tcx),
+            ty::Projection(_)
+            | ty::Opaque(_, _)
+            | ty::Param(_)
+            | ty::Bound(_, _)
+            | ty::Placeholder(_)
+            | ty::Infer(_) => throw_inval!(TooGeneric),
+            ty::Bool
+            | ty::Char
+            | ty::Int(_)
+            | ty::Uint(_)
+            | ty::Float(_)
+            | ty::Foreign(_)
+            | ty::Str
+            | ty::Array(_, _)
+            | ty::Slice(_)
+            | ty::RawPtr(_)
+            | ty::Ref(_, _, _)
+            | ty::FnDef(_, _)
+            | ty::FnPtr(_)
+            | ty::Dynamic(_, _)
+            | ty::Closure(_, _)
+            | ty::Generator(_, _, _)
+            | ty::GeneratorWitness(_)
+            | ty::Never
+            | ty::Tuple(_)
+            | ty::Error(_) => ConstValue::from_machine_usize(0u64, &tcx),
+        },
         other => bug!("`{}` is not a zero arg intrinsic", other),
     })
 }
index e49b1c9f64d44ef3f06480a59f5149fcff71af81..ec90f063a55240fb4afcca9094b010bcbbd77eae 100644 (file)
@@ -15,7 +15,7 @@
 
     struct UsedParamsNeedSubstVisitor<'tcx> {
         tcx: TyCtxt<'tcx>,
-    };
+    }
 
     impl<'tcx> TypeVisitor<'tcx> for UsedParamsNeedSubstVisitor<'tcx> {
         type BreakTy = ();
index a6f9099217253ff272c74f1649480c0b157cde70..6370ead97e798972cb9ef9886f5f7b2fa5398a9e 100644 (file)
@@ -993,7 +993,7 @@ fn visit_item(&mut self, item: &'v hir::Item<'v>) {
         match item.kind {
             hir::ItemKind::ExternCrate(..)
             | hir::ItemKind::Use(..)
-            | hir::ItemKind::ForeignMod(..)
+            | hir::ItemKind::ForeignMod { .. }
             | hir::ItemKind::TyAlias(..)
             | hir::ItemKind::Trait(..)
             | hir::ItemKind::TraitAlias(..)
@@ -1066,6 +1066,8 @@ fn visit_impl_item(&mut self, ii: &'v hir::ImplItem<'v>) {
             self.push_if_root(def_id);
         }
     }
+
+    fn visit_foreign_item(&mut self, _foreign_item: &'v hir::ForeignItem<'v>) {}
 }
 
 impl RootCollector<'_, 'v> {
index 3a1fa0018c104f29a541b19a3ee7b07ceb1fa232..aa5835686a291edf212e31d2bca3bffc1d79c124 100644 (file)
@@ -308,10 +308,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -
 
     match self_ty.kind() {
         _ if is_copy => builder.copy_shim(),
-        ty::Array(ty, len) => {
-            let len = len.eval_usize(tcx, param_env);
-            builder.array_shim(dest, src, ty, len)
-        }
+        ty::Array(ty, len) => builder.array_shim(dest, src, ty, len),
         ty::Closure(_, substs) => {
             builder.tuple_like_shim(dest, src, substs.as_closure().upvar_tys())
         }
@@ -485,7 +482,13 @@ fn make_usize(&self, value: u64) -> Box<Constant<'tcx>> {
         }
     }
 
-    fn array_shim(&mut self, dest: Place<'tcx>, src: Place<'tcx>, ty: Ty<'tcx>, len: u64) {
+    fn array_shim(
+        &mut self,
+        dest: Place<'tcx>,
+        src: Place<'tcx>,
+        ty: Ty<'tcx>,
+        len: &'tcx ty::Const<'tcx>,
+    ) {
         let tcx = self.tcx;
         let span = self.span;
 
@@ -503,7 +506,11 @@ fn array_shim(&mut self, dest: Place<'tcx>, src: Place<'tcx>, ty: Ty<'tcx>, len:
             ))),
             self.make_statement(StatementKind::Assign(box (
                 end,
-                Rvalue::Use(Operand::Constant(self.make_usize(len))),
+                Rvalue::Use(Operand::Constant(box Constant {
+                    span: self.span,
+                    user_ty: None,
+                    literal: len,
+                })),
             ))),
         ];
         self.block(inits, TerminatorKind::Goto { target: BasicBlock::new(1) }, false);
index e4893044a159933cabf2b6c5e323d508ece31145..d00038f345c9950ee022273b7436475c117043fa 100644 (file)
@@ -4,6 +4,7 @@
 use rustc_hir::def_id::DefId;
 use rustc_hir::{self as hir, HirId, LangItem};
 use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::cast::CastTy;
 use rustc_middle::ty::{
     self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt, TypeAndMut,
 };
+use rustc_middle::ty::{Binder, TraitPredicate, TraitRef};
 use rustc_span::{sym, Span, Symbol};
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
-use rustc_trait_selection::traits::{self, TraitEngine};
+use rustc_trait_selection::traits::{self, SelectionContext, TraitEngine};
 
 use std::mem;
 use std::ops::Deref;
@@ -765,9 +767,39 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
                     }
                 };
 
-                // Resolve a trait method call to its concrete implementation, which may be in a
-                // `const` trait impl.
-                if self.tcx.features().const_trait_impl {
+                // Attempting to call a trait method?
+                if let Some(trait_id) = tcx.trait_of_item(callee) {
+                    if !self.tcx.features().const_trait_impl {
+                        self.check_op(ops::FnCallNonConst(callee));
+                        return;
+                    }
+
+                    let trait_ref = TraitRef::from_method(tcx, trait_id, substs);
+                    let obligation = Obligation::new(
+                        ObligationCause::dummy(),
+                        param_env,
+                        Binder::bind(TraitPredicate {
+                            trait_ref: TraitRef::from_method(tcx, trait_id, substs),
+                        }),
+                    );
+
+                    let implsrc = tcx.infer_ctxt().enter(|infcx| {
+                        let mut selcx = SelectionContext::new(&infcx);
+                        selcx.select(&obligation).unwrap()
+                    });
+
+                    // If the method is provided via a where-clause that does not use the `?const`
+                    // opt-out, the call is allowed.
+                    if let Some(ImplSource::Param(_, hir::Constness::Const)) = implsrc {
+                        debug!(
+                            "const_trait_impl: provided {:?} via where-clause in {:?}",
+                            trait_ref, param_env
+                        );
+                        return;
+                    }
+
+                    // Resolve a trait method call to its concrete implementation, which may be in a
+                    // `const` trait impl.
                     let instance = Instance::resolve(tcx, param_env, callee, substs);
                     debug!("Resolving ({:?}) -> {:?}", callee, instance);
                     if let Ok(Some(func)) = instance {
index aeb9920c0e321c36c8f804c32211c992f0b0203b..abcf1862fd87366e052a8895ea6199d5adcce75c 100644 (file)
@@ -800,7 +800,7 @@ fn replace_with_const(
             }
         }
 
-        trace!("attepting to replace {:?} with {:?}", rval, value);
+        trace!("attempting to replace {:?} with {:?}", rval, value);
         if let Err(e) = self.ecx.const_validate_operand(
             value,
             vec![],
@@ -890,6 +890,10 @@ fn should_const_prop(&mut self, op: OpTy<'tcx>) -> bool {
             return false;
         }
 
+        if !self.tcx.consider_optimizing(|| format!("ConstantPropagation - OpTy: {:?}", op)) {
+            return false;
+        }
+
         match *op {
             interpret::Operand::Immediate(Immediate::Scalar(ScalarMaybeUninit::Scalar(s))) => {
                 s.is_bits()
index 7f1dc3844b21dc2cc1481ba310a03a6f1e4e802c..e9528557b3337d9d2e96a41681fe29325e57f68c 100644 (file)
 //!
 //!     Depending on the values and combinations, counters can be labeled by:
 //!
-//!         * `id` - counter or expression ID (ascending counter IDs, starting at 1, or descending
-//!           expression IDs, starting at `u32:MAX`)
-//!         * `block` - the `BasicCoverageBlock` label (for example, `bcb0`) or edge label (for
-//!           example `bcb0->bcb1`), for counters or expressions assigned to count a
-//!           `BasicCoverageBlock` or edge. Intermediate expressions (not directly associated with
-//!           a BCB or edge) will be labeled by their expression ID, unless `operation` is also
-//!           specified.
-//!         * `operation` - applied to expressions only, labels include the left-hand-side counter
-//!           or expression label (lhs operand), the operator (`+` or `-`), and the right-hand-side
-//!           counter or expression (rhs operand). Expression operand labels are generated
-//!           recursively, generating labels with nested operations, enclosed in parentheses
-//!           (for example: `bcb2 + (bcb0 - bcb1)`).
+//!       * `id` - counter or expression ID (ascending counter IDs, starting at 1, or descending
+//!         expression IDs, starting at `u32:MAX`)
+//!       * `block` - the `BasicCoverageBlock` label (for example, `bcb0`) or edge label (for
+//!         example `bcb0->bcb1`), for counters or expressions assigned to count a
+//!         `BasicCoverageBlock` or edge. Intermediate expressions (not directly associated with
+//!         a BCB or edge) will be labeled by their expression ID, unless `operation` is also
+//!         specified.
+//!       * `operation` - applied to expressions only, labels include the left-hand-side counter
+//!         or expression label (lhs operand), the operator (`+` or `-`), and the right-hand-side
+//!         counter or expression (rhs operand). Expression operand labels are generated
+//!         recursively, generating labels with nested operations, enclosed in parentheses
+//!         (for example: `bcb2 + (bcb0 - bcb1)`).
 
 use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph};
 use super::spans::CoverageSpan;
index f97dcf4852df477a398485fce1207949200a4329..f91477911a489015363ab72bcd08ca9c6dbfd1aa 100644 (file)
@@ -46,6 +46,10 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let should_cleanup = !opts_to_apply.is_empty();
 
         for opt_to_apply in opts_to_apply {
+            if !tcx.consider_optimizing(|| format!("EarlyOtherwiseBranch {:?}", &opt_to_apply)) {
+                break;
+            }
+
             trace!("SUCCESS: found optimization possibility to apply: {:?}", &opt_to_apply);
 
             let statements_before =
index 094c1513118679bf3e16a327f14dd698f9ee754b..4eeb8969bb11002fcea6d0694c76404c73396b9e 100644 (file)
@@ -254,6 +254,11 @@ fn should_inline(&self, callsite: CallSite<'tcx>, callee_body: &Body<'tcx>) -> b
             self.tcx.sess.opts.debugging_opts.inline_mir_threshold
         };
 
+        if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
+            debug!("#[naked] present - not inlining");
+            return false;
+        }
+
         if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) {
             debug!("#[cold] present - not inlining");
             return false;
index 59b7db243190081361b77f2e458e4422d412d46e..3eb2b500d6627324dd0950e91556b780511286d3 100644 (file)
@@ -39,13 +39,21 @@ pub struct InstCombineVisitor<'tcx> {
     tcx: TyCtxt<'tcx>,
 }
 
+impl<'tcx> InstCombineVisitor<'tcx> {
+    fn should_combine(&self, rvalue: &Rvalue<'tcx>, location: Location) -> bool {
+        self.tcx.consider_optimizing(|| {
+            format!("InstCombine - Rvalue: {:?} Location: {:?}", rvalue, location)
+        })
+    }
+}
+
 impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
     fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
-        if self.optimizations.and_stars.remove(&location) {
+        if self.optimizations.and_stars.remove(&location) && self.should_combine(rvalue, location) {
             debug!("replacing `&*`: {:?}", rvalue);
             let new_place = match rvalue {
                 Rvalue::Ref(_, _, place) => {
@@ -67,18 +75,24 @@ fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
         }
 
         if let Some(constant) = self.optimizations.arrays_lengths.remove(&location) {
-            debug!("replacing `Len([_; N])`: {:?}", rvalue);
-            *rvalue = Rvalue::Use(Operand::Constant(box constant));
+            if self.should_combine(rvalue, location) {
+                debug!("replacing `Len([_; N])`: {:?}", rvalue);
+                *rvalue = Rvalue::Use(Operand::Constant(box constant));
+            }
         }
 
         if let Some(operand) = self.optimizations.unneeded_equality_comparison.remove(&location) {
-            debug!("replacing {:?} with {:?}", rvalue, operand);
-            *rvalue = Rvalue::Use(operand);
+            if self.should_combine(rvalue, location) {
+                debug!("replacing {:?} with {:?}", rvalue, operand);
+                *rvalue = Rvalue::Use(operand);
+            }
         }
 
         if let Some(place) = self.optimizations.unneeded_deref.remove(&location) {
-            debug!("unneeded_deref: replacing {:?} with {:?}", rvalue, place);
-            *rvalue = Rvalue::Use(Operand::Copy(place));
+            if self.should_combine(rvalue, location) {
+                debug!("unneeded_deref: replacing {:?} with {:?}", rvalue, place);
+                *rvalue = Rvalue::Use(Operand::Copy(place));
+            }
         }
 
         self.super_rvalue(rvalue, location)
index da937094c41702c163465971f254c2407176eedf..543acb74acbc9102f89fa7508a6986fd8eed0c59 100644 (file)
 
 impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        for block in body.basic_blocks_mut() {
+        let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
+        for block in basic_blocks {
             let terminator = block.terminator.as_mut().unwrap();
-            if let TerminatorKind::Call {
-                func: Operand::Constant(box Constant { literal: ty::Const { ty: func_ty, .. }, .. }),
-                args,
-                destination,
-                ..
-            } = &mut terminator.kind
-            {
+            if let TerminatorKind::Call { func, args, destination, .. } = &mut terminator.kind {
+                let func_ty = func.ty(local_decls, tcx);
                 let (intrinsic_name, substs) = match resolve_rust_intrinsic(tcx, func_ty) {
                     None => continue,
                     Some(it) => it,
index 82c0b924f287e3330facfed2e52b6bb43d654249..53eeecc780f6f1ed628c1ec766ac147b24aa3d1f 100644 (file)
@@ -43,8 +43,13 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         }
 
         let param_env = tcx.param_env(body.source.def_id());
+        let def_id = body.source.def_id();
         let (bbs, local_decls) = body.basic_blocks_and_local_decls_mut();
         'outer: for bb_idx in bbs.indices() {
+            if !tcx.consider_optimizing(|| format!("MatchBranchSimplification {:?} ", def_id)) {
+                continue;
+            }
+
             let (discr, val, switch_ty, first, second) = match bbs[bb_idx].terminator().kind {
                 TerminatorKind::SwitchInt {
                     discr: ref discr @ (Operand::Copy(_) | Operand::Move(_)),
index c37b54a3190f8fb7e6eb736b89d1341a59a968ea..617086622cc1ac7728317681276c6ca473849b10 100644 (file)
@@ -16,6 +16,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 
         // find basic blocks with no statement and a return terminator
         let mut bbs_simple_returns = BitSet::new_empty(body.basic_blocks().len());
+        let def_id = body.source.def_id();
         let bbs = body.basic_blocks_mut();
         for idx in bbs.indices() {
             if bbs[idx].statements.is_empty()
@@ -26,6 +27,10 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         }
 
         for bb in bbs {
+            if !tcx.consider_optimizing(|| format!("MultipleReturnTerminators {:?} ", def_id)) {
+                break;
+            }
+
             if let TerminatorKind::Goto { target } = bb.terminator().kind {
                 if bbs_simple_returns.contains(target) {
                     bb.terminator_mut().kind = TerminatorKind::Return;
index 45b906bf542d5a37703c98e1d1ad7b039020664d..ce02fb261df6f981991fa955cc3772d72861fe65 100644 (file)
@@ -38,18 +38,22 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) {
             return;
         }
 
+        let def_id = body.source.def_id();
         let returned_local = match local_eligible_for_nrvo(body) {
             Some(l) => l,
             None => {
-                debug!("`{:?}` was ineligible for NRVO", body.source.def_id());
+                debug!("`{:?}` was ineligible for NRVO", def_id);
                 return;
             }
         };
 
+        if !tcx.consider_optimizing(|| format!("RenameReturnPlace {:?}", def_id)) {
+            return;
+        }
+
         debug!(
             "`{:?}` was eligible for NRVO, making {:?} the return place",
-            body.source.def_id(),
-            returned_local
+            def_id, returned_local
         );
 
         RenameToReturnPlace { tcx, to_rename: returned_local }.visit_body(body);
index aaf3ecab4dca728ac3302d78f0fc7a0307369a14..221114eebaa45a670c93b8699c9906160eb4ee1e 100644 (file)
@@ -21,6 +21,12 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         opt_finder.visit_body(body);
         let should_simplify = !opt_finder.optimizations.is_empty();
         for (loc, target) in opt_finder.optimizations {
+            if !tcx
+                .consider_optimizing(|| format!("RemoveUnneededDrops {:?} ", body.source.def_id()))
+            {
+                break;
+            }
+
             let terminator = body.basic_blocks_mut()[loc.block].terminator_mut();
             debug!("SUCCESS: replacing `drop` with goto({:?})", target);
             terminator.kind = TerminatorKind::Goto { target };
index f6d39dae3429e18b2651c73abeedb3b38e5454b6..e39c8656021b25a245d1dcd667d002a4f5a16302 100644 (file)
@@ -50,6 +50,12 @@ fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 
         let replaced = !replacements.is_empty();
         for (bb, terminator_kind) in replacements {
+            if !tcx.consider_optimizing(|| {
+                format!("UnreachablePropagation {:?} ", body.source.def_id())
+            }) {
+                break;
+            }
+
             body.basic_blocks_mut()[bb].terminator_mut().kind = terminator_kind;
         }
 
index 75399e9c32cc7b4e923395aa70e3dec80dc31a2c..29b90bff210bdcec17aec07a4fc132263a653230 100644 (file)
@@ -12,7 +12,7 @@
 use rustc_middle::mir::visit::{PlaceContext, Visitor};
 use rustc_middle::mir::{
     AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceRef,
-    Rvalue, SourceScope, Statement, StatementKind, Terminator, TerminatorKind, VarDebugInfo,
+    Rvalue, SourceScope, Statement, StatementKind, Terminator, TerminatorKind,
 };
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeFoldable};
@@ -38,9 +38,7 @@ pub struct Validator {
 impl<'tcx> MirPass<'tcx> for Validator {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let def_id = body.source.def_id();
-        // We need to param_env_reveal_all_normalized, as some optimizations
-        // change types in ways that require unfolding opaque types.
-        let param_env = tcx.param_env_reveal_all_normalized(def_id);
+        let param_env = tcx.param_env(def_id);
         let mir_phase = self.mir_phase;
 
         let always_live_locals = AlwaysLiveLocals::new(body);
@@ -81,6 +79,7 @@ pub fn equal_up_to_regions(
     }
 
     // Normalize lifetimes away on both sides, then compare.
+    let param_env = param_env.with_reveal_all_normalized(tcx);
     let normalize = |ty: Ty<'tcx>| {
         tcx.normalize_erasing_regions(
             param_env,
@@ -168,14 +167,17 @@ fn mir_assign_valid_types(&self, src: Ty<'tcx>, dest: Ty<'tcx>) -> bool {
             return true;
         }
         // Normalize projections and things like that.
-        let src = self.tcx.normalize_erasing_regions(self.param_env, src);
-        let dest = self.tcx.normalize_erasing_regions(self.param_env, dest);
+        // FIXME: We need to reveal_all, as some optimizations change types in ways
+        // that require unfolding opaque types.
+        let param_env = self.param_env.with_reveal_all_normalized(self.tcx);
+        let src = self.tcx.normalize_erasing_regions(param_env, src);
+        let dest = self.tcx.normalize_erasing_regions(param_env, dest);
 
         // Type-changing assignments can happen when subtyping is used. While
         // all normal lifetimes are erased, higher-ranked types with their
         // late-bound lifetimes are still around and can lead to type
         // differences. So we compare ignoring lifetimes.
-        equal_up_to_regions(self.tcx, self.param_env, src, dest)
+        equal_up_to_regions(self.tcx, param_env, src, dest)
     }
 }
 
@@ -198,12 +200,6 @@ fn visit_local(&mut self, local: &Local, context: PlaceContext, location: Locati
         }
     }
 
-    fn visit_var_debug_info(&mut self, var_debug_info: &VarDebugInfo<'tcx>) {
-        // Debuginfo can contain field projections, which count as a use of the base local. Skip
-        // debuginfo so that we avoid the storage liveness assertion in that case.
-        self.visit_source_info(&var_debug_info.source_info);
-    }
-
     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 {
@@ -363,7 +359,6 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
             }
             TerminatorKind::Call { func, args, destination, cleanup, .. } => {
                 let func_ty = func.ty(&self.body.local_decls, self.tcx);
-                let func_ty = self.tcx.normalize_erasing_regions(self.param_env, func_ty);
                 match func_ty.kind() {
                     ty::FnPtr(..) | ty::FnDef(..) => {}
                     _ => self.fail(
index b94346fa439119e4a2f83595c1aa62260e7eb6d3..e6263e5d6cf9bdbdf39a6378daab00f90bf6d122 100644 (file)
@@ -160,7 +160,30 @@ fn expr_as_place(
                 expr_span,
                 source_info,
             ),
-            ExprKind::SelfRef => block.and(PlaceBuilder::from(Local::new(1))),
+            ExprKind::UpvarRef { closure_def_id, var_hir_id } => {
+                let capture = this
+                    .hir
+                    .typeck_results
+                    .closure_captures
+                    .get(&closure_def_id)
+                    .and_then(|captures| captures.get_full(&var_hir_id));
+
+                if capture.is_none() {
+                    if !this.hir.tcx().features().capture_disjoint_fields {
+                        bug!(
+                            "No associated capture found for {:?} even though \
+                            capture_disjoint_fields isn't enabled",
+                            expr.kind
+                        )
+                    }
+                    // FIXME(project-rfc-2229#24): Handle this case properly
+                }
+
+                // Unwrap until the FIXME has been resolved
+                let (capture_index, _, upvar_id) = capture.unwrap();
+                this.lower_closure_capture(block, capture_index, *upvar_id)
+            }
+
             ExprKind::VarRef { id } => {
                 let place_builder = if this.is_bound_var_in_guard(id) {
                     let index = this.var_local_id(id, RefWithinGuard);
@@ -270,6 +293,61 @@ fn expr_as_place(
         }
     }
 
+    /// Lower a closure/generator capture by representing it as a field
+    /// access within the desugared closure/generator.
+    ///
+    /// `capture_index` is the index of the capture within the desugared
+    /// closure/generator.
+    fn lower_closure_capture(
+        &mut self,
+        block: BasicBlock,
+        capture_index: usize,
+        upvar_id: ty::UpvarId,
+    )  -> BlockAnd<PlaceBuilder<'tcx>> {
+        let closure_ty = self
+            .hir
+            .typeck_results()
+            .node_type(self.hir.tcx().hir().local_def_id_to_hir_id(upvar_id.closure_expr_id));
+
+        // Captures are represented using fields inside a structure.
+        // This represents accessing self in the closure structure
+        let mut place_builder = PlaceBuilder::from(Local::new(1));
+
+        // In case of Fn/FnMut closures we must deref to access the fields
+        // Generators are considered FnOnce, so we ignore this step for them.
+        if let ty::Closure(_, closure_substs) = closure_ty.kind() {
+            match self.hir.infcx().closure_kind(closure_substs).unwrap() {
+                ty::ClosureKind::Fn | ty::ClosureKind::FnMut => {
+                    place_builder = place_builder.deref();
+                }
+                ty::ClosureKind::FnOnce => {}
+            }
+        }
+
+        let substs = match closure_ty.kind() {
+            ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs),
+            ty::Generator(_, substs, _) => ty::UpvarSubsts::Generator(substs),
+            _ => bug!("Lowering capture for non-closure type {:?}", closure_ty)
+        };
+
+        // Access the capture by accessing the field within the Closure struct.
+        //
+        // We must have inferred the capture types since we are building MIR, therefore
+        // it's safe to call `upvar_tys` and we can unwrap here because
+        // we know that the capture exists and is the `capture_index`-th capture.
+        let var_ty = substs.upvar_tys().nth(capture_index).unwrap();
+        place_builder = place_builder.field(Field::new(capture_index), var_ty);
+
+        // If the variable is captured via ByRef(Immutable/Mutable) Borrow,
+        // we need to deref it
+        match self.hir.typeck_results.upvar_capture(upvar_id) {
+            ty::UpvarCapture::ByRef(_) => {
+                block.and(place_builder.deref())
+            }
+            ty::UpvarCapture::ByValue(_) => block.and(place_builder),
+        }
+    }
+
     /// Lower an index expression
     ///
     /// This has two complications;
index 2853bf887faaf4fa7b4f8f3857c5421f68abbbf6..7c34b996055d3e214f4091b9324fdf2c566b85fa 100644 (file)
@@ -96,7 +96,7 @@ fn expr_as_rvalue(
             ExprKind::Box { value } => {
                 let value = this.hir.mirror(value);
                 // The `Box<T>` temporary created here is not a part of the HIR,
-                // and therefore is not considered during generator OIBIT
+                // and therefore is not considered during generator auto-trait
                 // determination. See the comment about `box` at `yield_in_scope`.
                 let result = this.local_decls.push(LocalDecl::new(expr.ty, expr_span).internal());
                 this.cfg.push(
@@ -250,7 +250,7 @@ fn expr_as_rvalue(
             | ExprKind::Deref { .. }
             | ExprKind::Index { .. }
             | ExprKind::VarRef { .. }
-            | ExprKind::SelfRef
+            | ExprKind::UpvarRef { .. }
             | ExprKind::Break { .. }
             | ExprKind::Continue { .. }
             | ExprKind::Return { .. }
index ac5cf187aa01bced7ceaf74bc114a1f4d72798bd..8561170856fd415708d02d6621f5f4d79b654487 100644 (file)
@@ -38,7 +38,7 @@ impl Category {
             ExprKind::Field { .. }
             | ExprKind::Deref { .. }
             | ExprKind::Index { .. }
-            | ExprKind::SelfRef
+            | ExprKind::UpvarRef { .. }
             | ExprKind::VarRef { .. }
             | ExprKind::PlaceTypeAscription { .. }
             | ExprKind::ValueTypeAscription { .. } => Some(Category::Place),
index 9dc596a345fe1a556e3106739401c8b87cd9b711..50001c38dc73744fe512571a2b12f9a9785649ea 100644 (file)
@@ -400,7 +400,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
             // Avoid creating a temporary
             ExprKind::VarRef { .. }
-            | ExprKind::SelfRef
+            | ExprKind::UpvarRef { .. }
             | ExprKind::PlaceTypeAscription { .. }
             | ExprKind::ValueTypeAscription { .. } => {
                 debug_assert!(Category::of(&expr.kind) == Some(Category::Place));
index 47c0400533bd828f1e46e8b2140a29843d6c8c7b..e404afeb698a6809cf9209eb9a7ad51b7b7eb78c 100644 (file)
@@ -880,130 +880,26 @@ fn convert_path_expr<'a, 'tcx>(
             ExprKind::Deref { arg: Expr { ty, temp_lifetime, span: expr.span, kind }.to_ref() }
         }
 
-        Res::Local(var_hir_id) => convert_var(cx, expr, var_hir_id),
+        Res::Local(var_hir_id) => convert_var(cx, var_hir_id),
 
         _ => span_bug!(expr.span, "res `{:?}` not yet implemented", res),
     }
 }
 
-fn convert_var<'tcx>(
-    cx: &mut Cx<'_, 'tcx>,
-    expr: &'tcx hir::Expr<'tcx>,
-    var_hir_id: hir::HirId,
-) -> ExprKind<'tcx> {
-    let upvar_index = cx
-        .typeck_results()
-        .closure_captures
-        .get(&cx.body_owner)
-        .and_then(|upvars| upvars.get_full(&var_hir_id).map(|(i, _, _)| i));
-
-    debug!(
-        "convert_var({:?}): upvar_index={:?}, body_owner={:?}",
-        var_hir_id, upvar_index, cx.body_owner
-    );
-
-    let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
-
-    match upvar_index {
-        None => ExprKind::VarRef { id: var_hir_id },
+fn convert_var<'tcx>(cx: &mut Cx<'_, 'tcx>, var_hir_id: hir::HirId) -> ExprKind<'tcx> {
+    // We want upvars here not captures.
+    // Captures will be handled in MIR.
+    let is_upvar = cx
+        .tcx
+        .upvars_mentioned(cx.body_owner)
+        .map_or(false, |upvars| upvars.contains_key(&var_hir_id));
 
-        Some(upvar_index) => {
-            let closure_def_id = cx.body_owner;
-            let upvar_id = ty::UpvarId {
-                var_path: ty::UpvarPath { hir_id: var_hir_id },
-                closure_expr_id: closure_def_id.expect_local(),
-            };
-            let var_ty = cx.typeck_results().node_type(var_hir_id);
+    debug!("convert_var({:?}): is_upvar={}, body_owner={:?}", var_hir_id, is_upvar, cx.body_owner);
 
-            // FIXME free regions in closures are not right
-            let closure_ty = cx
-                .typeck_results()
-                .node_type(cx.tcx.hir().local_def_id_to_hir_id(upvar_id.closure_expr_id));
-
-            // FIXME we're just hard-coding the idea that the
-            // signature will be &self or &mut self and hence will
-            // have a bound region with number 0
-            let region = ty::ReFree(ty::FreeRegion {
-                scope: closure_def_id,
-                bound_region: ty::BoundRegion::BrAnon(0),
-            });
-            let region = cx.tcx.mk_region(region);
-
-            let self_expr = if let ty::Closure(_, closure_substs) = closure_ty.kind() {
-                match cx.infcx.closure_kind(closure_substs).unwrap() {
-                    ty::ClosureKind::Fn => {
-                        let ref_closure_ty = cx.tcx.mk_ref(
-                            region,
-                            ty::TypeAndMut { ty: closure_ty, mutbl: hir::Mutability::Not },
-                        );
-                        Expr {
-                            ty: closure_ty,
-                            temp_lifetime,
-                            span: expr.span,
-                            kind: ExprKind::Deref {
-                                arg: Expr {
-                                    ty: ref_closure_ty,
-                                    temp_lifetime,
-                                    span: expr.span,
-                                    kind: ExprKind::SelfRef,
-                                }
-                                .to_ref(),
-                            },
-                        }
-                    }
-                    ty::ClosureKind::FnMut => {
-                        let ref_closure_ty = cx.tcx.mk_ref(
-                            region,
-                            ty::TypeAndMut { ty: closure_ty, mutbl: hir::Mutability::Mut },
-                        );
-                        Expr {
-                            ty: closure_ty,
-                            temp_lifetime,
-                            span: expr.span,
-                            kind: ExprKind::Deref {
-                                arg: Expr {
-                                    ty: ref_closure_ty,
-                                    temp_lifetime,
-                                    span: expr.span,
-                                    kind: ExprKind::SelfRef,
-                                }
-                                .to_ref(),
-                            },
-                        }
-                    }
-                    ty::ClosureKind::FnOnce => Expr {
-                        ty: closure_ty,
-                        temp_lifetime,
-                        span: expr.span,
-                        kind: ExprKind::SelfRef,
-                    },
-                }
-            } else {
-                Expr { ty: closure_ty, temp_lifetime, span: expr.span, kind: ExprKind::SelfRef }
-            };
-
-            // at this point we have `self.n`, which loads up the upvar
-            let field_kind =
-                ExprKind::Field { lhs: self_expr.to_ref(), name: Field::new(upvar_index) };
-
-            // ...but the upvar might be an `&T` or `&mut T` capture, at which
-            // point we need an implicit deref
-            match cx.typeck_results().upvar_capture(upvar_id) {
-                ty::UpvarCapture::ByValue(_) => field_kind,
-                ty::UpvarCapture::ByRef(borrow) => ExprKind::Deref {
-                    arg: Expr {
-                        temp_lifetime,
-                        ty: cx.tcx.mk_ref(
-                            borrow.region,
-                            ty::TypeAndMut { ty: var_ty, mutbl: borrow.kind.to_mutbl_lossy() },
-                        ),
-                        span: expr.span,
-                        kind: field_kind,
-                    }
-                    .to_ref(),
-                },
-            }
-        }
+    if is_upvar {
+        ExprKind::UpvarRef { closure_def_id: cx.body_owner, var_hir_id }
+    } else {
+        ExprKind::VarRef { id: var_hir_id }
     }
 }
 
@@ -1102,7 +998,7 @@ fn capture_upvar<'tcx>(
         temp_lifetime,
         ty: var_ty,
         span: closure_expr.span,
-        kind: convert_var(cx, closure_expr, var_hir_id),
+        kind: convert_var(cx, var_hir_id),
     };
     match upvar_capture {
         ty::UpvarCapture::ByValue(_) => captured_var.to_ref(),
index cf42fee873e158f19cd3dfdc37f4d06de31eab23..465808cea9dd50cc9c1e03d9e99f2dcfb71e85bd 100644 (file)
@@ -186,6 +186,10 @@ impl<'a, 'tcx> Cx<'a, 'tcx> {
         ty.needs_drop(self.tcx, self.param_env)
     }
 
+    crate fn infcx(&self) -> &'a InferCtxt<'a, 'tcx> {
+        self.infcx
+    }
+
     crate fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
index f2a2ef0d8f2bcf5ae8d44ea4eabc05f13c53fdf8..1a901746d5086e971def252630d15dacd845a8d5 100644 (file)
     VarRef {
         id: hir::HirId,
     },
-    /// first argument, used for self in a closure
-    SelfRef,
+    /// Used to represent upvars mentioned in a closure/generator
+    UpvarRef {
+        /// DefId of the closure/generator
+        closure_def_id: DefId,
+
+        /// HirId of the root variable
+        var_hir_id: hir::HirId,
+    },
     Borrow {
         borrow_kind: BorrowKind,
         arg: ExprRef<'tcx>,
diff --git a/compiler/rustc_mir_build/src/thir/pattern/_match.rs b/compiler/rustc_mir_build/src/thir/pattern/_match.rs
deleted file mode 100644 (file)
index 6bea238..0000000
+++ /dev/null
@@ -1,2352 +0,0 @@
-//! Note: tests specific to this file can be found in:
-//!     - ui/pattern/usefulness
-//!     - ui/or-patterns
-//!     - ui/consts/const_in_pattern
-//!     - ui/rfc-2008-non-exhaustive
-//!     - probably many others
-//! I (Nadrieril) prefer to put new tests in `ui/pattern/usefulness` unless there's a specific
-//! reason not to, for example if they depend on a particular feature like or_patterns.
-//!
-//! This file includes the logic for exhaustiveness and usefulness checking for
-//! pattern-matching. Specifically, given a list of patterns for a type, we can
-//! tell whether:
-//! (a) the patterns cover every possible constructor for the type (exhaustiveness)
-//! (b) each pattern is necessary (usefulness)
-//!
-//! The algorithm implemented here is a modified version of the one described in:
-//! <http://moscova.inria.fr/~maranget/papers/warn/index.html>
-//! However, to save future implementors from reading the original paper, we
-//! summarise the algorithm here to hopefully save time and be a little clearer
-//! (without being so rigorous).
-//!
-//! # Premise
-//!
-//! The core of the algorithm revolves about a "usefulness" check. In particular, we
-//! are trying to compute a predicate `U(P, p)` where `P` is a list of patterns (we refer to this as
-//! a matrix). `U(P, p)` represents whether, given an existing list of patterns
-//! `P_1 ..= P_m`, adding a new pattern `p` will be "useful" (that is, cover previously-
-//! uncovered values of the type).
-//!
-//! If we have this predicate, then we can easily compute both exhaustiveness of an
-//! entire set of patterns and the individual usefulness of each one.
-//! (a) the set of patterns is exhaustive iff `U(P, _)` is false (i.e., adding a wildcard
-//! match doesn't increase the number of values we're matching)
-//! (b) a pattern `P_i` is not useful if `U(P[0..=(i-1), P_i)` is false (i.e., adding a
-//! pattern to those that have come before it doesn't increase the number of values
-//! we're matching).
-//!
-//! # Core concept
-//!
-//! The idea that powers everything that is done in this file is the following: a value is made
-//! from a constructor applied to some fields. Examples of constructors are `Some`, `None`, `(,)`
-//! (the 2-tuple constructor), `Foo {..}` (the constructor for a struct `Foo`), and `2` (the
-//! constructor for the number `2`). Fields are just a (possibly empty) list of values.
-//!
-//! Some of the constructors listed above might feel weird: `None` and `2` don't take any
-//! arguments. This is part of what makes constructors so general: we will consider plain values
-//! like numbers and string literals to be constructors that take no arguments, also called "0-ary
-//! constructors"; they are the simplest case of constructors. This allows us to see any value as
-//! made up from a tree of constructors, each having a given number of children. For example:
-//! `(None, Ok(0))` is made from 4 different constructors.
-//!
-//! This idea can be extended to patterns: a pattern captures a set of possible values, and we can
-//! describe this set using constructors. For example, `Err(_)` captures all values of the type
-//! `Result<T, E>` that start with the `Err` constructor (for some choice of `T` and `E`). The
-//! wildcard `_` captures all values of the given type starting with any of the constructors for
-//! that type.
-//!
-//! We use this to compute whether different patterns might capture a same value. Do the patterns
-//! `Ok("foo")` and `Err(_)` capture a common value? The answer is no, because the first pattern
-//! captures only values starting with the `Ok` constructor and the second only values starting
-//! with the `Err` constructor. Do the patterns `Some(42)` and `Some(1..10)` intersect? They might,
-//! since they both capture values starting with `Some`. To be certain, we need to dig under the
-//! `Some` constructor and continue asking the question. This is the main idea behind the
-//! exhaustiveness algorithm: by looking at patterns constructor-by-constructor, we can efficiently
-//! figure out if some new pattern might capture a value that hadn't been captured by previous
-//! patterns.
-//!
-//! Constructors are represented by the `Constructor` enum, and its fields by the `Fields` enum.
-//! Most of the complexity of this file resides in transforming between patterns and
-//! (`Constructor`, `Fields`) pairs, handling all the special cases correctly.
-//!
-//! Caveat: this constructors/fields distinction doesn't quite cover every Rust value. For example
-//! a value of type `Rc<u64>` doesn't fit this idea very well, nor do various other things.
-//! However, this idea covers most of the cases that are relevant to exhaustiveness checking.
-//!
-//!
-//! # Algorithm
-//!
-//! Recall that `U(P, p)` represents whether, given an existing list of patterns (aka matrix) `P`,
-//! adding a new pattern `p` will cover previously-uncovered values of the type.
-//! During the course of the algorithm, the rows of the matrix won't just be individual patterns,
-//! but rather partially-deconstructed patterns in the form of a list of fields. The paper
-//! calls those pattern-vectors, and we will call them pattern-stacks. The same holds for the
-//! new pattern `p`.
-//!
-//! For example, say we have the following:
-//!
-//! ```
-//! // x: (Option<bool>, Result<()>)
-//! match x {
-//!     (Some(true), _) => {}
-//!     (None, Err(())) => {}
-//!     (None, Err(_)) => {}
-//! }
-//! ```
-//!
-//! Here, the matrix `P` starts as:
-//!
-//! ```
-//! [
-//!     [(Some(true), _)],
-//!     [(None, Err(()))],
-//!     [(None, Err(_))],
-//! ]
-//! ```
-//!
-//! We can tell it's not exhaustive, because `U(P, _)` is true (we're not covering
-//! `[(Some(false), _)]`, for instance). In addition, row 3 is not useful, because
-//! all the values it covers are already covered by row 2.
-//!
-//! A list of patterns can be thought of as a stack, because we are mainly interested in the top of
-//! the stack at any given point, and we can pop or apply constructors to get new pattern-stacks.
-//! To match the paper, the top of the stack is at the beginning / on the left.
-//!
-//! There are two important operations on pattern-stacks necessary to understand the algorithm:
-//!
-//! 1. We can pop a given constructor off the top of a stack. This operation is called
-//!    `specialize`, and is denoted `S(c, p)` where `c` is a constructor (like `Some` or
-//!    `None`) and `p` a pattern-stack.
-//!    If the pattern on top of the stack can cover `c`, this removes the constructor and
-//!    pushes its arguments onto the stack. It also expands OR-patterns into distinct patterns.
-//!    Otherwise the pattern-stack is discarded.
-//!    This essentially filters those pattern-stacks whose top covers the constructor `c` and
-//!    discards the others.
-//!
-//!    For example, the first pattern above initially gives a stack `[(Some(true), _)]`. If we
-//!    pop the tuple constructor, we are left with `[Some(true), _]`, and if we then pop the
-//!    `Some` constructor we get `[true, _]`. If we had popped `None` instead, we would get
-//!    nothing back.
-//!
-//!    This returns zero or more new pattern-stacks, as follows. We look at the pattern `p_1`
-//!    on top of the stack, and we have four cases:
-//!         1.1. `p_1 = c(r_1, .., r_a)`, i.e. the top of the stack has constructor `c`. We
-//!              push onto the stack the arguments of this constructor, and return the result:
-//!                 r_1, .., r_a, p_2, .., p_n
-//!         1.2. `p_1 = c'(r_1, .., r_a')` where `c ≠ c'`. We discard the current stack and
-//!              return nothing.
-//!         1.3. `p_1 = _`. We push onto the stack as many wildcards as the constructor `c` has
-//!              arguments (its arity), and return the resulting stack:
-//!                 _, .., _, p_2, .., p_n
-//!         1.4. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting
-//!              stack:
-//!                 S(c, (r_1, p_2, .., p_n))
-//!                 S(c, (r_2, p_2, .., p_n))
-//!
-//! 2. We can pop a wildcard off the top of the stack. This is called `S(_, p)`, where `p` is
-//!    a pattern-stack. Note: the paper calls this `D(p)`.
-//!    This is used when we know there are missing constructor cases, but there might be
-//!    existing wildcard patterns, so to check the usefulness of the matrix, we have to check
-//!    all its *other* components.
-//!
-//!    It is computed as follows. We look at the pattern `p_1` on top of the stack,
-//!    and we have three cases:
-//!         2.1. `p_1 = c(r_1, .., r_a)`. We discard the current stack and return nothing.
-//!         2.2. `p_1 = _`. We return the rest of the stack:
-//!                 p_2, .., p_n
-//!         2.3. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting
-//!           stack.
-//!                 S(_, (r_1, p_2, .., p_n))
-//!                 S(_, (r_2, p_2, .., p_n))
-//!
-//! Note that the OR-patterns are not always used directly in Rust, but are used to derive the
-//! exhaustive integer matching rules, so they're written here for posterity.
-//!
-//! Both those operations extend straightforwardly to a list or pattern-stacks, i.e. a matrix, by
-//! working row-by-row. Popping a constructor ends up keeping only the matrix rows that start with
-//! the given constructor, and popping a wildcard keeps those rows that start with a wildcard.
-//!
-//!
-//! The algorithm for computing `U`
-//! -------------------------------
-//! The algorithm is inductive (on the number of columns: i.e., components of tuple patterns).
-//! That means we're going to check the components from left-to-right, so the algorithm
-//! operates principally on the first component of the matrix and new pattern-stack `p`.
-//! This algorithm is realised in the `is_useful` function.
-//!
-//! Base case. (`n = 0`, i.e., an empty tuple pattern)
-//!     - If `P` already contains an empty pattern (i.e., if the number of patterns `m > 0`),
-//!       then `U(P, p)` is false.
-//!     - Otherwise, `P` must be empty, so `U(P, p)` is true.
-//!
-//! Inductive step. (`n > 0`, i.e., whether there's at least one column
-//!                  [which may then be expanded into further columns later])
-//! We're going to match on the top of the new pattern-stack, `p_1`.
-//!     - If `p_1 == c(r_1, .., r_a)`, i.e. we have a constructor pattern.
-//! Then, the usefulness of `p_1` can be reduced to whether it is useful when
-//! we ignore all the patterns in the first column of `P` that involve other constructors.
-//! This is where `S(c, P)` comes in:
-//! `U(P, p) := U(S(c, P), S(c, p))`
-//!
-//! For example, if `P` is:
-//!
-//! ```
-//! [
-//!     [Some(true), _],
-//!     [None, 0],
-//! ]
-//! ```
-//!
-//! and `p` is [Some(false), 0], then we don't care about row 2 since we know `p` only
-//! matches values that row 2 doesn't. For row 1 however, we need to dig into the
-//! arguments of `Some` to know whether some new value is covered. So we compute
-//! `U([[true, _]], [false, 0])`.
-//!
-//!   - If `p_1 == _`, then we look at the list of constructors that appear in the first
-//! component of the rows of `P`:
-//!   + If there are some constructors that aren't present, then we might think that the
-//! wildcard `_` is useful, since it covers those constructors that weren't covered
-//! before.
-//! That's almost correct, but only works if there were no wildcards in those first
-//! components. So we need to check that `p` is useful with respect to the rows that
-//! start with a wildcard, if there are any. This is where `S(_, x)` comes in:
-//! `U(P, p) := U(S(_, P), S(_, p))`
-//!
-//! For example, if `P` is:
-//!
-//! ```
-//! [
-//!     [_, true, _],
-//!     [None, false, 1],
-//! ]
-//! ```
-//!
-//! and `p` is [_, false, _], the `Some` constructor doesn't appear in `P`. So if we
-//! only had row 2, we'd know that `p` is useful. However row 1 starts with a
-//! wildcard, so we need to check whether `U([[true, _]], [false, 1])`.
-//!
-//!   + Otherwise, all possible constructors (for the relevant type) are present. In this
-//! case we must check whether the wildcard pattern covers any unmatched value. For
-//! that, we can think of the `_` pattern as a big OR-pattern that covers all
-//! possible constructors. For `Option`, that would mean `_ = None | Some(_)` for
-//! example. The wildcard pattern is useful in this case if it is useful when
-//! specialized to one of the possible constructors. So we compute:
-//! `U(P, p) := ∃(k ϵ constructors) U(S(k, P), S(k, p))`
-//!
-//! For example, if `P` is:
-//!
-//! ```
-//! [
-//!     [Some(true), _],
-//!     [None, false],
-//! ]
-//! ```
-//!
-//! and `p` is [_, false], both `None` and `Some` constructors appear in the first
-//! components of `P`. We will therefore try popping both constructors in turn: we
-//! compute `U([[true, _]], [_, false])` for the `Some` constructor, and `U([[false]],
-//! [false])` for the `None` constructor. The first case returns true, so we know that
-//! `p` is useful for `P`. Indeed, it matches `[Some(false), _]` that wasn't matched
-//! before.
-//!
-//!   - If `p_1 == r_1 | r_2`, then the usefulness depends on each `r_i` separately:
-//! `U(P, p) := U(P, (r_1, p_2, .., p_n))
-//!  || U(P, (r_2, p_2, .., p_n))`
-//!
-//! Modifications to the algorithm
-//! ------------------------------
-//! The algorithm in the paper doesn't cover some of the special cases that arise in Rust, for
-//! example uninhabited types and variable-length slice patterns. These are drawn attention to
-//! throughout the code below. I'll make a quick note here about how exhaustive integer matching is
-//! accounted for, though.
-//!
-//! Exhaustive integer matching
-//! ---------------------------
-//! An integer type can be thought of as a (huge) sum type: 1 | 2 | 3 | ...
-//! So to support exhaustive integer matching, we can make use of the logic in the paper for
-//! OR-patterns. However, we obviously can't just treat ranges x..=y as individual sums, because
-//! they are likely gigantic. So we instead treat ranges as constructors of the integers. This means
-//! that we have a constructor *of* constructors (the integers themselves). We then need to work
-//! through all the inductive step rules above, deriving how the ranges would be treated as
-//! OR-patterns, and making sure that they're treated in the same way even when they're ranges.
-//! There are really only four special cases here:
-//! - When we match on a constructor that's actually a range, we have to treat it as if we would
-//!   an OR-pattern.
-//!     + It turns out that we can simply extend the case for single-value patterns in
-//!      `specialize` to either be *equal* to a value constructor, or *contained within* a range
-//!      constructor.
-//!     + When the pattern itself is a range, you just want to tell whether any of the values in
-//!       the pattern range coincide with values in the constructor range, which is precisely
-//!       intersection.
-//!   Since when encountering a range pattern for a value constructor, we also use inclusion, it
-//!   means that whenever the constructor is a value/range and the pattern is also a value/range,
-//!   we can simply use intersection to test usefulness.
-//! - When we're testing for usefulness of a pattern and the pattern's first component is a
-//!   wildcard.
-//!     + If all the constructors appear in the matrix, we have a slight complication. By default,
-//!       the behaviour (i.e., a disjunction over specialised matrices for each constructor) is
-//!       invalid, because we want a disjunction over every *integer* in each range, not just a
-//!       disjunction over every range. This is a bit more tricky to deal with: essentially we need
-//!       to form equivalence classes of subranges of the constructor range for which the behaviour
-//!       of the matrix `P` and new pattern `p` are the same. This is described in more
-//!       detail in `Constructor::split`.
-//!     + If some constructors are missing from the matrix, it turns out we don't need to do
-//!       anything special (because we know none of the integers are actually wildcards: i.e., we
-//!       can't span wildcards using ranges).
-use self::Constructor::*;
-use self::SliceKind::*;
-use self::Usefulness::*;
-use self::WitnessPreference::*;
-
-use rustc_data_structures::captures::Captures;
-use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::sync::OnceCell;
-use rustc_index::vec::Idx;
-
-use super::{compare_const_vals, PatternFoldable, PatternFolder};
-use super::{FieldPat, Pat, PatKind, PatRange};
-
-use rustc_arena::TypedArena;
-use rustc_attr::{SignedInt, UnsignedInt};
-use rustc_hir::def_id::DefId;
-use rustc_hir::{HirId, RangeEnd};
-use rustc_middle::mir::interpret::ConstValue;
-use rustc_middle::mir::Field;
-use rustc_middle::ty::layout::IntegerExt;
-use rustc_middle::ty::{self, Const, Ty, TyCtxt};
-use rustc_session::lint;
-use rustc_span::{Span, DUMMY_SP};
-use rustc_target::abi::{Integer, Size, VariantIdx};
-
-use smallvec::{smallvec, SmallVec};
-use std::cmp::{self, max, min, Ordering};
-use std::fmt;
-use std::iter::{FromIterator, IntoIterator};
-use std::ops::RangeInclusive;
-
-crate fn expand_pattern<'tcx>(pat: Pat<'tcx>) -> Pat<'tcx> {
-    LiteralExpander.fold_pattern(&pat)
-}
-
-struct LiteralExpander;
-
-impl<'tcx> PatternFolder<'tcx> for LiteralExpander {
-    fn fold_pattern(&mut self, pat: &Pat<'tcx>) -> Pat<'tcx> {
-        debug!("fold_pattern {:?} {:?} {:?}", pat, pat.ty.kind(), pat.kind);
-        match (pat.ty.kind(), pat.kind.as_ref()) {
-            (_, PatKind::Binding { subpattern: Some(s), .. }) => s.fold_with(self),
-            (_, PatKind::AscribeUserType { subpattern: s, .. }) => s.fold_with(self),
-            (ty::Ref(_, t, _), PatKind::Constant { .. }) if t.is_str() => {
-                // Treat string literal patterns as deref patterns to a `str` constant, i.e.
-                // `&CONST`. This expands them like other const patterns. This could have been done
-                // in `const_to_pat`, but that causes issues with the rest of the matching code.
-                let mut new_pat = pat.super_fold_with(self);
-                // Make a fake const pattern of type `str` (instead of `&str`). That the carried
-                // constant value still knows it is of type `&str`.
-                new_pat.ty = t;
-                Pat {
-                    kind: Box::new(PatKind::Deref { subpattern: new_pat }),
-                    span: pat.span,
-                    ty: pat.ty,
-                }
-            }
-            _ => pat.super_fold_with(self),
-        }
-    }
-}
-
-impl<'tcx> Pat<'tcx> {
-    pub(super) fn is_wildcard(&self) -> bool {
-        matches!(*self.kind, PatKind::Binding { subpattern: None, .. } | PatKind::Wild)
-    }
-}
-
-/// A row of a matrix. Rows of len 1 are very common, which is why `SmallVec[_; 2]`
-/// works well.
-#[derive(Debug, Clone)]
-struct PatStack<'p, 'tcx> {
-    pats: SmallVec<[&'p Pat<'tcx>; 2]>,
-    /// Cache for the constructor of the head
-    head_ctor: OnceCell<Constructor<'tcx>>,
-}
-
-impl<'p, 'tcx> PatStack<'p, 'tcx> {
-    fn from_pattern(pat: &'p Pat<'tcx>) -> Self {
-        Self::from_vec(smallvec![pat])
-    }
-
-    fn from_vec(vec: SmallVec<[&'p Pat<'tcx>; 2]>) -> Self {
-        PatStack { pats: vec, head_ctor: OnceCell::new() }
-    }
-
-    fn is_empty(&self) -> bool {
-        self.pats.is_empty()
-    }
-
-    fn len(&self) -> usize {
-        self.pats.len()
-    }
-
-    fn head(&self) -> &'p Pat<'tcx> {
-        self.pats[0]
-    }
-
-    fn head_ctor<'a>(&'a self, cx: &MatchCheckCtxt<'p, 'tcx>) -> &'a Constructor<'tcx> {
-        self.head_ctor.get_or_init(|| pat_constructor(cx, self.head()))
-    }
-
-    fn iter(&self) -> impl Iterator<Item = &Pat<'tcx>> {
-        self.pats.iter().copied()
-    }
-
-    // If the first pattern is an or-pattern, expand this pattern. Otherwise, return `None`.
-    fn expand_or_pat(&self) -> Option<Vec<Self>> {
-        if self.is_empty() {
-            None
-        } else if let PatKind::Or { pats } = &*self.head().kind {
-            Some(
-                pats.iter()
-                    .map(|pat| {
-                        let mut new_patstack = PatStack::from_pattern(pat);
-                        new_patstack.pats.extend_from_slice(&self.pats[1..]);
-                        new_patstack
-                    })
-                    .collect(),
-            )
-        } else {
-            None
-        }
-    }
-
-    /// This computes `S(self.head_ctor(), self)`. See top of the file for explanations.
-    ///
-    /// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
-    /// fields filled with wild patterns.
-    ///
-    /// This is roughly the inverse of `Constructor::apply`.
-    fn pop_head_constructor(&self, ctor_wild_subpatterns: &Fields<'p, 'tcx>) -> PatStack<'p, 'tcx> {
-        // We pop the head pattern and push the new fields extracted from the arguments of
-        // `self.head()`.
-        let new_fields = ctor_wild_subpatterns.replace_with_pattern_arguments(self.head());
-        new_fields.push_on_patstack(&self.pats[1..])
-    }
-}
-
-impl<'p, 'tcx> Default for PatStack<'p, 'tcx> {
-    fn default() -> Self {
-        Self::from_vec(smallvec![])
-    }
-}
-
-impl<'p, 'tcx> PartialEq for PatStack<'p, 'tcx> {
-    fn eq(&self, other: &Self) -> bool {
-        self.pats == other.pats
-    }
-}
-
-impl<'p, 'tcx> FromIterator<&'p Pat<'tcx>> for PatStack<'p, 'tcx> {
-    fn from_iter<T>(iter: T) -> Self
-    where
-        T: IntoIterator<Item = &'p Pat<'tcx>>,
-    {
-        Self::from_vec(iter.into_iter().collect())
-    }
-}
-
-/// A 2D matrix.
-#[derive(Clone, PartialEq)]
-struct Matrix<'p, 'tcx> {
-    patterns: Vec<PatStack<'p, 'tcx>>,
-}
-
-impl<'p, 'tcx> Matrix<'p, 'tcx> {
-    fn empty() -> Self {
-        Matrix { patterns: vec![] }
-    }
-
-    /// Pushes a new row to the matrix. If the row starts with an or-pattern, this expands it.
-    fn push(&mut self, row: PatStack<'p, 'tcx>) {
-        if let Some(rows) = row.expand_or_pat() {
-            for row in rows {
-                // We recursively expand the or-patterns of the new rows.
-                // This is necessary as we might have `0 | (1 | 2)` or e.g., `x @ 0 | x @ (1 | 2)`.
-                self.push(row)
-            }
-        } else {
-            self.patterns.push(row);
-        }
-    }
-
-    /// Iterate over the first component of each row
-    fn heads<'a>(&'a self) -> impl Iterator<Item = &'a Pat<'tcx>> + Captures<'p> {
-        self.patterns.iter().map(|r| r.head())
-    }
-
-    /// Iterate over the first constructor of each row
-    fn head_ctors<'a>(
-        &'a self,
-        cx: &'a MatchCheckCtxt<'p, 'tcx>,
-    ) -> impl Iterator<Item = &'a Constructor<'tcx>> + Captures<'a> + Captures<'p> {
-        self.patterns.iter().map(move |r| r.head_ctor(cx))
-    }
-
-    /// This computes `S(constructor, self)`. See top of the file for explanations.
-    fn specialize_constructor(
-        &self,
-        pcx: PatCtxt<'_, 'p, 'tcx>,
-        ctor: &Constructor<'tcx>,
-        ctor_wild_subpatterns: &Fields<'p, 'tcx>,
-    ) -> Matrix<'p, 'tcx> {
-        self.patterns
-            .iter()
-            .filter(|r| ctor.is_covered_by(pcx, r.head_ctor(pcx.cx)))
-            .map(|r| r.pop_head_constructor(ctor_wild_subpatterns))
-            .collect()
-    }
-}
-
-/// Pretty-printer for matrices of patterns, example:
-///
-/// ```text
-/// +++++++++++++++++++++++++++++
-/// + _     + []                +
-/// +++++++++++++++++++++++++++++
-/// + true  + [First]           +
-/// +++++++++++++++++++++++++++++
-/// + true  + [Second(true)]    +
-/// +++++++++++++++++++++++++++++
-/// + false + [_]               +
-/// +++++++++++++++++++++++++++++
-/// + _     + [_, _, tail @ ..] +
-/// +++++++++++++++++++++++++++++
-/// ```
-impl<'p, 'tcx> fmt::Debug for Matrix<'p, 'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "\n")?;
-
-        let Matrix { patterns: m, .. } = self;
-        let pretty_printed_matrix: Vec<Vec<String>> =
-            m.iter().map(|row| row.iter().map(|pat| format!("{:?}", pat)).collect()).collect();
-
-        let column_count = m.iter().map(|row| row.len()).max().unwrap_or(0);
-        assert!(m.iter().all(|row| row.len() == column_count));
-        let column_widths: Vec<usize> = (0..column_count)
-            .map(|col| pretty_printed_matrix.iter().map(|row| row[col].len()).max().unwrap_or(0))
-            .collect();
-
-        let total_width = column_widths.iter().cloned().sum::<usize>() + column_count * 3 + 1;
-        let br = "+".repeat(total_width);
-        write!(f, "{}\n", br)?;
-        for row in pretty_printed_matrix {
-            write!(f, "+")?;
-            for (column, pat_str) in row.into_iter().enumerate() {
-                write!(f, " ")?;
-                write!(f, "{:1$}", pat_str, column_widths[column])?;
-                write!(f, " +")?;
-            }
-            write!(f, "\n")?;
-            write!(f, "{}\n", br)?;
-        }
-        Ok(())
-    }
-}
-
-impl<'p, 'tcx> FromIterator<PatStack<'p, 'tcx>> for Matrix<'p, 'tcx> {
-    fn from_iter<T>(iter: T) -> Self
-    where
-        T: IntoIterator<Item = PatStack<'p, 'tcx>>,
-    {
-        let mut matrix = Matrix::empty();
-        for x in iter {
-            // Using `push` ensures we correctly expand or-patterns.
-            matrix.push(x);
-        }
-        matrix
-    }
-}
-
-crate struct MatchCheckCtxt<'a, 'tcx> {
-    crate tcx: TyCtxt<'tcx>,
-    /// The module in which the match occurs. This is necessary for
-    /// checking inhabited-ness of types because whether a type is (visibly)
-    /// inhabited can depend on whether it was defined in the current module or
-    /// not. E.g., `struct Foo { _private: ! }` cannot be seen to be empty
-    /// outside it's module and should not be matchable with an empty match
-    /// statement.
-    crate module: DefId,
-    crate param_env: ty::ParamEnv<'tcx>,
-    crate pattern_arena: &'a TypedArena<Pat<'tcx>>,
-}
-
-impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
-    fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
-        if self.tcx.features().exhaustive_patterns {
-            self.tcx.is_ty_uninhabited_from(self.module, ty, self.param_env)
-        } else {
-            false
-        }
-    }
-
-    /// Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`.
-    fn is_foreign_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
-        match ty.kind() {
-            ty::Adt(def, ..) => {
-                def.is_enum() && def.is_variant_list_non_exhaustive() && !def.did.is_local()
-            }
-            _ => false,
-        }
-    }
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-enum SliceKind {
-    /// Patterns of length `n` (`[x, y]`).
-    FixedLen(u64),
-    /// Patterns using the `..` notation (`[x, .., y]`).
-    /// Captures any array constructor of `length >= i + j`.
-    /// In the case where `array_len` is `Some(_)`,
-    /// this indicates that we only care about the first `i` and the last `j` values of the array,
-    /// and everything in between is a wildcard `_`.
-    VarLen(u64, u64),
-}
-
-impl SliceKind {
-    fn arity(self) -> u64 {
-        match self {
-            FixedLen(length) => length,
-            VarLen(prefix, suffix) => prefix + suffix,
-        }
-    }
-
-    /// Whether this pattern includes patterns of length `other_len`.
-    fn covers_length(self, other_len: u64) -> bool {
-        match self {
-            FixedLen(len) => len == other_len,
-            VarLen(prefix, suffix) => prefix + suffix <= other_len,
-        }
-    }
-}
-
-/// A constructor for array and slice patterns.
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-struct Slice {
-    /// `None` if the matched value is a slice, `Some(n)` if it is an array of size `n`.
-    array_len: Option<u64>,
-    /// The kind of pattern it is: fixed-length `[x, y]` or variable length `[x, .., y]`.
-    kind: SliceKind,
-}
-
-impl Slice {
-    fn new(array_len: Option<u64>, kind: SliceKind) -> Self {
-        let kind = match (array_len, kind) {
-            // If the middle `..` is empty, we effectively have a fixed-length pattern.
-            (Some(len), VarLen(prefix, suffix)) if prefix + suffix >= len => FixedLen(len),
-            _ => kind,
-        };
-        Slice { array_len, kind }
-    }
-
-    fn arity(self) -> u64 {
-        self.kind.arity()
-    }
-
-    /// The exhaustiveness-checking paper does not include any details on
-    /// checking variable-length slice patterns. However, they may be
-    /// matched by an infinite collection of fixed-length array patterns.
-    ///
-    /// Checking the infinite set directly would take an infinite amount
-    /// of time. However, it turns out that for each finite set of
-    /// patterns `P`, all sufficiently large array lengths are equivalent:
-    ///
-    /// Each slice `s` with a "sufficiently-large" length `l ≥ L` that applies
-    /// to exactly the subset `Pₜ` of `P` can be transformed to a slice
-    /// `sₘ` for each sufficiently-large length `m` that applies to exactly
-    /// the same subset of `P`.
-    ///
-    /// Because of that, each witness for reachability-checking of one
-    /// of the sufficiently-large lengths can be transformed to an
-    /// equally-valid witness of any other length, so we only have
-    /// to check slices of the "minimal sufficiently-large length"
-    /// and less.
-    ///
-    /// Note that the fact that there is a *single* `sₘ` for each `m`
-    /// not depending on the specific pattern in `P` is important: if
-    /// you look at the pair of patterns
-    ///     `[true, ..]`
-    ///     `[.., false]`
-    /// Then any slice of length ≥1 that matches one of these two
-    /// patterns can be trivially turned to a slice of any
-    /// other length ≥1 that matches them and vice-versa,
-    /// but the slice of length 2 `[false, true]` that matches neither
-    /// of these patterns can't be turned to a slice from length 1 that
-    /// matches neither of these patterns, so we have to consider
-    /// slices from length 2 there.
-    ///
-    /// Now, to see that that length exists and find it, observe that slice
-    /// patterns are either "fixed-length" patterns (`[_, _, _]`) or
-    /// "variable-length" patterns (`[_, .., _]`).
-    ///
-    /// For fixed-length patterns, all slices with lengths *longer* than
-    /// the pattern's length have the same outcome (of not matching), so
-    /// as long as `L` is greater than the pattern's length we can pick
-    /// any `sₘ` from that length and get the same result.
-    ///
-    /// For variable-length patterns, the situation is more complicated,
-    /// because as seen above the precise value of `sₘ` matters.
-    ///
-    /// However, for each variable-length pattern `p` with a prefix of length
-    /// `plₚ` and suffix of length `slₚ`, only the first `plₚ` and the last
-    /// `slₚ` elements are examined.
-    ///
-    /// Therefore, as long as `L` is positive (to avoid concerns about empty
-    /// types), all elements after the maximum prefix length and before
-    /// the maximum suffix length are not examined by any variable-length
-    /// pattern, and therefore can be added/removed without affecting
-    /// them - creating equivalent patterns from any sufficiently-large
-    /// length.
-    ///
-    /// Of course, if fixed-length patterns exist, we must be sure
-    /// that our length is large enough to miss them all, so
-    /// we can pick `L = max(max(FIXED_LEN)+1, max(PREFIX_LEN) + max(SUFFIX_LEN))`
-    ///
-    /// for example, with the above pair of patterns, all elements
-    /// but the first and last can be added/removed, so any
-    /// witness of length ≥2 (say, `[false, false, true]`) can be
-    /// turned to a witness from any other length ≥2.
-    fn split<'p, 'tcx>(self, pcx: PatCtxt<'_, 'p, 'tcx>) -> SmallVec<[Constructor<'tcx>; 1]> {
-        let (self_prefix, self_suffix) = match self.kind {
-            VarLen(self_prefix, self_suffix) => (self_prefix, self_suffix),
-            _ => return smallvec![Slice(self)],
-        };
-
-        let head_ctors = pcx.matrix.head_ctors(pcx.cx).filter(|c| !c.is_wildcard());
-
-        let mut max_prefix_len = self_prefix;
-        let mut max_suffix_len = self_suffix;
-        let mut max_fixed_len = 0;
-
-        for ctor in head_ctors {
-            if let Slice(slice) = ctor {
-                match slice.kind {
-                    FixedLen(len) => {
-                        max_fixed_len = cmp::max(max_fixed_len, len);
-                    }
-                    VarLen(prefix, suffix) => {
-                        max_prefix_len = cmp::max(max_prefix_len, prefix);
-                        max_suffix_len = cmp::max(max_suffix_len, suffix);
-                    }
-                }
-            } else {
-                bug!("unexpected ctor for slice type: {:?}", ctor);
-            }
-        }
-
-        // For diagnostics, we keep the prefix and suffix lengths separate, so in the case
-        // where `max_fixed_len + 1` is the largest, we adapt `max_prefix_len` accordingly,
-        // so that `L = max_prefix_len + max_suffix_len`.
-        if max_fixed_len + 1 >= max_prefix_len + max_suffix_len {
-            // The subtraction can't overflow thanks to the above check.
-            // The new `max_prefix_len` is also guaranteed to be larger than its previous
-            // value.
-            max_prefix_len = max_fixed_len + 1 - max_suffix_len;
-        }
-
-        let final_slice = VarLen(max_prefix_len, max_suffix_len);
-        let final_slice = Slice::new(self.array_len, final_slice);
-        match self.array_len {
-            Some(_) => smallvec![Slice(final_slice)],
-            None => {
-                // `self` originally covered the range `(self.arity()..infinity)`. We split that
-                // range into two: lengths smaller than `final_slice.arity()` are treated
-                // independently as fixed-lengths slices, and lengths above are captured by
-                // `final_slice`.
-                let smaller_lengths = (self.arity()..final_slice.arity()).map(FixedLen);
-                smaller_lengths
-                    .map(|kind| Slice::new(self.array_len, kind))
-                    .chain(Some(final_slice))
-                    .map(Slice)
-                    .collect()
-            }
-        }
-    }
-
-    /// See `Constructor::is_covered_by`
-    fn is_covered_by(self, other: Self) -> bool {
-        other.kind.covers_length(self.arity())
-    }
-}
-
-/// A value can be decomposed into a constructor applied to some fields. This struct represents
-/// the constructor. See also `Fields`.
-///
-/// `pat_constructor` retrieves the constructor corresponding to a pattern.
-/// `specialize_constructor` returns the list of fields corresponding to a pattern, given a
-/// constructor. `Constructor::apply` reconstructs the pattern from a pair of `Constructor` and
-/// `Fields`.
-#[derive(Clone, Debug, PartialEq)]
-enum Constructor<'tcx> {
-    /// The constructor for patterns that have a single constructor, like tuples, struct patterns
-    /// and fixed-length arrays.
-    Single,
-    /// Enum variants.
-    Variant(DefId),
-    /// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
-    IntRange(IntRange<'tcx>),
-    /// Ranges of floating-point literal values (`2.0..=5.2`).
-    FloatRange(&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>, RangeEnd),
-    /// String literals. Strings are not quite the same as `&[u8]` so we treat them separately.
-    Str(&'tcx ty::Const<'tcx>),
-    /// Array and slice patterns.
-    Slice(Slice),
-    /// Constants that must not be matched structurally. They are treated as black
-    /// boxes for the purposes of exhaustiveness: we must not inspect them, and they
-    /// don't count towards making a match exhaustive.
-    Opaque,
-    /// Fake extra constructor for enums that aren't allowed to be matched exhaustively. Also used
-    /// for those types for which we cannot list constructors explicitly, like `f64` and `str`.
-    NonExhaustive,
-    /// Wildcard pattern.
-    Wildcard,
-}
-
-impl<'tcx> Constructor<'tcx> {
-    fn is_wildcard(&self) -> bool {
-        matches!(self, Wildcard)
-    }
-
-    fn as_int_range(&self) -> Option<&IntRange<'tcx>> {
-        match self {
-            IntRange(range) => Some(range),
-            _ => None,
-        }
-    }
-
-    fn as_slice(&self) -> Option<Slice> {
-        match self {
-            Slice(slice) => Some(*slice),
-            _ => None,
-        }
-    }
-
-    fn variant_index_for_adt(&self, adt: &'tcx ty::AdtDef) -> VariantIdx {
-        match *self {
-            Variant(id) => adt.variant_index_with_id(id),
-            Single => {
-                assert!(!adt.is_enum());
-                VariantIdx::new(0)
-            }
-            _ => bug!("bad constructor {:?} for adt {:?}", self, adt),
-        }
-    }
-
-    /// Some constructors (namely `Wildcard`, `IntRange` and `Slice`) actually stand for a set of actual
-    /// constructors (like variants, integers or fixed-sized slices). When specializing for these
-    /// constructors, we want to be specialising for the actual underlying constructors.
-    /// Naively, we would simply return the list of constructors they correspond to. We instead are
-    /// more clever: if there are constructors that we know will behave the same wrt the current
-    /// matrix, we keep them grouped. For example, all slices of a sufficiently large length
-    /// will either be all useful or all non-useful with a given matrix.
-    ///
-    /// See the branches for details on how the splitting is done.
-    ///
-    /// This function may discard some irrelevant constructors if this preserves behavior and
-    /// diagnostics. Eg. for the `_` case, we ignore the constructors already present in the
-    /// matrix, unless all of them are.
-    ///
-    /// `hir_id` is `None` when we're evaluating the wildcard pattern. In that case we do not want
-    /// to lint for overlapping ranges.
-    fn split<'p>(&self, pcx: PatCtxt<'_, 'p, 'tcx>, hir_id: Option<HirId>) -> SmallVec<[Self; 1]> {
-        debug!("Constructor::split({:#?}, {:#?})", self, pcx.matrix);
-
-        match self {
-            Wildcard => Constructor::split_wildcard(pcx),
-            // Fast-track if the range is trivial. In particular, we don't do the overlapping
-            // ranges check.
-            IntRange(ctor_range)
-                if ctor_range.treat_exhaustively(pcx.cx.tcx) && !ctor_range.is_singleton() =>
-            {
-                ctor_range.split(pcx, hir_id)
-            }
-            Slice(slice @ Slice { kind: VarLen(..), .. }) => slice.split(pcx),
-            // Any other constructor can be used unchanged.
-            _ => smallvec![self.clone()],
-        }
-    }
-
-    /// For wildcards, there are two groups of constructors: there are the constructors actually
-    /// present in the matrix (`head_ctors`), and the constructors not present (`missing_ctors`).
-    /// Two constructors that are not in the matrix will either both be caught (by a wildcard), or
-    /// both not be caught. Therefore we can keep the missing constructors grouped together.
-    fn split_wildcard<'p>(pcx: PatCtxt<'_, 'p, 'tcx>) -> SmallVec<[Self; 1]> {
-        // Missing constructors are those that are not matched by any non-wildcard patterns in the
-        // current column. We only fully construct them on-demand, because they're rarely used and
-        // can be big.
-        let missing_ctors = MissingConstructors::new(pcx);
-        if missing_ctors.is_empty(pcx) {
-            // All the constructors are present in the matrix, so we just go through them all.
-            // We must also split them first.
-            missing_ctors.all_ctors
-        } else {
-            // Some constructors are missing, thus we can specialize with the wildcard constructor,
-            // which will stand for those constructors that are missing, and behaves like any of
-            // them.
-            smallvec![Wildcard]
-        }
-    }
-
-    /// Returns whether `self` is covered by `other`, i.e. whether `self` is a subset of `other`.
-    /// For the simple cases, this is simply checking for equality. For the "grouped" constructors,
-    /// this checks for inclusion.
-    fn is_covered_by<'p>(&self, pcx: PatCtxt<'_, 'p, 'tcx>, other: &Self) -> bool {
-        // This must be kept in sync with `is_covered_by_any`.
-        match (self, other) {
-            // Wildcards cover anything
-            (_, Wildcard) => true,
-            // Wildcards are only covered by wildcards
-            (Wildcard, _) => false,
-
-            (Single, Single) => true,
-            (Variant(self_id), Variant(other_id)) => self_id == other_id,
-
-            (IntRange(self_range), IntRange(other_range)) => {
-                self_range.is_covered_by(pcx, other_range)
-            }
-            (
-                FloatRange(self_from, self_to, self_end),
-                FloatRange(other_from, other_to, other_end),
-            ) => {
-                match (
-                    compare_const_vals(pcx.cx.tcx, self_to, other_to, pcx.cx.param_env, pcx.ty),
-                    compare_const_vals(pcx.cx.tcx, self_from, other_from, pcx.cx.param_env, pcx.ty),
-                ) {
-                    (Some(to), Some(from)) => {
-                        (from == Ordering::Greater || from == Ordering::Equal)
-                            && (to == Ordering::Less
-                                || (other_end == self_end && to == Ordering::Equal))
-                    }
-                    _ => false,
-                }
-            }
-            (Str(self_val), Str(other_val)) => {
-                // FIXME: there's probably a more direct way of comparing for equality
-                match compare_const_vals(pcx.cx.tcx, self_val, other_val, pcx.cx.param_env, pcx.ty)
-                {
-                    Some(comparison) => comparison == Ordering::Equal,
-                    None => false,
-                }
-            }
-            (Slice(self_slice), Slice(other_slice)) => self_slice.is_covered_by(*other_slice),
-
-            // We are trying to inspect an opaque constant. Thus we skip the row.
-            (Opaque, _) | (_, Opaque) => false,
-            // Only a wildcard pattern can match the special extra constructor.
-            (NonExhaustive, _) => false,
-
-            _ => span_bug!(
-                pcx.span,
-                "trying to compare incompatible constructors {:?} and {:?}",
-                self,
-                other
-            ),
-        }
-    }
-
-    /// Faster version of `is_covered_by` when applied to many constructors. `used_ctors` is
-    /// assumed to be built from `matrix.head_ctors()` with wildcards filtered out, and `self` is
-    /// assumed to have been split from a wildcard.
-    fn is_covered_by_any<'p>(
-        &self,
-        pcx: PatCtxt<'_, 'p, 'tcx>,
-        used_ctors: &[Constructor<'tcx>],
-    ) -> bool {
-        if used_ctors.is_empty() {
-            return false;
-        }
-
-        // This must be kept in sync with `is_covered_by`.
-        match self {
-            // If `self` is `Single`, `used_ctors` cannot contain anything else than `Single`s.
-            Single => !used_ctors.is_empty(),
-            Variant(_) => used_ctors.iter().any(|c| c == self),
-            IntRange(range) => used_ctors
-                .iter()
-                .filter_map(|c| c.as_int_range())
-                .any(|other| range.is_covered_by(pcx, other)),
-            Slice(slice) => used_ctors
-                .iter()
-                .filter_map(|c| c.as_slice())
-                .any(|other| slice.is_covered_by(other)),
-            // This constructor is never covered by anything else
-            NonExhaustive => false,
-            Str(..) | FloatRange(..) | Opaque | Wildcard => {
-                bug!("found unexpected ctor in all_ctors: {:?}", self)
-            }
-        }
-    }
-
-    /// Apply a constructor to a list of patterns, yielding a new pattern. `pats`
-    /// must have as many elements as this constructor's arity.
-    ///
-    /// This is roughly the inverse of `specialize_constructor`.
-    ///
-    /// Examples:
-    /// `self`: `Constructor::Single`
-    /// `ty`: `(u32, u32, u32)`
-    /// `pats`: `[10, 20, _]`
-    /// returns `(10, 20, _)`
-    ///
-    /// `self`: `Constructor::Variant(Option::Some)`
-    /// `ty`: `Option<bool>`
-    /// `pats`: `[false]`
-    /// returns `Some(false)`
-    fn apply<'p>(&self, pcx: PatCtxt<'_, 'p, 'tcx>, fields: Fields<'p, 'tcx>) -> Pat<'tcx> {
-        let mut subpatterns = fields.all_patterns();
-
-        let pat = match self {
-            Single | Variant(_) => match pcx.ty.kind() {
-                ty::Adt(..) | ty::Tuple(..) => {
-                    let subpatterns = subpatterns
-                        .enumerate()
-                        .map(|(i, p)| FieldPat { field: Field::new(i), pattern: p })
-                        .collect();
-
-                    if let ty::Adt(adt, substs) = pcx.ty.kind() {
-                        if adt.is_enum() {
-                            PatKind::Variant {
-                                adt_def: adt,
-                                substs,
-                                variant_index: self.variant_index_for_adt(adt),
-                                subpatterns,
-                            }
-                        } else {
-                            PatKind::Leaf { subpatterns }
-                        }
-                    } else {
-                        PatKind::Leaf { subpatterns }
-                    }
-                }
-                // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should
-                // be careful to reconstruct the correct constant pattern here. However a string
-                // literal pattern will never be reported as a non-exhaustiveness witness, so we
-                // can ignore this issue.
-                ty::Ref(..) => PatKind::Deref { subpattern: subpatterns.next().unwrap() },
-                ty::Slice(_) | ty::Array(..) => bug!("bad slice pattern {:?} {:?}", self, pcx.ty),
-                _ => PatKind::Wild,
-            },
-            Slice(slice) => match slice.kind {
-                FixedLen(_) => {
-                    PatKind::Slice { prefix: subpatterns.collect(), slice: None, suffix: vec![] }
-                }
-                VarLen(prefix, _) => {
-                    let mut prefix: Vec<_> = subpatterns.by_ref().take(prefix as usize).collect();
-                    if slice.array_len.is_some() {
-                        // Improves diagnostics a bit: if the type is a known-size array, instead
-                        // of reporting `[x, _, .., _, y]`, we prefer to report `[x, .., y]`.
-                        // This is incorrect if the size is not known, since `[_, ..]` captures
-                        // arrays of lengths `>= 1` whereas `[..]` captures any length.
-                        while !prefix.is_empty() && prefix.last().unwrap().is_wildcard() {
-                            prefix.pop();
-                        }
-                    }
-                    let suffix: Vec<_> = if slice.array_len.is_some() {
-                        // Same as above.
-                        subpatterns.skip_while(Pat::is_wildcard).collect()
-                    } else {
-                        subpatterns.collect()
-                    };
-                    let wild = Pat::wildcard_from_ty(pcx.ty);
-                    PatKind::Slice { prefix, slice: Some(wild), suffix }
-                }
-            },
-            &Str(value) => PatKind::Constant { value },
-            &FloatRange(lo, hi, end) => PatKind::Range(PatRange { lo, hi, end }),
-            IntRange(range) => return range.to_pat(pcx.cx.tcx),
-            NonExhaustive => PatKind::Wild,
-            Opaque => bug!("we should not try to apply an opaque constructor"),
-            Wildcard => bug!(
-                "trying to apply a wildcard constructor; this should have been done in `apply_constructors`"
-            ),
-        };
-
-        Pat { ty: pcx.ty, span: DUMMY_SP, kind: Box::new(pat) }
-    }
-}
-
-/// Some fields need to be explicitly hidden away in certain cases; see the comment above the
-/// `Fields` struct. This struct represents such a potentially-hidden field. When a field is hidden
-/// we still keep its type around.
-#[derive(Debug, Copy, Clone)]
-enum FilteredField<'p, 'tcx> {
-    Kept(&'p Pat<'tcx>),
-    Hidden(Ty<'tcx>),
-}
-
-impl<'p, 'tcx> FilteredField<'p, 'tcx> {
-    fn kept(self) -> Option<&'p Pat<'tcx>> {
-        match self {
-            FilteredField::Kept(p) => Some(p),
-            FilteredField::Hidden(_) => None,
-        }
-    }
-
-    fn to_pattern(self) -> Pat<'tcx> {
-        match self {
-            FilteredField::Kept(p) => p.clone(),
-            FilteredField::Hidden(ty) => Pat::wildcard_from_ty(ty),
-        }
-    }
-}
-
-/// A value can be decomposed into a constructor applied to some fields. This struct represents
-/// those fields, generalized to allow patterns in each field. See also `Constructor`.
-///
-/// If a private or `non_exhaustive` field is uninhabited, the code mustn't observe that it is
-/// uninhabited. For that, we filter these fields out of the matrix. This is subtle because we
-/// still need to have those fields back when going to/from a `Pat`. Most of this is handled
-/// automatically in `Fields`, but when constructing or deconstructing `Fields` you need to be
-/// careful. As a rule, when going to/from the matrix, use the filtered field list; when going
-/// to/from `Pat`, use the full field list.
-/// This filtering is uncommon in practice, because uninhabited fields are rarely used, so we avoid
-/// it when possible to preserve performance.
-#[derive(Debug, Clone)]
-enum Fields<'p, 'tcx> {
-    /// Lists of patterns that don't contain any filtered fields.
-    /// `Slice` and `Vec` behave the same; the difference is only to avoid allocating and
-    /// triple-dereferences when possible. Frankly this is premature optimization, I (Nadrieril)
-    /// have not measured if it really made a difference.
-    Slice(&'p [Pat<'tcx>]),
-    Vec(SmallVec<[&'p Pat<'tcx>; 2]>),
-    /// Patterns where some of the fields need to be hidden. `kept_count` caches the number of
-    /// non-hidden fields.
-    Filtered {
-        fields: SmallVec<[FilteredField<'p, 'tcx>; 2]>,
-        kept_count: usize,
-    },
-}
-
-impl<'p, 'tcx> Fields<'p, 'tcx> {
-    fn empty() -> Self {
-        Fields::Slice(&[])
-    }
-
-    /// Construct a new `Fields` from the given pattern. Must not be used if the pattern is a field
-    /// of a struct/tuple/variant.
-    fn from_single_pattern(pat: &'p Pat<'tcx>) -> Self {
-        Fields::Slice(std::slice::from_ref(pat))
-    }
-
-    /// Convenience; internal use.
-    fn wildcards_from_tys(
-        cx: &MatchCheckCtxt<'p, 'tcx>,
-        tys: impl IntoIterator<Item = Ty<'tcx>>,
-    ) -> Self {
-        let wilds = tys.into_iter().map(Pat::wildcard_from_ty);
-        let pats = cx.pattern_arena.alloc_from_iter(wilds);
-        Fields::Slice(pats)
-    }
-
-    /// Creates a new list of wildcard fields for a given constructor.
-    fn wildcards(pcx: PatCtxt<'_, 'p, 'tcx>, constructor: &Constructor<'tcx>) -> Self {
-        let ty = pcx.ty;
-        let cx = pcx.cx;
-        let wildcard_from_ty = |ty| &*cx.pattern_arena.alloc(Pat::wildcard_from_ty(ty));
-
-        let ret = match constructor {
-            Single | Variant(_) => match ty.kind() {
-                ty::Tuple(ref fs) => {
-                    Fields::wildcards_from_tys(cx, fs.into_iter().map(|ty| ty.expect_ty()))
-                }
-                ty::Ref(_, rty, _) => Fields::from_single_pattern(wildcard_from_ty(rty)),
-                ty::Adt(adt, substs) => {
-                    if adt.is_box() {
-                        // Use T as the sub pattern type of Box<T>.
-                        Fields::from_single_pattern(wildcard_from_ty(substs.type_at(0)))
-                    } else {
-                        let variant = &adt.variants[constructor.variant_index_for_adt(adt)];
-                        // Whether we must not match the fields of this variant exhaustively.
-                        let is_non_exhaustive =
-                            variant.is_field_list_non_exhaustive() && !adt.did.is_local();
-                        let field_tys = variant.fields.iter().map(|field| field.ty(cx.tcx, substs));
-                        // In the following cases, we don't need to filter out any fields. This is
-                        // the vast majority of real cases, since uninhabited fields are uncommon.
-                        let has_no_hidden_fields = (adt.is_enum() && !is_non_exhaustive)
-                            || !field_tys.clone().any(|ty| cx.is_uninhabited(ty));
-
-                        if has_no_hidden_fields {
-                            Fields::wildcards_from_tys(cx, field_tys)
-                        } else {
-                            let mut kept_count = 0;
-                            let fields = variant
-                                .fields
-                                .iter()
-                                .map(|field| {
-                                    let ty = field.ty(cx.tcx, substs);
-                                    let is_visible = adt.is_enum()
-                                        || field.vis.is_accessible_from(cx.module, cx.tcx);
-                                    let is_uninhabited = cx.is_uninhabited(ty);
-
-                                    // In the cases of either a `#[non_exhaustive]` field list
-                                    // or a non-public field, we hide uninhabited fields in
-                                    // order not to reveal the uninhabitedness of the whole
-                                    // variant.
-                                    if is_uninhabited && (!is_visible || is_non_exhaustive) {
-                                        FilteredField::Hidden(ty)
-                                    } else {
-                                        kept_count += 1;
-                                        FilteredField::Kept(wildcard_from_ty(ty))
-                                    }
-                                })
-                                .collect();
-                            Fields::Filtered { fields, kept_count }
-                        }
-                    }
-                }
-                _ => bug!("Unexpected type for `Single` constructor: {:?}", ty),
-            },
-            Slice(slice) => match *ty.kind() {
-                ty::Slice(ty) | ty::Array(ty, _) => {
-                    let arity = slice.arity();
-                    Fields::wildcards_from_tys(cx, (0..arity).map(|_| ty))
-                }
-                _ => bug!("bad slice pattern {:?} {:?}", constructor, ty),
-            },
-            Str(..) | FloatRange(..) | IntRange(..) | NonExhaustive | Opaque | Wildcard => {
-                Fields::empty()
-            }
-        };
-        debug!("Fields::wildcards({:?}, {:?}) = {:#?}", constructor, ty, ret);
-        ret
-    }
-
-    /// Returns the number of patterns from the viewpoint of match-checking, i.e. excluding hidden
-    /// fields. This is what we want in most cases in this file, the only exception being
-    /// conversion to/from `Pat`.
-    fn len(&self) -> usize {
-        match self {
-            Fields::Slice(pats) => pats.len(),
-            Fields::Vec(pats) => pats.len(),
-            Fields::Filtered { kept_count, .. } => *kept_count,
-        }
-    }
-
-    /// Returns the complete list of patterns, including hidden fields.
-    fn all_patterns(self) -> impl Iterator<Item = Pat<'tcx>> {
-        let pats: SmallVec<[_; 2]> = match self {
-            Fields::Slice(pats) => pats.iter().cloned().collect(),
-            Fields::Vec(pats) => pats.into_iter().cloned().collect(),
-            Fields::Filtered { fields, .. } => {
-                // We don't skip any fields here.
-                fields.into_iter().map(|p| p.to_pattern()).collect()
-            }
-        };
-        pats.into_iter()
-    }
-
-    /// Overrides some of the fields with the provided patterns. Exactly like
-    /// `replace_fields_indexed`, except that it takes `FieldPat`s as input.
-    fn replace_with_fieldpats(
-        &self,
-        new_pats: impl IntoIterator<Item = &'p FieldPat<'tcx>>,
-    ) -> Self {
-        self.replace_fields_indexed(
-            new_pats.into_iter().map(|pat| (pat.field.index(), &pat.pattern)),
-        )
-    }
-
-    /// Overrides some of the fields with the provided patterns. This is used when a pattern
-    /// defines some fields but not all, for example `Foo { field1: Some(_), .. }`: here we start with a
-    /// `Fields` that is just one wildcard per field of the `Foo` struct, and override the entry
-    /// corresponding to `field1` with the pattern `Some(_)`. This is also used for slice patterns
-    /// for the same reason.
-    fn replace_fields_indexed(
-        &self,
-        new_pats: impl IntoIterator<Item = (usize, &'p Pat<'tcx>)>,
-    ) -> Self {
-        let mut fields = self.clone();
-        if let Fields::Slice(pats) = fields {
-            fields = Fields::Vec(pats.iter().collect());
-        }
-
-        match &mut fields {
-            Fields::Vec(pats) => {
-                for (i, pat) in new_pats {
-                    pats[i] = pat
-                }
-            }
-            Fields::Filtered { fields, .. } => {
-                for (i, pat) in new_pats {
-                    if let FilteredField::Kept(p) = &mut fields[i] {
-                        *p = pat
-                    }
-                }
-            }
-            Fields::Slice(_) => unreachable!(),
-        }
-        fields
-    }
-
-    /// Replaces contained fields with the given filtered list of patterns, e.g. taken from the
-    /// matrix. There must be `len()` patterns in `pats`.
-    fn replace_fields(
-        &self,
-        cx: &MatchCheckCtxt<'p, 'tcx>,
-        pats: impl IntoIterator<Item = Pat<'tcx>>,
-    ) -> Self {
-        let pats: &[_] = cx.pattern_arena.alloc_from_iter(pats);
-
-        match self {
-            Fields::Filtered { fields, kept_count } => {
-                let mut pats = pats.iter();
-                let mut fields = fields.clone();
-                for f in &mut fields {
-                    if let FilteredField::Kept(p) = f {
-                        // We take one input pattern for each `Kept` field, in order.
-                        *p = pats.next().unwrap();
-                    }
-                }
-                Fields::Filtered { fields, kept_count: *kept_count }
-            }
-            _ => Fields::Slice(pats),
-        }
-    }
-
-    /// Replaces contained fields with the arguments of the given pattern. Only use on a pattern
-    /// that is compatible with the constructor used to build `self`.
-    /// This is meant to be used on the result of `Fields::wildcards()`. The idea is that
-    /// `wildcards` constructs a list of fields where all entries are wildcards, and the pattern
-    /// provided to this function fills some of the fields with non-wildcards.
-    /// In the following example `Fields::wildcards` would return `[_, _, _, _]`. If we call
-    /// `replace_with_pattern_arguments` on it with the pattern, the result will be `[Some(0), _,
-    /// _, _]`.
-    /// ```rust
-    /// let x: [Option<u8>; 4] = foo();
-    /// match x {
-    ///     [Some(0), ..] => {}
-    /// }
-    /// ```
-    /// This is guaranteed to preserve the number of patterns in `self`.
-    fn replace_with_pattern_arguments(&self, pat: &'p Pat<'tcx>) -> Self {
-        match pat.kind.as_ref() {
-            PatKind::Deref { subpattern } => {
-                assert_eq!(self.len(), 1);
-                Fields::from_single_pattern(subpattern)
-            }
-            PatKind::Leaf { subpatterns } | PatKind::Variant { subpatterns, .. } => {
-                self.replace_with_fieldpats(subpatterns)
-            }
-            PatKind::Array { prefix, suffix, .. } | PatKind::Slice { prefix, suffix, .. } => {
-                // Number of subpatterns for the constructor
-                let ctor_arity = self.len();
-
-                // Replace the prefix and the suffix with the given patterns, leaving wildcards in
-                // the middle if there was a subslice pattern `..`.
-                let prefix = prefix.iter().enumerate();
-                let suffix =
-                    suffix.iter().enumerate().map(|(i, p)| (ctor_arity - suffix.len() + i, p));
-                self.replace_fields_indexed(prefix.chain(suffix))
-            }
-            _ => self.clone(),
-        }
-    }
-
-    fn push_on_patstack(self, stack: &[&'p Pat<'tcx>]) -> PatStack<'p, 'tcx> {
-        let pats: SmallVec<_> = match self {
-            Fields::Slice(pats) => pats.iter().chain(stack.iter().copied()).collect(),
-            Fields::Vec(mut pats) => {
-                pats.extend_from_slice(stack);
-                pats
-            }
-            Fields::Filtered { fields, .. } => {
-                // We skip hidden fields here
-                fields.into_iter().filter_map(|p| p.kept()).chain(stack.iter().copied()).collect()
-            }
-        };
-        PatStack::from_vec(pats)
-    }
-}
-
-#[derive(Clone, Debug)]
-crate enum Usefulness<'tcx> {
-    /// Carries, for each column in the matrix, a set of sub-branches that have been found to be
-    /// unreachable. Used only in the presence of or-patterns, otherwise it stays empty.
-    Useful(Vec<FxHashSet<Span>>),
-    /// Carries a list of witnesses of non-exhaustiveness.
-    UsefulWithWitness(Vec<Witness<'tcx>>),
-    NotUseful,
-}
-
-impl<'tcx> Usefulness<'tcx> {
-    fn new_useful(preference: WitnessPreference) -> Self {
-        match preference {
-            ConstructWitness => UsefulWithWitness(vec![Witness(vec![])]),
-            LeaveOutWitness => Useful(vec![]),
-        }
-    }
-
-    fn is_useful(&self) -> bool {
-        !matches!(*self, NotUseful)
-    }
-
-    fn apply_constructor<'p>(
-        self,
-        pcx: PatCtxt<'_, 'p, 'tcx>,
-        ctor: &Constructor<'tcx>,
-        ctor_wild_subpatterns: &Fields<'p, 'tcx>,
-    ) -> Self {
-        match self {
-            UsefulWithWitness(witnesses) => {
-                let new_witnesses = if ctor.is_wildcard() {
-                    let missing_ctors = MissingConstructors::new(pcx);
-                    let new_patterns = missing_ctors.report_patterns(pcx);
-                    witnesses
-                        .into_iter()
-                        .flat_map(|witness| {
-                            new_patterns.iter().map(move |pat| {
-                                let mut witness = witness.clone();
-                                witness.0.push(pat.clone());
-                                witness
-                            })
-                        })
-                        .collect()
-                } else {
-                    witnesses
-                        .into_iter()
-                        .map(|witness| witness.apply_constructor(pcx, &ctor, ctor_wild_subpatterns))
-                        .collect()
-                };
-                UsefulWithWitness(new_witnesses)
-            }
-            Useful(mut unreachables) => {
-                if !unreachables.is_empty() {
-                    // When we apply a constructor, there are `arity` columns of the matrix that
-                    // corresponded to its arguments. All the unreachables found in these columns
-                    // will, after `apply`, come from the first column. So we take the union of all
-                    // the corresponding sets and put them in the first column.
-                    // Note that `arity` may be 0, in which case we just push a new empty set.
-                    let len = unreachables.len();
-                    let arity = ctor_wild_subpatterns.len();
-                    let mut unioned = FxHashSet::default();
-                    for set in unreachables.drain((len - arity)..) {
-                        unioned.extend(set)
-                    }
-                    unreachables.push(unioned);
-                }
-                Useful(unreachables)
-            }
-            x => x,
-        }
-    }
-}
-
-#[derive(Copy, Clone, Debug)]
-enum WitnessPreference {
-    ConstructWitness,
-    LeaveOutWitness,
-}
-
-#[derive(Copy, Clone)]
-struct PatCtxt<'a, 'p, 'tcx> {
-    cx: &'a MatchCheckCtxt<'p, 'tcx>,
-    /// Current state of the matrix.
-    matrix: &'a Matrix<'p, 'tcx>,
-    /// Type of the current column under investigation.
-    ty: Ty<'tcx>,
-    /// Span of the current pattern under investigation.
-    span: Span,
-    /// Whether the current pattern is the whole pattern as found in a match arm, or if it's a
-    /// subpattern.
-    is_top_level: bool,
-}
-
-/// A witness of non-exhaustiveness for error reporting, represented
-/// as a list of patterns (in reverse order of construction) with
-/// wildcards inside to represent elements that can take any inhabitant
-/// of the type as a value.
-///
-/// A witness against a list of patterns should have the same types
-/// and length as the pattern matched against. Because Rust `match`
-/// is always against a single pattern, at the end the witness will
-/// have length 1, but in the middle of the algorithm, it can contain
-/// multiple patterns.
-///
-/// For example, if we are constructing a witness for the match against
-///
-/// ```
-/// struct Pair(Option<(u32, u32)>, bool);
-///
-/// match (p: Pair) {
-///    Pair(None, _) => {}
-///    Pair(_, false) => {}
-/// }
-/// ```
-///
-/// We'll perform the following steps:
-/// 1. Start with an empty witness
-///     `Witness(vec![])`
-/// 2. Push a witness `Some(_)` against the `None`
-///     `Witness(vec![Some(_)])`
-/// 3. Push a witness `true` against the `false`
-///     `Witness(vec![Some(_), true])`
-/// 4. Apply the `Pair` constructor to the witnesses
-///     `Witness(vec![Pair(Some(_), true)])`
-///
-/// The final `Pair(Some(_), true)` is then the resulting witness.
-#[derive(Clone, Debug)]
-crate struct Witness<'tcx>(Vec<Pat<'tcx>>);
-
-impl<'tcx> Witness<'tcx> {
-    /// Asserts that the witness contains a single pattern, and returns it.
-    fn single_pattern(self) -> Pat<'tcx> {
-        assert_eq!(self.0.len(), 1);
-        self.0.into_iter().next().unwrap()
-    }
-
-    /// Constructs a partial witness for a pattern given a list of
-    /// patterns expanded by the specialization step.
-    ///
-    /// When a pattern P is discovered to be useful, this function is used bottom-up
-    /// to reconstruct a complete witness, e.g., a pattern P' that covers a subset
-    /// of values, V, where each value in that set is not covered by any previously
-    /// used patterns and is covered by the pattern P'. Examples:
-    ///
-    /// left_ty: tuple of 3 elements
-    /// pats: [10, 20, _]           => (10, 20, _)
-    ///
-    /// left_ty: struct X { a: (bool, &'static str), b: usize}
-    /// pats: [(false, "foo"), 42]  => X { a: (false, "foo"), b: 42 }
-    fn apply_constructor<'p>(
-        mut self,
-        pcx: PatCtxt<'_, 'p, 'tcx>,
-        ctor: &Constructor<'tcx>,
-        ctor_wild_subpatterns: &Fields<'p, 'tcx>,
-    ) -> Self {
-        let pat = {
-            let len = self.0.len();
-            let arity = ctor_wild_subpatterns.len();
-            let pats = self.0.drain((len - arity)..).rev();
-            let fields = ctor_wild_subpatterns.replace_fields(pcx.cx, pats);
-            ctor.apply(pcx, fields)
-        };
-
-        self.0.push(pat);
-
-        self
-    }
-}
-
-/// This determines the set of all possible constructors of a pattern matching
-/// values of type `left_ty`. For vectors, this would normally be an infinite set
-/// but is instead bounded by the maximum fixed length of slice patterns in
-/// the column of patterns being analyzed.
-///
-/// We make sure to omit constructors that are statically impossible. E.g., for
-/// `Option<!>`, we do not include `Some(_)` in the returned list of constructors.
-/// Invariant: this returns an empty `Vec` if and only if the type is uninhabited (as determined by
-/// `cx.is_uninhabited()`).
-fn all_constructors<'p, 'tcx>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Vec<Constructor<'tcx>> {
-    debug!("all_constructors({:?})", pcx.ty);
-    let cx = pcx.cx;
-    let make_range = |start, end| {
-        IntRange(
-            // `unwrap()` is ok because we know the type is an integer.
-            IntRange::from_range(cx.tcx, start, end, pcx.ty, &RangeEnd::Included, pcx.span)
-                .unwrap(),
-        )
-    };
-    match pcx.ty.kind() {
-        ty::Bool => vec![make_range(0, 1)],
-        ty::Array(sub_ty, len) if len.try_eval_usize(cx.tcx, cx.param_env).is_some() => {
-            let len = len.eval_usize(cx.tcx, cx.param_env);
-            if len != 0 && cx.is_uninhabited(sub_ty) {
-                vec![]
-            } else {
-                vec![Slice(Slice::new(Some(len), VarLen(0, 0)))]
-            }
-        }
-        // Treat arrays of a constant but unknown length like slices.
-        ty::Array(sub_ty, _) | ty::Slice(sub_ty) => {
-            let kind = if cx.is_uninhabited(sub_ty) { FixedLen(0) } else { VarLen(0, 0) };
-            vec![Slice(Slice::new(None, kind))]
-        }
-        ty::Adt(def, substs) if def.is_enum() => {
-            // If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an
-            // additional "unknown" constructor.
-            // There is no point in enumerating all possible variants, because the user can't
-            // actually match against them all themselves. So we always return only the fictitious
-            // constructor.
-            // E.g., in an example like:
-            //
-            // ```
-            //     let err: io::ErrorKind = ...;
-            //     match err {
-            //         io::ErrorKind::NotFound => {},
-            //     }
-            // ```
-            //
-            // we don't want to show every possible IO error, but instead have only `_` as the
-            // witness.
-            let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive_enum(pcx.ty);
-
-            // If `exhaustive_patterns` is disabled and our scrutinee is an empty enum, we treat it
-            // as though it had an "unknown" constructor to avoid exposing its emptiness. The
-            // exception is if the pattern is at the top level, because we want empty matches to be
-            // considered exhaustive.
-            let is_secretly_empty = def.variants.is_empty()
-                && !cx.tcx.features().exhaustive_patterns
-                && !pcx.is_top_level;
-
-            if is_secretly_empty || is_declared_nonexhaustive {
-                vec![NonExhaustive]
-            } else if cx.tcx.features().exhaustive_patterns {
-                // If `exhaustive_patterns` is enabled, we exclude variants known to be
-                // uninhabited.
-                def.variants
-                    .iter()
-                    .filter(|v| {
-                        !v.uninhabited_from(cx.tcx, substs, def.adt_kind(), cx.param_env)
-                            .contains(cx.tcx, cx.module)
-                    })
-                    .map(|v| Variant(v.def_id))
-                    .collect()
-            } else {
-                def.variants.iter().map(|v| Variant(v.def_id)).collect()
-            }
-        }
-        ty::Char => {
-            vec![
-                // The valid Unicode Scalar Value ranges.
-                make_range('\u{0000}' as u128, '\u{D7FF}' as u128),
-                make_range('\u{E000}' as u128, '\u{10FFFF}' as u128),
-            ]
-        }
-        ty::Int(_) | ty::Uint(_)
-            if pcx.ty.is_ptr_sized_integral()
-                && !cx.tcx.features().precise_pointer_size_matching =>
-        {
-            // `usize`/`isize` are not allowed to be matched exhaustively unless the
-            // `precise_pointer_size_matching` feature is enabled. So we treat those types like
-            // `#[non_exhaustive]` enums by returning a special unmatcheable constructor.
-            vec![NonExhaustive]
-        }
-        &ty::Int(ity) => {
-            let bits = Integer::from_attr(&cx.tcx, SignedInt(ity)).size().bits() as u128;
-            let min = 1u128 << (bits - 1);
-            let max = min - 1;
-            vec![make_range(min, max)]
-        }
-        &ty::Uint(uty) => {
-            let size = Integer::from_attr(&cx.tcx, UnsignedInt(uty)).size();
-            let max = size.truncate(u128::MAX);
-            vec![make_range(0, max)]
-        }
-        // If `exhaustive_patterns` is disabled and our scrutinee is the never type, we cannot
-        // expose its emptiness. The exception is if the pattern is at the top level, because we
-        // want empty matches to be considered exhaustive.
-        ty::Never if !cx.tcx.features().exhaustive_patterns && !pcx.is_top_level => {
-            vec![NonExhaustive]
-        }
-        ty::Never => vec![],
-        _ if cx.is_uninhabited(pcx.ty) => vec![],
-        ty::Adt(..) | ty::Tuple(..) | ty::Ref(..) => vec![Single],
-        // This type is one for which we cannot list constructors, like `str` or `f64`.
-        _ => vec![NonExhaustive],
-    }
-}
-
-/// An inclusive interval, used for precise integer exhaustiveness checking.
-/// `IntRange`s always store a contiguous range. This means that values are
-/// encoded such that `0` encodes the minimum value for the integer,
-/// regardless of the signedness.
-/// For example, the pattern `-128..=127i8` is encoded as `0..=255`.
-/// This makes comparisons and arithmetic on interval endpoints much more
-/// straightforward. See `signed_bias` for details.
-///
-/// `IntRange` is never used to encode an empty range or a "range" that wraps
-/// around the (offset) space: i.e., `range.lo <= range.hi`.
-#[derive(Clone, Debug)]
-struct IntRange<'tcx> {
-    range: RangeInclusive<u128>,
-    ty: Ty<'tcx>,
-    span: Span,
-}
-
-impl<'tcx> IntRange<'tcx> {
-    #[inline]
-    fn is_integral(ty: Ty<'_>) -> bool {
-        matches!(ty.kind(), ty::Char | ty::Int(_) | ty::Uint(_) | ty::Bool)
-    }
-
-    fn is_singleton(&self) -> bool {
-        self.range.start() == self.range.end()
-    }
-
-    fn boundaries(&self) -> (u128, u128) {
-        (*self.range.start(), *self.range.end())
-    }
-
-    /// Don't treat `usize`/`isize` exhaustively unless the `precise_pointer_size_matching` feature
-    /// is enabled.
-    fn treat_exhaustively(&self, tcx: TyCtxt<'tcx>) -> bool {
-        !self.ty.is_ptr_sized_integral() || tcx.features().precise_pointer_size_matching
-    }
-
-    #[inline]
-    fn integral_size_and_signed_bias(tcx: TyCtxt<'tcx>, ty: Ty<'_>) -> Option<(Size, u128)> {
-        match *ty.kind() {
-            ty::Bool => Some((Size::from_bytes(1), 0)),
-            ty::Char => Some((Size::from_bytes(4), 0)),
-            ty::Int(ity) => {
-                let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
-                Some((size, 1u128 << (size.bits() as u128 - 1)))
-            }
-            ty::Uint(uty) => Some((Integer::from_attr(&tcx, UnsignedInt(uty)).size(), 0)),
-            _ => None,
-        }
-    }
-
-    #[inline]
-    fn from_const(
-        tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        value: &Const<'tcx>,
-        span: Span,
-    ) -> Option<IntRange<'tcx>> {
-        if let Some((target_size, bias)) = Self::integral_size_and_signed_bias(tcx, value.ty) {
-            let ty = value.ty;
-            let val = (|| {
-                if let ty::ConstKind::Value(ConstValue::Scalar(scalar)) = value.val {
-                    // For this specific pattern we can skip a lot of effort and go
-                    // straight to the result, after doing a bit of checking. (We
-                    // could remove this branch and just fall through, which
-                    // is more general but much slower.)
-                    if let Ok(bits) = scalar.to_bits_or_ptr(target_size, &tcx) {
-                        return Some(bits);
-                    }
-                }
-                // This is a more general form of the previous case.
-                value.try_eval_bits(tcx, param_env, ty)
-            })()?;
-            let val = val ^ bias;
-            Some(IntRange { range: val..=val, ty, span })
-        } else {
-            None
-        }
-    }
-
-    #[inline]
-    fn from_range(
-        tcx: TyCtxt<'tcx>,
-        lo: u128,
-        hi: u128,
-        ty: Ty<'tcx>,
-        end: &RangeEnd,
-        span: Span,
-    ) -> Option<IntRange<'tcx>> {
-        if Self::is_integral(ty) {
-            // Perform a shift if the underlying types are signed,
-            // which makes the interval arithmetic simpler.
-            let bias = IntRange::signed_bias(tcx, ty);
-            let (lo, hi) = (lo ^ bias, hi ^ bias);
-            let offset = (*end == RangeEnd::Excluded) as u128;
-            if lo > hi || (lo == hi && *end == RangeEnd::Excluded) {
-                // This should have been caught earlier by E0030.
-                bug!("malformed range pattern: {}..={}", lo, (hi - offset));
-            }
-            Some(IntRange { range: lo..=(hi - offset), ty, span })
-        } else {
-            None
-        }
-    }
-
-    // The return value of `signed_bias` should be XORed with an endpoint to encode/decode it.
-    fn signed_bias(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> u128 {
-        match *ty.kind() {
-            ty::Int(ity) => {
-                let bits = Integer::from_attr(&tcx, SignedInt(ity)).size().bits() as u128;
-                1u128 << (bits - 1)
-            }
-            _ => 0,
-        }
-    }
-
-    fn is_subrange(&self, other: &Self) -> bool {
-        other.range.start() <= self.range.start() && self.range.end() <= other.range.end()
-    }
-
-    fn intersection(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Option<Self> {
-        let ty = self.ty;
-        let (lo, hi) = self.boundaries();
-        let (other_lo, other_hi) = other.boundaries();
-        if self.treat_exhaustively(tcx) {
-            if lo <= other_hi && other_lo <= hi {
-                let span = other.span;
-                Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi), ty, span })
-            } else {
-                None
-            }
-        } else {
-            // If the range should not be treated exhaustively, fallback to checking for inclusion.
-            if self.is_subrange(other) { Some(self.clone()) } else { None }
-        }
-    }
-
-    fn suspicious_intersection(&self, other: &Self) -> bool {
-        // `false` in the following cases:
-        // 1     ----      // 1  ----------   // 1 ----        // 1       ----
-        // 2  ----------   // 2     ----      // 2       ----  // 2 ----
-        //
-        // The following are currently `false`, but could be `true` in the future (#64007):
-        // 1 ---------       // 1     ---------
-        // 2     ----------  // 2 ----------
-        //
-        // `true` in the following cases:
-        // 1 -------          // 1       -------
-        // 2       --------   // 2 -------
-        let (lo, hi) = self.boundaries();
-        let (other_lo, other_hi) = other.boundaries();
-        lo == other_hi || hi == other_lo
-    }
-
-    fn to_pat(&self, tcx: TyCtxt<'tcx>) -> Pat<'tcx> {
-        let (lo, hi) = self.boundaries();
-
-        let bias = IntRange::signed_bias(tcx, self.ty);
-        let (lo, hi) = (lo ^ bias, hi ^ bias);
-
-        let ty = ty::ParamEnv::empty().and(self.ty);
-        let lo_const = ty::Const::from_bits(tcx, lo, ty);
-        let hi_const = ty::Const::from_bits(tcx, hi, ty);
-
-        let kind = if lo == hi {
-            PatKind::Constant { value: lo_const }
-        } else {
-            PatKind::Range(PatRange { lo: lo_const, hi: hi_const, end: RangeEnd::Included })
-        };
-
-        // This is a brand new pattern, so we don't reuse `self.span`.
-        Pat { ty: self.ty, span: DUMMY_SP, kind: Box::new(kind) }
-    }
-
-    /// For exhaustive integer matching, some constructors are grouped within other constructors
-    /// (namely integer typed values are grouped within ranges). However, when specialising these
-    /// constructors, we want to be specialising for the underlying constructors (the integers), not
-    /// the groups (the ranges). Thus we need to split the groups up. Splitting them up naïvely would
-    /// mean creating a separate constructor for every single value in the range, which is clearly
-    /// impractical. However, observe that for some ranges of integers, the specialisation will be
-    /// identical across all values in that range (i.e., there are equivalence classes of ranges of
-    /// constructors based on their `U(S(c, P), S(c, p))` outcome). These classes are grouped by
-    /// the patterns that apply to them (in the matrix `P`). We can split the range whenever the
-    /// patterns that apply to that range (specifically: the patterns that *intersect* with that range)
-    /// change.
-    /// Our solution, therefore, is to split the range constructor into subranges at every single point
-    /// the group of intersecting patterns changes (using the method described below).
-    /// And voilà! We're testing precisely those ranges that we need to, without any exhaustive matching
-    /// on actual integers. The nice thing about this is that the number of subranges is linear in the
-    /// number of rows in the matrix (i.e., the number of cases in the `match` statement), so we don't
-    /// need to be worried about matching over gargantuan ranges.
-    ///
-    /// Essentially, given the first column of a matrix representing ranges, looking like the following:
-    ///
-    /// |------|  |----------| |-------|    ||
-    ///    |-------| |-------|            |----| ||
-    ///       |---------|
-    ///
-    /// We split the ranges up into equivalence classes so the ranges are no longer overlapping:
-    ///
-    /// |--|--|||-||||--||---|||-------|  |-|||| ||
-    ///
-    /// The logic for determining how to split the ranges is fairly straightforward: we calculate
-    /// boundaries for each interval range, sort them, then create constructors for each new interval
-    /// between every pair of boundary points. (This essentially sums up to performing the intuitive
-    /// merging operation depicted above.)
-    fn split<'p>(
-        &self,
-        pcx: PatCtxt<'_, 'p, 'tcx>,
-        hir_id: Option<HirId>,
-    ) -> SmallVec<[Constructor<'tcx>; 1]> {
-        let ty = pcx.ty;
-
-        /// Represents a border between 2 integers. Because the intervals spanning borders
-        /// must be able to cover every integer, we need to be able to represent
-        /// 2^128 + 1 such borders.
-        #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
-        enum Border {
-            JustBefore(u128),
-            AfterMax,
-        }
-
-        // A function for extracting the borders of an integer interval.
-        fn range_borders(r: IntRange<'_>) -> impl Iterator<Item = Border> {
-            let (lo, hi) = r.range.into_inner();
-            let from = Border::JustBefore(lo);
-            let to = match hi.checked_add(1) {
-                Some(m) => Border::JustBefore(m),
-                None => Border::AfterMax,
-            };
-            vec![from, to].into_iter()
-        }
-
-        // Collect the span and range of all the intersecting ranges to lint on likely
-        // incorrect range patterns. (#63987)
-        let mut overlaps = vec![];
-        let row_len = pcx.matrix.patterns.get(0).map(|r| r.len()).unwrap_or(0);
-        // `borders` is the set of borders between equivalence classes: each equivalence
-        // class lies between 2 borders.
-        let row_borders = pcx
-            .matrix
-            .head_ctors(pcx.cx)
-            .filter_map(|ctor| ctor.as_int_range())
-            .filter_map(|range| {
-                let intersection = self.intersection(pcx.cx.tcx, &range);
-                let should_lint = self.suspicious_intersection(&range);
-                if let (Some(range), 1, true) = (&intersection, row_len, should_lint) {
-                    // FIXME: for now, only check for overlapping ranges on simple range
-                    // patterns. Otherwise with the current logic the following is detected
-                    // as overlapping:
-                    //   match (10u8, true) {
-                    //    (0 ..= 125, false) => {}
-                    //    (126 ..= 255, false) => {}
-                    //    (0 ..= 255, true) => {}
-                    //  }
-                    overlaps.push(range.clone());
-                }
-                intersection
-            })
-            .flat_map(range_borders);
-        let self_borders = range_borders(self.clone());
-        let mut borders: Vec<_> = row_borders.chain(self_borders).collect();
-        borders.sort_unstable();
-
-        self.lint_overlapping_patterns(pcx.cx.tcx, hir_id, ty, overlaps);
-
-        // We're going to iterate through every adjacent pair of borders, making sure that
-        // each represents an interval of nonnegative length, and convert each such
-        // interval into a constructor.
-        borders
-            .array_windows()
-            .filter_map(|&pair| match pair {
-                [Border::JustBefore(n), Border::JustBefore(m)] => {
-                    if n < m {
-                        Some(n..=(m - 1))
-                    } else {
-                        None
-                    }
-                }
-                [Border::JustBefore(n), Border::AfterMax] => Some(n..=u128::MAX),
-                [Border::AfterMax, _] => None,
-            })
-            .map(|range| IntRange { range, ty, span: pcx.span })
-            .map(IntRange)
-            .collect()
-    }
-
-    fn lint_overlapping_patterns(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        hir_id: Option<HirId>,
-        ty: Ty<'tcx>,
-        overlaps: Vec<IntRange<'tcx>>,
-    ) {
-        if let (true, Some(hir_id)) = (!overlaps.is_empty(), hir_id) {
-            tcx.struct_span_lint_hir(
-                lint::builtin::OVERLAPPING_PATTERNS,
-                hir_id,
-                self.span,
-                |lint| {
-                    let mut err = lint.build("multiple patterns covering the same range");
-                    err.span_label(self.span, "overlapping patterns");
-                    for int_range in overlaps {
-                        // Use the real type for user display of the ranges:
-                        err.span_label(
-                            int_range.span,
-                            &format!(
-                                "this range overlaps on `{}`",
-                                IntRange { range: int_range.range, ty, span: DUMMY_SP }.to_pat(tcx),
-                            ),
-                        );
-                    }
-                    err.emit();
-                },
-            );
-        }
-    }
-
-    /// See `Constructor::is_covered_by`
-    fn is_covered_by<'p>(&self, pcx: PatCtxt<'_, 'p, 'tcx>, other: &Self) -> bool {
-        if self.intersection(pcx.cx.tcx, other).is_some() {
-            // Constructor splitting should ensure that all intersections we encounter are actually
-            // inclusions.
-            assert!(self.is_subrange(other));
-            true
-        } else {
-            false
-        }
-    }
-}
-
-/// Ignore spans when comparing, they don't carry semantic information as they are only for lints.
-impl<'tcx> std::cmp::PartialEq for IntRange<'tcx> {
-    fn eq(&self, other: &Self) -> bool {
-        self.range == other.range && self.ty == other.ty
-    }
-}
-
-// A struct to compute a set of constructors equivalent to `all_ctors \ used_ctors`.
-#[derive(Debug)]
-struct MissingConstructors<'tcx> {
-    all_ctors: SmallVec<[Constructor<'tcx>; 1]>,
-    used_ctors: Vec<Constructor<'tcx>>,
-}
-
-impl<'tcx> MissingConstructors<'tcx> {
-    fn new<'p>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Self {
-        let used_ctors: Vec<Constructor<'_>> =
-            pcx.matrix.head_ctors(pcx.cx).cloned().filter(|c| !c.is_wildcard()).collect();
-        // Since `all_ctors` never contains wildcards, this won't recurse further.
-        let all_ctors =
-            all_constructors(pcx).into_iter().flat_map(|ctor| ctor.split(pcx, None)).collect();
-
-        MissingConstructors { all_ctors, used_ctors }
-    }
-
-    fn is_empty<'p>(&self, pcx: PatCtxt<'_, 'p, 'tcx>) -> bool {
-        self.iter(pcx).next().is_none()
-    }
-
-    /// Iterate over all_ctors \ used_ctors
-    fn iter<'a, 'p>(
-        &'a self,
-        pcx: PatCtxt<'a, 'p, 'tcx>,
-    ) -> impl Iterator<Item = &'a Constructor<'tcx>> + Captures<'p> {
-        self.all_ctors.iter().filter(move |ctor| !ctor.is_covered_by_any(pcx, &self.used_ctors))
-    }
-
-    /// List the patterns corresponding to the missing constructors. In some cases, instead of
-    /// listing all constructors of a given type, we prefer to simply report a wildcard.
-    fn report_patterns<'p>(&self, pcx: PatCtxt<'_, 'p, 'tcx>) -> SmallVec<[Pat<'tcx>; 1]> {
-        // There are 2 ways we can report a witness here.
-        // Commonly, we can report all the "free"
-        // constructors as witnesses, e.g., if we have:
-        //
-        // ```
-        //     enum Direction { N, S, E, W }
-        //     let Direction::N = ...;
-        // ```
-        //
-        // we can report 3 witnesses: `S`, `E`, and `W`.
-        //
-        // However, there is a case where we don't want
-        // to do this and instead report a single `_` witness:
-        // if the user didn't actually specify a constructor
-        // in this arm, e.g., in
-        //
-        // ```
-        //     let x: (Direction, Direction, bool) = ...;
-        //     let (_, _, false) = x;
-        // ```
-        //
-        // we don't want to show all 16 possible witnesses
-        // `(<direction-1>, <direction-2>, true)` - we are
-        // satisfied with `(_, _, true)`. In this case,
-        // `used_ctors` is empty.
-        // The exception is: if we are at the top-level, for example in an empty match, we
-        // sometimes prefer reporting the list of constructors instead of just `_`.
-        let report_when_all_missing = pcx.is_top_level && !IntRange::is_integral(pcx.ty);
-        if self.used_ctors.is_empty() && !report_when_all_missing {
-            // All constructors are unused. Report only a wildcard
-            // rather than each individual constructor.
-            smallvec![Pat::wildcard_from_ty(pcx.ty)]
-        } else {
-            // Construct for each missing constructor a "wild" version of this
-            // constructor, that matches everything that can be built with
-            // it. For example, if `ctor` is a `Constructor::Variant` for
-            // `Option::Some`, we get the pattern `Some(_)`.
-            self.iter(pcx)
-                .map(|missing_ctor| {
-                    let fields = Fields::wildcards(pcx, &missing_ctor);
-                    missing_ctor.apply(pcx, fields)
-                })
-                .collect()
-        }
-    }
-}
-
-/// Algorithm from <http://moscova.inria.fr/~maranget/papers/warn/index.html>.
-/// The algorithm from the paper has been modified to correctly handle empty
-/// types. The changes are:
-///   (0) We don't exit early if the pattern matrix has zero rows. We just
-///       continue to recurse over columns.
-///   (1) all_constructors will only return constructors that are statically
-///       possible. E.g., it will only return `Ok` for `Result<T, !>`.
-///
-/// This finds whether a (row) vector `v` of patterns is 'useful' in relation
-/// to a set of such vectors `m` - this is defined as there being a set of
-/// inputs that will match `v` but not any of the sets in `m`.
-///
-/// All the patterns at each column of the `matrix ++ v` matrix must have the same type.
-///
-/// This is used both for reachability checking (if a pattern isn't useful in
-/// relation to preceding patterns, it is not reachable) and exhaustiveness
-/// checking (if a wildcard pattern is useful in relation to a matrix, the
-/// matrix isn't exhaustive).
-///
-/// `is_under_guard` is used to inform if the pattern has a guard. If it
-/// has one it must not be inserted into the matrix. This shouldn't be
-/// relied on for soundness.
-fn is_useful<'p, 'tcx>(
-    cx: &MatchCheckCtxt<'p, 'tcx>,
-    matrix: &Matrix<'p, 'tcx>,
-    v: &PatStack<'p, 'tcx>,
-    witness_preference: WitnessPreference,
-    hir_id: HirId,
-    is_under_guard: bool,
-    is_top_level: bool,
-) -> Usefulness<'tcx> {
-    let Matrix { patterns: rows, .. } = matrix;
-    debug!("is_useful({:#?}, {:#?})", matrix, v);
-
-    // The base case. We are pattern-matching on () and the return value is
-    // based on whether our matrix has a row or not.
-    // NOTE: This could potentially be optimized by checking rows.is_empty()
-    // first and then, if v is non-empty, the return value is based on whether
-    // the type of the tuple we're checking is inhabited or not.
-    if v.is_empty() {
-        return if rows.is_empty() {
-            Usefulness::new_useful(witness_preference)
-        } else {
-            NotUseful
-        };
-    };
-
-    assert!(rows.iter().all(|r| r.len() == v.len()));
-
-    // If the first pattern is an or-pattern, expand it.
-    if let Some(vs) = v.expand_or_pat() {
-        // We expand the or pattern, trying each of its branches in turn and keeping careful track
-        // of possible unreachable sub-branches.
-        //
-        // If two branches have detected some unreachable sub-branches, we need to be careful. If
-        // they were detected in columns that are not the current one, we want to keep only the
-        // sub-branches that were unreachable in _all_ branches. Eg. in the following, the last
-        // `true` is unreachable in the second branch of the first or-pattern, but not otherwise.
-        // Therefore we don't want to lint that it is unreachable.
-        //
-        // ```
-        // match (true, true) {
-        //     (true, true) => {}
-        //     (false | true, false | true) => {}
-        // }
-        // ```
-        // If however the sub-branches come from the current column, they come from the inside of
-        // the current or-pattern, and we want to keep them all. Eg. in the following, we _do_ want
-        // to lint that the last `false` is unreachable.
-        // ```
-        // match None {
-        //     Some(false) => {}
-        //     None | Some(true | false) => {}
-        // }
-        // ```
-
-        let mut matrix = matrix.clone();
-        // We keep track of sub-branches separately depending on whether they come from this column
-        // or from others.
-        let mut unreachables_this_column: FxHashSet<Span> = FxHashSet::default();
-        let mut unreachables_other_columns: Vec<FxHashSet<Span>> = Vec::default();
-        // Whether at least one branch is reachable.
-        let mut any_is_useful = false;
-
-        for v in vs {
-            let res = is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false);
-            match res {
-                Useful(unreachables) => {
-                    if let Some((this_column, other_columns)) = unreachables.split_last() {
-                        // We keep the union of unreachables found in the first column.
-                        unreachables_this_column.extend(this_column);
-                        // We keep the intersection of unreachables found in other columns.
-                        if unreachables_other_columns.is_empty() {
-                            unreachables_other_columns = other_columns.to_vec();
-                        } else {
-                            unreachables_other_columns = unreachables_other_columns
-                                .into_iter()
-                                .zip(other_columns)
-                                .map(|(x, y)| x.intersection(&y).copied().collect())
-                                .collect();
-                        }
-                    }
-                    any_is_useful = true;
-                }
-                NotUseful => {
-                    unreachables_this_column.insert(v.head().span);
-                }
-                UsefulWithWitness(_) => bug!(
-                    "encountered or-pat in the expansion of `_` during exhaustiveness checking"
-                ),
-            }
-
-            // If pattern has a guard don't add it to the matrix.
-            if !is_under_guard {
-                // We push the already-seen patterns into the matrix in order to detect redundant
-                // branches like `Some(_) | Some(0)`.
-                matrix.push(v);
-            }
-        }
-
-        return if any_is_useful {
-            let mut unreachables = if unreachables_other_columns.is_empty() {
-                let n_columns = v.len();
-                (0..n_columns - 1).map(|_| FxHashSet::default()).collect()
-            } else {
-                unreachables_other_columns
-            };
-            unreachables.push(unreachables_this_column);
-            Useful(unreachables)
-        } else {
-            NotUseful
-        };
-    }
-
-    // FIXME(Nadrieril): Hack to work around type normalization issues (see #72476).
-    let ty = matrix.heads().next().map(|r| r.ty).unwrap_or(v.head().ty);
-    let pcx = PatCtxt { cx, matrix, ty, span: v.head().span, is_top_level };
-
-    debug!("is_useful_expand_first_col: ty={:#?}, expanding {:#?}", pcx.ty, v.head());
-
-    let ret = v
-        .head_ctor(cx)
-        .split(pcx, Some(hir_id))
-        .into_iter()
-        .map(|ctor| {
-            // We cache the result of `Fields::wildcards` because it is used a lot.
-            let ctor_wild_subpatterns = Fields::wildcards(pcx, &ctor);
-            let matrix = pcx.matrix.specialize_constructor(pcx, &ctor, &ctor_wild_subpatterns);
-            let v = v.pop_head_constructor(&ctor_wild_subpatterns);
-            let usefulness =
-                is_useful(pcx.cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false);
-            usefulness.apply_constructor(pcx, &ctor, &ctor_wild_subpatterns)
-        })
-        .find(|result| result.is_useful())
-        .unwrap_or(NotUseful);
-    debug!("is_useful::returns({:#?}, {:#?}) = {:?}", matrix, v, ret);
-    ret
-}
-
-/// Determines the constructor that the given pattern can be specialized to.
-/// Returns `None` in case of a catch-all, which can't be specialized.
-fn pat_constructor<'p, 'tcx>(
-    cx: &MatchCheckCtxt<'p, 'tcx>,
-    pat: &'p Pat<'tcx>,
-) -> Constructor<'tcx> {
-    match pat.kind.as_ref() {
-        PatKind::AscribeUserType { .. } => bug!(), // Handled by `expand_pattern`
-        PatKind::Binding { .. } | PatKind::Wild => Wildcard,
-        PatKind::Leaf { .. } | PatKind::Deref { .. } => Single,
-        &PatKind::Variant { adt_def, variant_index, .. } => {
-            Variant(adt_def.variants[variant_index].def_id)
-        }
-        PatKind::Constant { value } => {
-            if let Some(int_range) = IntRange::from_const(cx.tcx, cx.param_env, value, pat.span) {
-                IntRange(int_range)
-            } else {
-                match pat.ty.kind() {
-                    ty::Float(_) => FloatRange(value, value, RangeEnd::Included),
-                    // In `expand_pattern`, we convert string literals to `&CONST` patterns with
-                    // `CONST` a pattern of type `str`. In truth this contains a constant of type
-                    // `&str`.
-                    ty::Str => Str(value),
-                    // All constants that can be structurally matched have already been expanded
-                    // into the corresponding `Pat`s by `const_to_pat`. Constants that remain are
-                    // opaque.
-                    _ => Opaque,
-                }
-            }
-        }
-        &PatKind::Range(PatRange { lo, hi, end }) => {
-            let ty = lo.ty;
-            if let Some(int_range) = IntRange::from_range(
-                cx.tcx,
-                lo.eval_bits(cx.tcx, cx.param_env, lo.ty),
-                hi.eval_bits(cx.tcx, cx.param_env, hi.ty),
-                ty,
-                &end,
-                pat.span,
-            ) {
-                IntRange(int_range)
-            } else {
-                FloatRange(lo, hi, end)
-            }
-        }
-        PatKind::Array { prefix, slice, suffix } | PatKind::Slice { prefix, slice, suffix } => {
-            let array_len = match pat.ty.kind() {
-                ty::Array(_, length) => Some(length.eval_usize(cx.tcx, cx.param_env)),
-                ty::Slice(_) => None,
-                _ => span_bug!(pat.span, "bad ty {:?} for slice pattern", pat.ty),
-            };
-            let prefix = prefix.len() as u64;
-            let suffix = suffix.len() as u64;
-            let kind =
-                if slice.is_some() { VarLen(prefix, suffix) } else { FixedLen(prefix + suffix) };
-            Slice(Slice::new(array_len, kind))
-        }
-        PatKind::Or { .. } => bug!("Or-pattern should have been expanded earlier on."),
-    }
-}
-
-/// The arm of a match expression.
-#[derive(Clone, Copy)]
-crate struct MatchArm<'p, 'tcx> {
-    /// The pattern must have been lowered through `MatchVisitor::lower_pattern`.
-    crate pat: &'p super::Pat<'tcx>,
-    crate hir_id: HirId,
-    crate has_guard: bool,
-}
-
-/// The output of checking a match for exhaustiveness and arm reachability.
-crate struct UsefulnessReport<'p, 'tcx> {
-    /// For each arm of the input, whether that arm is reachable after the arms above it.
-    crate arm_usefulness: Vec<(MatchArm<'p, 'tcx>, Usefulness<'tcx>)>,
-    /// If the match is exhaustive, this is empty. If not, this contains witnesses for the lack of
-    /// exhaustiveness.
-    crate non_exhaustiveness_witnesses: Vec<super::Pat<'tcx>>,
-}
-
-/// The entrypoint for the usefulness algorithm. Computes whether a match is exhaustive and which
-/// of its arms are reachable.
-///
-/// Note: the input patterns must have been lowered through `MatchVisitor::lower_pattern`.
-crate fn compute_match_usefulness<'p, 'tcx>(
-    cx: &MatchCheckCtxt<'p, 'tcx>,
-    arms: &[MatchArm<'p, 'tcx>],
-    scrut_hir_id: HirId,
-    scrut_ty: Ty<'tcx>,
-) -> UsefulnessReport<'p, 'tcx> {
-    let mut matrix = Matrix::empty();
-    let arm_usefulness: Vec<_> = arms
-        .iter()
-        .copied()
-        .map(|arm| {
-            let v = PatStack::from_pattern(arm.pat);
-            let usefulness =
-                is_useful(cx, &matrix, &v, LeaveOutWitness, arm.hir_id, arm.has_guard, true);
-            if !arm.has_guard {
-                matrix.push(v);
-            }
-            (arm, usefulness)
-        })
-        .collect();
-
-    let wild_pattern = cx.pattern_arena.alloc(super::Pat::wildcard_from_ty(scrut_ty));
-    let v = PatStack::from_pattern(wild_pattern);
-    let usefulness = is_useful(cx, &matrix, &v, ConstructWitness, scrut_hir_id, false, true);
-    let non_exhaustiveness_witnesses = match usefulness {
-        NotUseful => vec![], // Wildcard pattern isn't useful, so the match is exhaustive.
-        UsefulWithWitness(pats) => {
-            if pats.is_empty() {
-                bug!("Exhaustiveness check returned no witnesses")
-            } else {
-                pats.into_iter().map(|w| w.single_pattern()).collect()
-            }
-        }
-        Useful(_) => bug!(),
-    };
-    UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses }
-}
index f9fe261bcee028644eab36372beab401338326e5..97edbd83b89cece6bcc8654445c785c376ee8dc3 100644 (file)
@@ -1,5 +1,5 @@
-use super::_match::Usefulness::*;
-use super::_match::{
+use super::usefulness::Usefulness::*;
+use super::usefulness::{
     compute_match_usefulness, expand_pattern, MatchArm, MatchCheckCtxt, UsefulnessReport,
 };
 use super::{PatCtxt, PatKind, PatternError};
diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
new file mode 100644 (file)
index 0000000..62b4468
--- /dev/null
@@ -0,0 +1,1394 @@
+//! This module provides functions to deconstruct and reconstruct patterns into a constructor
+//! applied to some fields. This is used by the `_match` module to compute pattern
+//! usefulness/exhaustiveness.
+use self::Constructor::*;
+use self::SliceKind::*;
+
+use super::compare_const_vals;
+use super::usefulness::{MatchCheckCtxt, PatCtxt};
+use super::{FieldPat, Pat, PatKind, PatRange};
+
+use rustc_data_structures::captures::Captures;
+use rustc_index::vec::Idx;
+
+use rustc_attr::{SignedInt, UnsignedInt};
+use rustc_hir::def_id::DefId;
+use rustc_hir::{HirId, RangeEnd};
+use rustc_middle::mir::interpret::ConstValue;
+use rustc_middle::mir::Field;
+use rustc_middle::ty::layout::IntegerExt;
+use rustc_middle::ty::{self, Const, Ty, TyCtxt};
+use rustc_session::lint;
+use rustc_span::{Span, DUMMY_SP};
+use rustc_target::abi::{Integer, Size, VariantIdx};
+
+use smallvec::{smallvec, SmallVec};
+use std::cmp::{self, max, min, Ordering};
+use std::iter::IntoIterator;
+use std::ops::RangeInclusive;
+
+/// An inclusive interval, used for precise integer exhaustiveness checking.
+/// `IntRange`s always store a contiguous range. This means that values are
+/// encoded such that `0` encodes the minimum value for the integer,
+/// regardless of the signedness.
+/// For example, the pattern `-128..=127i8` is encoded as `0..=255`.
+/// This makes comparisons and arithmetic on interval endpoints much more
+/// straightforward. See `signed_bias` for details.
+///
+/// `IntRange` is never used to encode an empty range or a "range" that wraps
+/// around the (offset) space: i.e., `range.lo <= range.hi`.
+#[derive(Clone, Debug)]
+pub(super) struct IntRange<'tcx> {
+    range: RangeInclusive<u128>,
+    ty: Ty<'tcx>,
+    span: Span,
+}
+
+impl<'tcx> IntRange<'tcx> {
+    #[inline]
+    fn is_integral(ty: Ty<'_>) -> bool {
+        matches!(ty.kind(), ty::Char | ty::Int(_) | ty::Uint(_) | ty::Bool)
+    }
+
+    fn is_singleton(&self) -> bool {
+        self.range.start() == self.range.end()
+    }
+
+    fn boundaries(&self) -> (u128, u128) {
+        (*self.range.start(), *self.range.end())
+    }
+
+    /// Don't treat `usize`/`isize` exhaustively unless the `precise_pointer_size_matching` feature
+    /// is enabled.
+    fn treat_exhaustively(&self, tcx: TyCtxt<'tcx>) -> bool {
+        !self.ty.is_ptr_sized_integral() || tcx.features().precise_pointer_size_matching
+    }
+
+    #[inline]
+    fn integral_size_and_signed_bias(tcx: TyCtxt<'tcx>, ty: Ty<'_>) -> Option<(Size, u128)> {
+        match *ty.kind() {
+            ty::Bool => Some((Size::from_bytes(1), 0)),
+            ty::Char => Some((Size::from_bytes(4), 0)),
+            ty::Int(ity) => {
+                let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
+                Some((size, 1u128 << (size.bits() as u128 - 1)))
+            }
+            ty::Uint(uty) => Some((Integer::from_attr(&tcx, UnsignedInt(uty)).size(), 0)),
+            _ => None,
+        }
+    }
+
+    #[inline]
+    fn from_const(
+        tcx: TyCtxt<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        value: &Const<'tcx>,
+        span: Span,
+    ) -> Option<IntRange<'tcx>> {
+        if let Some((target_size, bias)) = Self::integral_size_and_signed_bias(tcx, value.ty) {
+            let ty = value.ty;
+            let val = (|| {
+                if let ty::ConstKind::Value(ConstValue::Scalar(scalar)) = value.val {
+                    // For this specific pattern we can skip a lot of effort and go
+                    // straight to the result, after doing a bit of checking. (We
+                    // could remove this branch and just fall through, which
+                    // is more general but much slower.)
+                    if let Ok(bits) = scalar.to_bits_or_ptr(target_size, &tcx) {
+                        return Some(bits);
+                    }
+                }
+                // This is a more general form of the previous case.
+                value.try_eval_bits(tcx, param_env, ty)
+            })()?;
+            let val = val ^ bias;
+            Some(IntRange { range: val..=val, ty, span })
+        } else {
+            None
+        }
+    }
+
+    #[inline]
+    fn from_range(
+        tcx: TyCtxt<'tcx>,
+        lo: u128,
+        hi: u128,
+        ty: Ty<'tcx>,
+        end: &RangeEnd,
+        span: Span,
+    ) -> Option<IntRange<'tcx>> {
+        if Self::is_integral(ty) {
+            // Perform a shift if the underlying types are signed,
+            // which makes the interval arithmetic simpler.
+            let bias = IntRange::signed_bias(tcx, ty);
+            let (lo, hi) = (lo ^ bias, hi ^ bias);
+            let offset = (*end == RangeEnd::Excluded) as u128;
+            if lo > hi || (lo == hi && *end == RangeEnd::Excluded) {
+                // This should have been caught earlier by E0030.
+                bug!("malformed range pattern: {}..={}", lo, (hi - offset));
+            }
+            Some(IntRange { range: lo..=(hi - offset), ty, span })
+        } else {
+            None
+        }
+    }
+
+    // The return value of `signed_bias` should be XORed with an endpoint to encode/decode it.
+    fn signed_bias(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> u128 {
+        match *ty.kind() {
+            ty::Int(ity) => {
+                let bits = Integer::from_attr(&tcx, SignedInt(ity)).size().bits() as u128;
+                1u128 << (bits - 1)
+            }
+            _ => 0,
+        }
+    }
+
+    fn is_subrange(&self, other: &Self) -> bool {
+        other.range.start() <= self.range.start() && self.range.end() <= other.range.end()
+    }
+
+    fn intersection(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Option<Self> {
+        let ty = self.ty;
+        let (lo, hi) = self.boundaries();
+        let (other_lo, other_hi) = other.boundaries();
+        if self.treat_exhaustively(tcx) {
+            if lo <= other_hi && other_lo <= hi {
+                let span = other.span;
+                Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi), ty, span })
+            } else {
+                None
+            }
+        } else {
+            // If the range should not be treated exhaustively, fallback to checking for inclusion.
+            if self.is_subrange(other) { Some(self.clone()) } else { None }
+        }
+    }
+
+    fn suspicious_intersection(&self, other: &Self) -> bool {
+        // `false` in the following cases:
+        // 1     ----      // 1  ----------   // 1 ----        // 1       ----
+        // 2  ----------   // 2     ----      // 2       ----  // 2 ----
+        //
+        // The following are currently `false`, but could be `true` in the future (#64007):
+        // 1 ---------       // 1     ---------
+        // 2     ----------  // 2 ----------
+        //
+        // `true` in the following cases:
+        // 1 -------          // 1       -------
+        // 2       --------   // 2 -------
+        let (lo, hi) = self.boundaries();
+        let (other_lo, other_hi) = other.boundaries();
+        lo == other_hi || hi == other_lo
+    }
+
+    fn to_pat(&self, tcx: TyCtxt<'tcx>) -> Pat<'tcx> {
+        let (lo, hi) = self.boundaries();
+
+        let bias = IntRange::signed_bias(tcx, self.ty);
+        let (lo, hi) = (lo ^ bias, hi ^ bias);
+
+        let ty = ty::ParamEnv::empty().and(self.ty);
+        let lo_const = ty::Const::from_bits(tcx, lo, ty);
+        let hi_const = ty::Const::from_bits(tcx, hi, ty);
+
+        let kind = if lo == hi {
+            PatKind::Constant { value: lo_const }
+        } else {
+            PatKind::Range(PatRange { lo: lo_const, hi: hi_const, end: RangeEnd::Included })
+        };
+
+        // This is a brand new pattern, so we don't reuse `self.span`.
+        Pat { ty: self.ty, span: DUMMY_SP, kind: Box::new(kind) }
+    }
+
+    /// For exhaustive integer matching, some constructors are grouped within other constructors
+    /// (namely integer typed values are grouped within ranges). However, when specialising these
+    /// constructors, we want to be specialising for the underlying constructors (the integers), not
+    /// the groups (the ranges). Thus we need to split the groups up. Splitting them up naïvely would
+    /// mean creating a separate constructor for every single value in the range, which is clearly
+    /// impractical. However, observe that for some ranges of integers, the specialisation will be
+    /// identical across all values in that range (i.e., there are equivalence classes of ranges of
+    /// constructors based on their `U(S(c, P), S(c, p))` outcome). These classes are grouped by
+    /// the patterns that apply to them (in the matrix `P`). We can split the range whenever the
+    /// patterns that apply to that range (specifically: the patterns that *intersect* with that range)
+    /// change.
+    /// Our solution, therefore, is to split the range constructor into subranges at every single point
+    /// the group of intersecting patterns changes (using the method described below).
+    /// And voilà! We're testing precisely those ranges that we need to, without any exhaustive matching
+    /// on actual integers. The nice thing about this is that the number of subranges is linear in the
+    /// number of rows in the matrix (i.e., the number of cases in the `match` statement), so we don't
+    /// need to be worried about matching over gargantuan ranges.
+    ///
+    /// Essentially, given the first column of a matrix representing ranges, looking like the following:
+    ///
+    /// |------|  |----------| |-------|    ||
+    ///    |-------| |-------|            |----| ||
+    ///       |---------|
+    ///
+    /// We split the ranges up into equivalence classes so the ranges are no longer overlapping:
+    ///
+    /// |--|--|||-||||--||---|||-------|  |-|||| ||
+    ///
+    /// The logic for determining how to split the ranges is fairly straightforward: we calculate
+    /// boundaries for each interval range, sort them, then create constructors for each new interval
+    /// between every pair of boundary points. (This essentially sums up to performing the intuitive
+    /// merging operation depicted above.)
+    fn split<'p>(
+        &self,
+        pcx: PatCtxt<'_, 'p, 'tcx>,
+        hir_id: Option<HirId>,
+    ) -> SmallVec<[Constructor<'tcx>; 1]> {
+        let ty = pcx.ty;
+
+        /// Represents a border between 2 integers. Because the intervals spanning borders
+        /// must be able to cover every integer, we need to be able to represent
+        /// 2^128 + 1 such borders.
+        #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
+        enum Border {
+            JustBefore(u128),
+            AfterMax,
+        }
+
+        // A function for extracting the borders of an integer interval.
+        fn range_borders(r: IntRange<'_>) -> impl Iterator<Item = Border> {
+            let (lo, hi) = r.range.into_inner();
+            let from = Border::JustBefore(lo);
+            let to = match hi.checked_add(1) {
+                Some(m) => Border::JustBefore(m),
+                None => Border::AfterMax,
+            };
+            vec![from, to].into_iter()
+        }
+
+        // Collect the span and range of all the intersecting ranges to lint on likely
+        // incorrect range patterns. (#63987)
+        let mut overlaps = vec![];
+        let row_len = pcx.matrix.column_count().unwrap_or(0);
+        // `borders` is the set of borders between equivalence classes: each equivalence
+        // class lies between 2 borders.
+        let row_borders = pcx
+            .matrix
+            .head_ctors(pcx.cx)
+            .filter_map(|ctor| ctor.as_int_range())
+            .filter_map(|range| {
+                let intersection = self.intersection(pcx.cx.tcx, &range);
+                let should_lint = self.suspicious_intersection(&range);
+                if let (Some(range), 1, true) = (&intersection, row_len, should_lint) {
+                    // FIXME: for now, only check for overlapping ranges on simple range
+                    // patterns. Otherwise with the current logic the following is detected
+                    // as overlapping:
+                    //   match (10u8, true) {
+                    //    (0 ..= 125, false) => {}
+                    //    (126 ..= 255, false) => {}
+                    //    (0 ..= 255, true) => {}
+                    //  }
+                    overlaps.push(range.clone());
+                }
+                intersection
+            })
+            .flat_map(range_borders);
+        let self_borders = range_borders(self.clone());
+        let mut borders: Vec<_> = row_borders.chain(self_borders).collect();
+        borders.sort_unstable();
+
+        self.lint_overlapping_patterns(pcx.cx.tcx, hir_id, ty, overlaps);
+
+        // We're going to iterate through every adjacent pair of borders, making sure that
+        // each represents an interval of nonnegative length, and convert each such
+        // interval into a constructor.
+        borders
+            .array_windows()
+            .filter_map(|&pair| match pair {
+                [Border::JustBefore(n), Border::JustBefore(m)] => {
+                    if n < m {
+                        Some(n..=(m - 1))
+                    } else {
+                        None
+                    }
+                }
+                [Border::JustBefore(n), Border::AfterMax] => Some(n..=u128::MAX),
+                [Border::AfterMax, _] => None,
+            })
+            .map(|range| IntRange { range, ty, span: pcx.span })
+            .map(IntRange)
+            .collect()
+    }
+
+    fn lint_overlapping_patterns(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        hir_id: Option<HirId>,
+        ty: Ty<'tcx>,
+        overlaps: Vec<IntRange<'tcx>>,
+    ) {
+        if let (true, Some(hir_id)) = (!overlaps.is_empty(), hir_id) {
+            tcx.struct_span_lint_hir(
+                lint::builtin::OVERLAPPING_PATTERNS,
+                hir_id,
+                self.span,
+                |lint| {
+                    let mut err = lint.build("multiple patterns covering the same range");
+                    err.span_label(self.span, "overlapping patterns");
+                    for int_range in overlaps {
+                        // Use the real type for user display of the ranges:
+                        err.span_label(
+                            int_range.span,
+                            &format!(
+                                "this range overlaps on `{}`",
+                                IntRange { range: int_range.range, ty, span: DUMMY_SP }.to_pat(tcx),
+                            ),
+                        );
+                    }
+                    err.emit();
+                },
+            );
+        }
+    }
+
+    /// See `Constructor::is_covered_by`
+    fn is_covered_by<'p>(&self, pcx: PatCtxt<'_, 'p, 'tcx>, other: &Self) -> bool {
+        if self.intersection(pcx.cx.tcx, other).is_some() {
+            // Constructor splitting should ensure that all intersections we encounter are actually
+            // inclusions.
+            assert!(self.is_subrange(other));
+            true
+        } else {
+            false
+        }
+    }
+}
+
+/// Ignore spans when comparing, they don't carry semantic information as they are only for lints.
+impl<'tcx> std::cmp::PartialEq for IntRange<'tcx> {
+    fn eq(&self, other: &Self) -> bool {
+        self.range == other.range && self.ty == other.ty
+    }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+enum SliceKind {
+    /// Patterns of length `n` (`[x, y]`).
+    FixedLen(u64),
+    /// Patterns using the `..` notation (`[x, .., y]`).
+    /// Captures any array constructor of `length >= i + j`.
+    /// In the case where `array_len` is `Some(_)`,
+    /// this indicates that we only care about the first `i` and the last `j` values of the array,
+    /// and everything in between is a wildcard `_`.
+    VarLen(u64, u64),
+}
+
+impl SliceKind {
+    fn arity(self) -> u64 {
+        match self {
+            FixedLen(length) => length,
+            VarLen(prefix, suffix) => prefix + suffix,
+        }
+    }
+
+    /// Whether this pattern includes patterns of length `other_len`.
+    fn covers_length(self, other_len: u64) -> bool {
+        match self {
+            FixedLen(len) => len == other_len,
+            VarLen(prefix, suffix) => prefix + suffix <= other_len,
+        }
+    }
+}
+
+/// A constructor for array and slice patterns.
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub(super) struct Slice {
+    /// `None` if the matched value is a slice, `Some(n)` if it is an array of size `n`.
+    array_len: Option<u64>,
+    /// The kind of pattern it is: fixed-length `[x, y]` or variable length `[x, .., y]`.
+    kind: SliceKind,
+}
+
+impl Slice {
+    fn new(array_len: Option<u64>, kind: SliceKind) -> Self {
+        let kind = match (array_len, kind) {
+            // If the middle `..` is empty, we effectively have a fixed-length pattern.
+            (Some(len), VarLen(prefix, suffix)) if prefix + suffix >= len => FixedLen(len),
+            _ => kind,
+        };
+        Slice { array_len, kind }
+    }
+
+    fn arity(self) -> u64 {
+        self.kind.arity()
+    }
+
+    /// The exhaustiveness-checking paper does not include any details on
+    /// checking variable-length slice patterns. However, they may be
+    /// matched by an infinite collection of fixed-length array patterns.
+    ///
+    /// Checking the infinite set directly would take an infinite amount
+    /// of time. However, it turns out that for each finite set of
+    /// patterns `P`, all sufficiently large array lengths are equivalent:
+    ///
+    /// Each slice `s` with a "sufficiently-large" length `l ≥ L` that applies
+    /// to exactly the subset `Pₜ` of `P` can be transformed to a slice
+    /// `sₘ` for each sufficiently-large length `m` that applies to exactly
+    /// the same subset of `P`.
+    ///
+    /// Because of that, each witness for reachability-checking of one
+    /// of the sufficiently-large lengths can be transformed to an
+    /// equally-valid witness of any other length, so we only have
+    /// to check slices of the "minimal sufficiently-large length"
+    /// and less.
+    ///
+    /// Note that the fact that there is a *single* `sₘ` for each `m`
+    /// not depending on the specific pattern in `P` is important: if
+    /// you look at the pair of patterns
+    ///     `[true, ..]`
+    ///     `[.., false]`
+    /// Then any slice of length ≥1 that matches one of these two
+    /// patterns can be trivially turned to a slice of any
+    /// other length ≥1 that matches them and vice-versa,
+    /// but the slice of length 2 `[false, true]` that matches neither
+    /// of these patterns can't be turned to a slice from length 1 that
+    /// matches neither of these patterns, so we have to consider
+    /// slices from length 2 there.
+    ///
+    /// Now, to see that that length exists and find it, observe that slice
+    /// patterns are either "fixed-length" patterns (`[_, _, _]`) or
+    /// "variable-length" patterns (`[_, .., _]`).
+    ///
+    /// For fixed-length patterns, all slices with lengths *longer* than
+    /// the pattern's length have the same outcome (of not matching), so
+    /// as long as `L` is greater than the pattern's length we can pick
+    /// any `sₘ` from that length and get the same result.
+    ///
+    /// For variable-length patterns, the situation is more complicated,
+    /// because as seen above the precise value of `sₘ` matters.
+    ///
+    /// However, for each variable-length pattern `p` with a prefix of length
+    /// `plₚ` and suffix of length `slₚ`, only the first `plₚ` and the last
+    /// `slₚ` elements are examined.
+    ///
+    /// Therefore, as long as `L` is positive (to avoid concerns about empty
+    /// types), all elements after the maximum prefix length and before
+    /// the maximum suffix length are not examined by any variable-length
+    /// pattern, and therefore can be added/removed without affecting
+    /// them - creating equivalent patterns from any sufficiently-large
+    /// length.
+    ///
+    /// Of course, if fixed-length patterns exist, we must be sure
+    /// that our length is large enough to miss them all, so
+    /// we can pick `L = max(max(FIXED_LEN)+1, max(PREFIX_LEN) + max(SUFFIX_LEN))`
+    ///
+    /// for example, with the above pair of patterns, all elements
+    /// but the first and last can be added/removed, so any
+    /// witness of length ≥2 (say, `[false, false, true]`) can be
+    /// turned to a witness from any other length ≥2.
+    fn split<'p, 'tcx>(self, pcx: PatCtxt<'_, 'p, 'tcx>) -> SmallVec<[Constructor<'tcx>; 1]> {
+        let (self_prefix, self_suffix) = match self.kind {
+            VarLen(self_prefix, self_suffix) => (self_prefix, self_suffix),
+            _ => return smallvec![Slice(self)],
+        };
+
+        let head_ctors = pcx.matrix.head_ctors(pcx.cx).filter(|c| !c.is_wildcard());
+
+        let mut max_prefix_len = self_prefix;
+        let mut max_suffix_len = self_suffix;
+        let mut max_fixed_len = 0;
+
+        for ctor in head_ctors {
+            if let Slice(slice) = ctor {
+                match slice.kind {
+                    FixedLen(len) => {
+                        max_fixed_len = cmp::max(max_fixed_len, len);
+                    }
+                    VarLen(prefix, suffix) => {
+                        max_prefix_len = cmp::max(max_prefix_len, prefix);
+                        max_suffix_len = cmp::max(max_suffix_len, suffix);
+                    }
+                }
+            } else {
+                bug!("unexpected ctor for slice type: {:?}", ctor);
+            }
+        }
+
+        // For diagnostics, we keep the prefix and suffix lengths separate, so in the case
+        // where `max_fixed_len + 1` is the largest, we adapt `max_prefix_len` accordingly,
+        // so that `L = max_prefix_len + max_suffix_len`.
+        if max_fixed_len + 1 >= max_prefix_len + max_suffix_len {
+            // The subtraction can't overflow thanks to the above check.
+            // The new `max_prefix_len` is also guaranteed to be larger than its previous
+            // value.
+            max_prefix_len = max_fixed_len + 1 - max_suffix_len;
+        }
+
+        let final_slice = VarLen(max_prefix_len, max_suffix_len);
+        let final_slice = Slice::new(self.array_len, final_slice);
+        match self.array_len {
+            Some(_) => smallvec![Slice(final_slice)],
+            None => {
+                // `self` originally covered the range `(self.arity()..infinity)`. We split that
+                // range into two: lengths smaller than `final_slice.arity()` are treated
+                // independently as fixed-lengths slices, and lengths above are captured by
+                // `final_slice`.
+                let smaller_lengths = (self.arity()..final_slice.arity()).map(FixedLen);
+                smaller_lengths
+                    .map(|kind| Slice::new(self.array_len, kind))
+                    .chain(Some(final_slice))
+                    .map(Slice)
+                    .collect()
+            }
+        }
+    }
+
+    /// See `Constructor::is_covered_by`
+    fn is_covered_by(self, other: Self) -> bool {
+        other.kind.covers_length(self.arity())
+    }
+}
+
+/// A value can be decomposed into a constructor applied to some fields. This struct represents
+/// the constructor. See also `Fields`.
+///
+/// `pat_constructor` retrieves the constructor corresponding to a pattern.
+/// `specialize_constructor` returns the list of fields corresponding to a pattern, given a
+/// constructor. `Constructor::apply` reconstructs the pattern from a pair of `Constructor` and
+/// `Fields`.
+#[derive(Clone, Debug, PartialEq)]
+pub(super) enum Constructor<'tcx> {
+    /// The constructor for patterns that have a single constructor, like tuples, struct patterns
+    /// and fixed-length arrays.
+    Single,
+    /// Enum variants.
+    Variant(DefId),
+    /// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
+    IntRange(IntRange<'tcx>),
+    /// Ranges of floating-point literal values (`2.0..=5.2`).
+    FloatRange(&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>, RangeEnd),
+    /// String literals. Strings are not quite the same as `&[u8]` so we treat them separately.
+    Str(&'tcx ty::Const<'tcx>),
+    /// Array and slice patterns.
+    Slice(Slice),
+    /// Constants that must not be matched structurally. They are treated as black
+    /// boxes for the purposes of exhaustiveness: we must not inspect them, and they
+    /// don't count towards making a match exhaustive.
+    Opaque,
+    /// Fake extra constructor for enums that aren't allowed to be matched exhaustively. Also used
+    /// for those types for which we cannot list constructors explicitly, like `f64` and `str`.
+    NonExhaustive,
+    /// Wildcard pattern.
+    Wildcard,
+}
+
+impl<'tcx> Constructor<'tcx> {
+    pub(super) fn is_wildcard(&self) -> bool {
+        matches!(self, Wildcard)
+    }
+
+    fn as_int_range(&self) -> Option<&IntRange<'tcx>> {
+        match self {
+            IntRange(range) => Some(range),
+            _ => None,
+        }
+    }
+
+    fn as_slice(&self) -> Option<Slice> {
+        match self {
+            Slice(slice) => Some(*slice),
+            _ => None,
+        }
+    }
+
+    fn variant_index_for_adt(&self, adt: &'tcx ty::AdtDef) -> VariantIdx {
+        match *self {
+            Variant(id) => adt.variant_index_with_id(id),
+            Single => {
+                assert!(!adt.is_enum());
+                VariantIdx::new(0)
+            }
+            _ => bug!("bad constructor {:?} for adt {:?}", self, adt),
+        }
+    }
+
+    /// Determines the constructor that the given pattern can be specialized to.
+    pub(super) fn from_pat<'p>(cx: &MatchCheckCtxt<'p, 'tcx>, pat: &'p Pat<'tcx>) -> Self {
+        match pat.kind.as_ref() {
+            PatKind::AscribeUserType { .. } => bug!(), // Handled by `expand_pattern`
+            PatKind::Binding { .. } | PatKind::Wild => Wildcard,
+            PatKind::Leaf { .. } | PatKind::Deref { .. } => Single,
+            &PatKind::Variant { adt_def, variant_index, .. } => {
+                Variant(adt_def.variants[variant_index].def_id)
+            }
+            PatKind::Constant { value } => {
+                if let Some(int_range) = IntRange::from_const(cx.tcx, cx.param_env, value, pat.span)
+                {
+                    IntRange(int_range)
+                } else {
+                    match pat.ty.kind() {
+                        ty::Float(_) => FloatRange(value, value, RangeEnd::Included),
+                        // In `expand_pattern`, we convert string literals to `&CONST` patterns with
+                        // `CONST` a pattern of type `str`. In truth this contains a constant of type
+                        // `&str`.
+                        ty::Str => Str(value),
+                        // All constants that can be structurally matched have already been expanded
+                        // into the corresponding `Pat`s by `const_to_pat`. Constants that remain are
+                        // opaque.
+                        _ => Opaque,
+                    }
+                }
+            }
+            &PatKind::Range(PatRange { lo, hi, end }) => {
+                let ty = lo.ty;
+                if let Some(int_range) = IntRange::from_range(
+                    cx.tcx,
+                    lo.eval_bits(cx.tcx, cx.param_env, lo.ty),
+                    hi.eval_bits(cx.tcx, cx.param_env, hi.ty),
+                    ty,
+                    &end,
+                    pat.span,
+                ) {
+                    IntRange(int_range)
+                } else {
+                    FloatRange(lo, hi, end)
+                }
+            }
+            PatKind::Array { prefix, slice, suffix } | PatKind::Slice { prefix, slice, suffix } => {
+                let array_len = match pat.ty.kind() {
+                    ty::Array(_, length) => Some(length.eval_usize(cx.tcx, cx.param_env)),
+                    ty::Slice(_) => None,
+                    _ => span_bug!(pat.span, "bad ty {:?} for slice pattern", pat.ty),
+                };
+                let prefix = prefix.len() as u64;
+                let suffix = suffix.len() as u64;
+                let kind = if slice.is_some() {
+                    VarLen(prefix, suffix)
+                } else {
+                    FixedLen(prefix + suffix)
+                };
+                Slice(Slice::new(array_len, kind))
+            }
+            PatKind::Or { .. } => bug!("Or-pattern should have been expanded earlier on."),
+        }
+    }
+
+    /// Some constructors (namely `Wildcard`, `IntRange` and `Slice`) actually stand for a set of actual
+    /// constructors (like variants, integers or fixed-sized slices). When specializing for these
+    /// constructors, we want to be specialising for the actual underlying constructors.
+    /// Naively, we would simply return the list of constructors they correspond to. We instead are
+    /// more clever: if there are constructors that we know will behave the same wrt the current
+    /// matrix, we keep them grouped. For example, all slices of a sufficiently large length
+    /// will either be all useful or all non-useful with a given matrix.
+    ///
+    /// See the branches for details on how the splitting is done.
+    ///
+    /// This function may discard some irrelevant constructors if this preserves behavior and
+    /// diagnostics. Eg. for the `_` case, we ignore the constructors already present in the
+    /// matrix, unless all of them are.
+    ///
+    /// `hir_id` is `None` when we're evaluating the wildcard pattern. In that case we do not want
+    /// to lint for overlapping ranges.
+    pub(super) fn split<'p>(
+        &self,
+        pcx: PatCtxt<'_, 'p, 'tcx>,
+        hir_id: Option<HirId>,
+    ) -> SmallVec<[Self; 1]> {
+        debug!("Constructor::split({:#?}, {:#?})", self, pcx.matrix);
+
+        match self {
+            Wildcard => Constructor::split_wildcard(pcx),
+            // Fast-track if the range is trivial. In particular, we don't do the overlapping
+            // ranges check.
+            IntRange(ctor_range)
+                if ctor_range.treat_exhaustively(pcx.cx.tcx) && !ctor_range.is_singleton() =>
+            {
+                ctor_range.split(pcx, hir_id)
+            }
+            Slice(slice @ Slice { kind: VarLen(..), .. }) => slice.split(pcx),
+            // Any other constructor can be used unchanged.
+            _ => smallvec![self.clone()],
+        }
+    }
+
+    /// For wildcards, there are two groups of constructors: there are the constructors actually
+    /// present in the matrix (`head_ctors`), and the constructors not present (`missing_ctors`).
+    /// Two constructors that are not in the matrix will either both be caught (by a wildcard), or
+    /// both not be caught. Therefore we can keep the missing constructors grouped together.
+    fn split_wildcard<'p>(pcx: PatCtxt<'_, 'p, 'tcx>) -> SmallVec<[Self; 1]> {
+        // Missing constructors are those that are not matched by any non-wildcard patterns in the
+        // current column. We only fully construct them on-demand, because they're rarely used and
+        // can be big.
+        let missing_ctors = MissingConstructors::new(pcx);
+        if missing_ctors.is_empty(pcx) {
+            // All the constructors are present in the matrix, so we just go through them all.
+            // We must also split them first.
+            missing_ctors.all_ctors
+        } else {
+            // Some constructors are missing, thus we can specialize with the wildcard constructor,
+            // which will stand for those constructors that are missing, and behaves like any of
+            // them.
+            smallvec![Wildcard]
+        }
+    }
+
+    /// Returns whether `self` is covered by `other`, i.e. whether `self` is a subset of `other`.
+    /// For the simple cases, this is simply checking for equality. For the "grouped" constructors,
+    /// this checks for inclusion.
+    pub(super) fn is_covered_by<'p>(&self, pcx: PatCtxt<'_, 'p, 'tcx>, other: &Self) -> bool {
+        // This must be kept in sync with `is_covered_by_any`.
+        match (self, other) {
+            // Wildcards cover anything
+            (_, Wildcard) => true,
+            // Wildcards are only covered by wildcards
+            (Wildcard, _) => false,
+
+            (Single, Single) => true,
+            (Variant(self_id), Variant(other_id)) => self_id == other_id,
+
+            (IntRange(self_range), IntRange(other_range)) => {
+                self_range.is_covered_by(pcx, other_range)
+            }
+            (
+                FloatRange(self_from, self_to, self_end),
+                FloatRange(other_from, other_to, other_end),
+            ) => {
+                match (
+                    compare_const_vals(pcx.cx.tcx, self_to, other_to, pcx.cx.param_env, pcx.ty),
+                    compare_const_vals(pcx.cx.tcx, self_from, other_from, pcx.cx.param_env, pcx.ty),
+                ) {
+                    (Some(to), Some(from)) => {
+                        (from == Ordering::Greater || from == Ordering::Equal)
+                            && (to == Ordering::Less
+                                || (other_end == self_end && to == Ordering::Equal))
+                    }
+                    _ => false,
+                }
+            }
+            (Str(self_val), Str(other_val)) => {
+                // FIXME: there's probably a more direct way of comparing for equality
+                match compare_const_vals(pcx.cx.tcx, self_val, other_val, pcx.cx.param_env, pcx.ty)
+                {
+                    Some(comparison) => comparison == Ordering::Equal,
+                    None => false,
+                }
+            }
+            (Slice(self_slice), Slice(other_slice)) => self_slice.is_covered_by(*other_slice),
+
+            // We are trying to inspect an opaque constant. Thus we skip the row.
+            (Opaque, _) | (_, Opaque) => false,
+            // Only a wildcard pattern can match the special extra constructor.
+            (NonExhaustive, _) => false,
+
+            _ => span_bug!(
+                pcx.span,
+                "trying to compare incompatible constructors {:?} and {:?}",
+                self,
+                other
+            ),
+        }
+    }
+
+    /// Faster version of `is_covered_by` when applied to many constructors. `used_ctors` is
+    /// assumed to be built from `matrix.head_ctors()` with wildcards filtered out, and `self` is
+    /// assumed to have been split from a wildcard.
+    fn is_covered_by_any<'p>(
+        &self,
+        pcx: PatCtxt<'_, 'p, 'tcx>,
+        used_ctors: &[Constructor<'tcx>],
+    ) -> bool {
+        if used_ctors.is_empty() {
+            return false;
+        }
+
+        // This must be kept in sync with `is_covered_by`.
+        match self {
+            // If `self` is `Single`, `used_ctors` cannot contain anything else than `Single`s.
+            Single => !used_ctors.is_empty(),
+            Variant(_) => used_ctors.iter().any(|c| c == self),
+            IntRange(range) => used_ctors
+                .iter()
+                .filter_map(|c| c.as_int_range())
+                .any(|other| range.is_covered_by(pcx, other)),
+            Slice(slice) => used_ctors
+                .iter()
+                .filter_map(|c| c.as_slice())
+                .any(|other| slice.is_covered_by(other)),
+            // This constructor is never covered by anything else
+            NonExhaustive => false,
+            Str(..) | FloatRange(..) | Opaque | Wildcard => {
+                bug!("found unexpected ctor in all_ctors: {:?}", self)
+            }
+        }
+    }
+}
+
+/// This determines the set of all possible constructors of a pattern matching
+/// values of type `left_ty`. For vectors, this would normally be an infinite set
+/// but is instead bounded by the maximum fixed length of slice patterns in
+/// the column of patterns being analyzed.
+///
+/// We make sure to omit constructors that are statically impossible. E.g., for
+/// `Option<!>`, we do not include `Some(_)` in the returned list of constructors.
+/// Invariant: this returns an empty `Vec` if and only if the type is uninhabited (as determined by
+/// `cx.is_uninhabited()`).
+fn all_constructors<'p, 'tcx>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Vec<Constructor<'tcx>> {
+    debug!("all_constructors({:?})", pcx.ty);
+    let cx = pcx.cx;
+    let make_range = |start, end| {
+        IntRange(
+            // `unwrap()` is ok because we know the type is an integer.
+            IntRange::from_range(cx.tcx, start, end, pcx.ty, &RangeEnd::Included, pcx.span)
+                .unwrap(),
+        )
+    };
+    match pcx.ty.kind() {
+        ty::Bool => vec![make_range(0, 1)],
+        ty::Array(sub_ty, len) if len.try_eval_usize(cx.tcx, cx.param_env).is_some() => {
+            let len = len.eval_usize(cx.tcx, cx.param_env);
+            if len != 0 && cx.is_uninhabited(sub_ty) {
+                vec![]
+            } else {
+                vec![Slice(Slice::new(Some(len), VarLen(0, 0)))]
+            }
+        }
+        // Treat arrays of a constant but unknown length like slices.
+        ty::Array(sub_ty, _) | ty::Slice(sub_ty) => {
+            let kind = if cx.is_uninhabited(sub_ty) { FixedLen(0) } else { VarLen(0, 0) };
+            vec![Slice(Slice::new(None, kind))]
+        }
+        ty::Adt(def, substs) if def.is_enum() => {
+            // If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an
+            // additional "unknown" constructor.
+            // There is no point in enumerating all possible variants, because the user can't
+            // actually match against them all themselves. So we always return only the fictitious
+            // constructor.
+            // E.g., in an example like:
+            //
+            // ```
+            //     let err: io::ErrorKind = ...;
+            //     match err {
+            //         io::ErrorKind::NotFound => {},
+            //     }
+            // ```
+            //
+            // we don't want to show every possible IO error, but instead have only `_` as the
+            // witness.
+            let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive_enum(pcx.ty);
+
+            // If `exhaustive_patterns` is disabled and our scrutinee is an empty enum, we treat it
+            // as though it had an "unknown" constructor to avoid exposing its emptiness. The
+            // exception is if the pattern is at the top level, because we want empty matches to be
+            // considered exhaustive.
+            let is_secretly_empty = def.variants.is_empty()
+                && !cx.tcx.features().exhaustive_patterns
+                && !pcx.is_top_level;
+
+            if is_secretly_empty || is_declared_nonexhaustive {
+                vec![NonExhaustive]
+            } else if cx.tcx.features().exhaustive_patterns {
+                // If `exhaustive_patterns` is enabled, we exclude variants known to be
+                // uninhabited.
+                def.variants
+                    .iter()
+                    .filter(|v| {
+                        !v.uninhabited_from(cx.tcx, substs, def.adt_kind(), cx.param_env)
+                            .contains(cx.tcx, cx.module)
+                    })
+                    .map(|v| Variant(v.def_id))
+                    .collect()
+            } else {
+                def.variants.iter().map(|v| Variant(v.def_id)).collect()
+            }
+        }
+        ty::Char => {
+            vec![
+                // The valid Unicode Scalar Value ranges.
+                make_range('\u{0000}' as u128, '\u{D7FF}' as u128),
+                make_range('\u{E000}' as u128, '\u{10FFFF}' as u128),
+            ]
+        }
+        ty::Int(_) | ty::Uint(_)
+            if pcx.ty.is_ptr_sized_integral()
+                && !cx.tcx.features().precise_pointer_size_matching =>
+        {
+            // `usize`/`isize` are not allowed to be matched exhaustively unless the
+            // `precise_pointer_size_matching` feature is enabled. So we treat those types like
+            // `#[non_exhaustive]` enums by returning a special unmatcheable constructor.
+            vec![NonExhaustive]
+        }
+        &ty::Int(ity) => {
+            let bits = Integer::from_attr(&cx.tcx, SignedInt(ity)).size().bits() as u128;
+            let min = 1u128 << (bits - 1);
+            let max = min - 1;
+            vec![make_range(min, max)]
+        }
+        &ty::Uint(uty) => {
+            let size = Integer::from_attr(&cx.tcx, UnsignedInt(uty)).size();
+            let max = size.truncate(u128::MAX);
+            vec![make_range(0, max)]
+        }
+        // If `exhaustive_patterns` is disabled and our scrutinee is the never type, we cannot
+        // expose its emptiness. The exception is if the pattern is at the top level, because we
+        // want empty matches to be considered exhaustive.
+        ty::Never if !cx.tcx.features().exhaustive_patterns && !pcx.is_top_level => {
+            vec![NonExhaustive]
+        }
+        ty::Never => vec![],
+        _ if cx.is_uninhabited(pcx.ty) => vec![],
+        ty::Adt(..) | ty::Tuple(..) | ty::Ref(..) => vec![Single],
+        // This type is one for which we cannot list constructors, like `str` or `f64`.
+        _ => vec![NonExhaustive],
+    }
+}
+
+// A struct to compute a set of constructors equivalent to `all_ctors \ used_ctors`.
+#[derive(Debug)]
+pub(super) struct MissingConstructors<'tcx> {
+    all_ctors: SmallVec<[Constructor<'tcx>; 1]>,
+    used_ctors: Vec<Constructor<'tcx>>,
+}
+
+impl<'tcx> MissingConstructors<'tcx> {
+    pub(super) fn new<'p>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Self {
+        let used_ctors: Vec<Constructor<'_>> =
+            pcx.matrix.head_ctors(pcx.cx).cloned().filter(|c| !c.is_wildcard()).collect();
+        // Since `all_ctors` never contains wildcards, this won't recurse further.
+        let all_ctors =
+            all_constructors(pcx).into_iter().flat_map(|ctor| ctor.split(pcx, None)).collect();
+
+        MissingConstructors { all_ctors, used_ctors }
+    }
+
+    fn is_empty<'p>(&self, pcx: PatCtxt<'_, 'p, 'tcx>) -> bool {
+        self.iter(pcx).next().is_none()
+    }
+
+    /// Iterate over all_ctors \ used_ctors
+    fn iter<'a, 'p>(
+        &'a self,
+        pcx: PatCtxt<'a, 'p, 'tcx>,
+    ) -> impl Iterator<Item = &'a Constructor<'tcx>> + Captures<'p> {
+        self.all_ctors.iter().filter(move |ctor| !ctor.is_covered_by_any(pcx, &self.used_ctors))
+    }
+
+    /// List the patterns corresponding to the missing constructors. In some cases, instead of
+    /// listing all constructors of a given type, we prefer to simply report a wildcard.
+    pub(super) fn report_patterns<'p>(
+        &self,
+        pcx: PatCtxt<'_, 'p, 'tcx>,
+    ) -> SmallVec<[Pat<'tcx>; 1]> {
+        // There are 2 ways we can report a witness here.
+        // Commonly, we can report all the "free"
+        // constructors as witnesses, e.g., if we have:
+        //
+        // ```
+        //     enum Direction { N, S, E, W }
+        //     let Direction::N = ...;
+        // ```
+        //
+        // we can report 3 witnesses: `S`, `E`, and `W`.
+        //
+        // However, there is a case where we don't want
+        // to do this and instead report a single `_` witness:
+        // if the user didn't actually specify a constructor
+        // in this arm, e.g., in
+        //
+        // ```
+        //     let x: (Direction, Direction, bool) = ...;
+        //     let (_, _, false) = x;
+        // ```
+        //
+        // we don't want to show all 16 possible witnesses
+        // `(<direction-1>, <direction-2>, true)` - we are
+        // satisfied with `(_, _, true)`. In this case,
+        // `used_ctors` is empty.
+        // The exception is: if we are at the top-level, for example in an empty match, we
+        // sometimes prefer reporting the list of constructors instead of just `_`.
+        let report_when_all_missing = pcx.is_top_level && !IntRange::is_integral(pcx.ty);
+        if self.used_ctors.is_empty() && !report_when_all_missing {
+            // All constructors are unused. Report only a wildcard
+            // rather than each individual constructor.
+            smallvec![Pat::wildcard_from_ty(pcx.ty)]
+        } else {
+            // Construct for each missing constructor a "wild" version of this
+            // constructor, that matches everything that can be built with
+            // it. For example, if `ctor` is a `Constructor::Variant` for
+            // `Option::Some`, we get the pattern `Some(_)`.
+            self.iter(pcx)
+                .map(|missing_ctor| Fields::wildcards(pcx, &missing_ctor).apply(pcx, missing_ctor))
+                .collect()
+        }
+    }
+}
+
+/// Some fields need to be explicitly hidden away in certain cases; see the comment above the
+/// `Fields` struct. This struct represents such a potentially-hidden field. When a field is hidden
+/// we still keep its type around.
+#[derive(Debug, Copy, Clone)]
+pub(super) enum FilteredField<'p, 'tcx> {
+    Kept(&'p Pat<'tcx>),
+    Hidden(Ty<'tcx>),
+}
+
+impl<'p, 'tcx> FilteredField<'p, 'tcx> {
+    fn kept(self) -> Option<&'p Pat<'tcx>> {
+        match self {
+            FilteredField::Kept(p) => Some(p),
+            FilteredField::Hidden(_) => None,
+        }
+    }
+
+    fn to_pattern(self) -> Pat<'tcx> {
+        match self {
+            FilteredField::Kept(p) => p.clone(),
+            FilteredField::Hidden(ty) => Pat::wildcard_from_ty(ty),
+        }
+    }
+}
+
+/// A value can be decomposed into a constructor applied to some fields. This struct represents
+/// those fields, generalized to allow patterns in each field. See also `Constructor`.
+///
+/// If a private or `non_exhaustive` field is uninhabited, the code mustn't observe that it is
+/// uninhabited. For that, we filter these fields out of the matrix. This is subtle because we
+/// still need to have those fields back when going to/from a `Pat`. Most of this is handled
+/// automatically in `Fields`, but when constructing or deconstructing `Fields` you need to be
+/// careful. As a rule, when going to/from the matrix, use the filtered field list; when going
+/// to/from `Pat`, use the full field list.
+/// This filtering is uncommon in practice, because uninhabited fields are rarely used, so we avoid
+/// it when possible to preserve performance.
+#[derive(Debug, Clone)]
+pub(super) enum Fields<'p, 'tcx> {
+    /// Lists of patterns that don't contain any filtered fields.
+    /// `Slice` and `Vec` behave the same; the difference is only to avoid allocating and
+    /// triple-dereferences when possible. Frankly this is premature optimization, I (Nadrieril)
+    /// have not measured if it really made a difference.
+    Slice(&'p [Pat<'tcx>]),
+    Vec(SmallVec<[&'p Pat<'tcx>; 2]>),
+    /// Patterns where some of the fields need to be hidden. `kept_count` caches the number of
+    /// non-hidden fields.
+    Filtered {
+        fields: SmallVec<[FilteredField<'p, 'tcx>; 2]>,
+        kept_count: usize,
+    },
+}
+
+impl<'p, 'tcx> Fields<'p, 'tcx> {
+    fn empty() -> Self {
+        Fields::Slice(&[])
+    }
+
+    /// Construct a new `Fields` from the given pattern. Must not be used if the pattern is a field
+    /// of a struct/tuple/variant.
+    fn from_single_pattern(pat: &'p Pat<'tcx>) -> Self {
+        Fields::Slice(std::slice::from_ref(pat))
+    }
+
+    /// Convenience; internal use.
+    fn wildcards_from_tys(
+        cx: &MatchCheckCtxt<'p, 'tcx>,
+        tys: impl IntoIterator<Item = Ty<'tcx>>,
+    ) -> Self {
+        let wilds = tys.into_iter().map(Pat::wildcard_from_ty);
+        let pats = cx.pattern_arena.alloc_from_iter(wilds);
+        Fields::Slice(pats)
+    }
+
+    /// Creates a new list of wildcard fields for a given constructor.
+    pub(super) fn wildcards(pcx: PatCtxt<'_, 'p, 'tcx>, constructor: &Constructor<'tcx>) -> Self {
+        let ty = pcx.ty;
+        let cx = pcx.cx;
+        let wildcard_from_ty = |ty| &*cx.pattern_arena.alloc(Pat::wildcard_from_ty(ty));
+
+        let ret = match constructor {
+            Single | Variant(_) => match ty.kind() {
+                ty::Tuple(ref fs) => {
+                    Fields::wildcards_from_tys(cx, fs.into_iter().map(|ty| ty.expect_ty()))
+                }
+                ty::Ref(_, rty, _) => Fields::from_single_pattern(wildcard_from_ty(rty)),
+                ty::Adt(adt, substs) => {
+                    if adt.is_box() {
+                        // Use T as the sub pattern type of Box<T>.
+                        Fields::from_single_pattern(wildcard_from_ty(substs.type_at(0)))
+                    } else {
+                        let variant = &adt.variants[constructor.variant_index_for_adt(adt)];
+                        // Whether we must not match the fields of this variant exhaustively.
+                        let is_non_exhaustive =
+                            variant.is_field_list_non_exhaustive() && !adt.did.is_local();
+                        let field_tys = variant.fields.iter().map(|field| field.ty(cx.tcx, substs));
+                        // In the following cases, we don't need to filter out any fields. This is
+                        // the vast majority of real cases, since uninhabited fields are uncommon.
+                        let has_no_hidden_fields = (adt.is_enum() && !is_non_exhaustive)
+                            || !field_tys.clone().any(|ty| cx.is_uninhabited(ty));
+
+                        if has_no_hidden_fields {
+                            Fields::wildcards_from_tys(cx, field_tys)
+                        } else {
+                            let mut kept_count = 0;
+                            let fields = variant
+                                .fields
+                                .iter()
+                                .map(|field| {
+                                    let ty = field.ty(cx.tcx, substs);
+                                    let is_visible = adt.is_enum()
+                                        || field.vis.is_accessible_from(cx.module, cx.tcx);
+                                    let is_uninhabited = cx.is_uninhabited(ty);
+
+                                    // In the cases of either a `#[non_exhaustive]` field list
+                                    // or a non-public field, we hide uninhabited fields in
+                                    // order not to reveal the uninhabitedness of the whole
+                                    // variant.
+                                    if is_uninhabited && (!is_visible || is_non_exhaustive) {
+                                        FilteredField::Hidden(ty)
+                                    } else {
+                                        kept_count += 1;
+                                        FilteredField::Kept(wildcard_from_ty(ty))
+                                    }
+                                })
+                                .collect();
+                            Fields::Filtered { fields, kept_count }
+                        }
+                    }
+                }
+                _ => bug!("Unexpected type for `Single` constructor: {:?}", ty),
+            },
+            Slice(slice) => match *ty.kind() {
+                ty::Slice(ty) | ty::Array(ty, _) => {
+                    let arity = slice.arity();
+                    Fields::wildcards_from_tys(cx, (0..arity).map(|_| ty))
+                }
+                _ => bug!("bad slice pattern {:?} {:?}", constructor, ty),
+            },
+            Str(..) | FloatRange(..) | IntRange(..) | NonExhaustive | Opaque | Wildcard => {
+                Fields::empty()
+            }
+        };
+        debug!("Fields::wildcards({:?}, {:?}) = {:#?}", constructor, ty, ret);
+        ret
+    }
+
+    /// Apply a constructor to a list of patterns, yielding a new pattern. `self`
+    /// must have as many elements as this constructor's arity.
+    ///
+    /// This is roughly the inverse of `specialize_constructor`.
+    ///
+    /// Examples:
+    /// `ctor`: `Constructor::Single`
+    /// `ty`: `Foo(u32, u32, u32)`
+    /// `self`: `[10, 20, _]`
+    /// returns `Foo(10, 20, _)`
+    ///
+    /// `ctor`: `Constructor::Variant(Option::Some)`
+    /// `ty`: `Option<bool>`
+    /// `self`: `[false]`
+    /// returns `Some(false)`
+    pub(super) fn apply(self, pcx: PatCtxt<'_, 'p, 'tcx>, ctor: &Constructor<'tcx>) -> Pat<'tcx> {
+        let mut subpatterns = self.all_patterns();
+
+        let pat = match ctor {
+            Single | Variant(_) => match pcx.ty.kind() {
+                ty::Adt(..) | ty::Tuple(..) => {
+                    let subpatterns = subpatterns
+                        .enumerate()
+                        .map(|(i, p)| FieldPat { field: Field::new(i), pattern: p })
+                        .collect();
+
+                    if let ty::Adt(adt, substs) = pcx.ty.kind() {
+                        if adt.is_enum() {
+                            PatKind::Variant {
+                                adt_def: adt,
+                                substs,
+                                variant_index: ctor.variant_index_for_adt(adt),
+                                subpatterns,
+                            }
+                        } else {
+                            PatKind::Leaf { subpatterns }
+                        }
+                    } else {
+                        PatKind::Leaf { subpatterns }
+                    }
+                }
+                // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should
+                // be careful to reconstruct the correct constant pattern here. However a string
+                // literal pattern will never be reported as a non-exhaustiveness witness, so we
+                // can ignore this issue.
+                ty::Ref(..) => PatKind::Deref { subpattern: subpatterns.next().unwrap() },
+                ty::Slice(_) | ty::Array(..) => bug!("bad slice pattern {:?} {:?}", ctor, pcx.ty),
+                _ => PatKind::Wild,
+            },
+            Slice(slice) => match slice.kind {
+                FixedLen(_) => {
+                    PatKind::Slice { prefix: subpatterns.collect(), slice: None, suffix: vec![] }
+                }
+                VarLen(prefix, _) => {
+                    let mut prefix: Vec<_> = subpatterns.by_ref().take(prefix as usize).collect();
+                    if slice.array_len.is_some() {
+                        // Improves diagnostics a bit: if the type is a known-size array, instead
+                        // of reporting `[x, _, .., _, y]`, we prefer to report `[x, .., y]`.
+                        // This is incorrect if the size is not known, since `[_, ..]` captures
+                        // arrays of lengths `>= 1` whereas `[..]` captures any length.
+                        while !prefix.is_empty() && prefix.last().unwrap().is_wildcard() {
+                            prefix.pop();
+                        }
+                    }
+                    let suffix: Vec<_> = if slice.array_len.is_some() {
+                        // Same as above.
+                        subpatterns.skip_while(Pat::is_wildcard).collect()
+                    } else {
+                        subpatterns.collect()
+                    };
+                    let wild = Pat::wildcard_from_ty(pcx.ty);
+                    PatKind::Slice { prefix, slice: Some(wild), suffix }
+                }
+            },
+            &Str(value) => PatKind::Constant { value },
+            &FloatRange(lo, hi, end) => PatKind::Range(PatRange { lo, hi, end }),
+            IntRange(range) => return range.to_pat(pcx.cx.tcx),
+            NonExhaustive => PatKind::Wild,
+            Opaque => bug!("we should not try to apply an opaque constructor"),
+            Wildcard => bug!(
+                "trying to apply a wildcard constructor; this should have been done in `apply_constructors`"
+            ),
+        };
+
+        Pat { ty: pcx.ty, span: DUMMY_SP, kind: Box::new(pat) }
+    }
+
+    /// Returns the number of patterns from the viewpoint of match-checking, i.e. excluding hidden
+    /// fields. This is what we want in most cases in this file, the only exception being
+    /// conversion to/from `Pat`.
+    pub(super) fn len(&self) -> usize {
+        match self {
+            Fields::Slice(pats) => pats.len(),
+            Fields::Vec(pats) => pats.len(),
+            Fields::Filtered { kept_count, .. } => *kept_count,
+        }
+    }
+
+    /// Returns the complete list of patterns, including hidden fields.
+    fn all_patterns(self) -> impl Iterator<Item = Pat<'tcx>> {
+        let pats: SmallVec<[_; 2]> = match self {
+            Fields::Slice(pats) => pats.iter().cloned().collect(),
+            Fields::Vec(pats) => pats.into_iter().cloned().collect(),
+            Fields::Filtered { fields, .. } => {
+                // We don't skip any fields here.
+                fields.into_iter().map(|p| p.to_pattern()).collect()
+            }
+        };
+        pats.into_iter()
+    }
+
+    /// Returns the filtered list of patterns, not including hidden fields.
+    pub(super) fn filtered_patterns(self) -> SmallVec<[&'p Pat<'tcx>; 2]> {
+        match self {
+            Fields::Slice(pats) => pats.iter().collect(),
+            Fields::Vec(pats) => pats,
+            Fields::Filtered { fields, .. } => {
+                // We skip hidden fields here
+                fields.into_iter().filter_map(|p| p.kept()).collect()
+            }
+        }
+    }
+
+    /// Overrides some of the fields with the provided patterns. Exactly like
+    /// `replace_fields_indexed`, except that it takes `FieldPat`s as input.
+    fn replace_with_fieldpats(
+        &self,
+        new_pats: impl IntoIterator<Item = &'p FieldPat<'tcx>>,
+    ) -> Self {
+        self.replace_fields_indexed(
+            new_pats.into_iter().map(|pat| (pat.field.index(), &pat.pattern)),
+        )
+    }
+
+    /// Overrides some of the fields with the provided patterns. This is used when a pattern
+    /// defines some fields but not all, for example `Foo { field1: Some(_), .. }`: here we start with a
+    /// `Fields` that is just one wildcard per field of the `Foo` struct, and override the entry
+    /// corresponding to `field1` with the pattern `Some(_)`. This is also used for slice patterns
+    /// for the same reason.
+    fn replace_fields_indexed(
+        &self,
+        new_pats: impl IntoIterator<Item = (usize, &'p Pat<'tcx>)>,
+    ) -> Self {
+        let mut fields = self.clone();
+        if let Fields::Slice(pats) = fields {
+            fields = Fields::Vec(pats.iter().collect());
+        }
+
+        match &mut fields {
+            Fields::Vec(pats) => {
+                for (i, pat) in new_pats {
+                    pats[i] = pat
+                }
+            }
+            Fields::Filtered { fields, .. } => {
+                for (i, pat) in new_pats {
+                    if let FilteredField::Kept(p) = &mut fields[i] {
+                        *p = pat
+                    }
+                }
+            }
+            Fields::Slice(_) => unreachable!(),
+        }
+        fields
+    }
+
+    /// Replaces contained fields with the given filtered list of patterns, e.g. taken from the
+    /// matrix. There must be `len()` patterns in `pats`.
+    pub(super) fn replace_fields(
+        &self,
+        cx: &MatchCheckCtxt<'p, 'tcx>,
+        pats: impl IntoIterator<Item = Pat<'tcx>>,
+    ) -> Self {
+        let pats: &[_] = cx.pattern_arena.alloc_from_iter(pats);
+
+        match self {
+            Fields::Filtered { fields, kept_count } => {
+                let mut pats = pats.iter();
+                let mut fields = fields.clone();
+                for f in &mut fields {
+                    if let FilteredField::Kept(p) = f {
+                        // We take one input pattern for each `Kept` field, in order.
+                        *p = pats.next().unwrap();
+                    }
+                }
+                Fields::Filtered { fields, kept_count: *kept_count }
+            }
+            _ => Fields::Slice(pats),
+        }
+    }
+
+    /// Replaces contained fields with the arguments of the given pattern. Only use on a pattern
+    /// that is compatible with the constructor used to build `self`.
+    /// This is meant to be used on the result of `Fields::wildcards()`. The idea is that
+    /// `wildcards` constructs a list of fields where all entries are wildcards, and the pattern
+    /// provided to this function fills some of the fields with non-wildcards.
+    /// In the following example `Fields::wildcards` would return `[_, _, _, _]`. If we call
+    /// `replace_with_pattern_arguments` on it with the pattern, the result will be `[Some(0), _,
+    /// _, _]`.
+    /// ```rust
+    /// let x: [Option<u8>; 4] = foo();
+    /// match x {
+    ///     [Some(0), ..] => {}
+    /// }
+    /// ```
+    /// This is guaranteed to preserve the number of patterns in `self`.
+    pub(super) fn replace_with_pattern_arguments(&self, pat: &'p Pat<'tcx>) -> Self {
+        match pat.kind.as_ref() {
+            PatKind::Deref { subpattern } => {
+                assert_eq!(self.len(), 1);
+                Fields::from_single_pattern(subpattern)
+            }
+            PatKind::Leaf { subpatterns } | PatKind::Variant { subpatterns, .. } => {
+                self.replace_with_fieldpats(subpatterns)
+            }
+            PatKind::Array { prefix, suffix, .. } | PatKind::Slice { prefix, suffix, .. } => {
+                // Number of subpatterns for the constructor
+                let ctor_arity = self.len();
+
+                // Replace the prefix and the suffix with the given patterns, leaving wildcards in
+                // the middle if there was a subslice pattern `..`.
+                let prefix = prefix.iter().enumerate();
+                let suffix =
+                    suffix.iter().enumerate().map(|(i, p)| (ctor_arity - suffix.len() + i, p));
+                self.replace_fields_indexed(prefix.chain(suffix))
+            }
+            _ => self.clone(),
+        }
+    }
+}
index db0ecd701bca4d3846cd5dbbda6ff7369615d630..7e9a3a37278b7641544cdd2085ed41e0a73ddb61 100644 (file)
@@ -1,8 +1,9 @@
 //! Validation of patterns/matches.
 
-mod _match;
 mod check_match;
 mod const_to_pat;
+mod deconstruct_pat;
+mod usefulness;
 
 pub(crate) use self::check_match::check_match;
 
diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
new file mode 100644 (file)
index 0000000..be96d5a
--- /dev/null
@@ -0,0 +1,992 @@
+//! Note: tests specific to this file can be found in:
+//!
+//!   - `ui/pattern/usefulness`
+//!   - `ui/or-patterns`
+//!   - `ui/consts/const_in_pattern`
+//!   - `ui/rfc-2008-non-exhaustive`
+//!   - `ui/half-open-range-patterns`
+//!   - probably many others
+//!
+//! I (Nadrieril) prefer to put new tests in `ui/pattern/usefulness` unless there's a specific
+//! reason not to, for example if they depend on a particular feature like `or_patterns`.
+//!
+//! -----
+//!
+//! This file includes the logic for exhaustiveness and usefulness checking for
+//! pattern-matching. Specifically, given a list of patterns for a type, we can
+//! tell whether:
+//! (a) the patterns cover every possible constructor for the type (exhaustiveness)
+//! (b) each pattern is necessary (usefulness)
+//!
+//! The algorithm implemented here is a modified version of the one described in
+//! [this paper](http://moscova.inria.fr/~maranget/papers/warn/index.html).
+//! However, to save future implementors from reading the original paper, we
+//! summarise the algorithm here to hopefully save time and be a little clearer
+//! (without being so rigorous).
+//!
+//! # Premise
+//!
+//! The core of the algorithm revolves about a "usefulness" check. In particular, we
+//! are trying to compute a predicate `U(P, p)` where `P` is a list of patterns (we refer to this as
+//! a matrix). `U(P, p)` represents whether, given an existing list of patterns
+//! `P_1 ..= P_m`, adding a new pattern `p` will be "useful" (that is, cover previously-
+//! uncovered values of the type).
+//!
+//! If we have this predicate, then we can easily compute both exhaustiveness of an
+//! entire set of patterns and the individual usefulness of each one.
+//! (a) the set of patterns is exhaustive iff `U(P, _)` is false (i.e., adding a wildcard
+//! match doesn't increase the number of values we're matching)
+//! (b) a pattern `P_i` is not useful if `U(P[0..=(i-1), P_i)` is false (i.e., adding a
+//! pattern to those that have come before it doesn't increase the number of values
+//! we're matching).
+//!
+//! # Core concept
+//!
+//! The idea that powers everything that is done in this file is the following: a value is made
+//! from a constructor applied to some fields. Examples of constructors are `Some`, `None`, `(,)`
+//! (the 2-tuple constructor), `Foo {..}` (the constructor for a struct `Foo`), and `2` (the
+//! constructor for the number `2`). Fields are just a (possibly empty) list of values.
+//!
+//! Some of the constructors listed above might feel weird: `None` and `2` don't take any
+//! arguments. This is part of what makes constructors so general: we will consider plain values
+//! like numbers and string literals to be constructors that take no arguments, also called "0-ary
+//! constructors"; they are the simplest case of constructors. This allows us to see any value as
+//! made up from a tree of constructors, each having a given number of children. For example:
+//! `(None, Ok(0))` is made from 4 different constructors.
+//!
+//! This idea can be extended to patterns: a pattern captures a set of possible values, and we can
+//! describe this set using constructors. For example, `Err(_)` captures all values of the type
+//! `Result<T, E>` that start with the `Err` constructor (for some choice of `T` and `E`). The
+//! wildcard `_` captures all values of the given type starting with any of the constructors for
+//! that type.
+//!
+//! We use this to compute whether different patterns might capture a same value. Do the patterns
+//! `Ok("foo")` and `Err(_)` capture a common value? The answer is no, because the first pattern
+//! captures only values starting with the `Ok` constructor and the second only values starting
+//! with the `Err` constructor. Do the patterns `Some(42)` and `Some(1..10)` intersect? They might,
+//! since they both capture values starting with `Some`. To be certain, we need to dig under the
+//! `Some` constructor and continue asking the question. This is the main idea behind the
+//! exhaustiveness algorithm: by looking at patterns constructor-by-constructor, we can efficiently
+//! figure out if some new pattern might capture a value that hadn't been captured by previous
+//! patterns.
+//!
+//! Constructors are represented by the `Constructor` enum, and its fields by the `Fields` enum.
+//! Most of the complexity of this file resides in transforming between patterns and
+//! (`Constructor`, `Fields`) pairs, handling all the special cases correctly.
+//!
+//! Caveat: this constructors/fields distinction doesn't quite cover every Rust value. For example
+//! a value of type `Rc<u64>` doesn't fit this idea very well, nor do various other things.
+//! However, this idea covers most of the cases that are relevant to exhaustiveness checking.
+//!
+//!
+//! # Algorithm
+//!
+//! Recall that `U(P, p)` represents whether, given an existing list of patterns (aka matrix) `P`,
+//! adding a new pattern `p` will cover previously-uncovered values of the type.
+//! During the course of the algorithm, the rows of the matrix won't just be individual patterns,
+//! but rather partially-deconstructed patterns in the form of a list of fields. The paper
+//! calls those pattern-vectors, and we will call them pattern-stacks. The same holds for the
+//! new pattern `p`.
+//!
+//! For example, say we have the following:
+//!
+//! ```
+//! // x: (Option<bool>, Result<()>)
+//! match x {
+//!     (Some(true), _) => {}
+//!     (None, Err(())) => {}
+//!     (None, Err(_)) => {}
+//! }
+//! ```
+//!
+//! Here, the matrix `P` starts as:
+//!
+//! ```
+//! [
+//!     [(Some(true), _)],
+//!     [(None, Err(()))],
+//!     [(None, Err(_))],
+//! ]
+//! ```
+//!
+//! We can tell it's not exhaustive, because `U(P, _)` is true (we're not covering
+//! `[(Some(false), _)]`, for instance). In addition, row 3 is not useful, because
+//! all the values it covers are already covered by row 2.
+//!
+//! A list of patterns can be thought of as a stack, because we are mainly interested in the top of
+//! the stack at any given point, and we can pop or apply constructors to get new pattern-stacks.
+//! To match the paper, the top of the stack is at the beginning / on the left.
+//!
+//! There are two important operations on pattern-stacks necessary to understand the algorithm:
+//!
+//! 1. We can pop a given constructor off the top of a stack. This operation is called
+//!    `specialize`, and is denoted `S(c, p)` where `c` is a constructor (like `Some` or
+//!    `None`) and `p` a pattern-stack.
+//!    If the pattern on top of the stack can cover `c`, this removes the constructor and
+//!    pushes its arguments onto the stack. It also expands OR-patterns into distinct patterns.
+//!    Otherwise the pattern-stack is discarded.
+//!    This essentially filters those pattern-stacks whose top covers the constructor `c` and
+//!    discards the others.
+//!
+//!    For example, the first pattern above initially gives a stack `[(Some(true), _)]`. If we
+//!    pop the tuple constructor, we are left with `[Some(true), _]`, and if we then pop the
+//!    `Some` constructor we get `[true, _]`. If we had popped `None` instead, we would get
+//!    nothing back.
+//!
+//!    This returns zero or more new pattern-stacks, as follows. We look at the pattern `p_1`
+//!    on top of the stack, and we have four cases:
+//!
+//!      1.1. `p_1 = c(r_1, .., r_a)`, i.e. the top of the stack has constructor `c`. We
+//!           push onto the stack the arguments of this constructor, and return the result:
+//!              `r_1, .., r_a, p_2, .., p_n`
+//!
+//!      1.2. `p_1 = c'(r_1, .., r_a')` where `c ≠ c'`. We discard the current stack and
+//!           return nothing.
+//!
+//!         1.3. `p_1 = _`. We push onto the stack as many wildcards as the constructor `c` has
+//!              arguments (its arity), and return the resulting stack:
+//!                 `_, .., _, p_2, .., p_n`
+//!
+//!         1.4. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting
+//!              stack:
+//!                 - `S(c, (r_1, p_2, .., p_n))`
+//!                 - `S(c, (r_2, p_2, .., p_n))`
+//!
+//! 2. We can pop a wildcard off the top of the stack. This is called `S(_, p)`, where `p` is
+//!    a pattern-stack. Note: the paper calls this `D(p)`.
+//!    This is used when we know there are missing constructor cases, but there might be
+//!    existing wildcard patterns, so to check the usefulness of the matrix, we have to check
+//!    all its *other* components.
+//!
+//!    It is computed as follows. We look at the pattern `p_1` on top of the stack,
+//!    and we have three cases:
+//!         2.1. `p_1 = c(r_1, .., r_a)`. We discard the current stack and return nothing.
+//!         2.2. `p_1 = _`. We return the rest of the stack:
+//!                 p_2, .., p_n
+//!         2.3. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting
+//!           stack.
+//!                 - `S(_, (r_1, p_2, .., p_n))`
+//!                 - `S(_, (r_2, p_2, .., p_n))`
+//!
+//! Note that the OR-patterns are not always used directly in Rust, but are used to derive the
+//! exhaustive integer matching rules, so they're written here for posterity.
+//!
+//! Both those operations extend straightforwardly to a list or pattern-stacks, i.e. a matrix, by
+//! working row-by-row. Popping a constructor ends up keeping only the matrix rows that start with
+//! the given constructor, and popping a wildcard keeps those rows that start with a wildcard.
+//!
+//!
+//! The algorithm for computing `U`
+//! -------------------------------
+//! The algorithm is inductive (on the number of columns: i.e., components of tuple patterns).
+//! That means we're going to check the components from left-to-right, so the algorithm
+//! operates principally on the first component of the matrix and new pattern-stack `p`.
+//! This algorithm is realised in the `is_useful` function.
+//!
+//! Base case. (`n = 0`, i.e., an empty tuple pattern)
+//!     - If `P` already contains an empty pattern (i.e., if the number of patterns `m > 0`),
+//!       then `U(P, p)` is false.
+//!     - Otherwise, `P` must be empty, so `U(P, p)` is true.
+//!
+//! Inductive step. (`n > 0`, i.e., whether there's at least one column
+//!                  [which may then be expanded into further columns later])
+//! We're going to match on the top of the new pattern-stack, `p_1`.
+//!     - If `p_1 == c(r_1, .., r_a)`, i.e. we have a constructor pattern.
+//! Then, the usefulness of `p_1` can be reduced to whether it is useful when
+//! we ignore all the patterns in the first column of `P` that involve other constructors.
+//! This is where `S(c, P)` comes in:
+//! `U(P, p) := U(S(c, P), S(c, p))`
+//!
+//! For example, if `P` is:
+//!
+//! ```
+//! [
+//!     [Some(true), _],
+//!     [None, 0],
+//! ]
+//! ```
+//!
+//! and `p` is `[Some(false), 0]`, then we don't care about row 2 since we know `p` only
+//! matches values that row 2 doesn't. For row 1 however, we need to dig into the
+//! arguments of `Some` to know whether some new value is covered. So we compute
+//! `U([[true, _]], [false, 0])`.
+//!
+//!   - If `p_1 == _`, then we look at the list of constructors that appear in the first
+//! component of the rows of `P`:
+//!   + If there are some constructors that aren't present, then we might think that the
+//! wildcard `_` is useful, since it covers those constructors that weren't covered
+//! before.
+//! That's almost correct, but only works if there were no wildcards in those first
+//! components. So we need to check that `p` is useful with respect to the rows that
+//! start with a wildcard, if there are any. This is where `S(_, x)` comes in:
+//! `U(P, p) := U(S(_, P), S(_, p))`
+//!
+//! For example, if `P` is:
+//!
+//! ```
+//! [
+//!     [_, true, _],
+//!     [None, false, 1],
+//! ]
+//! ```
+//!
+//! and `p` is `[_, false, _]`, the `Some` constructor doesn't appear in `P`. So if we
+//! only had row 2, we'd know that `p` is useful. However row 1 starts with a
+//! wildcard, so we need to check whether `U([[true, _]], [false, 1])`.
+//!
+//!   + Otherwise, all possible constructors (for the relevant type) are present. In this
+//! case we must check whether the wildcard pattern covers any unmatched value. For
+//! that, we can think of the `_` pattern as a big OR-pattern that covers all
+//! possible constructors. For `Option`, that would mean `_ = None | Some(_)` for
+//! example. The wildcard pattern is useful in this case if it is useful when
+//! specialized to one of the possible constructors. So we compute:
+//! `U(P, p) := ∃(k ϵ constructors) U(S(k, P), S(k, p))`
+//!
+//! For example, if `P` is:
+//!
+//! ```
+//! [
+//!     [Some(true), _],
+//!     [None, false],
+//! ]
+//! ```
+//!
+//! and `p` is `[_, false]`, both `None` and `Some` constructors appear in the first
+//! components of `P`. We will therefore try popping both constructors in turn: we
+//! compute `U([[true, _]], [_, false])` for the `Some` constructor, and `U([[false]],
+//! [false])` for the `None` constructor. The first case returns true, so we know that
+//! `p` is useful for `P`. Indeed, it matches `[Some(false), _]` that wasn't matched
+//! before.
+//!
+//!   - If `p_1 == r_1 | r_2`, then the usefulness depends on each `r_i` separately:
+//! `U(P, p) := U(P, (r_1, p_2, .., p_n))
+//!  || U(P, (r_2, p_2, .., p_n))`
+//!
+//! Modifications to the algorithm
+//! ------------------------------
+//! The algorithm in the paper doesn't cover some of the special cases that arise in Rust, for
+//! example uninhabited types and variable-length slice patterns. These are drawn attention to
+//! throughout the code below. I'll make a quick note here about how exhaustive integer matching is
+//! accounted for, though.
+//!
+//! Exhaustive integer matching
+//! ---------------------------
+//! An integer type can be thought of as a (huge) sum type: 1 | 2 | 3 | ...
+//! So to support exhaustive integer matching, we can make use of the logic in the paper for
+//! OR-patterns. However, we obviously can't just treat ranges x..=y as individual sums, because
+//! they are likely gigantic. So we instead treat ranges as constructors of the integers. This means
+//! that we have a constructor *of* constructors (the integers themselves). We then need to work
+//! through all the inductive step rules above, deriving how the ranges would be treated as
+//! OR-patterns, and making sure that they're treated in the same way even when they're ranges.
+//! There are really only four special cases here:
+//! - When we match on a constructor that's actually a range, we have to treat it as if we would
+//!   an OR-pattern.
+//!     + It turns out that we can simply extend the case for single-value patterns in
+//!      `specialize` to either be *equal* to a value constructor, or *contained within* a range
+//!      constructor.
+//!     + When the pattern itself is a range, you just want to tell whether any of the values in
+//!       the pattern range coincide with values in the constructor range, which is precisely
+//!       intersection.
+//!   Since when encountering a range pattern for a value constructor, we also use inclusion, it
+//!   means that whenever the constructor is a value/range and the pattern is also a value/range,
+//!   we can simply use intersection to test usefulness.
+//! - When we're testing for usefulness of a pattern and the pattern's first component is a
+//!   wildcard.
+//!     + If all the constructors appear in the matrix, we have a slight complication. By default,
+//!       the behaviour (i.e., a disjunction over specialised matrices for each constructor) is
+//!       invalid, because we want a disjunction over every *integer* in each range, not just a
+//!       disjunction over every range. This is a bit more tricky to deal with: essentially we need
+//!       to form equivalence classes of subranges of the constructor range for which the behaviour
+//!       of the matrix `P` and new pattern `p` are the same. This is described in more
+//!       detail in `Constructor::split`.
+//!     + If some constructors are missing from the matrix, it turns out we don't need to do
+//!       anything special (because we know none of the integers are actually wildcards: i.e., we
+//!       can't span wildcards using ranges).
+
+use self::Usefulness::*;
+use self::WitnessPreference::*;
+
+use super::deconstruct_pat::{Constructor, Fields, MissingConstructors};
+use super::{Pat, PatKind};
+use super::{PatternFoldable, PatternFolder};
+
+use rustc_data_structures::captures::Captures;
+use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::sync::OnceCell;
+
+use rustc_arena::TypedArena;
+use rustc_hir::def_id::DefId;
+use rustc_hir::HirId;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::Span;
+
+use smallvec::{smallvec, SmallVec};
+use std::fmt;
+use std::iter::{FromIterator, IntoIterator};
+
+crate struct MatchCheckCtxt<'a, 'tcx> {
+    crate tcx: TyCtxt<'tcx>,
+    /// The module in which the match occurs. This is necessary for
+    /// checking inhabited-ness of types because whether a type is (visibly)
+    /// inhabited can depend on whether it was defined in the current module or
+    /// not. E.g., `struct Foo { _private: ! }` cannot be seen to be empty
+    /// outside its module and should not be matchable with an empty match statement.
+    crate module: DefId,
+    crate param_env: ty::ParamEnv<'tcx>,
+    crate pattern_arena: &'a TypedArena<Pat<'tcx>>,
+}
+
+impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
+    pub(super) fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
+        if self.tcx.features().exhaustive_patterns {
+            self.tcx.is_ty_uninhabited_from(self.module, ty, self.param_env)
+        } else {
+            false
+        }
+    }
+
+    /// Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`.
+    pub(super) fn is_foreign_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
+        match ty.kind() {
+            ty::Adt(def, ..) => {
+                def.is_enum() && def.is_variant_list_non_exhaustive() && !def.did.is_local()
+            }
+            _ => false,
+        }
+    }
+}
+
+#[derive(Copy, Clone)]
+pub(super) struct PatCtxt<'a, 'p, 'tcx> {
+    pub(super) cx: &'a MatchCheckCtxt<'p, 'tcx>,
+    /// Current state of the matrix.
+    pub(super) matrix: &'a Matrix<'p, 'tcx>,
+    /// Type of the current column under investigation.
+    pub(super) ty: Ty<'tcx>,
+    /// Span of the current pattern under investigation.
+    pub(super) span: Span,
+    /// Whether the current pattern is the whole pattern as found in a match arm, or if it's a
+    /// subpattern.
+    pub(super) is_top_level: bool,
+}
+
+crate fn expand_pattern<'tcx>(pat: Pat<'tcx>) -> Pat<'tcx> {
+    LiteralExpander.fold_pattern(&pat)
+}
+
+struct LiteralExpander;
+
+impl<'tcx> PatternFolder<'tcx> for LiteralExpander {
+    fn fold_pattern(&mut self, pat: &Pat<'tcx>) -> Pat<'tcx> {
+        debug!("fold_pattern {:?} {:?} {:?}", pat, pat.ty.kind(), pat.kind);
+        match (pat.ty.kind(), pat.kind.as_ref()) {
+            (_, PatKind::Binding { subpattern: Some(s), .. }) => s.fold_with(self),
+            (_, PatKind::AscribeUserType { subpattern: s, .. }) => s.fold_with(self),
+            (ty::Ref(_, t, _), PatKind::Constant { .. }) if t.is_str() => {
+                // Treat string literal patterns as deref patterns to a `str` constant, i.e.
+                // `&CONST`. This expands them like other const patterns. This could have been done
+                // in `const_to_pat`, but that causes issues with the rest of the matching code.
+                let mut new_pat = pat.super_fold_with(self);
+                // Make a fake const pattern of type `str` (instead of `&str`). That the carried
+                // constant value still knows it is of type `&str`.
+                new_pat.ty = t;
+                Pat {
+                    kind: Box::new(PatKind::Deref { subpattern: new_pat }),
+                    span: pat.span,
+                    ty: pat.ty,
+                }
+            }
+            _ => pat.super_fold_with(self),
+        }
+    }
+}
+
+impl<'tcx> Pat<'tcx> {
+    pub(super) fn is_wildcard(&self) -> bool {
+        matches!(*self.kind, PatKind::Binding { subpattern: None, .. } | PatKind::Wild)
+    }
+}
+
+/// A row of a matrix. Rows of len 1 are very common, which is why `SmallVec[_; 2]`
+/// works well.
+#[derive(Debug, Clone)]
+struct PatStack<'p, 'tcx> {
+    pats: SmallVec<[&'p Pat<'tcx>; 2]>,
+    /// Cache for the constructor of the head
+    head_ctor: OnceCell<Constructor<'tcx>>,
+}
+
+impl<'p, 'tcx> PatStack<'p, 'tcx> {
+    fn from_pattern(pat: &'p Pat<'tcx>) -> Self {
+        Self::from_vec(smallvec![pat])
+    }
+
+    fn from_vec(vec: SmallVec<[&'p Pat<'tcx>; 2]>) -> Self {
+        PatStack { pats: vec, head_ctor: OnceCell::new() }
+    }
+
+    fn is_empty(&self) -> bool {
+        self.pats.is_empty()
+    }
+
+    fn len(&self) -> usize {
+        self.pats.len()
+    }
+
+    fn head(&self) -> &'p Pat<'tcx> {
+        self.pats[0]
+    }
+
+    fn head_ctor<'a>(&'a self, cx: &MatchCheckCtxt<'p, 'tcx>) -> &'a Constructor<'tcx> {
+        self.head_ctor.get_or_init(|| Constructor::from_pat(cx, self.head()))
+    }
+
+    fn iter(&self) -> impl Iterator<Item = &Pat<'tcx>> {
+        self.pats.iter().copied()
+    }
+
+    // If the first pattern is an or-pattern, expand this pattern. Otherwise, return `None`.
+    fn expand_or_pat(&self) -> Option<Vec<Self>> {
+        if self.is_empty() {
+            None
+        } else if let PatKind::Or { pats } = &*self.head().kind {
+            Some(
+                pats.iter()
+                    .map(|pat| {
+                        let mut new_patstack = PatStack::from_pattern(pat);
+                        new_patstack.pats.extend_from_slice(&self.pats[1..]);
+                        new_patstack
+                    })
+                    .collect(),
+            )
+        } else {
+            None
+        }
+    }
+
+    /// This computes `S(self.head_ctor(), self)`. See top of the file for explanations.
+    ///
+    /// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
+    /// fields filled with wild patterns.
+    ///
+    /// This is roughly the inverse of `Constructor::apply`.
+    fn pop_head_constructor(&self, ctor_wild_subpatterns: &Fields<'p, 'tcx>) -> PatStack<'p, 'tcx> {
+        // We pop the head pattern and push the new fields extracted from the arguments of
+        // `self.head()`.
+        let mut new_fields =
+            ctor_wild_subpatterns.replace_with_pattern_arguments(self.head()).filtered_patterns();
+        new_fields.extend_from_slice(&self.pats[1..]);
+        PatStack::from_vec(new_fields)
+    }
+}
+
+impl<'p, 'tcx> Default for PatStack<'p, 'tcx> {
+    fn default() -> Self {
+        Self::from_vec(smallvec![])
+    }
+}
+
+impl<'p, 'tcx> PartialEq for PatStack<'p, 'tcx> {
+    fn eq(&self, other: &Self) -> bool {
+        self.pats == other.pats
+    }
+}
+
+impl<'p, 'tcx> FromIterator<&'p Pat<'tcx>> for PatStack<'p, 'tcx> {
+    fn from_iter<T>(iter: T) -> Self
+    where
+        T: IntoIterator<Item = &'p Pat<'tcx>>,
+    {
+        Self::from_vec(iter.into_iter().collect())
+    }
+}
+
+/// A 2D matrix.
+#[derive(Clone, PartialEq)]
+pub(super) struct Matrix<'p, 'tcx> {
+    patterns: Vec<PatStack<'p, 'tcx>>,
+}
+
+impl<'p, 'tcx> Matrix<'p, 'tcx> {
+    fn empty() -> Self {
+        Matrix { patterns: vec![] }
+    }
+
+    /// Number of columns of this matrix. `None` is the matrix is empty.
+    pub(super) fn column_count(&self) -> Option<usize> {
+        self.patterns.get(0).map(|r| r.len())
+    }
+
+    /// Pushes a new row to the matrix. If the row starts with an or-pattern, this expands it.
+    fn push(&mut self, row: PatStack<'p, 'tcx>) {
+        if let Some(rows) = row.expand_or_pat() {
+            for row in rows {
+                // We recursively expand the or-patterns of the new rows.
+                // This is necessary as we might have `0 | (1 | 2)` or e.g., `x @ 0 | x @ (1 | 2)`.
+                self.push(row)
+            }
+        } else {
+            self.patterns.push(row);
+        }
+    }
+
+    /// Iterate over the first component of each row
+    fn heads<'a>(&'a self) -> impl Iterator<Item = &'a Pat<'tcx>> + Captures<'p> {
+        self.patterns.iter().map(|r| r.head())
+    }
+
+    /// Iterate over the first constructor of each row
+    pub(super) fn head_ctors<'a>(
+        &'a self,
+        cx: &'a MatchCheckCtxt<'p, 'tcx>,
+    ) -> impl Iterator<Item = &'a Constructor<'tcx>> + Captures<'a> + Captures<'p> {
+        self.patterns.iter().map(move |r| r.head_ctor(cx))
+    }
+
+    /// This computes `S(constructor, self)`. See top of the file for explanations.
+    fn specialize_constructor(
+        &self,
+        pcx: PatCtxt<'_, 'p, 'tcx>,
+        ctor: &Constructor<'tcx>,
+        ctor_wild_subpatterns: &Fields<'p, 'tcx>,
+    ) -> Matrix<'p, 'tcx> {
+        self.patterns
+            .iter()
+            .filter(|r| ctor.is_covered_by(pcx, r.head_ctor(pcx.cx)))
+            .map(|r| r.pop_head_constructor(ctor_wild_subpatterns))
+            .collect()
+    }
+}
+
+/// Pretty-printer for matrices of patterns, example:
+///
+/// ```text
+/// +++++++++++++++++++++++++++++
+/// + _     + []                +
+/// +++++++++++++++++++++++++++++
+/// + true  + [First]           +
+/// +++++++++++++++++++++++++++++
+/// + true  + [Second(true)]    +
+/// +++++++++++++++++++++++++++++
+/// + false + [_]               +
+/// +++++++++++++++++++++++++++++
+/// + _     + [_, _, tail @ ..] +
+/// +++++++++++++++++++++++++++++
+/// ```
+impl<'p, 'tcx> fmt::Debug for Matrix<'p, 'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "\n")?;
+
+        let Matrix { patterns: m, .. } = self;
+        let pretty_printed_matrix: Vec<Vec<String>> =
+            m.iter().map(|row| row.iter().map(|pat| format!("{:?}", pat)).collect()).collect();
+
+        let column_count = m.iter().map(|row| row.len()).max().unwrap_or(0);
+        assert!(m.iter().all(|row| row.len() == column_count));
+        let column_widths: Vec<usize> = (0..column_count)
+            .map(|col| pretty_printed_matrix.iter().map(|row| row[col].len()).max().unwrap_or(0))
+            .collect();
+
+        let total_width = column_widths.iter().cloned().sum::<usize>() + column_count * 3 + 1;
+        let br = "+".repeat(total_width);
+        write!(f, "{}\n", br)?;
+        for row in pretty_printed_matrix {
+            write!(f, "+")?;
+            for (column, pat_str) in row.into_iter().enumerate() {
+                write!(f, " ")?;
+                write!(f, "{:1$}", pat_str, column_widths[column])?;
+                write!(f, " +")?;
+            }
+            write!(f, "\n")?;
+            write!(f, "{}\n", br)?;
+        }
+        Ok(())
+    }
+}
+
+impl<'p, 'tcx> FromIterator<PatStack<'p, 'tcx>> for Matrix<'p, 'tcx> {
+    fn from_iter<T>(iter: T) -> Self
+    where
+        T: IntoIterator<Item = PatStack<'p, 'tcx>>,
+    {
+        let mut matrix = Matrix::empty();
+        for x in iter {
+            // Using `push` ensures we correctly expand or-patterns.
+            matrix.push(x);
+        }
+        matrix
+    }
+}
+
+#[derive(Clone, Debug)]
+crate enum Usefulness<'tcx> {
+    /// Carries, for each column in the matrix, a set of sub-branches that have been found to be
+    /// unreachable. Used only in the presence of or-patterns, otherwise it stays empty.
+    Useful(Vec<FxHashSet<Span>>),
+    /// Carries a list of witnesses of non-exhaustiveness.
+    UsefulWithWitness(Vec<Witness<'tcx>>),
+    NotUseful,
+}
+
+impl<'tcx> Usefulness<'tcx> {
+    fn new_useful(preference: WitnessPreference) -> Self {
+        match preference {
+            ConstructWitness => UsefulWithWitness(vec![Witness(vec![])]),
+            LeaveOutWitness => Useful(vec![]),
+        }
+    }
+
+    fn is_useful(&self) -> bool {
+        !matches!(*self, NotUseful)
+    }
+
+    fn apply_constructor<'p>(
+        self,
+        pcx: PatCtxt<'_, 'p, 'tcx>,
+        ctor: &Constructor<'tcx>,
+        ctor_wild_subpatterns: &Fields<'p, 'tcx>,
+    ) -> Self {
+        match self {
+            UsefulWithWitness(witnesses) => {
+                let new_witnesses = if ctor.is_wildcard() {
+                    let missing_ctors = MissingConstructors::new(pcx);
+                    let new_patterns = missing_ctors.report_patterns(pcx);
+                    witnesses
+                        .into_iter()
+                        .flat_map(|witness| {
+                            new_patterns.iter().map(move |pat| {
+                                let mut witness = witness.clone();
+                                witness.0.push(pat.clone());
+                                witness
+                            })
+                        })
+                        .collect()
+                } else {
+                    witnesses
+                        .into_iter()
+                        .map(|witness| witness.apply_constructor(pcx, &ctor, ctor_wild_subpatterns))
+                        .collect()
+                };
+                UsefulWithWitness(new_witnesses)
+            }
+            Useful(mut unreachables) => {
+                if !unreachables.is_empty() {
+                    // When we apply a constructor, there are `arity` columns of the matrix that
+                    // corresponded to its arguments. All the unreachables found in these columns
+                    // will, after `apply`, come from the first column. So we take the union of all
+                    // the corresponding sets and put them in the first column.
+                    // Note that `arity` may be 0, in which case we just push a new empty set.
+                    let len = unreachables.len();
+                    let arity = ctor_wild_subpatterns.len();
+                    let mut unioned = FxHashSet::default();
+                    for set in unreachables.drain((len - arity)..) {
+                        unioned.extend(set)
+                    }
+                    unreachables.push(unioned);
+                }
+                Useful(unreachables)
+            }
+            x => x,
+        }
+    }
+}
+
+#[derive(Copy, Clone, Debug)]
+enum WitnessPreference {
+    ConstructWitness,
+    LeaveOutWitness,
+}
+
+/// A witness of non-exhaustiveness for error reporting, represented
+/// as a list of patterns (in reverse order of construction) with
+/// wildcards inside to represent elements that can take any inhabitant
+/// of the type as a value.
+///
+/// A witness against a list of patterns should have the same types
+/// and length as the pattern matched against. Because Rust `match`
+/// is always against a single pattern, at the end the witness will
+/// have length 1, but in the middle of the algorithm, it can contain
+/// multiple patterns.
+///
+/// For example, if we are constructing a witness for the match against
+///
+/// ```
+/// struct Pair(Option<(u32, u32)>, bool);
+///
+/// match (p: Pair) {
+///    Pair(None, _) => {}
+///    Pair(_, false) => {}
+/// }
+/// ```
+///
+/// We'll perform the following steps:
+/// 1. Start with an empty witness
+///     `Witness(vec![])`
+/// 2. Push a witness `Some(_)` against the `None`
+///     `Witness(vec![Some(_)])`
+/// 3. Push a witness `true` against the `false`
+///     `Witness(vec![Some(_), true])`
+/// 4. Apply the `Pair` constructor to the witnesses
+///     `Witness(vec![Pair(Some(_), true)])`
+///
+/// The final `Pair(Some(_), true)` is then the resulting witness.
+#[derive(Clone, Debug)]
+crate struct Witness<'tcx>(Vec<Pat<'tcx>>);
+
+impl<'tcx> Witness<'tcx> {
+    /// Asserts that the witness contains a single pattern, and returns it.
+    fn single_pattern(self) -> Pat<'tcx> {
+        assert_eq!(self.0.len(), 1);
+        self.0.into_iter().next().unwrap()
+    }
+
+    /// Constructs a partial witness for a pattern given a list of
+    /// patterns expanded by the specialization step.
+    ///
+    /// When a pattern P is discovered to be useful, this function is used bottom-up
+    /// to reconstruct a complete witness, e.g., a pattern P' that covers a subset
+    /// of values, V, where each value in that set is not covered by any previously
+    /// used patterns and is covered by the pattern P'. Examples:
+    ///
+    /// left_ty: tuple of 3 elements
+    /// pats: [10, 20, _]           => (10, 20, _)
+    ///
+    /// left_ty: struct X { a: (bool, &'static str), b: usize}
+    /// pats: [(false, "foo"), 42]  => X { a: (false, "foo"), b: 42 }
+    fn apply_constructor<'p>(
+        mut self,
+        pcx: PatCtxt<'_, 'p, 'tcx>,
+        ctor: &Constructor<'tcx>,
+        ctor_wild_subpatterns: &Fields<'p, 'tcx>,
+    ) -> Self {
+        let pat = {
+            let len = self.0.len();
+            let arity = ctor_wild_subpatterns.len();
+            let pats = self.0.drain((len - arity)..).rev();
+            ctor_wild_subpatterns.replace_fields(pcx.cx, pats).apply(pcx, ctor)
+        };
+
+        self.0.push(pat);
+
+        self
+    }
+}
+
+/// Algorithm from <http://moscova.inria.fr/~maranget/papers/warn/index.html>.
+/// The algorithm from the paper has been modified to correctly handle empty
+/// types. The changes are:
+///   (0) We don't exit early if the pattern matrix has zero rows. We just
+///       continue to recurse over columns.
+///   (1) all_constructors will only return constructors that are statically
+///       possible. E.g., it will only return `Ok` for `Result<T, !>`.
+///
+/// This finds whether a (row) vector `v` of patterns is 'useful' in relation
+/// to a set of such vectors `m` - this is defined as there being a set of
+/// inputs that will match `v` but not any of the sets in `m`.
+///
+/// All the patterns at each column of the `matrix ++ v` matrix must have the same type.
+///
+/// This is used both for reachability checking (if a pattern isn't useful in
+/// relation to preceding patterns, it is not reachable) and exhaustiveness
+/// checking (if a wildcard pattern is useful in relation to a matrix, the
+/// matrix isn't exhaustive).
+///
+/// `is_under_guard` is used to inform if the pattern has a guard. If it
+/// has one it must not be inserted into the matrix. This shouldn't be
+/// relied on for soundness.
+fn is_useful<'p, 'tcx>(
+    cx: &MatchCheckCtxt<'p, 'tcx>,
+    matrix: &Matrix<'p, 'tcx>,
+    v: &PatStack<'p, 'tcx>,
+    witness_preference: WitnessPreference,
+    hir_id: HirId,
+    is_under_guard: bool,
+    is_top_level: bool,
+) -> Usefulness<'tcx> {
+    let Matrix { patterns: rows, .. } = matrix;
+    debug!("is_useful({:#?}, {:#?})", matrix, v);
+
+    // The base case. We are pattern-matching on () and the return value is
+    // based on whether our matrix has a row or not.
+    // NOTE: This could potentially be optimized by checking rows.is_empty()
+    // first and then, if v is non-empty, the return value is based on whether
+    // the type of the tuple we're checking is inhabited or not.
+    if v.is_empty() {
+        return if rows.is_empty() {
+            Usefulness::new_useful(witness_preference)
+        } else {
+            NotUseful
+        };
+    };
+
+    assert!(rows.iter().all(|r| r.len() == v.len()));
+
+    // If the first pattern is an or-pattern, expand it.
+    if let Some(vs) = v.expand_or_pat() {
+        // We expand the or pattern, trying each of its branches in turn and keeping careful track
+        // of possible unreachable sub-branches.
+        //
+        // If two branches have detected some unreachable sub-branches, we need to be careful. If
+        // they were detected in columns that are not the current one, we want to keep only the
+        // sub-branches that were unreachable in _all_ branches. Eg. in the following, the last
+        // `true` is unreachable in the second branch of the first or-pattern, but not otherwise.
+        // Therefore we don't want to lint that it is unreachable.
+        //
+        // ```
+        // match (true, true) {
+        //     (true, true) => {}
+        //     (false | true, false | true) => {}
+        // }
+        // ```
+        // If however the sub-branches come from the current column, they come from the inside of
+        // the current or-pattern, and we want to keep them all. Eg. in the following, we _do_ want
+        // to lint that the last `false` is unreachable.
+        // ```
+        // match None {
+        //     Some(false) => {}
+        //     None | Some(true | false) => {}
+        // }
+        // ```
+
+        let mut matrix = matrix.clone();
+        // We keep track of sub-branches separately depending on whether they come from this column
+        // or from others.
+        let mut unreachables_this_column: FxHashSet<Span> = FxHashSet::default();
+        let mut unreachables_other_columns: Vec<FxHashSet<Span>> = Vec::default();
+        // Whether at least one branch is reachable.
+        let mut any_is_useful = false;
+
+        for v in vs {
+            let res = is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false);
+            match res {
+                Useful(unreachables) => {
+                    if let Some((this_column, other_columns)) = unreachables.split_last() {
+                        // We keep the union of unreachables found in the first column.
+                        unreachables_this_column.extend(this_column);
+                        // We keep the intersection of unreachables found in other columns.
+                        if unreachables_other_columns.is_empty() {
+                            unreachables_other_columns = other_columns.to_vec();
+                        } else {
+                            unreachables_other_columns = unreachables_other_columns
+                                .into_iter()
+                                .zip(other_columns)
+                                .map(|(x, y)| x.intersection(&y).copied().collect())
+                                .collect();
+                        }
+                    }
+                    any_is_useful = true;
+                }
+                NotUseful => {
+                    unreachables_this_column.insert(v.head().span);
+                }
+                UsefulWithWitness(_) => bug!(
+                    "encountered or-pat in the expansion of `_` during exhaustiveness checking"
+                ),
+            }
+
+            // If pattern has a guard don't add it to the matrix.
+            if !is_under_guard {
+                // We push the already-seen patterns into the matrix in order to detect redundant
+                // branches like `Some(_) | Some(0)`.
+                matrix.push(v);
+            }
+        }
+
+        return if any_is_useful {
+            let mut unreachables = if unreachables_other_columns.is_empty() {
+                let n_columns = v.len();
+                (0..n_columns - 1).map(|_| FxHashSet::default()).collect()
+            } else {
+                unreachables_other_columns
+            };
+            unreachables.push(unreachables_this_column);
+            Useful(unreachables)
+        } else {
+            NotUseful
+        };
+    }
+
+    // FIXME(Nadrieril): Hack to work around type normalization issues (see #72476).
+    let ty = matrix.heads().next().map(|r| r.ty).unwrap_or(v.head().ty);
+    let pcx = PatCtxt { cx, matrix, ty, span: v.head().span, is_top_level };
+
+    debug!("is_useful_expand_first_col: ty={:#?}, expanding {:#?}", pcx.ty, v.head());
+
+    let ret = v
+        .head_ctor(cx)
+        .split(pcx, Some(hir_id))
+        .into_iter()
+        .map(|ctor| {
+            // We cache the result of `Fields::wildcards` because it is used a lot.
+            let ctor_wild_subpatterns = Fields::wildcards(pcx, &ctor);
+            let matrix = pcx.matrix.specialize_constructor(pcx, &ctor, &ctor_wild_subpatterns);
+            let v = v.pop_head_constructor(&ctor_wild_subpatterns);
+            let usefulness =
+                is_useful(pcx.cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false);
+            usefulness.apply_constructor(pcx, &ctor, &ctor_wild_subpatterns)
+        })
+        .find(|result| result.is_useful())
+        .unwrap_or(NotUseful);
+    debug!("is_useful::returns({:#?}, {:#?}) = {:?}", matrix, v, ret);
+    ret
+}
+
+/// The arm of a match expression.
+#[derive(Clone, Copy)]
+crate struct MatchArm<'p, 'tcx> {
+    /// The pattern must have been lowered through `MatchVisitor::lower_pattern`.
+    crate pat: &'p super::Pat<'tcx>,
+    crate hir_id: HirId,
+    crate has_guard: bool,
+}
+
+/// The output of checking a match for exhaustiveness and arm reachability.
+crate struct UsefulnessReport<'p, 'tcx> {
+    /// For each arm of the input, whether that arm is reachable after the arms above it.
+    crate arm_usefulness: Vec<(MatchArm<'p, 'tcx>, Usefulness<'tcx>)>,
+    /// If the match is exhaustive, this is empty. If not, this contains witnesses for the lack of
+    /// exhaustiveness.
+    crate non_exhaustiveness_witnesses: Vec<super::Pat<'tcx>>,
+}
+
+/// The entrypoint for the usefulness algorithm. Computes whether a match is exhaustive and which
+/// of its arms are reachable.
+///
+/// Note: the input patterns must have been lowered through `MatchVisitor::lower_pattern`.
+crate fn compute_match_usefulness<'p, 'tcx>(
+    cx: &MatchCheckCtxt<'p, 'tcx>,
+    arms: &[MatchArm<'p, 'tcx>],
+    scrut_hir_id: HirId,
+    scrut_ty: Ty<'tcx>,
+) -> UsefulnessReport<'p, 'tcx> {
+    let mut matrix = Matrix::empty();
+    let arm_usefulness: Vec<_> = arms
+        .iter()
+        .copied()
+        .map(|arm| {
+            let v = PatStack::from_pattern(arm.pat);
+            let usefulness =
+                is_useful(cx, &matrix, &v, LeaveOutWitness, arm.hir_id, arm.has_guard, true);
+            if !arm.has_guard {
+                matrix.push(v);
+            }
+            (arm, usefulness)
+        })
+        .collect();
+
+    let wild_pattern = cx.pattern_arena.alloc(super::Pat::wildcard_from_ty(scrut_ty));
+    let v = PatStack::from_pattern(wild_pattern);
+    let usefulness = is_useful(cx, &matrix, &v, ConstructWitness, scrut_hir_id, false, true);
+    let non_exhaustiveness_witnesses = match usefulness {
+        NotUseful => vec![], // Wildcard pattern isn't useful, so the match is exhaustive.
+        UsefulWithWitness(pats) => {
+            if pats.is_empty() {
+                bug!("Exhaustiveness check returned no witnesses")
+            } else {
+                pats.into_iter().map(|w| w.single_pattern()).collect()
+            }
+        }
+        Useful(_) => bug!(),
+    };
+    UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses }
+}
index 0dfacd78908babccf05fc7bc6ea4a53e01ca8275..b5b34c7338d8869b16c397cb5444191a9c7bbba0 100644 (file)
@@ -510,7 +510,7 @@ fn report_unterminated_raw_string(
         FatalError.raise()
     }
 
-    /// Note: It was decided to not add a test case, because it would be to big.
+    /// Note: It was decided to not add a test case, because it would be too big.
     /// <https://github.com/rust-lang/rust/pull/50296#issuecomment-392135180>
     fn report_too_many_hashes(&self, start: BytePos, found: usize) -> ! {
         self.fatal_span_(
index f125a12147af5cf04149a4c98d4ea85d60e72e97..44999c9b63ab6c2c428475f38ec6fe9fd3c2b232 100644 (file)
@@ -1,21 +1,23 @@
 //! The main parser interface.
 
-#![feature(bool_to_option)]
 #![feature(crate_visibility_modifier)]
 #![feature(bindings_after_at)]
 #![feature(iter_order_by)]
 #![feature(or_patterns)]
 
 use rustc_ast as ast;
+use rustc_ast::attr::HasAttrs;
 use rustc_ast::token::{self, DelimToken, Nonterminal, Token, TokenKind};
 use rustc_ast::tokenstream::{self, LazyTokenStream, TokenStream, TokenTree};
 use rustc_ast_pretty::pprust;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Diagnostic, FatalError, Level, PResult};
 use rustc_session::parse::ParseSess;
 use rustc_span::{symbol::kw, FileName, SourceFile, Span, DUMMY_SP};
 
 use smallvec::SmallVec;
+use std::cell::RefCell;
 use std::mem;
 use std::path::Path;
 use std::str;
@@ -250,29 +252,23 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
     // before we fall back to the stringification.
 
     let convert_tokens =
-        |tokens: &Option<LazyTokenStream>| tokens.as_ref().map(|t| t.create_token_stream());
+        |tokens: Option<&LazyTokenStream>| tokens.as_ref().map(|t| t.create_token_stream());
 
     let tokens = match *nt {
         Nonterminal::NtItem(ref item) => prepend_attrs(&item.attrs, item.tokens.as_ref()),
-        Nonterminal::NtBlock(ref block) => convert_tokens(&block.tokens),
-        Nonterminal::NtStmt(ref stmt) => {
-            // FIXME: We currently only collect tokens for `:stmt`
-            // matchers in `macro_rules!` macros. When we start collecting
-            // tokens for attributes on statements, we will need to prepend
-            // attributes here
-            convert_tokens(&stmt.tokens)
-        }
-        Nonterminal::NtPat(ref pat) => convert_tokens(&pat.tokens),
-        Nonterminal::NtTy(ref ty) => convert_tokens(&ty.tokens),
+        Nonterminal::NtBlock(ref block) => convert_tokens(block.tokens.as_ref()),
+        Nonterminal::NtStmt(ref stmt) => prepend_attrs(stmt.attrs(), stmt.tokens()),
+        Nonterminal::NtPat(ref pat) => convert_tokens(pat.tokens.as_ref()),
+        Nonterminal::NtTy(ref ty) => convert_tokens(ty.tokens.as_ref()),
         Nonterminal::NtIdent(ident, is_raw) => {
             Some(tokenstream::TokenTree::token(token::Ident(ident.name, is_raw), ident.span).into())
         }
         Nonterminal::NtLifetime(ident) => {
             Some(tokenstream::TokenTree::token(token::Lifetime(ident.name), ident.span).into())
         }
-        Nonterminal::NtMeta(ref attr) => convert_tokens(&attr.tokens),
-        Nonterminal::NtPath(ref path) => convert_tokens(&path.tokens),
-        Nonterminal::NtVis(ref vis) => convert_tokens(&vis.tokens),
+        Nonterminal::NtMeta(ref attr) => convert_tokens(attr.tokens.as_ref()),
+        Nonterminal::NtPath(ref path) => convert_tokens(path.tokens.as_ref()),
+        Nonterminal::NtVis(ref vis) => convert_tokens(vis.tokens.as_ref()),
         Nonterminal::NtTT(ref tt) => Some(tt.clone().into()),
         Nonterminal::NtExpr(ref expr) | Nonterminal::NtLiteral(ref expr) => {
             if expr.tokens.is_none() {
@@ -282,6 +278,25 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
         }
     };
 
+    // Caches the stringification of 'good' `TokenStreams` which passed
+    // `tokenstream_probably_equal_for_proc_macro`. This allows us to avoid
+    // repeatedly stringifying and comparing the same `TokenStream` for deeply
+    // nested nonterminals.
+    //
+    // We cache by the strinification instead of the `TokenStream` to avoid
+    // needing to implement `Hash` for `TokenStream`. Note that it's possible to
+    // have two distinct `TokenStream`s that stringify to the same result
+    // (e.g. if they differ only in hygiene information). However, any
+    // information lost during the stringification process is also intentionally
+    // ignored by `tokenstream_probably_equal_for_proc_macro`, so it's fine
+    // that a single cache entry may 'map' to multiple distinct `TokenStream`s.
+    //
+    // This is a temporary hack to prevent compilation blowup on certain inputs.
+    // The entire pretty-print/retokenize process will be removed soon.
+    thread_local! {
+        static GOOD_TOKEN_CACHE: RefCell<FxHashSet<String>> = Default::default();
+    }
+
     // FIXME(#43081): Avoid this pretty-print + reparse hack
     // Pretty-print the AST struct without inserting any parenthesis
     // beyond those explicitly written by the user (e.g. `ExpnKind::Paren`).
@@ -289,7 +304,7 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
     // ever used for a comparison against the capture tokenstream.
     let source = pprust::nonterminal_to_string_no_extra_parens(nt);
     let filename = FileName::macro_expansion_source_code(&source);
-    let reparsed_tokens = parse_stream_from_source_str(filename, source, sess, Some(span));
+    let reparsed_tokens = parse_stream_from_source_str(filename, source.clone(), sess, Some(span));
 
     // During early phases of the compiler the AST could get modified
     // directly (e.g., attributes added or removed) and the internal cache
@@ -315,8 +330,13 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
     // modifications, including adding/removing typically non-semantic
     // tokens such as extra braces and commas, don't happen.
     if let Some(tokens) = tokens {
+        if GOOD_TOKEN_CACHE.with(|cache| cache.borrow().contains(&source)) {
+            return tokens;
+        }
+
         // Compare with a non-relaxed delim match to start.
         if tokenstream_probably_equal_for_proc_macro(&tokens, &reparsed_tokens, sess, false) {
+            GOOD_TOKEN_CACHE.with(|cache| cache.borrow_mut().insert(source.clone()));
             return tokens;
         }
 
@@ -325,6 +345,11 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
         // token stream to match up with inserted parenthesis in the reparsed stream.
         let source_with_parens = pprust::nonterminal_to_string(nt);
         let filename_with_parens = FileName::macro_expansion_source_code(&source_with_parens);
+
+        if GOOD_TOKEN_CACHE.with(|cache| cache.borrow().contains(&source_with_parens)) {
+            return tokens;
+        }
+
         let reparsed_tokens_with_parens = parse_stream_from_source_str(
             filename_with_parens,
             source_with_parens,
@@ -340,6 +365,7 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
             sess,
             true,
         ) {
+            GOOD_TOKEN_CACHE.with(|cache| cache.borrow_mut().insert(source.clone()));
             return tokens;
         }
 
@@ -419,9 +445,9 @@ fn break_tokens(tree: TokenTree) -> impl Iterator<Item = TokenTree> {
         // to iterate breaking tokens mutliple times. For example:
         // '[BinOpEq(Shr)] => [Gt, Ge] -> [Gt, Gt, Eq]'
         let mut token_trees: SmallVec<[_; 2]>;
-        if let TokenTree::Token(token) = &tree {
+        if let TokenTree::Token(token) = tree {
             let mut out = SmallVec::<[_; 2]>::new();
-            out.push(token.clone());
+            out.push(token);
             // Iterate to fixpoint:
             // * We start off with 'out' containing our initial token, and `temp` empty
             // * If we are able to break any tokens in `out`, then `out` will have
index 3738fbaeac84ffaeccd00bb6cfd14cdee0d3d0e2..fae09fa6fec65bcb43c283ab2088749427530925 100644 (file)
@@ -8,8 +8,9 @@
 
 use tracing::debug;
 
+// Public for rustfmt usage
 #[derive(Debug)]
-pub(super) enum InnerAttrPolicy<'a> {
+pub enum InnerAttrPolicy<'a> {
     Permitted,
     Forbidden { reason: &'a str, saw_doc_comment: bool, prev_attr_sp: Option<Span> },
 }
@@ -78,7 +79,8 @@ pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, Vec<ast::Attribut
 
     /// Matches `attribute = # ! [ meta_item ]`.
     /// `inner_parse_policy` prescribes how to handle inner attributes.
-    fn parse_attribute(
+    // Public for rustfmt usage.
+    pub fn parse_attribute(
         &mut self,
         inner_parse_policy: InnerAttrPolicy<'_>,
     ) -> PResult<'a, ast::Attribute> {
@@ -312,14 +314,13 @@ fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> {
 }
 
 pub fn maybe_needs_tokens(attrs: &[ast::Attribute]) -> bool {
+    // One of the attributes may either itself be a macro, or apply derive macros (`derive`),
+    // or expand to macro attributes (`cfg_attr`).
     attrs.iter().any(|attr| {
-        if let Some(ident) = attr.ident() {
+        attr.ident().map_or(true, |ident| {
             ident.name == sym::derive
-            // This might apply a custom attribute/derive
-            || ident.name == sym::cfg_attr
-            || !rustc_feature::is_builtin_attr_name(ident.name)
-        } else {
-            true
-        }
+                || ident.name == sym::cfg_attr
+                || !rustc_feature::is_builtin_attr_name(ident.name)
+        })
     })
 }
index cd3b8db2303b366a65d5a99d5e38876ad33d255b..350a372a684cc5e7b6f829f1e13026c0f61a37c7 100644 (file)
@@ -1808,9 +1808,13 @@ pub fn handle_ambiguous_unbraced_const_arg(
         return Ok(false); // Don't continue.
     }
 
-    /// Handle a generic const argument that had not been enclosed in braces, and suggest enclosing
-    /// it braces. In this situation, unlike in `handle_ambiguous_unbraced_const_arg`, this is
-    /// almost certainly a const argument, so we always offer a suggestion.
+    /// Attempt to parse a generic const argument that has not been enclosed in braces.
+    /// There are a limited number of expressions that are permitted without being encoded
+    /// in braces:
+    /// - Literals.
+    /// - Single-segment paths (i.e. standalone generic const parameters).
+    /// All other expressions that can be parsed will emit an error suggesting the expression be
+    /// wrapped in braces.
     pub fn handle_unambiguous_unbraced_const_arg(&mut self) -> PResult<'a, P<Expr>> {
         let start = self.token.span;
         let expr = self.parse_expr_res(Restrictions::CONST_EXPR, None).map_err(|mut err| {
index 40aa2db58c720f374d581be7962ac695d21c0c79..2a779c37b89627a10ae897b7c544e1797a919c74 100644 (file)
@@ -1213,14 +1213,20 @@ pub fn collect_tokens<R>(
         //
         // This also makes `Parser` very cheap to clone, since
         // there is no intermediate collection buffer to clone.
+        #[derive(Clone)]
         struct LazyTokenStreamImpl {
             start_token: (Token, Spacing),
             cursor_snapshot: TokenCursor,
             num_calls: usize,
             desugar_doc_comments: bool,
+            trailing_semi: bool,
         }
         impl CreateTokenStream for LazyTokenStreamImpl {
             fn create_token_stream(&self) -> TokenStream {
+                let mut num_calls = self.num_calls;
+                if self.trailing_semi {
+                    num_calls += 1;
+                }
                 // The token produced by the final call to `next` or `next_desugared`
                 // was not actually consumed by the callback. The combination
                 // of chaining the initial token and using `take` produces the desired
@@ -1228,17 +1234,25 @@ fn create_token_stream(&self) -> TokenStream {
                 // and omit the final token otherwise.
                 let mut cursor_snapshot = self.cursor_snapshot.clone();
                 let tokens = std::iter::once(self.start_token.clone())
-                    .chain((0..self.num_calls).map(|_| {
+                    .chain((0..num_calls).map(|_| {
                         if self.desugar_doc_comments {
                             cursor_snapshot.next_desugared()
                         } else {
                             cursor_snapshot.next()
                         }
                     }))
-                    .take(self.num_calls);
+                    .take(num_calls);
 
                 make_token_stream(tokens)
             }
+            fn add_trailing_semi(&self) -> Box<dyn CreateTokenStream> {
+                if self.trailing_semi {
+                    panic!("Called `add_trailing_semi` twice!");
+                }
+                let mut new = self.clone();
+                new.trailing_semi = true;
+                Box::new(new)
+            }
         }
 
         let lazy_impl = LazyTokenStreamImpl {
@@ -1246,6 +1260,7 @@ fn create_token_stream(&self) -> TokenStream {
             num_calls: self.token_cursor.num_next_calls - cursor_snapshot.num_next_calls,
             cursor_snapshot,
             desugar_doc_comments: self.desugar_doc_comments,
+            trailing_semi: false,
         };
         Ok((ret, Some(LazyTokenStream::new(lazy_impl))))
     }
index ab88362dad954900d4fcebe748048a63fb569ce5..c007f96a79800cb9b3b8055dc54998748b7ab618 100644 (file)
@@ -117,8 +117,8 @@ pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, Nonter
                 let (stmt, tokens) = self.collect_tokens(|this| this.parse_stmt())?;
                 match stmt {
                     Some(mut s) => {
-                        if s.tokens.is_none() {
-                            s.tokens = tokens;
+                        if s.tokens().is_none() {
+                            s.set_tokens(tokens);
                         }
                         token::NtStmt(s)
                     }
index 79e737490386c023eaa1d6842ffce0f4fafcca63..17e5bcf760504c944ba80eee89bf9137aeaae811 100644 (file)
@@ -3,10 +3,9 @@
 use crate::maybe_whole;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Token};
-use rustc_ast::{
-    self as ast, AngleBracketedArg, AngleBracketedArgs, GenericArg, ParenthesizedArgs,
-};
+use rustc_ast::{self as ast, AngleBracketedArg, AngleBracketedArgs, ParenthesizedArgs};
 use rustc_ast::{AnonConst, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode};
+use rustc_ast::{GenericArg, GenericArgs};
 use rustc_ast::{Path, PathSegment, QSelf};
 use rustc_errors::{pluralize, Applicability, PResult};
 use rustc_span::source_map::{BytePos, Span};
@@ -414,32 +413,40 @@ pub(super) fn parse_angle_args(&mut self) -> PResult<'a, Vec<AngleBracketedArg>>
 
     /// Parses a single argument in the angle arguments `<...>` of a path segment.
     fn parse_angle_arg(&mut self) -> PResult<'a, Option<AngleBracketedArg>> {
-        if self.check_ident() && self.look_ahead(1, |t| matches!(t.kind, token::Eq | token::Colon))
-        {
-            // Parse associated type constraint.
-            let lo = self.token.span;
-            let ident = self.parse_ident()?;
-            let kind = if self.eat(&token::Eq) {
-                let ty = self.parse_assoc_equality_term(ident, self.prev_token.span)?;
-                AssocTyConstraintKind::Equality { ty }
-            } else if self.eat(&token::Colon) {
-                let bounds = self.parse_generic_bounds(Some(self.prev_token.span))?;
-                AssocTyConstraintKind::Bound { bounds }
-            } else {
-                unreachable!();
-            };
+        let lo = self.token.span;
+        let arg = self.parse_generic_arg()?;
+        match arg {
+            Some(arg) => {
+                if self.check(&token::Colon) | self.check(&token::Eq) {
+                    let (ident, gen_args) = self.get_ident_from_generic_arg(arg, lo)?;
+                    let kind = if self.eat(&token::Colon) {
+                        // Parse associated type constraint bound.
+
+                        let bounds = self.parse_generic_bounds(Some(self.prev_token.span))?;
+                        AssocTyConstraintKind::Bound { bounds }
+                    } else if self.eat(&token::Eq) {
+                        // Parse associated type equality constraint
+
+                        let ty = self.parse_assoc_equality_term(ident, self.prev_token.span)?;
+                        AssocTyConstraintKind::Equality { ty }
+                    } else {
+                        unreachable!();
+                    };
 
-            let span = lo.to(self.prev_token.span);
+                    let span = lo.to(self.prev_token.span);
 
-            // Gate associated type bounds, e.g., `Iterator<Item: Ord>`.
-            if let AssocTyConstraintKind::Bound { .. } = kind {
-                self.sess.gated_spans.gate(sym::associated_type_bounds, span);
+                    // Gate associated type bounds, e.g., `Iterator<Item: Ord>`.
+                    if let AssocTyConstraintKind::Bound { .. } = kind {
+                        self.sess.gated_spans.gate(sym::associated_type_bounds, span);
+                    }
+                    let constraint =
+                        AssocTyConstraint { id: ast::DUMMY_NODE_ID, ident, gen_args, kind, span };
+                    Ok(Some(AngleBracketedArg::Constraint(constraint)))
+                } else {
+                    Ok(Some(AngleBracketedArg::Arg(arg)))
+                }
             }
-
-            let constraint = AssocTyConstraint { id: ast::DUMMY_NODE_ID, ident, kind, span };
-            Ok(Some(AngleBracketedArg::Constraint(constraint)))
-        } else {
-            Ok(self.parse_generic_arg()?.map(AngleBracketedArg::Arg))
+            _ => Ok(None),
         }
     }
 
@@ -489,6 +496,7 @@ fn parse_assoc_equality_term(&mut self, ident: Ident, eq: Span) -> PResult<'a, P
     /// - An expression surrounded in `{}`.
     /// - A literal.
     /// - A numeric literal prefixed by `-`.
+    /// - A single-segment path.
     pub(super) fn expr_is_valid_const_arg(&self, expr: &P<rustc_ast::Expr>) -> bool {
         match &expr.kind {
             ast::ExprKind::Block(_, _) | ast::ExprKind::Lit(_) => true,
@@ -496,6 +504,13 @@ pub(super) fn expr_is_valid_const_arg(&self, expr: &P<rustc_ast::Expr>) -> bool
                 ast::ExprKind::Lit(_) => true,
                 _ => false,
             },
+            // We can only resolve single-segment paths at the moment, because multi-segment paths
+            // require type-checking: see `visit_generic_arg` in `src/librustc_resolve/late.rs`.
+            ast::ExprKind::Path(None, path)
+                if path.segments.len() == 1 && path.segments[0].args.is_none() =>
+            {
+                true
+            }
             _ => false,
         }
     }
@@ -534,4 +549,54 @@ fn parse_generic_arg(&mut self) -> PResult<'a, Option<GenericArg>> {
         };
         Ok(Some(arg))
     }
+
+    fn get_ident_from_generic_arg(
+        &self,
+        gen_arg: GenericArg,
+        lo: Span,
+    ) -> PResult<'a, (Ident, Option<GenericArgs>)> {
+        let gen_arg_span = gen_arg.span();
+        match gen_arg {
+            GenericArg::Type(t) => match t.into_inner().kind {
+                ast::TyKind::Path(qself, mut path) => {
+                    if let Some(qself) = qself {
+                        let mut err = self.struct_span_err(
+                            gen_arg_span,
+                            "qualified paths cannot be used in associated type constraints",
+                        );
+                        err.span_label(
+                            qself.path_span,
+                            "not allowed in associated type constraints",
+                        );
+                        return Err(err);
+                    }
+                    if path.segments.len() == 1 {
+                        let path_seg = path.segments.remove(0);
+                        let ident = path_seg.ident;
+                        let gen_args = path_seg.args.map(|args| args.into_inner());
+                        return Ok((ident, gen_args));
+                    }
+                    let err = self.struct_span_err(
+                        path.span,
+                        "paths with multiple segments cannot be used in associated type constraints",
+                    );
+                    return Err(err);
+                }
+                _ => {
+                    let span = lo.to(self.prev_token.span);
+                    let err = self.struct_span_err(
+                        span,
+                        "only path types can be used in associated type constraints",
+                    );
+                    return Err(err);
+                }
+            },
+            _ => {
+                let span = lo.to(self.prev_token.span);
+                let err = self
+                    .struct_span_err(span, "only types can be used in associated type constraints");
+                return Err(err);
+            }
+        }
+    }
 }
index 131ff1ae6b3da9a92f4fb7938a89c9d72140630d..e974556f43a49eb7f30306f177665efa5eaf8302 100644 (file)
@@ -7,8 +7,10 @@
 use crate::maybe_whole;
 
 use rustc_ast as ast;
+use rustc_ast::attr::HasAttrs;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, TokenKind};
+use rustc_ast::tokenstream::LazyTokenStream;
 use rustc_ast::util::classify;
 use rustc_ast::{AttrStyle, AttrVec, Attribute, MacCall, MacCallStmt, MacStmtStyle};
 use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt, StmtKind, DUMMY_NODE_ID};
@@ -31,45 +33,75 @@ pub fn parse_stmt(&mut self) -> PResult<'a, Option<Stmt>> {
     }
 
     fn parse_stmt_without_recovery(&mut self) -> PResult<'a, Option<Stmt>> {
-        maybe_whole!(self, NtStmt, |x| Some(x));
-
-        let attrs = self.parse_outer_attributes()?;
+        let mut attrs = self.parse_outer_attributes()?;
+        let has_attrs = !attrs.is_empty();
         let lo = self.token.span;
 
-        let stmt = if self.eat_keyword(kw::Let) {
-            self.parse_local_mk(lo, attrs.into())?
-        } else if self.is_kw_followed_by_ident(kw::Mut) {
-            self.recover_stmt_local(lo, attrs.into(), "missing keyword", "let mut")?
-        } else if self.is_kw_followed_by_ident(kw::Auto) {
-            self.bump(); // `auto`
-            let msg = "write `let` instead of `auto` to introduce a new variable";
-            self.recover_stmt_local(lo, attrs.into(), msg, "let")?
-        } else if self.is_kw_followed_by_ident(sym::var) {
-            self.bump(); // `var`
-            let msg = "write `let` instead of `var` to introduce a new variable";
-            self.recover_stmt_local(lo, attrs.into(), msg, "let")?
-        } else if self.check_path() && !self.token.is_qpath_start() && !self.is_path_start_item() {
-            // We have avoided contextual keywords like `union`, items with `crate` visibility,
-            // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something
-            // that starts like a path (1 token), but it fact not a path.
-            // Also, we avoid stealing syntax from `parse_item_`.
-            self.parse_stmt_path_start(lo, attrs)?
-        } else if let Some(item) = self.parse_item_common(attrs.clone(), false, true, |_| true)? {
-            // FIXME: Bad copy of attrs
-            self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item)))
-        } else if self.eat(&token::Semi) {
-            // Do not attempt to parse an expression if we're done here.
-            self.error_outer_attrs(&attrs);
-            self.mk_stmt(lo, StmtKind::Empty)
-        } else if self.token != token::CloseDelim(token::Brace) {
-            // Remainder are line-expr stmts.
-            let e = self.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs.into()))?;
-            self.mk_stmt(lo.to(e.span), StmtKind::Expr(e))
+        maybe_whole!(self, NtStmt, |stmt| {
+            let mut stmt = stmt;
+            stmt.visit_attrs(|stmt_attrs| {
+                mem::swap(stmt_attrs, &mut attrs);
+                stmt_attrs.extend(attrs);
+            });
+            Some(stmt)
+        });
+
+        let parse_stmt_inner = |this: &mut Self| {
+            let stmt = if this.eat_keyword(kw::Let) {
+                this.parse_local_mk(lo, attrs.into())?
+            } else if this.is_kw_followed_by_ident(kw::Mut) {
+                this.recover_stmt_local(lo, attrs.into(), "missing keyword", "let mut")?
+            } else if this.is_kw_followed_by_ident(kw::Auto) {
+                this.bump(); // `auto`
+                let msg = "write `let` instead of `auto` to introduce a new variable";
+                this.recover_stmt_local(lo, attrs.into(), msg, "let")?
+            } else if this.is_kw_followed_by_ident(sym::var) {
+                this.bump(); // `var`
+                let msg = "write `let` instead of `var` to introduce a new variable";
+                this.recover_stmt_local(lo, attrs.into(), msg, "let")?
+            } else if this.check_path()
+                && !this.token.is_qpath_start()
+                && !this.is_path_start_item()
+            {
+                // We have avoided contextual keywords like `union`, items with `crate` visibility,
+                // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something
+                // that starts like a path (1 token), but it fact not a path.
+                // Also, we avoid stealing syntax from `parse_item_`.
+                this.parse_stmt_path_start(lo, attrs)?
+            } else if let Some(item) =
+                this.parse_item_common(attrs.clone(), false, true, |_| true)?
+            {
+                // FIXME: Bad copy of attrs
+                this.mk_stmt(lo.to(item.span), StmtKind::Item(P(item)))
+            } else if this.eat(&token::Semi) {
+                // Do not attempt to parse an expression if we're done here.
+                this.error_outer_attrs(&attrs);
+                this.mk_stmt(lo, StmtKind::Empty)
+            } else if this.token != token::CloseDelim(token::Brace) {
+                // Remainder are line-expr stmts.
+                let e = this.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs.into()))?;
+                this.mk_stmt(lo.to(e.span), StmtKind::Expr(e))
+            } else {
+                this.error_outer_attrs(&attrs);
+                return Ok(None);
+            };
+            Ok(Some(stmt))
+        };
+
+        let stmt = if has_attrs {
+            let (mut stmt, tokens) = self.collect_tokens(parse_stmt_inner)?;
+            if let Some(stmt) = &mut stmt {
+                // If we already have tokens (e.g. due to encounting an `NtStmt`),
+                // use those instead.
+                if stmt.tokens().is_none() {
+                    stmt.set_tokens(tokens);
+                }
+            }
+            stmt
         } else {
-            self.error_outer_attrs(&attrs);
-            return Ok(None);
+            parse_stmt_inner(self)?
         };
-        Ok(Some(stmt))
+        Ok(stmt)
     }
 
     fn parse_stmt_path_start(&mut self, lo: Span, attrs: Vec<Attribute>) -> PResult<'a, Stmt> {
@@ -107,7 +139,7 @@ fn parse_stmt_mac(&mut self, lo: Span, attrs: AttrVec, path: ast::Path) -> PResu
 
         let kind = if delim == token::Brace || self.token == token::Semi || self.token == token::Eof
         {
-            StmtKind::MacCall(P(MacCallStmt { mac, style, attrs }))
+            StmtKind::MacCall(P(MacCallStmt { mac, style, attrs, tokens: None }))
         } else {
             // Since none of the above applied, this is an expression statement macro.
             let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac), AttrVec::new());
@@ -219,7 +251,7 @@ fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P<Local>> {
             }
         };
         let hi = if self.token == token::Semi { self.token.span } else { self.prev_token.span };
-        Ok(P(ast::Local { ty, pat, init, id: DUMMY_NODE_ID, span: lo.to(hi), attrs }))
+        Ok(P(ast::Local { ty, pat, init, id: DUMMY_NODE_ID, span: lo.to(hi), attrs, tokens: None }))
     }
 
     /// Parses the RHS of a local variable declaration (e.g., '= 14;').
@@ -376,6 +408,12 @@ pub fn parse_full_stmt(
             None => return Ok(None),
         };
 
+        let add_semi_token = |tokens: Option<&mut LazyTokenStream>| {
+            if let Some(tokens) = tokens {
+                *tokens = tokens.add_trailing_semi();
+            }
+        };
+
         let mut eat_semi = true;
         match stmt.kind {
             // Expression without semicolon.
@@ -417,6 +455,7 @@ pub fn parse_full_stmt(
                     *expr = self.mk_expr_err(sp);
                 }
             }
+            StmtKind::Expr(_) | StmtKind::MacCall(_) => {}
             StmtKind::Local(ref mut local) => {
                 if let Err(e) = self.expect_semi() {
                     // We might be at the `,` in `let x = foo<bar, baz>;`. Try to recover.
@@ -430,13 +469,18 @@ pub fn parse_full_stmt(
                     }
                 }
                 eat_semi = false;
+                // We just checked that there's a semicolon in the tokenstream,
+                // so capture it
+                add_semi_token(local.tokens.as_mut());
             }
-            StmtKind::Empty => eat_semi = false,
-            _ => {}
+            StmtKind::Empty | StmtKind::Item(_) | StmtKind::Semi(_) => eat_semi = false,
         }
 
         if eat_semi && self.eat(&token::Semi) {
             stmt = stmt.add_trailing_semicolon();
+            // We just checked that we have a semicolon in the tokenstream,
+            // so capture it
+            add_semi_token(stmt.tokens_mut());
         }
         stmt.span = stmt.span.to(self.prev_token.span);
         Ok(Some(stmt))
@@ -447,7 +491,7 @@ pub(super) fn mk_block(&self, stmts: Vec<Stmt>, rules: BlockCheckMode, span: Spa
     }
 
     pub(super) fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt {
-        Stmt { id: DUMMY_NODE_ID, kind, span, tokens: None }
+        Stmt { id: DUMMY_NODE_ID, kind, span }
     }
 
     pub(super) fn mk_stmt_err(&self, span: Span) -> Stmt {
index 7679582f8811e39b2534d0f79f4e8ab1d7f46188..9c0234953bba996955aa9ca00172954cf30d7470 100644 (file)
@@ -89,6 +89,8 @@ fn check_attributes(
                 self.check_allow_internal_unstable(&attr, span, target, &attrs)
             } else if self.tcx.sess.check_name(attr, sym::rustc_allow_const_fn_unstable) {
                 self.check_rustc_allow_const_fn_unstable(hir_id, &attr, span, target)
+            } else if self.tcx.sess.check_name(attr, sym::naked) {
+                self.check_naked(attr, span, target)
             } else {
                 // lint-only checks
                 if self.tcx.sess.check_name(attr, sym::cold) {
@@ -162,6 +164,25 @@ fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Tar
         }
     }
 
+    /// Checks if `#[naked]` is applied to a function definition.
+    fn check_naked(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
+        match target {
+            Target::Fn
+            | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
+            _ => {
+                self.tcx
+                    .sess
+                    .struct_span_err(
+                        attr.span,
+                        "attribute should be applied to a function definition",
+                    )
+                    .span_label(*span, "not a function definition")
+                    .emit();
+                false
+            }
+        }
+    }
+
     /// Checks if a `#[track_caller]` is applied to a non-naked function. Returns `true` if valid.
     fn check_track_caller(
         &self,
@@ -171,7 +192,7 @@ fn check_track_caller(
         target: Target,
     ) -> bool {
         match target {
-            _ if self.tcx.sess.contains_name(attrs, sym::naked) => {
+            _ if attrs.iter().any(|attr| attr.has_name(sym::naked)) => {
                 struct_span_err!(
                     self.tcx.sess,
                     *attr_span,
index f567dd83bc13dc6b4b6ae3aee3fc1d04b3b60b4f..b87b13cff8053a35e55b367854cbf0d4900a55ce 100644 (file)
@@ -190,7 +190,7 @@ fn visit_node(&mut self, node: Node<'tcx>) {
 
                     intravisit::walk_item(self, &item);
                 }
-                hir::ItemKind::ForeignMod(..) => {}
+                hir::ItemKind::ForeignMod { .. } => {}
                 _ => {
                     intravisit::walk_item(self, &item);
                 }
@@ -447,6 +447,8 @@ fn visit_trait_item(&mut self, _item: &hir::TraitItem<'_>) {
     fn visit_impl_item(&mut self, _item: &hir::ImplItem<'_>) {
         // ignore: we are handling this in `visit_item` above
     }
+
+    fn visit_foreign_item(&mut self, _item: &'v hir::ForeignItem<'v>) {}
 }
 
 fn create_and_seed_worklist<'tcx>(
index 0f4aa72d5c47b0f05835f17253ee08849fa8f644..699c96bc49d5990645ef102f134d256f7c881d2b 100644 (file)
@@ -37,6 +37,10 @@ fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
     fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
         self.observe_item(&impl_item.attrs, impl_item.hir_id);
     }
+
+    fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem<'_>) {
+        self.observe_item(foreign_item.attrs, foreign_item.hir_id);
+    }
 }
 
 impl<'tcx> DiagnosticItemCollector<'tcx> {
@@ -100,17 +104,9 @@ fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> FxHashMap<Symbol, DefId> {
 
     // Collect diagnostic items in this crate.
     tcx.hir().krate().visit_all_item_likes(&mut collector);
-    // FIXME(visit_all_item_likes): Foreign items are not visited
-    // here, so we have to manually look at them for now.
-    for (_, foreign_module) in tcx.foreign_modules(LOCAL_CRATE).iter() {
-        for &foreign_item in foreign_module.foreign_items.iter() {
-            match tcx.hir().get(tcx.hir().local_def_id_to_hir_id(foreign_item.expect_local())) {
-                hir::Node::ForeignItem(item) => {
-                    collector.observe_item(item.attrs, item.hir_id);
-                }
-                item => bug!("unexpected foreign item {:?}", item),
-            }
-        }
+
+    for m in tcx.hir().krate().exported_macros {
+        collector.observe_item(m.attrs, m.hir_id);
     }
 
     collector.items
index e87adb378e7f77fe3166b7952dcb06df89e609ff..5ff631a24573f16ab062a2291703d98e882c0d4a 100644 (file)
@@ -2,7 +2,7 @@
 use rustc_errors::struct_span_err;
 use rustc_hir::def_id::{CrateNum, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_hir::{HirId, ImplItem, Item, ItemKind, TraitItem};
+use rustc_hir::{ForeignItem, HirId, ImplItem, Item, ItemKind, TraitItem};
 use rustc_middle::hir::map::Map;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
@@ -45,6 +45,10 @@ fn visit_trait_item(&mut self, _trait_item: &'tcx TraitItem<'tcx>) {
     fn visit_impl_item(&mut self, _impl_item: &'tcx ImplItem<'tcx>) {
         // Entry fn is never a trait item.
     }
+
+    fn visit_foreign_item(&mut self, _: &'tcx ForeignItem<'tcx>) {
+        // Entry fn is never a foreign item.
+    }
 }
 
 fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(LocalDefId, EntryFnType)> {
index 6d1a5fcc10b0ff14ff9c10e316e0358d3bef0370..c7e057927ab42065d330075261710d03d4e9526c 100644 (file)
@@ -68,6 +68,11 @@ fn visit_impl_item(&mut self, i: &'hir hir::ImplItem<'hir>) {
         let mut inner_visitor = self.new_inner_visitor(self.hir_map);
         inner_visitor.check(i.hir_id, |this| intravisit::walk_impl_item(this, i));
     }
+
+    fn visit_foreign_item(&mut self, i: &'hir hir::ForeignItem<'hir>) {
+        let mut inner_visitor = self.new_inner_visitor(self.hir_map);
+        inner_visitor.check(i.hir_id, |this| intravisit::walk_foreign_item(this, i));
+    }
 }
 
 impl<'a, 'hir> HirIdValidator<'a, 'hir> {
index 0ae0c381a110b13129e979795a3f58685677ac81..3132661e5f51608fff49051bc09640f7b3c25f7d 100644 (file)
@@ -54,6 +54,8 @@ fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
             impl_item.attrs,
         )
     }
+
+    fn visit_foreign_item(&mut self, _: &hir::ForeignItem<'_>) {}
 }
 
 impl LanguageItemCollector<'tcx> {
index 504cbbfcb765f92580fce50c42253d9b4ebe169f..9e83cbd668050e84b491391d2b636c8ecd97b2d5 100644 (file)
@@ -40,6 +40,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
 
     fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) {}
     fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {}
+    fn visit_foreign_item(&mut self, _: &'tcx hir::ForeignItem<'tcx>) {}
 }
 
 impl LayoutTest<'tcx> {
index c32c9c8eaa68c09dd6081c65a3089ea3c49aa7a6..9759a500e061980d7d4898459f68a227a7553fd4 100644 (file)
@@ -7,6 +7,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(const_fn)]
 #![feature(const_panic)]
+#![feature(crate_visibility_modifier)]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
 #![feature(or_patterns)]
@@ -32,6 +33,7 @@
 mod lib_features;
 mod liveness;
 pub mod loops;
+mod naked_functions;
 mod reachable;
 mod region;
 pub mod stability;
@@ -46,6 +48,7 @@ pub fn provide(providers: &mut Providers) {
     lang_items::provide(providers);
     lib_features::provide(providers);
     loops::provide(providers);
+    naked_functions::provide(providers);
     liveness::provide(providers);
     intrinsicck::provide(providers);
     reachable::provide(providers);
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
new file mode 100644 (file)
index 0000000..6ef45cd
--- /dev/null
@@ -0,0 +1,113 @@
+use rustc_hir as hir;
+use rustc_hir::def_id::LocalDefId;
+use rustc_hir::intravisit::{ErasedMap, FnKind, NestedVisitorMap, Visitor};
+use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::TyCtxt;
+use rustc_span::symbol::sym;
+use rustc_span::Span;
+
+fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
+    tcx.hir().visit_item_likes_in_module(
+        module_def_id,
+        &mut CheckNakedFunctions { tcx }.as_deep_visitor(),
+    );
+}
+
+crate fn provide(providers: &mut Providers) {
+    *providers = Providers { check_mod_naked_functions, ..*providers };
+}
+
+struct CheckNakedFunctions<'tcx> {
+    tcx: TyCtxt<'tcx>,
+}
+
+impl<'tcx> Visitor<'tcx> for CheckNakedFunctions<'tcx> {
+    type Map = ErasedMap<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::None
+    }
+
+    fn visit_fn(
+        &mut self,
+        fk: FnKind<'v>,
+        _fd: &'tcx hir::FnDecl<'tcx>,
+        body_id: hir::BodyId,
+        _span: Span,
+        _hir_id: hir::HirId,
+    ) {
+        match fk {
+            // Rejected during attribute check. Do not validate further.
+            FnKind::Closure(..) => return,
+            FnKind::ItemFn(..) | FnKind::Method(..) => {}
+        }
+
+        let naked = fk.attrs().iter().any(|attr| attr.has_name(sym::naked));
+        if naked {
+            let body = self.tcx.hir().body(body_id);
+            check_params(self.tcx, body);
+            check_body(self.tcx, body);
+        }
+    }
+}
+
+/// Checks that parameters don't use patterns. Mirrors the checks for function declarations.
+fn check_params(tcx: TyCtxt<'_>, body: &hir::Body<'_>) {
+    for param in body.params {
+        match param.pat.kind {
+            hir::PatKind::Wild
+            | hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, _, None) => {}
+            _ => {
+                tcx.sess
+                    .struct_span_err(
+                        param.pat.span,
+                        "patterns not allowed in naked function parameters",
+                    )
+                    .emit();
+            }
+        }
+    }
+}
+
+/// Checks that function parameters aren't referenced in the function body.
+fn check_body<'tcx>(tcx: TyCtxt<'tcx>, body: &'tcx hir::Body<'tcx>) {
+    let mut params = hir::HirIdSet::default();
+    for param in body.params {
+        param.pat.each_binding(|_binding_mode, hir_id, _span, _ident| {
+            params.insert(hir_id);
+        });
+    }
+    CheckBody { tcx, params }.visit_body(body);
+}
+
+struct CheckBody<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    params: hir::HirIdSet,
+}
+
+impl<'tcx> Visitor<'tcx> for CheckBody<'tcx> {
+    type Map = ErasedMap<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::None
+    }
+
+    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
+        if let hir::ExprKind::Path(hir::QPath::Resolved(
+            _,
+            hir::Path { res: hir::def::Res::Local(var_hir_id), .. },
+        )) = expr.kind
+        {
+            if self.params.contains(var_hir_id) {
+                self.tcx
+                    .sess
+                    .struct_span_err(
+                        expr.span,
+                        "use of parameters not allowed inside naked functions",
+                    )
+                    .emit();
+            }
+        }
+        hir::intravisit::walk_expr(self, expr);
+    }
+}
index 8d5c980609cd9a99c7d921e1ce4acf19bfadd8ce..fde83af99a569bdbd85803a957e36d78520ec727 100644 (file)
@@ -262,7 +262,7 @@ fn propagate_node(&mut self, node: &Node<'tcx>, search_item: LocalDefId) {
                     | hir::ItemKind::TyAlias(..)
                     | hir::ItemKind::Static(..)
                     | hir::ItemKind::Mod(..)
-                    | hir::ItemKind::ForeignMod(..)
+                    | hir::ItemKind::ForeignMod { .. }
                     | hir::ItemKind::Impl { .. }
                     | hir::ItemKind::Trait(..)
                     | hir::ItemKind::TraitAlias(..)
@@ -378,6 +378,10 @@ fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {
         // processed in visit_item above
     }
+
+    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {
+        // We never export foreign functions as they have no body to export.
+    }
 }
 
 fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> FxHashSet<LocalDefId> {
index 04b5c65e464fb5e52eec4ad4396ac17c29a3c604..f6bbbd80bf1eb0bc174c5d66887049bea027b0a2 100644 (file)
@@ -326,7 +326,7 @@ fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
             // they don't have their own stability. They still can be annotated as unstable
             // and propagate this unstability to children, but this annotation is completely
             // optional. They inherit stability from their parents when unannotated.
-            hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod(..) => {
+            hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod { .. } => {
                 self.in_trait_impl = false;
                 kind = AnnotationKind::Container;
             }
@@ -499,7 +499,7 @@ fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
         // optional. They inherit stability from their parents when unannotated.
         if !matches!(
             i.kind,
-            hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod(..)
+            hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod { .. }
         ) {
             self.check_missing_stability(i.hir_id, i.span);
         }
index d16dd701a120bfa36a01133bdb112ecb99cdf4c7..4796d9a80b69af7891d552b94378f41876962d90 100644 (file)
@@ -25,6 +25,8 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
     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<'_>) {}
 }
 
 /// Finds the function marked with `#[plugin_registrar]`, if any.
index 4a0d356d3377ba04eeb2ba8b13886c51ec547b52..4414bf57c6b7db5077c1e3a62565e447108c3a4d 100644 (file)
@@ -592,7 +592,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                 Option::<AccessLevel>::of_impl(item.hir_id, self.tcx, &self.access_levels)
             }
             // Foreign modules inherit level from parents.
-            hir::ItemKind::ForeignMod(..) => self.prev_level,
+            hir::ItemKind::ForeignMod { .. } => self.prev_level,
             // Other `pub` items inherit levels from parents.
             hir::ItemKind::Const(..)
             | hir::ItemKind::Enum(..)
@@ -654,10 +654,10 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                     }
                 }
             }
-            hir::ItemKind::ForeignMod(ref foreign_mod) => {
-                for foreign_item in foreign_mod.items {
+            hir::ItemKind::ForeignMod { items, .. } => {
+                for foreign_item in items {
                     if foreign_item.vis.node.is_pub() {
-                        self.update(foreign_item.hir_id, item_level);
+                        self.update(foreign_item.id.hir_id, item_level);
                     }
                 }
             }
@@ -691,7 +691,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
             hir::ItemKind::GlobalAsm(..) => {}
             hir::ItemKind::OpaqueTy(..) => {
                 // HACK(jynelson): trying to infer the type of `impl trait` breaks `async-std` (and `pub async fn` in general)
-                // Since rustdoc never need to do codegen and doesn't care about link-time reachability,
+                // Since rustdoc never needs to do codegen and doesn't care about link-time reachability,
                 // mark this as unreachable.
                 // See https://github.com/rust-lang/rust/issues/75100
                 if !self.tcx.sess.opts.actually_rustdoc {
@@ -770,11 +770,11 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                 }
             }
             // Visit everything, but foreign items have their own levels.
-            hir::ItemKind::ForeignMod(ref foreign_mod) => {
-                for foreign_item in foreign_mod.items {
-                    let foreign_item_level = self.get(foreign_item.hir_id);
+            hir::ItemKind::ForeignMod { items, .. } => {
+                for foreign_item in items {
+                    let foreign_item_level = self.get(foreign_item.id.hir_id);
                     if foreign_item_level.is_some() {
-                        self.reach(foreign_item.hir_id, foreign_item_level)
+                        self.reach(foreign_item.id.hir_id, foreign_item_level)
                             .generics()
                             .predicates()
                             .ty();
@@ -1430,7 +1430,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
 
             // An `extern {}` doesn't introduce a new privacy
             // namespace (the contents have their own privacies).
-            hir::ItemKind::ForeignMod(_) => {}
+            hir::ItemKind::ForeignMod { .. } => {}
 
             hir::ItemKind::Trait(.., ref bounds, _) => {
                 if !self.trait_is_public(item.hir_id) {
@@ -1948,10 +1948,10 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                 }
             }
             // Subitems of foreign modules have their own publicity.
-            hir::ItemKind::ForeignMod(ref foreign_mod) => {
-                for foreign_item in foreign_mod.items {
-                    let vis = tcx.visibility(tcx.hir().local_def_id(foreign_item.hir_id));
-                    self.check(foreign_item.hir_id, vis).generics().predicates().ty();
+            hir::ItemKind::ForeignMod { items, .. } => {
+                for foreign_item in items {
+                    let vis = tcx.visibility(tcx.hir().local_def_id(foreign_item.id.hir_id));
+                    self.check(foreign_item.id.hir_id, vis).generics().predicates().ty();
                 }
             }
             // Subitems of structs and unions have their own publicity.
index 7808a28dff0b7ed220cb17f4eb0359f437b8c484..3d9e739cd28c7e92803e7c408afbbd633e3f6c4c 100644 (file)
@@ -44,7 +44,7 @@
 
 use super::{DepContext, DepKind};
 
-use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 
 use std::fmt;
@@ -53,7 +53,7 @@
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
 pub struct DepNode<K> {
     pub kind: K,
-    pub hash: Fingerprint,
+    pub hash: PackedFingerprint,
 }
 
 impl<K: DepKind> DepNode<K> {
@@ -62,7 +62,7 @@ impl<K: DepKind> DepNode<K> {
     /// does not require any parameters.
     pub fn new_no_params(kind: K) -> DepNode<K> {
         debug_assert!(!kind.has_params());
-        DepNode { kind, hash: Fingerprint::ZERO }
+        DepNode { kind, hash: Fingerprint::ZERO.into() }
     }
 
     pub fn construct<Ctxt, Key>(tcx: Ctxt, kind: K, arg: &Key) -> DepNode<K>
@@ -71,7 +71,7 @@ pub fn construct<Ctxt, Key>(tcx: Ctxt, kind: K, arg: &Key) -> DepNode<K>
         Key: DepNodeParams<Ctxt>,
     {
         let hash = arg.to_fingerprint(tcx);
-        let dep_node = DepNode { kind, hash };
+        let dep_node = DepNode { kind, hash: hash.into() };
 
         #[cfg(debug_assertions)]
         {
index d9b687c48af01bb0feb29c075bc2ad3e9c6bc655..617ec84ae71a91226689b2bb4615032d990b9210 100644 (file)
@@ -976,7 +976,7 @@ fn complete_anon_task(&self, kind: K, task_deps: TaskDeps<K>) -> DepNodeIndex {
             // Fingerprint::combine() is faster than sending Fingerprint
             // through the StableHasher (at least as long as StableHasher
             // is so slow).
-            hash: self.anon_id_seed.combine(hasher.finish()),
+            hash: self.anon_id_seed.combine(hasher.finish()).into(),
         };
 
         self.intern_node(target_dep_node, task_deps.reads, Fingerprint::ZERO)
index c1d3210b61768308ca310fc8f201a9c8ea23b4f6..5fed500390b68a911173673afeef76882389a9ef 100644 (file)
@@ -33,11 +33,11 @@ pub struct QueryInfo<Q> {
 
 pub(crate) type QueryMap<D, Q> = FxHashMap<QueryJobId<D>, QueryJobInfo<D, Q>>;
 
-/// A value uniquely identifiying an active query job within a shard in the query cache.
+/// A value uniquely identifying an active query job within a shard in the query cache.
 #[derive(Copy, Clone, Eq, PartialEq, Hash)]
 pub struct QueryShardJobId(pub NonZeroU32);
 
-/// A value uniquely identifiying an active query job.
+/// A value uniquely identifying an active query job.
 #[derive(Copy, Clone, Eq, PartialEq, Hash)]
 pub struct QueryJobId<D> {
     /// Which job within a shard is this
@@ -536,7 +536,7 @@ fn remove_cycle<CTX: QueryContext>(
         };
 
         // We unwrap `waiter` here since there must always be one
-        // edge which is resumeable / waited using a query latch
+        // edge which is resumable / waited using a query latch
         let (waitee_query, waiter_idx) = waiter.unwrap();
 
         // Extract the waiter we want to resume
index 493b9f15271ef8258fbf63f8846bdc75fb85690d..6d7e4ebc253bd3dc75f1cd8713a79ed83d8e60b7 100644 (file)
@@ -1155,14 +1155,18 @@ fn contains_macro_use(&mut self, attrs: &[ast::Attribute]) -> bool {
         false
     }
 
-    fn visit_invoc(&mut self, id: NodeId) -> MacroRulesScopeRef<'a> {
+    fn visit_invoc(&mut self, id: NodeId) -> ExpnId {
         let invoc_id = id.placeholder_to_expn_id();
-
-        self.parent_scope.module.unexpanded_invocations.borrow_mut().insert(invoc_id);
-
         let old_parent_scope = self.r.invocation_parent_scopes.insert(invoc_id, self.parent_scope);
         assert!(old_parent_scope.is_none(), "invocation data is reset for an invocation");
+        invoc_id
+    }
 
+    /// Visit invocation in context in which it can emit a named item (possibly `macro_rules`)
+    /// directly into its parent scope's module.
+    fn visit_invoc_in_module(&mut self, id: NodeId) -> MacroRulesScopeRef<'a> {
+        let invoc_id = self.visit_invoc(id);
+        self.parent_scope.module.unexpanded_invocations.borrow_mut().insert(invoc_id);
         self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Invocation(invoc_id))
     }
 
@@ -1291,7 +1295,7 @@ fn visit_item(&mut self, item: &'b Item) {
                 return;
             }
             ItemKind::MacCall(..) => {
-                self.parent_scope.macro_rules = self.visit_invoc(item.id);
+                self.parent_scope.macro_rules = self.visit_invoc_in_module(item.id);
                 return;
             }
             ItemKind::Mod(..) => self.contains_macro_use(&item.attrs),
@@ -1309,7 +1313,7 @@ fn visit_item(&mut self, item: &'b Item) {
 
     fn visit_stmt(&mut self, stmt: &'b ast::Stmt) {
         if let ast::StmtKind::MacCall(..) = stmt.kind {
-            self.parent_scope.macro_rules = self.visit_invoc(stmt.id);
+            self.parent_scope.macro_rules = self.visit_invoc_in_module(stmt.id);
         } else {
             visit::walk_stmt(self, stmt);
         }
@@ -1317,7 +1321,7 @@ fn visit_stmt(&mut self, stmt: &'b ast::Stmt) {
 
     fn visit_foreign_item(&mut self, foreign_item: &'b ForeignItem) {
         if let ForeignItemKind::MacCall(_) = foreign_item.kind {
-            self.visit_invoc(foreign_item.id);
+            self.visit_invoc_in_module(foreign_item.id);
             return;
         }
 
@@ -1336,7 +1340,14 @@ fn visit_block(&mut self, block: &'b Block) {
 
     fn visit_assoc_item(&mut self, item: &'b AssocItem, ctxt: AssocCtxt) {
         if let AssocItemKind::MacCall(_) = item.kind {
-            self.visit_invoc(item.id);
+            match ctxt {
+                AssocCtxt::Trait => {
+                    self.visit_invoc_in_module(item.id);
+                }
+                AssocCtxt::Impl => {
+                    self.visit_invoc(item.id);
+                }
+            }
             return;
         }
 
@@ -1460,7 +1471,7 @@ fn visit_struct_field(&mut self, sf: &'b ast::StructField) {
     // type and value namespaces.
     fn visit_variant(&mut self, variant: &'b ast::Variant) {
         if variant.is_placeholder {
-            self.visit_invoc(variant.id);
+            self.visit_invoc_in_module(variant.id);
             return;
         }
 
index acd88af1806ca696c4219537263ad64832cfa14e..809de9beff625a7b8fd8cb1f605e6f33eceade89 100644 (file)
@@ -1,7 +1,6 @@
 use std::cmp::Reverse;
 use std::ptr;
 
-use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_ast::{self as ast, Path};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashSet;
@@ -14,6 +13,7 @@
 use rustc_middle::ty::{self, DefIdTree};
 use rustc_session::Session;
 use rustc_span::hygiene::MacroKind;
+use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, MultiSpan, Span};
@@ -143,7 +143,7 @@ impl<'a> Resolver<'a> {
                     _ => {
                         bug!(
                             "GenericParamsFromOuterFunction should only be used with Res::SelfTy, \
-                            DefKind::TyParam"
+                            DefKind::TyParam or DefKind::ConstParam"
                         );
                     }
                 }
@@ -481,6 +481,7 @@ impl<'a> Resolver<'a> {
                         name
                     ));
                 }
+                err.help("use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions");
 
                 err
             }
@@ -609,7 +610,7 @@ fn early_lookup_typo_candidate(
                     }
                 }
                 Scope::DeriveHelpersCompat => {
-                    let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
+                    let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat);
                     if filter_fn(res) {
                         for derive in parent_scope.derives {
                             let parent_scope = &ParentScope { derives: &[], ..*parent_scope };
@@ -715,7 +716,7 @@ fn early_lookup_typo_candidate(
         suggestions.sort_by_cached_key(|suggestion| suggestion.candidate.as_str());
 
         match find_best_match_for_name(
-            suggestions.iter().map(|suggestion| &suggestion.candidate),
+            &suggestions.iter().map(|suggestion| suggestion.candidate).collect::<Vec<Symbol>>(),
             ident.name,
             None,
         ) {
index 026cf8be73801043ba803177514dc0b978116106..cb1f0834ce7acd3d763f6f6d3b10a17a39a12330 100644 (file)
@@ -10,7 +10,6 @@
 use crate::{NameBinding, NameBindingKind, PathResult, PrivacyError, ToNameBinding};
 
 use rustc_ast::unwrap_or;
-use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_ast::NodeId;
 use rustc_ast_lowering::ResolverAstLowering;
 use rustc_data_structures::fx::FxHashSet;
@@ -25,6 +24,7 @@
 use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_session::DiagnosticMessageId;
 use rustc_span::hygiene::ExpnId;
+use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::{MultiSpan, Span};
 
@@ -1096,33 +1096,37 @@ fn finalize_import(&mut self, import: &'b Import<'b>) -> Option<UnresolvedImport
                     _ => None,
                 };
                 let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter());
-                let names = resolutions.filter_map(|(BindingKey { ident: i, .. }, resolution)| {
-                    if *i == ident {
-                        return None;
-                    } // Never suggest the same name
-                    match *resolution.borrow() {
-                        NameResolution { binding: Some(name_binding), .. } => {
-                            match name_binding.kind {
-                                NameBindingKind::Import { binding, .. } => {
-                                    match binding.kind {
-                                        // Never suggest the name that has binding error
-                                        // i.e., the name that cannot be previously resolved
-                                        NameBindingKind::Res(Res::Err, _) => None,
-                                        _ => Some(&i.name),
+                let names = resolutions
+                    .filter_map(|(BindingKey { ident: i, .. }, resolution)| {
+                        if *i == ident {
+                            return None;
+                        } // Never suggest the same name
+                        match *resolution.borrow() {
+                            NameResolution { binding: Some(name_binding), .. } => {
+                                match name_binding.kind {
+                                    NameBindingKind::Import { binding, .. } => {
+                                        match binding.kind {
+                                            // Never suggest the name that has binding error
+                                            // i.e., the name that cannot be previously resolved
+                                            NameBindingKind::Res(Res::Err, _) => None,
+                                            _ => Some(i.name),
+                                        }
                                     }
+                                    _ => Some(i.name),
                                 }
-                                _ => Some(&i.name),
                             }
+                            NameResolution { ref single_imports, .. }
+                                if single_imports.is_empty() =>
+                            {
+                                None
+                            }
+                            _ => Some(i.name),
                         }
-                        NameResolution { ref single_imports, .. } if single_imports.is_empty() => {
-                            None
-                        }
-                        _ => Some(&i.name),
-                    }
-                });
+                    })
+                    .collect::<Vec<Symbol>>();
 
                 let lev_suggestion =
-                    find_best_match_for_name(names, ident.name, None).map(|suggestion| {
+                    find_best_match_for_name(&names, ident.name, None).map(|suggestion| {
                         (
                             vec![(ident.span, suggestion.to_string())],
                             String::from("a similar name exists in the module"),
index 2473436a91675b14cbd9c3afe1193deb1ff4b4b0..6ce299a94170841f3f9a3be29d8f0cefdf999c13 100644 (file)
@@ -5,7 +5,6 @@
 use crate::{CrateLint, Module, ModuleKind, ModuleOrUniformRoot};
 use crate::{PathResult, PathSource, Segment};
 
-use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_ast::visit::FnKind;
 use rustc_ast::{self as ast, Expr, ExprKind, Item, ItemKind, NodeId, Path, Ty, TyKind};
 use rustc_ast_pretty::pprust::path_segment_to_string;
@@ -18,6 +17,7 @@
 use rustc_hir::PrimTy;
 use rustc_session::parse::feature_err;
 use rustc_span::hygiene::MacroKind;
+use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP};
 
@@ -1206,7 +1206,7 @@ fn lookup_typo_candidate(
         names.sort_by_cached_key(|suggestion| suggestion.candidate.as_str());
 
         match find_best_match_for_name(
-            names.iter().map(|suggestion| &suggestion.candidate),
+            &names.iter().map(|suggestion| suggestion.candidate).collect::<Vec<Symbol>>(),
             name,
             None,
         ) {
@@ -1592,9 +1592,10 @@ fn suggest_using_enum_variant(
             .bindings
             .iter()
             .filter(|(id, _)| id.span.ctxt() == label.span.ctxt())
-            .map(|(id, _)| &id.name);
+            .map(|(id, _)| id.name)
+            .collect::<Vec<Symbol>>();
 
-        find_best_match_for_name(names, label.name, None).map(|symbol| {
+        find_best_match_for_name(&names, label.name, None).map(|symbol| {
             // Upon finding a similar name, get the ident that it was from - the span
             // contained within helps make a useful diagnostic. In addition, determine
             // whether this candidate is within scope.
index c79d670737edd163356c0f7add862bd643459ec1..91edbebc05f3b9b027ebd59c9b9372d302d59143 100644 (file)
@@ -388,7 +388,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
             hir::ItemKind::ExternCrate(_)
             | hir::ItemKind::Use(..)
             | hir::ItemKind::Mod(..)
-            | hir::ItemKind::ForeignMod(..)
+            | hir::ItemKind::ForeignMod { .. }
             | hir::ItemKind::GlobalAsm(..) => {
                 // These sorts of items have no lifetime parameters at all.
                 intravisit::walk_item(self, item);
index d18335ef2e63a205d755e3a85241d75a96a12461..e8a06265adaf36d1c0d1a581e31b0005eb93fef0 100644 (file)
@@ -2539,6 +2539,7 @@ fn validate_res_from_ribs(
         span: Span,
         all_ribs: &[Rib<'a>],
     ) -> Res {
+        const CG_BUG_STR: &str = "min_const_generics resolve check didn't stop compilation";
         debug!("validate_res_from_ribs({:?})", res);
         let ribs = &all_ribs[rib_index + 1..];
 
@@ -2639,6 +2640,8 @@ fn validate_res_from_ribs(
                                             },
                                         );
                                     }
+
+                                    self.session.delay_span_bug(span, CG_BUG_STR);
                                     return Res::Err;
                                 }
                             }
@@ -2720,6 +2723,8 @@ fn validate_res_from_ribs(
                                         },
                                     );
                                 }
+
+                                self.session.delay_span_bug(span, CG_BUG_STR);
                                 return Res::Err;
                             }
 
index 21e43be20456b654697fc376f997a0243867e536..c8dbe685128576951283a9de01dbbb19265d5ed9 100644 (file)
 use rustc_attr::StabilityLevel;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::ptr_key::PtrKey;
+use rustc_data_structures::sync::Lrc;
 use rustc_errors::struct_span_err;
 use rustc_expand::base::{Indeterminate, InvocationRes, ResolverExpand, SyntaxExtension};
 use rustc_expand::compile_declarative_macro;
-use rustc_expand::expand::{AstFragment, AstFragmentKind, Invocation, InvocationKind};
+use rustc_expand::expand::{AstFragment, Invocation, InvocationKind};
 use rustc_feature::is_builtin_attr_name;
 use rustc_hir::def::{self, DefKind, NonMacroAttrKind};
 use rustc_hir::def_id;
 use rustc_middle::middle::stability;
 use rustc_middle::ty;
-use rustc_session::lint::builtin::UNUSED_MACROS;
+use rustc_session::lint::builtin::{SOFT_UNSTABLE, UNUSED_MACROS};
+use rustc_session::parse::feature_err;
 use rustc_session::Session;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::{self, ExpnData, ExpnId, ExpnKind};
+use rustc_span::hygiene::{AstPass, MacroKind};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
-
-use rustc_data_structures::sync::Lrc;
-use rustc_span::hygiene::{AstPass, MacroKind};
 use std::cell::Cell;
 use std::{mem, ptr};
 
@@ -241,15 +241,20 @@ fn resolve_macro_invocation(
             }
         };
 
-        let (path, kind, derives, after_derive) = match invoc.kind {
+        let (path, kind, inner_attr, derives, after_derive) = match invoc.kind {
             InvocationKind::Attr { ref attr, ref derives, after_derive, .. } => (
                 &attr.get_normal_item().path,
                 MacroKind::Attr,
+                attr.style == ast::AttrStyle::Inner,
                 self.arenas.alloc_ast_paths(derives),
                 after_derive,
             ),
-            InvocationKind::Bang { ref mac, .. } => (&mac.path, MacroKind::Bang, &[][..], false),
-            InvocationKind::Derive { ref path, .. } => (path, MacroKind::Derive, &[][..], false),
+            InvocationKind::Bang { ref mac, .. } => {
+                (&mac.path, MacroKind::Bang, false, &[][..], false)
+            }
+            InvocationKind::Derive { ref path, .. } => {
+                (path, MacroKind::Derive, false, &[][..], false)
+            }
             InvocationKind::DeriveContainer { ref derives, .. } => {
                 // Block expansion of the container until we resolve all derives in it.
                 // This is required for two reasons:
@@ -281,7 +286,7 @@ fn resolve_macro_invocation(
                                     ext.helper_attrs.iter().map(|name| Ident::new(*name, span)),
                                 );
                                 if ext.is_derive_copy {
-                                    self.add_derive_copy(invoc_id);
+                                    self.containers_deriving_copy.insert(invoc_id);
                                 }
                                 ext
                             }
@@ -299,8 +304,17 @@ fn resolve_macro_invocation(
 
         // Derives are not included when `invocations` are collected, so we have to add them here.
         let parent_scope = &ParentScope { derives, ..parent_scope };
+        let require_inert = !invoc.fragment_kind.supports_macro_expansion();
         let node_id = self.lint_node_id(eager_expansion_root);
-        let (ext, res) = self.smart_resolve_macro_path(path, kind, parent_scope, node_id, force)?;
+        let (ext, res) = self.smart_resolve_macro_path(
+            path,
+            kind,
+            require_inert,
+            inner_attr,
+            parent_scope,
+            node_id,
+            force,
+        )?;
 
         let span = invoc.span();
         invoc_id.set_expn_data(ext.expn_data(
@@ -318,29 +332,6 @@ fn resolve_macro_invocation(
             self.definitions.add_parent_module_of_macro_def(invoc_id, normal_module_def_id);
         }
 
-        match invoc.fragment_kind {
-            AstFragmentKind::Arms
-            | AstFragmentKind::Fields
-            | AstFragmentKind::FieldPats
-            | AstFragmentKind::GenericParams
-            | AstFragmentKind::Params
-            | AstFragmentKind::StructFields
-            | AstFragmentKind::Variants => {
-                if let Res::Def(..) = res {
-                    self.session.span_err(
-                        span,
-                        &format!(
-                            "expected an inert attribute, found {} {}",
-                            res.article(),
-                            res.descr()
-                        ),
-                    );
-                    return Ok(InvocationRes::Single(self.dummy_ext(kind)));
-                }
-            }
-            _ => {}
-        }
-
         Ok(InvocationRes::Single(ext))
     }
 
@@ -360,10 +351,6 @@ fn has_derive_copy(&self, expn_id: ExpnId) -> bool {
         self.containers_deriving_copy.contains(&expn_id)
     }
 
-    fn add_derive_copy(&mut self, expn_id: ExpnId) {
-        self.containers_deriving_copy.insert(expn_id);
-    }
-
     // The function that implements the resolution logic of `#[cfg_accessible(path)]`.
     // Returns true if the path can certainly be resolved in one of three namespaces,
     // returns false if the path certainly cannot be resolved in any of the three namespaces.
@@ -403,10 +390,14 @@ fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result<bool,
 
 impl<'a> Resolver<'a> {
     /// Resolve macro path with error reporting and recovery.
+    /// Uses dummy syntax extensions for unresolved macros or macros with unexpected resolutions
+    /// for better error recovery.
     fn smart_resolve_macro_path(
         &mut self,
         path: &ast::Path,
         kind: MacroKind,
+        require_inert: bool,
+        inner_attr: bool,
         parent_scope: &ParentScope<'a>,
         node_id: NodeId,
         force: bool,
@@ -414,7 +405,6 @@ fn smart_resolve_macro_path(
         let (ext, res) = match self.resolve_macro_path(path, Some(kind), parent_scope, true, force)
         {
             Ok((Some(ext), res)) => (ext, res),
-            // Use dummy syntax extensions for unresolved macros for better recovery.
             Ok((None, res)) => (self.dummy_ext(kind), res),
             Err(Determinacy::Determined) => (self.dummy_ext(kind), Res::Err),
             Err(Determinacy::Undetermined) => return Err(Indeterminate),
@@ -451,19 +441,42 @@ fn smart_resolve_macro_path(
 
         self.check_stability_and_deprecation(&ext, path, node_id);
 
-        Ok(if ext.macro_kind() != kind {
-            let expected = kind.descr_expected();
+        let unexpected_res = if ext.macro_kind() != kind {
+            Some((kind.article(), kind.descr_expected()))
+        } else if require_inert && matches!(res, Res::Def(..)) {
+            Some(("a", "non-macro attribute"))
+        } else {
+            None
+        };
+        if let Some((article, expected)) = unexpected_res {
             let path_str = pprust::path_to_string(path);
             let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path_str);
             self.session
                 .struct_span_err(path.span, &msg)
-                .span_label(path.span, format!("not {} {}", kind.article(), expected))
+                .span_label(path.span, format!("not {} {}", article, expected))
                 .emit();
-            // Use dummy syntax extensions for unexpected macro kinds for better recovery.
-            (self.dummy_ext(kind), Res::Err)
-        } else {
-            (ext, res)
-        })
+            return Ok((self.dummy_ext(kind), Res::Err));
+        }
+
+        // We are trying to avoid reporting this error if other related errors were reported.
+        if res != Res::Err
+            && inner_attr
+            && !self.session.features_untracked().custom_inner_attributes
+        {
+            let msg = match res {
+                Res::Def(..) => "inner macro attributes are unstable",
+                Res::NonMacroAttr(..) => "custom inner attributes are unstable",
+                _ => unreachable!(),
+            };
+            if path == &sym::test {
+                self.session.parse_sess.buffer_lint(SOFT_UNSTABLE, path.span, node_id, msg);
+            } else {
+                feature_err(&self.session.parse_sess, sym::custom_inner_attributes, path.span, msg)
+                    .emit();
+            }
+        }
+
+        Ok((ext, res))
     }
 
     pub fn resolve_macro_path(
@@ -568,10 +581,9 @@ pub fn resolve_macro_path(
             struct Flags: u8 {
                 const MACRO_RULES          = 1 << 0;
                 const MODULE               = 1 << 1;
-                const DERIVE_HELPER_COMPAT = 1 << 2;
-                const MISC_SUGGEST_CRATE   = 1 << 3;
-                const MISC_SUGGEST_SELF    = 1 << 4;
-                const MISC_FROM_PRELUDE    = 1 << 5;
+                const MISC_SUGGEST_CRATE   = 1 << 2;
+                const MISC_SUGGEST_SELF    = 1 << 3;
+                const MISC_FROM_PRELUDE    = 1 << 4;
             }
         }
 
@@ -646,14 +658,11 @@ struct Flags: u8 {
                             ) {
                                 Ok((Some(ext), _)) => {
                                     if ext.helper_attrs.contains(&ident.name) {
-                                        let binding = (
-                                            Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
-                                            ty::Visibility::Public,
+                                        result = ok(
+                                            Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat),
                                             derive.span,
-                                            ExpnId::root(),
-                                        )
-                                            .to_name_binding(this.arenas);
-                                        result = Ok((binding, Flags::DERIVE_HELPER_COMPAT));
+                                            this.arenas,
+                                        );
                                         break;
                                     }
                                 }
@@ -799,17 +808,15 @@ struct Flags: u8 {
                             let (res, innermost_res) = (binding.res(), innermost_binding.res());
                             if res != innermost_res {
                                 let builtin = Res::NonMacroAttr(NonMacroAttrKind::Builtin);
-                                let is_derive_helper_compat = |res, flags: Flags| {
-                                    res == Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper)
-                                        && flags.contains(Flags::DERIVE_HELPER_COMPAT)
-                                };
+                                let derive_helper_compat =
+                                    Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat);
 
                                 let ambiguity_error_kind = if is_import {
                                     Some(AmbiguityKind::Import)
                                 } else if innermost_res == builtin || res == builtin {
                                     Some(AmbiguityKind::BuiltinAttr)
-                                } else if is_derive_helper_compat(innermost_res, innermost_flags)
-                                    || is_derive_helper_compat(res, flags)
+                                } else if innermost_res == derive_helper_compat
+                                    || res == derive_helper_compat
                                 {
                                     Some(AmbiguityKind::DeriveHelper)
                                 } else if innermost_flags.contains(Flags::MACRO_RULES)
index 2f82d0546ba98a88b2c48616514e46d902f67301..ff445d727fa34b4bacb6b08498f1581d472c9461 100644 (file)
@@ -550,7 +550,7 @@ fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<
 
                 // FIXME where clause
             }
-            hir::ItemKind::ForeignMod(_) => Err("extern mod"),
+            hir::ItemKind::ForeignMod { .. } => Err("extern mod"),
             hir::ItemKind::GlobalAsm(_) => Err("global asm"),
             hir::ItemKind::ExternCrate(_) => Err("extern crate"),
             hir::ItemKind::OpaqueTy(..) => Err("opaque type"),
index 1cd3d11e3215367f8468c4bffa290a3a13fca96e..b438be0696ac1b803fd9138faa20501fcd55ec9d 100644 (file)
@@ -900,7 +900,7 @@ fn parse_target_feature(slot: &mut String, v: Option<&str>) -> bool {
         "emits a future-incompatibility report for lints (RFC 2834)"),
     emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED],
         "emit a section containing stack size metadata (default: no)"),
-    fewer_names: bool = (false, parse_bool, [TRACKED],
+    fewer_names: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) \
         (default: no)"),
     force_overflow_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],
@@ -1008,7 +1008,7 @@ fn parse_target_feature(slot: &mut String, v: Option<&str>) -> bool {
         "whether to use the PLT when calling into shared libraries;
         only has effect for PIC code on systems with ELF binaries
         (default: PLT is disabled if full relro is enabled)"),
-    polonius: bool = (false, parse_bool, [UNTRACKED],
+    polonius: bool = (false, parse_bool, [TRACKED],
         "enable polonius-based borrow-checker (default: no)"),
     polymorphize: bool = (false, parse_bool, [TRACKED],
           "perform polymorphization analysis"),
@@ -1113,6 +1113,8 @@ fn parse_target_feature(slot: &mut String, v: Option<&str>) -> bool {
         "choose the TLS model to use (`rustc --print tls-models` for details)"),
     trace_macros: bool = (false, parse_bool, [UNTRACKED],
         "for every macro invocation, print its name and arguments (default: no)"),
+    trap_unreachable: Option<bool> = (None, parse_opt_bool, [TRACKED],
+        "generate trap instructions for unreachable intrinsics (default: use target setting, usually yes)"),
     treat_err_as_bug: Option<usize> = (None, parse_treat_err_as_bug, [TRACKED],
         "treat error number `val` that occurs as bug"),
     trim_diagnostic_paths: bool = (true, parse_bool, [UNTRACKED],
index 419d1447764ec833e0182adef3ee8580ebfc44d9..5dddf0eb72ea641dfebe7913798f11d65baacb4e 100644 (file)
@@ -734,12 +734,15 @@ pub fn panic_strategy(&self) -> PanicStrategy {
         self.opts.cg.panic.unwrap_or(self.target.panic_strategy)
     }
     pub fn fewer_names(&self) -> bool {
-        let more_names = self.opts.output_types.contains_key(&OutputType::LlvmAssembly)
-            || self.opts.output_types.contains_key(&OutputType::Bitcode)
-            // AddressSanitizer and MemorySanitizer use alloca name when reporting an issue.
-            || self.opts.debugging_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY);
-
-        self.opts.debugging_opts.fewer_names || !more_names
+        if let Some(fewer_names) = self.opts.debugging_opts.fewer_names {
+            fewer_names
+        } else {
+            let more_names = self.opts.output_types.contains_key(&OutputType::LlvmAssembly)
+                || self.opts.output_types.contains_key(&OutputType::Bitcode)
+                // AddressSanitizer and MemorySanitizer use alloca name when reporting an issue.
+                || self.opts.debugging_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY);
+            !more_names
+        }
     }
 
     pub fn unstable_options(&self) -> bool {
diff --git a/compiler/rustc_span/src/lev_distance.rs b/compiler/rustc_span/src/lev_distance.rs
new file mode 100644 (file)
index 0000000..edc6625
--- /dev/null
@@ -0,0 +1,104 @@
+use crate::symbol::Symbol;
+use std::cmp;
+
+#[cfg(test)]
+mod tests;
+
+/// Finds the Levenshtein distance between two strings
+pub fn lev_distance(a: &str, b: &str) -> usize {
+    // cases which don't require further computation
+    if a.is_empty() {
+        return b.chars().count();
+    } else if b.is_empty() {
+        return a.chars().count();
+    }
+
+    let mut dcol: Vec<_> = (0..=b.len()).collect();
+    let mut t_last = 0;
+
+    for (i, sc) in a.chars().enumerate() {
+        let mut current = i;
+        dcol[0] = current + 1;
+
+        for (j, tc) in b.chars().enumerate() {
+            let next = dcol[j + 1];
+            if sc == tc {
+                dcol[j + 1] = current;
+            } else {
+                dcol[j + 1] = cmp::min(current, next);
+                dcol[j + 1] = cmp::min(dcol[j + 1], dcol[j]) + 1;
+            }
+            current = next;
+            t_last = j;
+        }
+    }
+    dcol[t_last + 1]
+}
+
+/// Finds the best match for a given word in the given iterator
+///
+/// As a loose rule to avoid the obviously incorrect suggestions, it takes
+/// an optional limit for the maximum allowable edit distance, which defaults
+/// to one-third of the given word.
+///
+/// Besides Levenshtein, we use case insensitive comparison to improve accuracy on an edge case with
+/// a lower(upper)case letters mismatch.
+#[cold]
+pub fn find_best_match_for_name(
+    name_vec: &[Symbol],
+    lookup: Symbol,
+    dist: Option<usize>,
+) -> Option<Symbol> {
+    let lookup = &lookup.as_str();
+    let max_dist = dist.unwrap_or_else(|| cmp::max(lookup.len(), 3) / 3);
+
+    let (case_insensitive_match, levenshtein_match) = name_vec
+        .iter()
+        .filter_map(|&name| {
+            let dist = lev_distance(lookup, &name.as_str());
+            if dist <= max_dist { Some((name, dist)) } else { None }
+        })
+        // Here we are collecting the next structure:
+        // (case_insensitive_match, (levenshtein_match, levenshtein_distance))
+        .fold((None, None), |result, (candidate, dist)| {
+            (
+                if candidate.as_str().to_uppercase() == lookup.to_uppercase() {
+                    Some(candidate)
+                } else {
+                    result.0
+                },
+                match result.1 {
+                    None => Some((candidate, dist)),
+                    Some((c, d)) => Some(if dist < d { (candidate, dist) } else { (c, d) }),
+                },
+            )
+        });
+    // Priority of matches:
+    // 1. Exact case insensitive match
+    // 2. Levenshtein distance match
+    // 3. Sorted word match
+    if let Some(candidate) = case_insensitive_match {
+        Some(candidate)
+    } else if levenshtein_match.is_some() {
+        levenshtein_match.map(|(candidate, _)| candidate)
+    } else {
+        find_match_by_sorted_words(name_vec, lookup)
+    }
+}
+
+fn find_match_by_sorted_words(iter_names: &[Symbol], lookup: &str) -> Option<Symbol> {
+    iter_names.iter().fold(None, |result, candidate| {
+        if sort_by_words(&candidate.as_str()) == sort_by_words(lookup) {
+            Some(*candidate)
+        } else {
+            result
+        }
+    })
+}
+
+fn sort_by_words(name: &str) -> String {
+    let mut split_words: Vec<&str> = name.split('_').collect();
+    // We are sorting primitive &strs and can use unstable sort here
+    split_words.sort_unstable();
+    split_words.join("_")
+}
diff --git a/compiler/rustc_span/src/lev_distance/tests.rs b/compiler/rustc_span/src/lev_distance/tests.rs
new file mode 100644 (file)
index 0000000..7aa01cb
--- /dev/null
@@ -0,0 +1,56 @@
+use super::*;
+
+#[test]
+fn test_lev_distance() {
+    use std::char::{from_u32, MAX};
+    // Test bytelength agnosticity
+    for c in (0..MAX as u32).filter_map(|i| from_u32(i)).map(|i| i.to_string()) {
+        assert_eq!(lev_distance(&c[..], &c[..]), 0);
+    }
+
+    let a = "\nMäry häd ä little lämb\n\nLittle lämb\n";
+    let b = "\nMary häd ä little lämb\n\nLittle lämb\n";
+    let c = "Mary häd ä little lämb\n\nLittle lämb\n";
+    assert_eq!(lev_distance(a, b), 1);
+    assert_eq!(lev_distance(b, a), 1);
+    assert_eq!(lev_distance(a, c), 2);
+    assert_eq!(lev_distance(c, a), 2);
+    assert_eq!(lev_distance(b, c), 1);
+    assert_eq!(lev_distance(c, b), 1);
+}
+
+#[test]
+fn test_find_best_match_for_name() {
+    use crate::with_default_session_globals;
+    with_default_session_globals(|| {
+        let input = vec![Symbol::intern("aaab"), Symbol::intern("aaabc")];
+        assert_eq!(
+            find_best_match_for_name(&input, Symbol::intern("aaaa"), None),
+            Some(Symbol::intern("aaab"))
+        );
+
+        assert_eq!(find_best_match_for_name(&input, Symbol::intern("1111111111"), None), None);
+
+        let input = vec![Symbol::intern("aAAA")];
+        assert_eq!(
+            find_best_match_for_name(&input, Symbol::intern("AAAA"), None),
+            Some(Symbol::intern("aAAA"))
+        );
+
+        let input = vec![Symbol::intern("AAAA")];
+        // Returns None because `lev_distance > max_dist / 3`
+        assert_eq!(find_best_match_for_name(&input, Symbol::intern("aaaa"), None), None);
+
+        let input = vec![Symbol::intern("AAAA")];
+        assert_eq!(
+            find_best_match_for_name(&input, Symbol::intern("aaaa"), Some(4)),
+            Some(Symbol::intern("AAAA"))
+        );
+
+        let input = vec![Symbol::intern("a_longer_variable_name")];
+        assert_eq!(
+            find_best_match_for_name(&input, Symbol::intern("a_variable_longer_name"), None),
+            Some(Symbol::intern("a_longer_variable_name"))
+        );
+    })
+}
index 0926561f4c5134038ddd78e9116389934a80a0b0..11a49d1ab887daf91c8deb2fc64992f44816b1eb 100644 (file)
@@ -34,6 +34,7 @@
 pub use hygiene::{DesugaringKind, ExpnData, ExpnId, ExpnKind, ForLoopLoc, MacroKind};
 pub mod def_id;
 use def_id::{CrateNum, DefId, LOCAL_CRATE};
+pub mod lev_distance;
 mod span_encoding;
 pub use span_encoding::{Span, DUMMY_SP};
 
index 3a2a3adce35c91cecac03a664584ab2faf1bfe57..d5fccdeb189cc04007dfe7cea3f5f56e4c2713ce 100644 (file)
         asm,
         assert,
         assert_inhabited,
+        assert_macro,
         assert_receiver_is_total_eq,
         assert_uninit_valid,
         assert_zero_valid,
         attr_literals,
         attributes,
         augmented_assignments,
+        auto_traits,
         automatically_derived,
         avx512_target_feature,
         await_macro,
         copysignf64,
         core,
         core_intrinsics,
+        core_panic_macro,
         cosf32,
         cosf64,
         crate_id,
         dead_code,
         dealloc,
         debug,
+        debug_assert_macro,
         debug_assertions,
         debug_struct,
         debug_trait,
         panic_runtime,
         panic_str,
         panic_unwind,
+        panicking,
         param_attrs,
         parent_trait,
         partial_cmp,
         staticlib,
         std,
         std_inject,
+        std_panic_macro,
         stmt,
         stmt_expr_attributes,
         stop_after_dataflow,
index a28c8cac728101c3d6f6785cf27b01c87a3b4ffe..8c5e438a7284b456976f181023f0c7453ba85621 100644 (file)
@@ -71,4 +71,8 @@ fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         self.process_attrs(impl_item.hir_id);
     }
+
+    fn visit_foreign_item(&mut self, foreign_item: &'tcx hir::ForeignItem<'tcx>) {
+        self.process_attrs(foreign_item.hir_id);
+    }
 }
index 917dd104d1496fd24f60cb0c20c627ff72af7063..a630c84142b4d4ebb4f749ff68097bbcfa615d96 100644 (file)
@@ -1,4 +1,4 @@
-use crate::abi::call::{ArgAbi, ArgAttribute, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
+use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
 use crate::abi::{self, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods};
 
 fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) {
@@ -7,7 +7,7 @@ fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) {
         if let abi::Int(i, signed) = scalar.value {
             if !signed && i.size().bits() == 32 {
                 if let PassMode::Direct(ref mut attrs) = arg.mode {
-                    attrs.set(ArgAttribute::SExt);
+                    attrs.ext(ArgExtension::Sext);
                     return;
                 }
             }
@@ -137,7 +137,7 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
     let rest_size = size - Size::from_bytes(8) * prefix_index as u64;
     arg.cast_to(CastTarget {
         prefix,
-        prefix_chunk: Size::from_bytes(8),
+        prefix_chunk_size: Size::from_bytes(8),
         rest: Uniform { unit: Reg::i64(), total: rest_size },
     });
 }
index 429a3375cd893f4f729fbfe37404510aac5d2807..5de9a8dfa7ac1719a7b0e388962d3c1881c6374f 100644 (file)
@@ -36,9 +36,12 @@ pub enum PassMode {
     /// a single uniform or a pair of registers.
     Cast(CastTarget),
     /// Pass the argument indirectly via a hidden pointer.
-    /// The second value, if any, is for the extra data (vtable or length)
+    /// The `extra_attrs` value, if any, is for the extra data (vtable or length)
     /// which indicates that it refers to an unsized rvalue.
-    Indirect(ArgAttributes, Option<ArgAttributes>),
+    /// `on_stack` defines that the the value should be passed at a fixed
+    /// stack offset in accordance to the ABI rather than passed using a
+    /// pointer. This corresponds to the `byval` LLVM argument attribute.
+    Indirect { attrs: ArgAttributes, extra_attrs: Option<ArgAttributes>, on_stack: bool },
 }
 
 // Hack to disable non_upper_case_globals only for the bitflags! and not for the rest
@@ -52,24 +55,31 @@ mod attr_impl {
     bitflags::bitflags! {
         #[derive(Default)]
         pub struct ArgAttribute: u16 {
-            const ByVal     = 1 << 0;
             const NoAlias   = 1 << 1;
             const NoCapture = 1 << 2;
             const NonNull   = 1 << 3;
             const ReadOnly  = 1 << 4;
-            const SExt      = 1 << 5;
-            const StructRet = 1 << 6;
-            const ZExt      = 1 << 7;
             const InReg     = 1 << 8;
         }
     }
 }
 
+/// Sometimes an ABI requires small integers to be extended to a full or partial register. This enum
+/// defines if this extension should be zero-extension or sign-extension when necssary. When it is
+/// not necesary to extend the argument, this enum is ignored.
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum ArgExtension {
+    None,
+    Zext,
+    Sext,
+}
+
 /// A compact representation of LLVM attributes (at least those relevant for this module)
 /// that can be manipulated without interacting with LLVM's Attribute machinery.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub struct ArgAttributes {
     pub regular: ArgAttribute,
+    pub arg_ext: ArgExtension,
     /// The minimum size of the pointee, guaranteed to be valid for the duration of the whole call
     /// (corresponding to LLVM's dereferenceable and dereferenceable_or_null attributes).
     pub pointee_size: Size,
@@ -80,11 +90,18 @@ impl ArgAttributes {
     pub fn new() -> Self {
         ArgAttributes {
             regular: ArgAttribute::default(),
+            arg_ext: ArgExtension::None,
             pointee_size: Size::ZERO,
             pointee_align: None,
         }
     }
 
+    pub fn ext(&mut self, ext: ArgExtension) -> &mut Self {
+        assert!(self.arg_ext == ArgExtension::None || self.arg_ext == ext);
+        self.arg_ext = ext;
+        self
+    }
+
     pub fn set(&mut self, attr: ArgAttribute) -> &mut Self {
         self.regular |= attr;
         self
@@ -180,7 +197,7 @@ pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
 pub struct CastTarget {
     pub prefix: [Option<RegKind>; 8],
-    pub prefix_chunk: Size,
+    pub prefix_chunk_size: Size,
     pub rest: Uniform,
 }
 
@@ -192,7 +209,7 @@ fn from(unit: Reg) -> CastTarget {
 
 impl From<Uniform> for CastTarget {
     fn from(uniform: Uniform) -> CastTarget {
-        CastTarget { prefix: [None; 8], prefix_chunk: Size::ZERO, rest: uniform }
+        CastTarget { prefix: [None; 8], prefix_chunk_size: Size::ZERO, rest: uniform }
     }
 }
 
@@ -200,13 +217,13 @@ impl CastTarget {
     pub fn pair(a: Reg, b: Reg) -> CastTarget {
         CastTarget {
             prefix: [Some(a.kind), None, None, None, None, None, None, None],
-            prefix_chunk: a.size,
+            prefix_chunk_size: a.size,
             rest: Uniform::from(b),
         }
     }
 
     pub fn size<C: HasDataLayout>(&self, cx: &C) -> Size {
-        (self.prefix_chunk * self.prefix.iter().filter(|x| x.is_some()).count() as u64)
+        (self.prefix_chunk_size * self.prefix.iter().filter(|x| x.is_some()).count() as u64)
             .align_to(self.rest.align(cx))
             + self.rest.total
     }
@@ -214,7 +231,7 @@ pub fn size<C: HasDataLayout>(&self, cx: &C) -> Size {
     pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
         self.prefix
             .iter()
-            .filter_map(|x| x.map(|kind| Reg { kind, size: self.prefix_chunk }.align(cx)))
+            .filter_map(|x| x.map(|kind| Reg { kind, size: self.prefix_chunk_size }.align(cx)))
             .fold(cx.data_layout().aggregate_align.abi.max(self.rest.align(cx)), |acc, align| {
                 acc.max(align)
             })
@@ -438,14 +455,14 @@ pub fn make_indirect(&mut self) {
 
         let extra_attrs = self.layout.is_unsized().then_some(ArgAttributes::new());
 
-        self.mode = PassMode::Indirect(attrs, extra_attrs);
+        self.mode = PassMode::Indirect { attrs, extra_attrs, on_stack: false };
     }
 
     pub fn make_indirect_byval(&mut self) {
         self.make_indirect();
         match self.mode {
-            PassMode::Indirect(ref mut attrs, _) => {
-                attrs.set(ArgAttribute::ByVal);
+            PassMode::Indirect { attrs: _, extra_attrs: _, ref mut on_stack } => {
+                *on_stack = true;
             }
             _ => unreachable!(),
         }
@@ -457,7 +474,11 @@ pub fn extend_integer_width_to(&mut self, bits: u64) {
             if let abi::Int(i, signed) = scalar.value {
                 if i.size().bits() < bits {
                     if let PassMode::Direct(ref mut attrs) = self.mode {
-                        attrs.set(if signed { ArgAttribute::SExt } else { ArgAttribute::ZExt });
+                        if signed {
+                            attrs.ext(ArgExtension::Sext)
+                        } else {
+                            attrs.ext(ArgExtension::Zext)
+                        };
                     }
                 }
             }
@@ -474,15 +495,15 @@ pub fn pad_with(&mut self, reg: Reg) {
     }
 
     pub fn is_indirect(&self) -> bool {
-        matches!(self.mode, PassMode::Indirect(..))
+        matches!(self.mode, PassMode::Indirect {..})
     }
 
     pub fn is_sized_indirect(&self) -> bool {
-        matches!(self.mode, PassMode::Indirect(_, None))
+        matches!(self.mode, PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ })
     }
 
     pub fn is_unsized_indirect(&self) -> bool {
-        matches!(self.mode, PassMode::Indirect(_, Some(_)))
+        matches!(self.mode, PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ })
     }
 
     pub fn is_ignore(&self) -> bool {
@@ -591,10 +612,6 @@ pub fn adjust_for_cabi<C>(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(),
             a => return Err(format!("unrecognized arch \"{}\" in target specification", a)),
         }
 
-        if let PassMode::Indirect(ref mut attrs, _) = self.ret.mode {
-            attrs.set(ArgAttribute::StructRet);
-        }
-
         Ok(())
     }
 }
index 782c661c31fdb5b9f7aa0d1bcdf7443baf3ffe3f..1ab881dd13d1c46a1e8d5f4e0e0b7519fc115ff7 100644 (file)
@@ -4,7 +4,7 @@
 // Reference: Clang RISC-V ELF psABI lowering code
 // https://github.com/llvm/llvm-project/blob/8e780252a7284be45cf1ba224cabd884847e8e92/clang/lib/CodeGen/TargetInfo.cpp#L9311-L9773
 
-use crate::abi::call::{ArgAbi, ArgAttribute, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
+use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
 use crate::abi::{
     self, Abi, FieldsShape, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods,
 };
@@ -308,7 +308,7 @@ fn extend_integer_width<'a, Ty>(arg: &mut ArgAbi<'a, Ty>, xlen: u64) {
             // 32-bit integers are always sign-extended
             if i.size().bits() == 32 && xlen > 32 {
                 if let PassMode::Direct(ref mut attrs) = arg.mode {
-                    attrs.set(ArgAttribute::SExt);
+                    attrs.ext(ArgExtension::Sext);
                     return;
                 }
             }
index 07bf1e94c617eee072e45bd3982fcc4bc3e34573..713b4100a33351472f8a1abfc739588956617021 100644 (file)
@@ -92,9 +92,14 @@ pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, flavor: F
 
         for arg in &mut fn_abi.args {
             let attrs = match arg.mode {
-                PassMode::Ignore | PassMode::Indirect(_, None) => continue,
+                PassMode::Ignore
+                | PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => {
+                    continue;
+                }
                 PassMode::Direct(ref mut attrs) => attrs,
-                PassMode::Pair(..) | PassMode::Indirect(_, Some(_)) | PassMode::Cast(_) => {
+                PassMode::Pair(..)
+                | PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ }
+                | PassMode::Cast(_) => {
                     unreachable!("x86 shouldn't be passing arguments by {:?}", arg.mode)
                 }
             };
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
new file mode 100644 (file)
index 0000000..3a88197
--- /dev/null
@@ -0,0 +1,31 @@
+use super::apple_sdk_base::{opts, Arch};
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+    let base = opts("ios", Arch::Arm64_macabi);
+    Target {
+        llvm_target: "arm64-apple-ios-macabi".to_string(),
+        pointer_width: 64,
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(),
+        arch: "aarch64".to_string(),
+        options: TargetOptions {
+            features: "+neon,+fp-armv8,+apple-a7".to_string(),
+            eliminate_frame_pointer: false,
+            max_atomic_width: Some(128),
+            unsupported_abis: super::arm_base::unsupported_abis(),
+            forces_embed_bitcode: true,
+            // Taken from a clang build on Xcode 11.4.1.
+            // These arguments are not actually invoked - they just have
+            // to look right to pass App Store validation.
+            bitcode_llvm_cmdline: "-triple\0\
+                arm64-apple-ios-macabi\0\
+                -emit-obj\0\
+                -disable-llvm-passes\0\
+                -target-abi\0\
+                darwinpcs\0\
+                -Os\0"
+                .to_string(),
+            ..base
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_cloudabi.rs b/compiler/rustc_target/src/spec/aarch64_unknown_cloudabi.rs
deleted file mode 100644 (file)
index 67f69b4..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-use crate::spec::Target;
-
-pub fn target() -> Target {
-    let mut base = super::cloudabi_base::opts();
-    base.max_atomic_width = Some(128);
-    base.unsupported_abis = super::arm_base::unsupported_abis();
-    base.linker = Some("aarch64-unknown-cloudabi-cc".to_string());
-
-    Target {
-        llvm_target: "aarch64-unknown-cloudabi".to_string(),
-        pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
-        arch: "aarch64".to_string(),
-        options: base,
-    }
-}
index 092401f11462edb6465c6f215c1f3a1d0f67e248..d894f7599377e55d5414280c420eb51c3b74ca40 100644 (file)
@@ -10,6 +10,7 @@ pub enum Arch {
     I386,
     X86_64,
     X86_64_macabi,
+    Arm64_macabi,
 }
 
 fn target_cpu(arch: Arch) -> String {
@@ -20,6 +21,7 @@ fn target_cpu(arch: Arch) -> String {
         I386 => "yonah",
         X86_64 => "core2",
         X86_64_macabi => "core2",
+        Arm64_macabi => "apple-a12",
     }
     .to_string()
 }
@@ -27,7 +29,7 @@ fn target_cpu(arch: Arch) -> String {
 fn link_env_remove(arch: Arch) -> Vec<String> {
     match arch {
         Armv7 | Armv7s | Arm64 | I386 | X86_64 => vec!["MACOSX_DEPLOYMENT_TARGET".to_string()],
-        X86_64_macabi => vec!["IPHONEOS_DEPLOYMENT_TARGET".to_string()],
+        X86_64_macabi | Arm64_macabi => vec!["IPHONEOS_DEPLOYMENT_TARGET".to_string()],
     }
 }
 
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_cloudabi_eabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_cloudabi_eabihf.rs
deleted file mode 100644 (file)
index d47ee54..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-use crate::spec::{Target, TargetOptions};
-
-pub fn target() -> Target {
-    let mut base = super::cloudabi_base::opts();
-    base.cpu = "cortex-a8".to_string();
-    base.max_atomic_width = Some(64);
-    base.features = "+v7,+vfp3,+neon".to_string();
-    base.unsupported_abis = super::arm_base::unsupported_abis();
-    base.linker = Some("armv7-unknown-cloudabi-eabihf-cc".to_string());
-
-    Target {
-        llvm_target: "armv7-unknown-cloudabi-eabihf".to_string(),
-        pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
-        options: TargetOptions { mcount: "\u{1}mcount".to_string(), ..base },
-    }
-}
diff --git a/compiler/rustc_target/src/spec/cloudabi_base.rs b/compiler/rustc_target/src/spec/cloudabi_base.rs
deleted file mode 100644 (file)
index 20a0957..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions, TlsModel};
-
-pub fn opts() -> TargetOptions {
-    let mut args = LinkArgs::new();
-    args.insert(
-        LinkerFlavor::Gcc,
-        vec![
-            "-Wl,-Bstatic".to_string(),
-            "-Wl,--no-dynamic-linker".to_string(),
-            "-Wl,--gc-sections".to_string(),
-        ],
-    );
-
-    TargetOptions {
-        os: "cloudabi".to_string(),
-        executables: true,
-        os_family: None,
-        linker_is_gnu: true,
-        pre_link_args: args,
-        position_independent_executables: true,
-        // As CloudABI only supports static linkage, there is no need
-        // for dynamic TLS. The C library therefore does not provide
-        // __tls_get_addr(), which is normally used to perform dynamic
-        // TLS lookups by programs that make use of dlopen(). Only the
-        // "local-exec" and "initial-exec" TLS models can be used.
-        //
-        // "local-exec" is more efficient than "initial-exec", as the
-        // latter has one more level of indirection: it accesses the GOT
-        // (Global Offset Table) to obtain the effective address of a
-        // thread-local variable. Using a GOT is useful only when doing
-        // dynamic linking.
-        tls_model: TlsModel::LocalExec,
-        relro_level: RelroLevel::Full,
-        ..Default::default()
-    }
-}
diff --git a/compiler/rustc_target/src/spec/i686_unknown_cloudabi.rs b/compiler/rustc_target/src/spec/i686_unknown_cloudabi.rs
deleted file mode 100644 (file)
index 0cdb9f9..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-use crate::spec::{LinkerFlavor, Target};
-
-pub fn target() -> Target {
-    let mut base = super::cloudabi_base::opts();
-    base.cpu = "pentium4".to_string();
-    base.max_atomic_width = Some(64);
-    base.linker = Some("i686-unknown-cloudabi-cc".to_string());
-    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
-    base.stack_probes = true;
-
-    Target {
-        llvm_target: "i686-unknown-cloudabi".to_string(),
-        pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            f64:32:64-f80:32-n8:16:32-S128"
-            .to_string(),
-        arch: "x86".to_string(),
-        options: base,
-    }
-}
index 045da7963c5673bc2cb9701529b2b40d9d294f90..b4414e53331955decd7476f5eaccaa7ea9681ecd 100644 (file)
@@ -54,7 +54,6 @@
 mod apple_sdk_base;
 mod arm_base;
 mod avr_gnu_base;
-mod cloudabi_base;
 mod dragonfly_base;
 mod freebsd_base;
 mod fuchsia_base;
@@ -580,6 +579,7 @@ fn $module() {
     ("armv7-apple-ios", armv7_apple_ios),
     ("armv7s-apple-ios", armv7s_apple_ios),
     ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi),
+    ("aarch64-apple-ios-macabi", aarch64_apple_ios_macabi),
     ("aarch64-apple-tvos", aarch64_apple_tvos),
     ("x86_64-apple-tvos", x86_64_apple_tvos),
 
@@ -628,11 +628,6 @@ fn $module() {
 
     ("msp430-none-elf", msp430_none_elf),
 
-    ("aarch64-unknown-cloudabi", aarch64_unknown_cloudabi),
-    ("armv7-unknown-cloudabi-eabihf", armv7_unknown_cloudabi_eabihf),
-    ("i686-unknown-cloudabi", i686_unknown_cloudabi),
-    ("x86_64-unknown-cloudabi", x86_64_unknown_cloudabi),
-
     ("aarch64-unknown-hermit", aarch64_unknown_hermit),
     ("x86_64-unknown-hermit", x86_64_unknown_hermit),
     ("x86_64-unknown-hermit-kernel", x86_64_unknown_hermit_kernel),
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_cloudabi.rs b/compiler/rustc_target/src/spec/x86_64_unknown_cloudabi.rs
deleted file mode 100644 (file)
index cf57f4e..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-use crate::spec::{LinkerFlavor, Target};
-
-pub fn target() -> Target {
-    let mut base = super::cloudabi_base::opts();
-    base.cpu = "x86-64".to_string();
-    base.max_atomic_width = Some(64);
-    base.linker = Some("x86_64-unknown-cloudabi-cc".to_string());
-    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
-    base.stack_probes = true;
-
-    Target {
-        llvm_target: "x86_64-unknown-cloudabi".to_string(),
-        pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
-        options: base,
-    }
-}
index d429d889fcc15b3cbd744c0fc0481640f903869d..fe4127fd4d8b94baada65ad2195083c590bc4868 100644 (file)
@@ -200,6 +200,7 @@ fn report_overflow_error<T>(
             &obligation.predicate,
             &obligation.cause.code,
             &mut vec![],
+            &mut Default::default(),
         );
 
         err.emit();
@@ -1700,6 +1701,7 @@ fn note_obligation_cause(
                 &obligation.predicate,
                 &obligation.cause.code,
                 &mut vec![],
+                &mut Default::default(),
             );
             self.suggest_unsized_bound_if_applicable(err, obligation);
         }
index 7e92df28ca27e5fc9ef8c13277e501116a35be23..095483aa5a25dbf6ea4752b179d7c173f1c46026 100644 (file)
@@ -7,6 +7,7 @@
 use crate::infer::InferCtxt;
 use crate::traits::normalize_projection_type;
 
+use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder, Style};
 use rustc_hir as hir;
@@ -158,6 +159,7 @@ fn note_obligation_cause_code<T>(
         predicate: &T,
         cause_code: &ObligationCauseCode<'tcx>,
         obligated_types: &mut Vec<&ty::TyS<'tcx>>,
+        seen_requirements: &mut FxHashSet<DefId>,
     ) where
         T: fmt::Display;
 
@@ -1787,6 +1789,7 @@ fn note_obligation_cause_for_async_await(
             &obligation.predicate,
             next_code.unwrap(),
             &mut Vec::new(),
+            &mut Default::default(),
         );
     }
 
@@ -1796,6 +1799,7 @@ fn note_obligation_cause_code<T>(
         predicate: &T,
         cause_code: &ObligationCauseCode<'tcx>,
         obligated_types: &mut Vec<&ty::TyS<'tcx>>,
+        seen_requirements: &mut FxHashSet<DefId>,
     ) where
         T: fmt::Display,
     {
@@ -2050,18 +2054,44 @@ fn note_obligation_cause_code<T>(
                             &parent_predicate,
                             &data.parent_code,
                             obligated_types,
+                            seen_requirements,
                         )
                     });
                 }
             }
             ObligationCauseCode::ImplDerivedObligation(ref data) => {
-                let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_ref);
+                let mut parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_ref);
+                let parent_def_id = parent_trait_ref.def_id();
                 err.note(&format!(
                     "required because of the requirements on the impl of `{}` for `{}`",
                     parent_trait_ref.print_only_trait_path(),
                     parent_trait_ref.skip_binder().self_ty()
                 ));
-                let parent_predicate = parent_trait_ref.without_const().to_predicate(tcx);
+
+                let mut parent_predicate = parent_trait_ref.without_const().to_predicate(tcx);
+                let mut data = data;
+                let mut count = 0;
+                seen_requirements.insert(parent_def_id);
+                while let ObligationCauseCode::ImplDerivedObligation(child) = &*data.parent_code {
+                    // Skip redundant recursive obligation notes. See `ui/issue-20413.rs`.
+                    let child_trait_ref = self.resolve_vars_if_possible(child.parent_trait_ref);
+                    let child_def_id = child_trait_ref.def_id();
+                    if seen_requirements.insert(child_def_id) {
+                        break;
+                    }
+                    count += 1;
+                    data = child;
+                    parent_predicate = child_trait_ref.without_const().to_predicate(tcx);
+                    parent_trait_ref = child_trait_ref;
+                }
+                if count > 0 {
+                    err.note(&format!("{} redundant requirements hidden", count));
+                    err.note(&format!(
+                        "required because of the requirements on the impl of `{}` for `{}`",
+                        parent_trait_ref.print_only_trait_path(),
+                        parent_trait_ref.skip_binder().self_ty()
+                    ));
+                }
                 // #74711: avoid a stack overflow
                 ensure_sufficient_stack(|| {
                     self.note_obligation_cause_code(
@@ -2069,6 +2099,7 @@ fn note_obligation_cause_code<T>(
                         &parent_predicate,
                         &data.parent_code,
                         obligated_types,
+                        seen_requirements,
                     )
                 });
             }
@@ -2082,20 +2113,21 @@ fn note_obligation_cause_code<T>(
                         &parent_predicate,
                         &data.parent_code,
                         obligated_types,
+                        seen_requirements,
                     )
                 });
             }
             ObligationCauseCode::CompareImplMethodObligation { .. } => {
                 err.note(&format!(
-                    "the requirement `{}` appears on the impl method \
-                     but not on the corresponding trait method",
+                    "the requirement `{}` appears on the impl method but not on the corresponding \
+                     trait method",
                     predicate
                 ));
             }
             ObligationCauseCode::CompareImplTypeObligation { .. } => {
                 err.note(&format!(
-                    "the requirement `{}` appears on the associated impl type \
-                     but not on the corresponding associated trait type",
+                    "the requirement `{}` appears on the associated impl type but not on the \
+                     corresponding associated trait type",
                     predicate
                 ));
             }
index dead795c6afe7ecb14e317a42e16fefbaa145ba8..df472e6ed7e9d7698fc744efeb0076d500ee6436 100644 (file)
@@ -997,7 +997,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                 // type.
                 //
                 // NOTE: This should be kept in sync with the similar code in
-                // `rustc_ty::instance::resolve_associated_item()`.
+                // `rustc_ty_utils::instance::resolve_associated_item()`.
                 let node_item =
                     assoc_ty_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id)
                         .map_err(|ErrorReported| ())?;
index d2556c44fb453b9e8218e235d3aa0454f2358086..ca3369b8f1e9d2d2c313f16d3d782faa6efdd752 100644 (file)
@@ -350,11 +350,11 @@ fn assemble_candidates_from_caller_bounds<'o>(
 
         // Micro-optimization: filter out predicates relating to different traits.
         let matching_bounds =
-            all_bounds.filter(|p| p.def_id() == stack.obligation.predicate.def_id());
+            all_bounds.filter(|p| p.value.def_id() == stack.obligation.predicate.def_id());
 
         // Keep only those bounds which may apply, and propagate overflow if it occurs.
         for bound in matching_bounds {
-            let wc = self.evaluate_where_clause(stack, bound)?;
+            let wc = self.evaluate_where_clause(stack, bound.value)?;
             if wc.may_apply() {
                 candidates.vec.push(ParamCandidate(bound));
             }
index 7c155c7684ec25fa3a3b905d5e495898bc5cd0e1..a42c8021346496fc6a30b3f2c67e56efa4a24722 100644 (file)
@@ -8,6 +8,7 @@
 //! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::lang_items::LangItem;
+use rustc_hir::Constness;
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_infer::infer::InferOk;
 use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
@@ -55,8 +56,8 @@ pub(super) fn confirm_candidate(
             }
 
             ParamCandidate(param) => {
-                let obligations = self.confirm_param_candidate(obligation, param);
-                Ok(ImplSource::Param(obligations))
+                let obligations = self.confirm_param_candidate(obligation, param.value);
+                Ok(ImplSource::Param(obligations, param.constness))
             }
 
             ImplCandidate(impl_def_id) => {
@@ -70,7 +71,8 @@ pub(super) fn confirm_candidate(
 
             ProjectionCandidate(idx) => {
                 let obligations = self.confirm_projection_candidate(obligation, idx)?;
-                Ok(ImplSource::Param(obligations))
+                // FIXME(jschievink): constness
+                Ok(ImplSource::Param(obligations, Constness::NotConst))
             }
 
             ObjectCandidate(idx) => {
@@ -106,7 +108,7 @@ pub(super) fn confirm_candidate(
                 // This indicates something like `Trait + Send: Send`. In this case, we know that
                 // this holds because that's what the object type is telling us, and there's really
                 // no additional obligations to prove and no types in particular to unify, etc.
-                Ok(ImplSource::Param(Vec::new()))
+                Ok(ImplSource::Param(Vec::new(), Constness::NotConst))
             }
 
             BuiltinUnsizeCandidate => {
@@ -151,7 +153,7 @@ fn confirm_projection_candidate(
             obligations.extend(self.infcx.commit_if_ok(|_| {
                 self.infcx
                     .at(&obligation.cause, obligation.param_env)
-                    .sup(placeholder_trait_predicate.trait_ref.to_poly_trait_ref(), candidate)
+                    .sup(placeholder_trait_predicate.trait_ref.to_poly_trait_ref(), candidate.value)
                     .map(|InferOk { obligations, .. }| obligations)
                     .map_err(|_| Unimplemented)
             })?);
index 05ff9a6fb9ca6ea4d77a793efffce80e5298b9bc..5b31998b7d33f162b8be57bab648a7492835cf2e 100644 (file)
@@ -31,6 +31,7 @@
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_hir::Constness;
 use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::fast_reject;
@@ -1335,7 +1336,14 @@ fn candidate_should_be_dropped_in_favor_of(
             (BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate, _) => true,
             (_, BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate) => false,
 
-            (ParamCandidate(..), ParamCandidate(..)) => false,
+            (ParamCandidate(other), ParamCandidate(victim)) => {
+                if other.value == victim.value && victim.constness == Constness::NotConst {
+                    // Drop otherwise equivalent non-const candidates in favor of const candidates.
+                    true
+                } else {
+                    false
+                }
+            }
 
             // Global bounds from the where clause should be ignored
             // here (see issue #50825). Otherwise, we have a where
@@ -1354,11 +1362,11 @@ fn candidate_should_be_dropped_in_favor_of(
                 | TraitAliasCandidate(..)
                 | ObjectCandidate(_)
                 | ProjectionCandidate(_),
-            ) => !is_global(cand),
+            ) => !is_global(&cand.value),
             (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref cand)) => {
                 // Prefer these to a global where-clause bound
                 // (see issue #50825).
-                is_global(cand)
+                is_global(&cand.value)
             }
             (
                 ImplCandidate(_)
@@ -1373,7 +1381,7 @@ fn candidate_should_be_dropped_in_favor_of(
             ) => {
                 // Prefer these to a global where-clause bound
                 // (see issue #50825).
-                is_global(cand) && other.evaluation.must_apply_modulo_regions()
+                is_global(&cand.value) && other.evaluation.must_apply_modulo_regions()
             }
 
             (ProjectionCandidate(i), ProjectionCandidate(j))
@@ -2364,13 +2372,9 @@ impl<'o, 'tcx> Iterator for TraitObligationStackList<'o, 'tcx> {
     type Item = &'o TraitObligationStack<'o, 'tcx>;
 
     fn next(&mut self) -> Option<&'o TraitObligationStack<'o, 'tcx>> {
-        match self.head {
-            Some(o) => {
-                *self = o.previous;
-                Some(o)
-            }
-            None => None,
-        }
+        let o = self.head?;
+        *self = o.previous;
+        Some(o)
     }
 }
 
index 512591960f551fcf37009778d259887945226ebd..0133a961c11a7a343f2b89ef857c89f8e8642835 100644 (file)
@@ -498,8 +498,8 @@ fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<String>
 
     for (p, _) in predicates {
         if let Some(poly_trait_ref) = p.to_opt_poly_trait_ref() {
-            if Some(poly_trait_ref.def_id()) == sized_trait {
-                types_without_default_bounds.remove(poly_trait_ref.self_ty().skip_binder());
+            if Some(poly_trait_ref.value.def_id()) == sized_trait {
+                types_without_default_bounds.remove(poly_trait_ref.value.self_ty().skip_binder());
                 continue;
             }
         }
index 2430620323f72d5c50f3392def69a93e95c60e32..ab4a81c7d152edcc9bcd28e70fbf5d31c9dd7883 100644 (file)
@@ -125,7 +125,7 @@ fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool {
         let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {
             pred.subst_supertrait(tcx, &trait_ref)
                 .to_opt_poly_trait_ref()
-                .map(|trait_ref| item.clone_and_push(trait_ref, *span))
+                .map(|trait_ref| item.clone_and_push(trait_ref.value, *span))
         });
         debug!("expand_trait_aliases: items={:?}", items.clone());
 
@@ -182,7 +182,7 @@ fn next(&mut self) -> Option<DefId> {
                 .predicates
                 .iter()
                 .filter_map(|(pred, _)| pred.to_opt_poly_trait_ref())
-                .map(|trait_ref| trait_ref.def_id())
+                .map(|trait_ref| trait_ref.value.def_id())
                 .filter(|&super_def_id| visited.insert(super_def_id)),
         );
         Some(def_id)
index e5a792f229d194b930f45f4f8776bdc2c6333e4a..5bcb16d21e09c6789326ef4f40b08a763de5ba9e 100644 (file)
@@ -294,7 +294,7 @@ fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elabo
             let mut cause = cause.clone();
             if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_ref() {
                 let derived_cause = traits::DerivedObligationCause {
-                    parent_trait_ref,
+                    parent_trait_ref: parent_trait_ref.value,
                     parent_code: Rc::new(obligation.cause.code.clone()),
                 };
                 cause.make_mut().code =
diff --git a/compiler/rustc_ty/Cargo.toml b/compiler/rustc_ty/Cargo.toml
deleted file mode 100644 (file)
index acb011b..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-name = "rustc_ty"
-version = "0.0.0"
-edition = "2018"
-
-[dependencies]
-tracing = "0.1"
-rustc_middle = { path = "../rustc_middle" }
-rustc_data_structures = { path = "../rustc_data_structures" }
-rustc_errors = { path = "../rustc_errors" }
-rustc_hir = { path = "../rustc_hir" }
-rustc_infer = { path = "../rustc_infer" }
-rustc_span = { path = "../rustc_span" }
-rustc_session = { path = "../rustc_session" }
-rustc_target = { path = "../rustc_target" }
-rustc_trait_selection = { path = "../rustc_trait_selection" }
diff --git a/compiler/rustc_ty/src/common_traits.rs b/compiler/rustc_ty/src/common_traits.rs
deleted file mode 100644 (file)
index 24ba071..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-//! Queries for checking whether a type implements one of a few common traits.
-
-use rustc_hir::lang_items::LangItem;
-use rustc_infer::infer::TyCtxtInferExt;
-use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_span::DUMMY_SP;
-use rustc_trait_selection::traits;
-
-fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-    is_item_raw(tcx, query, LangItem::Copy)
-}
-
-fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-    is_item_raw(tcx, query, LangItem::Sized)
-}
-
-fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-    is_item_raw(tcx, query, LangItem::Freeze)
-}
-
-fn is_item_raw<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
-    item: LangItem,
-) -> bool {
-    let (param_env, ty) = query.into_parts();
-    let trait_def_id = tcx.require_lang_item(item, None);
-    tcx.infer_ctxt().enter(|infcx| {
-        traits::type_known_to_meet_bound_modulo_regions(
-            &infcx,
-            param_env,
-            ty,
-            trait_def_id,
-            DUMMY_SP,
-        )
-    })
-}
-
-pub(crate) fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { is_copy_raw, is_sized_raw, is_freeze_raw, ..*providers };
-}
diff --git a/compiler/rustc_ty/src/instance.rs b/compiler/rustc_ty/src/instance.rs
deleted file mode 100644 (file)
index cf2c6ef..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-use rustc_errors::ErrorReported;
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_infer::infer::TyCtxtInferExt;
-use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, Instance, TyCtxt, TypeFoldable};
-use rustc_span::{sym, DUMMY_SP};
-use rustc_target::spec::abi::Abi;
-use rustc_trait_selection::traits;
-use traits::{translate_substs, Reveal};
-
-use tracing::debug;
-
-fn resolve_instance<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>,
-) -> Result<Option<Instance<'tcx>>, ErrorReported> {
-    let (param_env, (did, substs)) = key.into_parts();
-    if let Some(did) = did.as_local() {
-        if let Some(param_did) = tcx.opt_const_param_of(did) {
-            return tcx.resolve_instance_of_const_arg(param_env.and((did, param_did, substs)));
-        }
-    }
-
-    inner_resolve_instance(tcx, param_env.and((ty::WithOptConstParam::unknown(did), substs)))
-}
-
-fn resolve_instance_of_const_arg<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    key: ty::ParamEnvAnd<'tcx, (LocalDefId, DefId, SubstsRef<'tcx>)>,
-) -> Result<Option<Instance<'tcx>>, ErrorReported> {
-    let (param_env, (did, const_param_did, substs)) = key.into_parts();
-    inner_resolve_instance(
-        tcx,
-        param_env.and((
-            ty::WithOptConstParam { did: did.to_def_id(), const_param_did: Some(const_param_did) },
-            substs,
-        )),
-    )
-}
-
-fn inner_resolve_instance<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    key: ty::ParamEnvAnd<'tcx, (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>)>,
-) -> Result<Option<Instance<'tcx>>, ErrorReported> {
-    let (param_env, (def, substs)) = key.into_parts();
-
-    debug!("resolve(def={:?}, substs={:?})", def.did, substs);
-    let result = if let Some(trait_def_id) = tcx.trait_of_item(def.did) {
-        debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
-        let item = tcx.associated_item(def.did);
-        resolve_associated_item(tcx, &item, param_env, trait_def_id, substs)
-    } else {
-        let ty = tcx.type_of(def.def_id_for_type_of());
-        let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, ty);
-
-        let def = match *item_type.kind() {
-            ty::FnDef(..)
-                if {
-                    let f = item_type.fn_sig(tcx);
-                    f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic
-                } =>
-            {
-                debug!(" => intrinsic");
-                ty::InstanceDef::Intrinsic(def.did)
-            }
-            ty::FnDef(def_id, substs) if Some(def_id) == tcx.lang_items().drop_in_place_fn() => {
-                let ty = substs.type_at(0);
-
-                if ty.needs_drop(tcx, param_env) {
-                    debug!(" => nontrivial drop glue");
-                    match *ty.kind() {
-                        ty::Closure(..)
-                        | ty::Generator(..)
-                        | ty::Tuple(..)
-                        | ty::Adt(..)
-                        | ty::Dynamic(..)
-                        | ty::Array(..)
-                        | ty::Slice(..) => {}
-                        // Drop shims can only be built from ADTs.
-                        _ => return Ok(None),
-                    }
-
-                    ty::InstanceDef::DropGlue(def_id, Some(ty))
-                } else {
-                    debug!(" => trivial drop glue");
-                    ty::InstanceDef::DropGlue(def_id, None)
-                }
-            }
-            _ => {
-                debug!(" => free item");
-                ty::InstanceDef::Item(def)
-            }
-        };
-        Ok(Some(Instance { def, substs }))
-    };
-    debug!("resolve(def.did={:?}, substs={:?}) = {:?}", def.did, substs, result);
-    result
-}
-
-fn resolve_associated_item<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_item: &ty::AssocItem,
-    param_env: ty::ParamEnv<'tcx>,
-    trait_id: DefId,
-    rcvr_substs: SubstsRef<'tcx>,
-) -> Result<Option<Instance<'tcx>>, ErrorReported> {
-    let def_id = trait_item.def_id;
-    debug!(
-        "resolve_associated_item(trait_item={:?}, \
-            param_env={:?}, \
-            trait_id={:?}, \
-            rcvr_substs={:?})",
-        def_id, param_env, trait_id, rcvr_substs
-    );
-
-    let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
-    let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref)))?;
-
-    // Now that we know which impl is being used, we can dispatch to
-    // the actual function:
-    Ok(match vtbl {
-        traits::ImplSource::UserDefined(impl_data) => {
-            debug!(
-                "resolving ImplSource::UserDefined: {:?}, {:?}, {:?}, {:?}",
-                param_env, trait_item, rcvr_substs, impl_data
-            );
-            assert!(!rcvr_substs.needs_infer());
-            assert!(!trait_ref.needs_infer());
-
-            let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
-            let trait_def = tcx.trait_def(trait_def_id);
-            let leaf_def = trait_def
-                .ancestors(tcx, impl_data.impl_def_id)?
-                .leaf_def(tcx, trait_item.ident, trait_item.kind)
-                .unwrap_or_else(|| {
-                    bug!("{:?} not found in {:?}", trait_item, impl_data.impl_def_id);
-                });
-
-            let substs = tcx.infer_ctxt().enter(|infcx| {
-                let param_env = param_env.with_reveal_all_normalized(tcx);
-                let substs = rcvr_substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
-                let substs = translate_substs(
-                    &infcx,
-                    param_env,
-                    impl_data.impl_def_id,
-                    substs,
-                    leaf_def.defining_node,
-                );
-                infcx.tcx.erase_regions(substs)
-            });
-
-            // Since this is a trait item, we need to see if the item is either a trait default item
-            // or a specialization because we can't resolve those unless we can `Reveal::All`.
-            // NOTE: This should be kept in sync with the similar code in
-            // `rustc_trait_selection::traits::project::assemble_candidates_from_impls()`.
-            let eligible = if leaf_def.is_final() {
-                // Non-specializable items are always projectable.
-                true
-            } else {
-                // Only reveal a specializable default if we're past type-checking
-                // and the obligation is monomorphic, otherwise passes such as
-                // transmute checking and polymorphic MIR optimizations could
-                // get a result which isn't correct for all monomorphizations.
-                if param_env.reveal() == Reveal::All {
-                    !trait_ref.still_further_specializable()
-                } else {
-                    false
-                }
-            };
-
-            if !eligible {
-                return Ok(None);
-            }
-
-            let substs = tcx.erase_regions(substs);
-
-            // Check if we just resolved an associated `const` declaration from
-            // a `trait` to an associated `const` definition in an `impl`, where
-            // the definition in the `impl` has the wrong type (for which an
-            // error has already been/will be emitted elsewhere).
-            //
-            // NB: this may be expensive, we try to skip it in all the cases where
-            // we know the error would've been caught (e.g. in an upstream crate).
-            //
-            // A better approach might be to just introduce a query (returning
-            // `Result<(), ErrorReported>`) for the check that `rustc_typeck`
-            // performs (i.e. that the definition's type in the `impl` matches
-            // the declaration in the `trait`), so that we can cheaply check
-            // here if it failed, instead of approximating it.
-            if trait_item.kind == ty::AssocKind::Const
-                && trait_item.def_id != leaf_def.item.def_id
-                && leaf_def.item.def_id.is_local()
-            {
-                let normalized_type_of = |def_id, substs| {
-                    tcx.subst_and_normalize_erasing_regions(substs, param_env, tcx.type_of(def_id))
-                };
-
-                let original_ty = normalized_type_of(trait_item.def_id, rcvr_substs);
-                let resolved_ty = normalized_type_of(leaf_def.item.def_id, substs);
-
-                if original_ty != resolved_ty {
-                    let msg = format!(
-                        "Instance::resolve: inconsistent associated `const` type: \
-                         was `{}: {}` but resolved to `{}: {}`",
-                        tcx.def_path_str_with_substs(trait_item.def_id, rcvr_substs),
-                        original_ty,
-                        tcx.def_path_str_with_substs(leaf_def.item.def_id, substs),
-                        resolved_ty,
-                    );
-                    let span = tcx.def_span(leaf_def.item.def_id);
-                    tcx.sess.delay_span_bug(span, &msg);
-
-                    return Err(ErrorReported);
-                }
-            }
-
-            Some(ty::Instance::new(leaf_def.item.def_id, substs))
-        }
-        traits::ImplSource::Generator(generator_data) => Some(Instance {
-            def: ty::InstanceDef::Item(ty::WithOptConstParam::unknown(
-                generator_data.generator_def_id,
-            )),
-            substs: generator_data.substs,
-        }),
-        traits::ImplSource::Closure(closure_data) => {
-            let trait_closure_kind = tcx.fn_trait_kind_from_lang_item(trait_id).unwrap();
-            Some(Instance::resolve_closure(
-                tcx,
-                closure_data.closure_def_id,
-                closure_data.substs,
-                trait_closure_kind,
-            ))
-        }
-        traits::ImplSource::FnPointer(ref data) => match data.fn_ty.kind() {
-            ty::FnDef(..) | ty::FnPtr(..) => Some(Instance {
-                def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),
-                substs: rcvr_substs,
-            }),
-            _ => None,
-        },
-        traits::ImplSource::Object(ref data) => {
-            let index = traits::get_vtable_index_of_object_method(tcx, data, def_id);
-            Some(Instance { def: ty::InstanceDef::Virtual(def_id, index), substs: rcvr_substs })
-        }
-        traits::ImplSource::Builtin(..) => {
-            if Some(trait_ref.def_id) == tcx.lang_items().clone_trait() {
-                // FIXME(eddyb) use lang items for methods instead of names.
-                let name = tcx.item_name(def_id);
-                if name == sym::clone {
-                    let self_ty = trait_ref.self_ty();
-
-                    let is_copy = self_ty.is_copy_modulo_regions(tcx.at(DUMMY_SP), param_env);
-                    match self_ty.kind() {
-                        _ if is_copy => (),
-                        ty::Array(..) | ty::Closure(..) | ty::Tuple(..) => {}
-                        _ => return Ok(None),
-                    };
-
-                    Some(Instance {
-                        def: ty::InstanceDef::CloneShim(def_id, self_ty),
-                        substs: rcvr_substs,
-                    })
-                } else {
-                    assert_eq!(name, sym::clone_from);
-
-                    // Use the default `fn clone_from` from `trait Clone`.
-                    let substs = tcx.erase_regions(rcvr_substs);
-                    Some(ty::Instance::new(def_id, substs))
-                }
-            } else {
-                None
-            }
-        }
-        traits::ImplSource::AutoImpl(..)
-        | traits::ImplSource::Param(..)
-        | traits::ImplSource::TraitAlias(..)
-        | traits::ImplSource::DiscriminantKind(..) => None,
-    })
-}
-
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers =
-        ty::query::Providers { resolve_instance, resolve_instance_of_const_arg, ..*providers };
-}
diff --git a/compiler/rustc_ty/src/lib.rs b/compiler/rustc_ty/src/lib.rs
deleted file mode 100644 (file)
index 904c006..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-//! Various checks
-//!
-//! # Note
-//!
-//! This API is completely unstable and subject to change.
-
-#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![feature(nll)]
-#![recursion_limit = "256"]
-
-#[macro_use]
-extern crate rustc_middle;
-#[macro_use]
-extern crate tracing;
-
-use rustc_middle::ty::query::Providers;
-
-mod common_traits;
-pub mod instance;
-mod needs_drop;
-mod ty;
-
-pub fn provide(providers: &mut Providers) {
-    common_traits::provide(providers);
-    needs_drop::provide(providers);
-    ty::provide(providers);
-    instance::provide(providers);
-}
diff --git a/compiler/rustc_ty/src/needs_drop.rs b/compiler/rustc_ty/src/needs_drop.rs
deleted file mode 100644 (file)
index d62fc76..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-//! Check whether a type has (potentially) non-trivial drop glue.
-
-use rustc_data_structures::fx::FxHashSet;
-use rustc_hir::def_id::DefId;
-use rustc_middle::ty::subst::Subst;
-use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop};
-use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_session::Limit;
-use rustc_span::DUMMY_SP;
-
-type NeedsDropResult<T> = Result<T, AlwaysRequiresDrop>;
-
-fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-    let adt_fields =
-        move |adt_def: &ty::AdtDef| tcx.adt_drop_tys(adt_def.did).map(|tys| tys.iter());
-    // If we don't know a type doesn't need drop, for example if it's a type
-    // parameter without a `Copy` bound, then we conservatively return that it
-    // needs drop.
-    let res = NeedsDropTypes::new(tcx, query.param_env, query.value, adt_fields).next().is_some();
-    debug!("needs_drop_raw({:?}) = {:?}", query, res);
-    res
-}
-
-struct NeedsDropTypes<'tcx, F> {
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    query_ty: Ty<'tcx>,
-    seen_tys: FxHashSet<Ty<'tcx>>,
-    /// A stack of types left to process, and the recursion depth when we
-    /// pushed that type. Each round, we pop something from the stack and check
-    /// if it needs drop. If the result depends on whether some other types
-    /// need drop we push them onto the stack.
-    unchecked_tys: Vec<(Ty<'tcx>, usize)>,
-    recursion_limit: Limit,
-    adt_components: F,
-}
-
-impl<'tcx, F> NeedsDropTypes<'tcx, F> {
-    fn new(
-        tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        ty: Ty<'tcx>,
-        adt_components: F,
-    ) -> Self {
-        let mut seen_tys = FxHashSet::default();
-        seen_tys.insert(ty);
-        Self {
-            tcx,
-            param_env,
-            seen_tys,
-            query_ty: ty,
-            unchecked_tys: vec![(ty, 0)],
-            recursion_limit: tcx.sess.recursion_limit(),
-            adt_components,
-        }
-    }
-}
-
-impl<'tcx, F, I> Iterator for NeedsDropTypes<'tcx, F>
-where
-    F: Fn(&ty::AdtDef) -> NeedsDropResult<I>,
-    I: Iterator<Item = Ty<'tcx>>,
-{
-    type Item = NeedsDropResult<Ty<'tcx>>;
-
-    fn next(&mut self) -> Option<NeedsDropResult<Ty<'tcx>>> {
-        let tcx = self.tcx;
-
-        while let Some((ty, level)) = self.unchecked_tys.pop() {
-            if !self.recursion_limit.value_within_limit(level) {
-                // Not having a `Span` isn't great. But there's hopefully some other
-                // recursion limit error as well.
-                tcx.sess.span_err(
-                    DUMMY_SP,
-                    &format!("overflow while checking whether `{}` requires drop", self.query_ty),
-                );
-                return Some(Err(AlwaysRequiresDrop));
-            }
-
-            let components = match needs_drop_components(ty, &tcx.data_layout) {
-                Err(e) => return Some(Err(e)),
-                Ok(components) => components,
-            };
-            debug!("needs_drop_components({:?}) = {:?}", ty, components);
-
-            let queue_type = move |this: &mut Self, component: Ty<'tcx>| {
-                if this.seen_tys.insert(component) {
-                    this.unchecked_tys.push((component, level + 1));
-                }
-            };
-
-            for component in components {
-                match *component.kind() {
-                    _ if component.is_copy_modulo_regions(tcx.at(DUMMY_SP), self.param_env) => (),
-
-                    ty::Closure(_, substs) => {
-                        for upvar_ty in substs.as_closure().upvar_tys() {
-                            queue_type(self, upvar_ty);
-                        }
-                    }
-
-                    ty::Generator(def_id, substs, _) => {
-                        let substs = substs.as_generator();
-                        for upvar_ty in substs.upvar_tys() {
-                            queue_type(self, upvar_ty);
-                        }
-
-                        let witness = substs.witness();
-                        let interior_tys = match witness.kind() {
-                            &ty::GeneratorWitness(tys) => tcx.erase_late_bound_regions(tys),
-                            _ => {
-                                tcx.sess.delay_span_bug(
-                                    tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP),
-                                    &format!("unexpected generator witness type {:?}", witness),
-                                );
-                                return Some(Err(AlwaysRequiresDrop));
-                            }
-                        };
-
-                        for interior_ty in interior_tys {
-                            queue_type(self, interior_ty);
-                        }
-                    }
-
-                    // Check for a `Drop` impl and whether this is a union or
-                    // `ManuallyDrop`. If it's a struct or enum without a `Drop`
-                    // impl then check whether the field types need `Drop`.
-                    ty::Adt(adt_def, substs) => {
-                        let tys = match (self.adt_components)(adt_def) {
-                            Err(e) => return Some(Err(e)),
-                            Ok(tys) => tys,
-                        };
-                        for required_ty in tys {
-                            let subst_ty = tcx.normalize_erasing_regions(
-                                self.param_env,
-                                required_ty.subst(tcx, substs),
-                            );
-                            queue_type(self, subst_ty);
-                        }
-                    }
-                    ty::Array(..) | ty::Opaque(..) | ty::Projection(..) | ty::Param(_) => {
-                        if ty == component {
-                            // Return the type to the caller: they may be able
-                            // to normalize further than we can.
-                            return Some(Ok(component));
-                        } else {
-                            // Store the type for later. We can't return here
-                            // because we would then lose any other components
-                            // of the type.
-                            queue_type(self, component);
-                        }
-                    }
-                    _ => return Some(Err(AlwaysRequiresDrop)),
-                }
-            }
-        }
-
-        None
-    }
-}
-
-fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
-    let adt_components = move |adt_def: &ty::AdtDef| {
-        if adt_def.is_manually_drop() {
-            debug!("adt_drop_tys: `{:?}` is manually drop", adt_def);
-            return Ok(Vec::new().into_iter());
-        } else if adt_def.destructor(tcx).is_some() {
-            debug!("adt_drop_tys: `{:?}` implements `Drop`", adt_def);
-            return Err(AlwaysRequiresDrop);
-        } else if adt_def.is_union() {
-            debug!("adt_drop_tys: `{:?}` is a union", adt_def);
-            return Ok(Vec::new().into_iter());
-        }
-        Ok(adt_def.all_fields().map(|field| tcx.type_of(field.did)).collect::<Vec<_>>().into_iter())
-    };
-
-    let adt_ty = tcx.type_of(def_id);
-    let param_env = tcx.param_env(def_id);
-    let res: Result<Vec<_>, _> =
-        NeedsDropTypes::new(tcx, param_env, adt_ty, adt_components).collect();
-
-    debug!("adt_drop_tys(`{}`) = `{:?}`", tcx.def_path_str(def_id), res);
-    res.map(|components| tcx.intern_type_list(&components))
-}
-
-pub(crate) fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { needs_drop_raw, adt_drop_tys, ..*providers };
-}
diff --git a/compiler/rustc_ty/src/ty.rs b/compiler/rustc_ty/src/ty.rs
deleted file mode 100644 (file)
index 720ad42..0000000
+++ /dev/null
@@ -1,505 +0,0 @@
-use rustc_data_structures::fx::FxIndexSet;
-use rustc_data_structures::svh::Svh;
-use rustc_hir as hir;
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
-use rustc_middle::hir::map as hir_map;
-use rustc_middle::ty::subst::Subst;
-use rustc_middle::ty::{
-    self, Binder, Predicate, PredicateAtom, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness,
-};
-use rustc_session::CrateDisambiguator;
-use rustc_span::symbol::Symbol;
-use rustc_span::Span;
-use rustc_trait_selection::traits;
-
-fn sized_constraint_for_ty<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    adtdef: &ty::AdtDef,
-    ty: Ty<'tcx>,
-) -> Vec<Ty<'tcx>> {
-    use ty::TyKind::*;
-
-    let result = match ty.kind() {
-        Bool | Char | Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..)
-        | FnPtr(_) | Array(..) | Closure(..) | Generator(..) | Never => vec![],
-
-        Str | Dynamic(..) | Slice(_) | Foreign(..) | Error(_) | GeneratorWitness(..) => {
-            // these are never sized - return the target type
-            vec![ty]
-        }
-
-        Tuple(ref tys) => match tys.last() {
-            None => vec![],
-            Some(ty) => sized_constraint_for_ty(tcx, adtdef, ty.expect_ty()),
-        },
-
-        Adt(adt, substs) => {
-            // recursive case
-            let adt_tys = adt.sized_constraint(tcx);
-            debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_tys);
-            adt_tys
-                .iter()
-                .map(|ty| ty.subst(tcx, substs))
-                .flat_map(|ty| sized_constraint_for_ty(tcx, adtdef, ty))
-                .collect()
-        }
-
-        Projection(..) | Opaque(..) => {
-            // must calculate explicitly.
-            // FIXME: consider special-casing always-Sized projections
-            vec![ty]
-        }
-
-        Param(..) => {
-            // perf hack: if there is a `T: Sized` bound, then
-            // we know that `T` is Sized and do not need to check
-            // it on the impl.
-
-            let sized_trait = match tcx.lang_items().sized_trait() {
-                Some(x) => x,
-                _ => return vec![ty],
-            };
-            let sized_predicate = ty::Binder::dummy(ty::TraitRef {
-                def_id: sized_trait,
-                substs: tcx.mk_substs_trait(ty, &[]),
-            })
-            .without_const()
-            .to_predicate(tcx);
-            let predicates = tcx.predicates_of(adtdef.did).predicates;
-            if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] }
-        }
-
-        Placeholder(..) | Bound(..) | Infer(..) => {
-            bug!("unexpected type `{:?}` in sized_constraint_for_ty", ty)
-        }
-    };
-    debug!("sized_constraint_for_ty({:?}) = {:?}", ty, result);
-    result
-}
-
-fn associated_item_from_trait_item_ref(
-    tcx: TyCtxt<'_>,
-    parent_def_id: LocalDefId,
-    trait_item_ref: &hir::TraitItemRef,
-) -> ty::AssocItem {
-    let def_id = tcx.hir().local_def_id(trait_item_ref.id.hir_id);
-    let (kind, has_self) = match trait_item_ref.kind {
-        hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
-        hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
-        hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
-    };
-
-    ty::AssocItem {
-        ident: trait_item_ref.ident,
-        kind,
-        vis: tcx.visibility(def_id),
-        defaultness: trait_item_ref.defaultness,
-        def_id: def_id.to_def_id(),
-        container: ty::TraitContainer(parent_def_id.to_def_id()),
-        fn_has_self_parameter: has_self,
-    }
-}
-
-fn associated_item_from_impl_item_ref(
-    tcx: TyCtxt<'_>,
-    parent_def_id: LocalDefId,
-    impl_item_ref: &hir::ImplItemRef<'_>,
-) -> ty::AssocItem {
-    let def_id = tcx.hir().local_def_id(impl_item_ref.id.hir_id);
-    let (kind, has_self) = match impl_item_ref.kind {
-        hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
-        hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
-        hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
-    };
-
-    ty::AssocItem {
-        ident: impl_item_ref.ident,
-        kind,
-        vis: tcx.visibility(def_id),
-        defaultness: impl_item_ref.defaultness,
-        def_id: def_id.to_def_id(),
-        container: ty::ImplContainer(parent_def_id.to_def_id()),
-        fn_has_self_parameter: has_self,
-    }
-}
-
-fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
-    let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-    let parent_id = tcx.hir().get_parent_item(id);
-    let parent_def_id = tcx.hir().local_def_id(parent_id);
-    let parent_item = tcx.hir().expect_item(parent_id);
-    match parent_item.kind {
-        hir::ItemKind::Impl { ref items, .. } => {
-            if let Some(impl_item_ref) = items.iter().find(|i| i.id.hir_id == id) {
-                let assoc_item =
-                    associated_item_from_impl_item_ref(tcx, parent_def_id, impl_item_ref);
-                debug_assert_eq!(assoc_item.def_id, def_id);
-                return assoc_item;
-            }
-        }
-
-        hir::ItemKind::Trait(.., ref trait_item_refs) => {
-            if let Some(trait_item_ref) = trait_item_refs.iter().find(|i| i.id.hir_id == id) {
-                let assoc_item =
-                    associated_item_from_trait_item_ref(tcx, parent_def_id, trait_item_ref);
-                debug_assert_eq!(assoc_item.def_id, def_id);
-                return assoc_item;
-            }
-        }
-
-        _ => {}
-    }
-
-    span_bug!(
-        parent_item.span,
-        "unexpected parent of trait or impl item or item not found: {:?}",
-        parent_item.kind
-    )
-}
-
-fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-    let item = tcx.hir().expect_item(hir_id);
-    if let hir::ItemKind::Impl { defaultness, .. } = item.kind {
-        defaultness
-    } else {
-        bug!("`impl_defaultness` called on {:?}", item);
-    }
-}
-
-/// Calculates the `Sized` constraint.
-///
-/// In fact, there are only a few options for the types in the constraint:
-///     - an obviously-unsized type
-///     - a type parameter or projection whose Sizedness can't be known
-///     - a tuple of type parameters or projections, if there are multiple
-///       such.
-///     - a Error, if a type contained itself. The representability
-///       check should catch this case.
-fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtSizedConstraint<'_> {
-    let def = tcx.adt_def(def_id);
-
-    let result = tcx.mk_type_list(
-        def.variants
-            .iter()
-            .flat_map(|v| v.fields.last())
-            .flat_map(|f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did))),
-    );
-
-    debug!("adt_sized_constraint: {:?} => {:?}", def, result);
-
-    ty::AdtSizedConstraint(result)
-}
-
-fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
-    let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-    let item = tcx.hir().expect_item(id);
-    match item.kind {
-        hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter(
-            trait_item_refs
-                .iter()
-                .map(|trait_item_ref| trait_item_ref.id)
-                .map(|id| tcx.hir().local_def_id(id.hir_id).to_def_id()),
-        ),
-        hir::ItemKind::Impl { ref items, .. } => tcx.arena.alloc_from_iter(
-            items
-                .iter()
-                .map(|impl_item_ref| impl_item_ref.id)
-                .map(|id| tcx.hir().local_def_id(id.hir_id).to_def_id()),
-        ),
-        hir::ItemKind::TraitAlias(..) => &[],
-        _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
-    }
-}
-
-fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssociatedItems<'_> {
-    let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did));
-    ty::AssociatedItems::new(items)
-}
-
-fn def_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span {
-    tcx.hir().span_if_local(def_id).unwrap()
-}
-
-/// If the given `DefId` describes an item belonging to a trait,
-/// returns the `DefId` of the trait that the trait item belongs to;
-/// otherwise, returns `None`.
-fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
-    tcx.opt_associated_item(def_id).and_then(|associated_item| match associated_item.container {
-        ty::TraitContainer(def_id) => Some(def_id),
-        ty::ImplContainer(_) => None,
-    })
-}
-
-/// See `ParamEnv` struct definition for details.
-fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
-    // The param_env of an impl Trait type is its defining function's param_env
-    if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
-        return param_env(tcx, parent);
-    }
-    // Compute the bounds on Self and the type parameters.
-
-    let ty::InstantiatedPredicates { mut predicates, .. } =
-        tcx.predicates_of(def_id).instantiate_identity(tcx);
-
-    // Finally, we have to normalize the bounds in the environment, in
-    // case they contain any associated type projections. This process
-    // can yield errors if the put in illegal associated types, like
-    // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We
-    // report these errors right here; this doesn't actually feel
-    // right to me, because constructing the environment feels like a
-    // kind of a "idempotent" action, but I'm not sure where would be
-    // a better place. In practice, we construct environments for
-    // every fn once during type checking, and we'll abort if there
-    // are any errors at that point, so after type checking you can be
-    // sure that this will succeed without errors anyway.
-
-    if tcx.sess.opts.debugging_opts.chalk {
-        let environment = well_formed_types_in_env(tcx, def_id);
-        predicates.extend(environment);
-    }
-
-    let unnormalized_env =
-        ty::ParamEnv::new(tcx.intern_predicates(&predicates), traits::Reveal::UserFacing);
-
-    let body_id = def_id
-        .as_local()
-        .map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
-        .map_or(hir::CRATE_HIR_ID, |id| {
-            tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id)
-        });
-    let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
-    traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
-}
-
-/// Elaborate the environment.
-///
-/// Collect a list of `Predicate`'s used for building the `ParamEnv`. Adds `TypeWellFormedFromEnv`'s
-/// that are assumed to be well-formed (because they come from the environment).
-///
-/// Used only in chalk mode.
-fn well_formed_types_in_env<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    def_id: DefId,
-) -> &'tcx ty::List<Predicate<'tcx>> {
-    use rustc_hir::{ForeignItemKind, ImplItemKind, ItemKind, Node, TraitItemKind};
-    use rustc_middle::ty::subst::GenericArgKind;
-
-    debug!("environment(def_id = {:?})", def_id);
-
-    // The environment of an impl Trait type is its defining function's environment.
-    if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
-        return well_formed_types_in_env(tcx, parent);
-    }
-
-    // Compute the bounds on `Self` and the type parameters.
-    let ty::InstantiatedPredicates { predicates, .. } =
-        tcx.predicates_of(def_id).instantiate_identity(tcx);
-
-    let clauses = predicates.into_iter();
-
-    if !def_id.is_local() {
-        return ty::List::empty();
-    }
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-    let node = tcx.hir().get(hir_id);
-
-    enum NodeKind {
-        TraitImpl,
-        InherentImpl,
-        Fn,
-        Other,
-    };
-
-    let node_kind = match node {
-        Node::TraitItem(item) => match item.kind {
-            TraitItemKind::Fn(..) => NodeKind::Fn,
-            _ => NodeKind::Other,
-        },
-
-        Node::ImplItem(item) => match item.kind {
-            ImplItemKind::Fn(..) => NodeKind::Fn,
-            _ => NodeKind::Other,
-        },
-
-        Node::Item(item) => match item.kind {
-            ItemKind::Impl { of_trait: Some(_), .. } => NodeKind::TraitImpl,
-            ItemKind::Impl { of_trait: None, .. } => NodeKind::InherentImpl,
-            ItemKind::Fn(..) => NodeKind::Fn,
-            _ => NodeKind::Other,
-        },
-
-        Node::ForeignItem(item) => match item.kind {
-            ForeignItemKind::Fn(..) => NodeKind::Fn,
-            _ => NodeKind::Other,
-        },
-
-        // FIXME: closures?
-        _ => NodeKind::Other,
-    };
-
-    // FIXME(eddyb) isn't the unordered nature of this a hazard?
-    let mut inputs = FxIndexSet::default();
-
-    match node_kind {
-        // In a trait impl, we assume that the header trait ref and all its
-        // constituents are well-formed.
-        NodeKind::TraitImpl => {
-            let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl");
-
-            // FIXME(chalk): this has problems because of late-bound regions
-            //inputs.extend(trait_ref.substs.iter().flat_map(|arg| arg.walk()));
-            inputs.extend(trait_ref.substs.iter());
-        }
-
-        // In an inherent impl, we assume that the receiver type and all its
-        // constituents are well-formed.
-        NodeKind::InherentImpl => {
-            let self_ty = tcx.type_of(def_id);
-            inputs.extend(self_ty.walk());
-        }
-
-        // In an fn, we assume that the arguments and all their constituents are
-        // well-formed.
-        NodeKind::Fn => {
-            let fn_sig = tcx.fn_sig(def_id);
-            let fn_sig = tcx.liberate_late_bound_regions(def_id, fn_sig);
-
-            inputs.extend(fn_sig.inputs().iter().flat_map(|ty| ty.walk()));
-        }
-
-        NodeKind::Other => (),
-    }
-    let input_clauses = inputs.into_iter().filter_map(|arg| {
-        match arg.unpack() {
-            GenericArgKind::Type(ty) => {
-                let binder = Binder::dummy(PredicateAtom::TypeWellFormedFromEnv(ty));
-                Some(tcx.mk_predicate(PredicateKind::ForAll(binder)))
-            }
-
-            // FIXME(eddyb) no WF conditions from lifetimes?
-            GenericArgKind::Lifetime(_) => None,
-
-            // FIXME(eddyb) support const generics in Chalk
-            GenericArgKind::Const(_) => None,
-        }
-    });
-
-    tcx.mk_predicates(clauses.chain(input_clauses))
-}
-
-fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
-    tcx.param_env(def_id).with_reveal_all_normalized(tcx)
-}
-
-fn crate_disambiguator(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateDisambiguator {
-    assert_eq!(crate_num, LOCAL_CRATE);
-    tcx.sess.local_crate_disambiguator()
-}
-
-fn original_crate_name(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Symbol {
-    assert_eq!(crate_num, LOCAL_CRATE);
-    tcx.crate_name
-}
-
-fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
-    tcx.index_hir(crate_num).crate_hash
-}
-
-fn instance_def_size_estimate<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    instance_def: ty::InstanceDef<'tcx>,
-) -> usize {
-    use ty::InstanceDef;
-
-    match instance_def {
-        InstanceDef::Item(..) | InstanceDef::DropGlue(..) => {
-            let mir = tcx.instance_mir(instance_def);
-            mir.basic_blocks().iter().map(|bb| bb.statements.len()).sum()
-        }
-        // Estimate the size of other compiler-generated shims to be 1.
-        _ => 1,
-    }
-}
-
-/// If `def_id` is an issue 33140 hack impl, returns its self type; otherwise, returns `None`.
-///
-/// See [`ty::ImplOverlapKind::Issue33140`] for more details.
-fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
-    debug!("issue33140_self_ty({:?})", def_id);
-
-    let trait_ref = tcx
-        .impl_trait_ref(def_id)
-        .unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id));
-
-    debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref);
-
-    let is_marker_like = tcx.impl_polarity(def_id) == ty::ImplPolarity::Positive
-        && tcx.associated_item_def_ids(trait_ref.def_id).is_empty();
-
-    // Check whether these impls would be ok for a marker trait.
-    if !is_marker_like {
-        debug!("issue33140_self_ty - not marker-like!");
-        return None;
-    }
-
-    // impl must be `impl Trait for dyn Marker1 + Marker2 + ...`
-    if trait_ref.substs.len() != 1 {
-        debug!("issue33140_self_ty - impl has substs!");
-        return None;
-    }
-
-    let predicates = tcx.predicates_of(def_id);
-    if predicates.parent.is_some() || !predicates.predicates.is_empty() {
-        debug!("issue33140_self_ty - impl has predicates {:?}!", predicates);
-        return None;
-    }
-
-    let self_ty = trait_ref.self_ty();
-    let self_ty_matches = match self_ty.kind() {
-        ty::Dynamic(ref data, ty::ReStatic) => data.principal().is_none(),
-        _ => false,
-    };
-
-    if self_ty_matches {
-        debug!("issue33140_self_ty - MATCHES!");
-        Some(self_ty)
-    } else {
-        debug!("issue33140_self_ty - non-matching self type");
-        None
-    }
-}
-
-/// Check if a function is async.
-fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-
-    let node = tcx.hir().get(hir_id);
-
-    let fn_like = hir_map::blocks::FnLikeNode::from_node(node).unwrap_or_else(|| {
-        bug!("asyncness: expected fn-like node but got `{:?}`", def_id);
-    });
-
-    fn_like.asyncness()
-}
-
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers {
-        asyncness,
-        associated_item,
-        associated_item_def_ids,
-        associated_items,
-        adt_sized_constraint,
-        def_span,
-        param_env,
-        param_env_reveal_all_normalized,
-        trait_of_item,
-        crate_disambiguator,
-        original_crate_name,
-        crate_hash,
-        instance_def_size_estimate,
-        issue33140_self_ty,
-        impl_defaultness,
-        ..*providers
-    };
-}
diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml
new file mode 100644 (file)
index 0000000..5020437
--- /dev/null
@@ -0,0 +1,17 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_ty_utils"
+version = "0.0.0"
+edition = "2018"
+
+[dependencies]
+tracing = "0.1"
+rustc_middle = { path = "../rustc_middle" }
+rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_errors = { path = "../rustc_errors" }
+rustc_hir = { path = "../rustc_hir" }
+rustc_infer = { path = "../rustc_infer" }
+rustc_span = { path = "../rustc_span" }
+rustc_session = { path = "../rustc_session" }
+rustc_target = { path = "../rustc_target" }
+rustc_trait_selection = { path = "../rustc_trait_selection" }
diff --git a/compiler/rustc_ty_utils/src/common_traits.rs b/compiler/rustc_ty_utils/src/common_traits.rs
new file mode 100644 (file)
index 0000000..24ba071
--- /dev/null
@@ -0,0 +1,41 @@
+//! Queries for checking whether a type implements one of a few common traits.
+
+use rustc_hir::lang_items::LangItem;
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::DUMMY_SP;
+use rustc_trait_selection::traits;
+
+fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
+    is_item_raw(tcx, query, LangItem::Copy)
+}
+
+fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
+    is_item_raw(tcx, query, LangItem::Sized)
+}
+
+fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
+    is_item_raw(tcx, query, LangItem::Freeze)
+}
+
+fn is_item_raw<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
+    item: LangItem,
+) -> bool {
+    let (param_env, ty) = query.into_parts();
+    let trait_def_id = tcx.require_lang_item(item, None);
+    tcx.infer_ctxt().enter(|infcx| {
+        traits::type_known_to_meet_bound_modulo_regions(
+            &infcx,
+            param_env,
+            ty,
+            trait_def_id,
+            DUMMY_SP,
+        )
+    })
+}
+
+pub(crate) fn provide(providers: &mut ty::query::Providers) {
+    *providers = ty::query::Providers { is_copy_raw, is_sized_raw, is_freeze_raw, ..*providers };
+}
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
new file mode 100644 (file)
index 0000000..cf2c6ef
--- /dev/null
@@ -0,0 +1,284 @@
+use rustc_errors::ErrorReported;
+use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::{self, Instance, TyCtxt, TypeFoldable};
+use rustc_span::{sym, DUMMY_SP};
+use rustc_target::spec::abi::Abi;
+use rustc_trait_selection::traits;
+use traits::{translate_substs, Reveal};
+
+use tracing::debug;
+
+fn resolve_instance<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>,
+) -> Result<Option<Instance<'tcx>>, ErrorReported> {
+    let (param_env, (did, substs)) = key.into_parts();
+    if let Some(did) = did.as_local() {
+        if let Some(param_did) = tcx.opt_const_param_of(did) {
+            return tcx.resolve_instance_of_const_arg(param_env.and((did, param_did, substs)));
+        }
+    }
+
+    inner_resolve_instance(tcx, param_env.and((ty::WithOptConstParam::unknown(did), substs)))
+}
+
+fn resolve_instance_of_const_arg<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    key: ty::ParamEnvAnd<'tcx, (LocalDefId, DefId, SubstsRef<'tcx>)>,
+) -> Result<Option<Instance<'tcx>>, ErrorReported> {
+    let (param_env, (did, const_param_did, substs)) = key.into_parts();
+    inner_resolve_instance(
+        tcx,
+        param_env.and((
+            ty::WithOptConstParam { did: did.to_def_id(), const_param_did: Some(const_param_did) },
+            substs,
+        )),
+    )
+}
+
+fn inner_resolve_instance<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    key: ty::ParamEnvAnd<'tcx, (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>)>,
+) -> Result<Option<Instance<'tcx>>, ErrorReported> {
+    let (param_env, (def, substs)) = key.into_parts();
+
+    debug!("resolve(def={:?}, substs={:?})", def.did, substs);
+    let result = if let Some(trait_def_id) = tcx.trait_of_item(def.did) {
+        debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
+        let item = tcx.associated_item(def.did);
+        resolve_associated_item(tcx, &item, param_env, trait_def_id, substs)
+    } else {
+        let ty = tcx.type_of(def.def_id_for_type_of());
+        let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, ty);
+
+        let def = match *item_type.kind() {
+            ty::FnDef(..)
+                if {
+                    let f = item_type.fn_sig(tcx);
+                    f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic
+                } =>
+            {
+                debug!(" => intrinsic");
+                ty::InstanceDef::Intrinsic(def.did)
+            }
+            ty::FnDef(def_id, substs) if Some(def_id) == tcx.lang_items().drop_in_place_fn() => {
+                let ty = substs.type_at(0);
+
+                if ty.needs_drop(tcx, param_env) {
+                    debug!(" => nontrivial drop glue");
+                    match *ty.kind() {
+                        ty::Closure(..)
+                        | ty::Generator(..)
+                        | ty::Tuple(..)
+                        | ty::Adt(..)
+                        | ty::Dynamic(..)
+                        | ty::Array(..)
+                        | ty::Slice(..) => {}
+                        // Drop shims can only be built from ADTs.
+                        _ => return Ok(None),
+                    }
+
+                    ty::InstanceDef::DropGlue(def_id, Some(ty))
+                } else {
+                    debug!(" => trivial drop glue");
+                    ty::InstanceDef::DropGlue(def_id, None)
+                }
+            }
+            _ => {
+                debug!(" => free item");
+                ty::InstanceDef::Item(def)
+            }
+        };
+        Ok(Some(Instance { def, substs }))
+    };
+    debug!("resolve(def.did={:?}, substs={:?}) = {:?}", def.did, substs, result);
+    result
+}
+
+fn resolve_associated_item<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_item: &ty::AssocItem,
+    param_env: ty::ParamEnv<'tcx>,
+    trait_id: DefId,
+    rcvr_substs: SubstsRef<'tcx>,
+) -> Result<Option<Instance<'tcx>>, ErrorReported> {
+    let def_id = trait_item.def_id;
+    debug!(
+        "resolve_associated_item(trait_item={:?}, \
+            param_env={:?}, \
+            trait_id={:?}, \
+            rcvr_substs={:?})",
+        def_id, param_env, trait_id, rcvr_substs
+    );
+
+    let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
+    let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref)))?;
+
+    // Now that we know which impl is being used, we can dispatch to
+    // the actual function:
+    Ok(match vtbl {
+        traits::ImplSource::UserDefined(impl_data) => {
+            debug!(
+                "resolving ImplSource::UserDefined: {:?}, {:?}, {:?}, {:?}",
+                param_env, trait_item, rcvr_substs, impl_data
+            );
+            assert!(!rcvr_substs.needs_infer());
+            assert!(!trait_ref.needs_infer());
+
+            let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
+            let trait_def = tcx.trait_def(trait_def_id);
+            let leaf_def = trait_def
+                .ancestors(tcx, impl_data.impl_def_id)?
+                .leaf_def(tcx, trait_item.ident, trait_item.kind)
+                .unwrap_or_else(|| {
+                    bug!("{:?} not found in {:?}", trait_item, impl_data.impl_def_id);
+                });
+
+            let substs = tcx.infer_ctxt().enter(|infcx| {
+                let param_env = param_env.with_reveal_all_normalized(tcx);
+                let substs = rcvr_substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
+                let substs = translate_substs(
+                    &infcx,
+                    param_env,
+                    impl_data.impl_def_id,
+                    substs,
+                    leaf_def.defining_node,
+                );
+                infcx.tcx.erase_regions(substs)
+            });
+
+            // Since this is a trait item, we need to see if the item is either a trait default item
+            // or a specialization because we can't resolve those unless we can `Reveal::All`.
+            // NOTE: This should be kept in sync with the similar code in
+            // `rustc_trait_selection::traits::project::assemble_candidates_from_impls()`.
+            let eligible = if leaf_def.is_final() {
+                // Non-specializable items are always projectable.
+                true
+            } else {
+                // Only reveal a specializable default if we're past type-checking
+                // and the obligation is monomorphic, otherwise passes such as
+                // transmute checking and polymorphic MIR optimizations could
+                // get a result which isn't correct for all monomorphizations.
+                if param_env.reveal() == Reveal::All {
+                    !trait_ref.still_further_specializable()
+                } else {
+                    false
+                }
+            };
+
+            if !eligible {
+                return Ok(None);
+            }
+
+            let substs = tcx.erase_regions(substs);
+
+            // Check if we just resolved an associated `const` declaration from
+            // a `trait` to an associated `const` definition in an `impl`, where
+            // the definition in the `impl` has the wrong type (for which an
+            // error has already been/will be emitted elsewhere).
+            //
+            // NB: this may be expensive, we try to skip it in all the cases where
+            // we know the error would've been caught (e.g. in an upstream crate).
+            //
+            // A better approach might be to just introduce a query (returning
+            // `Result<(), ErrorReported>`) for the check that `rustc_typeck`
+            // performs (i.e. that the definition's type in the `impl` matches
+            // the declaration in the `trait`), so that we can cheaply check
+            // here if it failed, instead of approximating it.
+            if trait_item.kind == ty::AssocKind::Const
+                && trait_item.def_id != leaf_def.item.def_id
+                && leaf_def.item.def_id.is_local()
+            {
+                let normalized_type_of = |def_id, substs| {
+                    tcx.subst_and_normalize_erasing_regions(substs, param_env, tcx.type_of(def_id))
+                };
+
+                let original_ty = normalized_type_of(trait_item.def_id, rcvr_substs);
+                let resolved_ty = normalized_type_of(leaf_def.item.def_id, substs);
+
+                if original_ty != resolved_ty {
+                    let msg = format!(
+                        "Instance::resolve: inconsistent associated `const` type: \
+                         was `{}: {}` but resolved to `{}: {}`",
+                        tcx.def_path_str_with_substs(trait_item.def_id, rcvr_substs),
+                        original_ty,
+                        tcx.def_path_str_with_substs(leaf_def.item.def_id, substs),
+                        resolved_ty,
+                    );
+                    let span = tcx.def_span(leaf_def.item.def_id);
+                    tcx.sess.delay_span_bug(span, &msg);
+
+                    return Err(ErrorReported);
+                }
+            }
+
+            Some(ty::Instance::new(leaf_def.item.def_id, substs))
+        }
+        traits::ImplSource::Generator(generator_data) => Some(Instance {
+            def: ty::InstanceDef::Item(ty::WithOptConstParam::unknown(
+                generator_data.generator_def_id,
+            )),
+            substs: generator_data.substs,
+        }),
+        traits::ImplSource::Closure(closure_data) => {
+            let trait_closure_kind = tcx.fn_trait_kind_from_lang_item(trait_id).unwrap();
+            Some(Instance::resolve_closure(
+                tcx,
+                closure_data.closure_def_id,
+                closure_data.substs,
+                trait_closure_kind,
+            ))
+        }
+        traits::ImplSource::FnPointer(ref data) => match data.fn_ty.kind() {
+            ty::FnDef(..) | ty::FnPtr(..) => Some(Instance {
+                def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),
+                substs: rcvr_substs,
+            }),
+            _ => None,
+        },
+        traits::ImplSource::Object(ref data) => {
+            let index = traits::get_vtable_index_of_object_method(tcx, data, def_id);
+            Some(Instance { def: ty::InstanceDef::Virtual(def_id, index), substs: rcvr_substs })
+        }
+        traits::ImplSource::Builtin(..) => {
+            if Some(trait_ref.def_id) == tcx.lang_items().clone_trait() {
+                // FIXME(eddyb) use lang items for methods instead of names.
+                let name = tcx.item_name(def_id);
+                if name == sym::clone {
+                    let self_ty = trait_ref.self_ty();
+
+                    let is_copy = self_ty.is_copy_modulo_regions(tcx.at(DUMMY_SP), param_env);
+                    match self_ty.kind() {
+                        _ if is_copy => (),
+                        ty::Array(..) | ty::Closure(..) | ty::Tuple(..) => {}
+                        _ => return Ok(None),
+                    };
+
+                    Some(Instance {
+                        def: ty::InstanceDef::CloneShim(def_id, self_ty),
+                        substs: rcvr_substs,
+                    })
+                } else {
+                    assert_eq!(name, sym::clone_from);
+
+                    // Use the default `fn clone_from` from `trait Clone`.
+                    let substs = tcx.erase_regions(rcvr_substs);
+                    Some(ty::Instance::new(def_id, substs))
+                }
+            } else {
+                None
+            }
+        }
+        traits::ImplSource::AutoImpl(..)
+        | traits::ImplSource::Param(..)
+        | traits::ImplSource::TraitAlias(..)
+        | traits::ImplSource::DiscriminantKind(..) => None,
+    })
+}
+
+pub fn provide(providers: &mut ty::query::Providers) {
+    *providers =
+        ty::query::Providers { resolve_instance, resolve_instance_of_const_arg, ..*providers };
+}
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
new file mode 100644 (file)
index 0000000..904c006
--- /dev/null
@@ -0,0 +1,28 @@
+//! Various checks
+//!
+//! # Note
+//!
+//! This API is completely unstable and subject to change.
+
+#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(nll)]
+#![recursion_limit = "256"]
+
+#[macro_use]
+extern crate rustc_middle;
+#[macro_use]
+extern crate tracing;
+
+use rustc_middle::ty::query::Providers;
+
+mod common_traits;
+pub mod instance;
+mod needs_drop;
+mod ty;
+
+pub fn provide(providers: &mut Providers) {
+    common_traits::provide(providers);
+    needs_drop::provide(providers);
+    ty::provide(providers);
+    instance::provide(providers);
+}
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
new file mode 100644 (file)
index 0000000..d62fc76
--- /dev/null
@@ -0,0 +1,188 @@
+//! Check whether a type has (potentially) non-trivial drop glue.
+
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::def_id::DefId;
+use rustc_middle::ty::subst::Subst;
+use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop};
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_session::Limit;
+use rustc_span::DUMMY_SP;
+
+type NeedsDropResult<T> = Result<T, AlwaysRequiresDrop>;
+
+fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
+    let adt_fields =
+        move |adt_def: &ty::AdtDef| tcx.adt_drop_tys(adt_def.did).map(|tys| tys.iter());
+    // If we don't know a type doesn't need drop, for example if it's a type
+    // parameter without a `Copy` bound, then we conservatively return that it
+    // needs drop.
+    let res = NeedsDropTypes::new(tcx, query.param_env, query.value, adt_fields).next().is_some();
+    debug!("needs_drop_raw({:?}) = {:?}", query, res);
+    res
+}
+
+struct NeedsDropTypes<'tcx, F> {
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    query_ty: Ty<'tcx>,
+    seen_tys: FxHashSet<Ty<'tcx>>,
+    /// A stack of types left to process, and the recursion depth when we
+    /// pushed that type. Each round, we pop something from the stack and check
+    /// if it needs drop. If the result depends on whether some other types
+    /// need drop we push them onto the stack.
+    unchecked_tys: Vec<(Ty<'tcx>, usize)>,
+    recursion_limit: Limit,
+    adt_components: F,
+}
+
+impl<'tcx, F> NeedsDropTypes<'tcx, F> {
+    fn new(
+        tcx: TyCtxt<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        ty: Ty<'tcx>,
+        adt_components: F,
+    ) -> Self {
+        let mut seen_tys = FxHashSet::default();
+        seen_tys.insert(ty);
+        Self {
+            tcx,
+            param_env,
+            seen_tys,
+            query_ty: ty,
+            unchecked_tys: vec![(ty, 0)],
+            recursion_limit: tcx.sess.recursion_limit(),
+            adt_components,
+        }
+    }
+}
+
+impl<'tcx, F, I> Iterator for NeedsDropTypes<'tcx, F>
+where
+    F: Fn(&ty::AdtDef) -> NeedsDropResult<I>,
+    I: Iterator<Item = Ty<'tcx>>,
+{
+    type Item = NeedsDropResult<Ty<'tcx>>;
+
+    fn next(&mut self) -> Option<NeedsDropResult<Ty<'tcx>>> {
+        let tcx = self.tcx;
+
+        while let Some((ty, level)) = self.unchecked_tys.pop() {
+            if !self.recursion_limit.value_within_limit(level) {
+                // Not having a `Span` isn't great. But there's hopefully some other
+                // recursion limit error as well.
+                tcx.sess.span_err(
+                    DUMMY_SP,
+                    &format!("overflow while checking whether `{}` requires drop", self.query_ty),
+                );
+                return Some(Err(AlwaysRequiresDrop));
+            }
+
+            let components = match needs_drop_components(ty, &tcx.data_layout) {
+                Err(e) => return Some(Err(e)),
+                Ok(components) => components,
+            };
+            debug!("needs_drop_components({:?}) = {:?}", ty, components);
+
+            let queue_type = move |this: &mut Self, component: Ty<'tcx>| {
+                if this.seen_tys.insert(component) {
+                    this.unchecked_tys.push((component, level + 1));
+                }
+            };
+
+            for component in components {
+                match *component.kind() {
+                    _ if component.is_copy_modulo_regions(tcx.at(DUMMY_SP), self.param_env) => (),
+
+                    ty::Closure(_, substs) => {
+                        for upvar_ty in substs.as_closure().upvar_tys() {
+                            queue_type(self, upvar_ty);
+                        }
+                    }
+
+                    ty::Generator(def_id, substs, _) => {
+                        let substs = substs.as_generator();
+                        for upvar_ty in substs.upvar_tys() {
+                            queue_type(self, upvar_ty);
+                        }
+
+                        let witness = substs.witness();
+                        let interior_tys = match witness.kind() {
+                            &ty::GeneratorWitness(tys) => tcx.erase_late_bound_regions(tys),
+                            _ => {
+                                tcx.sess.delay_span_bug(
+                                    tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP),
+                                    &format!("unexpected generator witness type {:?}", witness),
+                                );
+                                return Some(Err(AlwaysRequiresDrop));
+                            }
+                        };
+
+                        for interior_ty in interior_tys {
+                            queue_type(self, interior_ty);
+                        }
+                    }
+
+                    // Check for a `Drop` impl and whether this is a union or
+                    // `ManuallyDrop`. If it's a struct or enum without a `Drop`
+                    // impl then check whether the field types need `Drop`.
+                    ty::Adt(adt_def, substs) => {
+                        let tys = match (self.adt_components)(adt_def) {
+                            Err(e) => return Some(Err(e)),
+                            Ok(tys) => tys,
+                        };
+                        for required_ty in tys {
+                            let subst_ty = tcx.normalize_erasing_regions(
+                                self.param_env,
+                                required_ty.subst(tcx, substs),
+                            );
+                            queue_type(self, subst_ty);
+                        }
+                    }
+                    ty::Array(..) | ty::Opaque(..) | ty::Projection(..) | ty::Param(_) => {
+                        if ty == component {
+                            // Return the type to the caller: they may be able
+                            // to normalize further than we can.
+                            return Some(Ok(component));
+                        } else {
+                            // Store the type for later. We can't return here
+                            // because we would then lose any other components
+                            // of the type.
+                            queue_type(self, component);
+                        }
+                    }
+                    _ => return Some(Err(AlwaysRequiresDrop)),
+                }
+            }
+        }
+
+        None
+    }
+}
+
+fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
+    let adt_components = move |adt_def: &ty::AdtDef| {
+        if adt_def.is_manually_drop() {
+            debug!("adt_drop_tys: `{:?}` is manually drop", adt_def);
+            return Ok(Vec::new().into_iter());
+        } else if adt_def.destructor(tcx).is_some() {
+            debug!("adt_drop_tys: `{:?}` implements `Drop`", adt_def);
+            return Err(AlwaysRequiresDrop);
+        } else if adt_def.is_union() {
+            debug!("adt_drop_tys: `{:?}` is a union", adt_def);
+            return Ok(Vec::new().into_iter());
+        }
+        Ok(adt_def.all_fields().map(|field| tcx.type_of(field.did)).collect::<Vec<_>>().into_iter())
+    };
+
+    let adt_ty = tcx.type_of(def_id);
+    let param_env = tcx.param_env(def_id);
+    let res: Result<Vec<_>, _> =
+        NeedsDropTypes::new(tcx, param_env, adt_ty, adt_components).collect();
+
+    debug!("adt_drop_tys(`{}`) = `{:?}`", tcx.def_path_str(def_id), res);
+    res.map(|components| tcx.intern_type_list(&components))
+}
+
+pub(crate) fn provide(providers: &mut ty::query::Providers) {
+    *providers = ty::query::Providers { needs_drop_raw, adt_drop_tys, ..*providers };
+}
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
new file mode 100644 (file)
index 0000000..aa1de6d
--- /dev/null
@@ -0,0 +1,505 @@
+use rustc_data_structures::fx::FxIndexSet;
+use rustc_data_structures::svh::Svh;
+use rustc_hir as hir;
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
+use rustc_middle::hir::map as hir_map;
+use rustc_middle::ty::subst::Subst;
+use rustc_middle::ty::{
+    self, Binder, Predicate, PredicateAtom, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness,
+};
+use rustc_session::CrateDisambiguator;
+use rustc_span::symbol::Symbol;
+use rustc_span::Span;
+use rustc_trait_selection::traits;
+
+fn sized_constraint_for_ty<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    adtdef: &ty::AdtDef,
+    ty: Ty<'tcx>,
+) -> Vec<Ty<'tcx>> {
+    use ty::TyKind::*;
+
+    let result = match ty.kind() {
+        Bool | Char | Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..)
+        | FnPtr(_) | Array(..) | Closure(..) | Generator(..) | Never => vec![],
+
+        Str | Dynamic(..) | Slice(_) | Foreign(..) | Error(_) | GeneratorWitness(..) => {
+            // these are never sized - return the target type
+            vec![ty]
+        }
+
+        Tuple(ref tys) => match tys.last() {
+            None => vec![],
+            Some(ty) => sized_constraint_for_ty(tcx, adtdef, ty.expect_ty()),
+        },
+
+        Adt(adt, substs) => {
+            // recursive case
+            let adt_tys = adt.sized_constraint(tcx);
+            debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_tys);
+            adt_tys
+                .iter()
+                .map(|ty| ty.subst(tcx, substs))
+                .flat_map(|ty| sized_constraint_for_ty(tcx, adtdef, ty))
+                .collect()
+        }
+
+        Projection(..) | Opaque(..) => {
+            // must calculate explicitly.
+            // FIXME: consider special-casing always-Sized projections
+            vec![ty]
+        }
+
+        Param(..) => {
+            // perf hack: if there is a `T: Sized` bound, then
+            // we know that `T` is Sized and do not need to check
+            // it on the impl.
+
+            let sized_trait = match tcx.lang_items().sized_trait() {
+                Some(x) => x,
+                _ => return vec![ty],
+            };
+            let sized_predicate = ty::Binder::dummy(ty::TraitRef {
+                def_id: sized_trait,
+                substs: tcx.mk_substs_trait(ty, &[]),
+            })
+            .without_const()
+            .to_predicate(tcx);
+            let predicates = tcx.predicates_of(adtdef.did).predicates;
+            if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] }
+        }
+
+        Placeholder(..) | Bound(..) | Infer(..) => {
+            bug!("unexpected type `{:?}` in sized_constraint_for_ty", ty)
+        }
+    };
+    debug!("sized_constraint_for_ty({:?}) = {:?}", ty, result);
+    result
+}
+
+fn associated_item_from_trait_item_ref(
+    tcx: TyCtxt<'_>,
+    parent_def_id: LocalDefId,
+    trait_item_ref: &hir::TraitItemRef,
+) -> ty::AssocItem {
+    let def_id = tcx.hir().local_def_id(trait_item_ref.id.hir_id);
+    let (kind, has_self) = match trait_item_ref.kind {
+        hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
+        hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
+        hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
+    };
+
+    ty::AssocItem {
+        ident: trait_item_ref.ident,
+        kind,
+        vis: tcx.visibility(def_id),
+        defaultness: trait_item_ref.defaultness,
+        def_id: def_id.to_def_id(),
+        container: ty::TraitContainer(parent_def_id.to_def_id()),
+        fn_has_self_parameter: has_self,
+    }
+}
+
+fn associated_item_from_impl_item_ref(
+    tcx: TyCtxt<'_>,
+    parent_def_id: LocalDefId,
+    impl_item_ref: &hir::ImplItemRef<'_>,
+) -> ty::AssocItem {
+    let def_id = tcx.hir().local_def_id(impl_item_ref.id.hir_id);
+    let (kind, has_self) = match impl_item_ref.kind {
+        hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
+        hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
+        hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
+    };
+
+    ty::AssocItem {
+        ident: impl_item_ref.ident,
+        kind,
+        vis: tcx.visibility(def_id),
+        defaultness: impl_item_ref.defaultness,
+        def_id: def_id.to_def_id(),
+        container: ty::ImplContainer(parent_def_id.to_def_id()),
+        fn_has_self_parameter: has_self,
+    }
+}
+
+fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
+    let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+    let parent_id = tcx.hir().get_parent_item(id);
+    let parent_def_id = tcx.hir().local_def_id(parent_id);
+    let parent_item = tcx.hir().expect_item(parent_id);
+    match parent_item.kind {
+        hir::ItemKind::Impl { ref items, .. } => {
+            if let Some(impl_item_ref) = items.iter().find(|i| i.id.hir_id == id) {
+                let assoc_item =
+                    associated_item_from_impl_item_ref(tcx, parent_def_id, impl_item_ref);
+                debug_assert_eq!(assoc_item.def_id, def_id);
+                return assoc_item;
+            }
+        }
+
+        hir::ItemKind::Trait(.., ref trait_item_refs) => {
+            if let Some(trait_item_ref) = trait_item_refs.iter().find(|i| i.id.hir_id == id) {
+                let assoc_item =
+                    associated_item_from_trait_item_ref(tcx, parent_def_id, trait_item_ref);
+                debug_assert_eq!(assoc_item.def_id, def_id);
+                return assoc_item;
+            }
+        }
+
+        _ => {}
+    }
+
+    span_bug!(
+        parent_item.span,
+        "unexpected parent of trait or impl item or item not found: {:?}",
+        parent_item.kind
+    )
+}
+
+fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness {
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+    let item = tcx.hir().expect_item(hir_id);
+    if let hir::ItemKind::Impl { defaultness, .. } = item.kind {
+        defaultness
+    } else {
+        bug!("`impl_defaultness` called on {:?}", item);
+    }
+}
+
+/// Calculates the `Sized` constraint.
+///
+/// In fact, there are only a few options for the types in the constraint:
+///     - an obviously-unsized type
+///     - a type parameter or projection whose Sizedness can't be known
+///     - a tuple of type parameters or projections, if there are multiple
+///       such.
+///     - a Error, if a type contained itself. The representability
+///       check should catch this case.
+fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtSizedConstraint<'_> {
+    let def = tcx.adt_def(def_id);
+
+    let result = tcx.mk_type_list(
+        def.variants
+            .iter()
+            .flat_map(|v| v.fields.last())
+            .flat_map(|f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did))),
+    );
+
+    debug!("adt_sized_constraint: {:?} => {:?}", def, result);
+
+    ty::AdtSizedConstraint(result)
+}
+
+fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
+    let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+    let item = tcx.hir().expect_item(id);
+    match item.kind {
+        hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter(
+            trait_item_refs
+                .iter()
+                .map(|trait_item_ref| trait_item_ref.id)
+                .map(|id| tcx.hir().local_def_id(id.hir_id).to_def_id()),
+        ),
+        hir::ItemKind::Impl { ref items, .. } => tcx.arena.alloc_from_iter(
+            items
+                .iter()
+                .map(|impl_item_ref| impl_item_ref.id)
+                .map(|id| tcx.hir().local_def_id(id.hir_id).to_def_id()),
+        ),
+        hir::ItemKind::TraitAlias(..) => &[],
+        _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
+    }
+}
+
+fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssociatedItems<'_> {
+    let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did));
+    ty::AssociatedItems::new(items)
+}
+
+fn def_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span {
+    tcx.hir().span_if_local(def_id).unwrap()
+}
+
+/// If the given `DefId` describes an item belonging to a trait,
+/// returns the `DefId` of the trait that the trait item belongs to;
+/// otherwise, returns `None`.
+fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
+    tcx.opt_associated_item(def_id).and_then(|associated_item| match associated_item.container {
+        ty::TraitContainer(def_id) => Some(def_id),
+        ty::ImplContainer(_) => None,
+    })
+}
+
+/// See `ParamEnv` struct definition for details.
+fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
+    // The param_env of an impl Trait type is its defining function's param_env
+    if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
+        return param_env(tcx, parent);
+    }
+    // Compute the bounds on Self and the type parameters.
+
+    let ty::InstantiatedPredicates { mut predicates, .. } =
+        tcx.predicates_of(def_id).instantiate_identity(tcx);
+
+    // Finally, we have to normalize the bounds in the environment, in
+    // case they contain any associated type projections. This process
+    // can yield errors if the put in illegal associated types, like
+    // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We
+    // report these errors right here; this doesn't actually feel
+    // right to me, because constructing the environment feels like a
+    // kind of a "idempotent" action, but I'm not sure where would be
+    // a better place. In practice, we construct environments for
+    // every fn once during type checking, and we'll abort if there
+    // are any errors at that point, so after type checking you can be
+    // sure that this will succeed without errors anyway.
+
+    if tcx.sess.opts.debugging_opts.chalk {
+        let environment = well_formed_types_in_env(tcx, def_id);
+        predicates.extend(environment);
+    }
+
+    let unnormalized_env =
+        ty::ParamEnv::new(tcx.intern_predicates(&predicates), traits::Reveal::UserFacing);
+
+    let body_id = def_id
+        .as_local()
+        .map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
+        .map_or(hir::CRATE_HIR_ID, |id| {
+            tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id)
+        });
+    let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
+    traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
+}
+
+/// Elaborate the environment.
+///
+/// Collect a list of `Predicate`'s used for building the `ParamEnv`. Adds `TypeWellFormedFromEnv`'s
+/// that are assumed to be well-formed (because they come from the environment).
+///
+/// Used only in chalk mode.
+fn well_formed_types_in_env<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: DefId,
+) -> &'tcx ty::List<Predicate<'tcx>> {
+    use rustc_hir::{ForeignItemKind, ImplItemKind, ItemKind, Node, TraitItemKind};
+    use rustc_middle::ty::subst::GenericArgKind;
+
+    debug!("environment(def_id = {:?})", def_id);
+
+    // The environment of an impl Trait type is its defining function's environment.
+    if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
+        return well_formed_types_in_env(tcx, parent);
+    }
+
+    // Compute the bounds on `Self` and the type parameters.
+    let ty::InstantiatedPredicates { predicates, .. } =
+        tcx.predicates_of(def_id).instantiate_identity(tcx);
+
+    let clauses = predicates.into_iter();
+
+    if !def_id.is_local() {
+        return ty::List::empty();
+    }
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+    let node = tcx.hir().get(hir_id);
+
+    enum NodeKind {
+        TraitImpl,
+        InherentImpl,
+        Fn,
+        Other,
+    }
+
+    let node_kind = match node {
+        Node::TraitItem(item) => match item.kind {
+            TraitItemKind::Fn(..) => NodeKind::Fn,
+            _ => NodeKind::Other,
+        },
+
+        Node::ImplItem(item) => match item.kind {
+            ImplItemKind::Fn(..) => NodeKind::Fn,
+            _ => NodeKind::Other,
+        },
+
+        Node::Item(item) => match item.kind {
+            ItemKind::Impl { of_trait: Some(_), .. } => NodeKind::TraitImpl,
+            ItemKind::Impl { of_trait: None, .. } => NodeKind::InherentImpl,
+            ItemKind::Fn(..) => NodeKind::Fn,
+            _ => NodeKind::Other,
+        },
+
+        Node::ForeignItem(item) => match item.kind {
+            ForeignItemKind::Fn(..) => NodeKind::Fn,
+            _ => NodeKind::Other,
+        },
+
+        // FIXME: closures?
+        _ => NodeKind::Other,
+    };
+
+    // FIXME(eddyb) isn't the unordered nature of this a hazard?
+    let mut inputs = FxIndexSet::default();
+
+    match node_kind {
+        // In a trait impl, we assume that the header trait ref and all its
+        // constituents are well-formed.
+        NodeKind::TraitImpl => {
+            let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl");
+
+            // FIXME(chalk): this has problems because of late-bound regions
+            //inputs.extend(trait_ref.substs.iter().flat_map(|arg| arg.walk()));
+            inputs.extend(trait_ref.substs.iter());
+        }
+
+        // In an inherent impl, we assume that the receiver type and all its
+        // constituents are well-formed.
+        NodeKind::InherentImpl => {
+            let self_ty = tcx.type_of(def_id);
+            inputs.extend(self_ty.walk());
+        }
+
+        // In an fn, we assume that the arguments and all their constituents are
+        // well-formed.
+        NodeKind::Fn => {
+            let fn_sig = tcx.fn_sig(def_id);
+            let fn_sig = tcx.liberate_late_bound_regions(def_id, fn_sig);
+
+            inputs.extend(fn_sig.inputs().iter().flat_map(|ty| ty.walk()));
+        }
+
+        NodeKind::Other => (),
+    }
+    let input_clauses = inputs.into_iter().filter_map(|arg| {
+        match arg.unpack() {
+            GenericArgKind::Type(ty) => {
+                let binder = Binder::dummy(PredicateAtom::TypeWellFormedFromEnv(ty));
+                Some(tcx.mk_predicate(PredicateKind::ForAll(binder)))
+            }
+
+            // FIXME(eddyb) no WF conditions from lifetimes?
+            GenericArgKind::Lifetime(_) => None,
+
+            // FIXME(eddyb) support const generics in Chalk
+            GenericArgKind::Const(_) => None,
+        }
+    });
+
+    tcx.mk_predicates(clauses.chain(input_clauses))
+}
+
+fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
+    tcx.param_env(def_id).with_reveal_all_normalized(tcx)
+}
+
+fn crate_disambiguator(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateDisambiguator {
+    assert_eq!(crate_num, LOCAL_CRATE);
+    tcx.sess.local_crate_disambiguator()
+}
+
+fn original_crate_name(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Symbol {
+    assert_eq!(crate_num, LOCAL_CRATE);
+    tcx.crate_name
+}
+
+fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
+    tcx.index_hir(crate_num).crate_hash
+}
+
+fn instance_def_size_estimate<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    instance_def: ty::InstanceDef<'tcx>,
+) -> usize {
+    use ty::InstanceDef;
+
+    match instance_def {
+        InstanceDef::Item(..) | InstanceDef::DropGlue(..) => {
+            let mir = tcx.instance_mir(instance_def);
+            mir.basic_blocks().iter().map(|bb| bb.statements.len()).sum()
+        }
+        // Estimate the size of other compiler-generated shims to be 1.
+        _ => 1,
+    }
+}
+
+/// If `def_id` is an issue 33140 hack impl, returns its self type; otherwise, returns `None`.
+///
+/// See [`ty::ImplOverlapKind::Issue33140`] for more details.
+fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
+    debug!("issue33140_self_ty({:?})", def_id);
+
+    let trait_ref = tcx
+        .impl_trait_ref(def_id)
+        .unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id));
+
+    debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref);
+
+    let is_marker_like = tcx.impl_polarity(def_id) == ty::ImplPolarity::Positive
+        && tcx.associated_item_def_ids(trait_ref.def_id).is_empty();
+
+    // Check whether these impls would be ok for a marker trait.
+    if !is_marker_like {
+        debug!("issue33140_self_ty - not marker-like!");
+        return None;
+    }
+
+    // impl must be `impl Trait for dyn Marker1 + Marker2 + ...`
+    if trait_ref.substs.len() != 1 {
+        debug!("issue33140_self_ty - impl has substs!");
+        return None;
+    }
+
+    let predicates = tcx.predicates_of(def_id);
+    if predicates.parent.is_some() || !predicates.predicates.is_empty() {
+        debug!("issue33140_self_ty - impl has predicates {:?}!", predicates);
+        return None;
+    }
+
+    let self_ty = trait_ref.self_ty();
+    let self_ty_matches = match self_ty.kind() {
+        ty::Dynamic(ref data, ty::ReStatic) => data.principal().is_none(),
+        _ => false,
+    };
+
+    if self_ty_matches {
+        debug!("issue33140_self_ty - MATCHES!");
+        Some(self_ty)
+    } else {
+        debug!("issue33140_self_ty - non-matching self type");
+        None
+    }
+}
+
+/// Check if a function is async.
+fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+
+    let node = tcx.hir().get(hir_id);
+
+    let fn_like = hir_map::blocks::FnLikeNode::from_node(node).unwrap_or_else(|| {
+        bug!("asyncness: expected fn-like node but got `{:?}`", def_id);
+    });
+
+    fn_like.asyncness()
+}
+
+pub fn provide(providers: &mut ty::query::Providers) {
+    *providers = ty::query::Providers {
+        asyncness,
+        associated_item,
+        associated_item_def_ids,
+        associated_items,
+        adt_sized_constraint,
+        def_span,
+        param_env,
+        param_env_reveal_all_normalized,
+        trait_of_item,
+        crate_disambiguator,
+        original_crate_name,
+        crate_hash,
+        instance_def_size_estimate,
+        issue33140_self_ty,
+        impl_defaultness,
+        ..*providers
+    };
+}
index 685243f54cb903b35069fac7c876255b0a404caf..b04acd9660d4572baa9747fa789ae9813d21e505 100644 (file)
@@ -1,11 +1,11 @@
 use crate::astconv::AstConv;
-use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{pluralize, struct_span_err, Applicability};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty;
 use rustc_session::parse::feature_err;
+use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::{Span, DUMMY_SP};
 
@@ -180,7 +180,7 @@ pub(crate) fn complain_about_assoc_type_not_found<I>(
             .collect();
 
         if let (Some(suggested_name), true) = (
-            find_best_match_for_name(all_candidate_names.iter(), assoc_name.name, None),
+            find_best_match_for_name(&all_candidate_names, assoc_name.name, None),
             assoc_name.span != DUMMY_SP,
         ) {
             err.span_suggestion(
index 89c5adfa14c670a0c9e1749af59203518186de4f..2f64597a510f090367505aa9303db3a47a3673d4 100644 (file)
@@ -13,7 +13,6 @@
 };
 use crate::middle::resolve_lifetime as rl;
 use crate::require_c_abi_if_c_variadic;
-use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{struct_span_err, Applicability, ErrorReported, FatalError};
 use rustc_hir as hir;
@@ -26,6 +25,7 @@
 use rustc_middle::ty::GenericParamDefKind;
 use rustc_middle::ty::{self, Const, DefIdTree, Ty, TyCtxt, TypeFoldable};
 use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
+use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::spec::abi;
@@ -337,6 +337,14 @@ fn create_substs_for_ast_path<'a>(
             infer_args,
         );
 
+        // Skip processing if type has no generic parameters.
+        // Traits always have `Self` as a generic parameter, which means they will not return early
+        // here and so associated type bindings will be handled regardless of whether there are any
+        // non-`Self` generic parameters.
+        if generic_params.params.len() == 0 {
+            return (tcx.intern_substs(&[]), vec![], arg_count);
+        }
+
         let is_object = self_ty.map_or(false, |ty| ty == self.tcx().types.trait_object_dummy_self);
 
         struct SubstsForAstPathCtxt<'a, 'tcx> {
@@ -1364,7 +1372,9 @@ fn find_bound_for_assoc_item(
             || {
                 traits::transitive_bounds(
                     tcx,
-                    predicates.iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref()),
+                    predicates.iter().filter_map(|(p, _)| {
+                        p.to_opt_poly_trait_ref().map(|trait_ref| trait_ref.value)
+                    }),
                 )
             },
             || param_name.to_string(),
@@ -1577,7 +1587,11 @@ pub fn associated_path_to_ty(
 
                     let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT");
                     if let Some(suggested_name) = find_best_match_for_name(
-                        adt_def.variants.iter().map(|variant| &variant.ident.name),
+                        &adt_def
+                            .variants
+                            .iter()
+                            .map(|variant| variant.ident.name)
+                            .collect::<Vec<Symbol>>(),
                         assoc_ident.name,
                         None,
                     ) {
index 1220c313932bf0c45bfaa7da06e62eb2645c2b64..55c815b21ad206a13d9b27910d80275890dd5a50 100644 (file)
@@ -94,6 +94,37 @@ pub(super) fn check_fn<'a, 'tcx>(
 
     fn_maybe_err(tcx, span, fn_sig.abi);
 
+    if fn_sig.abi == Abi::RustCall {
+        let expected_args = if let ImplicitSelfKind::None = decl.implicit_self { 1 } else { 2 };
+
+        let err = || {
+            let item = match tcx.hir().get(fn_id) {
+                Node::Item(hir::Item { kind: ItemKind::Fn(header, ..), .. }) => Some(header),
+                Node::ImplItem(hir::ImplItem {
+                    kind: hir::ImplItemKind::Fn(header, ..), ..
+                }) => Some(header),
+                // Closures are RustCall, but they tuple their arguments, so shouldn't be checked
+                Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => None,
+                node => bug!("Item being checked wasn't a function/closure: {:?}", node),
+            };
+
+            if let Some(header) = item {
+                tcx.sess.span_err(header.span, "A function with the \"rust-call\" ABI must take a single non-self argument that is a tuple")
+            }
+        };
+
+        if fn_sig.inputs().len() != expected_args {
+            err()
+        } else {
+            // FIXME(CraftSpider) Add a check on parameter expansion, so we don't just make the ICE happen later on
+            //   This will probably require wide-scale changes to support a TupleKind obligation
+            //   We can't resolve this without knowing the type of the param
+            if !matches!(fn_sig.inputs()[expected_args - 1].kind(), ty::Tuple(_) | ty::Param(_)) {
+                err()
+            }
+        }
+    }
+
     if body.generator_kind.is_some() && can_be_generator.is_some() {
         let yield_ty = fcx
             .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
@@ -446,7 +477,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
     struct ProhibitOpaqueVisitor<'tcx> {
         opaque_identity_ty: Ty<'tcx>,
         generics: &'tcx ty::Generics,
-    };
+    }
 
     impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {
         type BreakTy = Option<Ty<'tcx>>;
@@ -715,20 +746,22 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
             let generics = tcx.generics_of(def_id);
             check_type_params_are_used(tcx, &generics, pty_ty);
         }
-        hir::ItemKind::ForeignMod(ref m) => {
-            check_abi(tcx, it.span, m.abi);
+        hir::ItemKind::ForeignMod { abi, items } => {
+            check_abi(tcx, it.span, abi);
 
-            if m.abi == Abi::RustIntrinsic {
-                for item in m.items {
+            if abi == Abi::RustIntrinsic {
+                for item in items {
+                    let item = tcx.hir().foreign_item(item.id);
                     intrinsic::check_intrinsic_type(tcx, item);
                 }
-            } else if m.abi == Abi::PlatformIntrinsic {
-                for item in m.items {
+            } else if abi == Abi::PlatformIntrinsic {
+                for item in items {
+                    let item = tcx.hir().foreign_item(item.id);
                     intrinsic::check_platform_intrinsic_type(tcx, item);
                 }
             } else {
-                for item in m.items {
-                    let def_id = tcx.hir().local_def_id(item.hir_id);
+                for item in items {
+                    let def_id = tcx.hir().local_def_id(item.id.hir_id);
                     let generics = tcx.generics_of(def_id);
                     let own_counts = generics.own_counts();
                     if generics.params.len() - own_counts.lifetimes != 0 {
@@ -760,9 +793,10 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
                         .emit();
                     }
 
+                    let item = tcx.hir().foreign_item(item.id);
                     match item.kind {
                         hir::ForeignItemKind::Fn(ref fn_decl, _, _) => {
-                            require_c_abi_if_c_variadic(tcx, fn_decl, m.abi, item.span);
+                            require_c_abi_if_c_variadic(tcx, fn_decl, abi, item.span);
                         }
                         hir::ForeignItemKind::Static(..) => {
                             check_static_inhabited(tcx, def_id, item.span);
index 241803fab1e68b7b8b994057b45fa3386bd6cae5..d12d2cb59a5a9e7dc076252ca586b564d835c8c2 100644 (file)
@@ -810,10 +810,12 @@ pub fn check_for_cast(
                 // can be given the suggestion "u32::from(x) > y" rather than
                 // "x > y.try_into().unwrap()".
                 let lhs_expr_and_src = expected_ty_expr.and_then(|expr| {
-                    match self.tcx.sess.source_map().span_to_snippet(expr.span).ok() {
-                        Some(src) => Some((expr, src)),
-                        None => None,
-                    }
+                    self.tcx
+                        .sess
+                        .source_map()
+                        .span_to_snippet(expr.span)
+                        .ok()
+                        .map(|src| (expr, src))
                 });
                 let (span, msg, suggestion) = if let (Some((lhs_expr, lhs_src)), false) =
                     (lhs_expr_and_src, exp_to_found_is_fallible)
index f7f9e607a74412bbc2b04f12e5fd445700e75e71..26962d2222d32f592c87264183e5e9c8372cc855 100644 (file)
@@ -22,7 +22,6 @@
 
 use crate::errors::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive};
 use rustc_ast as ast;
-use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::ErrorReported;
@@ -40,6 +39,7 @@
 use rustc_middle::ty::TypeFoldable;
 use rustc_middle::ty::{AdtKind, Visibility};
 use rustc_span::hygiene::DesugaringKind;
+use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::source_map::Span;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_trait_selection::traits::{self, ObligationCauseCode};
@@ -1441,18 +1441,22 @@ fn suggest_field_name(
         field: Symbol,
         skip: Vec<Symbol>,
     ) -> Option<Symbol> {
-        let names = variant.fields.iter().filter_map(|field| {
-            // ignore already set fields and private fields from non-local crates
-            if skip.iter().any(|&x| x == field.ident.name)
-                || (!variant.def_id.is_local() && field.vis != Visibility::Public)
-            {
-                None
-            } else {
-                Some(&field.ident.name)
-            }
-        });
+        let names = variant
+            .fields
+            .iter()
+            .filter_map(|field| {
+                // ignore already set fields and private fields from non-local crates
+                if skip.iter().any(|&x| x == field.ident.name)
+                    || (!variant.def_id.is_local() && field.vis != Visibility::Public)
+                {
+                    None
+                } else {
+                    Some(field.ident.name)
+                }
+            })
+            .collect::<Vec<Symbol>>();
 
-        find_best_match_for_name(names, field, None)
+        find_best_match_for_name(&names, field, None)
     }
 
     fn available_field_names(&self, variant: &'tcx ty::VariantDef) -> Vec<Symbol> {
index 478f8a16169edb6d192e4a029d7275b2966acece..39a79893b6441c603f70a78a83a608e943505ef7 100644 (file)
@@ -9,7 +9,6 @@
 use crate::hir::def_id::DefId;
 
 use rustc_ast as ast;
-use rustc_ast::util::lev_distance::{find_best_match_for_name, lev_distance};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
 use rustc_hir as hir;
@@ -27,6 +26,7 @@
 };
 use rustc_session::lint;
 use rustc_span::def_id::LocalDefId;
+use rustc_span::lev_distance::{find_best_match_for_name, lev_distance};
 use rustc_span::{symbol::Ident, Span, Symbol, DUMMY_SP};
 use rustc_trait_selection::autoderef::{self, Autoderef};
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
@@ -1538,8 +1538,11 @@ fn probe_for_lev_candidate(&mut self) -> Result<Option<ty::AssocItem>, MethodErr
                 Ok(None)
             } else {
                 let best_name = {
-                    let names = applicable_close_candidates.iter().map(|cand| &cand.ident.name);
-                    find_best_match_for_name(names, self.method_name.unwrap().name, None)
+                    let names = applicable_close_candidates
+                        .iter()
+                        .map(|cand| cand.ident.name)
+                        .collect::<Vec<Symbol>>();
+                    find_best_match_for_name(&names, self.method_name.unwrap().name, None)
                 }
                 .unwrap();
                 Ok(applicable_close_candidates
index 3d5ce57a491c5717e1249aea535ead859d6c5827..7ed2933c08bbf6cb56a192ec2fc4785e55068119 100644 (file)
@@ -2,7 +2,6 @@
 //! found or is otherwise invalid.
 
 use crate::check::FnCtxt;
-use rustc_ast::util::lev_distance;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
@@ -17,6 +16,7 @@
 use rustc_middle::ty::{
     self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
 };
+use rustc_span::lev_distance;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{source_map, FileName, Span};
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
@@ -744,7 +744,7 @@ trait bound{s}",
                 if actual.is_enum() {
                     let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
                     if let Some(suggestion) = lev_distance::find_best_match_for_name(
-                        adt_def.variants.iter().map(|s| &s.ident.name),
+                        &adt_def.variants.iter().map(|s| s.ident.name).collect::<Vec<_>>(),
                         item_name.name,
                         None,
                     ) {
@@ -1308,6 +1308,8 @@ fn visit_item(&mut self, i: &'v hir::Item<'v>) {
         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<'_>) {}
     }
 
     tcx.hir().krate().visit_all_item_likes(&mut Visitor { map: &tcx.hir(), traits: &mut traits });
index b242900a1221f69a43c02d587ab533af1a38b899..d27a68ccf1bda52fda474d2ce5841b315f50f082 100644 (file)
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_hir::{HirIdMap, Node};
+use rustc_hir::{HirIdMap, ImplicitSelfKind, Node};
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::Idx;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -1134,6 +1134,7 @@ fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
     }
     fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) {}
     fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {}
+    fn visit_foreign_item(&mut self, _: &'tcx hir::ForeignItem<'tcx>) {}
 }
 
 fn typeck_item_bodies(tcx: TyCtxt<'_>, crate_num: CrateNum) {
index a729912126e4f0d3462d59f6bd3cc5751b06a0d5..bcb73e1b4e74e9a4bf11fdd185d2fe7df759b623 100644 (file)
@@ -1,7 +1,6 @@
 use crate::check::FnCtxt;
 use rustc_ast as ast;
 
-use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
@@ -13,6 +12,7 @@
 use rustc_middle::ty::subst::GenericArg;
 use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeFoldable};
 use rustc_span::hygiene::DesugaringKind;
+use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::source_map::{Span, Spanned};
 use rustc_span::symbol::Ident;
 use rustc_trait_selection::traits::{ObligationCause, Pattern};
@@ -1302,8 +1302,9 @@ fn error_inexistent_fields(
                 ),
             );
             if plural == "" {
-                let input = unmentioned_fields.iter().map(|(_, field)| &field.name);
-                let suggested_name = find_best_match_for_name(input, ident.name, None);
+                let input =
+                    unmentioned_fields.iter().map(|(_, field)| field.name).collect::<Vec<_>>();
+                let suggested_name = find_best_match_for_name(&input, ident.name, None);
                 if let Some(suggested_name) = suggested_name {
                     err.span_suggestion(
                         ident.span,
index 5dffe5107b58123ddd29741ae6c8c8a072d497aa..c09f8cce5b44de9d8eb3bae178c27fb6ed9848fc 100644 (file)
@@ -156,8 +156,9 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         hir::ItemKind::Const(ref ty, ..) => {
             check_item_type(tcx, item.hir_id, ty.span, false);
         }
-        hir::ItemKind::ForeignMod(ref module) => {
-            for it in module.items.iter() {
+        hir::ItemKind::ForeignMod { items, .. } => {
+            for it in items.iter() {
+                let it = tcx.hir().foreign_item(it.id);
                 match it.kind {
                     hir::ForeignItemKind::Fn(ref decl, ..) => {
                         check_item_fn(tcx, it.hir_id, it.ident, it.span, decl)
@@ -329,7 +330,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
                             ),
                         )
                         .note("the only supported types are integers, `bool` and `char`")
-                        .note("more complex types are supported with `#[feature(const_generics)]`")
+                        .help("more complex types are supported with `#[feature(const_generics)]`")
                         .emit()
                 }
             };
@@ -1345,6 +1346,10 @@ fn visit_trait_item(&self, trait_item: &'tcx hir::TraitItem<'tcx>) {
     fn visit_impl_item(&self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         Visitor::visit_impl_item(&mut self.clone(), impl_item);
     }
+
+    fn visit_foreign_item(&self, foreign_item: &'tcx hir::ForeignItem<'tcx>) {
+        Visitor::visit_foreign_item(&mut self.clone(), foreign_item)
+    }
 }
 
 impl Visitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> {
index 335f2cc2716c75c392e0de6fe5fd4cf70ef89c31..d1ada123c0d5adcef36676c7b1bbeefbe4ad7386 100644 (file)
@@ -194,7 +194,9 @@ fn fix_index_builtin_expr(&mut self, e: &hir::Expr<'_>) {
             let mut typeck_results = self.fcx.typeck_results.borrow_mut();
 
             // All valid indexing looks like this; might encounter non-valid indexes at this point.
-            let base_ty = typeck_results.expr_ty_adjusted_opt(&base).map(|t| t.kind());
+            let base_ty = typeck_results
+                .expr_ty_adjusted_opt(&base)
+                .map(|t| self.fcx.resolve_vars_if_possible(t).kind());
             if base_ty.is_none() {
                 // When encountering `return [0][0]` outside of a `fn` body we can encounter a base
                 // that isn't in the type table. We assume more relevant errors have already been
index 4fda8932e213b0d294e1712dc94587b123eb2d23..31121ece898aa7e02695120e2d0b7031af59991a 100644 (file)
@@ -35,6 +35,8 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
     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<'_>) {}
 }
 
 struct CheckVisitor<'tcx> {
@@ -225,4 +227,6 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
     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 373acb95c9e37896dc13cb6719337ecb6d2725df..483ab2f58f222f51f608a3ec6ad3cc2df55fa106 100644 (file)
@@ -334,6 +334,8 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
     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<'_>) {}
 }
 
 impl InherentCollect<'tcx> {
index ce157f809ef875019f4eb113903830d07e3215aa..dd90724e93fee748f15dc94e3a49169ef8dffac5 100644 (file)
@@ -149,4 +149,6 @@ fn visit_item(&mut self, item: &'v hir::Item<'v>) {
     fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'v>) {}
 
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'v>) {}
+
+    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'v>) {}
 }
index b2009962aba2ec9b00d97300f22115b203d6214f..253dcf06e01de6b283e097dc7a62dcf8392609a3 100644 (file)
@@ -244,4 +244,6 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
     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 b281092ea631d45d60d351562474fc09d1b5520d..2d9128e7dc0b7ef637bfa46ac571744827ef8649 100644 (file)
@@ -94,4 +94,6 @@ fn visit_item(&mut self, item: &'v hir::Item<'v>) {
     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 dee0e6c2ebbefa4102ec6c7aa43ed4d800e4281b..0ff10abb60a357a5aff432be3631478bc1bca6cf 100644 (file)
@@ -646,8 +646,9 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) {
         | hir::ItemKind::Use(..)
         | hir::ItemKind::Mod(_)
         | hir::ItemKind::GlobalAsm(_) => {}
-        hir::ItemKind::ForeignMod(ref foreign_mod) => {
-            for item in foreign_mod.items {
+        hir::ItemKind::ForeignMod { items, .. } => {
+            for item in items {
+                let item = tcx.hir().foreign_item(item.id);
                 let def_id = tcx.hir().local_def_id(item.hir_id);
                 tcx.ensure().generics_of(def_id);
                 tcx.ensure().type_of(def_id);
index c4f4c8bc76b46a432917404aec7023ffa9cced05..88ba5788b05d191536865b4c5be74e33d1c5cff5 100644 (file)
@@ -259,7 +259,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                 ItemKind::Trait(..)
                 | ItemKind::TraitAlias(..)
                 | ItemKind::Mod(..)
-                | ItemKind::ForeignMod(..)
+                | ItemKind::ForeignMod { .. }
                 | ItemKind::GlobalAsm(..)
                 | ItemKind::ExternCrate(..)
                 | ItemKind::Use(..) => {
index 4901d6041d6f02bdc54e90b32e1b421eac9a7465..14daa97c2c587759393533bc278f2902b58ced53 100644 (file)
@@ -93,6 +93,8 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
     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>) {}
 }
 
 fn enforce_impl_params_are_constrained(
index e7a9e078a737f8efdc93d945b14c1c8db4d68696..3d0635e3fe4375039a4ea239032d0389a58df848 100644 (file)
@@ -109,6 +109,8 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
     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>) {}
 }
 
 fn insert_required_predicates_to_be_wf<'tcx>(
index abe9319d71c591438c5faa42a46949d6ba107468..56d42f756c4960a0f6255502e77bd57adc0b0b62 100644 (file)
@@ -26,4 +26,5 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
 
     fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) {}
     fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {}
+    fn visit_foreign_item(&mut self, _: &'tcx hir::ForeignItem<'tcx>) {}
 }
index b2b062e40951efc4683a504f253f3d2c2b18e55a..a8fbdfb7c651441a4654f1efba08708fed880f3a 100644 (file)
@@ -92,14 +92,6 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                 self.visit_node_helper(item.hir_id);
             }
 
-            hir::ItemKind::ForeignMod(ref foreign_mod) => {
-                for foreign_item in foreign_mod.items {
-                    if let hir::ForeignItemKind::Fn(..) = foreign_item.kind {
-                        self.visit_node_helper(foreign_item.hir_id);
-                    }
-                }
-            }
-
             _ => {}
         }
     }
@@ -115,6 +107,12 @@ fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
             self.visit_node_helper(impl_item.hir_id);
         }
     }
+
+    fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem<'_>) {
+        if let hir::ForeignItemKind::Fn(..) = foreign_item.kind {
+            self.visit_node_helper(foreign_item.hir_id);
+        }
+    }
 }
 
 impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
index 81c858c53cb8e4035a2a8143882fd7e231e91809..3b2a1c24ddd8d54d8ae58d5543fbff76e15f9f5e 100644 (file)
@@ -153,14 +153,6 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                 self.add_inferreds_for_item(item.hir_id);
             }
 
-            hir::ItemKind::ForeignMod(ref foreign_mod) => {
-                for foreign_item in foreign_mod.items {
-                    if let hir::ForeignItemKind::Fn(..) = foreign_item.kind {
-                        self.add_inferreds_for_item(foreign_item.hir_id);
-                    }
-                }
-            }
-
             _ => {}
         }
     }
@@ -176,4 +168,10 @@ fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
             self.add_inferreds_for_item(impl_item.hir_id);
         }
     }
+
+    fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem<'_>) {
+        if let hir::ForeignItemKind::Fn(..) = foreign_item.kind {
+            self.add_inferreds_for_item(foreign_item.hir_id);
+        }
+    }
 }
index 1aab89310c6e881ccc41eb096fb2051e7a63da8e..d6e43b6d66950c4f10b1b7e94e458a741685fc26 100644 (file)
@@ -26,4 +26,5 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
 
     fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) {}
     fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {}
+    fn visit_foreign_item(&mut self, _: &'tcx hir::ForeignItem<'tcx>) {}
 }
index c9e183887504c20605b749917fd0c50c27bb68b1..5b045d4e32d8d739ebbab49580d20affbdcd1cda 100644 (file)
@@ -446,6 +446,11 @@ changelog-seen = 2
 # nightly features
 #channel = "dev"
 
+# A descriptive string to be appended to `rustc --version` output, which is
+# also used in places like debuginfo `DW_AT_producer`. This may be useful for
+# supplementary build information, like distro-specific package versions.
+#description = ""
+
 # The root location of the musl installation directory.
 #musl-root = "..."
 
index 3427c83a18f2a36afc440b2f6c036d901e39765c..b1bfc2abe44ac5f917d4363394edf26a4359ed4a 100644 (file)
@@ -358,8 +358,9 @@ pub(crate) unsafe fn box_free<T: ?Sized, A: AllocRef>(ptr: Unique<T>, alloc: A)
 /// [`set_alloc_error_hook`]: ../../std/alloc/fn.set_alloc_error_hook.html
 /// [`take_alloc_error_hook`]: ../../std/alloc/fn.take_alloc_error_hook.html
 #[stable(feature = "global_alloc", since = "1.28.0")]
-#[cfg(not(any(test, bootstrap)))]
+#[cfg(not(test))]
 #[rustc_allocator_nounwind]
+#[cold]
 pub fn handle_alloc_error(layout: Layout) -> ! {
     unsafe {
         __rust_alloc_error_handler(layout.size(), layout.align());
@@ -370,22 +371,7 @@ pub fn handle_alloc_error(layout: Layout) -> ! {
 #[cfg(test)]
 pub use std::alloc::handle_alloc_error;
 
-// In stage0 (bootstrap) `__rust_alloc_error_handler`,
-// might not be generated yet, because an old compiler is used,
-// so use the old direct call.
-#[cfg(all(bootstrap, not(test)))]
-#[stable(feature = "global_alloc", since = "1.28.0")]
-#[doc(hidden)]
-#[rustc_allocator_nounwind]
-pub fn handle_alloc_error(layout: Layout) -> ! {
-    extern "Rust" {
-        #[lang = "oom"]
-        fn oom_impl(layout: Layout) -> !;
-    }
-    unsafe { oom_impl(layout) }
-}
-
-#[cfg(not(any(target_os = "hermit", test, bootstrap)))]
+#[cfg(not(any(target_os = "hermit", test)))]
 #[doc(hidden)]
 #[allow(unused_attributes)]
 #[unstable(feature = "alloc_internals", issue = "none")]
index 1512235da6a8198e089d375182a8dd20be846f7d..f56e3af4ff29d4221dfc31cd05519a070c32dcc8 100644 (file)
 //! T` obtained from [`Box::<T>::into_raw`] may be deallocated using the
 //! [`Global`] allocator with [`Layout::for_value(&*value)`].
 //!
+//! For zero-sized values, the `Box` pointer still has to be [valid] for reads
+//! and writes and sufficiently aligned. In particular, casting any aligned
+//! non-zero integer literal to a raw pointer produces a valid pointer, but a
+//! pointer pointing into previously allocated memory that since got freed is
+//! not valid. The recommended way to build a Box to a ZST if `Box::new` cannot
+//! be used is to use [`ptr::NonNull::dangling`].
+//!
 //! So long as `T: Sized`, a `Box<T>` is guaranteed to be represented
 //! as a single pointer and is also ABI-compatible with C pointers
 //! (i.e. the C type `T*`). This means that if you have extern "C"
 //! [`Global`]: crate::alloc::Global
 //! [`Layout`]: crate::alloc::Layout
 //! [`Layout::for_value(&*value)`]: crate::alloc::Layout::for_value
+//! [valid]: ptr#safety
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -530,7 +538,10 @@ impl<T: ?Sized> Box<T> {
     /// memory problems. For example, a double-free may occur if the
     /// function is called twice on the same raw pointer.
     ///
+    /// The safety conditions are described in the [memory layout] section.
+    ///
     /// # Examples
+    ///
     /// Recreate a `Box` which was previously converted to a raw pointer
     /// using [`Box::into_raw`]:
     /// ```
@@ -1336,9 +1347,10 @@ fn from_iter<T: IntoIterator<Item = I>>(iter: T) -> Self {
 }
 
 #[stable(feature = "box_slice_clone", since = "1.3.0")]
-impl<T: Clone> Clone for Box<[T]> {
+impl<T: Clone, A: AllocRef + Clone> Clone for Box<[T], A> {
     fn clone(&self) -> Self {
-        self.to_vec().into_boxed_slice()
+        let alloc = Box::alloc_ref(self).clone();
+        self.to_vec_in(alloc).into_boxed_slice()
     }
 
     fn clone_from(&mut self, other: &Self) {
index a4253a732c30f1404b91e3fe7f238dc813d3d1ec..bd99c4ed2f14e7e24bc21fd61efa22d7b6e7a3d2 100644 (file)
@@ -34,7 +34,7 @@ fn bulk_push<I>(&mut self, iter: I, length: &mut usize)
     where
         I: Iterator<Item = (K, V)>,
     {
-        let mut cur_node = self.node_as_mut().last_leaf_edge().into_node();
+        let mut cur_node = self.borrow_mut().last_leaf_edge().into_node();
         // Iterate through all key-value pairs, pushing them into nodes at the right level.
         for (key, value) in iter {
             // Try to push key-value pair into the current leaf node.
@@ -67,7 +67,7 @@ fn bulk_push<I>(&mut self, iter: I, length: &mut usize)
 
                 // Push key-value pair and new right subtree.
                 let tree_height = open_node.height() - 1;
-                let mut right_tree = Root::new_leaf();
+                let mut right_tree = Root::new();
                 for _ in 0..tree_height {
                     right_tree.push_internal_level();
                 }
@@ -86,7 +86,7 @@ fn bulk_push<I>(&mut self, iter: I, length: &mut usize)
 
     fn fix_right_edge(&mut self) {
         // Handle underfull nodes, start from the top.
-        let mut cur_node = self.node_as_mut();
+        let mut cur_node = self.borrow_mut();
         while let Internal(internal) = cur_node.force() {
             // Check if right-most child is underfull.
             let mut last_kv = internal.last_kv().consider_for_balancing();
index 7151d3763f01fcb3c0dd7f8572fcf24aa2e49881..bd2ad257402fa6511069015fe56382ab72ff7b33 100644 (file)
@@ -9,7 +9,7 @@
 use core::ptr;
 
 use super::borrow::DormantMutRef;
-use super::node::{self, marker, ForceResult::*, Handle, NodeRef};
+use super::node::{self, marker, ForceResult::*, Handle, NodeRef, Root};
 use super::search::{self, SearchResult::*};
 use super::unwrap_unchecked;
 
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct BTreeMap<K, V> {
-    root: Option<node::Root<K, V>>,
+    root: Option<Root<K, V>>,
     length: usize,
 }
 
@@ -145,7 +145,7 @@ fn drop(&mut self) {
 impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
     fn clone(&self) -> BTreeMap<K, V> {
         fn clone_subtree<'a, K: Clone, V: Clone>(
-            node: node::NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>,
+            node: NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>,
         ) -> BTreeMap<K, V>
         where
             K: 'a,
@@ -153,11 +153,11 @@ fn clone_subtree<'a, K: Clone, V: Clone>(
         {
             match node.force() {
                 Leaf(leaf) => {
-                    let mut out_tree = BTreeMap { root: Some(node::Root::new_leaf()), length: 0 };
+                    let mut out_tree = BTreeMap { root: Some(Root::new()), length: 0 };
 
                     {
                         let root = out_tree.root.as_mut().unwrap(); // unwrap succeeds because we just wrapped
-                        let mut out_node = match root.node_as_mut().force() {
+                        let mut out_node = match root.borrow_mut().force() {
                             Leaf(leaf) => leaf,
                             Internal(_) => unreachable!(),
                         };
@@ -198,7 +198,7 @@ fn clone_subtree<'a, K: Clone, V: Clone>(
                                 (root, length)
                             };
 
-                            out_node.push(k, v, subroot.unwrap_or_else(node::Root::new_leaf));
+                            out_node.push(k, v, subroot.unwrap_or_else(Root::new));
                             out_tree.length += 1 + sublength;
                         }
                     }
@@ -213,7 +213,7 @@ fn clone_subtree<'a, K: Clone, V: Clone>(
             // Ord` constraint, which this method lacks.
             BTreeMap { root: None, length: 0 }
         } else {
-            clone_subtree(self.root.as_ref().unwrap().node_as_ref()) // unwrap succeeds because not empty
+            clone_subtree(self.root.as_ref().unwrap().reborrow()) // unwrap succeeds because not empty
         }
     }
 }
@@ -226,7 +226,7 @@ impl<K, Q: ?Sized> super::Recover<Q> for BTreeMap<K, ()>
     type Key = K;
 
     fn get(&self, key: &Q) -> Option<&K> {
-        let root_node = self.root.as_ref()?.node_as_ref();
+        let root_node = self.root.as_ref()?.reborrow();
         match search::search_tree(root_node, key) {
             Found(handle) => Some(handle.into_kv().0),
             GoDown(_) => None,
@@ -235,7 +235,7 @@ fn get(&self, key: &Q) -> Option<&K> {
 
     fn take(&mut self, key: &Q) -> Option<K> {
         let (map, dormant_map) = DormantMutRef::new(self);
-        let root_node = map.root.as_mut()?.node_as_mut();
+        let root_node = map.root.as_mut()?.borrow_mut();
         match search::search_tree(root_node, key) {
             Found(handle) => {
                 Some(OccupiedEntry { handle, dormant_map, _marker: PhantomData }.remove_kv().0)
@@ -246,7 +246,7 @@ fn take(&mut self, key: &Q) -> Option<K> {
 
     fn replace(&mut self, key: K) -> Option<K> {
         let (map, dormant_map) = DormantMutRef::new(self);
-        let root_node = Self::ensure_is_owned(&mut map.root).node_as_mut();
+        let root_node = Self::ensure_is_owned(&mut map.root).borrow_mut();
         match search::search_tree::<marker::Mut<'_>, K, (), K>(root_node, &key) {
             Found(handle) => Some(mem::replace(handle.into_key_mut(), key)),
             GoDown(handle) => {
@@ -458,7 +458,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 }
 
 impl<K: Ord, V> BTreeMap<K, V> {
-    /// Makes a new empty BTreeMap.
+    /// Makes a new, empty `BTreeMap`.
     ///
     /// Does not allocate anything on its own.
     ///
@@ -522,7 +522,7 @@ pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>
         K: Borrow<Q>,
         Q: Ord,
     {
-        let root_node = self.root.as_ref()?.node_as_ref();
+        let root_node = self.root.as_ref()?.reborrow();
         match search::search_tree(root_node, key) {
             Found(handle) => Some(handle.into_kv().1),
             GoDown(_) => None,
@@ -550,7 +550,7 @@ pub fn get_key_value<Q: ?Sized>(&self, k: &Q) -> Option<(&K, &V)>
         K: Borrow<Q>,
         Q: Ord,
     {
-        let root_node = self.root.as_ref()?.node_as_ref();
+        let root_node = self.root.as_ref()?.reborrow();
         match search::search_tree(root_node, k) {
             Found(handle) => Some(handle.into_kv()),
             GoDown(_) => None,
@@ -576,7 +576,7 @@ pub fn get_key_value<Q: ?Sized>(&self, k: &Q) -> Option<(&K, &V)>
     /// ```
     #[unstable(feature = "map_first_last", issue = "62924")]
     pub fn first_key_value(&self) -> Option<(&K, &V)> {
-        let root_node = self.root.as_ref()?.node_as_ref();
+        let root_node = self.root.as_ref()?.reborrow();
         root_node.first_leaf_edge().right_kv().ok().map(Handle::into_kv)
     }
 
@@ -603,7 +603,7 @@ pub fn first_key_value(&self) -> Option<(&K, &V)> {
     #[unstable(feature = "map_first_last", issue = "62924")]
     pub fn first_entry(&mut self) -> Option<OccupiedEntry<'_, K, V>> {
         let (map, dormant_map) = DormantMutRef::new(self);
-        let root_node = map.root.as_mut()?.node_as_mut();
+        let root_node = map.root.as_mut()?.borrow_mut();
         let kv = root_node.first_leaf_edge().right_kv().ok()?;
         Some(OccupiedEntry { handle: kv.forget_node_type(), dormant_map, _marker: PhantomData })
     }
@@ -650,7 +650,7 @@ pub fn pop_first(&mut self) -> Option<(K, V)> {
     /// ```
     #[unstable(feature = "map_first_last", issue = "62924")]
     pub fn last_key_value(&self) -> Option<(&K, &V)> {
-        let root_node = self.root.as_ref()?.node_as_ref();
+        let root_node = self.root.as_ref()?.reborrow();
         root_node.last_leaf_edge().left_kv().ok().map(Handle::into_kv)
     }
 
@@ -677,7 +677,7 @@ pub fn last_key_value(&self) -> Option<(&K, &V)> {
     #[unstable(feature = "map_first_last", issue = "62924")]
     pub fn last_entry(&mut self) -> Option<OccupiedEntry<'_, K, V>> {
         let (map, dormant_map) = DormantMutRef::new(self);
-        let root_node = map.root.as_mut()?.node_as_mut();
+        let root_node = map.root.as_mut()?.borrow_mut();
         let kv = root_node.last_leaf_edge().left_kv().ok()?;
         Some(OccupiedEntry { handle: kv.forget_node_type(), dormant_map, _marker: PhantomData })
     }
@@ -758,7 +758,7 @@ pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<&mut V>
         K: Borrow<Q>,
         Q: Ord,
     {
-        let root_node = self.root.as_mut()?.node_as_mut();
+        let root_node = self.root.as_mut()?.borrow_mut();
         match search::search_tree(root_node, key) {
             Found(handle) => Some(handle.into_val_mut()),
             GoDown(_) => None,
@@ -854,7 +854,7 @@ pub fn remove_entry<Q: ?Sized>(&mut self, key: &Q) -> Option<(K, V)>
         Q: Ord,
     {
         let (map, dormant_map) = DormantMutRef::new(self);
-        let root_node = map.root.as_mut()?.node_as_mut();
+        let root_node = map.root.as_mut()?.borrow_mut();
         match search::search_tree(root_node, key) {
             Found(handle) => {
                 Some(OccupiedEntry { handle, dormant_map, _marker: PhantomData }.remove_entry())
@@ -971,7 +971,7 @@ pub fn range<T: ?Sized, R>(&self, range: R) -> Range<'_, K, V>
         R: RangeBounds<T>,
     {
         if let Some(root) = &self.root {
-            let (f, b) = root.node_as_ref().range_search(range);
+            let (f, b) = root.reborrow().range_search(range);
 
             Range { front: Some(f), back: Some(b) }
         } else {
@@ -1017,7 +1017,7 @@ pub fn range_mut<T: ?Sized, R>(&mut self, range: R) -> RangeMut<'_, K, V>
         R: RangeBounds<T>,
     {
         if let Some(root) = &mut self.root {
-            let (f, b) = root.node_as_valmut().range_search(range);
+            let (f, b) = root.borrow_valmut().range_search(range);
 
             RangeMut { front: Some(f), back: Some(b), _marker: PhantomData }
         } else {
@@ -1037,7 +1037,7 @@ pub fn range_mut<T: ?Sized, R>(&mut self, range: R) -> RangeMut<'_, K, V>
     /// let mut count: BTreeMap<&str, usize> = BTreeMap::new();
     ///
     /// // count the number of occurrences of letters in the vec
-    /// for x in vec!["a","b","a","c","a","b"] {
+    /// for x in vec!["a", "b", "a", "c", "a", "b"] {
     ///     *count.entry(x).or_insert(0) += 1;
     /// }
     ///
@@ -1047,7 +1047,7 @@ pub fn range_mut<T: ?Sized, R>(&mut self, range: R) -> RangeMut<'_, K, V>
     pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
         // FIXME(@porglezomp) Avoid allocating if we don't insert
         let (map, dormant_map) = DormantMutRef::new(self);
-        let root_node = Self::ensure_is_owned(&mut map.root).node_as_mut();
+        let root_node = Self::ensure_is_owned(&mut map.root).borrow_mut();
         match search::search_tree(root_node, &key) {
             Found(handle) => Occupied(OccupiedEntry { handle, dormant_map, _marker: PhantomData }),
             GoDown(handle) => {
@@ -1103,10 +1103,10 @@ pub fn split_off<Q: ?Sized + Ord>(&mut self, key: &Q) -> Self
         left_root.split_off(right_root, key);
 
         if left_root.height() < right_root.height() {
-            self.length = left_root.node_as_ref().calc_length();
+            self.length = left_root.reborrow().calc_length();
             right.length = total_num - self.len();
         } else {
-            right.length = right_root.node_as_ref().calc_length();
+            right.length = right_root.reborrow().calc_length();
             self.length = total_num - right.len();
         }
 
@@ -1154,7 +1154,7 @@ pub fn drain_filter<F>(&mut self, pred: F) -> DrainFilter<'_, K, V, F>
     pub(super) fn drain_filter_inner(&mut self) -> DrainFilterInner<'_, K, V> {
         if let Some(root) = self.root.as_mut() {
             let (root, dormant_root) = DormantMutRef::new(root);
-            let front = root.node_as_mut().first_leaf_edge();
+            let front = root.borrow_mut().first_leaf_edge();
             DrainFilterInner {
                 length: &mut self.length,
                 dormant_root: Some(dormant_root),
@@ -1361,7 +1361,7 @@ impl<K, V> IntoIterator for BTreeMap<K, V> {
     fn into_iter(self) -> IntoIter<K, V> {
         let mut me = ManuallyDrop::new(self);
         if let Some(root) = me.root.take() {
-            let (f, b) = root.into_ref().full_range();
+            let (f, b) = root.full_range();
 
             IntoIter { front: Some(f), back: Some(b), length: me.length }
         } else {
@@ -1551,14 +1551,14 @@ pub struct DrainFilter<'a, K, V, F>
     pred: F,
     inner: DrainFilterInner<'a, K, V>,
 }
-/// Most of the implementation of DrainFilter, independent of the type
+/// Most of the implementation of DrainFilter are generic over the type
 /// of the predicate, thus also serving for BTreeSet::DrainFilter.
 pub(super) struct DrainFilterInner<'a, K: 'a, V: 'a> {
     /// Reference to the length field in the borrowed map, updated live.
     length: &'a mut usize,
-    /// Burried reference to the root field in the borrowed map.
+    /// Buried reference to the root field in the borrowed map.
     /// Wrapped in `Option` to allow drop handler to `take` it.
-    dormant_root: Option<DormantMutRef<'a, node::Root<K, V>>>,
+    dormant_root: Option<DormantMutRef<'a, Root<K, V>>>,
     /// Contains a leaf edge preceding the next element to be returned, or the last leaf edge.
     /// Empty if the map has no root, if iteration went beyond the last leaf edge,
     /// or if a panic occurred in the predicate.
@@ -1924,7 +1924,7 @@ fn hash<H: Hasher>(&self, state: &mut H) {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K: Ord, V> Default for BTreeMap<K, V> {
-    /// Creates an empty `BTreeMap<K, V>`.
+    /// Creates an empty `BTreeMap`.
     fn default() -> BTreeMap<K, V> {
         BTreeMap::new()
     }
@@ -2007,7 +2007,7 @@ impl<K, V> BTreeMap<K, V> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter<'_, K, V> {
         if let Some(root) = &self.root {
-            let (f, b) = root.node_as_ref().full_range();
+            let (f, b) = root.reborrow().full_range();
 
             Iter { range: Range { front: Some(f), back: Some(b) }, length: self.length }
         } else {
@@ -2039,7 +2039,7 @@ pub fn iter(&self) -> Iter<'_, K, V> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
         if let Some(root) = &mut self.root {
-            let (f, b) = root.node_as_valmut().full_range();
+            let (f, b) = root.borrow_valmut().full_range();
 
             IterMut {
                 range: RangeMut { front: Some(f), back: Some(b), _marker: PhantomData },
@@ -2160,8 +2160,8 @@ pub const fn is_empty(&self) -> bool {
 
     /// If the root node is the empty (non-allocated) root node, allocate our
     /// own node. Is an associated function to avoid borrowing the entire BTreeMap.
-    fn ensure_is_owned(root: &mut Option<node::Root<K, V>>) -> &mut node::Root<K, V> {
-        root.get_or_insert_with(node::Root::new_leaf)
+    fn ensure_is_owned(root: &mut Option<Root<K, V>>) -> &mut Root<K, V> {
+        root.get_or_insert_with(Root::new)
     }
 }
 
index 73a0ca21f6733f919d3ac12beae88d3c82caa19a..69926ac2aff6d0c7ecffcf58fe2b7d68ab6d54e2 100644 (file)
@@ -286,7 +286,7 @@ pub fn insert(self, value: V) -> &'a mut V {
                 // Safety: We have consumed self.handle and the reference returned.
                 let map = unsafe { self.dormant_map.awaken() };
                 let root = map.root.as_mut().unwrap();
-                root.push_internal_level().push(ins.k, ins.v, ins.right);
+                root.push_internal_level().push(ins.kv.0, ins.kv.1, ins.right);
                 map.length += 1;
                 val_ptr
             }
index 6e45d38dd9f912f9ee40e9407879b2a1059bc2e7..23cd4f3d83d624c09078e9819f00d1f73a90e6b4 100644 (file)
@@ -6,13 +6,14 @@
 use crate::rc::Rc;
 use crate::string::{String, ToString};
 use crate::vec::Vec;
+use std::cmp::Ordering;
 use std::convert::TryFrom;
 use std::iter::{self, FromIterator};
 use std::mem;
 use std::ops::Bound::{self, Excluded, Included, Unbounded};
 use std::ops::RangeBounds;
 use std::panic::{catch_unwind, AssertUnwindSafe};
-use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
 
 mod ord_chaos;
 use ord_chaos::{Cyclic3, Governed, Governor};
@@ -49,31 +50,30 @@ impl<K, V> BTreeMap<K, V> {
     // Panics if the map (or the code navigating it) is corrupted.
     fn check_invariants(&self) {
         if let Some(root) = &self.root {
-            let root_node = root.node_as_ref();
+            let root_node = root.reborrow();
 
             // Check the back pointers top-down, before we attempt to rely on
             // more serious navigation code.
             assert!(root_node.ascend().is_err());
             root_node.assert_back_pointers();
 
-            // Check consistenty of `length` and some of the navigation.
+            // Check consistency of `length` with what navigation code encounters.
             assert_eq!(self.length, root_node.calc_length());
-            assert_eq!(self.length, self.keys().count());
 
             // Lastly, check the invariant causing the least harm.
             root_node.assert_min_len(if root_node.height() > 0 { 1 } else { 0 });
         } else {
-            // Check consistenty of `length` and some of the navigation.
             assert_eq!(self.length, 0);
-            assert_eq!(self.length, self.keys().count());
         }
+
+        // Check that `assert_strictly_ascending` will encounter all keys.
+        assert_eq!(self.length, self.keys().count());
     }
 
     // Panics if the map is corrupted or if the keys are not in strictly
     // ascending order, in the current opinion of the `Ord` implementation.
-    // If the `Ord` implementation does not honor transitivity, this method
-    // does not guarantee that all the keys are unique, just that adjacent
-    // keys are unique.
+    // If the `Ord` implementation violates transitivity, this method does not
+    // guarantee that all keys are unique, just that adjacent keys are unique.
     fn check(&self)
     where
         K: Debug + Ord,
@@ -92,7 +92,7 @@ fn dump_keys(&self) -> String
         K: Debug,
     {
         if let Some(root) = self.root.as_ref() {
-            root.node_as_ref().dump_keys()
+            root.reborrow().dump_keys()
         } else {
             String::from("not yet allocated")
         }
@@ -879,6 +879,7 @@ fn empty() {
         map.check();
     }
 
+    // Explicitly consumes the iterator, where most test cases drop it instantly.
     #[test]
     fn consumed_keeping_all() {
         let pairs = (0..3).map(|i| (i, i));
@@ -887,6 +888,7 @@ fn consumed_keeping_all() {
         map.check();
     }
 
+    // Explicitly consumes the iterator, where most test cases drop it instantly.
     #[test]
     fn consumed_removing_all() {
         let pairs = (0..3).map(|i| (i, i));
@@ -896,15 +898,7 @@ fn consumed_removing_all() {
         map.check();
     }
 
-    #[test]
-    fn dropped_removing_all() {
-        let pairs = (0..3).map(|i| (i, i));
-        let mut map: BTreeMap<_, _> = pairs.collect();
-        map.drain_filter(|_, _| true);
-        assert!(map.is_empty());
-        map.check();
-    }
-
+    // Explicitly consumes the iterator and modifies values through it.
     #[test]
     fn mutating_and_keeping() {
         let pairs = (0..3).map(|i| (i, i));
@@ -921,6 +915,7 @@ fn mutating_and_keeping() {
         map.check();
     }
 
+    // Explicitly consumes the iterator and modifies values through it.
     #[test]
     fn mutating_and_removing() {
         let pairs = (0..3).map(|i| (i, i));
@@ -1094,7 +1089,7 @@ fn drop_panic_leak() {
         struct D;
         impl Drop for D {
             fn drop(&mut self) {
-                if DROPS.fetch_add(1, Ordering::SeqCst) == 1 {
+                if DROPS.fetch_add(1, SeqCst) == 1 {
                     panic!("panic in `drop`");
                 }
             }
@@ -1105,14 +1100,14 @@ fn drop(&mut self) {
 
         catch_unwind(move || {
             drop(map.drain_filter(|i, _| {
-                PREDS.fetch_add(1usize << i, Ordering::SeqCst);
+                PREDS.fetch_add(1usize << i, SeqCst);
                 true
             }))
         })
         .unwrap_err();
 
-        assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
-        assert_eq!(DROPS.load(Ordering::SeqCst), 3);
+        assert_eq!(PREDS.load(SeqCst), 0x011);
+        assert_eq!(DROPS.load(SeqCst), 3);
     }
 
     #[test]
@@ -1123,7 +1118,7 @@ fn pred_panic_leak() {
         struct D;
         impl Drop for D {
             fn drop(&mut self) {
-                DROPS.fetch_add(1, Ordering::SeqCst);
+                DROPS.fetch_add(1, SeqCst);
             }
         }
 
@@ -1132,7 +1127,7 @@ fn drop(&mut self) {
 
         catch_unwind(AssertUnwindSafe(|| {
             drop(map.drain_filter(|i, _| {
-                PREDS.fetch_add(1usize << i, Ordering::SeqCst);
+                PREDS.fetch_add(1usize << i, SeqCst);
                 match i {
                     0 => true,
                     _ => panic!(),
@@ -1141,8 +1136,8 @@ fn drop(&mut self) {
         }))
         .unwrap_err();
 
-        assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
-        assert_eq!(DROPS.load(Ordering::SeqCst), 1);
+        assert_eq!(PREDS.load(SeqCst), 0x011);
+        assert_eq!(DROPS.load(SeqCst), 1);
         assert_eq!(map.len(), 2);
         assert_eq!(map.first_entry().unwrap().key(), &4);
         assert_eq!(map.last_entry().unwrap().key(), &8);
@@ -1158,7 +1153,7 @@ fn pred_panic_reuse() {
         struct D;
         impl Drop for D {
             fn drop(&mut self) {
-                DROPS.fetch_add(1, Ordering::SeqCst);
+                DROPS.fetch_add(1, SeqCst);
             }
         }
 
@@ -1167,7 +1162,7 @@ fn drop(&mut self) {
 
         {
             let mut it = map.drain_filter(|i, _| {
-                PREDS.fetch_add(1usize << i, Ordering::SeqCst);
+                PREDS.fetch_add(1usize << i, SeqCst);
                 match i {
                     0 => true,
                     _ => panic!(),
@@ -1180,8 +1175,8 @@ fn drop(&mut self) {
             assert!(matches!(result, Ok(None)));
         }
 
-        assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
-        assert_eq!(DROPS.load(Ordering::SeqCst), 1);
+        assert_eq!(PREDS.load(SeqCst), 0x011);
+        assert_eq!(DROPS.load(SeqCst), 1);
         assert_eq!(map.len(), 2);
         assert_eq!(map.first_entry().unwrap().key(), &4);
         assert_eq!(map.last_entry().unwrap().key(), &8);
@@ -1315,8 +1310,6 @@ fn test_zst() {
 // undefined.
 #[test]
 fn test_bad_zst() {
-    use std::cmp::Ordering;
-
     #[derive(Clone, Copy, Debug)]
     struct Bad;
 
@@ -1763,7 +1756,7 @@ fn test_append_drop_leak() {
 
     impl Drop for D {
         fn drop(&mut self) {
-            if DROPS.fetch_add(1, Ordering::SeqCst) == 0 {
+            if DROPS.fetch_add(1, SeqCst) == 0 {
                 panic!("panic in `drop`");
             }
         }
@@ -1779,7 +1772,7 @@ fn drop(&mut self) {
 
     catch_unwind(move || left.append(&mut right)).unwrap_err();
 
-    assert_eq!(DROPS.load(Ordering::SeqCst), 4); // Rust issue #47949 ate one little piggy
+    assert_eq!(DROPS.load(SeqCst), 4); // Rust issue #47949 ate one little piggy
 }
 
 #[test]
@@ -1894,7 +1887,7 @@ fn test_into_iter_drop_leak_height_0() {
 
     impl Drop for D {
         fn drop(&mut self) {
-            if DROPS.fetch_add(1, Ordering::SeqCst) == 3 {
+            if DROPS.fetch_add(1, SeqCst) == 3 {
                 panic!("panic in `drop`");
             }
         }
@@ -1909,7 +1902,7 @@ fn drop(&mut self) {
 
     catch_unwind(move || drop(map.into_iter())).unwrap_err();
 
-    assert_eq!(DROPS.load(Ordering::SeqCst), 5);
+    assert_eq!(DROPS.load(SeqCst), 5);
 }
 
 #[test]
@@ -1921,18 +1914,18 @@ fn test_into_iter_drop_leak_height_1() {
     struct D;
     impl Drop for D {
         fn drop(&mut self) {
-            if DROPS.fetch_add(1, Ordering::SeqCst) == PANIC_POINT.load(Ordering::SeqCst) {
+            if DROPS.fetch_add(1, SeqCst) == PANIC_POINT.load(SeqCst) {
                 panic!("panic in `drop`");
             }
         }
     }
 
     for panic_point in vec![0, 1, size - 2, size - 1] {
-        DROPS.store(0, Ordering::SeqCst);
-        PANIC_POINT.store(panic_point, Ordering::SeqCst);
+        DROPS.store(0, SeqCst);
+        PANIC_POINT.store(panic_point, SeqCst);
         let map: BTreeMap<_, _> = (0..size).map(|i| (i, D)).collect();
         catch_unwind(move || drop(map.into_iter())).unwrap_err();
-        assert_eq!(DROPS.load(Ordering::SeqCst), size);
+        assert_eq!(DROPS.load(SeqCst), size);
     }
 }
 
index 91d1d6ea9ef38f48fe9ef73171c4ebc6014a3514..96ce7c15790463b3770285f6395859d64ea9afdc 100644 (file)
@@ -2,6 +2,7 @@
 use std::cmp::Ordering::{self, *};
 use std::ptr;
 
+// Minimal type with an `Ord` implementation violating transitivity.
 #[derive(Debug)]
 pub enum Cyclic3 {
     A,
@@ -34,6 +35,7 @@ fn eq(&self, other: &Self) -> bool {
 
 impl Eq for Cyclic3 {}
 
+// Controls the ordering of values wrapped by `Governed`.
 #[derive(Debug)]
 pub struct Governor {
     flipped: Cell<bool>,
@@ -49,6 +51,9 @@ pub fn flip(&self) {
     }
 }
 
+// Type with an `Ord` implementation that forms a total order at any moment
+// (assuming that `T` respects total order), but can suddenly be made to invert
+// that total order.
 #[derive(Debug)]
 pub struct Governed<'a, T>(pub T, pub &'a Governor);
 
index 5feab9201382ef0156eb8a4edef901100c0ba674..6a8be441513a0b7b7b4fa7a43ba9a56a386b947f 100644 (file)
@@ -31,7 +31,7 @@
 use core::cmp::Ordering;
 use core::marker::PhantomData;
 use core::mem::{self, MaybeUninit};
-use core::ptr::{self, NonNull, Unique};
+use core::ptr::{self, NonNull};
 
 use crate::alloc::{AllocRef, Global, Layout};
 use crate::boxed::Box;
@@ -112,102 +112,65 @@ unsafe fn new() -> Self {
 ///
 /// However, `BoxedNode` contains no information as to which of the two types
 /// of nodes it actually contains, and, partially due to this lack of information,
-/// has no destructor.
-struct BoxedNode<K, V> {
-    ptr: Unique<LeafNode<K, V>>,
-}
-
-impl<K, V> BoxedNode<K, V> {
-    fn from_leaf(node: Box<LeafNode<K, V>>) -> Self {
-        BoxedNode { ptr: Unique::from(Box::leak(node)) }
-    }
-
-    fn from_internal(node: Box<InternalNode<K, V>>) -> Self {
-        BoxedNode { ptr: Unique::from(Box::leak(node)).cast() }
-    }
-
-    fn as_ptr(&self) -> NonNull<LeafNode<K, V>> {
-        NonNull::from(self.ptr)
-    }
-}
+/// is not a separate type and has no destructor.
+type BoxedNode<K, V> = NonNull<LeafNode<K, V>>;
 
 /// An owned tree.
 ///
 /// Note that this does not have a destructor, and must be cleaned up manually.
-pub struct Root<K, V> {
-    node: BoxedNode<K, V>,
-    /// The number of levels below the root node.
-    height: usize,
-}
-
-unsafe impl<K: Sync, V: Sync> Sync for Root<K, V> {}
-unsafe impl<K: Send, V: Send> Send for Root<K, V> {}
+pub type Root<K, V> = NodeRef<marker::Owned, K, V, marker::LeafOrInternal>;
 
 impl<K, V> Root<K, V> {
-    /// Returns the number of levels below the root.
-    pub fn height(&self) -> usize {
-        self.height
-    }
-
     /// Returns a new owned tree, with its own root node that is initially empty.
-    pub fn new_leaf() -> Self {
-        Root { node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })), height: 0 }
+    pub fn new() -> Self {
+        NodeRef::new_leaf().forget_type()
     }
+}
 
-    /// Borrows and returns an immutable reference to the node owned by the root.
-    pub fn node_as_ref(&self) -> NodeRef<marker::Immut<'_>, K, V, marker::LeafOrInternal> {
-        NodeRef { height: self.height, node: self.node.as_ptr(), _marker: PhantomData }
+impl<K, V> NodeRef<marker::Owned, K, V, marker::Leaf> {
+    fn new_leaf() -> Self {
+        Self::from_new_leaf(Box::new(unsafe { LeafNode::new() }))
     }
 
-    /// Borrows and returns a mutable reference to the node owned by the root.
-    pub fn node_as_mut(&mut self) -> NodeRef<marker::Mut<'_>, K, V, marker::LeafOrInternal> {
-        NodeRef { height: self.height, node: self.node.as_ptr(), _marker: PhantomData }
-    }
-
-    /// Borrows and returns a mutable reference to the leaf node owned by the root.
-    /// # Safety
-    /// The root node is a leaf.
-    unsafe fn leaf_node_as_mut(&mut self) -> NodeRef<marker::Mut<'_>, K, V, marker::Leaf> {
-        debug_assert!(self.height == 0);
-        NodeRef { height: self.height, node: self.node.as_ptr(), _marker: PhantomData }
-    }
-
-    /// Borrows and returns a mutable reference to the internal node owned by the root.
-    /// # Safety
-    /// The root node is not a leaf.
-    unsafe fn internal_node_as_mut(&mut self) -> NodeRef<marker::Mut<'_>, K, V, marker::Internal> {
-        debug_assert!(self.height > 0);
-        NodeRef { height: self.height, node: self.node.as_ptr(), _marker: PhantomData }
+    fn from_new_leaf(leaf: Box<LeafNode<K, V>>) -> Self {
+        NodeRef { height: 0, node: NonNull::from(Box::leak(leaf)), _marker: PhantomData }
     }
+}
 
-    pub fn node_as_valmut(&mut self) -> NodeRef<marker::ValMut<'_>, K, V, marker::LeafOrInternal> {
-        NodeRef { height: self.height, node: self.node.as_ptr(), _marker: PhantomData }
+impl<K, V> NodeRef<marker::Owned, K, V, marker::Internal> {
+    fn from_new_internal(internal: Box<InternalNode<K, V>>, height: usize) -> Self {
+        NodeRef { height, node: NonNull::from(Box::leak(internal)).cast(), _marker: PhantomData }
     }
+}
 
-    pub fn into_ref(self) -> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
-        NodeRef { height: self.height, node: self.node.as_ptr(), _marker: PhantomData }
+impl<K, V, Type> NodeRef<marker::Owned, K, V, Type> {
+    /// Mutably borrows the owned node. Unlike `reborrow_mut`, this is safe,
+    /// because the return value cannot be used to destroy the node itself,
+    /// and there cannot be other references to the tree (except during the
+    /// process of `into_iter` or `drop`, but that is a horrific already).
+    pub fn borrow_mut(&mut self) -> NodeRef<marker::Mut<'_>, K, V, Type> {
+        NodeRef { height: self.height, node: self.node, _marker: PhantomData }
     }
 
-    /// Packs the reference, aware of type and height, into a type-agnostic pointer.
-    fn into_boxed_node(self) -> BoxedNode<K, V> {
-        self.node
+    /// Slightly mutably borrows the owned node.
+    pub fn borrow_valmut(&mut self) -> NodeRef<marker::ValMut<'_>, K, V, Type> {
+        NodeRef { height: self.height, node: self.node, _marker: PhantomData }
     }
+}
 
+impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
     /// Adds a new internal node with a single edge pointing to the previous root node,
     /// make that new node the root node, and return it. This increases the height by 1
     /// and is the opposite of `pop_internal_level`.
     pub fn push_internal_level(&mut self) -> NodeRef<marker::Mut<'_>, K, V, marker::Internal> {
         let mut new_node = Box::new(unsafe { InternalNode::new() });
-        new_node.edges[0].write(unsafe { ptr::read(&mut self.node) });
-
-        self.node = BoxedNode::from_internal(new_node);
-        self.height += 1;
+        new_node.edges[0].write(self.node);
+        let mut new_root = NodeRef::from_new_internal(new_node, self.height + 1);
+        new_root.borrow_mut().first_edge().correct_parent_link();
+        *self = new_root.forget_type();
 
-        unsafe {
-            let mut ret = self.internal_node_as_mut();
-            ret.reborrow_mut().first_edge().correct_parent_link();
-            ret
-        }
+        // `self.borrow_mut()`, except that we just forgot we're internal now:
+        NodeRef { height: self.height, node: self.node, _marker: PhantomData }
     }
 
     /// Removes the internal root node, using its first child as the new root node.
@@ -216,19 +179,17 @@ pub fn push_internal_level(&mut self) -> NodeRef<marker::Mut<'_>, K, V, marker::
     /// This decreases the height by 1 and is the opposite of `push_internal_level`.
     ///
     /// Requires exclusive access to the `Root` object but not to the root node;
-    /// it will not invalidate existing handles or references to the root node.
+    /// it will not invalidate other handles or references to the root node.
     ///
     /// Panics if there is no internal level, i.e., if the root node is a leaf.
     pub fn pop_internal_level(&mut self) {
         assert!(self.height > 0);
 
-        let top = BoxedNode::as_ptr(&self.node);
+        let top = self.node;
 
-        let mut internal_node = unsafe { self.internal_node_as_mut() };
-        let internal_node = NodeRef::as_internal_mut(&mut internal_node);
-        self.node = unsafe { internal_node.edges[0].assume_init_read() };
-        self.height -= 1;
-        self.node_as_mut().clear_parent_link();
+        let internal_node = NodeRef { height: self.height, node: top, _marker: PhantomData };
+        *self = internal_node.first_edge().descend();
+        self.borrow_mut().clear_parent_link();
 
         unsafe {
             Global.dealloc(top.cast(), Layout::new::<InternalNode<K, V>>());
@@ -310,13 +271,6 @@ unsafe impl<'a, K: Send + 'a, V: Send + 'a, Type> Send for NodeRef<marker::Mut<'
 unsafe impl<'a, K: Send + 'a, V: Send + 'a, Type> Send for NodeRef<marker::ValMut<'a>, K, V, Type> {}
 unsafe impl<K: Send, V: Send, Type> Send for NodeRef<marker::Owned, K, V, Type> {}
 
-impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
-    /// Unpack a node reference that was packed by `Root::into_boxed_node`.
-    fn from_boxed_node(boxed_node: BoxedNode<K, V>, height: usize) -> Self {
-        NodeRef { height, node: boxed_node.as_ptr(), _marker: PhantomData }
-    }
-}
-
 impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Internal> {
     /// Unpack a node reference that was packed as `NodeRef::parent`.
     fn from_internal(node: NonNull<InternalNode<K, V>>, height: usize) -> Self {
@@ -717,7 +671,7 @@ pub fn push(&mut self, key: K, val: V, edge: Root<K, V>) {
         unsafe {
             self.reborrow_mut().into_key_area_mut_at(idx).write(key);
             self.reborrow_mut().into_val_area_mut_at(idx).write(val);
-            self.reborrow_mut().into_edge_area_mut_at(idx + 1).write(edge.into_boxed_node());
+            self.reborrow_mut().into_edge_area_mut_at(idx + 1).write(edge.node);
             Handle::new_edge(self.reborrow_mut(), idx + 1).correct_parent_link();
         }
     }
@@ -732,7 +686,7 @@ fn push_front(&mut self, key: K, val: V, edge: Root<K, V>) {
             *self.reborrow_mut().into_len_mut() += 1;
             slice_insert(self.reborrow_mut().into_key_area_slice(), 0, key);
             slice_insert(self.reborrow_mut().into_val_area_slice(), 0, val);
-            slice_insert(self.reborrow_mut().into_edge_area_slice(), 0, edge.into_boxed_node());
+            slice_insert(self.reborrow_mut().into_edge_area_slice(), 0, edge.node);
         }
 
         self.correct_all_childrens_parent_links();
@@ -754,11 +708,11 @@ fn pop(&mut self) -> (K, V, Option<Root<K, V>>) {
             let edge = match self.reborrow_mut().force() {
                 ForceResult::Leaf(_) => None,
                 ForceResult::Internal(internal) => {
-                    let boxed_node = ptr::read(internal.reborrow().edge_at(idx + 1));
-                    let mut edge = Root { node: boxed_node, height: internal.height - 1 };
+                    let node = ptr::read(internal.reborrow().edge_at(idx + 1));
+                    let mut edge = Root { node, height: internal.height - 1, _marker: PhantomData };
                     // In practice, clearing the parent is a waste of time, because we will
                     // insert the node elsewhere and set its parent link again.
-                    edge.node_as_mut().clear_parent_link();
+                    edge.borrow_mut().clear_parent_link();
                     Some(edge)
                 }
             };
@@ -782,12 +736,11 @@ fn pop_front(&mut self) -> (K, V, Option<Root<K, V>>) {
             let edge = match self.reborrow_mut().force() {
                 ForceResult::Leaf(_) => None,
                 ForceResult::Internal(mut internal) => {
-                    let boxed_node =
-                        slice_remove(internal.reborrow_mut().into_edge_area_slice(), 0);
-                    let mut edge = Root { node: boxed_node, height: internal.height - 1 };
+                    let node = slice_remove(internal.reborrow_mut().into_edge_area_slice(), 0);
+                    let mut edge = Root { node, height: internal.height - 1, _marker: PhantomData };
                     // In practice, clearing the parent is a waste of time, because we will
                     // insert the node elsewhere and set its parent link again.
-                    edge.node_as_mut().clear_parent_link();
+                    edge.borrow_mut().clear_parent_link();
 
                     internal.correct_childrens_parent_links(0..old_len);
 
@@ -1028,17 +981,17 @@ fn insert(mut self, key: K, val: V) -> (InsertResult<'a, K, V, marker::Leaf>, *m
         } else {
             let (middle_kv_idx, insertion) = splitpoint(self.idx);
             let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) };
-            let (mut left, k, v, mut right) = middle.split();
+            let mut result = middle.split();
             let mut insertion_edge = match insertion {
                 LeftOrRight::Left(insert_idx) => unsafe {
-                    Handle::new_edge(left.reborrow_mut(), insert_idx)
+                    Handle::new_edge(result.left.reborrow_mut(), insert_idx)
                 },
                 LeftOrRight::Right(insert_idx) => unsafe {
-                    Handle::new_edge(right.leaf_node_as_mut(), insert_idx)
+                    Handle::new_edge(result.right.borrow_mut(), insert_idx)
                 },
             };
             let val_ptr = insertion_edge.insert_fit(key, val);
-            (InsertResult::Split(SplitResult { left: left.forget_type(), k, v, right }), val_ptr)
+            (InsertResult::Split(result), val_ptr)
         }
     }
 }
@@ -1063,12 +1016,11 @@ fn insert_fit(&mut self, key: K, val: V, edge: Root<K, V>) {
         debug_assert!(self.node.len() < CAPACITY);
         debug_assert!(edge.height == self.node.height - 1);
 
-        let boxed_node = edge.into_boxed_node();
         unsafe {
             *self.node.reborrow_mut().into_len_mut() += 1;
             slice_insert(self.node.reborrow_mut().into_key_area_slice(), self.idx, key);
             slice_insert(self.node.reborrow_mut().into_val_area_slice(), self.idx, val);
-            slice_insert(self.node.reborrow_mut().into_edge_area_slice(), self.idx + 1, boxed_node);
+            slice_insert(self.node.reborrow_mut().into_edge_area_slice(), self.idx + 1, edge.node);
 
             self.node.correct_childrens_parent_links((self.idx + 1)..=self.node.len());
         }
@@ -1092,17 +1044,17 @@ fn insert(
         } else {
             let (middle_kv_idx, insertion) = splitpoint(self.idx);
             let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) };
-            let (mut left, k, v, mut right) = middle.split();
+            let mut result = middle.split();
             let mut insertion_edge = match insertion {
                 LeftOrRight::Left(insert_idx) => unsafe {
-                    Handle::new_edge(left.reborrow_mut(), insert_idx)
+                    Handle::new_edge(result.left.reborrow_mut(), insert_idx)
                 },
                 LeftOrRight::Right(insert_idx) => unsafe {
-                    Handle::new_edge(right.internal_node_as_mut(), insert_idx)
+                    Handle::new_edge(result.right.borrow_mut(), insert_idx)
                 },
             };
             insertion_edge.insert_fit(key, val, edge);
-            InsertResult::Split(SplitResult { left: left.forget_type(), k, v, right })
+            InsertResult::Split(result)
         }
     }
 }
@@ -1124,16 +1076,16 @@ pub fn insert_recursing(
             (InsertResult::Fit(handle), ptr) => {
                 return (InsertResult::Fit(handle.forget_node_type()), ptr);
             }
-            (InsertResult::Split(split), val_ptr) => (split, val_ptr),
+            (InsertResult::Split(split), val_ptr) => (split.forget_node_type(), val_ptr),
         };
 
         loop {
             split = match split.left.ascend() {
-                Ok(parent) => match parent.insert(split.k, split.v, split.right) {
+                Ok(parent) => match parent.insert(split.kv.0, split.kv.1, split.right) {
                     InsertResult::Fit(handle) => {
                         return (InsertResult::Fit(handle.forget_node_type()), val_ptr);
                     }
-                    InsertResult::Split(split) => split,
+                    InsertResult::Split(split) => split.forget_node_type(),
                 },
                 Err(root) => {
                     return (InsertResult::Split(SplitResult { left: root, ..split }), val_ptr);
@@ -1157,8 +1109,8 @@ pub fn descend(self) -> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
         // reference (Rust issue #73987) and invalidate any other references
         // to or inside the array, should any be around.
         let parent_ptr = NodeRef::as_internal_ptr(&self.node);
-        let boxed_node = unsafe { (*parent_ptr).edges.get_unchecked(self.idx).assume_init_read() };
-        NodeRef::from_boxed_node(boxed_node, self.node.height - 1)
+        let node = unsafe { (*parent_ptr).edges.get_unchecked(self.idx).assume_init_read() };
+        NodeRef { node, height: self.node.height - 1, _marker: PhantomData }
     }
 }
 
@@ -1239,14 +1191,14 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
     /// - The key and value pointed to by this handle are extracted.
     /// - All the key/value pairs to the right of this handle are put into a newly
     ///   allocated node.
-    pub fn split(mut self) -> (NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, K, V, Root<K, V>) {
+    pub fn split(mut self) -> SplitResult<'a, K, V, marker::Leaf> {
         unsafe {
             let mut new_node = Box::new(LeafNode::new());
 
-            let (k, v) = self.split_leaf_data(&mut new_node);
+            let kv = self.split_leaf_data(&mut new_node);
 
-            let right = Root { node: BoxedNode::from_leaf(new_node), height: 0 };
-            (self.node, k, v, right)
+            let right = NodeRef::from_new_leaf(new_node);
+            SplitResult { left: self.node, kv, right }
         }
     }
 
@@ -1272,7 +1224,7 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>,
     /// - The key and value pointed to by this handle are extracted.
     /// - All the edges and key/value pairs to the right of this handle are put into
     ///   a newly allocated node.
-    pub fn split(mut self) -> (NodeRef<marker::Mut<'a>, K, V, marker::Internal>, K, V, Root<K, V>) {
+    pub fn split(mut self) -> SplitResult<'a, K, V, marker::Internal> {
         unsafe {
             let mut new_node = Box::new(InternalNode::new());
             let new_len = self.split_new_node_len();
@@ -1282,14 +1234,14 @@ pub fn split(mut self) -> (NodeRef<marker::Mut<'a>, K, V, marker::Internal>, K,
                 new_node.edges.as_mut_ptr(),
                 new_len + 1,
             );
-            let (k, v) = self.split_leaf_data(&mut new_node.data);
+            let kv = self.split_leaf_data(&mut new_node.data);
 
             let height = self.node.height;
-            let mut right = Root { node: BoxedNode::from_internal(new_node), height };
+            let mut right = NodeRef::from_new_internal(new_node, height);
 
-            right.internal_node_as_mut().correct_childrens_parent_links(0..=new_len);
+            right.borrow_mut().correct_childrens_parent_links(0..=new_len);
 
-            (self.node, k, v, right)
+            SplitResult { left: self.node, kv, right }
         }
     }
 }
@@ -1756,20 +1708,30 @@ pub enum ForceResult<Leaf, Internal> {
 }
 
 /// Result of insertion, when a node needed to expand beyond its capacity.
-/// Does not distinguish between `Leaf` and `Internal` because `Root` doesn't.
-pub struct SplitResult<'a, K, V> {
-    // Altered node in existing tree with elements and edges that belong to the left of `k`.
-    pub left: NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>,
+pub struct SplitResult<'a, K, V, NodeType> {
+    // Altered node in existing tree with elements and edges that belong to the left of `kv`.
+    pub left: NodeRef<marker::Mut<'a>, K, V, NodeType>,
     // Some key and value split off, to be inserted elsewhere.
-    pub k: K,
-    pub v: V,
-    // Owned, unattached, new node with elements and edges that belong to the right of `k`.
-    pub right: Root<K, V>,
+    pub kv: (K, V),
+    // Owned, unattached, new node with elements and edges that belong to the right of `kv`.
+    pub right: NodeRef<marker::Owned, K, V, NodeType>,
+}
+
+impl<'a, K, V> SplitResult<'a, K, V, marker::Leaf> {
+    pub fn forget_node_type(self) -> SplitResult<'a, K, V, marker::LeafOrInternal> {
+        SplitResult { left: self.left.forget_type(), kv: self.kv, right: self.right.forget_type() }
+    }
+}
+
+impl<'a, K, V> SplitResult<'a, K, V, marker::Internal> {
+    pub fn forget_node_type(self) -> SplitResult<'a, K, V, marker::LeafOrInternal> {
+        SplitResult { left: self.left.forget_type(), kv: self.kv, right: self.right.forget_type() }
+    }
 }
 
-pub enum InsertResult<'a, K, V, Type> {
-    Fit(Handle<NodeRef<marker::Mut<'a>, K, V, Type>, marker::KV>),
-    Split(SplitResult<'a, K, V>),
+pub enum InsertResult<'a, K, V, NodeType> {
+    Fit(Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::KV>),
+    Split(SplitResult<'a, K, V, NodeType>),
 }
 
 pub mod marker {
index b04b29320ac988756eb6bc337ac35da52bdca65f..6886962106b02ea5dfd20c3df28f70c68a7af984 100644 (file)
@@ -74,16 +74,19 @@ fn test_splitpoint() {
 
 #[test]
 fn test_partial_cmp_eq() {
-    let mut root1: Root<i32, ()> = Root::new_leaf();
-    let mut leaf1 = unsafe { root1.leaf_node_as_mut() };
+    let mut root1 = NodeRef::new_leaf();
+    let mut leaf1 = root1.borrow_mut();
     leaf1.push(1, ());
+    let mut root1 = root1.forget_type();
     root1.push_internal_level();
-    let root2: Root<i32, ()> = Root::new_leaf();
+    let root2 = Root::new();
+    root1.reborrow().assert_back_pointers();
+    root2.reborrow().assert_back_pointers();
 
-    let leaf_edge_1a = root1.node_as_ref().first_leaf_edge().forget_node_type();
-    let leaf_edge_1b = root1.node_as_ref().last_leaf_edge().forget_node_type();
-    let top_edge_1 = root1.node_as_ref().first_edge();
-    let top_edge_2 = root2.node_as_ref().first_edge();
+    let leaf_edge_1a = root1.reborrow().first_leaf_edge().forget_node_type();
+    let leaf_edge_1b = root1.reborrow().last_leaf_edge().forget_node_type();
+    let top_edge_1 = root1.reborrow().first_edge();
+    let top_edge_2 = root2.reborrow().first_edge();
 
     assert!(leaf_edge_1a == leaf_edge_1a);
     assert!(leaf_edge_1a != leaf_edge_1b);
@@ -100,8 +103,8 @@ fn test_partial_cmp_eq() {
     assert_eq!(top_edge_1.partial_cmp(&top_edge_2), None);
 
     root1.pop_internal_level();
-    unsafe { root1.into_ref().deallocate_and_ascend() };
-    unsafe { root2.into_ref().deallocate_and_ascend() };
+    unsafe { root1.deallocate_and_ascend() };
+    unsafe { root2.deallocate_and_ascend() };
 }
 
 #[test]
index 701d5ec73e218ddfb38bcd2d73db6f40a8e8d4bb..93de2d829ac8d9c6249d5da7efe38131cafca51b 100644 (file)
@@ -50,7 +50,7 @@ pub fn search_node<BorrowType, K, V, Type, Q: ?Sized>(
 {
     match search_linear(&node, key) {
         (idx, true) => Found(unsafe { Handle::new_kv(node, idx) }),
-        (idx, false) => SearchResult::GoDown(unsafe { Handle::new_edge(node, idx) }),
+        (idx, false) => GoDown(unsafe { Handle::new_edge(node, idx) }),
     }
 }
 
index 1a807100653bc1a9270d679dd7107d9d824616de..f4046e87b99a85779ac74cd6a55e526a9d544213 100644 (file)
@@ -220,7 +220,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 const ITER_PERFORMANCE_TIPPING_SIZE_DIFF: usize = 16;
 
 impl<T: Ord> BTreeSet<T> {
-    /// Makes a new `BTreeSet` with a reasonable choice of B.
+    /// Makes a new, empty `BTreeSet`.
+    ///
+    /// Does not allocate anything on its own.
     ///
     /// # Examples
     ///
@@ -1121,7 +1123,7 @@ fn extend_one(&mut self, &elem: &'a T) {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> Default for BTreeSet<T> {
-    /// Makes an empty `BTreeSet<T>` with a reasonable choice of B.
+    /// Creates an empty `BTreeSet`.
     fn default() -> BTreeSet<T> {
         BTreeSet::new()
     }
index ef40a048a382ecccf8911610c8e9e64e13dc9f18..4d05bc4ebfa1e9aa5255d60f5103b123496f6504 100644 (file)
@@ -1,9 +1,10 @@
 use super::super::DeterministicRng;
 use super::*;
 use crate::vec::Vec;
+use std::cmp::Ordering;
 use std::iter::FromIterator;
 use std::panic::{catch_unwind, AssertUnwindSafe};
-use std::sync::atomic::{AtomicU32, Ordering};
+use std::sync::atomic::{AtomicU32, Ordering::SeqCst};
 
 #[test]
 fn test_clone_eq() {
@@ -355,7 +356,7 @@ fn test_drain_filter_drop_panic_leak() {
     struct D(i32);
     impl Drop for D {
         fn drop(&mut self) {
-            if DROPS.fetch_add(1, Ordering::SeqCst) == 1 {
+            if DROPS.fetch_add(1, SeqCst) == 1 {
                 panic!("panic in `drop`");
             }
         }
@@ -368,14 +369,14 @@ fn drop(&mut self) {
 
     catch_unwind(move || {
         drop(set.drain_filter(|d| {
-            PREDS.fetch_add(1u32 << d.0, Ordering::SeqCst);
+            PREDS.fetch_add(1u32 << d.0, SeqCst);
             true
         }))
     })
     .ok();
 
-    assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
-    assert_eq!(DROPS.load(Ordering::SeqCst), 3);
+    assert_eq!(PREDS.load(SeqCst), 0x011);
+    assert_eq!(DROPS.load(SeqCst), 3);
 }
 
 #[test]
@@ -387,7 +388,7 @@ fn test_drain_filter_pred_panic_leak() {
     struct D(i32);
     impl Drop for D {
         fn drop(&mut self) {
-            DROPS.fetch_add(1, Ordering::SeqCst);
+            DROPS.fetch_add(1, SeqCst);
         }
     }
 
@@ -398,7 +399,7 @@ fn drop(&mut self) {
 
     catch_unwind(AssertUnwindSafe(|| {
         drop(set.drain_filter(|d| {
-            PREDS.fetch_add(1u32 << d.0, Ordering::SeqCst);
+            PREDS.fetch_add(1u32 << d.0, SeqCst);
             match d.0 {
                 0 => true,
                 _ => panic!(),
@@ -407,8 +408,8 @@ fn drop(&mut self) {
     }))
     .ok();
 
-    assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
-    assert_eq!(DROPS.load(Ordering::SeqCst), 1);
+    assert_eq!(PREDS.load(SeqCst), 0x011);
+    assert_eq!(DROPS.load(SeqCst), 1);
     assert_eq!(set.len(), 2);
     assert_eq!(set.first().unwrap().0, 4);
     assert_eq!(set.last().unwrap().0, 8);
@@ -498,8 +499,6 @@ fn test_extend_ref() {
 
 #[test]
 fn test_recovery() {
-    use std::cmp::Ordering;
-
     #[derive(Debug)]
     struct Foo(&'static str, i32);
 
index cd9615a330df61c25c6f4e1a087843f24de19eac..701f36c37ee8884b47dcc93502ff23a80cd22a85 100644 (file)
@@ -9,7 +9,7 @@ pub fn split_off<Q: ?Sized + Ord>(&mut self, right_root: &mut Self, key: &Q)
         K: Borrow<Q>,
     {
         debug_assert!(right_root.height() == 0);
-        debug_assert!(right_root.node_as_ref().len() == 0);
+        debug_assert!(right_root.len() == 0);
 
         let left_root = self;
         for _ in 0..left_root.height() {
@@ -17,8 +17,8 @@ pub fn split_off<Q: ?Sized + Ord>(&mut self, right_root: &mut Self, key: &Q)
         }
 
         {
-            let mut left_node = left_root.node_as_mut();
-            let mut right_node = right_root.node_as_mut();
+            let mut left_node = left_root.borrow_mut();
+            let mut right_node = right_root.borrow_mut();
 
             loop {
                 let mut split_edge = match search_node(left_node, key) {
@@ -48,7 +48,7 @@ pub fn split_off<Q: ?Sized + Ord>(&mut self, right_root: &mut Self, key: &Q)
 
     /// Removes empty levels on the top, but keeps an empty leaf if the entire tree is empty.
     fn fix_top(&mut self) {
-        while self.height() > 0 && self.node_as_ref().len() == 0 {
+        while self.height() > 0 && self.len() == 0 {
             self.pop_internal_level();
         }
     }
@@ -57,7 +57,7 @@ fn fix_right_border(&mut self) {
         self.fix_top();
 
         {
-            let mut cur_node = self.node_as_mut();
+            let mut cur_node = self.borrow_mut();
 
             while let Internal(node) = cur_node.force() {
                 let mut last_kv = node.last_kv().consider_for_balancing();
@@ -83,7 +83,7 @@ fn fix_left_border(&mut self) {
         self.fix_top();
 
         {
-            let mut cur_node = self.node_as_mut();
+            let mut cur_node = self.borrow_mut();
 
             while let Internal(node) = cur_node.force() {
                 let mut first_kv = node.first_kv().consider_for_balancing();
index 1c183858e7a5e814554e2280568a78cd47ed9c85..85c809e0d188d7dfacfd9573eafe9f9ca8db3fa8 100644 (file)
@@ -1962,7 +1962,7 @@ pub fn remove(&mut self, index: usize) -> Option<T> {
     /// ```
     /// use std::collections::VecDeque;
     ///
-    /// let mut buf: VecDeque<_> = vec![1,2,3].into_iter().collect();
+    /// let mut buf: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
     /// let buf2 = buf.split_off(1);
     /// assert_eq!(buf, [1]);
     /// assert_eq!(buf2, [2, 3]);
@@ -2514,10 +2514,10 @@ pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize>
     ///          (3, 1), (1, 2), (2, 3), (4, 5), (5, 8), (3, 13),
     ///          (1, 21), (2, 34), (4, 55)].into();
     ///
-    /// assert_eq!(deque.binary_search_by_key(&13, |&(a,b)| b),  Ok(9));
-    /// assert_eq!(deque.binary_search_by_key(&4, |&(a,b)| b),   Err(7));
-    /// assert_eq!(deque.binary_search_by_key(&100, |&(a,b)| b), Err(13));
-    /// let r = deque.binary_search_by_key(&1, |&(a,b)| b);
+    /// assert_eq!(deque.binary_search_by_key(&13, |&(a, b)| b),  Ok(9));
+    /// assert_eq!(deque.binary_search_by_key(&4, |&(a, b)| b),   Err(7));
+    /// assert_eq!(deque.binary_search_by_key(&100, |&(a, b)| b), Err(13));
+    /// let r = deque.binary_search_by_key(&1, |&(a, b)| b);
     /// assert!(matches!(r, Ok(1..=4)));
     /// ```
     #[unstable(feature = "vecdeque_binary_search", issue = "78021")]
index f21fc8854d05e16af76539b0493fee70616a092b..3ac34c9ae28af271afe810bc5b357c5cd4604ddb 100644 (file)
@@ -72,7 +72,7 @@
 #![allow(explicit_outlives_requirements)]
 #![allow(incomplete_features)]
 #![deny(unsafe_op_in_unsafe_fn)]
-#![cfg_attr(not(bootstrap), feature(rustc_allow_const_fn_unstable))]
+#![feature(rustc_allow_const_fn_unstable)]
 #![cfg_attr(not(test), feature(generator_trait))]
 #![cfg_attr(test, feature(test))]
 #![cfg_attr(test, feature(new_uninit))]
 #![feature(never_type)]
 #![feature(nll)]
 #![feature(nonnull_slice_from_raw_parts)]
-#![feature(optin_builtin_traits)]
+#![cfg_attr(bootstrap, feature(optin_builtin_traits))]
+#![cfg_attr(not(bootstrap), feature(auto_traits))]
 #![feature(or_patterns)]
 #![feature(pattern)]
 #![feature(ptr_internals)]
 #![feature(unicode_internals)]
 #![feature(unsafe_block_in_unsafe_fn)]
 #![feature(unsize)]
-#![cfg_attr(not(bootstrap), feature(unsized_fn_params))]
-#![cfg_attr(bootstrap, feature(unsized_locals))]
+#![feature(unsized_fn_params)]
 #![feature(allocator_internals)]
 #![feature(slice_partition_dedup)]
 #![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_uninit_array)]
index 522c5bcf5af109004ccc61acf4ab4398915529ac..edab576bea8dda26299566ecc077e61500a59bbb 100644 (file)
@@ -116,8 +116,7 @@ pub unsafe fn from_raw_parts(ptr: *mut T, capacity: usize) -> Self {
 impl<T, A: AllocRef> RawVec<T, A> {
     /// Like `new`, but parameterized over the choice of allocator for
     /// the returned `RawVec`.
-    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn))]
-    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn))]
+    #[rustc_allow_const_fn_unstable(const_fn)]
     pub const fn new_in(alloc: A) -> Self {
         // `cap: 0` means "unallocated". zero-sized types are ignored.
         Self { ptr: Unique::dangling(), cap: 0, alloc }
@@ -233,15 +232,10 @@ pub fn capacity(&self) -> usize {
     }
 
     /// Returns a shared reference to the allocator backing this `RawVec`.
-    pub fn alloc(&self) -> &A {
+    pub fn alloc_ref(&self) -> &A {
         &self.alloc
     }
 
-    /// Returns a mutable reference to the allocator backing this `RawVec`.
-    pub fn alloc_mut(&mut self) -> &mut A {
-        &mut self.alloc
-    }
-
     fn current_memory(&self) -> Option<(NonNull<u8>, Layout)> {
         if mem::size_of::<T>() == 0 || self.cap == 0 {
             None
index 3db66964941c3dbd679115f5d6d259ee242aa9ec..949a3bb1d708c2067f51e5f1764d0e696b1fc9ce 100644 (file)
@@ -87,6 +87,7 @@
 use core::mem::{self, size_of};
 use core::ptr;
 
+use crate::alloc::{AllocRef, Global};
 use crate::borrow::ToOwned;
 use crate::boxed::Box;
 use crate::vec::Vec;
 // `core::slice::SliceExt` - we need to supply these functions for the
 // `test_permutations` test
 mod hack {
+    use core::alloc::AllocRef;
+
     use crate::boxed::Box;
     use crate::vec::Vec;
 
     // We shouldn't add inline attribute to this since this is used in
     // `vec!` macro mostly and causes perf regression. See #71204 for
     // discussion and perf results.
-    pub fn into_vec<T>(b: Box<[T]>) -> Vec<T> {
+    pub fn into_vec<T, A: AllocRef>(b: Box<[T], A>) -> Vec<T, A> {
         unsafe {
             let len = b.len();
-            let b = Box::into_raw(b);
-            Vec::from_raw_parts(b as *mut T, len, len)
+            let (b, alloc) = Box::into_raw_with_alloc(b);
+            Vec::from_raw_parts_in(b as *mut T, len, len, alloc)
         }
     }
 
     #[inline]
-    pub fn to_vec<T>(s: &[T]) -> Vec<T>
-    where
-        T: Clone,
-    {
-        let mut vec = Vec::with_capacity(s.len());
-        vec.extend_from_slice(s);
-        vec
+    pub fn to_vec<T: ConvertVec, A: AllocRef>(s: &[T], alloc: A) -> Vec<T, A> {
+        T::to_vec(s, alloc)
+    }
+
+    pub trait ConvertVec {
+        fn to_vec<A: AllocRef>(s: &[Self], alloc: A) -> Vec<Self, A>
+        where
+            Self: Sized;
+    }
+
+    impl<T: Clone> ConvertVec for T {
+        #[inline]
+        default fn to_vec<A: AllocRef>(s: &[Self], alloc: A) -> Vec<Self, A> {
+            struct DropGuard<'a, T, A: AllocRef> {
+                vec: &'a mut Vec<T, A>,
+                num_init: usize,
+            }
+            impl<'a, T, A: AllocRef> Drop for DropGuard<'a, T, A> {
+                #[inline]
+                fn drop(&mut self) {
+                    // SAFETY:
+                    // items were marked initialized in the loop below
+                    unsafe {
+                        self.vec.set_len(self.num_init);
+                    }
+                }
+            }
+            let mut vec = Vec::with_capacity_in(s.len(), alloc);
+            let mut guard = DropGuard { vec: &mut vec, num_init: 0 };
+            let slots = guard.vec.spare_capacity_mut();
+            // .take(slots.len()) is necessary for LLVM to remove bounds checks
+            // and has better codegen than zip.
+            for (i, b) in s.iter().enumerate().take(slots.len()) {
+                guard.num_init = i;
+                slots[i].write(b.clone());
+            }
+            core::mem::forget(guard);
+            // SAFETY:
+            // the vec was allocated and initialized above to at least this length.
+            unsafe {
+                vec.set_len(s.len());
+            }
+            vec
+        }
+    }
+
+    impl<T: Copy> ConvertVec for T {
+        #[inline]
+        fn to_vec<A: AllocRef>(s: &[Self], alloc: A) -> Vec<Self, A> {
+            let mut v = Vec::with_capacity_in(s.len(), alloc);
+            // SAFETY:
+            // allocated above with the capacity of `s`, and initialize to `s.len()` in
+            // ptr::copy_to_non_overlapping below.
+            unsafe {
+                s.as_ptr().copy_to_nonoverlapping(v.as_mut_ptr(), s.len());
+                v.set_len(s.len());
+            }
+            v
+        }
     }
 }
 
@@ -388,11 +443,33 @@ macro_rules! sort_by_key {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn to_vec(&self) -> Vec<T>
+    where
+        T: Clone,
+    {
+        self.to_vec_in(Global)
+    }
+
+    /// Copies `self` into a new `Vec` with an allocator.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(allocator_api)]
+    ///
+    /// use std::alloc::System;
+    ///
+    /// let s = [10, 40, 30];
+    /// let x = s.to_vec_in(System);
+    /// // Here, `s` and `x` can be modified independently.
+    /// ```
+    #[inline]
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    pub fn to_vec_in<A: AllocRef>(&self, alloc: A) -> Vec<T, A>
     where
         T: Clone,
     {
         // N.B., see the `hack` module in this file for more details.
-        hack::to_vec(self)
+        hack::to_vec(self, alloc)
     }
 
     /// Converts `self` into a vector without clones or allocation.
@@ -411,7 +488,7 @@ pub fn to_vec(&self) -> Vec<T>
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn into_vec(self: Box<Self>) -> Vec<T> {
+    pub fn into_vec<A: AllocRef>(self: Box<Self, A>) -> Vec<T, A> {
         // N.B., see the `hack` module in this file for more details.
         hack::into_vec(self)
     }
@@ -730,7 +807,7 @@ fn to_owned(&self) -> Vec<T> {
 
     #[cfg(test)]
     fn to_owned(&self) -> Vec<T> {
-        hack::to_vec(self)
+        hack::to_vec(self, Global)
     }
 
     fn clone_into(&self, target: &mut Vec<T>) {
index 2c8bc3d53ef76e2f25b4b2c78e54ecca866a79ab..5168792092823fd5111efd2cded686cf38e6b119 100644 (file)
@@ -68,6 +68,7 @@
 use core::ptr::{self, NonNull};
 use core::slice::{self, SliceIndex};
 
+use crate::alloc::{AllocRef, Global};
 use crate::borrow::{Cow, ToOwned};
 use crate::boxed::Box;
 use crate::collections::TryReserveError;
 /// [`&`]: ../../std/primitive.reference.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "vec_type")]
-pub struct Vec<T> {
-    buf: RawVec<T>,
+pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: AllocRef = Global> {
+    buf: RawVec<T, A>,
     len: usize,
 }
 
@@ -320,7 +321,7 @@ impl<T> Vec<T> {
     #[inline]
     #[rustc_const_stable(feature = "const_vec_new", since = "1.39.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub const fn new() -> Vec<T> {
+    pub const fn new() -> Self {
         Vec { buf: RawVec::NEW, len: 0 }
     }
 
@@ -359,49 +360,145 @@ pub const fn new() -> Vec<T> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn with_capacity(capacity: usize) -> Vec<T> {
-        Vec { buf: RawVec::with_capacity(capacity), len: 0 }
+    pub fn with_capacity(capacity: usize) -> Self {
+        Self::with_capacity_in(capacity, Global)
     }
 
-    /// Decomposes a `Vec<T>` into its raw components.
+    /// Creates a `Vec<T>` directly from the raw components of another vector.
     ///
-    /// Returns the raw pointer to the underlying data, the length of
-    /// the vector (in elements), and the allocated capacity of the
-    /// data (in elements). These are the same arguments in the same
-    /// order as the arguments to [`from_raw_parts`].
+    /// # Safety
     ///
-    /// After calling this function, the caller is responsible for the
-    /// memory previously managed by the `Vec`. The only way to do
-    /// this is to convert the raw pointer, length, and capacity back
-    /// into a `Vec` with the [`from_raw_parts`] function, allowing
-    /// the destructor to perform the cleanup.
+    /// This is highly unsafe, due to the number of invariants that aren't
+    /// checked:
     ///
-    /// [`from_raw_parts`]: Vec::from_raw_parts
+    /// * `ptr` needs to have been previously allocated via [`String`]/`Vec<T>`
+    ///   (at least, it's highly likely to be incorrect if it wasn't).
+    /// * `T` needs to have the same size and alignment as what `ptr` was allocated with.
+    ///   (`T` having a less strict alignment is not sufficient, the alignment really
+    ///   needs to be equal to satisfy the [`dealloc`] requirement that memory must be
+    ///   allocated and deallocated with the same layout.)
+    /// * `length` needs to be less than or equal to `capacity`.
+    /// * `capacity` needs to be the capacity that the pointer was allocated with.
+    ///
+    /// Violating these may cause problems like corrupting the allocator's
+    /// internal data structures. For example it is **not** safe
+    /// to build a `Vec<u8>` from a pointer to a C `char` array with length `size_t`.
+    /// It's also not safe to build one from a `Vec<u16>` and its length, because
+    /// the allocator cares about the alignment, and these two types have different
+    /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after
+    /// turning it into a `Vec<u8>` it'll be deallocated with alignment 1.
+    ///
+    /// The ownership of `ptr` is effectively transferred to the
+    /// `Vec<T>` which may then deallocate, reallocate or change the
+    /// contents of memory pointed to by the pointer at will. Ensure
+    /// that nothing else uses the pointer after calling this
+    /// function.
+    ///
+    /// [`String`]: crate::string::String
+    /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(vec_into_raw_parts)]
-    /// let v: Vec<i32> = vec![-1, 0, 1];
+    /// use std::ptr;
+    /// use std::mem;
     ///
-    /// let (ptr, len, cap) = v.into_raw_parts();
+    /// let v = vec![1, 2, 3];
     ///
-    /// let rebuilt = unsafe {
-    ///     // We can now make changes to the components, such as
-    ///     // transmuting the raw pointer to a compatible type.
-    ///     let ptr = ptr as *mut u32;
+    // FIXME Update this when vec_into_raw_parts is stabilized
+    /// // Prevent running `v`'s destructor so we are in complete control
+    /// // of the allocation.
+    /// let mut v = mem::ManuallyDrop::new(v);
     ///
-    ///     Vec::from_raw_parts(ptr, len, cap)
-    /// };
-    /// assert_eq!(rebuilt, [4294967295, 0, 1]);
+    /// // Pull out the various important pieces of information about `v`
+    /// let p = v.as_mut_ptr();
+    /// let len = v.len();
+    /// let cap = v.capacity();
+    ///
+    /// unsafe {
+    ///     // Overwrite memory with 4, 5, 6
+    ///     for i in 0..len as isize {
+    ///         ptr::write(p.offset(i), 4 + i);
+    ///     }
+    ///
+    ///     // Put everything back together into a Vec
+    ///     let rebuilt = Vec::from_raw_parts(p, len, cap);
+    ///     assert_eq!(rebuilt, [4, 5, 6]);
+    /// }
     /// ```
-    #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")]
-    pub fn into_raw_parts(self) -> (*mut T, usize, usize) {
-        let mut me = ManuallyDrop::new(self);
-        (me.as_mut_ptr(), me.len(), me.capacity())
+    #[inline]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Self {
+        unsafe { Self::from_raw_parts_in(ptr, length, capacity, Global) }
     }
+}
 
-    /// Creates a `Vec<T>` directly from the raw components of another vector.
+impl<T, A: AllocRef> Vec<T, A> {
+    /// Constructs a new, empty `Vec<T, A>`.
+    ///
+    /// The vector will not allocate until elements are pushed onto it.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(allocator_api)]
+    ///
+    /// use std::alloc::System;
+    ///
+    /// # #[allow(unused_mut)]
+    /// let mut vec: Vec<i32, _> = Vec::new_in(System);
+    /// ```
+    #[inline]
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    pub const fn new_in(alloc: A) -> Self {
+        Vec { buf: RawVec::new_in(alloc), len: 0 }
+    }
+
+    /// Constructs a new, empty `Vec<T, A>` with the specified capacity with the provided
+    /// allocator.
+    ///
+    /// The vector will be able to hold exactly `capacity` elements without
+    /// reallocating. If `capacity` is 0, the vector will not allocate.
+    ///
+    /// It is important to note that although the returned vector has the
+    /// *capacity* specified, the vector will have a zero *length*. For an
+    /// explanation of the difference between length and capacity, see
+    /// *[Capacity and reallocation]*.
+    ///
+    /// [Capacity and reallocation]: #capacity-and-reallocation
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(allocator_api)]
+    ///
+    /// use std::alloc::System;
+    ///
+    /// let mut vec = Vec::with_capacity_in(10, System);
+    ///
+    /// // The vector contains no items, even though it has capacity for more
+    /// assert_eq!(vec.len(), 0);
+    /// assert_eq!(vec.capacity(), 10);
+    ///
+    /// // These are all done without reallocating...
+    /// for i in 0..10 {
+    ///     vec.push(i);
+    /// }
+    /// assert_eq!(vec.len(), 10);
+    /// assert_eq!(vec.capacity(), 10);
+    ///
+    /// // ...but this may make the vector reallocate
+    /// vec.push(11);
+    /// assert_eq!(vec.len(), 11);
+    /// assert!(vec.capacity() >= 11);
+    /// ```
+    #[inline]
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
+        Vec { buf: RawVec::with_capacity_in(capacity, alloc), len: 0 }
+    }
+
+    /// Creates a `Vec<T, A>` directly from the raw components of another vector.
     ///
     /// # Safety
     ///
@@ -437,10 +534,17 @@ pub fn into_raw_parts(self) -> (*mut T, usize, usize) {
     /// # Examples
     ///
     /// ```
+    /// #![feature(allocator_api)]
+    ///
+    /// use std::alloc::System;
+    ///
     /// use std::ptr;
     /// use std::mem;
     ///
-    /// let v = vec![1, 2, 3];
+    /// let mut v = Vec::with_capacity_in(3, System);
+    /// v.push(1);
+    /// v.push(2);
+    /// v.push(3);
     ///
     // FIXME Update this when vec_into_raw_parts is stabilized
     /// // Prevent running `v`'s destructor so we are in complete control
@@ -451,6 +555,7 @@ pub fn into_raw_parts(self) -> (*mut T, usize, usize) {
     /// let p = v.as_mut_ptr();
     /// let len = v.len();
     /// let cap = v.capacity();
+    /// let alloc = v.alloc_ref();
     ///
     /// unsafe {
     ///     // Overwrite memory with 4, 5, 6
@@ -459,13 +564,100 @@ pub fn into_raw_parts(self) -> (*mut T, usize, usize) {
     ///     }
     ///
     ///     // Put everything back together into a Vec
-    ///     let rebuilt = Vec::from_raw_parts(p, len, cap);
+    ///     let rebuilt = Vec::from_raw_parts_in(p, len, cap, alloc.clone());
     ///     assert_eq!(rebuilt, [4, 5, 6]);
     /// }
     /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Vec<T> {
-        unsafe { Vec { buf: RawVec::from_raw_parts(ptr, capacity), len: length } }
+    #[inline]
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    pub unsafe fn from_raw_parts_in(ptr: *mut T, length: usize, capacity: usize, alloc: A) -> Self {
+        unsafe { Vec { buf: RawVec::from_raw_parts_in(ptr, capacity, alloc), len: length } }
+    }
+
+    /// Decomposes a `Vec<T>` into its raw components.
+    ///
+    /// Returns the raw pointer to the underlying data, the length of
+    /// the vector (in elements), and the allocated capacity of the
+    /// data (in elements). These are the same arguments in the same
+    /// order as the arguments to [`from_raw_parts`].
+    ///
+    /// After calling this function, the caller is responsible for the
+    /// memory previously managed by the `Vec`. The only way to do
+    /// this is to convert the raw pointer, length, and capacity back
+    /// into a `Vec` with the [`from_raw_parts`] function, allowing
+    /// the destructor to perform the cleanup.
+    ///
+    /// [`from_raw_parts`]: Vec::from_raw_parts
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(vec_into_raw_parts)]
+    /// let v: Vec<i32> = vec![-1, 0, 1];
+    ///
+    /// let (ptr, len, cap) = v.into_raw_parts();
+    ///
+    /// let rebuilt = unsafe {
+    ///     // We can now make changes to the components, such as
+    ///     // transmuting the raw pointer to a compatible type.
+    ///     let ptr = ptr as *mut u32;
+    ///
+    ///     Vec::from_raw_parts(ptr, len, cap)
+    /// };
+    /// assert_eq!(rebuilt, [4294967295, 0, 1]);
+    /// ```
+    #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")]
+    pub fn into_raw_parts(self) -> (*mut T, usize, usize) {
+        let mut me = ManuallyDrop::new(self);
+        (me.as_mut_ptr(), me.len(), me.capacity())
+    }
+
+    /// Decomposes a `Vec<T>` into its raw components.
+    ///
+    /// Returns the raw pointer to the underlying data, the length of the vector (in elements),
+    /// the allocated capacity of the data (in elements), and the allocator. These are the same
+    /// arguments in the same order as the arguments to [`from_raw_parts_in`].
+    ///
+    /// After calling this function, the caller is responsible for the
+    /// memory previously managed by the `Vec`. The only way to do
+    /// this is to convert the raw pointer, length, and capacity back
+    /// into a `Vec` with the [`from_raw_parts_in`] function, allowing
+    /// the destructor to perform the cleanup.
+    ///
+    /// [`from_raw_parts_in`]: Vec::from_raw_parts_in
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(allocator_api, vec_into_raw_parts)]
+    ///
+    /// use std::alloc::System;
+    ///
+    /// let mut v: Vec<i32, System> = Vec::new_in(System);
+    /// v.push(-1);
+    /// v.push(0);
+    /// v.push(1);
+    ///
+    /// let (ptr, len, cap, alloc) = v.into_raw_parts_with_alloc();
+    ///
+    /// let rebuilt = unsafe {
+    ///     // We can now make changes to the components, such as
+    ///     // transmuting the raw pointer to a compatible type.
+    ///     let ptr = ptr as *mut u32;
+    ///
+    ///     Vec::from_raw_parts_in(ptr, len, cap, alloc)
+    /// };
+    /// assert_eq!(rebuilt, [4294967295, 0, 1]);
+    /// ```
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    // #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")]
+    pub fn into_raw_parts_with_alloc(self) -> (*mut T, usize, usize, A) {
+        let mut me = ManuallyDrop::new(self);
+        let len = me.len();
+        let capacity = me.capacity();
+        let ptr = me.as_mut_ptr();
+        let alloc = unsafe { ptr::read(me.alloc_ref()) };
+        (ptr, len, capacity, alloc)
     }
 
     /// Returns the number of elements the vector can hold without
@@ -684,7 +876,7 @@ pub fn shrink_to(&mut self, min_capacity: usize) {
     /// assert_eq!(slice.into_vec().capacity(), 3);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn into_boxed_slice(mut self) -> Box<[T]> {
+    pub fn into_boxed_slice(mut self) -> Box<[T], A> {
         unsafe {
             self.shrink_to_fit();
             let me = ManuallyDrop::new(self);
@@ -849,7 +1041,7 @@ pub fn as_ptr(&self) -> *const T {
     ///     }
     ///     x.set_len(size);
     /// }
-    /// assert_eq!(&*x, &[0,1,2,3]);
+    /// assert_eq!(&*x, &[0, 1, 2, 3]);
     /// ```
     #[stable(feature = "vec_as_ptr", since = "1.37.0")]
     #[inline]
@@ -863,6 +1055,13 @@ pub fn as_mut_ptr(&mut self) -> *mut T {
         ptr
     }
 
+    /// Returns a reference to the underlying allocator.
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    #[inline]
+    pub fn alloc_ref(&self) -> &A {
+        self.buf.alloc_ref()
+    }
+
     /// Forces the length of the vector to `new_len`.
     ///
     /// This is a low-level operation that maintains none of the normal
@@ -1299,7 +1498,7 @@ unsafe fn append_elements(&mut self, other: *const [T]) {
     /// assert_eq!(v, &[]);
     /// ```
     #[stable(feature = "drain", since = "1.6.0")]
-    pub fn drain<R>(&mut self, range: R) -> Drain<'_, T>
+    pub fn drain<R>(&mut self, range: R) -> Drain<'_, T, A>
     where
         R: RangeBounds<usize>,
     {
@@ -1395,7 +1594,7 @@ pub fn is_empty(&self) -> bool {
     /// # Examples
     ///
     /// ```
-    /// let mut vec = vec![1,2,3];
+    /// let mut vec = vec![1, 2, 3];
     /// let vec2 = vec.split_off(1);
     /// assert_eq!(vec, [1]);
     /// assert_eq!(vec2, [2, 3]);
@@ -1403,7 +1602,10 @@ pub fn is_empty(&self) -> bool {
     #[inline]
     #[must_use = "use `.truncate()` if you don't need the other half"]
     #[stable(feature = "split_off", since = "1.4.0")]
-    pub fn split_off(&mut self, at: usize) -> Self {
+    pub fn split_off(&mut self, at: usize) -> Self
+    where
+        A: Clone,
+    {
         #[cold]
         #[inline(never)]
         fn assert_failed(at: usize, len: usize) -> ! {
@@ -1416,11 +1618,14 @@ fn assert_failed(at: usize, len: usize) -> ! {
 
         if at == 0 {
             // the new vector can take over the original buffer and avoid the copy
-            return mem::replace(self, Vec::with_capacity(self.capacity()));
+            return mem::replace(
+                self,
+                Vec::with_capacity_in(self.capacity(), self.alloc_ref().clone()),
+            );
         }
 
         let other_len = self.len - at;
-        let mut other = Vec::with_capacity(other_len);
+        let mut other = Vec::with_capacity_in(other_len, self.alloc_ref().clone());
 
         // Unsafely `set_len` and copy items to `other`.
         unsafe {
@@ -1497,7 +1702,7 @@ pub fn resize_with<F>(&mut self, new_len: usize, f: F)
     #[inline]
     pub fn leak<'a>(self) -> &'a mut [T]
     where
-        T: 'a, // Technically not needed, but kept to be explicit.
+        A: 'a,
     {
         Box::leak(self.into_boxed_slice())
     }
@@ -1544,7 +1749,7 @@ pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<T>] {
     }
 }
 
-impl<T: Clone> Vec<T> {
+impl<T: Clone, A: AllocRef> Vec<T, A> {
     /// Resizes the `Vec` in-place so that `len` is equal to `new_len`.
     ///
     /// If `new_len` is greater than `len`, the `Vec` is extended by the
@@ -1639,7 +1844,7 @@ fn last(mut self) -> T {
     }
 }
 
-impl<T> Vec<T> {
+impl<T, A: AllocRef> Vec<T, A> {
     /// Extend the vector by `n` values, using the given generator.
     fn extend_with<E: ExtendWith<T>>(&mut self, n: usize, mut value: E) {
         self.reserve(n);
@@ -1699,7 +1904,7 @@ fn drop(&mut self) {
     }
 }
 
-impl<T: PartialEq> Vec<T> {
+impl<T: PartialEq, A: AllocRef> Vec<T, A> {
     /// Removes consecutive repeated elements in the vector according to the
     /// [`PartialEq`] trait implementation.
     ///
@@ -1721,7 +1926,7 @@ pub fn dedup(&mut self) {
     }
 }
 
-impl<T> Vec<T> {
+impl<T, A: AllocRef> Vec<T, A> {
     /// Removes the first instance of `item` from the vector if the item exists.
     ///
     /// This method will be removed soon.
@@ -1749,17 +1954,23 @@ pub fn remove_item<V>(&mut self, item: &V) -> Option<T>
 #[doc(hidden)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn from_elem<T: Clone>(elem: T, n: usize) -> Vec<T> {
-    <T as SpecFromElem>::from_elem(elem, n)
+    <T as SpecFromElem>::from_elem(elem, n, Global)
+}
+
+#[doc(hidden)]
+#[unstable(feature = "allocator_api", issue = "32838")]
+pub fn from_elem_in<T: Clone, A: AllocRef>(elem: T, n: usize, alloc: A) -> Vec<T, A> {
+    <T as SpecFromElem>::from_elem(elem, n, alloc)
 }
 
 // Specialization trait used for Vec::from_elem
 trait SpecFromElem: Sized {
-    fn from_elem(elem: Self, n: usize) -> Vec<Self>;
+    fn from_elem<A: AllocRef>(elem: Self, n: usize, alloc: A) -> Vec<Self, A>;
 }
 
 impl<T: Clone> SpecFromElem for T {
-    default fn from_elem(elem: Self, n: usize) -> Vec<Self> {
-        let mut v = Vec::with_capacity(n);
+    default fn from_elem<A: AllocRef>(elem: Self, n: usize, alloc: A) -> Vec<Self, A> {
+        let mut v = Vec::with_capacity_in(n, alloc);
         v.extend_with(n, ExtendElement(elem));
         v
     }
@@ -1767,12 +1978,12 @@ impl<T: Clone> SpecFromElem for T {
 
 impl SpecFromElem for i8 {
     #[inline]
-    fn from_elem(elem: i8, n: usize) -> Vec<i8> {
+    fn from_elem<A: AllocRef>(elem: i8, n: usize, alloc: A) -> Vec<i8, A> {
         if elem == 0 {
-            return Vec { buf: RawVec::with_capacity_zeroed(n), len: n };
+            return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n };
         }
         unsafe {
-            let mut v = Vec::with_capacity(n);
+            let mut v = Vec::with_capacity_in(n, alloc);
             ptr::write_bytes(v.as_mut_ptr(), elem as u8, n);
             v.set_len(n);
             v
@@ -1782,12 +1993,12 @@ fn from_elem(elem: i8, n: usize) -> Vec<i8> {
 
 impl SpecFromElem for u8 {
     #[inline]
-    fn from_elem(elem: u8, n: usize) -> Vec<u8> {
+    fn from_elem<A: AllocRef>(elem: u8, n: usize, alloc: A) -> Vec<u8, A> {
         if elem == 0 {
-            return Vec { buf: RawVec::with_capacity_zeroed(n), len: n };
+            return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n };
         }
         unsafe {
-            let mut v = Vec::with_capacity(n);
+            let mut v = Vec::with_capacity_in(n, alloc);
             ptr::write_bytes(v.as_mut_ptr(), elem, n);
             v.set_len(n);
             v
@@ -1797,11 +2008,11 @@ fn from_elem(elem: u8, n: usize) -> Vec<u8> {
 
 impl<T: Clone + IsZero> SpecFromElem for T {
     #[inline]
-    fn from_elem(elem: T, n: usize) -> Vec<T> {
+    fn from_elem<A: AllocRef>(elem: T, n: usize, alloc: A) -> Vec<T, A> {
         if elem.is_zero() {
-            return Vec { buf: RawVec::with_capacity_zeroed(n), len: n };
+            return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n };
         }
-        let mut v = Vec::with_capacity(n);
+        let mut v = Vec::with_capacity_in(n, alloc);
         v.extend_with(n, ExtendElement(elem));
         v
     }
@@ -1882,7 +2093,7 @@ fn is_zero(&self) -> bool {
 ////////////////////////////////////////////////////////////////////////////////
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> ops::Deref for Vec<T> {
+impl<T, A: AllocRef> ops::Deref for Vec<T, A> {
     type Target = [T];
 
     fn deref(&self) -> &[T] {
@@ -1891,17 +2102,18 @@ fn deref(&self) -> &[T] {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> ops::DerefMut for Vec<T> {
+impl<T, A: AllocRef> ops::DerefMut for Vec<T, A> {
     fn deref_mut(&mut self) -> &mut [T] {
         unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) }
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Clone> Clone for Vec<T> {
+impl<T: Clone, A: AllocRef + Clone> Clone for Vec<T, A> {
     #[cfg(not(test))]
-    fn clone(&self) -> Vec<T> {
-        <[T]>::to_vec(&**self)
+    fn clone(&self) -> Self {
+        let alloc = self.alloc_ref().clone();
+        <[T]>::to_vec_in(&**self, alloc)
     }
 
     // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is
@@ -1909,17 +2121,27 @@ fn clone(&self) -> Vec<T> {
     // `slice::to_vec`  function which is only available with cfg(test)
     // NB see the slice::hack module in slice.rs for more information
     #[cfg(test)]
-    fn clone(&self) -> Vec<T> {
-        crate::slice::to_vec(&**self)
+    fn clone(&self) -> Self {
+        let alloc = self.alloc_ref().clone();
+        crate::slice::to_vec(&**self, alloc)
     }
 
-    fn clone_from(&mut self, other: &Vec<T>) {
-        other.as_slice().clone_into(self);
+    fn clone_from(&mut self, other: &Self) {
+        // drop anything that will not be overwritten
+        self.truncate(other.len());
+
+        // self.len <= other.len due to the truncate above, so the
+        // slices here are always in-bounds.
+        let (init, tail) = other.split_at(self.len());
+
+        // reuse the contained values' allocations/resources.
+        self.clone_from_slice(init);
+        self.extend_from_slice(tail);
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Hash> Hash for Vec<T> {
+impl<T: Hash, A: AllocRef> Hash for Vec<T, A> {
     #[inline]
     fn hash<H: Hasher>(&self, state: &mut H) {
         Hash::hash(&**self, state)
@@ -1931,7 +2153,7 @@ fn hash<H: Hasher>(&self, state: &mut H) {
     message = "vector indices are of type `usize` or ranges of `usize`",
     label = "vector indices are of type `usize` or ranges of `usize`"
 )]
-impl<T, I: SliceIndex<[T]>> Index<I> for Vec<T> {
+impl<T, I: SliceIndex<[T]>, A: AllocRef> Index<I> for Vec<T, A> {
     type Output = I::Output;
 
     #[inline]
@@ -1945,7 +2167,7 @@ fn index(&self, index: I) -> &Self::Output {
     message = "vector indices are of type `usize` or ranges of `usize`",
     label = "vector indices are of type `usize` or ranges of `usize`"
 )]
-impl<T, I: SliceIndex<[T]>> IndexMut<I> for Vec<T> {
+impl<T, I: SliceIndex<[T]>, A: AllocRef> IndexMut<I> for Vec<T, A> {
     #[inline]
     fn index_mut(&mut self, index: I) -> &mut Self::Output {
         IndexMut::index_mut(&mut **self, index)
@@ -1961,9 +2183,9 @@ fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Vec<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> IntoIterator for Vec<T> {
+impl<T, A: AllocRef> IntoIterator for Vec<T, A> {
     type Item = T;
-    type IntoIter = IntoIter<T>;
+    type IntoIter = IntoIter<T, A>;
 
     /// Creates a consuming iterator, that is, one that moves each value out of
     /// the vector (from start to end). The vector cannot be used after calling
@@ -1979,9 +2201,10 @@ impl<T> IntoIterator for Vec<T> {
     /// }
     /// ```
     #[inline]
-    fn into_iter(self) -> IntoIter<T> {
+    fn into_iter(self) -> IntoIter<T, A> {
         unsafe {
             let mut me = ManuallyDrop::new(self);
+            let alloc = ptr::read(me.alloc_ref());
             let begin = me.as_mut_ptr();
             let end = if mem::size_of::<T>() == 0 {
                 arith_offset(begin as *const i8, me.len() as isize) as *const T
@@ -1993,6 +2216,7 @@ fn into_iter(self) -> IntoIter<T> {
                 buf: NonNull::new_unchecked(begin),
                 phantom: PhantomData,
                 cap,
+                alloc,
                 ptr: begin,
                 end,
             }
@@ -2001,7 +2225,7 @@ fn into_iter(self) -> IntoIter<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> IntoIterator for &'a Vec<T> {
+impl<'a, T, A: AllocRef> IntoIterator for &'a Vec<T, A> {
     type Item = &'a T;
     type IntoIter = slice::Iter<'a, T>;
 
@@ -2011,7 +2235,7 @@ fn into_iter(self) -> slice::Iter<'a, T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> IntoIterator for &'a mut Vec<T> {
+impl<'a, T, A: AllocRef> IntoIterator for &'a mut Vec<T, A> {
     type Item = &'a mut T;
     type IntoIter = slice::IterMut<'a, T>;
 
@@ -2021,7 +2245,7 @@ fn into_iter(self) -> slice::IterMut<'a, T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Extend<T> for Vec<T> {
+impl<T, A: AllocRef> Extend<T> for Vec<T, A> {
     #[inline]
     fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
         <Self as SpecExtend<T, I::IntoIter>>::spec_extend(self, iter.into_iter())
@@ -2284,17 +2508,23 @@ impl<'a, T: 'a, I> SpecFromIter<&'a T, I> for Vec<T>
     }
 }
 
-impl<'a, T: 'a> SpecFromIter<&'a T, slice::Iter<'a, T>> for Vec<T>
-where
-    T: Copy,
-{
-    // reuses the extend specialization for T: Copy
+// This utilizes `iterator.as_slice().to_vec()` since spec_extend
+// must take more steps to reason about the final capacity + length
+// and thus do more work. `to_vec()` directly allocates the correct amount
+// and fills it exactly.
+impl<'a, T: 'a + Clone> SpecFromIter<&'a T, slice::Iter<'a, T>> for Vec<T> {
+    #[cfg(not(test))]
     fn from_iter(iterator: slice::Iter<'a, T>) -> Self {
-        let mut vec = Vec::new();
-        // must delegate to spec_extend() since extend() itself delegates
-        // to spec_from for empty Vecs
-        vec.spec_extend(iterator);
-        vec
+        iterator.as_slice().to_vec()
+    }
+
+    // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is
+    // required for this method definition, is not available. Instead use the
+    // `slice::to_vec`  function which is only available with cfg(test)
+    // NB see the slice::hack module in slice.rs for more information
+    #[cfg(test)]
+    fn from_iter(iterator: slice::Iter<'a, T>) -> Self {
+        crate::slice::to_vec(iterator.as_slice(), Global)
     }
 }
 
@@ -2303,7 +2533,7 @@ trait SpecExtend<T, I> {
     fn spec_extend(&mut self, iter: I);
 }
 
-impl<T, I> SpecExtend<T, I> for Vec<T>
+impl<T, I, A: AllocRef> SpecExtend<T, I> for Vec<T, A>
 where
     I: Iterator<Item = T>,
 {
@@ -2312,7 +2542,7 @@ impl<T, I> SpecExtend<T, I> for Vec<T>
     }
 }
 
-impl<T, I> SpecExtend<T, I> for Vec<T>
+impl<T, I, A: AllocRef> SpecExtend<T, I> for Vec<T, A>
 where
     I: TrustedLen<Item = T>,
 {
@@ -2345,7 +2575,7 @@ impl<T, I> SpecExtend<T, I> for Vec<T>
     }
 }
 
-impl<T> SpecExtend<T, IntoIter<T>> for Vec<T> {
+impl<T, A: AllocRef> SpecExtend<T, IntoIter<T>> for Vec<T, A> {
     fn spec_extend(&mut self, mut iterator: IntoIter<T>) {
         unsafe {
             self.append_elements(iterator.as_slice() as _);
@@ -2354,7 +2584,7 @@ fn spec_extend(&mut self, mut iterator: IntoIter<T>) {
     }
 }
 
-impl<'a, T: 'a, I> SpecExtend<&'a T, I> for Vec<T>
+impl<'a, T: 'a, I, A: AllocRef + 'a> SpecExtend<&'a T, I> for Vec<T, A>
 where
     I: Iterator<Item = &'a T>,
     T: Clone,
@@ -2364,7 +2594,7 @@ impl<'a, T: 'a, I> SpecExtend<&'a T, I> for Vec<T>
     }
 }
 
-impl<'a, T: 'a> SpecExtend<&'a T, slice::Iter<'a, T>> for Vec<T>
+impl<'a, T: 'a, A: AllocRef + 'a> SpecExtend<&'a T, slice::Iter<'a, T>> for Vec<T, A>
 where
     T: Copy,
 {
@@ -2374,7 +2604,7 @@ fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) {
     }
 }
 
-impl<T> Vec<T> {
+impl<T, A: AllocRef> Vec<T, A> {
     // leaf method to which various SpecFrom/SpecExtend implementations delegate when
     // they have no further optimizations to apply
     fn extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) {
@@ -2434,7 +2664,7 @@ fn extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) {
     /// ```
     #[inline]
     #[stable(feature = "vec_splice", since = "1.21.0")]
-    pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter>
+    pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter, A>
     where
         R: RangeBounds<usize>,
         I: IntoIterator<Item = T>,
@@ -2487,7 +2717,7 @@ pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoI
     /// assert_eq!(odds, vec![1, 3, 5, 9, 11, 13, 15]);
     /// ```
     #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
-    pub fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<'_, T, F>
+    pub fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<'_, T, F, A>
     where
         F: FnMut(&mut T) -> bool,
     {
@@ -2509,7 +2739,7 @@ pub fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<'_, T, F>
 ///
 /// [`copy_from_slice`]: ../../std/primitive.slice.html#method.copy_from_slice
 #[stable(feature = "extend_ref", since = "1.2.0")]
-impl<'a, T: 'a + Copy> Extend<&'a T> for Vec<T> {
+impl<'a, T: Copy + 'a, A: AllocRef + 'a> Extend<&'a T> for Vec<T, A> {
     fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
         self.spec_extend(iter.into_iter())
     }
@@ -2528,9 +2758,9 @@ fn extend_reserve(&mut self, additional: usize) {
 macro_rules! __impl_slice_eq1 {
     ([$($vars:tt)*] $lhs:ty, $rhs:ty $(where $ty:ty: $bound:ident)?, #[$stability:meta]) => {
         #[$stability]
-        impl<A, B, $($vars)*> PartialEq<$rhs> for $lhs
+        impl<T, U, $($vars)*> PartialEq<$rhs> for $lhs
         where
-            A: PartialEq<B>,
+            T: PartialEq<U>,
             $($ty: $bound)?
         {
             #[inline]
@@ -2541,18 +2771,18 @@ fn ne(&self, other: &$rhs) -> bool { self[..] != other[..] }
     }
 }
 
-__impl_slice_eq1! { [] Vec<A>, Vec<B>, #[stable(feature = "rust1", since = "1.0.0")] }
-__impl_slice_eq1! { [] Vec<A>, &[B], #[stable(feature = "rust1", since = "1.0.0")] }
-__impl_slice_eq1! { [] Vec<A>, &mut [B], #[stable(feature = "rust1", since = "1.0.0")] }
-__impl_slice_eq1! { [] &[A], Vec<B>, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] }
-__impl_slice_eq1! { [] &mut [A], Vec<B>, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] }
-__impl_slice_eq1! { [] Vec<A>, [B], #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")]  }
-__impl_slice_eq1! { [] [A], Vec<B>, #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")]  }
-__impl_slice_eq1! { [] Cow<'_, [A]>, Vec<B> where A: Clone, #[stable(feature = "rust1", since = "1.0.0")] }
-__impl_slice_eq1! { [] Cow<'_, [A]>, &[B] where A: Clone, #[stable(feature = "rust1", since = "1.0.0")] }
-__impl_slice_eq1! { [] Cow<'_, [A]>, &mut [B] where A: Clone, #[stable(feature = "rust1", since = "1.0.0")] }
-__impl_slice_eq1! { [const N: usize] Vec<A>, [B; N], #[stable(feature = "rust1", since = "1.0.0")] }
-__impl_slice_eq1! { [const N: usize] Vec<A>, &[B; N], #[stable(feature = "rust1", since = "1.0.0")] }
+__impl_slice_eq1! { [A: AllocRef] Vec<T, A>, Vec<U, A>, #[stable(feature = "rust1", since = "1.0.0")] }
+__impl_slice_eq1! { [A: AllocRef] Vec<T, A>, &[U], #[stable(feature = "rust1", since = "1.0.0")] }
+__impl_slice_eq1! { [A: AllocRef] Vec<T, A>, &mut [U], #[stable(feature = "rust1", since = "1.0.0")] }
+__impl_slice_eq1! { [A: AllocRef] &[T], Vec<U, A>, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] }
+__impl_slice_eq1! { [A: AllocRef] &mut [T], Vec<U, A>, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] }
+__impl_slice_eq1! { [A: AllocRef] Vec<T, A>, [U], #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")]  }
+__impl_slice_eq1! { [A: AllocRef] [T], Vec<U, A>, #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")]  }
+__impl_slice_eq1! { [A: AllocRef] Cow<'_, [T]>, Vec<U, A> where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] }
+__impl_slice_eq1! { [] Cow<'_, [T]>, &[U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] }
+__impl_slice_eq1! { [] Cow<'_, [T]>, &mut [U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] }
+__impl_slice_eq1! { [A: AllocRef, const N: usize] Vec<T, A>, [U; N], #[stable(feature = "rust1", since = "1.0.0")] }
+__impl_slice_eq1! { [A: AllocRef, const N: usize] Vec<T, A>, &[U; N], #[stable(feature = "rust1", since = "1.0.0")] }
 
 // NOTE: some less important impls are omitted to reduce code bloat
 // FIXME(Centril): Reconsider this?
@@ -2566,27 +2796,27 @@ fn ne(&self, other: &$rhs) -> bool { self[..] != other[..] }
 
 /// Implements comparison of vectors, [lexicographically](core::cmp::Ord#lexicographical-comparison).
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: PartialOrd> PartialOrd for Vec<T> {
+impl<T: PartialOrd, A: AllocRef> PartialOrd for Vec<T, A> {
     #[inline]
-    fn partial_cmp(&self, other: &Vec<T>) -> Option<Ordering> {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
         PartialOrd::partial_cmp(&**self, &**other)
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Eq> Eq for Vec<T> {}
+impl<T: Eq, A: AllocRef> Eq for Vec<T, A> {}
 
 /// Implements ordering of vectors, [lexicographically](core::cmp::Ord#lexicographical-comparison).
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Ord> Ord for Vec<T> {
+impl<T: Ord, A: AllocRef> Ord for Vec<T, A> {
     #[inline]
-    fn cmp(&self, other: &Vec<T>) -> Ordering {
+    fn cmp(&self, other: &Self) -> Ordering {
         Ord::cmp(&**self, &**other)
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<#[may_dangle] T> Drop for Vec<T> {
+unsafe impl<#[may_dangle] T, A: AllocRef> Drop for Vec<T, A> {
     fn drop(&mut self) {
         unsafe {
             // use drop for [T]
@@ -2607,35 +2837,35 @@ fn default() -> Vec<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: fmt::Debug> fmt::Debug for Vec<T> {
+impl<T: fmt::Debug, A: AllocRef> fmt::Debug for Vec<T, A> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Debug::fmt(&**self, f)
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> AsRef<Vec<T>> for Vec<T> {
-    fn as_ref(&self) -> &Vec<T> {
+impl<T, A: AllocRef> AsRef<Vec<T, A>> for Vec<T, A> {
+    fn as_ref(&self) -> &Vec<T, A> {
         self
     }
 }
 
 #[stable(feature = "vec_as_mut", since = "1.5.0")]
-impl<T> AsMut<Vec<T>> for Vec<T> {
-    fn as_mut(&mut self) -> &mut Vec<T> {
+impl<T, A: AllocRef> AsMut<Vec<T, A>> for Vec<T, A> {
+    fn as_mut(&mut self) -> &mut Vec<T, A> {
         self
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> AsRef<[T]> for Vec<T> {
+impl<T, A: AllocRef> AsRef<[T]> for Vec<T, A> {
     fn as_ref(&self) -> &[T] {
         self
     }
 }
 
 #[stable(feature = "vec_as_mut", since = "1.5.0")]
-impl<T> AsMut<[T]> for Vec<T> {
+impl<T, A: AllocRef> AsMut<[T]> for Vec<T, A> {
     fn as_mut(&mut self) -> &mut [T] {
         self
     }
@@ -2649,7 +2879,7 @@ fn from(s: &[T]) -> Vec<T> {
     }
     #[cfg(test)]
     fn from(s: &[T]) -> Vec<T> {
-        crate::slice::to_vec(s)
+        crate::slice::to_vec(s, Global)
     }
 }
 
@@ -2661,7 +2891,7 @@ fn from(s: &mut [T]) -> Vec<T> {
     }
     #[cfg(test)]
     fn from(s: &mut [T]) -> Vec<T> {
-        crate::slice::to_vec(s)
+        crate::slice::to_vec(s, Global)
     }
 }
 
@@ -2690,17 +2920,18 @@ fn from(s: Cow<'a, [T]>) -> Vec<T> {
 // note: test pulls in libstd, which causes errors here
 #[cfg(not(test))]
 #[stable(feature = "vec_from_box", since = "1.18.0")]
-impl<T> From<Box<[T]>> for Vec<T> {
-    fn from(s: Box<[T]>) -> Vec<T> {
-        s.into_vec()
+impl<T, A: AllocRef> From<Box<[T], A>> for Vec<T, A> {
+    fn from(s: Box<[T], A>) -> Self {
+        let len = s.len();
+        Self { buf: RawVec::from_box(s), len }
     }
 }
 
 // note: test pulls in libstd, which causes errors here
 #[cfg(not(test))]
 #[stable(feature = "box_from_vec", since = "1.20.0")]
-impl<T> From<Vec<T>> for Box<[T]> {
-    fn from(v: Vec<T>) -> Box<[T]> {
+impl<T, A: AllocRef> From<Vec<T, A>> for Box<[T], A> {
+    fn from(v: Vec<T, A>) -> Self {
         v.into_boxed_slice()
     }
 }
@@ -2713,8 +2944,8 @@ fn from(s: &str) -> Vec<u8> {
 }
 
 #[stable(feature = "array_try_from_vec", since = "1.48.0")]
-impl<T, const N: usize> TryFrom<Vec<T>> for [T; N] {
-    type Error = Vec<T>;
+impl<T, A: AllocRef, const N: usize> TryFrom<Vec<T, A>> for [T; N] {
+    type Error = Vec<T, A>;
 
     /// Gets the entire contents of the `Vec<T>` as an array,
     /// if its size exactly matches that of the requested array.
@@ -2745,7 +2976,7 @@ fn from(s: &str) -> Vec<u8> {
     /// assert_eq!(a, b' ');
     /// assert_eq!(b, b'd');
     /// ```
-    fn try_from(mut vec: Vec<T>) -> Result<[T; N], Vec<T>> {
+    fn try_from(mut vec: Vec<T, A>) -> Result<[T; N], Vec<T, A>> {
         if vec.len() != N {
             return Err(vec);
         }
@@ -2814,22 +3045,24 @@ fn from_iter<I: IntoIterator<Item = T>>(it: I) -> Cow<'a, [T]> {
 /// let iter: std::vec::IntoIter<_> = v.into_iter();
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct IntoIter<T> {
+pub struct IntoIter<T, #[unstable(feature = "allocator_api", issue = "32838")] A: AllocRef = Global>
+{
     buf: NonNull<T>,
     phantom: PhantomData<T>,
     cap: usize,
+    alloc: A,
     ptr: *const T,
     end: *const T,
 }
 
 #[stable(feature = "vec_intoiter_debug", since = "1.13.0")]
-impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
+impl<T: fmt::Debug, A: AllocRef> fmt::Debug for IntoIter<T, A> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
     }
 }
 
-impl<T> IntoIter<T> {
+impl<T, A: AllocRef> IntoIter<T, A> {
     /// Returns the remaining items of this iterator as a slice.
     ///
     /// # Examples
@@ -2864,6 +3097,13 @@ pub fn as_mut_slice(&mut self) -> &mut [T] {
         unsafe { &mut *self.as_raw_mut_slice() }
     }
 
+    /// Returns a reference to the underlying allocator.
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    #[inline]
+    pub fn alloc_ref(&self) -> &A {
+        &self.alloc
+    }
+
     fn as_raw_mut_slice(&mut self) -> *mut [T] {
         ptr::slice_from_raw_parts_mut(self.ptr as *mut T, self.len())
     }
@@ -2886,19 +3126,19 @@ fn forget_allocation(&mut self) {
 }
 
 #[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")]
-impl<T> AsRef<[T]> for IntoIter<T> {
+impl<T, A: AllocRef> AsRef<[T]> for IntoIter<T, A> {
     fn as_ref(&self) -> &[T] {
         self.as_slice()
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<T: Send> Send for IntoIter<T> {}
+unsafe impl<T: Send, A: AllocRef + Send> Send for IntoIter<T, A> {}
 #[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<T: Sync> Sync for IntoIter<T> {}
+unsafe impl<T: Sync, A: AllocRef> Sync for IntoIter<T, A> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Iterator for IntoIter<T> {
+impl<T, A: AllocRef> Iterator for IntoIter<T, A> {
     type Item = T;
 
     #[inline]
@@ -2955,7 +3195,7 @@ unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> Self::Item
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> DoubleEndedIterator for IntoIter<T> {
+impl<T, A: AllocRef> DoubleEndedIterator for IntoIter<T, A> {
     #[inline]
     fn next_back(&mut self) -> Option<T> {
         if self.end == self.ptr {
@@ -2975,23 +3215,23 @@ fn next_back(&mut self) -> Option<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> ExactSizeIterator for IntoIter<T> {
+impl<T, A: AllocRef> ExactSizeIterator for IntoIter<T, A> {
     fn is_empty(&self) -> bool {
         self.ptr == self.end
     }
 }
 
 #[stable(feature = "fused", since = "1.26.0")]
-impl<T> FusedIterator for IntoIter<T> {}
+impl<T, A: AllocRef> FusedIterator for IntoIter<T, A> {}
 
 #[unstable(feature = "trusted_len", issue = "37572")]
-unsafe impl<T> TrustedLen for IntoIter<T> {}
+unsafe impl<T, A: AllocRef> TrustedLen for IntoIter<T, A> {}
 
 #[doc(hidden)]
 #[unstable(issue = "none", feature = "std_internals")]
 // T: Copy as approximation for !Drop since get_unchecked does not advance self.ptr
 // and thus we can't implement drop-handling
-unsafe impl<T> TrustedRandomAccess for IntoIter<T>
+unsafe impl<T, A: AllocRef> TrustedRandomAccess for IntoIter<T, A>
 where
     T: Copy,
 {
@@ -3001,21 +3241,30 @@ fn may_have_side_effect() -> bool {
 }
 
 #[stable(feature = "vec_into_iter_clone", since = "1.8.0")]
-impl<T: Clone> Clone for IntoIter<T> {
-    fn clone(&self) -> IntoIter<T> {
-        self.as_slice().to_owned().into_iter()
+impl<T: Clone, A: AllocRef + Clone> Clone for IntoIter<T, A> {
+    #[cfg(not(test))]
+    fn clone(&self) -> Self {
+        self.as_slice().to_vec_in(self.alloc.clone()).into_iter()
+    }
+    #[cfg(test)]
+    fn clone(&self) -> Self {
+        crate::slice::to_vec(self.as_slice(), self.alloc.clone()).into_iter()
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<#[may_dangle] T> Drop for IntoIter<T> {
+unsafe impl<#[may_dangle] T, A: AllocRef> Drop for IntoIter<T, A> {
     fn drop(&mut self) {
-        struct DropGuard<'a, T>(&'a mut IntoIter<T>);
+        struct DropGuard<'a, T, A: AllocRef>(&'a mut IntoIter<T, A>);
 
-        impl<T> Drop for DropGuard<'_, T> {
+        impl<T, A: AllocRef> Drop for DropGuard<'_, T, A> {
             fn drop(&mut self) {
-                // RawVec handles deallocation
-                let _ = unsafe { RawVec::from_raw_parts(self.0.buf.as_ptr(), self.0.cap) };
+                unsafe {
+                    // `IntoIter::alloc` is not used anymore after this
+                    let alloc = ptr::read(&self.0.alloc);
+                    // RawVec handles deallocation
+                    let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc);
+                }
             }
         }
 
@@ -3029,11 +3278,11 @@ fn drop(&mut self) {
 }
 
 #[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T> InPlaceIterable for IntoIter<T> {}
+unsafe impl<T, A: AllocRef> InPlaceIterable for IntoIter<T, A> {}
 
 #[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T> SourceIter for IntoIter<T> {
-    type Source = IntoIter<T>;
+unsafe impl<T, A: AllocRef> SourceIter for IntoIter<T, A> {
+    type Source = Self;
 
     #[inline]
     unsafe fn as_inner(&mut self) -> &mut Self::Source {
@@ -3068,24 +3317,28 @@ fn as_into_iter(&mut self) -> &mut IntoIter<Self::Item> {
 /// let iter: std::vec::Drain<_> = v.drain(..);
 /// ```
 #[stable(feature = "drain", since = "1.6.0")]
-pub struct Drain<'a, T: 'a> {
+pub struct Drain<
+    'a,
+    T: 'a,
+    #[unstable(feature = "allocator_api", issue = "32838")] A: AllocRef + 'a = Global,
+> {
     /// Index of tail to preserve
     tail_start: usize,
     /// Length of tail
     tail_len: usize,
     /// Current remaining range to remove
     iter: slice::Iter<'a, T>,
-    vec: NonNull<Vec<T>>,
+    vec: NonNull<Vec<T, A>>,
 }
 
 #[stable(feature = "collection_debug", since = "1.17.0")]
-impl<T: fmt::Debug> fmt::Debug for Drain<'_, T> {
+impl<T: fmt::Debug, A: AllocRef> fmt::Debug for Drain<'_, T, A> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_tuple("Drain").field(&self.iter.as_slice()).finish()
     }
 }
 
-impl<'a, T> Drain<'a, T> {
+impl<'a, T, A: AllocRef> Drain<'a, T, A> {
     /// Returns the remaining items of this iterator as a slice.
     ///
     /// # Examples
@@ -3101,22 +3354,29 @@ impl<'a, T> Drain<'a, T> {
     pub fn as_slice(&self) -> &[T] {
         self.iter.as_slice()
     }
+
+    /// Returns a reference to the underlying allocator.
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    #[inline]
+    pub fn alloc_ref(&self) -> &A {
+        unsafe { self.vec.as_ref().alloc_ref() }
+    }
 }
 
 #[stable(feature = "vec_drain_as_slice", since = "1.46.0")]
-impl<'a, T> AsRef<[T]> for Drain<'a, T> {
+impl<'a, T, A: AllocRef> AsRef<[T]> for Drain<'a, T, A> {
     fn as_ref(&self) -> &[T] {
         self.as_slice()
     }
 }
 
 #[stable(feature = "drain", since = "1.6.0")]
-unsafe impl<T: Sync> Sync for Drain<'_, T> {}
+unsafe impl<T: Sync, A: Sync + AllocRef> Sync for Drain<'_, T, A> {}
 #[stable(feature = "drain", since = "1.6.0")]
-unsafe impl<T: Send> Send for Drain<'_, T> {}
+unsafe impl<T: Send, A: Send + AllocRef> Send for Drain<'_, T, A> {}
 
 #[stable(feature = "drain", since = "1.6.0")]
-impl<T> Iterator for Drain<'_, T> {
+impl<T, A: AllocRef> Iterator for Drain<'_, T, A> {
     type Item = T;
 
     #[inline]
@@ -3130,7 +3390,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 }
 
 #[stable(feature = "drain", since = "1.6.0")]
-impl<T> DoubleEndedIterator for Drain<'_, T> {
+impl<T, A: AllocRef> DoubleEndedIterator for Drain<'_, T, A> {
     #[inline]
     fn next_back(&mut self) -> Option<T> {
         self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) })
@@ -3138,13 +3398,13 @@ fn next_back(&mut self) -> Option<T> {
 }
 
 #[stable(feature = "drain", since = "1.6.0")]
-impl<T> Drop for Drain<'_, T> {
+impl<T, A: AllocRef> Drop for Drain<'_, T, A> {
     fn drop(&mut self) {
         /// Continues dropping the remaining elements in the `Drain`, then moves back the
         /// un-`Drain`ed elements to restore the original `Vec`.
-        struct DropGuard<'r, 'a, T>(&'r mut Drain<'a, T>);
+        struct DropGuard<'r, 'a, T, A: AllocRef>(&'r mut Drain<'a, T, A>);
 
-        impl<'r, 'a, T> Drop for DropGuard<'r, 'a, T> {
+        impl<'r, 'a, T, A: AllocRef> Drop for DropGuard<'r, 'a, T, A> {
             fn drop(&mut self) {
                 // Continue the same loop we have below. If the loop already finished, this does
                 // nothing.
@@ -3180,17 +3440,17 @@ fn drop(&mut self) {
 }
 
 #[stable(feature = "drain", since = "1.6.0")]
-impl<T> ExactSizeIterator for Drain<'_, T> {
+impl<T, A: AllocRef> ExactSizeIterator for Drain<'_, T, A> {
     fn is_empty(&self) -> bool {
         self.iter.is_empty()
     }
 }
 
 #[unstable(feature = "trusted_len", issue = "37572")]
-unsafe impl<T> TrustedLen for Drain<'_, T> {}
+unsafe impl<T, A: AllocRef> TrustedLen for Drain<'_, T, A> {}
 
 #[stable(feature = "fused", since = "1.26.0")]
-impl<T> FusedIterator for Drain<'_, T> {}
+impl<T, A: AllocRef> FusedIterator for Drain<'_, T, A> {}
 
 /// A splicing iterator for `Vec`.
 ///
@@ -3206,13 +3466,17 @@ impl<T> FusedIterator for Drain<'_, T> {}
 /// ```
 #[derive(Debug)]
 #[stable(feature = "vec_splice", since = "1.21.0")]
-pub struct Splice<'a, I: Iterator + 'a> {
-    drain: Drain<'a, I::Item>,
+pub struct Splice<
+    'a,
+    I: Iterator + 'a,
+    #[unstable(feature = "allocator_api", issue = "32838")] A: AllocRef + 'a = Global,
+> {
+    drain: Drain<'a, I::Item, A>,
     replace_with: I,
 }
 
 #[stable(feature = "vec_splice", since = "1.21.0")]
-impl<I: Iterator> Iterator for Splice<'_, I> {
+impl<I: Iterator, A: AllocRef> Iterator for Splice<'_, I, A> {
     type Item = I::Item;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -3225,17 +3489,17 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 }
 
 #[stable(feature = "vec_splice", since = "1.21.0")]
-impl<I: Iterator> DoubleEndedIterator for Splice<'_, I> {
+impl<I: Iterator, A: AllocRef> DoubleEndedIterator for Splice<'_, I, A> {
     fn next_back(&mut self) -> Option<Self::Item> {
         self.drain.next_back()
     }
 }
 
 #[stable(feature = "vec_splice", since = "1.21.0")]
-impl<I: Iterator> ExactSizeIterator for Splice<'_, I> {}
+impl<I: Iterator, A: AllocRef> ExactSizeIterator for Splice<'_, I, A> {}
 
 #[stable(feature = "vec_splice", since = "1.21.0")]
-impl<I: Iterator> Drop for Splice<'_, I> {
+impl<I: Iterator, A: AllocRef> Drop for Splice<'_, I, A> {
     fn drop(&mut self) {
         self.drain.by_ref().for_each(drop);
 
@@ -3276,7 +3540,7 @@ fn drop(&mut self) {
 }
 
 /// Private helper methods for `Splice::drop`
-impl<T> Drain<'_, T> {
+impl<T, A: AllocRef> Drain<'_, T, A> {
     /// The range from `self.vec.len` to `self.tail_start` contains elements
     /// that have been moved out.
     /// Fill that range as much as possible with new elements from the `replace_with` iterator.
@@ -3331,11 +3595,15 @@ unsafe fn move_tail(&mut self, additional: usize) {
 /// ```
 #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
 #[derive(Debug)]
-pub struct DrainFilter<'a, T, F>
-where
+pub struct DrainFilter<
+    'a,
+    T,
+    F,
+    #[unstable(feature = "allocator_api", issue = "32838")] A: AllocRef = Global,
+> where
     F: FnMut(&mut T) -> bool,
 {
-    vec: &'a mut Vec<T>,
+    vec: &'a mut Vec<T, A>,
     /// The index of the item that will be inspected by the next call to `next`.
     idx: usize,
     /// The number of items that have been drained (removed) thus far.
@@ -3352,8 +3620,20 @@ pub struct DrainFilter<'a, T, F>
     panic_flag: bool,
 }
 
+impl<T, F, A: AllocRef> DrainFilter<'_, T, F, A>
+where
+    F: FnMut(&mut T) -> bool,
+{
+    /// Returns a reference to the underlying allocator.
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    #[inline]
+    pub fn alloc_ref(&self) -> &A {
+        self.vec.alloc_ref()
+    }
+}
+
 #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
-impl<T, F> Iterator for DrainFilter<'_, T, F>
+impl<T, F, A: AllocRef> Iterator for DrainFilter<'_, T, F, A>
 where
     F: FnMut(&mut T) -> bool,
 {
@@ -3391,19 +3671,19 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 }
 
 #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
-impl<T, F> Drop for DrainFilter<'_, T, F>
+impl<T, F, A: AllocRef> Drop for DrainFilter<'_, T, F, A>
 where
     F: FnMut(&mut T) -> bool,
 {
     fn drop(&mut self) {
-        struct BackshiftOnDrop<'a, 'b, T, F>
+        struct BackshiftOnDrop<'a, 'b, T, F, A: AllocRef>
         where
             F: FnMut(&mut T) -> bool,
         {
-            drain: &'b mut DrainFilter<'a, T, F>,
+            drain: &'b mut DrainFilter<'a, T, F, A>,
         }
 
-        impl<'a, 'b, T, F> Drop for BackshiftOnDrop<'a, 'b, T, F>
+        impl<'a, 'b, T, F, A: AllocRef> Drop for BackshiftOnDrop<'a, 'b, T, F, A>
         where
             F: FnMut(&mut T) -> bool,
         {
index 47ebe56f9fd3bcfc379e7a2dd7e2c87877905341..e19406d7a069737a2019de90db0003bad46d6952 100644 (file)
@@ -919,7 +919,7 @@ fn test_from_iter_partially_drained_in_place_specialization() {
 
 #[test]
 fn test_from_iter_specialization_with_iterator_adapters() {
-    fn assert_in_place_trait<T: InPlaceIterable>(_: &T) {};
+    fn assert_in_place_trait<T: InPlaceIterable>(_: &T) {}
     let src: Vec<usize> = vec![0usize; 256];
     let srcptr = src.as_ptr();
     let iter = src
@@ -1198,7 +1198,7 @@ fn drain_filter_consumed_panic() {
     struct Check {
         index: usize,
         drop_counts: Rc<Mutex<Vec<usize>>>,
-    };
+    }
 
     impl Drop for Check {
         fn drop(&mut self) {
@@ -1250,7 +1250,7 @@ fn drain_filter_unconsumed_panic() {
     struct Check {
         index: usize,
         drop_counts: Rc<Mutex<Vec<usize>>>,
-    };
+    }
 
     impl Drop for Check {
         fn drop(&mut self) {
index 8b8ea53b56f519dd7780defdd4254daaec892584..af078ecc0b069ec594982f92d4c6c58af99efbb5 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 8b8ea53b56f519dd7780defdd4254daaec892584
+Subproject commit af078ecc0b069ec594982f92d4c6c58af99efbb5
index 2258d9614d53b767bef6d17652481e59d87bb360..339d85902b83f06e8da0ef0a2f2a2a7d6852fb3a 100644 (file)
@@ -50,7 +50,7 @@ impl Layout {
     ///    must not overflow (i.e., the rounded value must be less than
     ///    or equal to `usize::MAX`).
     #[stable(feature = "alloc_layout", since = "1.28.0")]
-    #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
+    #[rustc_const_stable(feature = "const_alloc_layout", since = "1.50.0")]
     #[inline]
     pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutError> {
         if !align.is_power_of_two() {
@@ -96,7 +96,7 @@ pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutEr
 
     /// The minimum size in bytes for a memory block of this layout.
     #[stable(feature = "alloc_layout", since = "1.28.0")]
-    #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
+    #[rustc_const_stable(feature = "const_alloc_layout", since = "1.50.0")]
     #[inline]
     pub const fn size(&self) -> usize {
         self.size_
@@ -104,7 +104,7 @@ pub const fn size(&self) -> usize {
 
     /// The minimum byte alignment for a memory block of this layout.
     #[stable(feature = "alloc_layout", since = "1.28.0")]
-    #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
+    #[rustc_const_stable(feature = "const_alloc_layout", since = "1.50.0")]
     #[inline]
     pub const fn align(&self) -> usize {
         self.align_.get()
index cafb002c01a1106433f5e5647adafb3936f524fd..706f865b4d14f1fd9fbe4573dc473a2c3f696876 100644 (file)
@@ -69,7 +69,8 @@ impl<T, const N: usize> IntoIter<T, N> {
 
     /// Returns an immutable slice of all elements that have not been yielded
     /// yet.
-    fn as_slice(&self) -> &[T] {
+    #[unstable(feature = "array_value_iter_slice", issue = "65798")]
+    pub fn as_slice(&self) -> &[T] {
         // SAFETY: We know that all elements within `alive` are properly initialized.
         unsafe {
             let slice = self.data.get_unchecked(self.alive.clone());
@@ -78,7 +79,8 @@ fn as_slice(&self) -> &[T] {
     }
 
     /// Returns a mutable slice of all elements that have not been yielded yet.
-    fn as_mut_slice(&mut self) -> &mut [T] {
+    #[unstable(feature = "array_value_iter_slice", issue = "65798")]
+    pub fn as_mut_slice(&mut self) -> &mut [T] {
         // SAFETY: We know that all elements within `alive` are properly initialized.
         unsafe {
             let slice = self.data.get_unchecked_mut(self.alive.clone());
index 6e0865e8653b7cfb769f62dbdb2dd6042ef20130..00164c631b305799cd760426cdfda0f08c752433 100644 (file)
@@ -23,12 +23,10 @@ pub fn then_some<T>(self, t: T) -> Option<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(bool_to_option)]
-    ///
     /// assert_eq!(false.then(|| 0), None);
     /// assert_eq!(true.then(|| 0), Some(0));
     /// ```
-    #[unstable(feature = "bool_to_option", issue = "64260")]
+    #[stable(feature = "lazy_bool_to_option", since = "1.50.0")]
     #[inline]
     pub fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
         if self { Some(f()) } else { None }
index b2afb702eeb86f65e242a5d8426691fc8528edf3..e1b6307613b7303e9e9e541869270330b9ab1da0 100644 (file)
@@ -1027,7 +1027,6 @@ impl<T: Default> RefCell<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(refcell_take)]
     /// use std::cell::RefCell;
     ///
     /// let c = RefCell::new(5);
@@ -1036,7 +1035,7 @@ impl<T: Default> RefCell<T> {
     /// assert_eq!(five, 5);
     /// assert_eq!(c.into_inner(), 0);
     /// ```
-    #[unstable(feature = "refcell_take", issue = "71395")]
+    #[stable(feature = "refcell_take", since = "1.50.0")]
     pub fn take(&self) -> T {
         self.replace(Default::default())
     }
index bbb3a3dea435ec67e15c969622974bc8c9650787..47ae1a64190edde757f573e9535b928bd2acc651 100644 (file)
@@ -641,14 +641,12 @@ fn min(self, other: Self) -> Self
     /// # Examples
     ///
     /// ```
-    /// #![feature(clamp)]
-    ///
     /// assert!((-3).clamp(-2, 1) == -2);
     /// assert!(0.clamp(-2, 1) == 0);
     /// assert!(2.clamp(-2, 1) == 1);
     /// ```
     #[must_use]
-    #[unstable(feature = "clamp", issue = "44095")]
+    #[stable(feature = "clamp", since = "1.50.0")]
     fn clamp(self, min: Self, max: Self) -> Self
     where
         Self: Sized,
index 506d77806868215828708f419b45d15b8093b9ca..23e8d1d856a30aaa4e2c7b844baea43d19b87b88 100644 (file)
@@ -1182,7 +1182,7 @@ fn wrap_buf<'b, 'c, F>(&'b mut self, wrap: F) -> Formatter<'c>
     /// ```
     /// use std::fmt;
     ///
-    /// struct Foo { nb: i32 };
+    /// struct Foo { nb: i32 }
     ///
     /// impl Foo {
     ///     fn new(nb: i32) -> Foo {
index f302cda09e721166e2d6929402d46e621aa5db4c..af63e1bb097b8c18e4bd2dd8507bc5947fb34b1f 100644 (file)
@@ -21,7 +21,7 @@
 ///
 /// let read_future = poll_fn(read_line);
 /// assert_eq!(read_future.await, "Hello, World!".to_owned());
-/// # };
+/// # }
 /// ```
 #[unstable(feature = "future_poll_fn", issue = "72302")]
 pub fn poll_fn<T, F>(f: F) -> PollFn<F>
index 433f0129306bda281086245c5400fd2b3d4b4d62..5a5aa76a076272210aef2da9248f209f1e896592 100644 (file)
     /// let num_leading = unsafe { ctlz_nonzero(x) };
     /// assert_eq!(num_leading, 3);
     /// ```
-    #[rustc_const_unstable(feature = "constctlz", issue = "none")]
+    #[rustc_const_stable(feature = "constctlz", since = "1.50.0")]
     pub fn ctlz_nonzero<T: Copy>(x: T) -> T;
 
     /// Returns the number of trailing unset bits (zeroes) in an integer type `T`.
index 2e070d71224422b9bb0e190e802a2d5fd1de0084..9753e1b43ba956aac96fc6c70d7c173ff316a4f4 100644 (file)
@@ -1,6 +1,5 @@
 use crate::iter::{DoubleEndedIterator, FusedIterator, Iterator, TrustedLen};
-use crate::ops::Try;
-use crate::usize;
+use crate::{ops::Try, usize};
 
 /// An iterator that links two iterators together, in a chain.
 ///
diff --git a/library/core/src/iter/adapters/cloned.rs b/library/core/src/iter/adapters/cloned.rs
new file mode 100644 (file)
index 0000000..7da47dc
--- /dev/null
@@ -0,0 +1,139 @@
+use crate::iter::adapters::{zip::try_get_unchecked, TrustedRandomAccess};
+use crate::iter::{FusedIterator, TrustedLen};
+use crate::ops::Try;
+
+/// An iterator that clones the elements of an underlying iterator.
+///
+/// This `struct` is created by the [`cloned`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`cloned`]: Iterator::cloned
+/// [`Iterator`]: trait.Iterator.html
+#[stable(feature = "iter_cloned", since = "1.1.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[derive(Clone, Debug)]
+pub struct Cloned<I> {
+    it: I,
+}
+
+impl<I> Cloned<I> {
+    pub(in crate::iter) fn new(it: I) -> Cloned<I> {
+        Cloned { it }
+    }
+}
+
+fn clone_try_fold<T: Clone, Acc, R>(mut f: impl FnMut(Acc, T) -> R) -> impl FnMut(Acc, &T) -> R {
+    move |acc, elt| f(acc, elt.clone())
+}
+
+#[stable(feature = "iter_cloned", since = "1.1.0")]
+impl<'a, I, T: 'a> Iterator for Cloned<I>
+where
+    I: Iterator<Item = &'a T>,
+    T: Clone,
+{
+    type Item = T;
+
+    fn next(&mut self) -> Option<T> {
+        self.it.next().cloned()
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.it.size_hint()
+    }
+
+    fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
+    where
+        Self: Sized,
+        F: FnMut(B, Self::Item) -> R,
+        R: Try<Ok = B>,
+    {
+        self.it.try_fold(init, clone_try_fold(f))
+    }
+
+    fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
+    where
+        F: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.it.map(T::clone).fold(init, f)
+    }
+
+    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
+    where
+        Self: TrustedRandomAccess,
+    {
+        // SAFETY: the caller must uphold the contract for
+        // `Iterator::__iterator_get_unchecked`.
+        unsafe { try_get_unchecked(&mut self.it, idx).clone() }
+    }
+}
+
+#[stable(feature = "iter_cloned", since = "1.1.0")]
+impl<'a, I, T: 'a> DoubleEndedIterator for Cloned<I>
+where
+    I: DoubleEndedIterator<Item = &'a T>,
+    T: Clone,
+{
+    fn next_back(&mut self) -> Option<T> {
+        self.it.next_back().cloned()
+    }
+
+    fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
+    where
+        Self: Sized,
+        F: FnMut(B, Self::Item) -> R,
+        R: Try<Ok = B>,
+    {
+        self.it.try_rfold(init, clone_try_fold(f))
+    }
+
+    fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
+    where
+        F: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.it.map(T::clone).rfold(init, f)
+    }
+}
+
+#[stable(feature = "iter_cloned", since = "1.1.0")]
+impl<'a, I, T: 'a> ExactSizeIterator for Cloned<I>
+where
+    I: ExactSizeIterator<Item = &'a T>,
+    T: Clone,
+{
+    fn len(&self) -> usize {
+        self.it.len()
+    }
+
+    fn is_empty(&self) -> bool {
+        self.it.is_empty()
+    }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<'a, I, T: 'a> FusedIterator for Cloned<I>
+where
+    I: FusedIterator<Item = &'a T>,
+    T: Clone,
+{
+}
+
+#[doc(hidden)]
+#[unstable(feature = "trusted_random_access", issue = "none")]
+unsafe impl<I> TrustedRandomAccess for Cloned<I>
+where
+    I: TrustedRandomAccess,
+{
+    #[inline]
+    fn may_have_side_effect() -> bool {
+        true
+    }
+}
+
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<'a, I, T: 'a> TrustedLen for Cloned<I>
+where
+    I: TrustedLen<Item = &'a T>,
+    T: Clone,
+{
+}
diff --git a/library/core/src/iter/adapters/copied.rs b/library/core/src/iter/adapters/copied.rs
new file mode 100644 (file)
index 0000000..46f2235
--- /dev/null
@@ -0,0 +1,155 @@
+use crate::iter::adapters::{zip::try_get_unchecked, TrustedRandomAccess};
+use crate::iter::{FusedIterator, TrustedLen};
+use crate::ops::Try;
+
+/// An iterator that copies the elements of an underlying iterator.
+///
+/// This `struct` is created by the [`copied`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`copied`]: Iterator::copied
+/// [`Iterator`]: trait.Iterator.html
+#[stable(feature = "iter_copied", since = "1.36.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[derive(Clone, Debug)]
+pub struct Copied<I> {
+    it: I,
+}
+
+impl<I> Copied<I> {
+    pub(in crate::iter) fn new(it: I) -> Copied<I> {
+        Copied { it }
+    }
+}
+
+fn copy_fold<T: Copy, Acc>(mut f: impl FnMut(Acc, T) -> Acc) -> impl FnMut(Acc, &T) -> Acc {
+    move |acc, &elt| f(acc, elt)
+}
+
+fn copy_try_fold<T: Copy, Acc, R>(mut f: impl FnMut(Acc, T) -> R) -> impl FnMut(Acc, &T) -> R {
+    move |acc, &elt| f(acc, elt)
+}
+
+#[stable(feature = "iter_copied", since = "1.36.0")]
+impl<'a, I, T: 'a> Iterator for Copied<I>
+where
+    I: Iterator<Item = &'a T>,
+    T: Copy,
+{
+    type Item = T;
+
+    fn next(&mut self) -> Option<T> {
+        self.it.next().copied()
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.it.size_hint()
+    }
+
+    fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
+    where
+        Self: Sized,
+        F: FnMut(B, Self::Item) -> R,
+        R: Try<Ok = B>,
+    {
+        self.it.try_fold(init, copy_try_fold(f))
+    }
+
+    fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
+    where
+        F: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.it.fold(init, copy_fold(f))
+    }
+
+    fn nth(&mut self, n: usize) -> Option<T> {
+        self.it.nth(n).copied()
+    }
+
+    fn last(self) -> Option<T> {
+        self.it.last().copied()
+    }
+
+    fn count(self) -> usize {
+        self.it.count()
+    }
+
+    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
+    where
+        Self: TrustedRandomAccess,
+    {
+        // SAFETY: the caller must uphold the contract for
+        // `Iterator::__iterator_get_unchecked`.
+        *unsafe { try_get_unchecked(&mut self.it, idx) }
+    }
+}
+
+#[stable(feature = "iter_copied", since = "1.36.0")]
+impl<'a, I, T: 'a> DoubleEndedIterator for Copied<I>
+where
+    I: DoubleEndedIterator<Item = &'a T>,
+    T: Copy,
+{
+    fn next_back(&mut self) -> Option<T> {
+        self.it.next_back().copied()
+    }
+
+    fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
+    where
+        Self: Sized,
+        F: FnMut(B, Self::Item) -> R,
+        R: Try<Ok = B>,
+    {
+        self.it.try_rfold(init, copy_try_fold(f))
+    }
+
+    fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
+    where
+        F: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.it.rfold(init, copy_fold(f))
+    }
+}
+
+#[stable(feature = "iter_copied", since = "1.36.0")]
+impl<'a, I, T: 'a> ExactSizeIterator for Copied<I>
+where
+    I: ExactSizeIterator<Item = &'a T>,
+    T: Copy,
+{
+    fn len(&self) -> usize {
+        self.it.len()
+    }
+
+    fn is_empty(&self) -> bool {
+        self.it.is_empty()
+    }
+}
+
+#[stable(feature = "iter_copied", since = "1.36.0")]
+impl<'a, I, T: 'a> FusedIterator for Copied<I>
+where
+    I: FusedIterator<Item = &'a T>,
+    T: Copy,
+{
+}
+
+#[doc(hidden)]
+#[unstable(feature = "trusted_random_access", issue = "none")]
+unsafe impl<I> TrustedRandomAccess for Copied<I>
+where
+    I: TrustedRandomAccess,
+{
+    #[inline]
+    fn may_have_side_effect() -> bool {
+        I::may_have_side_effect()
+    }
+}
+
+#[stable(feature = "iter_copied", since = "1.36.0")]
+unsafe impl<'a, I, T: 'a> TrustedLen for Copied<I>
+where
+    I: TrustedLen<Item = &'a T>,
+    T: Copy,
+{
+}
diff --git a/library/core/src/iter/adapters/cycle.rs b/library/core/src/iter/adapters/cycle.rs
new file mode 100644 (file)
index 0000000..6e9a011
--- /dev/null
@@ -0,0 +1,87 @@
+use crate::{iter::FusedIterator, ops::Try};
+
+/// An iterator that repeats endlessly.
+///
+/// This `struct` is created by the [`cycle`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`cycle`]: Iterator::cycle
+/// [`Iterator`]: trait.Iterator.html
+#[derive(Clone, Debug)]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Cycle<I> {
+    orig: I,
+    iter: I,
+}
+
+impl<I: Clone> Cycle<I> {
+    pub(in crate::iter) fn new(iter: I) -> Cycle<I> {
+        Cycle { orig: iter.clone(), iter }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I> Iterator for Cycle<I>
+where
+    I: Clone + Iterator,
+{
+    type Item = <I as Iterator>::Item;
+
+    #[inline]
+    fn next(&mut self) -> Option<<I as Iterator>::Item> {
+        match self.iter.next() {
+            None => {
+                self.iter = self.orig.clone();
+                self.iter.next()
+            }
+            y => y,
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        // the cycle iterator is either empty or infinite
+        match self.orig.size_hint() {
+            sz @ (0, Some(0)) => sz,
+            (0, _) => (0, None),
+            _ => (usize::MAX, None),
+        }
+    }
+
+    #[inline]
+    fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
+    where
+        F: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        // fully iterate the current iterator. this is necessary because
+        // `self.iter` may be empty even when `self.orig` isn't
+        acc = self.iter.try_fold(acc, &mut f)?;
+        self.iter = self.orig.clone();
+
+        // complete a full cycle, keeping track of whether the cycled
+        // iterator is empty or not. we need to return early in case
+        // of an empty iterator to prevent an infinite loop
+        let mut is_empty = true;
+        acc = self.iter.try_fold(acc, |acc, x| {
+            is_empty = false;
+            f(acc, x)
+        })?;
+
+        if is_empty {
+            return try { acc };
+        }
+
+        loop {
+            self.iter = self.orig.clone();
+            acc = self.iter.try_fold(acc, &mut f)?;
+        }
+    }
+
+    // No `fold` override, because `fold` doesn't make much sense for `Cycle`,
+    // and we can't do anything better than the default.
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<I> FusedIterator for Cycle<I> where I: Clone + Iterator {}
diff --git a/library/core/src/iter/adapters/enumerate.rs b/library/core/src/iter/adapters/enumerate.rs
new file mode 100644 (file)
index 0000000..5978c2d
--- /dev/null
@@ -0,0 +1,238 @@
+use crate::iter::adapters::{zip::try_get_unchecked, SourceIter, TrustedRandomAccess};
+use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
+use crate::ops::{Add, AddAssign, Try};
+
+/// An iterator that yields the current count and the element during iteration.
+///
+/// This `struct` is created by the [`enumerate`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`enumerate`]: Iterator::enumerate
+/// [`Iterator`]: trait.Iterator.html
+#[derive(Clone, Debug)]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Enumerate<I> {
+    iter: I,
+    count: usize,
+}
+impl<I> Enumerate<I> {
+    pub(in crate::iter) fn new(iter: I) -> Enumerate<I> {
+        Enumerate { iter, count: 0 }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I> Iterator for Enumerate<I>
+where
+    I: Iterator,
+{
+    type Item = (usize, <I as Iterator>::Item);
+
+    /// # Overflow Behavior
+    ///
+    /// The method does no guarding against overflows, so enumerating more than
+    /// `usize::MAX` elements either produces the wrong result or panics. If
+    /// debug assertions are enabled, a panic is guaranteed.
+    ///
+    /// # Panics
+    ///
+    /// Might panic if the index of the element overflows a `usize`.
+    #[inline]
+    fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
+        let a = self.iter.next()?;
+        let i = self.count;
+        // Possible undefined overflow.
+        AddAssign::add_assign(&mut self.count, 1);
+        Some((i, a))
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
+
+    #[inline]
+    fn nth(&mut self, n: usize) -> Option<(usize, I::Item)> {
+        let a = self.iter.nth(n)?;
+        // Possible undefined overflow.
+        let i = Add::add(self.count, n);
+        self.count = Add::add(i, 1);
+        Some((i, a))
+    }
+
+    #[inline]
+    fn count(self) -> usize {
+        self.iter.count()
+    }
+
+    #[inline]
+    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        #[inline]
+        fn enumerate<'a, T, Acc, R>(
+            count: &'a mut usize,
+            mut fold: impl FnMut(Acc, (usize, T)) -> R + 'a,
+        ) -> impl FnMut(Acc, T) -> R + 'a {
+            move |acc, item| {
+                let acc = fold(acc, (*count, item));
+                // Possible undefined overflow.
+                AddAssign::add_assign(count, 1);
+                acc
+            }
+        }
+
+        self.iter.try_fold(init, enumerate(&mut self.count, fold))
+    }
+
+    #[inline]
+    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+    where
+        Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        #[inline]
+        fn enumerate<T, Acc>(
+            mut count: usize,
+            mut fold: impl FnMut(Acc, (usize, T)) -> Acc,
+        ) -> impl FnMut(Acc, T) -> Acc {
+            move |acc, item| {
+                let acc = fold(acc, (count, item));
+                // Possible undefined overflow.
+                AddAssign::add_assign(&mut count, 1);
+                acc
+            }
+        }
+
+        self.iter.fold(init, enumerate(self.count, fold))
+    }
+
+    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item
+    where
+        Self: TrustedRandomAccess,
+    {
+        // SAFETY: the caller must uphold the contract for
+        // `Iterator::__iterator_get_unchecked`.
+        let value = unsafe { try_get_unchecked(&mut self.iter, idx) };
+        (Add::add(self.count, idx), value)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I> DoubleEndedIterator for Enumerate<I>
+where
+    I: ExactSizeIterator + DoubleEndedIterator,
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
+        let a = self.iter.next_back()?;
+        let len = self.iter.len();
+        // Can safely add, `ExactSizeIterator` promises that the number of
+        // elements fits into a `usize`.
+        Some((self.count + len, a))
+    }
+
+    #[inline]
+    fn nth_back(&mut self, n: usize) -> Option<(usize, <I as Iterator>::Item)> {
+        let a = self.iter.nth_back(n)?;
+        let len = self.iter.len();
+        // Can safely add, `ExactSizeIterator` promises that the number of
+        // elements fits into a `usize`.
+        Some((self.count + len, a))
+    }
+
+    #[inline]
+    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        // Can safely add and subtract the count, as `ExactSizeIterator` promises
+        // that the number of elements fits into a `usize`.
+        fn enumerate<T, Acc, R>(
+            mut count: usize,
+            mut fold: impl FnMut(Acc, (usize, T)) -> R,
+        ) -> impl FnMut(Acc, T) -> R {
+            move |acc, item| {
+                count -= 1;
+                fold(acc, (count, item))
+            }
+        }
+
+        let count = self.count + self.iter.len();
+        self.iter.try_rfold(init, enumerate(count, fold))
+    }
+
+    #[inline]
+    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+    where
+        Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        // Can safely add and subtract the count, as `ExactSizeIterator` promises
+        // that the number of elements fits into a `usize`.
+        fn enumerate<T, Acc>(
+            mut count: usize,
+            mut fold: impl FnMut(Acc, (usize, T)) -> Acc,
+        ) -> impl FnMut(Acc, T) -> Acc {
+            move |acc, item| {
+                count -= 1;
+                fold(acc, (count, item))
+            }
+        }
+
+        let count = self.count + self.iter.len();
+        self.iter.rfold(init, enumerate(count, fold))
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I> ExactSizeIterator for Enumerate<I>
+where
+    I: ExactSizeIterator,
+{
+    fn len(&self) -> usize {
+        self.iter.len()
+    }
+
+    fn is_empty(&self) -> bool {
+        self.iter.is_empty()
+    }
+}
+
+#[doc(hidden)]
+#[unstable(feature = "trusted_random_access", issue = "none")]
+unsafe impl<I> TrustedRandomAccess for Enumerate<I>
+where
+    I: TrustedRandomAccess,
+{
+    fn may_have_side_effect() -> bool {
+        I::may_have_side_effect()
+    }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<I> FusedIterator for Enumerate<I> where I: FusedIterator {}
+
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<I> TrustedLen for Enumerate<I> where I: TrustedLen {}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<S: Iterator, I: Iterator> SourceIter for Enumerate<I>
+where
+    I: SourceIter<Source = S>,
+{
+    type Source = S;
+
+    #[inline]
+    unsafe fn as_inner(&mut self) -> &mut S {
+        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
+        unsafe { SourceIter::as_inner(&mut self.iter) }
+    }
+}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<I: InPlaceIterable> InPlaceIterable for Enumerate<I> {}
diff --git a/library/core/src/iter/adapters/filter.rs b/library/core/src/iter/adapters/filter.rs
new file mode 100644 (file)
index 0000000..f8d684f
--- /dev/null
@@ -0,0 +1,152 @@
+use crate::fmt;
+use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
+use crate::ops::Try;
+
+/// An iterator that filters the elements of `iter` with `predicate`.
+///
+/// This `struct` is created by the [`filter`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`filter`]: Iterator::filter
+/// [`Iterator`]: trait.Iterator.html
+#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Clone)]
+pub struct Filter<I, P> {
+    iter: I,
+    predicate: P,
+}
+impl<I, P> Filter<I, P> {
+    pub(in crate::iter) fn new(iter: I, predicate: P) -> Filter<I, P> {
+        Filter { iter, predicate }
+    }
+}
+
+#[stable(feature = "core_impl_debug", since = "1.9.0")]
+impl<I: fmt::Debug, P> fmt::Debug for Filter<I, P> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("Filter").field("iter", &self.iter).finish()
+    }
+}
+
+fn filter_fold<T, Acc>(
+    mut predicate: impl FnMut(&T) -> bool,
+    mut fold: impl FnMut(Acc, T) -> Acc,
+) -> impl FnMut(Acc, T) -> Acc {
+    move |acc, item| if predicate(&item) { fold(acc, item) } else { acc }
+}
+
+fn filter_try_fold<'a, T, Acc, R: Try<Ok = Acc>>(
+    predicate: &'a mut impl FnMut(&T) -> bool,
+    mut fold: impl FnMut(Acc, T) -> R + 'a,
+) -> impl FnMut(Acc, T) -> R + 'a {
+    move |acc, item| if predicate(&item) { fold(acc, item) } else { try { acc } }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I: Iterator, P> Iterator for Filter<I, P>
+where
+    P: FnMut(&I::Item) -> bool,
+{
+    type Item = I::Item;
+
+    #[inline]
+    fn next(&mut self) -> Option<I::Item> {
+        self.iter.find(&mut self.predicate)
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let (_, upper) = self.iter.size_hint();
+        (0, upper) // can't know a lower bound, due to the predicate
+    }
+
+    // this special case allows the compiler to make `.filter(_).count()`
+    // branchless. Barring perfect branch prediction (which is unattainable in
+    // the general case), this will be much faster in >90% of cases (containing
+    // virtually all real workloads) and only a tiny bit slower in the rest.
+    //
+    // Having this specialization thus allows us to write `.filter(p).count()`
+    // where we would otherwise write `.map(|x| p(x) as usize).sum()`, which is
+    // less readable and also less backwards-compatible to Rust before 1.10.
+    //
+    // Using the branchless version will also simplify the LLVM byte code, thus
+    // leaving more budget for LLVM optimizations.
+    #[inline]
+    fn count(self) -> usize {
+        #[inline]
+        fn to_usize<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut(T) -> usize {
+            move |x| predicate(&x) as usize
+        }
+
+        self.iter.map(to_usize(self.predicate)).sum()
+    }
+
+    #[inline]
+    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        self.iter.try_fold(init, filter_try_fold(&mut self.predicate, fold))
+    }
+
+    #[inline]
+    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+    where
+        Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.iter.fold(init, filter_fold(self.predicate, fold))
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I: DoubleEndedIterator, P> DoubleEndedIterator for Filter<I, P>
+where
+    P: FnMut(&I::Item) -> bool,
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<I::Item> {
+        self.iter.rfind(&mut self.predicate)
+    }
+
+    #[inline]
+    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        self.iter.try_rfold(init, filter_try_fold(&mut self.predicate, fold))
+    }
+
+    #[inline]
+    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+    where
+        Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.iter.rfold(init, filter_fold(self.predicate, fold))
+    }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<I: FusedIterator, P> FusedIterator for Filter<I, P> where P: FnMut(&I::Item) -> bool {}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<S: Iterator, P, I: Iterator> SourceIter for Filter<I, P>
+where
+    P: FnMut(&I::Item) -> bool,
+    I: SourceIter<Source = S>,
+{
+    type Source = S;
+
+    #[inline]
+    unsafe fn as_inner(&mut self) -> &mut S {
+        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
+        unsafe { SourceIter::as_inner(&mut self.iter) }
+    }
+}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<I: InPlaceIterable, P> InPlaceIterable for Filter<I, P> where P: FnMut(&I::Item) -> bool {}
diff --git a/library/core/src/iter/adapters/filter_map.rs b/library/core/src/iter/adapters/filter_map.rs
new file mode 100644 (file)
index 0000000..0dccf2c
--- /dev/null
@@ -0,0 +1,150 @@
+use crate::fmt;
+use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
+use crate::ops::{ControlFlow, Try};
+
+/// An iterator that uses `f` to both filter and map elements from `iter`.
+///
+/// This `struct` is created by the [`filter_map`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`filter_map`]: Iterator::filter_map
+/// [`Iterator`]: trait.Iterator.html
+#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Clone)]
+pub struct FilterMap<I, F> {
+    iter: I,
+    f: F,
+}
+impl<I, F> FilterMap<I, F> {
+    pub(in crate::iter) fn new(iter: I, f: F) -> FilterMap<I, F> {
+        FilterMap { iter, f }
+    }
+}
+
+#[stable(feature = "core_impl_debug", since = "1.9.0")]
+impl<I: fmt::Debug, F> fmt::Debug for FilterMap<I, F> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("FilterMap").field("iter", &self.iter).finish()
+    }
+}
+
+fn filter_map_fold<T, B, Acc>(
+    mut f: impl FnMut(T) -> Option<B>,
+    mut fold: impl FnMut(Acc, B) -> Acc,
+) -> impl FnMut(Acc, T) -> Acc {
+    move |acc, item| match f(item) {
+        Some(x) => fold(acc, x),
+        None => acc,
+    }
+}
+
+fn filter_map_try_fold<'a, T, B, Acc, R: Try<Ok = Acc>>(
+    f: &'a mut impl FnMut(T) -> Option<B>,
+    mut fold: impl FnMut(Acc, B) -> R + 'a,
+) -> impl FnMut(Acc, T) -> R + 'a {
+    move |acc, item| match f(item) {
+        Some(x) => fold(acc, x),
+        None => try { acc },
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<B, I: Iterator, F> Iterator for FilterMap<I, F>
+where
+    F: FnMut(I::Item) -> Option<B>,
+{
+    type Item = B;
+
+    #[inline]
+    fn next(&mut self) -> Option<B> {
+        self.iter.find_map(&mut self.f)
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let (_, upper) = self.iter.size_hint();
+        (0, upper) // can't know a lower bound, due to the predicate
+    }
+
+    #[inline]
+    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        self.iter.try_fold(init, filter_map_try_fold(&mut self.f, fold))
+    }
+
+    #[inline]
+    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+    where
+        Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.iter.fold(init, filter_map_fold(self.f, fold))
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for FilterMap<I, F>
+where
+    F: FnMut(I::Item) -> Option<B>,
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<B> {
+        #[inline]
+        fn find<T, B>(
+            f: &mut impl FnMut(T) -> Option<B>,
+        ) -> impl FnMut((), T) -> ControlFlow<B> + '_ {
+            move |(), x| match f(x) {
+                Some(x) => ControlFlow::Break(x),
+                None => ControlFlow::CONTINUE,
+            }
+        }
+
+        self.iter.try_rfold((), find(&mut self.f)).break_value()
+    }
+
+    #[inline]
+    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        self.iter.try_rfold(init, filter_map_try_fold(&mut self.f, fold))
+    }
+
+    #[inline]
+    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+    where
+        Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.iter.rfold(init, filter_map_fold(self.f, fold))
+    }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<B, I: FusedIterator, F> FusedIterator for FilterMap<I, F> where F: FnMut(I::Item) -> Option<B> {}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<S: Iterator, B, I: Iterator, F> SourceIter for FilterMap<I, F>
+where
+    F: FnMut(I::Item) -> Option<B>,
+    I: SourceIter<Source = S>,
+{
+    type Source = S;
+
+    #[inline]
+    unsafe fn as_inner(&mut self) -> &mut S {
+        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
+        unsafe { SourceIter::as_inner(&mut self.iter) }
+    }
+}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<B, I: InPlaceIterable, F> InPlaceIterable for FilterMap<I, F> where
+    F: FnMut(I::Item) -> Option<B>
+{
+}
index 96d0a60a32768c9ca623fb21452013dc05de012b..ff85e114dc98262699267286c50691c033e7fab0 100644 (file)
@@ -1,9 +1,7 @@
 use crate::fmt;
+use crate::iter::{DoubleEndedIterator, Fuse, FusedIterator, Iterator, Map};
 use crate::ops::Try;
 
-use super::super::{DoubleEndedIterator, Fuse, FusedIterator, Iterator};
-use super::Map;
-
 /// An iterator that maps each element to an iterator, and yields the elements
 /// of the produced iterators.
 ///
@@ -14,8 +12,9 @@
 pub struct FlatMap<I, U: IntoIterator, F> {
     inner: FlattenCompat<Map<I, F>, <U as IntoIterator>::IntoIter>,
 }
+
 impl<I: Iterator, U: IntoIterator, F: FnMut(I::Item) -> U> FlatMap<I, U, F> {
-    pub(in super::super) fn new(iter: I, f: F) -> FlatMap<I, U, F> {
+    pub(in crate::iter) fn new(iter: I, f: F) -> FlatMap<I, U, F> {
         FlatMap { inner: FlattenCompat::new(iter.map(f)) }
     }
 }
index 60ac3524e66964c65b3c37e1d6c517815c5bc788..ae074065315935f8a96971d7c7ef845ab2fe3a53 100644 (file)
@@ -1,9 +1,6 @@
-use super::InPlaceIterable;
 use crate::intrinsics;
-use crate::iter::adapters::zip::try_get_unchecked;
-use crate::iter::adapters::SourceIter;
-use crate::iter::TrustedRandomAccess;
-use crate::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator};
+use crate::iter::adapters::{zip::try_get_unchecked, InPlaceIterable, SourceIter};
+use crate::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedRandomAccess};
 use crate::ops::Try;
 
 /// An iterator that yields `None` forever after the underlying iterator
diff --git a/library/core/src/iter/adapters/inspect.rs b/library/core/src/iter/adapters/inspect.rs
new file mode 100644 (file)
index 0000000..88f5ee6
--- /dev/null
@@ -0,0 +1,167 @@
+use crate::fmt;
+use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
+use crate::ops::Try;
+
+/// An iterator that calls a function with a reference to each element before
+/// yielding it.
+///
+/// This `struct` is created by the [`inspect`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`inspect`]: Iterator::inspect
+/// [`Iterator`]: trait.Iterator.html
+#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Clone)]
+pub struct Inspect<I, F> {
+    iter: I,
+    f: F,
+}
+impl<I, F> Inspect<I, F> {
+    pub(in crate::iter) fn new(iter: I, f: F) -> Inspect<I, F> {
+        Inspect { iter, f }
+    }
+}
+
+#[stable(feature = "core_impl_debug", since = "1.9.0")]
+impl<I: fmt::Debug, F> fmt::Debug for Inspect<I, F> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("Inspect").field("iter", &self.iter).finish()
+    }
+}
+
+impl<I: Iterator, F> Inspect<I, F>
+where
+    F: FnMut(&I::Item),
+{
+    #[inline]
+    fn do_inspect(&mut self, elt: Option<I::Item>) -> Option<I::Item> {
+        if let Some(ref a) = elt {
+            (self.f)(a);
+        }
+
+        elt
+    }
+}
+
+fn inspect_fold<T, Acc>(
+    mut f: impl FnMut(&T),
+    mut fold: impl FnMut(Acc, T) -> Acc,
+) -> impl FnMut(Acc, T) -> Acc {
+    move |acc, item| {
+        f(&item);
+        fold(acc, item)
+    }
+}
+
+fn inspect_try_fold<'a, T, Acc, R>(
+    f: &'a mut impl FnMut(&T),
+    mut fold: impl FnMut(Acc, T) -> R + 'a,
+) -> impl FnMut(Acc, T) -> R + 'a {
+    move |acc, item| {
+        f(&item);
+        fold(acc, item)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I: Iterator, F> Iterator for Inspect<I, F>
+where
+    F: FnMut(&I::Item),
+{
+    type Item = I::Item;
+
+    #[inline]
+    fn next(&mut self) -> Option<I::Item> {
+        let next = self.iter.next();
+        self.do_inspect(next)
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
+
+    #[inline]
+    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        self.iter.try_fold(init, inspect_try_fold(&mut self.f, fold))
+    }
+
+    #[inline]
+    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+    where
+        Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.iter.fold(init, inspect_fold(self.f, fold))
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I: DoubleEndedIterator, F> DoubleEndedIterator for Inspect<I, F>
+where
+    F: FnMut(&I::Item),
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<I::Item> {
+        let next = self.iter.next_back();
+        self.do_inspect(next)
+    }
+
+    #[inline]
+    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        self.iter.try_rfold(init, inspect_try_fold(&mut self.f, fold))
+    }
+
+    #[inline]
+    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+    where
+        Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.iter.rfold(init, inspect_fold(self.f, fold))
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I: ExactSizeIterator, F> ExactSizeIterator for Inspect<I, F>
+where
+    F: FnMut(&I::Item),
+{
+    fn len(&self) -> usize {
+        self.iter.len()
+    }
+
+    fn is_empty(&self) -> bool {
+        self.iter.is_empty()
+    }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<I: FusedIterator, F> FusedIterator for Inspect<I, F> where F: FnMut(&I::Item) {}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<S: Iterator, I: Iterator, F> SourceIter for Inspect<I, F>
+where
+    F: FnMut(&I::Item),
+    I: SourceIter<Source = S>,
+{
+    type Source = S;
+
+    #[inline]
+    unsafe fn as_inner(&mut self) -> &mut S {
+        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
+        unsafe { SourceIter::as_inner(&mut self.iter) }
+    }
+}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<I: InPlaceIterable, F> InPlaceIterable for Inspect<I, F> where F: FnMut(&I::Item) {}
diff --git a/library/core/src/iter/adapters/map.rs b/library/core/src/iter/adapters/map.rs
new file mode 100644 (file)
index 0000000..1267380
--- /dev/null
@@ -0,0 +1,213 @@
+use crate::fmt;
+use crate::iter::adapters::{zip::try_get_unchecked, SourceIter, TrustedRandomAccess};
+use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
+use crate::ops::Try;
+
+/// An iterator that maps the values of `iter` with `f`.
+///
+/// This `struct` is created by the [`map`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`map`]: Iterator::map
+/// [`Iterator`]: trait.Iterator.html
+///
+/// # Notes about side effects
+///
+/// The [`map`] iterator implements [`DoubleEndedIterator`], meaning that
+/// you can also [`map`] backwards:
+///
+/// ```rust
+/// let v: Vec<i32> = vec![1, 2, 3].into_iter().map(|x| x + 1).rev().collect();
+///
+/// assert_eq!(v, [4, 3, 2]);
+/// ```
+///
+/// [`DoubleEndedIterator`]: trait.DoubleEndedIterator.html
+///
+/// But if your closure has state, iterating backwards may act in a way you do
+/// not expect. Let's go through an example. First, in the forward direction:
+///
+/// ```rust
+/// let mut c = 0;
+///
+/// for pair in vec!['a', 'b', 'c'].into_iter()
+///                                .map(|letter| { c += 1; (letter, c) }) {
+///     println!("{:?}", pair);
+/// }
+/// ```
+///
+/// This will print "('a', 1), ('b', 2), ('c', 3)".
+///
+/// Now consider this twist where we add a call to `rev`. This version will
+/// print `('c', 1), ('b', 2), ('a', 3)`. Note that the letters are reversed,
+/// but the values of the counter still go in order. This is because `map()` is
+/// still being called lazily on each item, but we are popping items off the
+/// back of the vector now, instead of shifting them from the front.
+///
+/// ```rust
+/// let mut c = 0;
+///
+/// for pair in vec!['a', 'b', 'c'].into_iter()
+///                                .map(|letter| { c += 1; (letter, c) })
+///                                .rev() {
+///     println!("{:?}", pair);
+/// }
+/// ```
+#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Clone)]
+pub struct Map<I, F> {
+    iter: I,
+    f: F,
+}
+impl<I, F> Map<I, F> {
+    pub(in crate::iter) fn new(iter: I, f: F) -> Map<I, F> {
+        Map { iter, f }
+    }
+}
+
+#[stable(feature = "core_impl_debug", since = "1.9.0")]
+impl<I: fmt::Debug, F> fmt::Debug for Map<I, F> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("Map").field("iter", &self.iter).finish()
+    }
+}
+
+fn map_fold<T, B, Acc>(
+    mut f: impl FnMut(T) -> B,
+    mut g: impl FnMut(Acc, B) -> Acc,
+) -> impl FnMut(Acc, T) -> Acc {
+    move |acc, elt| g(acc, f(elt))
+}
+
+fn map_try_fold<'a, T, B, Acc, R>(
+    f: &'a mut impl FnMut(T) -> B,
+    mut g: impl FnMut(Acc, B) -> R + 'a,
+) -> impl FnMut(Acc, T) -> R + 'a {
+    move |acc, elt| g(acc, f(elt))
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<B, I: Iterator, F> Iterator for Map<I, F>
+where
+    F: FnMut(I::Item) -> B,
+{
+    type Item = B;
+
+    #[inline]
+    fn next(&mut self) -> Option<B> {
+        self.iter.next().map(&mut self.f)
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
+
+    fn try_fold<Acc, G, R>(&mut self, init: Acc, g: G) -> R
+    where
+        Self: Sized,
+        G: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        self.iter.try_fold(init, map_try_fold(&mut self.f, g))
+    }
+
+    fn fold<Acc, G>(self, init: Acc, g: G) -> Acc
+    where
+        G: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.iter.fold(init, map_fold(self.f, g))
+    }
+
+    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> B
+    where
+        Self: TrustedRandomAccess,
+    {
+        // SAFETY: the caller must uphold the contract for
+        // `Iterator::__iterator_get_unchecked`.
+        unsafe { (self.f)(try_get_unchecked(&mut self.iter, idx)) }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for Map<I, F>
+where
+    F: FnMut(I::Item) -> B,
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<B> {
+        self.iter.next_back().map(&mut self.f)
+    }
+
+    fn try_rfold<Acc, G, R>(&mut self, init: Acc, g: G) -> R
+    where
+        Self: Sized,
+        G: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        self.iter.try_rfold(init, map_try_fold(&mut self.f, g))
+    }
+
+    fn rfold<Acc, G>(self, init: Acc, g: G) -> Acc
+    where
+        G: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.iter.rfold(init, map_fold(self.f, g))
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<B, I: ExactSizeIterator, F> ExactSizeIterator for Map<I, F>
+where
+    F: FnMut(I::Item) -> B,
+{
+    fn len(&self) -> usize {
+        self.iter.len()
+    }
+
+    fn is_empty(&self) -> bool {
+        self.iter.is_empty()
+    }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<B, I: FusedIterator, F> FusedIterator for Map<I, F> where F: FnMut(I::Item) -> B {}
+
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<B, I, F> TrustedLen for Map<I, F>
+where
+    I: TrustedLen,
+    F: FnMut(I::Item) -> B,
+{
+}
+
+#[doc(hidden)]
+#[unstable(feature = "trusted_random_access", issue = "none")]
+unsafe impl<I, F> TrustedRandomAccess for Map<I, F>
+where
+    I: TrustedRandomAccess,
+{
+    #[inline]
+    fn may_have_side_effect() -> bool {
+        true
+    }
+}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<S: Iterator, B, I: Iterator, F> SourceIter for Map<I, F>
+where
+    F: FnMut(I::Item) -> B,
+    I: SourceIter<Source = S>,
+{
+    type Source = S;
+
+    #[inline]
+    unsafe fn as_inner(&mut self) -> &mut S {
+        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
+        unsafe { SourceIter::as_inner(&mut self.iter) }
+    }
+}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<B, I: InPlaceIterable, F> InPlaceIterable for Map<I, F> where F: FnMut(I::Item) -> B {}
diff --git a/library/core/src/iter/adapters/map_while.rs b/library/core/src/iter/adapters/map_while.rs
new file mode 100644 (file)
index 0000000..26114d5
--- /dev/null
@@ -0,0 +1,101 @@
+use crate::fmt;
+use crate::iter::{adapters::SourceIter, InPlaceIterable};
+use crate::ops::{ControlFlow, Try};
+
+/// An iterator that only accepts elements while `predicate` returns `Some(_)`.
+///
+/// This `struct` is created by the [`map_while`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`map_while`]: Iterator::map_while
+/// [`Iterator`]: trait.Iterator.html
+#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+#[derive(Clone)]
+pub struct MapWhile<I, P> {
+    iter: I,
+    predicate: P,
+}
+
+impl<I, P> MapWhile<I, P> {
+    pub(in crate::iter) fn new(iter: I, predicate: P) -> MapWhile<I, P> {
+        MapWhile { iter, predicate }
+    }
+}
+
+#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+impl<I: fmt::Debug, P> fmt::Debug for MapWhile<I, P> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("MapWhile").field("iter", &self.iter).finish()
+    }
+}
+
+#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+impl<B, I: Iterator, P> Iterator for MapWhile<I, P>
+where
+    P: FnMut(I::Item) -> Option<B>,
+{
+    type Item = B;
+
+    #[inline]
+    fn next(&mut self) -> Option<B> {
+        let x = self.iter.next()?;
+        (self.predicate)(x)
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let (_, upper) = self.iter.size_hint();
+        (0, upper) // can't know a lower bound, due to the predicate
+    }
+
+    #[inline]
+    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        let Self { iter, predicate } = self;
+        iter.try_fold(init, |acc, x| match predicate(x) {
+            Some(item) => ControlFlow::from_try(fold(acc, item)),
+            None => ControlFlow::Break(try { acc }),
+        })
+        .into_try()
+    }
+
+    #[inline]
+    fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        #[inline]
+        fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
+            move |acc, x| Ok(f(acc, x))
+        }
+
+        self.try_fold(init, ok(fold)).unwrap()
+    }
+}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<S: Iterator, B, I: Iterator, P> SourceIter for MapWhile<I, P>
+where
+    P: FnMut(I::Item) -> Option<B>,
+    I: SourceIter<Source = S>,
+{
+    type Source = S;
+
+    #[inline]
+    unsafe fn as_inner(&mut self) -> &mut S {
+        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
+        unsafe { SourceIter::as_inner(&mut self.iter) }
+    }
+}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<B, I: InPlaceIterable, P> InPlaceIterable for MapWhile<I, P> where
+    P: FnMut(I::Item) -> Option<B>
+{
+}
index 9586284e1d706f288137cb2083de81b35ddcd27d..5ef5717085e4ffb403e1f54783eb0c30bce62da5 100644 (file)
@@ -1,26 +1,51 @@
-use crate::cmp;
-use crate::fmt;
-use crate::intrinsics;
-use crate::ops::{Add, AddAssign, ControlFlow, Try};
-
-use super::from_fn;
-use super::{
-    DoubleEndedIterator, ExactSizeIterator, FusedIterator, InPlaceIterable, Iterator, TrustedLen,
-};
+use crate::iter::{InPlaceIterable, Iterator};
+use crate::ops::{ControlFlow, Try};
 
 mod chain;
+mod cloned;
+mod copied;
+mod cycle;
+mod enumerate;
+mod filter;
+mod filter_map;
 mod flatten;
 mod fuse;
+mod inspect;
+mod map;
+mod map_while;
+mod peekable;
+mod rev;
+mod scan;
+mod skip;
+mod skip_while;
+mod step_by;
+mod take;
+mod take_while;
 mod zip;
 
-pub use self::chain::Chain;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::flatten::{FlatMap, Flatten};
-pub use self::fuse::Fuse;
-use self::zip::try_get_unchecked;
+pub use self::{
+    chain::Chain, cycle::Cycle, enumerate::Enumerate, filter::Filter, filter_map::FilterMap,
+    flatten::FlatMap, fuse::Fuse, inspect::Inspect, map::Map, peekable::Peekable, rev::Rev,
+    scan::Scan, skip::Skip, skip_while::SkipWhile, take::Take, take_while::TakeWhile, zip::Zip,
+};
+
+#[stable(feature = "iter_cloned", since = "1.1.0")]
+pub use self::cloned::Cloned;
+
+#[stable(feature = "iterator_step_by", since = "1.28.0")]
+pub use self::step_by::StepBy;
+
+#[stable(feature = "iterator_flatten", since = "1.29.0")]
+pub use self::flatten::Flatten;
+
+#[stable(feature = "iter_copied", since = "1.36.0")]
+pub use self::copied::Copied;
+
+#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+pub use self::map_while::MapWhile;
+
 #[unstable(feature = "trusted_random_access", issue = "none")]
 pub use self::zip::TrustedRandomAccess;
-pub use self::zip::Zip;
 
 /// This trait provides transitive access to source-stage in an interator-adapter pipeline
 /// under the conditions that
@@ -89,2810 +114,6 @@ pub unsafe trait SourceIter {
     unsafe fn as_inner(&mut self) -> &mut Self::Source;
 }
 
-/// A double-ended iterator with the direction inverted.
-///
-/// This `struct` is created by the [`rev`] method on [`Iterator`]. See its
-/// documentation for more.
-///
-/// [`rev`]: Iterator::rev
-/// [`Iterator`]: trait.Iterator.html
-#[derive(Clone, Debug)]
-#[must_use = "iterators are lazy and do nothing unless consumed"]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Rev<T> {
-    iter: T,
-}
-impl<T> Rev<T> {
-    pub(super) fn new(iter: T) -> Rev<T> {
-        Rev { iter }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I> Iterator for Rev<I>
-where
-    I: DoubleEndedIterator,
-{
-    type Item = <I as Iterator>::Item;
-
-    #[inline]
-    fn next(&mut self) -> Option<<I as Iterator>::Item> {
-        self.iter.next_back()
-    }
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-
-    #[inline]
-    fn advance_by(&mut self, n: usize) -> Result<(), usize> {
-        self.iter.advance_back_by(n)
-    }
-
-    #[inline]
-    fn nth(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
-        self.iter.nth_back(n)
-    }
-
-    fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
-    where
-        Self: Sized,
-        F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
-    {
-        self.iter.try_rfold(init, f)
-    }
-
-    fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
-    where
-        F: FnMut(Acc, Self::Item) -> Acc,
-    {
-        self.iter.rfold(init, f)
-    }
-
-    #[inline]
-    fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
-    where
-        P: FnMut(&Self::Item) -> bool,
-    {
-        self.iter.rfind(predicate)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I> DoubleEndedIterator for Rev<I>
-where
-    I: DoubleEndedIterator,
-{
-    #[inline]
-    fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
-        self.iter.next()
-    }
-
-    #[inline]
-    fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
-        self.iter.advance_by(n)
-    }
-
-    #[inline]
-    fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
-        self.iter.nth(n)
-    }
-
-    fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
-    where
-        Self: Sized,
-        F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
-    {
-        self.iter.try_fold(init, f)
-    }
-
-    fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
-    where
-        F: FnMut(Acc, Self::Item) -> Acc,
-    {
-        self.iter.fold(init, f)
-    }
-
-    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
-    where
-        P: FnMut(&Self::Item) -> bool,
-    {
-        self.iter.find(predicate)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I> ExactSizeIterator for Rev<I>
-where
-    I: ExactSizeIterator + DoubleEndedIterator,
-{
-    fn len(&self) -> usize {
-        self.iter.len()
-    }
-
-    fn is_empty(&self) -> bool {
-        self.iter.is_empty()
-    }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<I> FusedIterator for Rev<I> where I: FusedIterator + DoubleEndedIterator {}
-
-#[unstable(feature = "trusted_len", issue = "37572")]
-unsafe impl<I> TrustedLen for Rev<I> where I: TrustedLen + DoubleEndedIterator {}
-
-/// An iterator that copies the elements of an underlying iterator.
-///
-/// This `struct` is created by the [`copied`] method on [`Iterator`]. See its
-/// documentation for more.
-///
-/// [`copied`]: Iterator::copied
-/// [`Iterator`]: trait.Iterator.html
-#[stable(feature = "iter_copied", since = "1.36.0")]
-#[must_use = "iterators are lazy and do nothing unless consumed"]
-#[derive(Clone, Debug)]
-pub struct Copied<I> {
-    it: I,
-}
-
-impl<I> Copied<I> {
-    pub(super) fn new(it: I) -> Copied<I> {
-        Copied { it }
-    }
-}
-
-fn copy_fold<T: Copy, Acc>(mut f: impl FnMut(Acc, T) -> Acc) -> impl FnMut(Acc, &T) -> Acc {
-    move |acc, &elt| f(acc, elt)
-}
-
-fn copy_try_fold<T: Copy, Acc, R>(mut f: impl FnMut(Acc, T) -> R) -> impl FnMut(Acc, &T) -> R {
-    move |acc, &elt| f(acc, elt)
-}
-
-#[stable(feature = "iter_copied", since = "1.36.0")]
-impl<'a, I, T: 'a> Iterator for Copied<I>
-where
-    I: Iterator<Item = &'a T>,
-    T: Copy,
-{
-    type Item = T;
-
-    fn next(&mut self) -> Option<T> {
-        self.it.next().copied()
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.it.size_hint()
-    }
-
-    fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
-    where
-        Self: Sized,
-        F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
-    {
-        self.it.try_fold(init, copy_try_fold(f))
-    }
-
-    fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
-    where
-        F: FnMut(Acc, Self::Item) -> Acc,
-    {
-        self.it.fold(init, copy_fold(f))
-    }
-
-    fn nth(&mut self, n: usize) -> Option<T> {
-        self.it.nth(n).copied()
-    }
-
-    fn last(self) -> Option<T> {
-        self.it.last().copied()
-    }
-
-    fn count(self) -> usize {
-        self.it.count()
-    }
-
-    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
-    where
-        Self: TrustedRandomAccess,
-    {
-        // SAFETY: the caller must uphold the contract for
-        // `Iterator::__iterator_get_unchecked`.
-        *unsafe { try_get_unchecked(&mut self.it, idx) }
-    }
-}
-
-#[stable(feature = "iter_copied", since = "1.36.0")]
-impl<'a, I, T: 'a> DoubleEndedIterator for Copied<I>
-where
-    I: DoubleEndedIterator<Item = &'a T>,
-    T: Copy,
-{
-    fn next_back(&mut self) -> Option<T> {
-        self.it.next_back().copied()
-    }
-
-    fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
-    where
-        Self: Sized,
-        F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
-    {
-        self.it.try_rfold(init, copy_try_fold(f))
-    }
-
-    fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
-    where
-        F: FnMut(Acc, Self::Item) -> Acc,
-    {
-        self.it.rfold(init, copy_fold(f))
-    }
-}
-
-#[stable(feature = "iter_copied", since = "1.36.0")]
-impl<'a, I, T: 'a> ExactSizeIterator for Copied<I>
-where
-    I: ExactSizeIterator<Item = &'a T>,
-    T: Copy,
-{
-    fn len(&self) -> usize {
-        self.it.len()
-    }
-
-    fn is_empty(&self) -> bool {
-        self.it.is_empty()
-    }
-}
-
-#[stable(feature = "iter_copied", since = "1.36.0")]
-impl<'a, I, T: 'a> FusedIterator for Copied<I>
-where
-    I: FusedIterator<Item = &'a T>,
-    T: Copy,
-{
-}
-
-#[doc(hidden)]
-#[unstable(feature = "trusted_random_access", issue = "none")]
-unsafe impl<I> TrustedRandomAccess for Copied<I>
-where
-    I: TrustedRandomAccess,
-{
-    #[inline]
-    fn may_have_side_effect() -> bool {
-        I::may_have_side_effect()
-    }
-}
-
-#[stable(feature = "iter_copied", since = "1.36.0")]
-unsafe impl<'a, I, T: 'a> TrustedLen for Copied<I>
-where
-    I: TrustedLen<Item = &'a T>,
-    T: Copy,
-{
-}
-
-/// An iterator that clones the elements of an underlying iterator.
-///
-/// This `struct` is created by the [`cloned`] method on [`Iterator`]. See its
-/// documentation for more.
-///
-/// [`cloned`]: Iterator::cloned
-/// [`Iterator`]: trait.Iterator.html
-#[stable(feature = "iter_cloned", since = "1.1.0")]
-#[must_use = "iterators are lazy and do nothing unless consumed"]
-#[derive(Clone, Debug)]
-pub struct Cloned<I> {
-    it: I,
-}
-impl<I> Cloned<I> {
-    pub(super) fn new(it: I) -> Cloned<I> {
-        Cloned { it }
-    }
-}
-
-fn clone_try_fold<T: Clone, Acc, R>(mut f: impl FnMut(Acc, T) -> R) -> impl FnMut(Acc, &T) -> R {
-    move |acc, elt| f(acc, elt.clone())
-}
-
-#[stable(feature = "iter_cloned", since = "1.1.0")]
-impl<'a, I, T: 'a> Iterator for Cloned<I>
-where
-    I: Iterator<Item = &'a T>,
-    T: Clone,
-{
-    type Item = T;
-
-    fn next(&mut self) -> Option<T> {
-        self.it.next().cloned()
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.it.size_hint()
-    }
-
-    fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
-    where
-        Self: Sized,
-        F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
-    {
-        self.it.try_fold(init, clone_try_fold(f))
-    }
-
-    fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
-    where
-        F: FnMut(Acc, Self::Item) -> Acc,
-    {
-        self.it.map(T::clone).fold(init, f)
-    }
-
-    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
-    where
-        Self: TrustedRandomAccess,
-    {
-        // SAFETY: the caller must uphold the contract for
-        // `Iterator::__iterator_get_unchecked`.
-        unsafe { try_get_unchecked(&mut self.it, idx).clone() }
-    }
-}
-
-#[stable(feature = "iter_cloned", since = "1.1.0")]
-impl<'a, I, T: 'a> DoubleEndedIterator for Cloned<I>
-where
-    I: DoubleEndedIterator<Item = &'a T>,
-    T: Clone,
-{
-    fn next_back(&mut self) -> Option<T> {
-        self.it.next_back().cloned()
-    }
-
-    fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
-    where
-        Self: Sized,
-        F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
-    {
-        self.it.try_rfold(init, clone_try_fold(f))
-    }
-
-    fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
-    where
-        F: FnMut(Acc, Self::Item) -> Acc,
-    {
-        self.it.map(T::clone).rfold(init, f)
-    }
-}
-
-#[stable(feature = "iter_cloned", since = "1.1.0")]
-impl<'a, I, T: 'a> ExactSizeIterator for Cloned<I>
-where
-    I: ExactSizeIterator<Item = &'a T>,
-    T: Clone,
-{
-    fn len(&self) -> usize {
-        self.it.len()
-    }
-
-    fn is_empty(&self) -> bool {
-        self.it.is_empty()
-    }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<'a, I, T: 'a> FusedIterator for Cloned<I>
-where
-    I: FusedIterator<Item = &'a T>,
-    T: Clone,
-{
-}
-
-#[doc(hidden)]
-#[unstable(feature = "trusted_random_access", issue = "none")]
-unsafe impl<I> TrustedRandomAccess for Cloned<I>
-where
-    I: TrustedRandomAccess,
-{
-    #[inline]
-    fn may_have_side_effect() -> bool {
-        true
-    }
-}
-
-#[unstable(feature = "trusted_len", issue = "37572")]
-unsafe impl<'a, I, T: 'a> TrustedLen for Cloned<I>
-where
-    I: TrustedLen<Item = &'a T>,
-    T: Clone,
-{
-}
-
-/// An iterator that repeats endlessly.
-///
-/// This `struct` is created by the [`cycle`] method on [`Iterator`]. See its
-/// documentation for more.
-///
-/// [`cycle`]: Iterator::cycle
-/// [`Iterator`]: trait.Iterator.html
-#[derive(Clone, Debug)]
-#[must_use = "iterators are lazy and do nothing unless consumed"]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Cycle<I> {
-    orig: I,
-    iter: I,
-}
-impl<I: Clone> Cycle<I> {
-    pub(super) fn new(iter: I) -> Cycle<I> {
-        Cycle { orig: iter.clone(), iter }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I> Iterator for Cycle<I>
-where
-    I: Clone + Iterator,
-{
-    type Item = <I as Iterator>::Item;
-
-    #[inline]
-    fn next(&mut self) -> Option<<I as Iterator>::Item> {
-        match self.iter.next() {
-            None => {
-                self.iter = self.orig.clone();
-                self.iter.next()
-            }
-            y => y,
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        // the cycle iterator is either empty or infinite
-        match self.orig.size_hint() {
-            sz @ (0, Some(0)) => sz,
-            (0, _) => (0, None),
-            _ => (usize::MAX, None),
-        }
-    }
-
-    #[inline]
-    fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
-    where
-        F: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
-    {
-        // fully iterate the current iterator. this is necessary because
-        // `self.iter` may be empty even when `self.orig` isn't
-        acc = self.iter.try_fold(acc, &mut f)?;
-        self.iter = self.orig.clone();
-
-        // complete a full cycle, keeping track of whether the cycled
-        // iterator is empty or not. we need to return early in case
-        // of an empty iterator to prevent an infinite loop
-        let mut is_empty = true;
-        acc = self.iter.try_fold(acc, |acc, x| {
-            is_empty = false;
-            f(acc, x)
-        })?;
-
-        if is_empty {
-            return try { acc };
-        }
-
-        loop {
-            self.iter = self.orig.clone();
-            acc = self.iter.try_fold(acc, &mut f)?;
-        }
-    }
-
-    // No `fold` override, because `fold` doesn't make much sense for `Cycle`,
-    // and we can't do anything better than the default.
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<I> FusedIterator for Cycle<I> where I: Clone + Iterator {}
-
-/// An iterator for stepping iterators by a custom amount.
-///
-/// This `struct` is created by the [`step_by`] method on [`Iterator`]. See
-/// its documentation for more.
-///
-/// [`step_by`]: Iterator::step_by
-/// [`Iterator`]: trait.Iterator.html
-#[must_use = "iterators are lazy and do nothing unless consumed"]
-#[stable(feature = "iterator_step_by", since = "1.28.0")]
-#[derive(Clone, Debug)]
-pub struct StepBy<I> {
-    iter: I,
-    step: usize,
-    first_take: bool,
-}
-impl<I> StepBy<I> {
-    pub(super) fn new(iter: I, step: usize) -> StepBy<I> {
-        assert!(step != 0);
-        StepBy { iter, step: step - 1, first_take: true }
-    }
-}
-
-#[stable(feature = "iterator_step_by", since = "1.28.0")]
-impl<I> Iterator for StepBy<I>
-where
-    I: Iterator,
-{
-    type Item = I::Item;
-
-    #[inline]
-    fn next(&mut self) -> Option<Self::Item> {
-        if self.first_take {
-            self.first_take = false;
-            self.iter.next()
-        } else {
-            self.iter.nth(self.step)
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        #[inline]
-        fn first_size(step: usize) -> impl Fn(usize) -> usize {
-            move |n| if n == 0 { 0 } else { 1 + (n - 1) / (step + 1) }
-        }
-
-        #[inline]
-        fn other_size(step: usize) -> impl Fn(usize) -> usize {
-            move |n| n / (step + 1)
-        }
-
-        let (low, high) = self.iter.size_hint();
-
-        if self.first_take {
-            let f = first_size(self.step);
-            (f(low), high.map(f))
-        } else {
-            let f = other_size(self.step);
-            (f(low), high.map(f))
-        }
-    }
-
-    #[inline]
-    fn nth(&mut self, mut n: usize) -> Option<Self::Item> {
-        if self.first_take {
-            self.first_take = false;
-            let first = self.iter.next();
-            if n == 0 {
-                return first;
-            }
-            n -= 1;
-        }
-        // n and self.step are indices, we need to add 1 to get the amount of elements
-        // When calling `.nth`, we need to subtract 1 again to convert back to an index
-        // step + 1 can't overflow because `.step_by` sets `self.step` to `step - 1`
-        let mut step = self.step + 1;
-        // n + 1 could overflow
-        // thus, if n is usize::MAX, instead of adding one, we call .nth(step)
-        if n == usize::MAX {
-            self.iter.nth(step - 1);
-        } else {
-            n += 1;
-        }
-
-        // overflow handling
-        loop {
-            let mul = n.checked_mul(step);
-            {
-                if intrinsics::likely(mul.is_some()) {
-                    return self.iter.nth(mul.unwrap() - 1);
-                }
-            }
-            let div_n = usize::MAX / n;
-            let div_step = usize::MAX / step;
-            let nth_n = div_n * n;
-            let nth_step = div_step * step;
-            let nth = if nth_n > nth_step {
-                step -= div_n;
-                nth_n
-            } else {
-                n -= div_step;
-                nth_step
-            };
-            self.iter.nth(nth - 1);
-        }
-    }
-
-    fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
-    where
-        F: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
-    {
-        #[inline]
-        fn nth<I: Iterator>(iter: &mut I, step: usize) -> impl FnMut() -> Option<I::Item> + '_ {
-            move || iter.nth(step)
-        }
-
-        if self.first_take {
-            self.first_take = false;
-            match self.iter.next() {
-                None => return try { acc },
-                Some(x) => acc = f(acc, x)?,
-            }
-        }
-        from_fn(nth(&mut self.iter, self.step)).try_fold(acc, f)
-    }
-
-    fn fold<Acc, F>(mut self, mut acc: Acc, mut f: F) -> Acc
-    where
-        F: FnMut(Acc, Self::Item) -> Acc,
-    {
-        #[inline]
-        fn nth<I: Iterator>(iter: &mut I, step: usize) -> impl FnMut() -> Option<I::Item> + '_ {
-            move || iter.nth(step)
-        }
-
-        if self.first_take {
-            self.first_take = false;
-            match self.iter.next() {
-                None => return acc,
-                Some(x) => acc = f(acc, x),
-            }
-        }
-        from_fn(nth(&mut self.iter, self.step)).fold(acc, f)
-    }
-}
-
-impl<I> StepBy<I>
-where
-    I: ExactSizeIterator,
-{
-    // The zero-based index starting from the end of the iterator of the
-    // last element. Used in the `DoubleEndedIterator` implementation.
-    fn next_back_index(&self) -> usize {
-        let rem = self.iter.len() % (self.step + 1);
-        if self.first_take {
-            if rem == 0 { self.step } else { rem - 1 }
-        } else {
-            rem
-        }
-    }
-}
-
-#[stable(feature = "double_ended_step_by_iterator", since = "1.38.0")]
-impl<I> DoubleEndedIterator for StepBy<I>
-where
-    I: DoubleEndedIterator + ExactSizeIterator,
-{
-    #[inline]
-    fn next_back(&mut self) -> Option<Self::Item> {
-        self.iter.nth_back(self.next_back_index())
-    }
-
-    #[inline]
-    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
-        // `self.iter.nth_back(usize::MAX)` does the right thing here when `n`
-        // is out of bounds because the length of `self.iter` does not exceed
-        // `usize::MAX` (because `I: ExactSizeIterator`) and `nth_back` is
-        // zero-indexed
-        let n = n.saturating_mul(self.step + 1).saturating_add(self.next_back_index());
-        self.iter.nth_back(n)
-    }
-
-    fn try_rfold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R
-    where
-        F: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
-    {
-        #[inline]
-        fn nth_back<I: DoubleEndedIterator>(
-            iter: &mut I,
-            step: usize,
-        ) -> impl FnMut() -> Option<I::Item> + '_ {
-            move || iter.nth_back(step)
-        }
-
-        match self.next_back() {
-            None => try { init },
-            Some(x) => {
-                let acc = f(init, x)?;
-                from_fn(nth_back(&mut self.iter, self.step)).try_fold(acc, f)
-            }
-        }
-    }
-
-    #[inline]
-    fn rfold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc
-    where
-        Self: Sized,
-        F: FnMut(Acc, Self::Item) -> Acc,
-    {
-        #[inline]
-        fn nth_back<I: DoubleEndedIterator>(
-            iter: &mut I,
-            step: usize,
-        ) -> impl FnMut() -> Option<I::Item> + '_ {
-            move || iter.nth_back(step)
-        }
-
-        match self.next_back() {
-            None => init,
-            Some(x) => {
-                let acc = f(init, x);
-                from_fn(nth_back(&mut self.iter, self.step)).fold(acc, f)
-            }
-        }
-    }
-}
-
-// StepBy can only make the iterator shorter, so the len will still fit.
-#[stable(feature = "iterator_step_by", since = "1.28.0")]
-impl<I> ExactSizeIterator for StepBy<I> where I: ExactSizeIterator {}
-
-/// An iterator that maps the values of `iter` with `f`.
-///
-/// This `struct` is created by the [`map`] method on [`Iterator`]. See its
-/// documentation for more.
-///
-/// [`map`]: Iterator::map
-/// [`Iterator`]: trait.Iterator.html
-///
-/// # Notes about side effects
-///
-/// The [`map`] iterator implements [`DoubleEndedIterator`], meaning that
-/// you can also [`map`] backwards:
-///
-/// ```rust
-/// let v: Vec<i32> = vec![1, 2, 3].into_iter().map(|x| x + 1).rev().collect();
-///
-/// assert_eq!(v, [4, 3, 2]);
-/// ```
-///
-/// [`DoubleEndedIterator`]: trait.DoubleEndedIterator.html
-///
-/// But if your closure has state, iterating backwards may act in a way you do
-/// not expect. Let's go through an example. First, in the forward direction:
-///
-/// ```rust
-/// let mut c = 0;
-///
-/// for pair in vec!['a', 'b', 'c'].into_iter()
-///                                .map(|letter| { c += 1; (letter, c) }) {
-///     println!("{:?}", pair);
-/// }
-/// ```
-///
-/// This will print "('a', 1), ('b', 2), ('c', 3)".
-///
-/// Now consider this twist where we add a call to `rev`. This version will
-/// print `('c', 1), ('b', 2), ('a', 3)`. Note that the letters are reversed,
-/// but the values of the counter still go in order. This is because `map()` is
-/// still being called lazily on each item, but we are popping items off the
-/// back of the vector now, instead of shifting them from the front.
-///
-/// ```rust
-/// let mut c = 0;
-///
-/// for pair in vec!['a', 'b', 'c'].into_iter()
-///                                .map(|letter| { c += 1; (letter, c) })
-///                                .rev() {
-///     println!("{:?}", pair);
-/// }
-/// ```
-#[must_use = "iterators are lazy and do nothing unless consumed"]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Clone)]
-pub struct Map<I, F> {
-    iter: I,
-    f: F,
-}
-impl<I, F> Map<I, F> {
-    pub(super) fn new(iter: I, f: F) -> Map<I, F> {
-        Map { iter, f }
-    }
-}
-
-#[stable(feature = "core_impl_debug", since = "1.9.0")]
-impl<I: fmt::Debug, F> fmt::Debug for Map<I, F> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("Map").field("iter", &self.iter).finish()
-    }
-}
-
-fn map_fold<T, B, Acc>(
-    mut f: impl FnMut(T) -> B,
-    mut g: impl FnMut(Acc, B) -> Acc,
-) -> impl FnMut(Acc, T) -> Acc {
-    move |acc, elt| g(acc, f(elt))
-}
-
-fn map_try_fold<'a, T, B, Acc, R>(
-    f: &'a mut impl FnMut(T) -> B,
-    mut g: impl FnMut(Acc, B) -> R + 'a,
-) -> impl FnMut(Acc, T) -> R + 'a {
-    move |acc, elt| g(acc, f(elt))
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<B, I: Iterator, F> Iterator for Map<I, F>
-where
-    F: FnMut(I::Item) -> B,
-{
-    type Item = B;
-
-    #[inline]
-    fn next(&mut self) -> Option<B> {
-        self.iter.next().map(&mut self.f)
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-
-    fn try_fold<Acc, G, R>(&mut self, init: Acc, g: G) -> R
-    where
-        Self: Sized,
-        G: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
-    {
-        self.iter.try_fold(init, map_try_fold(&mut self.f, g))
-    }
-
-    fn fold<Acc, G>(self, init: Acc, g: G) -> Acc
-    where
-        G: FnMut(Acc, Self::Item) -> Acc,
-    {
-        self.iter.fold(init, map_fold(self.f, g))
-    }
-
-    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> B
-    where
-        Self: TrustedRandomAccess,
-    {
-        // SAFETY: the caller must uphold the contract for
-        // `Iterator::__iterator_get_unchecked`.
-        unsafe { (self.f)(try_get_unchecked(&mut self.iter, idx)) }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for Map<I, F>
-where
-    F: FnMut(I::Item) -> B,
-{
-    #[inline]
-    fn next_back(&mut self) -> Option<B> {
-        self.iter.next_back().map(&mut self.f)
-    }
-
-    fn try_rfold<Acc, G, R>(&mut self, init: Acc, g: G) -> R
-    where
-        Self: Sized,
-        G: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
-    {
-        self.iter.try_rfold(init, map_try_fold(&mut self.f, g))
-    }
-
-    fn rfold<Acc, G>(self, init: Acc, g: G) -> Acc
-    where
-        G: FnMut(Acc, Self::Item) -> Acc,
-    {
-        self.iter.rfold(init, map_fold(self.f, g))
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<B, I: ExactSizeIterator, F> ExactSizeIterator for Map<I, F>
-where
-    F: FnMut(I::Item) -> B,
-{
-    fn len(&self) -> usize {
-        self.iter.len()
-    }
-
-    fn is_empty(&self) -> bool {
-        self.iter.is_empty()
-    }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<B, I: FusedIterator, F> FusedIterator for Map<I, F> where F: FnMut(I::Item) -> B {}
-
-#[unstable(feature = "trusted_len", issue = "37572")]
-unsafe impl<B, I, F> TrustedLen for Map<I, F>
-where
-    I: TrustedLen,
-    F: FnMut(I::Item) -> B,
-{
-}
-
-#[doc(hidden)]
-#[unstable(feature = "trusted_random_access", issue = "none")]
-unsafe impl<I, F> TrustedRandomAccess for Map<I, F>
-where
-    I: TrustedRandomAccess,
-{
-    #[inline]
-    fn may_have_side_effect() -> bool {
-        true
-    }
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<S: Iterator, B, I: Iterator, F> SourceIter for Map<I, F>
-where
-    F: FnMut(I::Item) -> B,
-    I: SourceIter<Source = S>,
-{
-    type Source = S;
-
-    #[inline]
-    unsafe fn as_inner(&mut self) -> &mut S {
-        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
-        unsafe { SourceIter::as_inner(&mut self.iter) }
-    }
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<B, I: InPlaceIterable, F> InPlaceIterable for Map<I, F> where F: FnMut(I::Item) -> B {}
-
-/// An iterator that filters the elements of `iter` with `predicate`.
-///
-/// This `struct` is created by the [`filter`] method on [`Iterator`]. See its
-/// documentation for more.
-///
-/// [`filter`]: Iterator::filter
-/// [`Iterator`]: trait.Iterator.html
-#[must_use = "iterators are lazy and do nothing unless consumed"]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Clone)]
-pub struct Filter<I, P> {
-    iter: I,
-    predicate: P,
-}
-impl<I, P> Filter<I, P> {
-    pub(super) fn new(iter: I, predicate: P) -> Filter<I, P> {
-        Filter { iter, predicate }
-    }
-}
-
-#[stable(feature = "core_impl_debug", since = "1.9.0")]
-impl<I: fmt::Debug, P> fmt::Debug for Filter<I, P> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("Filter").field("iter", &self.iter).finish()
-    }
-}
-
-fn filter_fold<T, Acc>(
-    mut predicate: impl FnMut(&T) -> bool,
-    mut fold: impl FnMut(Acc, T) -> Acc,
-) -> impl FnMut(Acc, T) -> Acc {
-    move |acc, item| if predicate(&item) { fold(acc, item) } else { acc }
-}
-
-fn filter_try_fold<'a, T, Acc, R: Try<Ok = Acc>>(
-    predicate: &'a mut impl FnMut(&T) -> bool,
-    mut fold: impl FnMut(Acc, T) -> R + 'a,
-) -> impl FnMut(Acc, T) -> R + 'a {
-    move |acc, item| if predicate(&item) { fold(acc, item) } else { try { acc } }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I: Iterator, P> Iterator for Filter<I, P>
-where
-    P: FnMut(&I::Item) -> bool,
-{
-    type Item = I::Item;
-
-    #[inline]
-    fn next(&mut self) -> Option<I::Item> {
-        self.iter.find(&mut self.predicate)
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (_, upper) = self.iter.size_hint();
-        (0, upper) // can't know a lower bound, due to the predicate
-    }
-
-    // this special case allows the compiler to make `.filter(_).count()`
-    // branchless. Barring perfect branch prediction (which is unattainable in
-    // the general case), this will be much faster in >90% of cases (containing
-    // virtually all real workloads) and only a tiny bit slower in the rest.
-    //
-    // Having this specialization thus allows us to write `.filter(p).count()`
-    // where we would otherwise write `.map(|x| p(x) as usize).sum()`, which is
-    // less readable and also less backwards-compatible to Rust before 1.10.
-    //
-    // Using the branchless version will also simplify the LLVM byte code, thus
-    // leaving more budget for LLVM optimizations.
-    #[inline]
-    fn count(self) -> usize {
-        #[inline]
-        fn to_usize<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut(T) -> usize {
-            move |x| predicate(&x) as usize
-        }
-
-        self.iter.map(to_usize(self.predicate)).sum()
-    }
-
-    #[inline]
-    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
-    where
-        Self: Sized,
-        Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
-    {
-        self.iter.try_fold(init, filter_try_fold(&mut self.predicate, fold))
-    }
-
-    #[inline]
-    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
-    where
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-    {
-        self.iter.fold(init, filter_fold(self.predicate, fold))
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I: DoubleEndedIterator, P> DoubleEndedIterator for Filter<I, P>
-where
-    P: FnMut(&I::Item) -> bool,
-{
-    #[inline]
-    fn next_back(&mut self) -> Option<I::Item> {
-        self.iter.rfind(&mut self.predicate)
-    }
-
-    #[inline]
-    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
-    where
-        Self: Sized,
-        Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
-    {
-        self.iter.try_rfold(init, filter_try_fold(&mut self.predicate, fold))
-    }
-
-    #[inline]
-    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
-    where
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-    {
-        self.iter.rfold(init, filter_fold(self.predicate, fold))
-    }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<I: FusedIterator, P> FusedIterator for Filter<I, P> where P: FnMut(&I::Item) -> bool {}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<S: Iterator, P, I: Iterator> SourceIter for Filter<I, P>
-where
-    P: FnMut(&I::Item) -> bool,
-    I: SourceIter<Source = S>,
-{
-    type Source = S;
-
-    #[inline]
-    unsafe fn as_inner(&mut self) -> &mut S {
-        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
-        unsafe { SourceIter::as_inner(&mut self.iter) }
-    }
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: InPlaceIterable, P> InPlaceIterable for Filter<I, P> where P: FnMut(&I::Item) -> bool {}
-
-/// An iterator that uses `f` to both filter and map elements from `iter`.
-///
-/// This `struct` is created by the [`filter_map`] method on [`Iterator`]. See its
-/// documentation for more.
-///
-/// [`filter_map`]: Iterator::filter_map
-/// [`Iterator`]: trait.Iterator.html
-#[must_use = "iterators are lazy and do nothing unless consumed"]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Clone)]
-pub struct FilterMap<I, F> {
-    iter: I,
-    f: F,
-}
-impl<I, F> FilterMap<I, F> {
-    pub(super) fn new(iter: I, f: F) -> FilterMap<I, F> {
-        FilterMap { iter, f }
-    }
-}
-
-#[stable(feature = "core_impl_debug", since = "1.9.0")]
-impl<I: fmt::Debug, F> fmt::Debug for FilterMap<I, F> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("FilterMap").field("iter", &self.iter).finish()
-    }
-}
-
-fn filter_map_fold<T, B, Acc>(
-    mut f: impl FnMut(T) -> Option<B>,
-    mut fold: impl FnMut(Acc, B) -> Acc,
-) -> impl FnMut(Acc, T) -> Acc {
-    move |acc, item| match f(item) {
-        Some(x) => fold(acc, x),
-        None => acc,
-    }
-}
-
-fn filter_map_try_fold<'a, T, B, Acc, R: Try<Ok = Acc>>(
-    f: &'a mut impl FnMut(T) -> Option<B>,
-    mut fold: impl FnMut(Acc, B) -> R + 'a,
-) -> impl FnMut(Acc, T) -> R + 'a {
-    move |acc, item| match f(item) {
-        Some(x) => fold(acc, x),
-        None => try { acc },
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<B, I: Iterator, F> Iterator for FilterMap<I, F>
-where
-    F: FnMut(I::Item) -> Option<B>,
-{
-    type Item = B;
-
-    #[inline]
-    fn next(&mut self) -> Option<B> {
-        self.iter.find_map(&mut self.f)
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (_, upper) = self.iter.size_hint();
-        (0, upper) // can't know a lower bound, due to the predicate
-    }
-
-    #[inline]
-    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
-    where
-        Self: Sized,
-        Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
-    {
-        self.iter.try_fold(init, filter_map_try_fold(&mut self.f, fold))
-    }
-
-    #[inline]
-    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
-    where
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-    {
-        self.iter.fold(init, filter_map_fold(self.f, fold))
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for FilterMap<I, F>
-where
-    F: FnMut(I::Item) -> Option<B>,
-{
-    #[inline]
-    fn next_back(&mut self) -> Option<B> {
-        #[inline]
-        fn find<T, B>(
-            f: &mut impl FnMut(T) -> Option<B>,
-        ) -> impl FnMut((), T) -> ControlFlow<B> + '_ {
-            move |(), x| match f(x) {
-                Some(x) => ControlFlow::Break(x),
-                None => ControlFlow::CONTINUE,
-            }
-        }
-
-        self.iter.try_rfold((), find(&mut self.f)).break_value()
-    }
-
-    #[inline]
-    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
-    where
-        Self: Sized,
-        Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
-    {
-        self.iter.try_rfold(init, filter_map_try_fold(&mut self.f, fold))
-    }
-
-    #[inline]
-    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
-    where
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-    {
-        self.iter.rfold(init, filter_map_fold(self.f, fold))
-    }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<B, I: FusedIterator, F> FusedIterator for FilterMap<I, F> where F: FnMut(I::Item) -> Option<B> {}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<S: Iterator, B, I: Iterator, F> SourceIter for FilterMap<I, F>
-where
-    F: FnMut(I::Item) -> Option<B>,
-    I: SourceIter<Source = S>,
-{
-    type Source = S;
-
-    #[inline]
-    unsafe fn as_inner(&mut self) -> &mut S {
-        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
-        unsafe { SourceIter::as_inner(&mut self.iter) }
-    }
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<B, I: InPlaceIterable, F> InPlaceIterable for FilterMap<I, F> where
-    F: FnMut(I::Item) -> Option<B>
-{
-}
-
-/// An iterator that yields the current count and the element during iteration.
-///
-/// This `struct` is created by the [`enumerate`] method on [`Iterator`]. See its
-/// documentation for more.
-///
-/// [`enumerate`]: Iterator::enumerate
-/// [`Iterator`]: trait.Iterator.html
-#[derive(Clone, Debug)]
-#[must_use = "iterators are lazy and do nothing unless consumed"]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Enumerate<I> {
-    iter: I,
-    count: usize,
-}
-impl<I> Enumerate<I> {
-    pub(super) fn new(iter: I) -> Enumerate<I> {
-        Enumerate { iter, count: 0 }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I> Iterator for Enumerate<I>
-where
-    I: Iterator,
-{
-    type Item = (usize, <I as Iterator>::Item);
-
-    /// # Overflow Behavior
-    ///
-    /// The method does no guarding against overflows, so enumerating more than
-    /// `usize::MAX` elements either produces the wrong result or panics. If
-    /// debug assertions are enabled, a panic is guaranteed.
-    ///
-    /// # Panics
-    ///
-    /// Might panic if the index of the element overflows a `usize`.
-    #[inline]
-    fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
-        let a = self.iter.next()?;
-        let i = self.count;
-        // Possible undefined overflow.
-        AddAssign::add_assign(&mut self.count, 1);
-        Some((i, a))
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-
-    #[inline]
-    fn nth(&mut self, n: usize) -> Option<(usize, I::Item)> {
-        let a = self.iter.nth(n)?;
-        // Possible undefined overflow.
-        let i = Add::add(self.count, n);
-        self.count = Add::add(i, 1);
-        Some((i, a))
-    }
-
-    #[inline]
-    fn count(self) -> usize {
-        self.iter.count()
-    }
-
-    #[inline]
-    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
-    where
-        Self: Sized,
-        Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
-    {
-        #[inline]
-        fn enumerate<'a, T, Acc, R>(
-            count: &'a mut usize,
-            mut fold: impl FnMut(Acc, (usize, T)) -> R + 'a,
-        ) -> impl FnMut(Acc, T) -> R + 'a {
-            move |acc, item| {
-                let acc = fold(acc, (*count, item));
-                // Possible undefined overflow.
-                AddAssign::add_assign(count, 1);
-                acc
-            }
-        }
-
-        self.iter.try_fold(init, enumerate(&mut self.count, fold))
-    }
-
-    #[inline]
-    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
-    where
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-    {
-        #[inline]
-        fn enumerate<T, Acc>(
-            mut count: usize,
-            mut fold: impl FnMut(Acc, (usize, T)) -> Acc,
-        ) -> impl FnMut(Acc, T) -> Acc {
-            move |acc, item| {
-                let acc = fold(acc, (count, item));
-                // Possible undefined overflow.
-                AddAssign::add_assign(&mut count, 1);
-                acc
-            }
-        }
-
-        self.iter.fold(init, enumerate(self.count, fold))
-    }
-
-    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item
-    where
-        Self: TrustedRandomAccess,
-    {
-        // SAFETY: the caller must uphold the contract for
-        // `Iterator::__iterator_get_unchecked`.
-        let value = unsafe { try_get_unchecked(&mut self.iter, idx) };
-        (Add::add(self.count, idx), value)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I> DoubleEndedIterator for Enumerate<I>
-where
-    I: ExactSizeIterator + DoubleEndedIterator,
-{
-    #[inline]
-    fn next_back(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
-        let a = self.iter.next_back()?;
-        let len = self.iter.len();
-        // Can safely add, `ExactSizeIterator` promises that the number of
-        // elements fits into a `usize`.
-        Some((self.count + len, a))
-    }
-
-    #[inline]
-    fn nth_back(&mut self, n: usize) -> Option<(usize, <I as Iterator>::Item)> {
-        let a = self.iter.nth_back(n)?;
-        let len = self.iter.len();
-        // Can safely add, `ExactSizeIterator` promises that the number of
-        // elements fits into a `usize`.
-        Some((self.count + len, a))
-    }
-
-    #[inline]
-    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
-    where
-        Self: Sized,
-        Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
-    {
-        // Can safely add and subtract the count, as `ExactSizeIterator` promises
-        // that the number of elements fits into a `usize`.
-        fn enumerate<T, Acc, R>(
-            mut count: usize,
-            mut fold: impl FnMut(Acc, (usize, T)) -> R,
-        ) -> impl FnMut(Acc, T) -> R {
-            move |acc, item| {
-                count -= 1;
-                fold(acc, (count, item))
-            }
-        }
-
-        let count = self.count + self.iter.len();
-        self.iter.try_rfold(init, enumerate(count, fold))
-    }
-
-    #[inline]
-    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
-    where
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-    {
-        // Can safely add and subtract the count, as `ExactSizeIterator` promises
-        // that the number of elements fits into a `usize`.
-        fn enumerate<T, Acc>(
-            mut count: usize,
-            mut fold: impl FnMut(Acc, (usize, T)) -> Acc,
-        ) -> impl FnMut(Acc, T) -> Acc {
-            move |acc, item| {
-                count -= 1;
-                fold(acc, (count, item))
-            }
-        }
-
-        let count = self.count + self.iter.len();
-        self.iter.rfold(init, enumerate(count, fold))
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I> ExactSizeIterator for Enumerate<I>
-where
-    I: ExactSizeIterator,
-{
-    fn len(&self) -> usize {
-        self.iter.len()
-    }
-
-    fn is_empty(&self) -> bool {
-        self.iter.is_empty()
-    }
-}
-
-#[doc(hidden)]
-#[unstable(feature = "trusted_random_access", issue = "none")]
-unsafe impl<I> TrustedRandomAccess for Enumerate<I>
-where
-    I: TrustedRandomAccess,
-{
-    fn may_have_side_effect() -> bool {
-        I::may_have_side_effect()
-    }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<I> FusedIterator for Enumerate<I> where I: FusedIterator {}
-
-#[unstable(feature = "trusted_len", issue = "37572")]
-unsafe impl<I> TrustedLen for Enumerate<I> where I: TrustedLen {}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<S: Iterator, I: Iterator> SourceIter for Enumerate<I>
-where
-    I: SourceIter<Source = S>,
-{
-    type Source = S;
-
-    #[inline]
-    unsafe fn as_inner(&mut self) -> &mut S {
-        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
-        unsafe { SourceIter::as_inner(&mut self.iter) }
-    }
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: InPlaceIterable> InPlaceIterable for Enumerate<I> {}
-
-/// An iterator with a `peek()` that returns an optional reference to the next
-/// element.
-///
-/// This `struct` is created by the [`peekable`] method on [`Iterator`]. See its
-/// documentation for more.
-///
-/// [`peekable`]: Iterator::peekable
-/// [`Iterator`]: trait.Iterator.html
-#[derive(Clone, Debug)]
-#[must_use = "iterators are lazy and do nothing unless consumed"]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Peekable<I: Iterator> {
-    iter: I,
-    /// Remember a peeked value, even if it was None.
-    peeked: Option<Option<I::Item>>,
-}
-impl<I: Iterator> Peekable<I> {
-    pub(super) fn new(iter: I) -> Peekable<I> {
-        Peekable { iter, peeked: None }
-    }
-}
-
-// Peekable must remember if a None has been seen in the `.peek()` method.
-// It ensures that `.peek(); .peek();` or `.peek(); .next();` only advances the
-// underlying iterator at most once. This does not by itself make the iterator
-// fused.
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I: Iterator> Iterator for Peekable<I> {
-    type Item = I::Item;
-
-    #[inline]
-    fn next(&mut self) -> Option<I::Item> {
-        match self.peeked.take() {
-            Some(v) => v,
-            None => self.iter.next(),
-        }
-    }
-
-    #[inline]
-    #[rustc_inherit_overflow_checks]
-    fn count(mut self) -> usize {
-        match self.peeked.take() {
-            Some(None) => 0,
-            Some(Some(_)) => 1 + self.iter.count(),
-            None => self.iter.count(),
-        }
-    }
-
-    #[inline]
-    fn nth(&mut self, n: usize) -> Option<I::Item> {
-        match self.peeked.take() {
-            Some(None) => None,
-            Some(v @ Some(_)) if n == 0 => v,
-            Some(Some(_)) => self.iter.nth(n - 1),
-            None => self.iter.nth(n),
-        }
-    }
-
-    #[inline]
-    fn last(mut self) -> Option<I::Item> {
-        let peek_opt = match self.peeked.take() {
-            Some(None) => return None,
-            Some(v) => v,
-            None => None,
-        };
-        self.iter.last().or(peek_opt)
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let peek_len = match self.peeked {
-            Some(None) => return (0, Some(0)),
-            Some(Some(_)) => 1,
-            None => 0,
-        };
-        let (lo, hi) = self.iter.size_hint();
-        let lo = lo.saturating_add(peek_len);
-        let hi = match hi {
-            Some(x) => x.checked_add(peek_len),
-            None => None,
-        };
-        (lo, hi)
-    }
-
-    #[inline]
-    fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
-    where
-        Self: Sized,
-        F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
-    {
-        let acc = match self.peeked.take() {
-            Some(None) => return try { init },
-            Some(Some(v)) => f(init, v)?,
-            None => init,
-        };
-        self.iter.try_fold(acc, f)
-    }
-
-    #[inline]
-    fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
-    where
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-    {
-        let acc = match self.peeked {
-            Some(None) => return init,
-            Some(Some(v)) => fold(init, v),
-            None => init,
-        };
-        self.iter.fold(acc, fold)
-    }
-}
-
-#[stable(feature = "double_ended_peek_iterator", since = "1.38.0")]
-impl<I> DoubleEndedIterator for Peekable<I>
-where
-    I: DoubleEndedIterator,
-{
-    #[inline]
-    fn next_back(&mut self) -> Option<Self::Item> {
-        match self.peeked.as_mut() {
-            Some(v @ Some(_)) => self.iter.next_back().or_else(|| v.take()),
-            Some(None) => None,
-            None => self.iter.next_back(),
-        }
-    }
-
-    #[inline]
-    fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
-    where
-        Self: Sized,
-        F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
-    {
-        match self.peeked.take() {
-            Some(None) => try { init },
-            Some(Some(v)) => match self.iter.try_rfold(init, &mut f).into_result() {
-                Ok(acc) => f(acc, v),
-                Err(e) => {
-                    self.peeked = Some(Some(v));
-                    Try::from_error(e)
-                }
-            },
-            None => self.iter.try_rfold(init, f),
-        }
-    }
-
-    #[inline]
-    fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
-    where
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-    {
-        match self.peeked {
-            Some(None) => init,
-            Some(Some(v)) => {
-                let acc = self.iter.rfold(init, &mut fold);
-                fold(acc, v)
-            }
-            None => self.iter.rfold(init, fold),
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I: ExactSizeIterator> ExactSizeIterator for Peekable<I> {}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<I: FusedIterator> FusedIterator for Peekable<I> {}
-
-impl<I: Iterator> Peekable<I> {
-    /// Returns a reference to the next() value without advancing the iterator.
-    ///
-    /// Like [`next`], if there is a value, it is wrapped in a `Some(T)`.
-    /// But if the iteration is over, `None` is returned.
-    ///
-    /// [`next`]: Iterator::next
-    ///
-    /// Because `peek()` returns a reference, and many iterators iterate over
-    /// references, there can be a possibly confusing situation where the
-    /// return value is a double reference. You can see this effect in the
-    /// examples below.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let xs = [1, 2, 3];
-    ///
-    /// let mut iter = xs.iter().peekable();
-    ///
-    /// // peek() lets us see into the future
-    /// assert_eq!(iter.peek(), Some(&&1));
-    /// assert_eq!(iter.next(), Some(&1));
-    ///
-    /// assert_eq!(iter.next(), Some(&2));
-    ///
-    /// // The iterator does not advance even if we `peek` multiple times
-    /// assert_eq!(iter.peek(), Some(&&3));
-    /// assert_eq!(iter.peek(), Some(&&3));
-    ///
-    /// assert_eq!(iter.next(), Some(&3));
-    ///
-    /// // After the iterator is finished, so is `peek()`
-    /// assert_eq!(iter.peek(), None);
-    /// assert_eq!(iter.next(), None);
-    /// ```
-    #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn peek(&mut self) -> Option<&I::Item> {
-        let iter = &mut self.iter;
-        self.peeked.get_or_insert_with(|| iter.next()).as_ref()
-    }
-
-    /// Consume and return the next value of this iterator if a condition is true.
-    ///
-    /// If `func` returns `true` for the next value of this iterator, consume and return it.
-    /// Otherwise, return `None`.
-    ///
-    /// # Examples
-    /// Consume a number if it's equal to 0.
-    /// ```
-    /// #![feature(peekable_next_if)]
-    /// let mut iter = (0..5).peekable();
-    /// // The first item of the iterator is 0; consume it.
-    /// assert_eq!(iter.next_if(|&x| x == 0), Some(0));
-    /// // The next item returned is now 1, so `consume` will return `false`.
-    /// assert_eq!(iter.next_if(|&x| x == 0), None);
-    /// // `next_if` saves the value of the next item if it was not equal to `expected`.
-    /// assert_eq!(iter.next(), Some(1));
-    /// ```
-    ///
-    /// Consume any number less than 10.
-    /// ```
-    /// #![feature(peekable_next_if)]
-    /// let mut iter = (1..20).peekable();
-    /// // Consume all numbers less than 10
-    /// while iter.next_if(|&x| x < 10).is_some() {}
-    /// // The next value returned will be 10
-    /// assert_eq!(iter.next(), Some(10));
-    /// ```
-    #[unstable(feature = "peekable_next_if", issue = "72480")]
-    pub fn next_if(&mut self, func: impl FnOnce(&I::Item) -> bool) -> Option<I::Item> {
-        match self.next() {
-            Some(matched) if func(&matched) => Some(matched),
-            other => {
-                // Since we called `self.next()`, we consumed `self.peeked`.
-                assert!(self.peeked.is_none());
-                self.peeked = Some(other);
-                None
-            }
-        }
-    }
-
-    /// Consume and return the next item if it is equal to `expected`.
-    ///
-    /// # Example
-    /// Consume a number if it's equal to 0.
-    /// ```
-    /// #![feature(peekable_next_if)]
-    /// let mut iter = (0..5).peekable();
-    /// // The first item of the iterator is 0; consume it.
-    /// assert_eq!(iter.next_if_eq(&0), Some(0));
-    /// // The next item returned is now 1, so `consume` will return `false`.
-    /// assert_eq!(iter.next_if_eq(&0), None);
-    /// // `next_if_eq` saves the value of the next item if it was not equal to `expected`.
-    /// assert_eq!(iter.next(), Some(1));
-    /// ```
-    #[unstable(feature = "peekable_next_if", issue = "72480")]
-    pub fn next_if_eq<T>(&mut self, expected: &T) -> Option<I::Item>
-    where
-        T: ?Sized,
-        I::Item: PartialEq<T>,
-    {
-        self.next_if(|next| next == expected)
-    }
-}
-
-#[unstable(feature = "trusted_len", issue = "37572")]
-unsafe impl<I> TrustedLen for Peekable<I> where I: TrustedLen {}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<S: Iterator, I: Iterator> SourceIter for Peekable<I>
-where
-    I: SourceIter<Source = S>,
-{
-    type Source = S;
-
-    #[inline]
-    unsafe fn as_inner(&mut self) -> &mut S {
-        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
-        unsafe { SourceIter::as_inner(&mut self.iter) }
-    }
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: InPlaceIterable> InPlaceIterable for Peekable<I> {}
-
-/// An iterator that rejects elements while `predicate` returns `true`.
-///
-/// This `struct` is created by the [`skip_while`] method on [`Iterator`]. See its
-/// documentation for more.
-///
-/// [`skip_while`]: Iterator::skip_while
-/// [`Iterator`]: trait.Iterator.html
-#[must_use = "iterators are lazy and do nothing unless consumed"]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Clone)]
-pub struct SkipWhile<I, P> {
-    iter: I,
-    flag: bool,
-    predicate: P,
-}
-impl<I, P> SkipWhile<I, P> {
-    pub(super) fn new(iter: I, predicate: P) -> SkipWhile<I, P> {
-        SkipWhile { iter, flag: false, predicate }
-    }
-}
-
-#[stable(feature = "core_impl_debug", since = "1.9.0")]
-impl<I: fmt::Debug, P> fmt::Debug for SkipWhile<I, P> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("SkipWhile").field("iter", &self.iter).field("flag", &self.flag).finish()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I: Iterator, P> Iterator for SkipWhile<I, P>
-where
-    P: FnMut(&I::Item) -> bool,
-{
-    type Item = I::Item;
-
-    #[inline]
-    fn next(&mut self) -> Option<I::Item> {
-        fn check<'a, T>(
-            flag: &'a mut bool,
-            pred: &'a mut impl FnMut(&T) -> bool,
-        ) -> impl FnMut(&T) -> bool + 'a {
-            move |x| {
-                if *flag || !pred(x) {
-                    *flag = true;
-                    true
-                } else {
-                    false
-                }
-            }
-        }
-
-        let flag = &mut self.flag;
-        let pred = &mut self.predicate;
-        self.iter.find(check(flag, pred))
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (_, upper) = self.iter.size_hint();
-        (0, upper) // can't know a lower bound, due to the predicate
-    }
-
-    #[inline]
-    fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R
-    where
-        Self: Sized,
-        Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
-    {
-        if !self.flag {
-            match self.next() {
-                Some(v) => init = fold(init, v)?,
-                None => return try { init },
-            }
-        }
-        self.iter.try_fold(init, fold)
-    }
-
-    #[inline]
-    fn fold<Acc, Fold>(mut self, mut init: Acc, mut fold: Fold) -> Acc
-    where
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-    {
-        if !self.flag {
-            match self.next() {
-                Some(v) => init = fold(init, v),
-                None => return init,
-            }
-        }
-        self.iter.fold(init, fold)
-    }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<I, P> FusedIterator for SkipWhile<I, P>
-where
-    I: FusedIterator,
-    P: FnMut(&I::Item) -> bool,
-{
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<S: Iterator, P, I: Iterator> SourceIter for SkipWhile<I, P>
-where
-    P: FnMut(&I::Item) -> bool,
-    I: SourceIter<Source = S>,
-{
-    type Source = S;
-
-    #[inline]
-    unsafe fn as_inner(&mut self) -> &mut S {
-        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
-        unsafe { SourceIter::as_inner(&mut self.iter) }
-    }
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: InPlaceIterable, F> InPlaceIterable for SkipWhile<I, F> where
-    F: FnMut(&I::Item) -> bool
-{
-}
-
-/// An iterator that only accepts elements while `predicate` returns `true`.
-///
-/// This `struct` is created by the [`take_while`] method on [`Iterator`]. See its
-/// documentation for more.
-///
-/// [`take_while`]: Iterator::take_while
-/// [`Iterator`]: trait.Iterator.html
-#[must_use = "iterators are lazy and do nothing unless consumed"]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Clone)]
-pub struct TakeWhile<I, P> {
-    iter: I,
-    flag: bool,
-    predicate: P,
-}
-impl<I, P> TakeWhile<I, P> {
-    pub(super) fn new(iter: I, predicate: P) -> TakeWhile<I, P> {
-        TakeWhile { iter, flag: false, predicate }
-    }
-}
-
-#[stable(feature = "core_impl_debug", since = "1.9.0")]
-impl<I: fmt::Debug, P> fmt::Debug for TakeWhile<I, P> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("TakeWhile").field("iter", &self.iter).field("flag", &self.flag).finish()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I: Iterator, P> Iterator for TakeWhile<I, P>
-where
-    P: FnMut(&I::Item) -> bool,
-{
-    type Item = I::Item;
-
-    #[inline]
-    fn next(&mut self) -> Option<I::Item> {
-        if self.flag {
-            None
-        } else {
-            let x = self.iter.next()?;
-            if (self.predicate)(&x) {
-                Some(x)
-            } else {
-                self.flag = true;
-                None
-            }
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        if self.flag {
-            (0, Some(0))
-        } else {
-            let (_, upper) = self.iter.size_hint();
-            (0, upper) // can't know a lower bound, due to the predicate
-        }
-    }
-
-    #[inline]
-    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
-    where
-        Self: Sized,
-        Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
-    {
-        fn check<'a, T, Acc, R: Try<Ok = Acc>>(
-            flag: &'a mut bool,
-            p: &'a mut impl FnMut(&T) -> bool,
-            mut fold: impl FnMut(Acc, T) -> R + 'a,
-        ) -> impl FnMut(Acc, T) -> ControlFlow<R, Acc> + 'a {
-            move |acc, x| {
-                if p(&x) {
-                    ControlFlow::from_try(fold(acc, x))
-                } else {
-                    *flag = true;
-                    ControlFlow::Break(try { acc })
-                }
-            }
-        }
-
-        if self.flag {
-            try { init }
-        } else {
-            let flag = &mut self.flag;
-            let p = &mut self.predicate;
-            self.iter.try_fold(init, check(flag, p, fold)).into_try()
-        }
-    }
-
-    #[inline]
-    fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
-    where
-        Self: Sized,
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-    {
-        #[inline]
-        fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
-            move |acc, x| Ok(f(acc, x))
-        }
-
-        self.try_fold(init, ok(fold)).unwrap()
-    }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<I, P> FusedIterator for TakeWhile<I, P>
-where
-    I: FusedIterator,
-    P: FnMut(&I::Item) -> bool,
-{
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<S: Iterator, P, I: Iterator> SourceIter for TakeWhile<I, P>
-where
-    P: FnMut(&I::Item) -> bool,
-    I: SourceIter<Source = S>,
-{
-    type Source = S;
-
-    #[inline]
-    unsafe fn as_inner(&mut self) -> &mut S {
-        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
-        unsafe { SourceIter::as_inner(&mut self.iter) }
-    }
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: InPlaceIterable, F> InPlaceIterable for TakeWhile<I, F> where
-    F: FnMut(&I::Item) -> bool
-{
-}
-
-/// An iterator that only accepts elements while `predicate` returns `Some(_)`.
-///
-/// This `struct` is created by the [`map_while`] method on [`Iterator`]. See its
-/// documentation for more.
-///
-/// [`map_while`]: Iterator::map_while
-/// [`Iterator`]: trait.Iterator.html
-#[must_use = "iterators are lazy and do nothing unless consumed"]
-#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
-#[derive(Clone)]
-pub struct MapWhile<I, P> {
-    iter: I,
-    predicate: P,
-}
-
-impl<I, P> MapWhile<I, P> {
-    pub(super) fn new(iter: I, predicate: P) -> MapWhile<I, P> {
-        MapWhile { iter, predicate }
-    }
-}
-
-#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
-impl<I: fmt::Debug, P> fmt::Debug for MapWhile<I, P> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("MapWhile").field("iter", &self.iter).finish()
-    }
-}
-
-#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
-impl<B, I: Iterator, P> Iterator for MapWhile<I, P>
-where
-    P: FnMut(I::Item) -> Option<B>,
-{
-    type Item = B;
-
-    #[inline]
-    fn next(&mut self) -> Option<B> {
-        let x = self.iter.next()?;
-        (self.predicate)(x)
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (_, upper) = self.iter.size_hint();
-        (0, upper) // can't know a lower bound, due to the predicate
-    }
-
-    #[inline]
-    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R
-    where
-        Self: Sized,
-        Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
-    {
-        let Self { iter, predicate } = self;
-        iter.try_fold(init, |acc, x| match predicate(x) {
-            Some(item) => ControlFlow::from_try(fold(acc, item)),
-            None => ControlFlow::Break(try { acc }),
-        })
-        .into_try()
-    }
-
-    #[inline]
-    fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
-    where
-        Self: Sized,
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-    {
-        #[inline]
-        fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
-            move |acc, x| Ok(f(acc, x))
-        }
-
-        self.try_fold(init, ok(fold)).unwrap()
-    }
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<S: Iterator, B, I: Iterator, P> SourceIter for MapWhile<I, P>
-where
-    P: FnMut(I::Item) -> Option<B>,
-    I: SourceIter<Source = S>,
-{
-    type Source = S;
-
-    #[inline]
-    unsafe fn as_inner(&mut self) -> &mut S {
-        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
-        unsafe { SourceIter::as_inner(&mut self.iter) }
-    }
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<B, I: InPlaceIterable, P> InPlaceIterable for MapWhile<I, P> where
-    P: FnMut(I::Item) -> Option<B>
-{
-}
-
-/// An iterator that skips over `n` elements of `iter`.
-///
-/// This `struct` is created by the [`skip`] method on [`Iterator`]. See its
-/// documentation for more.
-///
-/// [`skip`]: Iterator::skip
-/// [`Iterator`]: trait.Iterator.html
-#[derive(Clone, Debug)]
-#[must_use = "iterators are lazy and do nothing unless consumed"]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Skip<I> {
-    iter: I,
-    n: usize,
-}
-impl<I> Skip<I> {
-    pub(super) fn new(iter: I, n: usize) -> Skip<I> {
-        Skip { iter, n }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I> Iterator for Skip<I>
-where
-    I: Iterator,
-{
-    type Item = <I as Iterator>::Item;
-
-    #[inline]
-    fn next(&mut self) -> Option<I::Item> {
-        if self.n == 0 {
-            self.iter.next()
-        } else {
-            let old_n = self.n;
-            self.n = 0;
-            self.iter.nth(old_n)
-        }
-    }
-
-    #[inline]
-    fn nth(&mut self, n: usize) -> Option<I::Item> {
-        // Can't just add n + self.n due to overflow.
-        if self.n > 0 {
-            let to_skip = self.n;
-            self.n = 0;
-            // nth(n) skips n+1
-            self.iter.nth(to_skip - 1)?;
-        }
-        self.iter.nth(n)
-    }
-
-    #[inline]
-    fn count(mut self) -> usize {
-        if self.n > 0 {
-            // nth(n) skips n+1
-            if self.iter.nth(self.n - 1).is_none() {
-                return 0;
-            }
-        }
-        self.iter.count()
-    }
-
-    #[inline]
-    fn last(mut self) -> Option<I::Item> {
-        if self.n > 0 {
-            // nth(n) skips n+1
-            self.iter.nth(self.n - 1)?;
-        }
-        self.iter.last()
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (lower, upper) = self.iter.size_hint();
-
-        let lower = lower.saturating_sub(self.n);
-        let upper = match upper {
-            Some(x) => Some(x.saturating_sub(self.n)),
-            None => None,
-        };
-
-        (lower, upper)
-    }
-
-    #[inline]
-    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
-    where
-        Self: Sized,
-        Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
-    {
-        let n = self.n;
-        self.n = 0;
-        if n > 0 {
-            // nth(n) skips n+1
-            if self.iter.nth(n - 1).is_none() {
-                return try { init };
-            }
-        }
-        self.iter.try_fold(init, fold)
-    }
-
-    #[inline]
-    fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
-    where
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-    {
-        if self.n > 0 {
-            // nth(n) skips n+1
-            if self.iter.nth(self.n - 1).is_none() {
-                return init;
-            }
-        }
-        self.iter.fold(init, fold)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I> ExactSizeIterator for Skip<I> where I: ExactSizeIterator {}
-
-#[stable(feature = "double_ended_skip_iterator", since = "1.9.0")]
-impl<I> DoubleEndedIterator for Skip<I>
-where
-    I: DoubleEndedIterator + ExactSizeIterator,
-{
-    fn next_back(&mut self) -> Option<Self::Item> {
-        if self.len() > 0 { self.iter.next_back() } else { None }
-    }
-
-    #[inline]
-    fn nth_back(&mut self, n: usize) -> Option<I::Item> {
-        let len = self.len();
-        if n < len {
-            self.iter.nth_back(n)
-        } else {
-            if len > 0 {
-                // consume the original iterator
-                self.iter.nth_back(len - 1);
-            }
-            None
-        }
-    }
-
-    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
-    where
-        Self: Sized,
-        Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
-    {
-        fn check<T, Acc, R: Try<Ok = Acc>>(
-            mut n: usize,
-            mut fold: impl FnMut(Acc, T) -> R,
-        ) -> impl FnMut(Acc, T) -> ControlFlow<R, Acc> {
-            move |acc, x| {
-                n -= 1;
-                let r = fold(acc, x);
-                if n == 0 { ControlFlow::Break(r) } else { ControlFlow::from_try(r) }
-            }
-        }
-
-        let n = self.len();
-        if n == 0 { try { init } } else { self.iter.try_rfold(init, check(n, fold)).into_try() }
-    }
-
-    fn rfold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
-    where
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-    {
-        #[inline]
-        fn ok<Acc, T>(mut f: impl FnMut(Acc, T) -> Acc) -> impl FnMut(Acc, T) -> Result<Acc, !> {
-            move |acc, x| Ok(f(acc, x))
-        }
-
-        self.try_rfold(init, ok(fold)).unwrap()
-    }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<I> FusedIterator for Skip<I> where I: FusedIterator {}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<S: Iterator, I: Iterator> SourceIter for Skip<I>
-where
-    I: SourceIter<Source = S>,
-{
-    type Source = S;
-
-    #[inline]
-    unsafe fn as_inner(&mut self) -> &mut S {
-        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
-        unsafe { SourceIter::as_inner(&mut self.iter) }
-    }
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: InPlaceIterable> InPlaceIterable for Skip<I> {}
-
-/// An iterator that only iterates over the first `n` iterations of `iter`.
-///
-/// This `struct` is created by the [`take`] method on [`Iterator`]. See its
-/// documentation for more.
-///
-/// [`take`]: Iterator::take
-/// [`Iterator`]: trait.Iterator.html
-#[derive(Clone, Debug)]
-#[must_use = "iterators are lazy and do nothing unless consumed"]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Take<I> {
-    pub(super) iter: I,
-    pub(super) n: usize,
-}
-impl<I> Take<I> {
-    pub(super) fn new(iter: I, n: usize) -> Take<I> {
-        Take { iter, n }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I> Iterator for Take<I>
-where
-    I: Iterator,
-{
-    type Item = <I as Iterator>::Item;
-
-    #[inline]
-    fn next(&mut self) -> Option<<I as Iterator>::Item> {
-        if self.n != 0 {
-            self.n -= 1;
-            self.iter.next()
-        } else {
-            None
-        }
-    }
-
-    #[inline]
-    fn nth(&mut self, n: usize) -> Option<I::Item> {
-        if self.n > n {
-            self.n -= n + 1;
-            self.iter.nth(n)
-        } else {
-            if self.n > 0 {
-                self.iter.nth(self.n - 1);
-                self.n = 0;
-            }
-            None
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        if self.n == 0 {
-            return (0, Some(0));
-        }
-
-        let (lower, upper) = self.iter.size_hint();
-
-        let lower = cmp::min(lower, self.n);
-
-        let upper = match upper {
-            Some(x) if x < self.n => Some(x),
-            _ => Some(self.n),
-        };
-
-        (lower, upper)
-    }
-
-    #[inline]
-    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
-    where
-        Self: Sized,
-        Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
-    {
-        fn check<'a, T, Acc, R: Try<Ok = Acc>>(
-            n: &'a mut usize,
-            mut fold: impl FnMut(Acc, T) -> R + 'a,
-        ) -> impl FnMut(Acc, T) -> ControlFlow<R, Acc> + 'a {
-            move |acc, x| {
-                *n -= 1;
-                let r = fold(acc, x);
-                if *n == 0 { ControlFlow::Break(r) } else { ControlFlow::from_try(r) }
-            }
-        }
-
-        if self.n == 0 {
-            try { init }
-        } else {
-            let n = &mut self.n;
-            self.iter.try_fold(init, check(n, fold)).into_try()
-        }
-    }
-
-    #[inline]
-    fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
-    where
-        Self: Sized,
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-    {
-        #[inline]
-        fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
-            move |acc, x| Ok(f(acc, x))
-        }
-
-        self.try_fold(init, ok(fold)).unwrap()
-    }
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<S: Iterator, I: Iterator> SourceIter for Take<I>
-where
-    I: SourceIter<Source = S>,
-{
-    type Source = S;
-
-    #[inline]
-    unsafe fn as_inner(&mut self) -> &mut S {
-        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
-        unsafe { SourceIter::as_inner(&mut self.iter) }
-    }
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: InPlaceIterable> InPlaceIterable for Take<I> {}
-
-#[stable(feature = "double_ended_take_iterator", since = "1.38.0")]
-impl<I> DoubleEndedIterator for Take<I>
-where
-    I: DoubleEndedIterator + ExactSizeIterator,
-{
-    #[inline]
-    fn next_back(&mut self) -> Option<Self::Item> {
-        if self.n == 0 {
-            None
-        } else {
-            let n = self.n;
-            self.n -= 1;
-            self.iter.nth_back(self.iter.len().saturating_sub(n))
-        }
-    }
-
-    #[inline]
-    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
-        let len = self.iter.len();
-        if self.n > n {
-            let m = len.saturating_sub(self.n) + n;
-            self.n -= n + 1;
-            self.iter.nth_back(m)
-        } else {
-            if len > 0 {
-                self.iter.nth_back(len - 1);
-            }
-            None
-        }
-    }
-
-    #[inline]
-    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
-    where
-        Self: Sized,
-        Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
-    {
-        if self.n == 0 {
-            try { init }
-        } else {
-            let len = self.iter.len();
-            if len > self.n && self.iter.nth_back(len - self.n - 1).is_none() {
-                try { init }
-            } else {
-                self.iter.try_rfold(init, fold)
-            }
-        }
-    }
-
-    #[inline]
-    fn rfold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
-    where
-        Self: Sized,
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-    {
-        if self.n == 0 {
-            init
-        } else {
-            let len = self.iter.len();
-            if len > self.n && self.iter.nth_back(len - self.n - 1).is_none() {
-                init
-            } else {
-                self.iter.rfold(init, fold)
-            }
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I> ExactSizeIterator for Take<I> where I: ExactSizeIterator {}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<I> FusedIterator for Take<I> where I: FusedIterator {}
-
-#[unstable(feature = "trusted_len", issue = "37572")]
-unsafe impl<I: TrustedLen> TrustedLen for Take<I> {}
-
-/// An iterator to maintain state while iterating another iterator.
-///
-/// This `struct` is created by the [`scan`] method on [`Iterator`]. See its
-/// documentation for more.
-///
-/// [`scan`]: Iterator::scan
-/// [`Iterator`]: trait.Iterator.html
-#[must_use = "iterators are lazy and do nothing unless consumed"]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Clone)]
-pub struct Scan<I, St, F> {
-    iter: I,
-    f: F,
-    state: St,
-}
-impl<I, St, F> Scan<I, St, F> {
-    pub(super) fn new(iter: I, state: St, f: F) -> Scan<I, St, F> {
-        Scan { iter, state, f }
-    }
-}
-
-#[stable(feature = "core_impl_debug", since = "1.9.0")]
-impl<I: fmt::Debug, St: fmt::Debug, F> fmt::Debug for Scan<I, St, F> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("Scan").field("iter", &self.iter).field("state", &self.state).finish()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<B, I, St, F> Iterator for Scan<I, St, F>
-where
-    I: Iterator,
-    F: FnMut(&mut St, I::Item) -> Option<B>,
-{
-    type Item = B;
-
-    #[inline]
-    fn next(&mut self) -> Option<B> {
-        let a = self.iter.next()?;
-        (self.f)(&mut self.state, a)
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (_, upper) = self.iter.size_hint();
-        (0, upper) // can't know a lower bound, due to the scan function
-    }
-
-    #[inline]
-    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
-    where
-        Self: Sized,
-        Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
-    {
-        fn scan<'a, T, St, B, Acc, R: Try<Ok = Acc>>(
-            state: &'a mut St,
-            f: &'a mut impl FnMut(&mut St, T) -> Option<B>,
-            mut fold: impl FnMut(Acc, B) -> R + 'a,
-        ) -> impl FnMut(Acc, T) -> ControlFlow<R, Acc> + 'a {
-            move |acc, x| match f(state, x) {
-                None => ControlFlow::Break(try { acc }),
-                Some(x) => ControlFlow::from_try(fold(acc, x)),
-            }
-        }
-
-        let state = &mut self.state;
-        let f = &mut self.f;
-        self.iter.try_fold(init, scan(state, f, fold)).into_try()
-    }
-
-    #[inline]
-    fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
-    where
-        Self: Sized,
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-    {
-        #[inline]
-        fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
-            move |acc, x| Ok(f(acc, x))
-        }
-
-        self.try_fold(init, ok(fold)).unwrap()
-    }
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<St, F, B, S: Iterator, I: Iterator> SourceIter for Scan<I, St, F>
-where
-    I: SourceIter<Source = S>,
-    F: FnMut(&mut St, I::Item) -> Option<B>,
-{
-    type Source = S;
-
-    #[inline]
-    unsafe fn as_inner(&mut self) -> &mut S {
-        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
-        unsafe { SourceIter::as_inner(&mut self.iter) }
-    }
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<St, F, B, I: InPlaceIterable> InPlaceIterable for Scan<I, St, F> where
-    F: FnMut(&mut St, I::Item) -> Option<B>
-{
-}
-
-/// An iterator that calls a function with a reference to each element before
-/// yielding it.
-///
-/// This `struct` is created by the [`inspect`] method on [`Iterator`]. See its
-/// documentation for more.
-///
-/// [`inspect`]: Iterator::inspect
-/// [`Iterator`]: trait.Iterator.html
-#[must_use = "iterators are lazy and do nothing unless consumed"]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Clone)]
-pub struct Inspect<I, F> {
-    iter: I,
-    f: F,
-}
-impl<I, F> Inspect<I, F> {
-    pub(super) fn new(iter: I, f: F) -> Inspect<I, F> {
-        Inspect { iter, f }
-    }
-}
-
-#[stable(feature = "core_impl_debug", since = "1.9.0")]
-impl<I: fmt::Debug, F> fmt::Debug for Inspect<I, F> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("Inspect").field("iter", &self.iter).finish()
-    }
-}
-
-impl<I: Iterator, F> Inspect<I, F>
-where
-    F: FnMut(&I::Item),
-{
-    #[inline]
-    fn do_inspect(&mut self, elt: Option<I::Item>) -> Option<I::Item> {
-        if let Some(ref a) = elt {
-            (self.f)(a);
-        }
-
-        elt
-    }
-}
-
-fn inspect_fold<T, Acc>(
-    mut f: impl FnMut(&T),
-    mut fold: impl FnMut(Acc, T) -> Acc,
-) -> impl FnMut(Acc, T) -> Acc {
-    move |acc, item| {
-        f(&item);
-        fold(acc, item)
-    }
-}
-
-fn inspect_try_fold<'a, T, Acc, R>(
-    f: &'a mut impl FnMut(&T),
-    mut fold: impl FnMut(Acc, T) -> R + 'a,
-) -> impl FnMut(Acc, T) -> R + 'a {
-    move |acc, item| {
-        f(&item);
-        fold(acc, item)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I: Iterator, F> Iterator for Inspect<I, F>
-where
-    F: FnMut(&I::Item),
-{
-    type Item = I::Item;
-
-    #[inline]
-    fn next(&mut self) -> Option<I::Item> {
-        let next = self.iter.next();
-        self.do_inspect(next)
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-
-    #[inline]
-    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
-    where
-        Self: Sized,
-        Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
-    {
-        self.iter.try_fold(init, inspect_try_fold(&mut self.f, fold))
-    }
-
-    #[inline]
-    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
-    where
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-    {
-        self.iter.fold(init, inspect_fold(self.f, fold))
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I: DoubleEndedIterator, F> DoubleEndedIterator for Inspect<I, F>
-where
-    F: FnMut(&I::Item),
-{
-    #[inline]
-    fn next_back(&mut self) -> Option<I::Item> {
-        let next = self.iter.next_back();
-        self.do_inspect(next)
-    }
-
-    #[inline]
-    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
-    where
-        Self: Sized,
-        Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
-    {
-        self.iter.try_rfold(init, inspect_try_fold(&mut self.f, fold))
-    }
-
-    #[inline]
-    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
-    where
-        Fold: FnMut(Acc, Self::Item) -> Acc,
-    {
-        self.iter.rfold(init, inspect_fold(self.f, fold))
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I: ExactSizeIterator, F> ExactSizeIterator for Inspect<I, F>
-where
-    F: FnMut(&I::Item),
-{
-    fn len(&self) -> usize {
-        self.iter.len()
-    }
-
-    fn is_empty(&self) -> bool {
-        self.iter.is_empty()
-    }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<I: FusedIterator, F> FusedIterator for Inspect<I, F> where F: FnMut(&I::Item) {}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<S: Iterator, I: Iterator, F> SourceIter for Inspect<I, F>
-where
-    F: FnMut(&I::Item),
-    I: SourceIter<Source = S>,
-{
-    type Source = S;
-
-    #[inline]
-    unsafe fn as_inner(&mut self) -> &mut S {
-        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
-        unsafe { SourceIter::as_inner(&mut self.iter) }
-    }
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: InPlaceIterable, F> InPlaceIterable for Inspect<I, F> where F: FnMut(&I::Item) {}
-
 /// An iterator adapter that produces output as long as the underlying
 /// iterator produces `Result::Ok` values.
 ///
diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs
new file mode 100644 (file)
index 0000000..ebdc255
--- /dev/null
@@ -0,0 +1,338 @@
+use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen};
+use crate::ops::Try;
+
+/// An iterator with a `peek()` that returns an optional reference to the next
+/// element.
+///
+/// This `struct` is created by the [`peekable`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`peekable`]: Iterator::peekable
+/// [`Iterator`]: trait.Iterator.html
+#[derive(Clone, Debug)]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Peekable<I: Iterator> {
+    iter: I,
+    /// Remember a peeked value, even if it was None.
+    peeked: Option<Option<I::Item>>,
+}
+
+impl<I: Iterator> Peekable<I> {
+    pub(in crate::iter) fn new(iter: I) -> Peekable<I> {
+        Peekable { iter, peeked: None }
+    }
+}
+
+// Peekable must remember if a None has been seen in the `.peek()` method.
+// It ensures that `.peek(); .peek();` or `.peek(); .next();` only advances the
+// underlying iterator at most once. This does not by itself make the iterator
+// fused.
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I: Iterator> Iterator for Peekable<I> {
+    type Item = I::Item;
+
+    #[inline]
+    fn next(&mut self) -> Option<I::Item> {
+        match self.peeked.take() {
+            Some(v) => v,
+            None => self.iter.next(),
+        }
+    }
+
+    #[inline]
+    #[rustc_inherit_overflow_checks]
+    fn count(mut self) -> usize {
+        match self.peeked.take() {
+            Some(None) => 0,
+            Some(Some(_)) => 1 + self.iter.count(),
+            None => self.iter.count(),
+        }
+    }
+
+    #[inline]
+    fn nth(&mut self, n: usize) -> Option<I::Item> {
+        match self.peeked.take() {
+            Some(None) => None,
+            Some(v @ Some(_)) if n == 0 => v,
+            Some(Some(_)) => self.iter.nth(n - 1),
+            None => self.iter.nth(n),
+        }
+    }
+
+    #[inline]
+    fn last(mut self) -> Option<I::Item> {
+        let peek_opt = match self.peeked.take() {
+            Some(None) => return None,
+            Some(v) => v,
+            None => None,
+        };
+        self.iter.last().or(peek_opt)
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let peek_len = match self.peeked {
+            Some(None) => return (0, Some(0)),
+            Some(Some(_)) => 1,
+            None => 0,
+        };
+        let (lo, hi) = self.iter.size_hint();
+        let lo = lo.saturating_add(peek_len);
+        let hi = match hi {
+            Some(x) => x.checked_add(peek_len),
+            None => None,
+        };
+        (lo, hi)
+    }
+
+    #[inline]
+    fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
+    where
+        Self: Sized,
+        F: FnMut(B, Self::Item) -> R,
+        R: Try<Ok = B>,
+    {
+        let acc = match self.peeked.take() {
+            Some(None) => return try { init },
+            Some(Some(v)) => f(init, v)?,
+            None => init,
+        };
+        self.iter.try_fold(acc, f)
+    }
+
+    #[inline]
+    fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+    where
+        Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        let acc = match self.peeked {
+            Some(None) => return init,
+            Some(Some(v)) => fold(init, v),
+            None => init,
+        };
+        self.iter.fold(acc, fold)
+    }
+}
+
+#[stable(feature = "double_ended_peek_iterator", since = "1.38.0")]
+impl<I> DoubleEndedIterator for Peekable<I>
+where
+    I: DoubleEndedIterator,
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<Self::Item> {
+        match self.peeked.as_mut() {
+            Some(v @ Some(_)) => self.iter.next_back().or_else(|| v.take()),
+            Some(None) => None,
+            None => self.iter.next_back(),
+        }
+    }
+
+    #[inline]
+    fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
+    where
+        Self: Sized,
+        F: FnMut(B, Self::Item) -> R,
+        R: Try<Ok = B>,
+    {
+        match self.peeked.take() {
+            Some(None) => try { init },
+            Some(Some(v)) => match self.iter.try_rfold(init, &mut f).into_result() {
+                Ok(acc) => f(acc, v),
+                Err(e) => {
+                    self.peeked = Some(Some(v));
+                    Try::from_error(e)
+                }
+            },
+            None => self.iter.try_rfold(init, f),
+        }
+    }
+
+    #[inline]
+    fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+    where
+        Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        match self.peeked {
+            Some(None) => init,
+            Some(Some(v)) => {
+                let acc = self.iter.rfold(init, &mut fold);
+                fold(acc, v)
+            }
+            None => self.iter.rfold(init, fold),
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I: ExactSizeIterator> ExactSizeIterator for Peekable<I> {}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<I: FusedIterator> FusedIterator for Peekable<I> {}
+
+impl<I: Iterator> Peekable<I> {
+    /// Returns a reference to the next() value without advancing the iterator.
+    ///
+    /// Like [`next`], if there is a value, it is wrapped in a `Some(T)`.
+    /// But if the iteration is over, `None` is returned.
+    ///
+    /// [`next`]: Iterator::next
+    ///
+    /// Because `peek()` returns a reference, and many iterators iterate over
+    /// references, there can be a possibly confusing situation where the
+    /// return value is a double reference. You can see this effect in the
+    /// examples below.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let xs = [1, 2, 3];
+    ///
+    /// let mut iter = xs.iter().peekable();
+    ///
+    /// // peek() lets us see into the future
+    /// assert_eq!(iter.peek(), Some(&&1));
+    /// assert_eq!(iter.next(), Some(&1));
+    ///
+    /// assert_eq!(iter.next(), Some(&2));
+    ///
+    /// // The iterator does not advance even if we `peek` multiple times
+    /// assert_eq!(iter.peek(), Some(&&3));
+    /// assert_eq!(iter.peek(), Some(&&3));
+    ///
+    /// assert_eq!(iter.next(), Some(&3));
+    ///
+    /// // After the iterator is finished, so is `peek()`
+    /// assert_eq!(iter.peek(), None);
+    /// assert_eq!(iter.next(), None);
+    /// ```
+    #[inline]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn peek(&mut self) -> Option<&I::Item> {
+        let iter = &mut self.iter;
+        self.peeked.get_or_insert_with(|| iter.next()).as_ref()
+    }
+
+    /// Returns a mutable reference to the next() value without advancing the iterator.
+    ///
+    /// Like [`next`], if there is a value, it is wrapped in a `Some(T)`.
+    /// But if the iteration is over, `None` is returned.
+    ///
+    /// Because `peek_mut()` returns a reference, and many iterators iterate over
+    /// references, there can be a possibly confusing situation where the
+    /// return value is a double reference. You can see this effect in the examples
+    /// below.
+    ///
+    /// [`next`]: Iterator::next
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(peekable_peek_mut)]
+    /// let mut iter = [1, 2, 3].iter().peekable();
+    ///
+    /// assert_eq!(iter.peek_mut(), Some(&mut &1));
+    /// assert_eq!(iter.next(), Some(&1));
+    ///
+    /// // Peek into the iterator and modify the value which will be returned next
+    /// if let Some(mut p) = iter.peek_mut() {
+    ///     if *p == &2 {
+    ///         *p = &5;
+    ///     }
+    /// }
+    ///
+    /// assert_eq!(iter.collect::<Vec<_>>(), vec![&5, &3]);
+    /// ```
+    #[inline]
+    #[unstable(feature = "peekable_peek_mut", issue = "78302")]
+    pub fn peek_mut(&mut self) -> Option<&mut I::Item> {
+        let iter = &mut self.iter;
+        self.peeked.get_or_insert_with(|| iter.next()).as_mut()
+    }
+
+    /// Consume and return the next value of this iterator if a condition is true.
+    ///
+    /// If `func` returns `true` for the next value of this iterator, consume and return it.
+    /// Otherwise, return `None`.
+    ///
+    /// # Examples
+    /// Consume a number if it's equal to 0.
+    /// ```
+    /// #![feature(peekable_next_if)]
+    /// let mut iter = (0..5).peekable();
+    /// // The first item of the iterator is 0; consume it.
+    /// assert_eq!(iter.next_if(|&x| x == 0), Some(0));
+    /// // The next item returned is now 1, so `consume` will return `false`.
+    /// assert_eq!(iter.next_if(|&x| x == 0), None);
+    /// // `next_if` saves the value of the next item if it was not equal to `expected`.
+    /// assert_eq!(iter.next(), Some(1));
+    /// ```
+    ///
+    /// Consume any number less than 10.
+    /// ```
+    /// #![feature(peekable_next_if)]
+    /// let mut iter = (1..20).peekable();
+    /// // Consume all numbers less than 10
+    /// while iter.next_if(|&x| x < 10).is_some() {}
+    /// // The next value returned will be 10
+    /// assert_eq!(iter.next(), Some(10));
+    /// ```
+    #[unstable(feature = "peekable_next_if", issue = "72480")]
+    pub fn next_if(&mut self, func: impl FnOnce(&I::Item) -> bool) -> Option<I::Item> {
+        match self.next() {
+            Some(matched) if func(&matched) => Some(matched),
+            other => {
+                // Since we called `self.next()`, we consumed `self.peeked`.
+                assert!(self.peeked.is_none());
+                self.peeked = Some(other);
+                None
+            }
+        }
+    }
+
+    /// Consume and return the next item if it is equal to `expected`.
+    ///
+    /// # Example
+    /// Consume a number if it's equal to 0.
+    /// ```
+    /// #![feature(peekable_next_if)]
+    /// let mut iter = (0..5).peekable();
+    /// // The first item of the iterator is 0; consume it.
+    /// assert_eq!(iter.next_if_eq(&0), Some(0));
+    /// // The next item returned is now 1, so `consume` will return `false`.
+    /// assert_eq!(iter.next_if_eq(&0), None);
+    /// // `next_if_eq` saves the value of the next item if it was not equal to `expected`.
+    /// assert_eq!(iter.next(), Some(1));
+    /// ```
+    #[unstable(feature = "peekable_next_if", issue = "72480")]
+    pub fn next_if_eq<T>(&mut self, expected: &T) -> Option<I::Item>
+    where
+        T: ?Sized,
+        I::Item: PartialEq<T>,
+    {
+        self.next_if(|next| next == expected)
+    }
+}
+
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<I> TrustedLen for Peekable<I> where I: TrustedLen {}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<S: Iterator, I: Iterator> SourceIter for Peekable<I>
+where
+    I: SourceIter<Source = S>,
+{
+    type Source = S;
+
+    #[inline]
+    unsafe fn as_inner(&mut self) -> &mut S {
+        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
+        unsafe { SourceIter::as_inner(&mut self.iter) }
+    }
+}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<I: InPlaceIterable> InPlaceIterable for Peekable<I> {}
diff --git a/library/core/src/iter/adapters/rev.rs b/library/core/src/iter/adapters/rev.rs
new file mode 100644 (file)
index 0000000..105ed40
--- /dev/null
@@ -0,0 +1,137 @@
+use crate::iter::{FusedIterator, TrustedLen};
+use crate::ops::Try;
+
+/// A double-ended iterator with the direction inverted.
+///
+/// This `struct` is created by the [`rev`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`rev`]: Iterator::rev
+/// [`Iterator`]: trait.Iterator.html
+#[derive(Clone, Debug)]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Rev<T> {
+    iter: T,
+}
+
+impl<T> Rev<T> {
+    pub(in crate::iter) fn new(iter: T) -> Rev<T> {
+        Rev { iter }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I> Iterator for Rev<I>
+where
+    I: DoubleEndedIterator,
+{
+    type Item = <I as Iterator>::Item;
+
+    #[inline]
+    fn next(&mut self) -> Option<<I as Iterator>::Item> {
+        self.iter.next_back()
+    }
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
+
+    #[inline]
+    fn advance_by(&mut self, n: usize) -> Result<(), usize> {
+        self.iter.advance_back_by(n)
+    }
+
+    #[inline]
+    fn nth(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
+        self.iter.nth_back(n)
+    }
+
+    fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
+    where
+        Self: Sized,
+        F: FnMut(B, Self::Item) -> R,
+        R: Try<Ok = B>,
+    {
+        self.iter.try_rfold(init, f)
+    }
+
+    fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
+    where
+        F: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.iter.rfold(init, f)
+    }
+
+    #[inline]
+    fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
+    where
+        P: FnMut(&Self::Item) -> bool,
+    {
+        self.iter.rfind(predicate)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I> DoubleEndedIterator for Rev<I>
+where
+    I: DoubleEndedIterator,
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
+        self.iter.next()
+    }
+
+    #[inline]
+    fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
+        self.iter.advance_by(n)
+    }
+
+    #[inline]
+    fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
+        self.iter.nth(n)
+    }
+
+    fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
+    where
+        Self: Sized,
+        F: FnMut(B, Self::Item) -> R,
+        R: Try<Ok = B>,
+    {
+        self.iter.try_fold(init, f)
+    }
+
+    fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
+    where
+        F: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.iter.fold(init, f)
+    }
+
+    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
+    where
+        P: FnMut(&Self::Item) -> bool,
+    {
+        self.iter.find(predicate)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I> ExactSizeIterator for Rev<I>
+where
+    I: ExactSizeIterator + DoubleEndedIterator,
+{
+    fn len(&self) -> usize {
+        self.iter.len()
+    }
+
+    fn is_empty(&self) -> bool {
+        self.iter.is_empty()
+    }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<I> FusedIterator for Rev<I> where I: FusedIterator + DoubleEndedIterator {}
+
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<I> TrustedLen for Rev<I> where I: TrustedLen + DoubleEndedIterator {}
diff --git a/library/core/src/iter/adapters/scan.rs b/library/core/src/iter/adapters/scan.rs
new file mode 100644 (file)
index 0000000..0214899
--- /dev/null
@@ -0,0 +1,111 @@
+use crate::fmt;
+use crate::iter::{adapters::SourceIter, InPlaceIterable};
+use crate::ops::{ControlFlow, Try};
+
+/// An iterator to maintain state while iterating another iterator.
+///
+/// This `struct` is created by the [`scan`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`scan`]: Iterator::scan
+/// [`Iterator`]: trait.Iterator.html
+#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Clone)]
+pub struct Scan<I, St, F> {
+    iter: I,
+    f: F,
+    state: St,
+}
+
+impl<I, St, F> Scan<I, St, F> {
+    pub(in crate::iter) fn new(iter: I, state: St, f: F) -> Scan<I, St, F> {
+        Scan { iter, state, f }
+    }
+}
+
+#[stable(feature = "core_impl_debug", since = "1.9.0")]
+impl<I: fmt::Debug, St: fmt::Debug, F> fmt::Debug for Scan<I, St, F> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("Scan").field("iter", &self.iter).field("state", &self.state).finish()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<B, I, St, F> Iterator for Scan<I, St, F>
+where
+    I: Iterator,
+    F: FnMut(&mut St, I::Item) -> Option<B>,
+{
+    type Item = B;
+
+    #[inline]
+    fn next(&mut self) -> Option<B> {
+        let a = self.iter.next()?;
+        (self.f)(&mut self.state, a)
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let (_, upper) = self.iter.size_hint();
+        (0, upper) // can't know a lower bound, due to the scan function
+    }
+
+    #[inline]
+    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        fn scan<'a, T, St, B, Acc, R: Try<Ok = Acc>>(
+            state: &'a mut St,
+            f: &'a mut impl FnMut(&mut St, T) -> Option<B>,
+            mut fold: impl FnMut(Acc, B) -> R + 'a,
+        ) -> impl FnMut(Acc, T) -> ControlFlow<R, Acc> + 'a {
+            move |acc, x| match f(state, x) {
+                None => ControlFlow::Break(try { acc }),
+                Some(x) => ControlFlow::from_try(fold(acc, x)),
+            }
+        }
+
+        let state = &mut self.state;
+        let f = &mut self.f;
+        self.iter.try_fold(init, scan(state, f, fold)).into_try()
+    }
+
+    #[inline]
+    fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        #[inline]
+        fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
+            move |acc, x| Ok(f(acc, x))
+        }
+
+        self.try_fold(init, ok(fold)).unwrap()
+    }
+}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<St, F, B, S: Iterator, I: Iterator> SourceIter for Scan<I, St, F>
+where
+    I: SourceIter<Source = S>,
+    F: FnMut(&mut St, I::Item) -> Option<B>,
+{
+    type Source = S;
+
+    #[inline]
+    unsafe fn as_inner(&mut self) -> &mut S {
+        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
+        unsafe { SourceIter::as_inner(&mut self.iter) }
+    }
+}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<St, F, B, I: InPlaceIterable> InPlaceIterable for Scan<I, St, F> where
+    F: FnMut(&mut St, I::Item) -> Option<B>
+{
+}
diff --git a/library/core/src/iter/adapters/skip.rs b/library/core/src/iter/adapters/skip.rs
new file mode 100644 (file)
index 0000000..dd53256
--- /dev/null
@@ -0,0 +1,199 @@
+use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
+use crate::ops::{ControlFlow, Try};
+
+/// An iterator that skips over `n` elements of `iter`.
+///
+/// This `struct` is created by the [`skip`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`skip`]: Iterator::skip
+/// [`Iterator`]: trait.Iterator.html
+#[derive(Clone, Debug)]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Skip<I> {
+    iter: I,
+    n: usize,
+}
+
+impl<I> Skip<I> {
+    pub(in crate::iter) fn new(iter: I, n: usize) -> Skip<I> {
+        Skip { iter, n }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I> Iterator for Skip<I>
+where
+    I: Iterator,
+{
+    type Item = <I as Iterator>::Item;
+
+    #[inline]
+    fn next(&mut self) -> Option<I::Item> {
+        if self.n == 0 {
+            self.iter.next()
+        } else {
+            let old_n = self.n;
+            self.n = 0;
+            self.iter.nth(old_n)
+        }
+    }
+
+    #[inline]
+    fn nth(&mut self, n: usize) -> Option<I::Item> {
+        // Can't just add n + self.n due to overflow.
+        if self.n > 0 {
+            let to_skip = self.n;
+            self.n = 0;
+            // nth(n) skips n+1
+            self.iter.nth(to_skip - 1)?;
+        }
+        self.iter.nth(n)
+    }
+
+    #[inline]
+    fn count(mut self) -> usize {
+        if self.n > 0 {
+            // nth(n) skips n+1
+            if self.iter.nth(self.n - 1).is_none() {
+                return 0;
+            }
+        }
+        self.iter.count()
+    }
+
+    #[inline]
+    fn last(mut self) -> Option<I::Item> {
+        if self.n > 0 {
+            // nth(n) skips n+1
+            self.iter.nth(self.n - 1)?;
+        }
+        self.iter.last()
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let (lower, upper) = self.iter.size_hint();
+
+        let lower = lower.saturating_sub(self.n);
+        let upper = match upper {
+            Some(x) => Some(x.saturating_sub(self.n)),
+            None => None,
+        };
+
+        (lower, upper)
+    }
+
+    #[inline]
+    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        let n = self.n;
+        self.n = 0;
+        if n > 0 {
+            // nth(n) skips n+1
+            if self.iter.nth(n - 1).is_none() {
+                return try { init };
+            }
+        }
+        self.iter.try_fold(init, fold)
+    }
+
+    #[inline]
+    fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
+    where
+        Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        if self.n > 0 {
+            // nth(n) skips n+1
+            if self.iter.nth(self.n - 1).is_none() {
+                return init;
+            }
+        }
+        self.iter.fold(init, fold)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I> ExactSizeIterator for Skip<I> where I: ExactSizeIterator {}
+
+#[stable(feature = "double_ended_skip_iterator", since = "1.9.0")]
+impl<I> DoubleEndedIterator for Skip<I>
+where
+    I: DoubleEndedIterator + ExactSizeIterator,
+{
+    fn next_back(&mut self) -> Option<Self::Item> {
+        if self.len() > 0 { self.iter.next_back() } else { None }
+    }
+
+    #[inline]
+    fn nth_back(&mut self, n: usize) -> Option<I::Item> {
+        let len = self.len();
+        if n < len {
+            self.iter.nth_back(n)
+        } else {
+            if len > 0 {
+                // consume the original iterator
+                self.iter.nth_back(len - 1);
+            }
+            None
+        }
+    }
+
+    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        fn check<T, Acc, R: Try<Ok = Acc>>(
+            mut n: usize,
+            mut fold: impl FnMut(Acc, T) -> R,
+        ) -> impl FnMut(Acc, T) -> ControlFlow<R, Acc> {
+            move |acc, x| {
+                n -= 1;
+                let r = fold(acc, x);
+                if n == 0 { ControlFlow::Break(r) } else { ControlFlow::from_try(r) }
+            }
+        }
+
+        let n = self.len();
+        if n == 0 { try { init } } else { self.iter.try_rfold(init, check(n, fold)).into_try() }
+    }
+
+    fn rfold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
+    where
+        Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        #[inline]
+        fn ok<Acc, T>(mut f: impl FnMut(Acc, T) -> Acc) -> impl FnMut(Acc, T) -> Result<Acc, !> {
+            move |acc, x| Ok(f(acc, x))
+        }
+
+        self.try_rfold(init, ok(fold)).unwrap()
+    }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<I> FusedIterator for Skip<I> where I: FusedIterator {}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<S: Iterator, I: Iterator> SourceIter for Skip<I>
+where
+    I: SourceIter<Source = S>,
+{
+    type Source = S;
+
+    #[inline]
+    unsafe fn as_inner(&mut self) -> &mut S {
+        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
+        unsafe { SourceIter::as_inner(&mut self.iter) }
+    }
+}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<I: InPlaceIterable> InPlaceIterable for Skip<I> {}
diff --git a/library/core/src/iter/adapters/skip_while.rs b/library/core/src/iter/adapters/skip_while.rs
new file mode 100644 (file)
index 0000000..efcb469
--- /dev/null
@@ -0,0 +1,126 @@
+use crate::fmt;
+use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
+use crate::ops::Try;
+
+/// An iterator that rejects elements while `predicate` returns `true`.
+///
+/// This `struct` is created by the [`skip_while`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`skip_while`]: Iterator::skip_while
+/// [`Iterator`]: trait.Iterator.html
+#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Clone)]
+pub struct SkipWhile<I, P> {
+    iter: I,
+    flag: bool,
+    predicate: P,
+}
+
+impl<I, P> SkipWhile<I, P> {
+    pub(in crate::iter) fn new(iter: I, predicate: P) -> SkipWhile<I, P> {
+        SkipWhile { iter, flag: false, predicate }
+    }
+}
+
+#[stable(feature = "core_impl_debug", since = "1.9.0")]
+impl<I: fmt::Debug, P> fmt::Debug for SkipWhile<I, P> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("SkipWhile").field("iter", &self.iter).field("flag", &self.flag).finish()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I: Iterator, P> Iterator for SkipWhile<I, P>
+where
+    P: FnMut(&I::Item) -> bool,
+{
+    type Item = I::Item;
+
+    #[inline]
+    fn next(&mut self) -> Option<I::Item> {
+        fn check<'a, T>(
+            flag: &'a mut bool,
+            pred: &'a mut impl FnMut(&T) -> bool,
+        ) -> impl FnMut(&T) -> bool + 'a {
+            move |x| {
+                if *flag || !pred(x) {
+                    *flag = true;
+                    true
+                } else {
+                    false
+                }
+            }
+        }
+
+        let flag = &mut self.flag;
+        let pred = &mut self.predicate;
+        self.iter.find(check(flag, pred))
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let (_, upper) = self.iter.size_hint();
+        (0, upper) // can't know a lower bound, due to the predicate
+    }
+
+    #[inline]
+    fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        if !self.flag {
+            match self.next() {
+                Some(v) => init = fold(init, v)?,
+                None => return try { init },
+            }
+        }
+        self.iter.try_fold(init, fold)
+    }
+
+    #[inline]
+    fn fold<Acc, Fold>(mut self, mut init: Acc, mut fold: Fold) -> Acc
+    where
+        Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        if !self.flag {
+            match self.next() {
+                Some(v) => init = fold(init, v),
+                None => return init,
+            }
+        }
+        self.iter.fold(init, fold)
+    }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<I, P> FusedIterator for SkipWhile<I, P>
+where
+    I: FusedIterator,
+    P: FnMut(&I::Item) -> bool,
+{
+}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<S: Iterator, P, I: Iterator> SourceIter for SkipWhile<I, P>
+where
+    P: FnMut(&I::Item) -> bool,
+    I: SourceIter<Source = S>,
+{
+    type Source = S;
+
+    #[inline]
+    unsafe fn as_inner(&mut self) -> &mut S {
+        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
+        unsafe { SourceIter::as_inner(&mut self.iter) }
+    }
+}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<I: InPlaceIterable, F> InPlaceIterable for SkipWhile<I, F> where
+    F: FnMut(&I::Item) -> bool
+{
+}
diff --git a/library/core/src/iter/adapters/step_by.rs b/library/core/src/iter/adapters/step_by.rs
new file mode 100644 (file)
index 0000000..2ba56ee
--- /dev/null
@@ -0,0 +1,235 @@
+use crate::{intrinsics, iter::from_fn, ops::Try};
+
+/// An iterator for stepping iterators by a custom amount.
+///
+/// This `struct` is created by the [`step_by`] method on [`Iterator`]. See
+/// its documentation for more.
+///
+/// [`step_by`]: Iterator::step_by
+/// [`Iterator`]: trait.Iterator.html
+#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[stable(feature = "iterator_step_by", since = "1.28.0")]
+#[derive(Clone, Debug)]
+pub struct StepBy<I> {
+    iter: I,
+    step: usize,
+    first_take: bool,
+}
+
+impl<I> StepBy<I> {
+    pub(in crate::iter) fn new(iter: I, step: usize) -> StepBy<I> {
+        assert!(step != 0);
+        StepBy { iter, step: step - 1, first_take: true }
+    }
+}
+
+#[stable(feature = "iterator_step_by", since = "1.28.0")]
+impl<I> Iterator for StepBy<I>
+where
+    I: Iterator,
+{
+    type Item = I::Item;
+
+    #[inline]
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.first_take {
+            self.first_take = false;
+            self.iter.next()
+        } else {
+            self.iter.nth(self.step)
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        #[inline]
+        fn first_size(step: usize) -> impl Fn(usize) -> usize {
+            move |n| if n == 0 { 0 } else { 1 + (n - 1) / (step + 1) }
+        }
+
+        #[inline]
+        fn other_size(step: usize) -> impl Fn(usize) -> usize {
+            move |n| n / (step + 1)
+        }
+
+        let (low, high) = self.iter.size_hint();
+
+        if self.first_take {
+            let f = first_size(self.step);
+            (f(low), high.map(f))
+        } else {
+            let f = other_size(self.step);
+            (f(low), high.map(f))
+        }
+    }
+
+    #[inline]
+    fn nth(&mut self, mut n: usize) -> Option<Self::Item> {
+        if self.first_take {
+            self.first_take = false;
+            let first = self.iter.next();
+            if n == 0 {
+                return first;
+            }
+            n -= 1;
+        }
+        // n and self.step are indices, we need to add 1 to get the amount of elements
+        // When calling `.nth`, we need to subtract 1 again to convert back to an index
+        // step + 1 can't overflow because `.step_by` sets `self.step` to `step - 1`
+        let mut step = self.step + 1;
+        // n + 1 could overflow
+        // thus, if n is usize::MAX, instead of adding one, we call .nth(step)
+        if n == usize::MAX {
+            self.iter.nth(step - 1);
+        } else {
+            n += 1;
+        }
+
+        // overflow handling
+        loop {
+            let mul = n.checked_mul(step);
+            {
+                if intrinsics::likely(mul.is_some()) {
+                    return self.iter.nth(mul.unwrap() - 1);
+                }
+            }
+            let div_n = usize::MAX / n;
+            let div_step = usize::MAX / step;
+            let nth_n = div_n * n;
+            let nth_step = div_step * step;
+            let nth = if nth_n > nth_step {
+                step -= div_n;
+                nth_n
+            } else {
+                n -= div_step;
+                nth_step
+            };
+            self.iter.nth(nth - 1);
+        }
+    }
+
+    fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
+    where
+        F: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        #[inline]
+        fn nth<I: Iterator>(iter: &mut I, step: usize) -> impl FnMut() -> Option<I::Item> + '_ {
+            move || iter.nth(step)
+        }
+
+        if self.first_take {
+            self.first_take = false;
+            match self.iter.next() {
+                None => return try { acc },
+                Some(x) => acc = f(acc, x)?,
+            }
+        }
+        from_fn(nth(&mut self.iter, self.step)).try_fold(acc, f)
+    }
+
+    fn fold<Acc, F>(mut self, mut acc: Acc, mut f: F) -> Acc
+    where
+        F: FnMut(Acc, Self::Item) -> Acc,
+    {
+        #[inline]
+        fn nth<I: Iterator>(iter: &mut I, step: usize) -> impl FnMut() -> Option<I::Item> + '_ {
+            move || iter.nth(step)
+        }
+
+        if self.first_take {
+            self.first_take = false;
+            match self.iter.next() {
+                None => return acc,
+                Some(x) => acc = f(acc, x),
+            }
+        }
+        from_fn(nth(&mut self.iter, self.step)).fold(acc, f)
+    }
+}
+
+impl<I> StepBy<I>
+where
+    I: ExactSizeIterator,
+{
+    // The zero-based index starting from the end of the iterator of the
+    // last element. Used in the `DoubleEndedIterator` implementation.
+    fn next_back_index(&self) -> usize {
+        let rem = self.iter.len() % (self.step + 1);
+        if self.first_take {
+            if rem == 0 { self.step } else { rem - 1 }
+        } else {
+            rem
+        }
+    }
+}
+
+#[stable(feature = "double_ended_step_by_iterator", since = "1.38.0")]
+impl<I> DoubleEndedIterator for StepBy<I>
+where
+    I: DoubleEndedIterator + ExactSizeIterator,
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<Self::Item> {
+        self.iter.nth_back(self.next_back_index())
+    }
+
+    #[inline]
+    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
+        // `self.iter.nth_back(usize::MAX)` does the right thing here when `n`
+        // is out of bounds because the length of `self.iter` does not exceed
+        // `usize::MAX` (because `I: ExactSizeIterator`) and `nth_back` is
+        // zero-indexed
+        let n = n.saturating_mul(self.step + 1).saturating_add(self.next_back_index());
+        self.iter.nth_back(n)
+    }
+
+    fn try_rfold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R
+    where
+        F: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        #[inline]
+        fn nth_back<I: DoubleEndedIterator>(
+            iter: &mut I,
+            step: usize,
+        ) -> impl FnMut() -> Option<I::Item> + '_ {
+            move || iter.nth_back(step)
+        }
+
+        match self.next_back() {
+            None => try { init },
+            Some(x) => {
+                let acc = f(init, x)?;
+                from_fn(nth_back(&mut self.iter, self.step)).try_fold(acc, f)
+            }
+        }
+    }
+
+    #[inline]
+    fn rfold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc
+    where
+        Self: Sized,
+        F: FnMut(Acc, Self::Item) -> Acc,
+    {
+        #[inline]
+        fn nth_back<I: DoubleEndedIterator>(
+            iter: &mut I,
+            step: usize,
+        ) -> impl FnMut() -> Option<I::Item> + '_ {
+            move || iter.nth_back(step)
+        }
+
+        match self.next_back() {
+            None => init,
+            Some(x) => {
+                let acc = f(init, x);
+                from_fn(nth_back(&mut self.iter, self.step)).fold(acc, f)
+            }
+        }
+    }
+}
+
+// StepBy can only make the iterator shorter, so the len will still fit.
+#[stable(feature = "iterator_step_by", since = "1.28.0")]
+impl<I> ExactSizeIterator for StepBy<I> where I: ExactSizeIterator {}
diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs
new file mode 100644 (file)
index 0000000..9efc7a4
--- /dev/null
@@ -0,0 +1,209 @@
+use crate::cmp;
+use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen};
+use crate::ops::{ControlFlow, Try};
+
+/// An iterator that only iterates over the first `n` iterations of `iter`.
+///
+/// This `struct` is created by the [`take`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`take`]: Iterator::take
+/// [`Iterator`]: trait.Iterator.html
+#[derive(Clone, Debug)]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Take<I> {
+    iter: I,
+    n: usize,
+}
+
+impl<I> Take<I> {
+    pub(in crate::iter) fn new(iter: I, n: usize) -> Take<I> {
+        Take { iter, n }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I> Iterator for Take<I>
+where
+    I: Iterator,
+{
+    type Item = <I as Iterator>::Item;
+
+    #[inline]
+    fn next(&mut self) -> Option<<I as Iterator>::Item> {
+        if self.n != 0 {
+            self.n -= 1;
+            self.iter.next()
+        } else {
+            None
+        }
+    }
+
+    #[inline]
+    fn nth(&mut self, n: usize) -> Option<I::Item> {
+        if self.n > n {
+            self.n -= n + 1;
+            self.iter.nth(n)
+        } else {
+            if self.n > 0 {
+                self.iter.nth(self.n - 1);
+                self.n = 0;
+            }
+            None
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        if self.n == 0 {
+            return (0, Some(0));
+        }
+
+        let (lower, upper) = self.iter.size_hint();
+
+        let lower = cmp::min(lower, self.n);
+
+        let upper = match upper {
+            Some(x) if x < self.n => Some(x),
+            _ => Some(self.n),
+        };
+
+        (lower, upper)
+    }
+
+    #[inline]
+    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        fn check<'a, T, Acc, R: Try<Ok = Acc>>(
+            n: &'a mut usize,
+            mut fold: impl FnMut(Acc, T) -> R + 'a,
+        ) -> impl FnMut(Acc, T) -> ControlFlow<R, Acc> + 'a {
+            move |acc, x| {
+                *n -= 1;
+                let r = fold(acc, x);
+                if *n == 0 { ControlFlow::Break(r) } else { ControlFlow::from_try(r) }
+            }
+        }
+
+        if self.n == 0 {
+            try { init }
+        } else {
+            let n = &mut self.n;
+            self.iter.try_fold(init, check(n, fold)).into_try()
+        }
+    }
+
+    #[inline]
+    fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        #[inline]
+        fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
+            move |acc, x| Ok(f(acc, x))
+        }
+
+        self.try_fold(init, ok(fold)).unwrap()
+    }
+}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<S: Iterator, I: Iterator> SourceIter for Take<I>
+where
+    I: SourceIter<Source = S>,
+{
+    type Source = S;
+
+    #[inline]
+    unsafe fn as_inner(&mut self) -> &mut S {
+        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
+        unsafe { SourceIter::as_inner(&mut self.iter) }
+    }
+}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<I: InPlaceIterable> InPlaceIterable for Take<I> {}
+
+#[stable(feature = "double_ended_take_iterator", since = "1.38.0")]
+impl<I> DoubleEndedIterator for Take<I>
+where
+    I: DoubleEndedIterator + ExactSizeIterator,
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<Self::Item> {
+        if self.n == 0 {
+            None
+        } else {
+            let n = self.n;
+            self.n -= 1;
+            self.iter.nth_back(self.iter.len().saturating_sub(n))
+        }
+    }
+
+    #[inline]
+    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
+        let len = self.iter.len();
+        if self.n > n {
+            let m = len.saturating_sub(self.n) + n;
+            self.n -= n + 1;
+            self.iter.nth_back(m)
+        } else {
+            if len > 0 {
+                self.iter.nth_back(len - 1);
+            }
+            None
+        }
+    }
+
+    #[inline]
+    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        if self.n == 0 {
+            try { init }
+        } else {
+            let len = self.iter.len();
+            if len > self.n && self.iter.nth_back(len - self.n - 1).is_none() {
+                try { init }
+            } else {
+                self.iter.try_rfold(init, fold)
+            }
+        }
+    }
+
+    #[inline]
+    fn rfold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        if self.n == 0 {
+            init
+        } else {
+            let len = self.iter.len();
+            if len > self.n && self.iter.nth_back(len - self.n - 1).is_none() {
+                init
+            } else {
+                self.iter.rfold(init, fold)
+            }
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I> ExactSizeIterator for Take<I> where I: ExactSizeIterator {}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<I> FusedIterator for Take<I> where I: FusedIterator {}
+
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<I: TrustedLen> TrustedLen for Take<I> {}
diff --git a/library/core/src/iter/adapters/take_while.rs b/library/core/src/iter/adapters/take_while.rs
new file mode 100644 (file)
index 0000000..746eb41
--- /dev/null
@@ -0,0 +1,139 @@
+use crate::fmt;
+use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
+use crate::ops::{ControlFlow, Try};
+
+/// An iterator that only accepts elements while `predicate` returns `true`.
+///
+/// This `struct` is created by the [`take_while`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`take_while`]: Iterator::take_while
+/// [`Iterator`]: trait.Iterator.html
+#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Clone)]
+pub struct TakeWhile<I, P> {
+    iter: I,
+    flag: bool,
+    predicate: P,
+}
+
+impl<I, P> TakeWhile<I, P> {
+    pub(in crate::iter) fn new(iter: I, predicate: P) -> TakeWhile<I, P> {
+        TakeWhile { iter, flag: false, predicate }
+    }
+}
+
+#[stable(feature = "core_impl_debug", since = "1.9.0")]
+impl<I: fmt::Debug, P> fmt::Debug for TakeWhile<I, P> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("TakeWhile").field("iter", &self.iter).field("flag", &self.flag).finish()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I: Iterator, P> Iterator for TakeWhile<I, P>
+where
+    P: FnMut(&I::Item) -> bool,
+{
+    type Item = I::Item;
+
+    #[inline]
+    fn next(&mut self) -> Option<I::Item> {
+        if self.flag {
+            None
+        } else {
+            let x = self.iter.next()?;
+            if (self.predicate)(&x) {
+                Some(x)
+            } else {
+                self.flag = true;
+                None
+            }
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        if self.flag {
+            (0, Some(0))
+        } else {
+            let (_, upper) = self.iter.size_hint();
+            (0, upper) // can't know a lower bound, due to the predicate
+        }
+    }
+
+    #[inline]
+    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        fn check<'a, T, Acc, R: Try<Ok = Acc>>(
+            flag: &'a mut bool,
+            p: &'a mut impl FnMut(&T) -> bool,
+            mut fold: impl FnMut(Acc, T) -> R + 'a,
+        ) -> impl FnMut(Acc, T) -> ControlFlow<R, Acc> + 'a {
+            move |acc, x| {
+                if p(&x) {
+                    ControlFlow::from_try(fold(acc, x))
+                } else {
+                    *flag = true;
+                    ControlFlow::Break(try { acc })
+                }
+            }
+        }
+
+        if self.flag {
+            try { init }
+        } else {
+            let flag = &mut self.flag;
+            let p = &mut self.predicate;
+            self.iter.try_fold(init, check(flag, p, fold)).into_try()
+        }
+    }
+
+    #[inline]
+    fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        #[inline]
+        fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
+            move |acc, x| Ok(f(acc, x))
+        }
+
+        self.try_fold(init, ok(fold)).unwrap()
+    }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<I, P> FusedIterator for TakeWhile<I, P>
+where
+    I: FusedIterator,
+    P: FnMut(&I::Item) -> bool,
+{
+}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<S: Iterator, P, I: Iterator> SourceIter for TakeWhile<I, P>
+where
+    P: FnMut(&I::Item) -> bool,
+    I: SourceIter<Source = S>,
+{
+    type Source = S;
+
+    #[inline]
+    unsafe fn as_inner(&mut self) -> &mut S {
+        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
+        unsafe { SourceIter::as_inner(&mut self.iter) }
+    }
+}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<I: InPlaceIterable, F> InPlaceIterable for TakeWhile<I, F> where
+    F: FnMut(&I::Item) -> bool
+{
+}
index 78712988eaea70e1ad27703c4ce5d5508cc91733..8cd4c775231926d54ba38bc8dd3965dfd4d097c5 100644 (file)
@@ -1,10 +1,7 @@
 use crate::cmp;
 use crate::fmt::{self, Debug};
-
-use super::super::{
-    DoubleEndedIterator, ExactSizeIterator, FusedIterator, InPlaceIterable, Iterator, SourceIter,
-    TrustedLen,
-};
+use crate::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator};
+use crate::iter::{InPlaceIterable, SourceIter, TrustedLen};
 
 /// An iterator that iterates two other iterators simultaneously.
 ///
@@ -21,7 +18,7 @@ pub struct Zip<A, B> {
     len: usize,
 }
 impl<A: Iterator, B: Iterator> Zip<A, B> {
-    pub(in super::super) fn new(a: A, b: B) -> Zip<A, B> {
+    pub(in crate::iter) fn new(a: A, b: B) -> Zip<A, B> {
         ZipImpl::new(a, b)
     }
     fn super_nth(&mut self, mut n: usize) -> Option<(A::Item, B::Item)> {
index 59f333e888b88cd7e2af852959d282347da6b21d..072373c00f679740ef3972c54b15199d6ba05561 100644 (file)
 
 #[stable(feature = "fused", since = "1.26.0")]
 pub use self::traits::FusedIterator;
+#[unstable(issue = "none", feature = "inplace_iteration")]
+pub use self::traits::InPlaceIterable;
 #[unstable(feature = "trusted_len", issue = "37572")]
 pub use self::traits::TrustedLen;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use self::traits::{DoubleEndedIterator, Extend, FromIterator, IntoIterator};
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::traits::{ExactSizeIterator, Product, Sum};
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-pub use self::traits::InPlaceIterable;
+pub use self::traits::{
+    DoubleEndedIterator, ExactSizeIterator, Extend, FromIterator, IntoIterator, Product, Sum,
+};
 
 #[stable(feature = "iter_cloned", since = "1.1.0")]
 pub use self::adapters::Cloned;
 pub use self::adapters::Copied;
 #[stable(feature = "iterator_flatten", since = "1.29.0")]
 pub use self::adapters::Flatten;
-
 #[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
 pub use self::adapters::MapWhile;
-#[unstable(issue = "none", feature = "inplace_iteration")]
+#[unstable(feature = "inplace_iteration", issue = "none")]
 pub use self::adapters::SourceIter;
 #[stable(feature = "iterator_step_by", since = "1.28.0")]
 pub use self::adapters::StepBy;
 #[unstable(feature = "trusted_random_access", issue = "none")]
 pub use self::adapters::TrustedRandomAccess;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use self::adapters::{Chain, Cycle, Enumerate, Filter, FilterMap, Map, Rev, Zip};
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::adapters::{FlatMap, Peekable, Scan, Skip, SkipWhile, Take, TakeWhile};
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::adapters::{Fuse, Inspect};
+pub use self::adapters::{
+    Chain, Cycle, Enumerate, Filter, FilterMap, FlatMap, Fuse, Inspect, Map, Peekable, Rev, Scan,
+    Skip, SkipWhile, Take, TakeWhile, Zip,
+};
 
 pub(crate) use self::adapters::process_results;
 
index 44da8f4715c88d371066860a3927cae255bcf4fb..de0663141e25274cb5e95d1039047e58297c60a7 100644 (file)
-use crate::fmt;
-use crate::marker;
+mod empty;
+mod from_fn;
+mod once;
+mod once_with;
+mod repeat;
+mod repeat_with;
+mod successors;
 
-use super::{FusedIterator, TrustedLen};
+pub use self::repeat::{repeat, Repeat};
 
-/// An iterator that repeats an element endlessly.
-///
-/// This `struct` is created by the [`repeat()`] function. See its documentation for more.
-#[derive(Clone, Debug)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Repeat<A> {
-    element: A,
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A: Clone> Iterator for Repeat<A> {
-    type Item = A;
-
-    #[inline]
-    fn next(&mut self) -> Option<A> {
-        Some(self.element.clone())
-    }
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (usize::MAX, None)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A: Clone> DoubleEndedIterator for Repeat<A> {
-    #[inline]
-    fn next_back(&mut self) -> Option<A> {
-        Some(self.element.clone())
-    }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<A: Clone> FusedIterator for Repeat<A> {}
-
-#[unstable(feature = "trusted_len", issue = "37572")]
-unsafe impl<A: Clone> TrustedLen for Repeat<A> {}
-
-/// Creates a new iterator that endlessly repeats a single element.
-///
-/// The `repeat()` function repeats a single value over and over again.
-///
-/// Infinite iterators like `repeat()` are often used with adapters like
-/// [`Iterator::take()`], in order to make them finite.
-///
-/// If the element type of the iterator you need does not implement `Clone`,
-/// or if you do not want to keep the repeated element in memory, you can
-/// instead use the [`repeat_with()`] function.
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// use std::iter;
-///
-/// // the number four 4ever:
-/// let mut fours = iter::repeat(4);
-///
-/// assert_eq!(Some(4), fours.next());
-/// assert_eq!(Some(4), fours.next());
-/// assert_eq!(Some(4), fours.next());
-/// assert_eq!(Some(4), fours.next());
-/// assert_eq!(Some(4), fours.next());
-///
-/// // yup, still four
-/// assert_eq!(Some(4), fours.next());
-/// ```
-///
-/// Going finite with [`Iterator::take()`]:
-///
-/// ```
-/// use std::iter;
-///
-/// // that last example was too many fours. Let's only have four fours.
-/// let mut four_fours = iter::repeat(4).take(4);
-///
-/// assert_eq!(Some(4), four_fours.next());
-/// assert_eq!(Some(4), four_fours.next());
-/// assert_eq!(Some(4), four_fours.next());
-/// assert_eq!(Some(4), four_fours.next());
-///
-/// // ... and now we're done
-/// assert_eq!(None, four_fours.next());
-/// ```
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn repeat<T: Clone>(elt: T) -> Repeat<T> {
-    Repeat { element: elt }
-}
-
-/// An iterator that repeats elements of type `A` endlessly by
-/// applying the provided closure `F: FnMut() -> A`.
-///
-/// This `struct` is created by the [`repeat_with()`] function.
-/// See its documentation for more.
-#[derive(Copy, Clone, Debug)]
-#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
-pub struct RepeatWith<F> {
-    repeater: F,
-}
-
-#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
-impl<A, F: FnMut() -> A> Iterator for RepeatWith<F> {
-    type Item = A;
-
-    #[inline]
-    fn next(&mut self) -> Option<A> {
-        Some((self.repeater)())
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (usize::MAX, None)
-    }
-}
-
-#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
-impl<A, F: FnMut() -> A> FusedIterator for RepeatWith<F> {}
-
-#[unstable(feature = "trusted_len", issue = "37572")]
-unsafe impl<A, F: FnMut() -> A> TrustedLen for RepeatWith<F> {}
-
-/// Creates a new iterator that repeats elements of type `A` endlessly by
-/// applying the provided closure, the repeater, `F: FnMut() -> A`.
-///
-/// The `repeat_with()` function calls the repeater over and over again.
-///
-/// Infinite iterators like `repeat_with()` are often used with adapters like
-/// [`Iterator::take()`], in order to make them finite.
-///
-/// If the element type of the iterator you need implements [`Clone`], and
-/// it is OK to keep the source element in memory, you should instead use
-/// the [`repeat()`] function.
-///
-/// An iterator produced by `repeat_with()` is not a [`DoubleEndedIterator`].
-/// If you need `repeat_with()` to return a [`DoubleEndedIterator`],
-/// please open a GitHub issue explaining your use case.
-///
-/// [`DoubleEndedIterator`]: crate::iter::DoubleEndedIterator
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// use std::iter;
-///
-/// // let's assume we have some value of a type that is not `Clone`
-/// // or which don't want to have in memory just yet because it is expensive:
-/// #[derive(PartialEq, Debug)]
-/// struct Expensive;
-///
-/// // a particular value forever:
-/// let mut things = iter::repeat_with(|| Expensive);
-///
-/// assert_eq!(Some(Expensive), things.next());
-/// assert_eq!(Some(Expensive), things.next());
-/// assert_eq!(Some(Expensive), things.next());
-/// assert_eq!(Some(Expensive), things.next());
-/// assert_eq!(Some(Expensive), things.next());
-/// ```
-///
-/// Using mutation and going finite:
-///
-/// ```rust
-/// use std::iter;
-///
-/// // From the zeroth to the third power of two:
-/// let mut curr = 1;
-/// let mut pow2 = iter::repeat_with(|| { let tmp = curr; curr *= 2; tmp })
-///                     .take(4);
-///
-/// assert_eq!(Some(1), pow2.next());
-/// assert_eq!(Some(2), pow2.next());
-/// assert_eq!(Some(4), pow2.next());
-/// assert_eq!(Some(8), pow2.next());
-///
-/// // ... and now we're done
-/// assert_eq!(None, pow2.next());
-/// ```
-#[inline]
-#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
-pub fn repeat_with<A, F: FnMut() -> A>(repeater: F) -> RepeatWith<F> {
-    RepeatWith { repeater }
-}
-
-/// An iterator that yields nothing.
-///
-/// This `struct` is created by the [`empty()`] function. See its documentation for more.
 #[stable(feature = "iter_empty", since = "1.2.0")]
-pub struct Empty<T>(marker::PhantomData<T>);
-
-#[stable(feature = "iter_empty_send_sync", since = "1.42.0")]
-unsafe impl<T> Send for Empty<T> {}
-#[stable(feature = "iter_empty_send_sync", since = "1.42.0")]
-unsafe impl<T> Sync for Empty<T> {}
+pub use self::empty::{empty, Empty};
 
-#[stable(feature = "core_impl_debug", since = "1.9.0")]
-impl<T> fmt::Debug for Empty<T> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("Empty")
-    }
-}
-
-#[stable(feature = "iter_empty", since = "1.2.0")]
-impl<T> Iterator for Empty<T> {
-    type Item = T;
-
-    fn next(&mut self) -> Option<T> {
-        None
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (0, Some(0))
-    }
-}
-
-#[stable(feature = "iter_empty", since = "1.2.0")]
-impl<T> DoubleEndedIterator for Empty<T> {
-    fn next_back(&mut self) -> Option<T> {
-        None
-    }
-}
-
-#[stable(feature = "iter_empty", since = "1.2.0")]
-impl<T> ExactSizeIterator for Empty<T> {
-    fn len(&self) -> usize {
-        0
-    }
-}
-
-#[unstable(feature = "trusted_len", issue = "37572")]
-unsafe impl<T> TrustedLen for Empty<T> {}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<T> FusedIterator for Empty<T> {}
-
-// not #[derive] because that adds a Clone bound on T,
-// which isn't necessary.
-#[stable(feature = "iter_empty", since = "1.2.0")]
-impl<T> Clone for Empty<T> {
-    fn clone(&self) -> Empty<T> {
-        Empty(marker::PhantomData)
-    }
-}
-
-// not #[derive] because that adds a Default bound on T,
-// which isn't necessary.
-#[stable(feature = "iter_empty", since = "1.2.0")]
-impl<T> Default for Empty<T> {
-    fn default() -> Empty<T> {
-        Empty(marker::PhantomData)
-    }
-}
-
-/// Creates an iterator that yields nothing.
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// use std::iter;
-///
-/// // this could have been an iterator over i32, but alas, it's just not.
-/// let mut nope = iter::empty::<i32>();
-///
-/// assert_eq!(None, nope.next());
-/// ```
-#[stable(feature = "iter_empty", since = "1.2.0")]
-#[rustc_const_stable(feature = "const_iter_empty", since = "1.32.0")]
-pub const fn empty<T>() -> Empty<T> {
-    Empty(marker::PhantomData)
-}
-
-/// An iterator that yields an element exactly once.
-///
-/// This `struct` is created by the [`once()`] function. See its documentation for more.
-#[derive(Clone, Debug)]
 #[stable(feature = "iter_once", since = "1.2.0")]
-pub struct Once<T> {
-    inner: crate::option::IntoIter<T>,
-}
+pub use self::once::{once, Once};
 
-#[stable(feature = "iter_once", since = "1.2.0")]
-impl<T> Iterator for Once<T> {
-    type Item = T;
-
-    fn next(&mut self) -> Option<T> {
-        self.inner.next()
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
-    }
-}
-
-#[stable(feature = "iter_once", since = "1.2.0")]
-impl<T> DoubleEndedIterator for Once<T> {
-    fn next_back(&mut self) -> Option<T> {
-        self.inner.next_back()
-    }
-}
-
-#[stable(feature = "iter_once", since = "1.2.0")]
-impl<T> ExactSizeIterator for Once<T> {
-    fn len(&self) -> usize {
-        self.inner.len()
-    }
-}
-
-#[unstable(feature = "trusted_len", issue = "37572")]
-unsafe impl<T> TrustedLen for Once<T> {}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<T> FusedIterator for Once<T> {}
-
-/// Creates an iterator that yields an element exactly once.
-///
-/// This is commonly used to adapt a single value into a [`chain()`] of other
-/// kinds of iteration. Maybe you have an iterator that covers almost
-/// everything, but you need an extra special case. Maybe you have a function
-/// which works on iterators, but you only need to process one value.
-///
-/// [`chain()`]: Iterator::chain
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// use std::iter;
-///
-/// // one is the loneliest number
-/// let mut one = iter::once(1);
-///
-/// assert_eq!(Some(1), one.next());
-///
-/// // just one, that's all we get
-/// assert_eq!(None, one.next());
-/// ```
-///
-/// Chaining together with another iterator. Let's say that we want to iterate
-/// over each file of the `.foo` directory, but also a configuration file,
-/// `.foorc`:
-///
-/// ```no_run
-/// use std::iter;
-/// use std::fs;
-/// use std::path::PathBuf;
-///
-/// let dirs = fs::read_dir(".foo").unwrap();
-///
-/// // we need to convert from an iterator of DirEntry-s to an iterator of
-/// // PathBufs, so we use map
-/// let dirs = dirs.map(|file| file.unwrap().path());
-///
-/// // now, our iterator just for our config file
-/// let config = iter::once(PathBuf::from(".foorc"));
-///
-/// // chain the two iterators together into one big iterator
-/// let files = dirs.chain(config);
-///
-/// // this will give us all of the files in .foo as well as .foorc
-/// for f in files {
-///     println!("{:?}", f);
-/// }
-/// ```
-#[stable(feature = "iter_once", since = "1.2.0")]
-pub fn once<T>(value: T) -> Once<T> {
-    Once { inner: Some(value).into_iter() }
-}
-
-/// An iterator that yields a single element of type `A` by
-/// applying the provided closure `F: FnOnce() -> A`.
-///
-/// This `struct` is created by the [`once_with()`] function.
-/// See its documentation for more.
-#[derive(Clone, Debug)]
-#[stable(feature = "iter_once_with", since = "1.43.0")]
-pub struct OnceWith<F> {
-    gen: Option<F>,
-}
-
-#[stable(feature = "iter_once_with", since = "1.43.0")]
-impl<A, F: FnOnce() -> A> Iterator for OnceWith<F> {
-    type Item = A;
-
-    #[inline]
-    fn next(&mut self) -> Option<A> {
-        let f = self.gen.take()?;
-        Some(f())
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.gen.iter().size_hint()
-    }
-}
-
-#[stable(feature = "iter_once_with", since = "1.43.0")]
-impl<A, F: FnOnce() -> A> DoubleEndedIterator for OnceWith<F> {
-    fn next_back(&mut self) -> Option<A> {
-        self.next()
-    }
-}
-
-#[stable(feature = "iter_once_with", since = "1.43.0")]
-impl<A, F: FnOnce() -> A> ExactSizeIterator for OnceWith<F> {
-    fn len(&self) -> usize {
-        self.gen.iter().len()
-    }
-}
-
-#[stable(feature = "iter_once_with", since = "1.43.0")]
-impl<A, F: FnOnce() -> A> FusedIterator for OnceWith<F> {}
-
-#[stable(feature = "iter_once_with", since = "1.43.0")]
-unsafe impl<A, F: FnOnce() -> A> TrustedLen for OnceWith<F> {}
-
-/// Creates an iterator that lazily generates a value exactly once by invoking
-/// the provided closure.
-///
-/// This is commonly used to adapt a single value generator into a [`chain()`] of
-/// other kinds of iteration. Maybe you have an iterator that covers almost
-/// everything, but you need an extra special case. Maybe you have a function
-/// which works on iterators, but you only need to process one value.
-///
-/// Unlike [`once()`], this function will lazily generate the value on request.
-///
-/// [`chain()`]: Iterator::chain
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// use std::iter;
-///
-/// // one is the loneliest number
-/// let mut one = iter::once_with(|| 1);
-///
-/// assert_eq!(Some(1), one.next());
-///
-/// // just one, that's all we get
-/// assert_eq!(None, one.next());
-/// ```
-///
-/// Chaining together with another iterator. Let's say that we want to iterate
-/// over each file of the `.foo` directory, but also a configuration file,
-/// `.foorc`:
-///
-/// ```no_run
-/// use std::iter;
-/// use std::fs;
-/// use std::path::PathBuf;
-///
-/// let dirs = fs::read_dir(".foo").unwrap();
-///
-/// // we need to convert from an iterator of DirEntry-s to an iterator of
-/// // PathBufs, so we use map
-/// let dirs = dirs.map(|file| file.unwrap().path());
-///
-/// // now, our iterator just for our config file
-/// let config = iter::once_with(|| PathBuf::from(".foorc"));
-///
-/// // chain the two iterators together into one big iterator
-/// let files = dirs.chain(config);
-///
-/// // this will give us all of the files in .foo as well as .foorc
-/// for f in files {
-///     println!("{:?}", f);
-/// }
-/// ```
-#[inline]
-#[stable(feature = "iter_once_with", since = "1.43.0")]
-pub fn once_with<A, F: FnOnce() -> A>(gen: F) -> OnceWith<F> {
-    OnceWith { gen: Some(gen) }
-}
-
-/// Creates a new iterator where each iteration calls the provided closure
-/// `F: FnMut() -> Option<T>`.
-///
-/// This allows creating a custom iterator with any behavior
-/// without using the more verbose syntax of creating a dedicated type
-/// and implementing the [`Iterator`] trait for it.
-///
-/// Note that the `FromFn` iterator doesn’t make assumptions about the behavior of the closure,
-/// and therefore conservatively does not implement [`FusedIterator`],
-/// or override [`Iterator::size_hint()`] from its default `(0, None)`.
-///
-/// The closure can use captures and its environment to track state across iterations. Depending on
-/// how the iterator is used, this may require specifying the [`move`] keyword on the closure.
-///
-/// [`move`]: ../../std/keyword.move.html
-///
-/// # Examples
-///
-/// Let’s re-implement the counter iterator from the [module-level documentation]:
-///
-/// [module-level documentation]: super
-///
-/// ```
-/// let mut count = 0;
-/// let counter = std::iter::from_fn(move || {
-///     // Increment our count. This is why we started at zero.
-///     count += 1;
-///
-///     // Check to see if we've finished counting or not.
-///     if count < 6 {
-///         Some(count)
-///     } else {
-///         None
-///     }
-/// });
-/// assert_eq!(counter.collect::<Vec<_>>(), &[1, 2, 3, 4, 5]);
-/// ```
-#[inline]
-#[stable(feature = "iter_from_fn", since = "1.34.0")]
-pub fn from_fn<T, F>(f: F) -> FromFn<F>
-where
-    F: FnMut() -> Option<T>,
-{
-    FromFn(f)
-}
-
-/// An iterator where each iteration calls the provided closure `F: FnMut() -> Option<T>`.
-///
-/// This `struct` is created by the [`iter::from_fn()`] function.
-/// See its documentation for more.
-///
-/// [`iter::from_fn()`]: from_fn
-#[derive(Clone)]
-#[stable(feature = "iter_from_fn", since = "1.34.0")]
-pub struct FromFn<F>(F);
-
-#[stable(feature = "iter_from_fn", since = "1.34.0")]
-impl<T, F> Iterator for FromFn<F>
-where
-    F: FnMut() -> Option<T>,
-{
-    type Item = T;
-
-    #[inline]
-    fn next(&mut self) -> Option<Self::Item> {
-        (self.0)()
-    }
-}
+#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
+pub use self::repeat_with::{repeat_with, RepeatWith};
 
 #[stable(feature = "iter_from_fn", since = "1.34.0")]
-impl<F> fmt::Debug for FromFn<F> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("FromFn").finish()
-    }
-}
+pub use self::from_fn::{from_fn, FromFn};
 
-/// Creates a new iterator where each successive item is computed based on the preceding one.
-///
-/// The iterator starts with the given first item (if any)
-/// and calls the given `FnMut(&T) -> Option<T>` closure to compute each item’s successor.
-///
-/// ```
-/// use std::iter::successors;
-///
-/// let powers_of_10 = successors(Some(1_u16), |n| n.checked_mul(10));
-/// assert_eq!(powers_of_10.collect::<Vec<_>>(), &[1, 10, 100, 1_000, 10_000]);
-/// ```
 #[stable(feature = "iter_successors", since = "1.34.0")]
-pub fn successors<T, F>(first: Option<T>, succ: F) -> Successors<T, F>
-where
-    F: FnMut(&T) -> Option<T>,
-{
-    // If this function returned `impl Iterator<Item=T>`
-    // it could be based on `unfold` and not need a dedicated type.
-    // However having a named `Successors<T, F>` type allows it to be `Clone` when `T` and `F` are.
-    Successors { next: first, succ }
-}
+pub use self::successors::{successors, Successors};
 
-/// An new iterator where each successive item is computed based on the preceding one.
-///
-/// This `struct` is created by the [`iter::successors()`] function.
-/// See its documentation for more.
-///
-/// [`iter::successors()`]: successors
-#[derive(Clone)]
-#[stable(feature = "iter_successors", since = "1.34.0")]
-pub struct Successors<T, F> {
-    next: Option<T>,
-    succ: F,
-}
-
-#[stable(feature = "iter_successors", since = "1.34.0")]
-impl<T, F> Iterator for Successors<T, F>
-where
-    F: FnMut(&T) -> Option<T>,
-{
-    type Item = T;
-
-    #[inline]
-    fn next(&mut self) -> Option<Self::Item> {
-        let item = self.next.take()?;
-        self.next = (self.succ)(&item);
-        Some(item)
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        if self.next.is_some() { (1, None) } else { (0, Some(0)) }
-    }
-}
-
-#[stable(feature = "iter_successors", since = "1.34.0")]
-impl<T, F> FusedIterator for Successors<T, F> where F: FnMut(&T) -> Option<T> {}
-
-#[stable(feature = "iter_successors", since = "1.34.0")]
-impl<T: fmt::Debug, F> fmt::Debug for Successors<T, F> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("Successors").field("next", &self.next).finish()
-    }
-}
+#[stable(feature = "iter_once_with", since = "1.43.0")]
+pub use self::once_with::{once_with, OnceWith};
diff --git a/library/core/src/iter/sources/empty.rs b/library/core/src/iter/sources/empty.rs
new file mode 100644 (file)
index 0000000..5d4a9fe
--- /dev/null
@@ -0,0 +1,92 @@
+use crate::fmt;
+use crate::iter::{FusedIterator, TrustedLen};
+use crate::marker;
+
+/// Creates an iterator that yields nothing.
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// use std::iter;
+///
+/// // this could have been an iterator over i32, but alas, it's just not.
+/// let mut nope = iter::empty::<i32>();
+///
+/// assert_eq!(None, nope.next());
+/// ```
+#[stable(feature = "iter_empty", since = "1.2.0")]
+#[rustc_const_stable(feature = "const_iter_empty", since = "1.32.0")]
+pub const fn empty<T>() -> Empty<T> {
+    Empty(marker::PhantomData)
+}
+
+/// An iterator that yields nothing.
+///
+/// This `struct` is created by the [`empty()`] function. See its documentation for more.
+#[stable(feature = "iter_empty", since = "1.2.0")]
+pub struct Empty<T>(marker::PhantomData<T>);
+
+#[stable(feature = "iter_empty_send_sync", since = "1.42.0")]
+unsafe impl<T> Send for Empty<T> {}
+#[stable(feature = "iter_empty_send_sync", since = "1.42.0")]
+unsafe impl<T> Sync for Empty<T> {}
+
+#[stable(feature = "core_impl_debug", since = "1.9.0")]
+impl<T> fmt::Debug for Empty<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.pad("Empty")
+    }
+}
+
+#[stable(feature = "iter_empty", since = "1.2.0")]
+impl<T> Iterator for Empty<T> {
+    type Item = T;
+
+    fn next(&mut self) -> Option<T> {
+        None
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (0, Some(0))
+    }
+}
+
+#[stable(feature = "iter_empty", since = "1.2.0")]
+impl<T> DoubleEndedIterator for Empty<T> {
+    fn next_back(&mut self) -> Option<T> {
+        None
+    }
+}
+
+#[stable(feature = "iter_empty", since = "1.2.0")]
+impl<T> ExactSizeIterator for Empty<T> {
+    fn len(&self) -> usize {
+        0
+    }
+}
+
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<T> TrustedLen for Empty<T> {}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<T> FusedIterator for Empty<T> {}
+
+// not #[derive] because that adds a Clone bound on T,
+// which isn't necessary.
+#[stable(feature = "iter_empty", since = "1.2.0")]
+impl<T> Clone for Empty<T> {
+    fn clone(&self) -> Empty<T> {
+        Empty(marker::PhantomData)
+    }
+}
+
+// not #[derive] because that adds a Default bound on T,
+// which isn't necessary.
+#[stable(feature = "iter_empty", since = "1.2.0")]
+impl<T> Default for Empty<T> {
+    fn default() -> Empty<T> {
+        Empty(marker::PhantomData)
+    }
+}
diff --git a/library/core/src/iter/sources/from_fn.rs b/library/core/src/iter/sources/from_fn.rs
new file mode 100644 (file)
index 0000000..3cd3830
--- /dev/null
@@ -0,0 +1,78 @@
+use crate::fmt;
+
+/// Creates a new iterator where each iteration calls the provided closure
+/// `F: FnMut() -> Option<T>`.
+///
+/// This allows creating a custom iterator with any behavior
+/// without using the more verbose syntax of creating a dedicated type
+/// and implementing the [`Iterator`] trait for it.
+///
+/// Note that the `FromFn` iterator doesn’t make assumptions about the behavior of the closure,
+/// and therefore conservatively does not implement [`FusedIterator`],
+/// or override [`Iterator::size_hint()`] from its default `(0, None)`.
+///
+/// The closure can use captures and its environment to track state across iterations. Depending on
+/// how the iterator is used, this may require specifying the [`move`] keyword on the closure.
+///
+/// [`move`]: ../../std/keyword.move.html
+/// [`FusedIterator`]: crate::iter::FusedIterator
+///
+/// # Examples
+///
+/// Let’s re-implement the counter iterator from [module-level documentation]:
+///
+/// [module-level documentation]: crate::iter
+///
+/// ```
+/// let mut count = 0;
+/// let counter = std::iter::from_fn(move || {
+///     // Increment our count. This is why we started at zero.
+///     count += 1;
+///
+///     // Check to see if we've finished counting or not.
+///     if count < 6 {
+///         Some(count)
+///     } else {
+///         None
+///     }
+/// });
+/// assert_eq!(counter.collect::<Vec<_>>(), &[1, 2, 3, 4, 5]);
+/// ```
+#[inline]
+#[stable(feature = "iter_from_fn", since = "1.34.0")]
+pub fn from_fn<T, F>(f: F) -> FromFn<F>
+where
+    F: FnMut() -> Option<T>,
+{
+    FromFn(f)
+}
+
+/// An iterator where each iteration calls the provided closure `F: FnMut() -> Option<T>`.
+///
+/// This `struct` is created by the [`iter::from_fn()`] function.
+/// See its documentation for more.
+///
+/// [`iter::from_fn()`]: from_fn
+#[derive(Clone)]
+#[stable(feature = "iter_from_fn", since = "1.34.0")]
+pub struct FromFn<F>(F);
+
+#[stable(feature = "iter_from_fn", since = "1.34.0")]
+impl<T, F> Iterator for FromFn<F>
+where
+    F: FnMut() -> Option<T>,
+{
+    type Item = T;
+
+    #[inline]
+    fn next(&mut self) -> Option<Self::Item> {
+        (self.0)()
+    }
+}
+
+#[stable(feature = "iter_from_fn", since = "1.34.0")]
+impl<F> fmt::Debug for FromFn<F> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("FromFn").finish()
+    }
+}
diff --git a/library/core/src/iter/sources/once.rs b/library/core/src/iter/sources/once.rs
new file mode 100644 (file)
index 0000000..27bc3dc
--- /dev/null
@@ -0,0 +1,99 @@
+use crate::iter::{FusedIterator, TrustedLen};
+
+/// Creates an iterator that yields an element exactly once.
+///
+/// This is commonly used to adapt a single value into a [`chain()`] of other
+/// kinds of iteration. Maybe you have an iterator that covers almost
+/// everything, but you need an extra special case. Maybe you have a function
+/// which works on iterators, but you only need to process one value.
+///
+/// [`chain()`]: Iterator::chain
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// use std::iter;
+///
+/// // one is the loneliest number
+/// let mut one = iter::once(1);
+///
+/// assert_eq!(Some(1), one.next());
+///
+/// // just one, that's all we get
+/// assert_eq!(None, one.next());
+/// ```
+///
+/// Chaining together with another iterator. Let's say that we want to iterate
+/// over each file of the `.foo` directory, but also a configuration file,
+/// `.foorc`:
+///
+/// ```no_run
+/// use std::iter;
+/// use std::fs;
+/// use std::path::PathBuf;
+///
+/// let dirs = fs::read_dir(".foo").unwrap();
+///
+/// // we need to convert from an iterator of DirEntry-s to an iterator of
+/// // PathBufs, so we use map
+/// let dirs = dirs.map(|file| file.unwrap().path());
+///
+/// // now, our iterator just for our config file
+/// let config = iter::once(PathBuf::from(".foorc"));
+///
+/// // chain the two iterators together into one big iterator
+/// let files = dirs.chain(config);
+///
+/// // this will give us all of the files in .foo as well as .foorc
+/// for f in files {
+///     println!("{:?}", f);
+/// }
+/// ```
+#[stable(feature = "iter_once", since = "1.2.0")]
+pub fn once<T>(value: T) -> Once<T> {
+    Once { inner: Some(value).into_iter() }
+}
+
+/// An iterator that yields an element exactly once.
+///
+/// This `struct` is created by the [`once()`] function. See its documentation for more.
+#[derive(Clone, Debug)]
+#[stable(feature = "iter_once", since = "1.2.0")]
+pub struct Once<T> {
+    inner: crate::option::IntoIter<T>,
+}
+
+#[stable(feature = "iter_once", since = "1.2.0")]
+impl<T> Iterator for Once<T> {
+    type Item = T;
+
+    fn next(&mut self) -> Option<T> {
+        self.inner.next()
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.inner.size_hint()
+    }
+}
+
+#[stable(feature = "iter_once", since = "1.2.0")]
+impl<T> DoubleEndedIterator for Once<T> {
+    fn next_back(&mut self) -> Option<T> {
+        self.inner.next_back()
+    }
+}
+
+#[stable(feature = "iter_once", since = "1.2.0")]
+impl<T> ExactSizeIterator for Once<T> {
+    fn len(&self) -> usize {
+        self.inner.len()
+    }
+}
+
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<T> TrustedLen for Once<T> {}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<T> FusedIterator for Once<T> {}
diff --git a/library/core/src/iter/sources/once_with.rs b/library/core/src/iter/sources/once_with.rs
new file mode 100644 (file)
index 0000000..cf6a3c1
--- /dev/null
@@ -0,0 +1,109 @@
+use crate::iter::{FusedIterator, TrustedLen};
+
+/// Creates an iterator that lazily generates a value exactly once by invoking
+/// the provided closure.
+///
+/// This is commonly used to adapt a single value generator into a [`chain()`] of
+/// other kinds of iteration. Maybe you have an iterator that covers almost
+/// everything, but you need an extra special case. Maybe you have a function
+/// which works on iterators, but you only need to process one value.
+///
+/// Unlike [`once()`], this function will lazily generate the value on request.
+///
+/// [`chain()`]: Iterator::chain
+/// [`once()`]: crate::iter::once
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// use std::iter;
+///
+/// // one is the loneliest number
+/// let mut one = iter::once_with(|| 1);
+///
+/// assert_eq!(Some(1), one.next());
+///
+/// // just one, that's all we get
+/// assert_eq!(None, one.next());
+/// ```
+///
+/// Chaining together with another iterator. Let's say that we want to iterate
+/// over each file of the `.foo` directory, but also a configuration file,
+/// `.foorc`:
+///
+/// ```no_run
+/// use std::iter;
+/// use std::fs;
+/// use std::path::PathBuf;
+///
+/// let dirs = fs::read_dir(".foo").unwrap();
+///
+/// // we need to convert from an iterator of DirEntry-s to an iterator of
+/// // PathBufs, so we use map
+/// let dirs = dirs.map(|file| file.unwrap().path());
+///
+/// // now, our iterator just for our config file
+/// let config = iter::once_with(|| PathBuf::from(".foorc"));
+///
+/// // chain the two iterators together into one big iterator
+/// let files = dirs.chain(config);
+///
+/// // this will give us all of the files in .foo as well as .foorc
+/// for f in files {
+///     println!("{:?}", f);
+/// }
+/// ```
+#[inline]
+#[stable(feature = "iter_once_with", since = "1.43.0")]
+pub fn once_with<A, F: FnOnce() -> A>(gen: F) -> OnceWith<F> {
+    OnceWith { gen: Some(gen) }
+}
+
+/// An iterator that yields a single element of type `A` by
+/// applying the provided closure `F: FnOnce() -> A`.
+///
+/// This `struct` is created by the [`once_with()`] function.
+/// See its documentation for more.
+#[derive(Clone, Debug)]
+#[stable(feature = "iter_once_with", since = "1.43.0")]
+pub struct OnceWith<F> {
+    gen: Option<F>,
+}
+
+#[stable(feature = "iter_once_with", since = "1.43.0")]
+impl<A, F: FnOnce() -> A> Iterator for OnceWith<F> {
+    type Item = A;
+
+    #[inline]
+    fn next(&mut self) -> Option<A> {
+        let f = self.gen.take()?;
+        Some(f())
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.gen.iter().size_hint()
+    }
+}
+
+#[stable(feature = "iter_once_with", since = "1.43.0")]
+impl<A, F: FnOnce() -> A> DoubleEndedIterator for OnceWith<F> {
+    fn next_back(&mut self) -> Option<A> {
+        self.next()
+    }
+}
+
+#[stable(feature = "iter_once_with", since = "1.43.0")]
+impl<A, F: FnOnce() -> A> ExactSizeIterator for OnceWith<F> {
+    fn len(&self) -> usize {
+        self.gen.iter().len()
+    }
+}
+
+#[stable(feature = "iter_once_with", since = "1.43.0")]
+impl<A, F: FnOnce() -> A> FusedIterator for OnceWith<F> {}
+
+#[stable(feature = "iter_once_with", since = "1.43.0")]
+unsafe impl<A, F: FnOnce() -> A> TrustedLen for OnceWith<F> {}
diff --git a/library/core/src/iter/sources/repeat.rs b/library/core/src/iter/sources/repeat.rs
new file mode 100644 (file)
index 0000000..d1f2879
--- /dev/null
@@ -0,0 +1,93 @@
+use crate::iter::{FusedIterator, TrustedLen};
+
+/// Creates a new iterator that endlessly repeats a single element.
+///
+/// The `repeat()` function repeats a single value over and over again.
+///
+/// Infinite iterators like `repeat()` are often used with adapters like
+/// [`Iterator::take()`], in order to make them finite.
+///
+/// If the element type of the iterator you need does not implement `Clone`,
+/// or if you do not want to keep the repeated element in memory, you can
+/// instead use the [`repeat_with()`] function.
+///
+/// [`repeat_with()`]: crate::iter::repeat_with
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// use std::iter;
+///
+/// // the number four 4ever:
+/// let mut fours = iter::repeat(4);
+///
+/// assert_eq!(Some(4), fours.next());
+/// assert_eq!(Some(4), fours.next());
+/// assert_eq!(Some(4), fours.next());
+/// assert_eq!(Some(4), fours.next());
+/// assert_eq!(Some(4), fours.next());
+///
+/// // yup, still four
+/// assert_eq!(Some(4), fours.next());
+/// ```
+///
+/// Going finite with [`Iterator::take()`]:
+///
+/// ```
+/// use std::iter;
+///
+/// // that last example was too many fours. Let's only have four fours.
+/// let mut four_fours = iter::repeat(4).take(4);
+///
+/// assert_eq!(Some(4), four_fours.next());
+/// assert_eq!(Some(4), four_fours.next());
+/// assert_eq!(Some(4), four_fours.next());
+/// assert_eq!(Some(4), four_fours.next());
+///
+/// // ... and now we're done
+/// assert_eq!(None, four_fours.next());
+/// ```
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn repeat<T: Clone>(elt: T) -> Repeat<T> {
+    Repeat { element: elt }
+}
+
+/// An iterator that repeats an element endlessly.
+///
+/// This `struct` is created by the [`repeat()`] function. See its documentation for more.
+#[derive(Clone, Debug)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Repeat<A> {
+    element: A,
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A: Clone> Iterator for Repeat<A> {
+    type Item = A;
+
+    #[inline]
+    fn next(&mut self) -> Option<A> {
+        Some(self.element.clone())
+    }
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (usize::MAX, None)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A: Clone> DoubleEndedIterator for Repeat<A> {
+    #[inline]
+    fn next_back(&mut self) -> Option<A> {
+        Some(self.element.clone())
+    }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<A: Clone> FusedIterator for Repeat<A> {}
+
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<A: Clone> TrustedLen for Repeat<A> {}
diff --git a/library/core/src/iter/sources/repeat_with.rs b/library/core/src/iter/sources/repeat_with.rs
new file mode 100644 (file)
index 0000000..44bc689
--- /dev/null
@@ -0,0 +1,98 @@
+use crate::iter::{FusedIterator, TrustedLen};
+
+/// Creates a new iterator that repeats elements of type `A` endlessly by
+/// applying the provided closure, the repeater, `F: FnMut() -> A`.
+///
+/// The `repeat_with()` function calls the repeater over and over again.
+///
+/// Infinite iterators like `repeat_with()` are often used with adapters like
+/// [`Iterator::take()`], in order to make them finite.
+///
+/// If the element type of the iterator you need implements [`Clone`], and
+/// it is OK to keep the source element in memory, you should instead use
+/// the [`repeat()`] function.
+///
+/// An iterator produced by `repeat_with()` is not a [`DoubleEndedIterator`].
+/// If you need `repeat_with()` to return a [`DoubleEndedIterator`],
+/// please open a GitHub issue explaining your use case.
+///
+/// [`repeat()`]: crate::iter::repeat
+/// [`DoubleEndedIterator`]: crate::iter::DoubleEndedIterator
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// use std::iter;
+///
+/// // let's assume we have some value of a type that is not `Clone`
+/// // or which don't want to have in memory just yet because it is expensive:
+/// #[derive(PartialEq, Debug)]
+/// struct Expensive;
+///
+/// // a particular value forever:
+/// let mut things = iter::repeat_with(|| Expensive);
+///
+/// assert_eq!(Some(Expensive), things.next());
+/// assert_eq!(Some(Expensive), things.next());
+/// assert_eq!(Some(Expensive), things.next());
+/// assert_eq!(Some(Expensive), things.next());
+/// assert_eq!(Some(Expensive), things.next());
+/// ```
+///
+/// Using mutation and going finite:
+///
+/// ```rust
+/// use std::iter;
+///
+/// // From the zeroth to the third power of two:
+/// let mut curr = 1;
+/// let mut pow2 = iter::repeat_with(|| { let tmp = curr; curr *= 2; tmp })
+///                     .take(4);
+///
+/// assert_eq!(Some(1), pow2.next());
+/// assert_eq!(Some(2), pow2.next());
+/// assert_eq!(Some(4), pow2.next());
+/// assert_eq!(Some(8), pow2.next());
+///
+/// // ... and now we're done
+/// assert_eq!(None, pow2.next());
+/// ```
+#[inline]
+#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
+pub fn repeat_with<A, F: FnMut() -> A>(repeater: F) -> RepeatWith<F> {
+    RepeatWith { repeater }
+}
+
+/// An iterator that repeats elements of type `A` endlessly by
+/// applying the provided closure `F: FnMut() -> A`.
+///
+/// This `struct` is created by the [`repeat_with()`] function.
+/// See its documentation for more.
+#[derive(Copy, Clone, Debug)]
+#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
+pub struct RepeatWith<F> {
+    repeater: F,
+}
+
+#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
+impl<A, F: FnMut() -> A> Iterator for RepeatWith<F> {
+    type Item = A;
+
+    #[inline]
+    fn next(&mut self) -> Option<A> {
+        Some((self.repeater)())
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (usize::MAX, None)
+    }
+}
+
+#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
+impl<A, F: FnMut() -> A> FusedIterator for RepeatWith<F> {}
+
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<A, F: FnMut() -> A> TrustedLen for RepeatWith<F> {}
diff --git a/library/core/src/iter/sources/successors.rs b/library/core/src/iter/sources/successors.rs
new file mode 100644 (file)
index 0000000..99f058a
--- /dev/null
@@ -0,0 +1,66 @@
+use crate::{fmt, iter::FusedIterator};
+
+/// Creates a new iterator where each successive item is computed based on the preceding one.
+///
+/// The iterator starts with the given first item (if any)
+/// and calls the given `FnMut(&T) -> Option<T>` closure to compute each item’s successor.
+///
+/// ```
+/// use std::iter::successors;
+///
+/// let powers_of_10 = successors(Some(1_u16), |n| n.checked_mul(10));
+/// assert_eq!(powers_of_10.collect::<Vec<_>>(), &[1, 10, 100, 1_000, 10_000]);
+/// ```
+#[stable(feature = "iter_successors", since = "1.34.0")]
+pub fn successors<T, F>(first: Option<T>, succ: F) -> Successors<T, F>
+where
+    F: FnMut(&T) -> Option<T>,
+{
+    // If this function returned `impl Iterator<Item=T>`
+    // it could be based on `unfold` and not need a dedicated type.
+    // However having a named `Successors<T, F>` type allows it to be `Clone` when `T` and `F` are.
+    Successors { next: first, succ }
+}
+
+/// An new iterator where each successive item is computed based on the preceding one.
+///
+/// This `struct` is created by the [`iter::successors()`] function.
+/// See its documentation for more.
+///
+/// [`iter::successors()`]: successors
+#[derive(Clone)]
+#[stable(feature = "iter_successors", since = "1.34.0")]
+pub struct Successors<T, F> {
+    next: Option<T>,
+    succ: F,
+}
+
+#[stable(feature = "iter_successors", since = "1.34.0")]
+impl<T, F> Iterator for Successors<T, F>
+where
+    F: FnMut(&T) -> Option<T>,
+{
+    type Item = T;
+
+    #[inline]
+    fn next(&mut self) -> Option<Self::Item> {
+        let item = self.next.take()?;
+        self.next = (self.succ)(&item);
+        Some(item)
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        if self.next.is_some() { (1, None) } else { (0, Some(0)) }
+    }
+}
+
+#[stable(feature = "iter_successors", since = "1.34.0")]
+impl<T, F> FusedIterator for Successors<T, F> where F: FnMut(&T) -> Option<T> {}
+
+#[stable(feature = "iter_successors", since = "1.34.0")]
+impl<T: fmt::Debug, F> fmt::Debug for Successors<T, F> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("Successors").field("next", &self.next).finish()
+    }
+}
index d67f9c15a1916dc218c5d27141df209076ca9659..e3b004be39afb4cd65b532f04d162598135db10a 100644 (file)
@@ -63,7 +63,7 @@
 #![warn(missing_debug_implementations)]
 #![allow(explicit_outlives_requirements)]
 #![allow(incomplete_features)]
-#![cfg_attr(not(bootstrap), feature(rustc_allow_const_fn_unstable))]
+#![feature(rustc_allow_const_fn_unstable)]
 #![feature(allow_internal_unstable)]
 #![feature(arbitrary_self_types)]
 #![feature(asm)]
 #![feature(const_overflowing_int_methods)]
 #![feature(const_int_unchecked_arith)]
 #![feature(const_mut_refs)]
-#![feature(const_int_pow)]
-#![feature(constctlz)]
 #![feature(const_cttz)]
 #![feature(const_panic)]
 #![feature(const_pin)]
 #![feature(const_fn)]
 #![feature(const_fn_union)]
-#![cfg_attr(not(bootstrap), feature(const_impl_trait))]
+#![feature(const_impl_trait)]
 #![feature(const_fn_floating_point_arithmetic)]
 #![feature(const_fn_fn_ptr_basics)]
 #![feature(const_generics)]
 #![feature(nll)]
 #![feature(exhaustive_patterns)]
 #![feature(no_core)]
-#![feature(optin_builtin_traits)]
+#![cfg_attr(bootstrap, feature(optin_builtin_traits))]
+#![cfg_attr(not(bootstrap), feature(auto_traits))]
 #![feature(or_patterns)]
 #![feature(prelude_import)]
 #![feature(repr_simd, platform_intrinsics)]
 #![feature(transparent_unions)]
 #![feature(try_blocks)]
 #![feature(unboxed_closures)]
-#![cfg_attr(not(bootstrap), feature(unsized_fn_params))]
-#![cfg_attr(bootstrap, feature(unsized_locals))]
-#![cfg_attr(bootstrap, feature(untagged_unions))]
+#![feature(unsized_fn_params)]
 #![feature(unwind_attributes)]
 #![feature(variant_count)]
 #![feature(tbm_target_feature)]
     unused_imports,
     unsafe_op_in_unsafe_fn
 )]
-#[cfg_attr(not(bootstrap), allow(non_autolinks))]
+#[allow(non_autolinks)]
 // FIXME: This annotation should be moved into rust-lang/stdarch after clashing_extern_declarations is
 // merged. It currently cannot because bootstrap fails as the lint hasn't been defined yet.
 #[allow(clashing_extern_declarations)]
index fe3eff04b4ae59e15860f79dcf58a9b8df36b52e..0699c9eab1871922b819558ef3ac74286da95eeb 100644 (file)
@@ -2,6 +2,7 @@
 #[macro_export]
 #[allow_internal_unstable(core_panic, const_caller_location)]
 #[stable(feature = "core", since = "1.6.0")]
+#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "core_panic_macro")]
 macro_rules! panic {
     () => (
         $crate::panic!("explicit panic")
@@ -44,7 +45,7 @@ macro_rules! assert_eq {
                     // The reborrows below are intentional. Without them, the stack slot for the
                     // borrow is initialized even before the values are compared, leading to a
                     // noticeable slow down.
-                    panic!(r#"assertion failed: `(left == right)`
+                    $crate::panic!(r#"assertion failed: `(left == right)`
   left: `{:?}`,
  right: `{:?}`"#, &*left_val, &*right_val)
                 }
@@ -58,7 +59,7 @@ macro_rules! assert_eq {
                     // The reborrows below are intentional. Without them, the stack slot for the
                     // borrow is initialized even before the values are compared, leading to a
                     // noticeable slow down.
-                    panic!(r#"assertion failed: `(left == right)`
+                    $crate::panic!(r#"assertion failed: `(left == right)`
   left: `{:?}`,
  right: `{:?}`: {}"#, &*left_val, &*right_val,
                            $crate::format_args!($($arg)+))
@@ -95,7 +96,7 @@ macro_rules! assert_ne {
                     // The reborrows below are intentional. Without them, the stack slot for the
                     // borrow is initialized even before the values are compared, leading to a
                     // noticeable slow down.
-                    panic!(r#"assertion failed: `(left != right)`
+                    $crate::panic!(r#"assertion failed: `(left != right)`
   left: `{:?}`,
  right: `{:?}`"#, &*left_val, &*right_val)
                 }
@@ -109,7 +110,7 @@ macro_rules! assert_ne {
                     // The reborrows below are intentional. Without them, the stack slot for the
                     // borrow is initialized even before the values are compared, leading to a
                     // noticeable slow down.
-                    panic!(r#"assertion failed: `(left != right)`
+                    $crate::panic!(r#"assertion failed: `(left != right)`
   left: `{:?}`,
  right: `{:?}`: {}"#, &*left_val, &*right_val,
                            $crate::format_args!($($arg)+))
@@ -162,6 +163,7 @@ macro_rules! assert_ne {
 /// ```
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "debug_assert_macro")]
 macro_rules! debug_assert {
     ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert!($($arg)*); })
 }
@@ -466,7 +468,7 @@ macro_rules! writeln {
 ///
 /// # Panics
 ///
-/// This will always [`panic!`]
+/// This will always [`panic!`].
 ///
 /// # Examples
 ///
@@ -500,13 +502,13 @@ macro_rules! writeln {
 #[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! unreachable {
     () => ({
-        panic!("internal error: entered unreachable code")
+        $crate::panic!("internal error: entered unreachable code")
     });
     ($msg:expr $(,)?) => ({
         $crate::unreachable!("{}", $msg)
     });
     ($fmt:expr, $($arg:tt)*) => ({
-        panic!($crate::concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
+        $crate::panic!($crate::concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
     });
 }
 
@@ -515,15 +517,15 @@ macro_rules! unreachable {
 /// This allows your code to type-check, which is useful if you are prototyping or
 /// implementing a trait that requires multiple methods which you don't plan of using all of.
 ///
-/// The difference between `unimplemented!` and [`todo!`](macro.todo.html) is that while `todo!`
+/// The difference between `unimplemented!` and [`todo!`] is that while `todo!`
 /// conveys an intent of implementing the functionality later and the message is "not yet
 /// implemented", `unimplemented!` makes no such claims. Its message is "not implemented".
 /// Also some IDEs will mark `todo!`s.
 ///
 /// # Panics
 ///
-/// This will always [panic!](macro.panic.html) because `unimplemented!` is just a
-/// shorthand for `panic!` with a fixed, specific message.
+/// This will always [`panic!`] because `unimplemented!` is just a shorthand for `panic!` with a
+/// fixed, specific message.
 ///
 /// Like `panic!`, this macro has a second form for displaying custom values.
 ///
@@ -584,8 +586,8 @@ macro_rules! unreachable {
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! unimplemented {
-    () => (panic!("not implemented"));
-    ($($arg:tt)+) => (panic!("not implemented: {}", $crate::format_args!($($arg)+)));
+    () => ($crate::panic!("not implemented"));
+    ($($arg:tt)+) => ($crate::panic!("not implemented: {}", $crate::format_args!($($arg)+)));
 }
 
 /// Indicates unfinished code.
@@ -600,7 +602,7 @@ macro_rules! unimplemented {
 ///
 /// # Panics
 ///
-/// This will always [panic!](macro.panic.html)
+/// This will always [`panic!`].
 ///
 /// # Examples
 ///
@@ -645,8 +647,8 @@ macro_rules! unimplemented {
 #[macro_export]
 #[stable(feature = "todo_macro", since = "1.40.0")]
 macro_rules! todo {
-    () => (panic!("not yet implemented"));
-    ($($arg:tt)+) => (panic!("not yet implemented: {}", $crate::format_args!($($arg)+)));
+    () => ($crate::panic!("not yet implemented"));
+    ($($arg:tt)+) => ($crate::panic!("not yet implemented: {}", $crate::format_args!($($arg)+)));
 }
 
 /// Definitions of built-in macros.
@@ -1215,6 +1217,8 @@ macro_rules! include {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_builtin_macro]
     #[macro_export]
+    #[cfg_attr(not(bootstrap), rustc_diagnostic_item = "assert_macro")]
+    #[allow_internal_unstable(core_panic)]
     macro_rules! assert {
         ($cond:expr $(,)?) => {{ /* compiler built-in */ }};
         ($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }};
index cdf742057b7b6f37458e1a009f774f2815dd6127..85e0e7200875d9eb390d68bfda428726ac29cd47 100644 (file)
@@ -156,18 +156,18 @@ pub trait StructuralPartialEq {
 /// Required trait for constants used in pattern matches.
 ///
 /// Any type that derives `Eq` automatically implements this trait, *regardless*
-/// of whether its type-parameters implement `Eq`.
+/// of whether its type parameters implement `Eq`.
 ///
-/// This is a hack to workaround a limitation in our type-system.
+/// This is a hack to work around a limitation in our type system.
 ///
-/// Background:
+/// # Background
 ///
 /// We want to require that types of consts used in pattern matches
 /// have the attribute `#[derive(PartialEq, Eq)]`.
 ///
 /// In a more ideal world, we could check that requirement by just checking that
-/// the given type implements both (1.) the `StructuralPartialEq` trait *and*
-/// (2.) the `Eq` trait. However, you can have ADTs that *do* `derive(PartialEq, Eq)`,
+/// the given type implements both the `StructuralPartialEq` trait *and*
+/// the `Eq` trait. However, you can have ADTs that *do* `derive(PartialEq, Eq)`,
 /// and be a case that we want the compiler to accept, and yet the constant's
 /// type fails to implement `Eq`.
 ///
@@ -176,8 +176,11 @@ pub trait StructuralPartialEq {
 /// ```rust
 /// #[derive(PartialEq, Eq)]
 /// struct Wrap<X>(X);
+///
 /// fn higher_order(_: &()) { }
+///
 /// const CFN: Wrap<fn(&())> = Wrap(higher_order);
+///
 /// fn main() {
 ///     match CFN {
 ///         CFN => {}
@@ -772,7 +775,7 @@ unsafe impl<T: ?Sized> Freeze for &mut T {}
 ///
 /// If a type contains a `PhantomPinned`, it will not implement `Unpin` by default.
 #[stable(feature = "pin", since = "1.33.0")]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
+#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
 pub struct PhantomPinned;
 
 #[stable(feature = "pin", since = "1.33.0")]
index 660b7db70be928ebebd5fcb5a36b98cc506044f3..1924720b949f84f479b9650db260c06ebb77b047 100644 (file)
@@ -348,7 +348,7 @@ pub const fn uninit() -> MaybeUninit<T> {
     /// ```rust,no_run
     /// use std::mem::MaybeUninit;
     ///
-    /// enum NotZero { One = 1, Two = 2 };
+    /// enum NotZero { One = 1, Two = 2 }
     ///
     /// let x = MaybeUninit::<(u8, NotZero)>::zeroed();
     /// let x = unsafe { x.assume_init() };
@@ -392,7 +392,7 @@ pub fn write(&mut self, val: T) -> &mut T {
     /// use std::mem::MaybeUninit;
     ///
     /// let mut x = MaybeUninit::<Vec<u32>>::uninit();
-    /// unsafe { x.as_mut_ptr().write(vec![0,1,2]); }
+    /// unsafe { x.as_mut_ptr().write(vec![0, 1, 2]); }
     /// // Create a reference into the `MaybeUninit<T>`. This is okay because we initialized it.
     /// let x_vec = unsafe { &*x.as_ptr() };
     /// assert_eq!(x_vec.len(), 3);
@@ -429,7 +429,7 @@ pub const fn as_ptr(&self) -> *const T {
     /// use std::mem::MaybeUninit;
     ///
     /// let mut x = MaybeUninit::<Vec<u32>>::uninit();
-    /// unsafe { x.as_mut_ptr().write(vec![0,1,2]); }
+    /// unsafe { x.as_mut_ptr().write(vec![0, 1, 2]); }
     /// // Create a reference into the `MaybeUninit<Vec<u32>>`.
     /// // This is okay because we initialized it.
     /// let x_vec = unsafe { &mut *x.as_mut_ptr() };
@@ -565,7 +565,7 @@ pub unsafe fn assume_init(self) -> T {
     /// use std::mem::MaybeUninit;
     ///
     /// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit();
-    /// x.write(Some(vec![0,1,2]));
+    /// x.write(Some(vec![0, 1, 2]));
     /// let x1 = unsafe { x.assume_init_read() };
     /// let x2 = unsafe { x.assume_init_read() };
     /// // We now created two copies of the same vector, leading to a double-free ⚠️ when
index 86e6352d132155340662a9dff6fc4a67da78688d..33df175bfc54d628ff3db0f9fd1763bd5b4e92eb 100644 (file)
@@ -441,6 +441,32 @@ pub const fn is_finite(self) -> bool {
         self.abs_private() < Self::INFINITY
     }
 
+    /// Returns `true` if the number is [subnormal].
+    ///
+    /// ```
+    /// #![feature(is_subnormal)]
+    /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32
+    /// let max = f32::MAX;
+    /// let lower_than_min = 1.0e-40_f32;
+    /// let zero = 0.0_f32;
+    ///
+    /// assert!(!min.is_subnormal());
+    /// assert!(!max.is_subnormal());
+    ///
+    /// assert!(!zero.is_subnormal());
+    /// assert!(!f32::NAN.is_subnormal());
+    /// assert!(!f32::INFINITY.is_subnormal());
+    /// // Values between `0` and `min` are Subnormal.
+    /// assert!(lower_than_min.is_subnormal());
+    /// ```
+    /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
+    #[unstable(feature = "is_subnormal", issue = "79288")]
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
+    #[inline]
+    pub const fn is_subnormal(self) -> bool {
+        matches!(self.classify(), FpCategory::Subnormal)
+    }
+
     /// Returns `true` if the number is neither zero, infinite,
     /// [subnormal], or `NaN`.
     ///
index 9b1405b479f7c3d2b7766704d9cac04a7ff5dc89..b85e8deb6d22c47606b95456a5698b0b37a1e751 100644 (file)
@@ -440,6 +440,32 @@ pub const fn is_finite(self) -> bool {
         self.abs_private() < Self::INFINITY
     }
 
+    /// Returns `true` if the number is [subnormal].
+    ///
+    /// ```
+    /// #![feature(is_subnormal)]
+    /// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308_f64
+    /// let max = f64::MAX;
+    /// let lower_than_min = 1.0e-308_f64;
+    /// let zero = 0.0_f64;
+    ///
+    /// assert!(!min.is_subnormal());
+    /// assert!(!max.is_subnormal());
+    ///
+    /// assert!(!zero.is_subnormal());
+    /// assert!(!f64::NAN.is_subnormal());
+    /// assert!(!f64::INFINITY.is_subnormal());
+    /// // Values between `0` and `min` are Subnormal.
+    /// assert!(lower_than_min.is_subnormal());
+    /// ```
+    /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
+    #[unstable(feature = "is_subnormal", issue = "79288")]
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
+    #[inline]
+    pub const fn is_subnormal(self) -> bool {
+        matches!(self.classify(), FpCategory::Subnormal)
+    }
+
     /// Returns `true` if the number is neither zero, infinite,
     /// [subnormal], or `NaN`.
     ///
index 728381b658f7cd837745a00d7ec6bc35868dd1d2..33eefe5d26580d8150658b884690af0c3fa17339 100644 (file)
@@ -791,7 +791,7 @@ pub const fn checked_abs(self) -> Option<Self> {
 ```"),
 
             #[stable(feature = "no_panic_pow", since = "1.34.0")]
-            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
@@ -974,7 +974,7 @@ pub const fn saturating_mul(self, rhs: Self) -> Self {
 $EndFeature, "
 ```"),
             #[stable(feature = "no_panic_pow", since = "1.34.0")]
-            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
@@ -1340,7 +1340,7 @@ pub const fn unsigned_abs(self) -> $UnsignedT {
 $EndFeature, "
 ```"),
             #[stable(feature = "no_panic_pow", since = "1.34.0")]
-            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
@@ -1707,7 +1707,7 @@ pub const fn overflowing_abs(self) -> (Self, bool) {
 $EndFeature, "
 ```"),
             #[stable(feature = "no_panic_pow", since = "1.34.0")]
-            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
@@ -1757,7 +1757,7 @@ pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
 $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
@@ -2047,8 +2047,7 @@ pub const fn is_negative(self) -> bool { self < 0 }
             #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             // SAFETY: const sound because integers are plain old datatypes so we can always
             // transmute them to arrays of bytes
-            #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
-            #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
+            #[rustc_allow_const_fn_unstable(const_fn_transmute)]
             #[inline]
             pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
                 // SAFETY: integers are plain old datatypes so we can always transmute them to
@@ -2196,8 +2195,7 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
             #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             // SAFETY: const sound because integers are plain old datatypes so we can always
             // transmute to them
-            #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
-            #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
+            #[rustc_allow_const_fn_unstable(const_fn_transmute)]
             #[inline]
             pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
                 // SAFETY: integers are plain old datatypes so we can always transmute to them
index adcbbf91433b61782069826e8032e3f7eacda7d0..390c1b7e9e8710f3ea415f61e7509fce07b29c7b 100644 (file)
@@ -749,7 +749,7 @@ pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
 assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);", $EndFeature, "
 ```"),
             #[stable(feature = "no_panic_pow", since = "1.34.0")]
-            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
@@ -865,7 +865,7 @@ pub const fn saturating_mul(self, rhs: Self) -> Self {
 $EndFeature, "
 ```"),
             #[stable(feature = "no_panic_pow", since = "1.34.0")]
-            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
@@ -1159,7 +1159,7 @@ pub const fn wrapping_shr(self, rhs: u32) -> Self {
 assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, "
 ```"),
             #[stable(feature = "no_panic_pow", since = "1.34.0")]
-            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
@@ -1484,7 +1484,7 @@ pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
 assert_eq!(3u8.overflowing_pow(6), (217, true));", $EndFeature, "
 ```"),
             #[stable(feature = "no_panic_pow", since = "1.34.0")]
-            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
@@ -1532,7 +1532,7 @@ pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
 ", $Feature, "assert_eq!(2", stringify!($SelfT), ".pow(5), 32);", $EndFeature, "
 ```"),
         #[stable(feature = "rust1", since = "1.0.0")]
-        #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
+        #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
         #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
         #[inline]
@@ -1648,7 +1648,7 @@ pub const fn is_power_of_two(self) -> bool {
         // overflow cases it instead ends up returning the maximum value
         // of the type, and can return 0 for 0.
         #[inline]
-        #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
+        #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
         const fn one_less_than_next_power_of_two(self) -> Self {
             if self <= 1 { return 0; }
 
@@ -1677,7 +1677,7 @@ const fn one_less_than_next_power_of_two(self) -> Self {
 assert_eq!(3", stringify!($SelfT), ".next_power_of_two(), 4);", $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
             #[inline]
             #[rustc_inherit_overflow_checks]
             pub const fn next_power_of_two(self) -> Self {
@@ -1703,7 +1703,7 @@ pub const fn next_power_of_two(self) -> Self {
 ```"),
             #[inline]
             #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
             pub const fn checked_next_power_of_two(self) -> Option<Self> {
                 self.one_less_than_next_power_of_two().checked_add(1)
             }
@@ -1728,7 +1728,7 @@ pub const fn checked_next_power_of_two(self) -> Option<Self> {
 ```"),
             #[unstable(feature = "wrapping_next_power_of_two", issue = "32463",
                        reason = "needs decision on wrapping behaviour")]
-            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
             pub const fn wrapping_next_power_of_two(self) -> Self {
                 self.one_less_than_next_power_of_two().wrapping_add(1)
             }
@@ -1805,8 +1805,7 @@ pub const fn wrapping_next_power_of_two(self) -> Self {
             #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             // SAFETY: const sound because integers are plain old datatypes so we can always
             // transmute them to arrays of bytes
-            #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
-            #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
+            #[rustc_allow_const_fn_unstable(const_fn_transmute)]
             #[inline]
             pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
                 // SAFETY: integers are plain old datatypes so we can always transmute them to
@@ -1954,8 +1953,7 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
             #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             // SAFETY: const sound because integers are plain old datatypes so we can always
             // transmute to them
-            #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
-            #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
+            #[rustc_allow_const_fn_unstable(const_fn_transmute)]
             #[inline]
             pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
                 // SAFETY: integers are plain old datatypes so we can always transmute to them
index 3c2ada57612337e0d865168bc7dc8b4d07af634b..a8dea4e9b4ea8f631c39ce79430183c98e6238ea 100644 (file)
@@ -79,7 +79,7 @@ pub trait Index<Idx: ?Sized> {
 /// each can be indexed mutably and immutably.
 ///
 /// ```
-/// use std::ops::{Index,IndexMut};
+/// use std::ops::{Index, IndexMut};
 ///
 /// #[derive(Debug)]
 /// enum Side {
index 09dd19b8f5f9385450fa7dc6ce4e5c85eeacf52f..25651502510e2c12dde7b4749b6752b37b2f47de 100644 (file)
@@ -52,7 +52,7 @@ pub fn panic(expr: &'static str) -> ! {
 
 #[inline]
 #[track_caller]
-#[cfg_attr(not(bootstrap), lang = "panic_str")] // needed for const-evaluated panics
+#[lang = "panic_str"] // needed for const-evaluated panics
 pub fn panic_str(expr: &str) -> ! {
     panic_fmt(format_args!("{}", expr));
 }
index 9de2758767e3ea8406c266f76b833eaf47e18576..27d49529a5ec20f13702df386b892c9d09e9ba06 100644 (file)
 //! provided at this point are very minimal:
 //!
 //! * A [null] pointer is *never* valid, not even for accesses of [size zero][zst].
-//! * All pointers (except for the null pointer) are valid for all operations of
-//!   [size zero][zst].
 //! * For a pointer to be valid, it is necessary, but not always sufficient, that the pointer
 //!   be *dereferenceable*: the memory range of the given size starting at the pointer must all be
 //!   within the bounds of a single allocated object. Note that in Rust,
 //!   every (stack-allocated) variable is considered a separate allocated object.
+//! * Even for operations of [size zero][zst], the pointer must not be pointing to deallocated
+//!   memory, i.e., deallocation makes pointers invalid even for zero-sized operations. However,
+//!   casting any non-zero integer *literal* to a pointer is valid for zero-sized accesses, even if
+//!   some memory happens to exist at that address and gets deallocated. This corresponds to writing
+//!   your own allocator: allocating zero-sized objects is not very hard. The canonical way to
+//!   obtain a pointer that is valid for zero-sized accesses is [`NonNull::dangling`].
 //! * All accesses performed by functions in this module are *non-atomic* in the sense
 //!   of [atomic operations] used to synchronize between threads. This means it is
 //!   undefined behavior to perform two concurrent accesses to the same location from different
index 0c0f1750264eb2dbe21418b3cdadf023077ff6c6..08077c700da69c0991f611e0ec5e7265f9c84fca 100644 (file)
@@ -1,8 +1,6 @@
 // Original implementation taken from rust-memchr.
 // Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
 
-// ignore-tidy-undocumented-unsafe
-
 use crate::cmp;
 use crate::mem;
 
@@ -72,6 +70,8 @@ fn memchr_general_case(x: u8, text: &[u8]) -> Option<usize> {
     // search the body of the text
     let repeated_x = repeat_byte(x);
     while offset <= len - 2 * USIZE_BYTES {
+        // SAFETY: the while's predicate guarantees a distance of at least 2 * usize_bytes
+        // between the offset and the end of the slice.
         unsafe {
             let u = *(ptr.add(offset) as *const usize);
             let v = *(ptr.add(offset + USIZE_BYTES) as *const usize);
@@ -105,6 +105,8 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
     let (min_aligned_offset, max_aligned_offset) = {
         // We call this just to obtain the length of the prefix and suffix.
         // In the middle we always process two chunks at once.
+        // SAFETY: transmuting `[u8]` to `[usize]` is safe except for size differences
+        // which are handled by `align_to`.
         let (prefix, _, suffix) = unsafe { text.align_to::<(Chunk, Chunk)>() };
         (prefix.len(), len - suffix.len())
     };
@@ -121,6 +123,8 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
     let chunk_bytes = mem::size_of::<Chunk>();
 
     while offset > min_aligned_offset {
+        // SAFETY: offset starts at len - suffix.len(), as long as it is greater than
+        // min_aligned_offset (prefix.len()) the remaining distance is at least 2 * chunk_bytes.
         unsafe {
             let u = *(ptr.offset(offset as isize - 2 * chunk_bytes as isize) as *const Chunk);
             let v = *(ptr.offset(offset as isize - chunk_bytes as isize) as *const Chunk);
index 79ae1d5829a24464a580d76d2e53306fef5ff481..44fe2ca88596f8dc63654f09eab4a7ac2cd6aa98 100644 (file)
@@ -88,8 +88,7 @@ impl<T> [T] {
     #[rustc_const_stable(feature = "const_slice_len", since = "1.32.0")]
     #[inline]
     // SAFETY: const sound because we transmute out the length field as a usize (which it must be)
-    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_union))]
-    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_union))]
+    #[rustc_allow_const_fn_unstable(const_fn_union)]
     pub const fn len(&self) -> usize {
         // SAFETY: this is safe because `&[T]` and `FatPtr<T>` have the same layout.
         // Only `std` can make this guarantee.
@@ -605,8 +604,9 @@ pub fn reverse(&mut self) {
                 //     many bytes away from the end of `self`.
                 //   - Any initialized memory is valid `usize`.
                 unsafe {
-                    let pa: *mut T = self.get_unchecked_mut(i);
-                    let pb: *mut T = self.get_unchecked_mut(ln - i - chunk);
+                    let ptr = self.as_mut_ptr();
+                    let pa = ptr.add(i);
+                    let pb = ptr.add(ln - i - chunk);
                     let va = ptr::read_unaligned(pa as *mut usize);
                     let vb = ptr::read_unaligned(pb as *mut usize);
                     ptr::write_unaligned(pa as *mut usize, vb.swap_bytes());
@@ -635,8 +635,9 @@ pub fn reverse(&mut self) {
                 // always respected, ensuring the `pb` pointer can be used
                 // safely.
                 unsafe {
-                    let pa: *mut T = self.get_unchecked_mut(i);
-                    let pb: *mut T = self.get_unchecked_mut(ln - i - chunk);
+                    let ptr = self.as_mut_ptr();
+                    let pa = ptr.add(i);
+                    let pb = ptr.add(ln - i - chunk);
                     let va = ptr::read_unaligned(pa as *mut u32);
                     let vb = ptr::read_unaligned(pb as *mut u32);
                     ptr::write_unaligned(pa as *mut u32, vb.rotate_left(16));
@@ -654,8 +655,9 @@ pub fn reverse(&mut self) {
             // aligned, and can be read from and written to.
             unsafe {
                 // Unsafe swap to avoid the bounds check in safe swap.
-                let pa: *mut T = self.get_unchecked_mut(i);
-                let pb: *mut T = self.get_unchecked_mut(ln - i - 1);
+                let ptr = self.as_mut_ptr();
+                let pa = ptr.add(i);
+                let pb = ptr.add(ln - i - 1);
                 ptr::swap(pa, pb);
             }
             i += 1;
@@ -1958,10 +1960,10 @@ pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize>
     ///          (1, 2), (2, 3), (4, 5), (5, 8), (3, 13),
     ///          (1, 21), (2, 34), (4, 55)];
     ///
-    /// assert_eq!(s.binary_search_by_key(&13, |&(a,b)| b),  Ok(9));
-    /// assert_eq!(s.binary_search_by_key(&4, |&(a,b)| b),   Err(7));
-    /// assert_eq!(s.binary_search_by_key(&100, |&(a,b)| b), Err(13));
-    /// let r = s.binary_search_by_key(&1, |&(a,b)| b);
+    /// assert_eq!(s.binary_search_by_key(&13, |&(a, b)| b),  Ok(9));
+    /// assert_eq!(s.binary_search_by_key(&4, |&(a, b)| b),   Err(7));
+    /// assert_eq!(s.binary_search_by_key(&100, |&(a, b)| b), Err(13));
+    /// let r = s.binary_search_by_key(&1, |&(a, b)| b);
     /// assert!(match r { Ok(1..=4) => true, _ => false, });
     /// ```
     #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")]
@@ -2585,6 +2587,7 @@ pub fn rotate_right(&mut self, k: usize) {
     /// buf.fill(1);
     /// assert_eq!(buf, vec![1; 10]);
     /// ```
+    #[doc(alias = "memset")]
     #[unstable(feature = "slice_fill", issue = "70758")]
     pub fn fill(&mut self, value: T)
     where
@@ -2599,6 +2602,34 @@ pub fn fill(&mut self, value: T)
         }
     }
 
+    /// Fills `self` with elements returned by calling a closure repeatedly.
+    ///
+    /// This method uses a closure to create new values. If you'd rather
+    /// [`Clone`] a given value, use [`fill`]. If you want to use the [`Default`]
+    /// trait to generate values, you can pass [`Default::default`] as the
+    /// argument.
+    ///
+    /// [`fill`]: #method.fill
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_fill_with)]
+    ///
+    /// let mut buf = vec![1; 10];
+    /// buf.fill_with(Default::default);
+    /// assert_eq!(buf, vec![0; 10]);
+    /// ```
+    #[unstable(feature = "slice_fill_with", issue = "79221")]
+    pub fn fill_with<F>(&mut self, mut f: F)
+    where
+        F: FnMut() -> T,
+    {
+        for el in self {
+            *el = f();
+        }
+    }
+
     /// Copies the elements from `src` into `self`.
     ///
     /// The length of `src` must be the same as `self`.
@@ -2724,6 +2755,7 @@ pub fn clone_from_slice(&mut self, src: &[T])
     ///
     /// [`clone_from_slice`]: #method.clone_from_slice
     /// [`split_at_mut`]: #method.split_at_mut
+    #[doc(alias = "memcpy")]
     #[stable(feature = "copy_from_slice", since = "1.9.0")]
     pub fn copy_from_slice(&mut self, src: &[T])
     where
index 952d0598a7c5b961366bb3aceda9a66b1c37edb8..73316433e090fb10f377300a1d3a0d5017b57cfc 100644 (file)
@@ -157,8 +157,7 @@ pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_str_from_utf8_unchecked", issue = "75196")]
-#[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
-#[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
+#[rustc_allow_const_fn_unstable(const_fn_transmute)]
 pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
     // SAFETY: the caller must guarantee that the bytes `v` are valid UTF-8.
     // Also relies on `&str` and `&[u8]` having the same layout.
index 23d63a4787efa595cb76a0218747c93089956fd5..604e317110c3e92ca060881267a998b8e2c54443 100644 (file)
@@ -219,8 +219,7 @@ pub fn is_char_boundary(&self, index: usize) -> bool {
     #[rustc_const_stable(feature = "str_as_bytes", since = "1.32.0")]
     #[inline(always)]
     #[allow(unused_attributes)]
-    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
-    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
+    #[rustc_allow_const_fn_unstable(const_fn_transmute)]
     pub const fn as_bytes(&self) -> &[u8] {
         // SAFETY: const sound because we transmute two types with the same layout
         unsafe { mem::transmute(self) }
index 10cf1e172e6e403b29dc85003119aea9b3c6c6b6..373a8212425acb3fe203b6acf19b54d5553f7622 100644 (file)
@@ -125,7 +125,7 @@ pub(super) fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
         let old_offset = index;
         macro_rules! err {
             ($error_len: expr) => {
-                return Err(Utf8Error { valid_up_to: old_offset, error_len: $error_len });
+                return Err(Utf8Error { valid_up_to: old_offset, error_len: $error_len })
             };
         }
 
index d48c02bf59c6463cffd8e29a68b3322a4c31b393..9d2045990570b5e4a919b27e9435be3aaf5d550e 100644 (file)
 //!
 //! * PowerPC and MIPS platforms with 32-bit pointers do not have `AtomicU64` or
 //!   `AtomicI64` types.
-//! * ARM platforms like `armv5te` that aren't for Linux do not have any atomics
-//!   at all.
-//! * ARM targets with `thumbv6m` do not have atomic operations at all.
+//! * ARM platforms like `armv5te` that aren't for Linux only provide `load`
+//!   and `store` operations, and do not support Compare and Swap (CAS)
+//!   operations, such as `swap`, `fetch_add`, etc. Additionally on Linux,
+//!   these CAS operations are implemented via [operating system support], which
+//!   may come with a performance penalty.
+//! * ARM targets with `thumbv6m` only provide `load` and `store` operations,
+//!   and do not support Compare and Swap (CAS) operations, such as `swap`,
+//!   `fetch_add`, etc.
+//!
+//! [operating system support]: https://www.kernel.org/doc/Documentation/arm/kernel_user_helpers.txt
 //!
 //! Note that future platforms may be added that also do not have support for
 //! some atomic operations. Maximally portable code will want to be careful
index d3c0d9b784139c08974ba0c9e0cce3aa27f7257b..b775e022a54b428290165f5ad292f1eb8e76abca 100644 (file)
@@ -130,8 +130,7 @@ impl RawWakerVTable {
     #[rustc_promotable]
     #[stable(feature = "futures_api", since = "1.36.0")]
     #[rustc_const_stable(feature = "futures_api", since = "1.36.0")]
-    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_fn_ptr_basics))]
-    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_fn_ptr_basics))]
+    #[rustc_allow_const_fn_unstable(const_fn_fn_ptr_basics)]
     pub const fn new(
         clone: unsafe fn(*const ()) -> RawWaker,
         wake: unsafe fn(*const ()),
index 75ca897cadc918c55324277a957e083b1e721889..6b8a989fa426ffe7f77c7815b7aa7a7732c1809c 100644 (file)
@@ -1134,6 +1134,17 @@ fn test_iterator_peekable_next_if_eq() {
     assert_eq!(it.next_if_eq(""), None);
 }
 
+#[test]
+fn test_iterator_peekable_mut() {
+    let mut it = vec![1, 2, 3].into_iter().peekable();
+    if let Some(p) = it.peek_mut() {
+        if *p == 1 {
+            *p = 5;
+        }
+    }
+    assert_eq!(it.collect::<Vec<_>>(), vec![5, 2, 3]);
+}
+
 /// This is an iterator that follows the Iterator contract,
 /// but it is not fused. After having returned None once, it will start
 /// producing elements if .next() is called again.
index 14ef03fd53ebacbceaf5a9f37a21b6e2df0cbbec..1efb3b7411898c2200038b85e5a9b0a967e27018 100644 (file)
@@ -56,6 +56,7 @@
 #![feature(unwrap_infallible)]
 #![feature(option_unwrap_none)]
 #![feature(peekable_next_if)]
+#![feature(peekable_peek_mut)]
 #![feature(partition_point)]
 #![feature(once_cell)]
 #![feature(unsafe_block_in_unsafe_fn)]
index ca449b4350ede910479698cc7257cc64f2489d50..b66c482c5e5e37622cc60a17850395e9409aa647 100644 (file)
@@ -85,7 +85,7 @@ fn test_match_option_string() {
     let five = "Five".to_string();
     match Some(five) {
         Some(s) => assert_eq!(s, "Five"),
-        None => panic!("unexpected None while matching on Some(String { ... })"),
+        None => panic!("{}", "unexpected None while matching on Some(String { ... })"),
     }
 }
 
diff --git a/library/core/tests/num/i128.rs b/library/core/tests/num/i128.rs
new file mode 100644 (file)
index 0000000..72c0b22
--- /dev/null
@@ -0,0 +1 @@
+int_module!(i128, i128);
index fcb0d6031be62f2b9816107307d95e8ed8c94bd1..90c476567844eae873e13efd4dacd8d4091c4bf1 100644 (file)
@@ -131,9 +131,9 @@ fn test_rotate() {
                 assert_eq!(B.rotate_left(0), B);
                 assert_eq!(C.rotate_left(0), C);
                 // Rotating by a multiple of word size should also have no effect
-                assert_eq!(A.rotate_left(64), A);
-                assert_eq!(B.rotate_left(64), B);
-                assert_eq!(C.rotate_left(64), C);
+                assert_eq!(A.rotate_left(128), A);
+                assert_eq!(B.rotate_left(128), B);
+                assert_eq!(C.rotate_left(128), C);
             }
 
             #[test]
index 49e5cc0eaa54484028e973667260d54e01f23d82..012ab4ea5c573a669ad352c2320947a273b2f56d 100644 (file)
@@ -11,6 +11,7 @@
 #[macro_use]
 mod int_macros;
 
+mod i128;
 mod i16;
 mod i32;
 mod i64;
@@ -19,6 +20,7 @@
 #[macro_use]
 mod uint_macros;
 
+mod u128;
 mod u16;
 mod u32;
 mod u64;
diff --git a/library/core/tests/num/u128.rs b/library/core/tests/num/u128.rs
new file mode 100644 (file)
index 0000000..716d183
--- /dev/null
@@ -0,0 +1 @@
+uint_module!(u128, u128);
index 952ec188dc1385f9911e4665c237db2935feb2f4..445f8fb350eebe24db114f45012111427efa29f1 100644 (file)
@@ -96,9 +96,9 @@ fn test_rotate() {
                 assert_eq!(B.rotate_left(0), B);
                 assert_eq!(C.rotate_left(0), C);
                 // Rotating by a multiple of word size should also have no effect
-                assert_eq!(A.rotate_left(64), A);
-                assert_eq!(B.rotate_left(64), B);
-                assert_eq!(C.rotate_left(64), C);
+                assert_eq!(A.rotate_left(128), A);
+                assert_eq!(B.rotate_left(128), B);
+                assert_eq!(C.rotate_left(128), C);
             }
 
             #[test]
index bf977c141cbf861e0f0e64dff04beea4c5aa54c7..1970b17e2672147e474554b80227c3ca805de8d4 100644 (file)
@@ -18,7 +18,7 @@ fn test() {
         struct Pair {
             fst: isize,
             snd: isize,
-        };
+        }
         let mut p = Pair { fst: 10, snd: 20 };
         let pptr: *mut Pair = &mut p;
         let iptr: *mut isize = pptr as *mut isize;
index 9690996e6021e6c9dd9b0182b6c4d7f66f48d8cc..a8ebb4b3219f79601c10a91feb431dd43317eb7d 100644 (file)
@@ -32,7 +32,7 @@
     abort();
 
     cfg_if::cfg_if! {
-        if #[cfg(any(unix, target_os = "cloudabi"))] {
+        if #[cfg(unix)] {
             unsafe fn abort() -> ! {
                 libc::abort();
             }
index 682289384c8e241eff20e35637a1e4a922de4350..0b74a844fec6ee6d828f2bbd89161a1adb6b41ac 100644 (file)
@@ -49,7 +49,6 @@
         mod real_imp;
     } else if #[cfg(any(
         all(target_family = "windows", target_env = "gnu"),
-        target_os = "cloudabi",
         target_os = "psp",
         target_family = "unix",
         all(target_vendor = "fortanix", target_env = "sgx"),
index dfe5df965cfacc043d518f9ddcaa509f7a5cfd5c..c6bec5a6fbdc287df1ddbc489201a7928d0f49f4 100644 (file)
@@ -401,8 +401,7 @@ fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>(
 }
 
 impl Client<fn(crate::TokenStream) -> crate::TokenStream> {
-    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn))]
-    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn))]
+    #[rustc_allow_const_fn_unstable(const_fn)]
     pub const fn expand1(f: fn(crate::TokenStream) -> crate::TokenStream) -> Self {
         extern "C" fn run(
             bridge: Bridge<'_>,
@@ -415,8 +414,7 @@ extern "C" fn run(
 }
 
 impl Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream> {
-    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn))]
-    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn))]
+    #[rustc_allow_const_fn_unstable(const_fn)]
     pub const fn expand2(
         f: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream,
     ) -> Self {
@@ -461,8 +459,7 @@ pub fn name(&self) -> &'static str {
         }
     }
 
-    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn))]
-    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn))]
+    #[rustc_allow_const_fn_unstable(const_fn)]
     pub const fn custom_derive(
         trait_name: &'static str,
         attributes: &'static [&'static str],
@@ -471,8 +468,7 @@ pub const fn custom_derive(
         ProcMacro::CustomDerive { trait_name, attributes, client: Client::expand1(expand) }
     }
 
-    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn))]
-    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn))]
+    #[rustc_allow_const_fn_unstable(const_fn)]
     pub const fn attr(
         name: &'static str,
         expand: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream,
@@ -480,8 +476,7 @@ pub const fn attr(
         ProcMacro::Attr { name, client: Client::expand2(expand) }
     }
 
-    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn))]
-    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn))]
+    #[rustc_allow_const_fn_unstable(const_fn)]
     pub const fn bang(
         name: &'static str,
         expand: fn(crate::TokenStream) -> crate::TokenStream,
index e7c32b10384d4afdcbafad435a220c92f6df50be..e1307856175b1406c06e11f91b7cac39b4ea8711 100644 (file)
@@ -35,8 +35,7 @@ fn deref_mut(&mut self) -> &mut Self::Target {
 pub struct ScopedCell<T: LambdaL>(Cell<<T as ApplyL<'static>>::Out>);
 
 impl<T: LambdaL> ScopedCell<T> {
-    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn))]
-    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn))]
+    #[rustc_allow_const_fn_unstable(const_fn)]
     pub const fn new(value: <T as ApplyL<'static>>::Out) -> Self {
         ScopedCell(Cell::new(value))
     }
index 03733d3b3edac95a7aedf2d4ca6e29251696738c..ca40293ed58214abacbe24e1688a5d0dd53ffa26 100644 (file)
@@ -18,7 +18,7 @@
     test(no_crate_inject, attr(deny(warnings))),
     test(attr(allow(dead_code, deprecated, unused_variables, unused_mut)))
 )]
-#![cfg_attr(not(bootstrap), feature(rustc_allow_const_fn_unstable))]
+#![feature(rustc_allow_const_fn_unstable)]
 #![feature(nll)]
 #![feature(staged_api)]
 #![feature(const_fn)]
@@ -28,7 +28,8 @@
 #![feature(extern_types)]
 #![feature(in_band_lifetimes)]
 #![feature(negative_impls)]
-#![feature(optin_builtin_traits)]
+#![cfg_attr(bootstrap, feature(optin_builtin_traits))]
+#![cfg_attr(not(bootstrap), feature(auto_traits))]
 #![feature(restricted_std)]
 #![feature(rustc_attrs)]
 #![feature(min_specialization)]
@@ -842,6 +843,13 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
+#[stable(feature = "proc_macro_punct_eq", since = "1.49.0")]
+impl PartialEq<char> for Punct {
+    fn eq(&self, rhs: &char) -> bool {
+        self.as_char() == *rhs
+    }
+}
+
 /// An identifier (`ident`).
 #[derive(Clone)]
 #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
index 331b330cf29f06326d9c34b621cceb41c20d4465..d2e6b0bb8093bb5ca329992d88d24d866c0153af 100644 (file)
@@ -1,6 +1,6 @@
 #![feature(proc_macro_span)]
 
-use proc_macro::LineColumn;
+use proc_macro::{LineColumn, Punct};
 
 #[test]
 fn test_line_column_ord() {
@@ -10,3 +10,11 @@ fn test_line_column_ord() {
     assert!(line0_column0 < line0_column1);
     assert!(line0_column1 < line1_column0);
 }
+
+#[test]
+fn test_punct_eq() {
+    // Good enough if it typechecks, since proc_macro::Punct can't exist in a test.
+    fn _check(punct: Punct) {
+        let _ = punct == ':';
+    }
+}
index bd1946133e8afe40708865f1fff3852d5dcfb3a0..b64f13dba4c2ea751b9bd404e827f69cb05469bf 100644 (file)
@@ -9,10 +9,13 @@
 // headers or footers.
 //
 // Note that the actual module entry point is located in the C runtime startup
-// object (usually called `crtX.o), which then invokes initialization callbacks
+// object (usually called `crtX.o`), which then invokes initialization callbacks
 // of other runtime components (registered via yet another special image section).
 
-#![feature(no_core, lang_items, optin_builtin_traits)]
+#![feature(no_core)]
+#![feature(lang_items)]
+#![cfg_attr(bootstrap, feature(optin_builtin_traits))]
+#![cfg_attr(not(bootstrap), feature(auto_traits))]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(non_camel_case_types)]
index 333761cd9770e2dbd2522bad731a7dbf9b0476a4..18ee7c19ba0f9a89ba694c955142b089aa849cbf 100644 (file)
@@ -1,6 +1,9 @@
 // See rsbegin.rs for details.
 
-#![feature(no_core, lang_items, optin_builtin_traits)]
+#![feature(no_core)]
+#![feature(lang_items)]
+#![cfg_attr(bootstrap, feature(optin_builtin_traits))]
+#![cfg_attr(not(bootstrap), feature(auto_traits))]
 #![crate_type = "rlib"]
 #![no_core]
 
index ad9d1238370ec1d93fbe82fb3fab3be6d8c24859..71d00b5c08735b85976958838d3d0f91b626fc8d 100644 (file)
@@ -23,14 +23,14 @@ unwind = { path = "../unwind" }
 hashbrown = { version = "0.9.0", default-features = false, features = ['rustc-dep-of-std'] }
 
 # Dependencies of the `backtrace` crate
-addr2line = { version = "0.13.0", optional = true, default-features = false }
+addr2line = { version = "0.14.0", optional = true, default-features = false }
 rustc-demangle = { version = "0.1.18", features = ['rustc-dep-of-std'] }
 miniz_oxide = { version = "0.4.0", optional = true, default-features = false }
 [dependencies.object]
-version = "0.20"
+version = "0.22"
 optional = true
 default-features = false
-features = ['read_core', 'elf', 'macho', 'pe']
+features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive']
 
 [dev-dependencies]
 rand = "0.7"
index f730569f74b0ee8273a02f0053108a7fd2162f5d..a14ac63c7a8e4ee908cb955e8ab86ba55ef24445 100644 (file)
@@ -18,7 +18,6 @@ fn main() {
         || target.contains("uwp")
         || target.contains("windows")
         || target.contains("fuchsia")
-        || target.contains("cloudabi")
         || (target.contains("sgx") && target.contains("fortanix"))
         || target.contains("hermit")
         || target.contains("l4re")
index 2a54b117ff4f8eab5bd2be2d4ca340d27f795a4f..09a9b184e3a43966554501e34c3ed7b27ff50a15 100644 (file)
@@ -893,14 +893,13 @@ pub fn atanh(self) -> f32 {
     /// # Examples
     ///
     /// ```
-    /// #![feature(clamp)]
     /// assert!((-3.0f32).clamp(-2.0, 1.0) == -2.0);
     /// assert!((0.0f32).clamp(-2.0, 1.0) == 0.0);
     /// assert!((2.0f32).clamp(-2.0, 1.0) == 1.0);
     /// assert!((f32::NAN).clamp(-2.0, 1.0).is_nan());
     /// ```
     #[must_use = "method returns a new number and does not mutate the original value"]
-    #[unstable(feature = "clamp", issue = "44095")]
+    #[stable(feature = "clamp", since = "1.50.0")]
     #[inline]
     pub fn clamp(self, min: f32, max: f32) -> f32 {
         assert!(min <= max);
index 363d1a0047613134669dfb8f3de7745c45d4d43d..64bb7cd9fd16635a09363adaea9545dccb8f9132 100644 (file)
@@ -895,14 +895,13 @@ pub fn atanh(self) -> f64 {
     /// # Examples
     ///
     /// ```
-    /// #![feature(clamp)]
     /// assert!((-3.0f64).clamp(-2.0, 1.0) == -2.0);
     /// assert!((0.0f64).clamp(-2.0, 1.0) == 0.0);
     /// assert!((2.0f64).clamp(-2.0, 1.0) == 1.0);
     /// assert!((f64::NAN).clamp(-2.0, 1.0).is_nan());
     /// ```
     #[must_use = "method returns a new number and does not mutate the original value"]
-    #[unstable(feature = "clamp", issue = "44095")]
+    #[stable(feature = "clamp", since = "1.50.0")]
     #[inline]
     pub fn clamp(self, min: f64, max: f64) -> f64 {
         assert!(min <= max);
index 8c6d6c80402fa58b66543e318d64be7ad09fa87c..60b642a6dba446575cdca5ce4552ba5453499aee 100644 (file)
@@ -1266,7 +1266,7 @@ pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&CStr, FromBytesWithNulError>
     /// behavior when `ptr` is used inside the `unsafe` block:
     ///
     /// ```no_run
-    /// # #![allow(unused_must_use)] #![cfg_attr(not(bootstrap), allow(temporary_cstring_as_ptr))]
+    /// # #![allow(unused_must_use)] #![allow(temporary_cstring_as_ptr)]
     /// use std::ffi::CString;
     ///
     /// let ptr = CString::new("Hello").expect("CString::new failed").as_ptr();
index a4123cc15b8767c5d3d2c27403dd8c2cfd119387..e2d4f2e6a56afd1bd5a876aa99f9549daa6f884d 100644 (file)
@@ -8,7 +8,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 #![deny(unsafe_op_in_unsafe_fn)]
 
-#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
+#[cfg(all(test, not(any(target_os = "emscripten", target_env = "sgx"))))]
 mod tests;
 
 use crate::ffi::OsString;
@@ -1698,12 +1698,14 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> {
 
 /// Creates a new hard link on the filesystem.
 ///
-/// The `dst` path will be a link pointing to the `src` path. Note that systems
-/// often require these two paths to both be located on the same filesystem.
+/// The `link` path will be a link pointing to the `original` path. Note that
+/// systems often require these two paths to both be located on the same
+/// filesystem.
 ///
-/// If `src` names a symbolic link, it is platform-specific whether the symbolic
-/// link is followed. On platforms where it's possible to not follow it, it is
-/// not followed, and the created hard link points to the symbolic link itself.
+/// If `original` names a symbolic link, it is platform-specific whether the
+/// symbolic link is followed. On platforms where it's possible to not follow
+/// it, it is not followed, and the created hard link points to the symbolic
+/// link itself.
 ///
 /// # Platform-specific behavior
 ///
@@ -1718,7 +1720,7 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> {
 /// This function will return an error in the following situations, but is not
 /// limited to just these cases:
 ///
-/// * The `src` path is not a file or doesn't exist.
+/// * The `original` path is not a file or doesn't exist.
 ///
 /// # Examples
 ///
@@ -1731,13 +1733,13 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> {
 /// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
-    fs_imp::link(src.as_ref(), dst.as_ref())
+pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
+    fs_imp::link(original.as_ref(), link.as_ref())
 }
 
 /// Creates a new symbolic link on the filesystem.
 ///
-/// The `dst` path will be a symbolic link pointing to the `src` path.
+/// The `link` path will be a symbolic link pointing to the `original` path.
 /// On Windows, this will be a file symlink, not a directory symlink;
 /// for this reason, the platform-specific [`std::os::unix::fs::symlink`]
 /// and [`std::os::windows::fs::symlink_file`] or [`symlink_dir`] should be
@@ -1763,8 +1765,8 @@ pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<(
     reason = "replaced with std::os::unix::fs::symlink and \
               std::os::windows::fs::{symlink_file, symlink_dir}"
 )]
-pub fn soft_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
-    fs_imp::symlink(src.as_ref(), dst.as_ref())
+pub fn soft_link<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
+    fs_imp::symlink(original.as_ref(), link.as_ref())
 }
 
 /// Reads a symbolic link, returning the file that the link points to.
index 9fd322adcfcbf3bbea25ea993efaa48dfe494cc3..8659f689ad62aa202d3047691d1f19a23d63a17d 100644 (file)
@@ -1750,7 +1750,7 @@ mod super_keyword {}
 ///
 /// # Differences between the 2015 and 2018 editions
 ///
-/// In the 2015 edition parameters pattern where not needed for traits:
+/// In the 2015 edition the parameters pattern was not needed for traits:
 ///
 /// ```rust,edition2015
 /// trait Tr {
index db523f05e01a5559bbc1f6255246d834e083a8da..f33804c988a1a259088ec0d594401f71c1ff7176 100644 (file)
 #![needs_panic_runtime]
 // std may use features in a platform-specific way
 #![allow(unused_features)]
-#![cfg_attr(not(bootstrap), feature(rustc_allow_const_fn_unstable))]
+#![feature(rustc_allow_const_fn_unstable)]
 #![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count))]
 #![cfg_attr(
     all(target_vendor = "fortanix", target_env = "sgx"),
 #![feature(asm)]
 #![feature(associated_type_bounds)]
 #![feature(atomic_mut_ptr)]
-#![feature(bool_to_option)]
 #![feature(box_syntax)]
 #![feature(c_variadic)]
 #![feature(cfg_accessible)]
 #![feature(cfg_target_thread_local)]
 #![feature(char_error_internals)]
 #![feature(char_internals)]
-#![feature(clamp)]
 #![feature(concat_idents)]
 #![feature(const_cstr_unchecked)]
 #![feature(const_fn_floating_point_arithmetic)]
 #![feature(nll)]
 #![feature(nonnull_slice_from_raw_parts)]
 #![feature(once_cell)]
-#![feature(optin_builtin_traits)]
+#![cfg_attr(bootstrap, feature(optin_builtin_traits))]
+#![cfg_attr(not(bootstrap), feature(auto_traits))]
 #![feature(or_patterns)]
 #![feature(panic_info_message)]
 #![feature(panic_internals)]
 #![feature(raw)]
 #![feature(raw_ref_macros)]
 #![feature(ready_macro)]
-#![feature(refcell_take)]
 #![feature(rustc_attrs)]
 #![feature(rustc_private)]
 #![feature(shrink_to)]
 #![feature(unsafe_block_in_unsafe_fn)]
 #![feature(unsafe_cell_get_mut)]
 #![feature(unsafe_cell_raw_get)]
-#![cfg_attr(bootstrap, feature(untagged_unions))]
 #![feature(unwind_attributes)]
 #![feature(vec_into_raw_parts)]
 #![feature(wake_trait)]
index 57649d6f8f25243312f1f3982c1650e01e9804e3..de072e83dfc419c1f181b44947ff41b4d83461ee 100644 (file)
@@ -8,6 +8,7 @@
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow_internal_unstable(libstd_sys_internals)]
+#[cfg_attr(not(any(bootstrap, test)), rustc_diagnostic_item = "std_panic_macro")]
 macro_rules! panic {
     () => ({ $crate::panic!("explicit panic") });
     ($msg:expr $(,)?) => ({ $crate::rt::begin_panic($msg) });
index bb3ece4c2739f239883ffe5402fa81d66baf3fe2..87bbd33bc0145a3c4846f488ec1a339058c5ad7a 100644 (file)
@@ -263,8 +263,9 @@ pub const fn is_documentation(&self) -> bool {
     /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true);
     /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), false);
     /// ```
+    #[rustc_const_stable(feature = "const_ip", since = "1.50.0")]
     #[stable(feature = "ipaddr_checker", since = "1.16.0")]
-    pub fn is_ipv4(&self) -> bool {
+    pub const fn is_ipv4(&self) -> bool {
         matches!(self, IpAddr::V4(_))
     }
 
@@ -281,8 +282,9 @@ pub fn is_ipv4(&self) -> bool {
     /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false);
     /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), true);
     /// ```
+    #[rustc_const_stable(feature = "const_ip", since = "1.50.0")]
     #[stable(feature = "ipaddr_checker", since = "1.16.0")]
-    pub fn is_ipv6(&self) -> bool {
+    pub const fn is_ipv6(&self) -> bool {
         matches!(self, IpAddr::V6(_))
     }
 }
@@ -1043,8 +1045,7 @@ impl Ipv6Addr {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
-    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
-    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
+    #[rustc_allow_const_fn_unstable(const_fn_transmute)]
     pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
         let addr16 = [
             a.to_be(),
index 58c6343ea34ae9f89ffdaa2b1b15373ee7594d0f..325acf0b9793193a0bd8f67b28a9157af12f6598 100644 (file)
@@ -1,6 +1,6 @@
 #![deny(unsafe_op_in_unsafe_fn)]
 
-#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests;
 
 use crate::io::prelude::*;
index 17e3e4497c4a811f59d19de582845ffd4b95c85e..2377a76a33de9799d7e2a1cd8d032246fddd186b 100644 (file)
@@ -1,4 +1,4 @@
-#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
+#[cfg(all(test, not(any(target_os = "emscripten", target_env = "sgx"))))]
 mod tests;
 
 use crate::fmt;
index 2f50b73f4907f9186ae2240cc35d99941a9ef6e9..df0df3f23f75603baf7d4618dff78cc1972dde75 100644 (file)
@@ -75,8 +75,8 @@ fn test_checked_mul() {
 
 macro_rules! test_is_power_of_two {
     ($test_name:ident, $T:ident) => {
+        #[test]
         fn $test_name() {
-            #![test]
             assert_eq!((0 as $T).is_power_of_two(), false);
             assert_eq!((1 as $T).is_power_of_two(), true);
             assert_eq!((2 as $T).is_power_of_two(), true);
@@ -96,8 +96,8 @@ fn $test_name() {
 
 macro_rules! test_next_power_of_two {
     ($test_name:ident, $T:ident) => {
+        #[test]
         fn $test_name() {
-            #![test]
             assert_eq!((0 as $T).next_power_of_two(), 1);
             let mut next_power = 1;
             for i in 1 as $T..40 {
@@ -118,8 +118,8 @@ fn $test_name() {
 
 macro_rules! test_checked_next_power_of_two {
     ($test_name:ident, $T:ident) => {
+        #[test]
         fn $test_name() {
-            #![test]
             assert_eq!((0 as $T).checked_next_power_of_two(), Some(1));
             let smax = $T::MAX >> 1;
             assert_eq!(smax.checked_next_power_of_two(), Some(smax + 1));
index 2c7ed4614bce9e4701c3687481852d265f440eae..fb78e62834a072f9dd56b38ea4f6bb8bdd0126ee 100644 (file)
@@ -97,7 +97,7 @@
 #![stable(feature = "process", since = "1.0.0")]
 #![deny(unsafe_op_in_unsafe_fn)]
 
-#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
+#[cfg(all(test, not(any(target_os = "emscripten", target_env = "sgx"))))]
 mod tests;
 
 use crate::io::prelude::*;
@@ -1779,6 +1779,7 @@ pub fn exit(code: i32) -> ! {
 ///
 /// [panic hook]: crate::panic::set_hook
 #[stable(feature = "process_abort", since = "1.17.0")]
+#[cold]
 pub fn abort() -> ! {
     crate::sys::abort_internal();
 }
diff --git a/library/std/src/sys/cloudabi/abi/bitflags.rs b/library/std/src/sys/cloudabi/abi/bitflags.rs
deleted file mode 100644 (file)
index 2383277..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 2018 Nuxi (https://nuxi.nl/) and contributors.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-// 1. Redistributions of source code must retain the above copyright
-//    notice, this list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright
-//    notice, this list of conditions and the following disclaimer in the
-//    documentation and/or other materials provided with the distribution.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-// SUCH DAMAGE.
-
-#[cfg(feature = "bitflags")]
-use bitflags::bitflags;
-
-// Minimal implementation of bitflags! in case we can't depend on the bitflags
-// crate. Only implements `bits()` and a `from_bits_truncate()` that doesn't
-// actually truncate.
-#[cfg(not(feature = "bitflags"))]
-macro_rules! bitflags {
-  (
-    $(#[$attr:meta])*
-    pub struct $name:ident: $type:ty {
-      $($(#[$const_attr:meta])* const $const:ident = $val:expr;)*
-    }
-  ) => {
-    $(#[$attr])*
-    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-    pub struct $name { bits: $type }
-    impl $name {
-      $($(#[$const_attr])* pub const $const: $name = $name{ bits: $val };)*
-      pub fn bits(&self) -> $type { self.bits }
-      pub fn from_bits_truncate(bits: $type) -> Self { $name{ bits } }
-    }
-  }
-}
diff --git a/library/std/src/sys/cloudabi/abi/cloudabi.rs b/library/std/src/sys/cloudabi/abi/cloudabi.rs
deleted file mode 100644 (file)
index d67f0f8..0000000
+++ /dev/null
@@ -1,2954 +0,0 @@
-// Copyright (c) 2016-2017 Nuxi <https://nuxi.nl/> and contributors.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-// 1. Redistributions of source code must retain the above copyright
-//    notice, this list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright
-//    notice, this list of conditions and the following disclaimer in the
-//    documentation and/or other materials provided with the distribution.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-// SUCH DAMAGE.
-//
-// This file is automatically generated. Do not edit.
-//
-// Source: https://github.com/NuxiNL/cloudabi
-
-// Appease Rust's tidy.
-// ignore-tidy-linelength
-
-//! **PLEASE NOTE: This entire crate including this
-//! documentation is automatically generated from
-//! [`cloudabi.txt`](https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt)**
-//!
-//! # Nuxi CloudABI
-//!
-//! CloudABI is what you get if you take POSIX, add capability-based
-//! security, and remove everything that's incompatible with that. The
-//! result is a minimal ABI consisting of only 49 syscalls.
-//!
-//! CloudABI doesn't have its own kernel, but instead is implemented in existing
-//! kernels: FreeBSD has CloudABI support for x86-64 and arm64, and [a patch-set
-//! for NetBSD](https://github.com/NuxiNL/netbsd) and [a patch-set for
-//! Linux](https://github.com/NuxiNL/linux) are available as well. This means that
-//! CloudABI binaries can be executed on different operating systems, without any
-//! modification.
-//!
-//! ## Capability-Based Security
-//!
-//! Capability-based security means that processes can only perform
-//! actions that have no global impact. Processes cannot open files by
-//! their absolute path, cannot open network connections, and cannot
-//! observe global system state such as the process table.
-//!
-//! The capabilities of a process are fully determined by its set of open
-//! file descriptors (fds). For example, files can only be opened if the
-//! process already has a file descriptor to a directory the file is in.
-//!
-//! Unlike in POSIX, where processes are normally started with file
-//! descriptors 0, 1, and 2 reserved for standard input, output, and
-//! error, CloudABI does not reserve any file descriptor numbers for
-//! specific purposes.
-//!
-//! In CloudABI, a process depends on its parent process to launch it with
-//! the right set of resources, since the process will not be able to open
-//! any new resources. For example, a simple static web server would need
-//! to be started with a file descriptor to a [TCP
-//! listener](https://github.com/NuxiNL/flower), and a file descriptor to
-//! the directory for which to serve files. The web server will then be
-//! unable to do anything other than reading files in that directory, and
-//! process incoming network connections.
-//!
-//! So, unknown CloudABI binaries can safely be executed without the need
-//! for containers, virtual machines, or other sandboxing technologies.
-//!
-//! Watch [Ed Schouten's Talk at
-//! 32C3](https://www.youtube.com/watch?v=3N29vrPoDv8) for more
-//! information about what capability-based security for UNIX means.
-//!
-//! ## Cloudlibc
-//!
-//! [Cloudlibc](https://github.com/NuxiNL/cloudlibc) is an implementation
-//! of the C standard library, without all CloudABI-incompatible
-//! functions. For example, Cloudlibc does not have `printf`, but does
-//! have `fprintf`. It does not have `open`, but does have `openat`.
-//!
-//! ## CloudABI-Ports
-//!
-//! [CloudABI-Ports](https://github.com/NuxiNL/cloudabi-ports) is a
-//! collection of ports of commonly used libraries and applications to
-//! CloudABI. It contains software such as `zlib`, `libpng`, `boost`,
-//! `memcached`, and much more. The software is patched to not depend on
-//! any global state, such as files in `/etc` or `/dev`, using `open()`,
-//! etc.
-//!
-//! ## Using CloudABI
-//!
-//! Instructions for using CloudABI (including kernel modules/patches,
-//! toolchain, and ports) are available for several operating systems:
-//!
-//! - [Arch Linux](https://nuxi.nl/cloudabi/archlinux/)
-//! - [Debian, Ubuntu, and other Debian derivatives](https://nuxi.nl/cloudabi/debian/)
-//! - [FreeBSD, PC-BSD and DragonFly BSD](https://nuxi.nl/cloudabi/freebsd/)
-//! - [Mac OS X](https://nuxi.nl/cloudabi/mac/)
-//! - [NetBSD](https://nuxi.nl/cloudabi/netbsd/)
-//!
-//! ## Specification of the ABI
-//!
-//! The entire ABI is specified in a file called
-//! [`cloudabi.txt`](https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt),
-//! from which all
-//! [headers](https://github.com/NuxiNL/cloudabi/tree/master/headers)
-//! and documentation (including the one you're reading now) is generated.
-
-#![no_std]
-#![allow(non_camel_case_types)]
-#![allow(deprecated)] // FIXME: using `mem::uninitialized()`
-
-include!("bitflags.rs");
-
-/// File or memory access pattern advisory information.
-#[repr(u8)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-#[non_exhaustive]
-pub enum advice {
-    /// The application expects that it will not access the
-    /// specified data in the near future.
-    DONTNEED = 1,
-    /// The application expects to access the specified data
-    /// once and then not reuse it thereafter.
-    NOREUSE = 2,
-    /// The application has no advice to give on its behavior
-    /// with respect to the specified data.
-    NORMAL = 3,
-    /// The application expects to access the specified data
-    /// in a random order.
-    RANDOM = 4,
-    /// The application expects to access the specified data
-    /// sequentially from lower offsets to higher offsets.
-    SEQUENTIAL = 5,
-    /// The application expects to access the specified data
-    /// in the near future.
-    WILLNEED = 6,
-}
-
-/// Enumeration describing the kind of value stored in [`auxv`].
-#[repr(u32)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-#[non_exhaustive]
-pub enum auxtype {
-    /// Base address of the binary argument data provided to
-    /// [`proc_exec()`](fn.proc_exec.html).
-    ARGDATA = 256,
-    /// Length of the binary argument data provided to
-    /// [`proc_exec()`](fn.proc_exec.html).
-    ARGDATALEN = 257,
-    /// Base address at which the executable is placed in
-    /// memory.
-    BASE = 7,
-    /// Base address of a buffer of random data that may be
-    /// used for non-cryptographic purposes, for example as a
-    /// canary for stack smashing protection.
-    CANARY = 258,
-    /// Length of a buffer of random data that may be used
-    /// for non-cryptographic purposes, for example as a
-    /// canary for stack smashing protection.
-    CANARYLEN = 259,
-    /// Number of CPUs that the system this process is running
-    /// on has.
-    NCPUS = 260,
-    /// Terminator of the auxiliary vector.
-    NULL = 0,
-    /// Smallest memory object size for which individual
-    /// memory protection controls can be configured.
-    PAGESZ = 6,
-    /// Address of the first ELF program header of the
-    /// executable.
-    PHDR = 3,
-    /// Number of ELF program headers of the executable.
-    PHNUM = 4,
-    /// Identifier of the process.
-    ///
-    /// This environment does not provide any simple numerical
-    /// process identifiers, for the reason that these are not
-    /// useful in distributed contexts. Instead, processes are
-    /// identified by a UUID.
-    ///
-    /// This record should point to sixteen bytes of binary
-    /// data, containing a version 4 UUID (fully random).
-    PID = 263,
-    /// Address of the ELF header of the vDSO.
-    ///
-    /// The vDSO is a shared library that is mapped in the
-    /// address space of the process. It provides entry points
-    /// for every system call supported by the environment,
-    /// all having a corresponding symbol that is prefixed
-    /// with `cloudabi_sys_`. System calls should be invoked
-    /// through these entry points.
-    ///
-    /// The first advantage of letting processes call into a
-    /// vDSO to perform system calls instead of raising
-    /// hardware traps is that it allows for easy emulation of
-    /// executables on top of existing operating systems. The
-    /// second advantage is that in cases where an operating
-    /// system provides native support for CloudABI executables,
-    /// it may still implement partial userspace
-    /// implementations of these system calls to improve
-    /// performance (e.g., [`clock_time_get()`](fn.clock_time_get.html)). It also provides
-    /// a more dynamic way of adding, removing or replacing
-    /// system calls.
-    SYSINFO_EHDR = 262,
-    /// Thread ID of the initial thread of the process.
-    TID = 261,
-}
-
-/// Identifiers for clocks.
-#[repr(u32)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-#[non_exhaustive]
-pub enum clockid {
-    /// The system-wide monotonic clock, which is defined as a
-    /// clock measuring real time, whose value cannot be
-    /// adjusted and which cannot have negative clock jumps.
-    ///
-    /// The epoch of this clock is undefined. The absolute
-    /// time value of this clock therefore has no meaning.
-    MONOTONIC = 1,
-    /// The CPU-time clock associated with the current
-    /// process.
-    PROCESS_CPUTIME_ID = 2,
-    /// The system-wide clock measuring real time. Time value
-    /// zero corresponds with 1970-01-01T00:00:00Z.
-    REALTIME = 3,
-    /// The CPU-time clock associated with the current thread.
-    THREAD_CPUTIME_ID = 4,
-}
-
-/// A userspace condition variable.
-#[repr(C)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-pub struct condvar(pub u32);
-/// The condition variable is in its initial state. There
-/// are no threads waiting to be woken up. If the
-/// condition variable has any other value, the kernel
-/// must be called to wake up any sleeping threads.
-pub const CONDVAR_HAS_NO_WAITERS: condvar = condvar(0);
-
-/// Identifier for a device containing a file system. Can be used
-/// in combination with [`inode`] to uniquely identify a file on the
-/// local system.
-#[repr(C)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-pub struct device(pub u64);
-
-/// A reference to the offset of a directory entry.
-#[repr(C)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-pub struct dircookie(pub u64);
-/// Permanent reference to the first directory entry
-/// within a directory.
-pub const DIRCOOKIE_START: dircookie = dircookie(0);
-
-/// Error codes returned by system calls.
-///
-/// Not all of these error codes are returned by the system calls
-/// provided by this environment, but are either used in userspace
-/// exclusively or merely provided for alignment with POSIX.
-#[repr(u16)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-#[non_exhaustive]
-pub enum errno {
-    /// No error occurred. System call completed successfully.
-    SUCCESS = 0,
-    /// Argument list too long.
-    TOOBIG = 1,
-    /// Permission denied.
-    ACCES = 2,
-    /// Address in use.
-    ADDRINUSE = 3,
-    /// Address not available.
-    ADDRNOTAVAIL = 4,
-    /// Address family not supported.
-    AFNOSUPPORT = 5,
-    /// Resource unavailable, or operation would block.
-    AGAIN = 6,
-    /// Connection already in progress.
-    ALREADY = 7,
-    /// Bad file descriptor.
-    BADF = 8,
-    /// Bad message.
-    BADMSG = 9,
-    /// Device or resource busy.
-    BUSY = 10,
-    /// Operation canceled.
-    CANCELED = 11,
-    /// No child processes.
-    CHILD = 12,
-    /// Connection aborted.
-    CONNABORTED = 13,
-    /// Connection refused.
-    CONNREFUSED = 14,
-    /// Connection reset.
-    CONNRESET = 15,
-    /// Resource deadlock would occur.
-    DEADLK = 16,
-    /// Destination address required.
-    DESTADDRREQ = 17,
-    /// Mathematics argument out of domain of function.
-    DOM = 18,
-    /// Reserved.
-    DQUOT = 19,
-    /// File exists.
-    EXIST = 20,
-    /// Bad address.
-    FAULT = 21,
-    /// File too large.
-    FBIG = 22,
-    /// Host is unreachable.
-    HOSTUNREACH = 23,
-    /// Identifier removed.
-    IDRM = 24,
-    /// Illegal byte sequence.
-    ILSEQ = 25,
-    /// Operation in progress.
-    INPROGRESS = 26,
-    /// Interrupted function.
-    INTR = 27,
-    /// Invalid argument.
-    INVAL = 28,
-    /// I/O error.
-    IO = 29,
-    /// Socket is connected.
-    ISCONN = 30,
-    /// Is a directory.
-    ISDIR = 31,
-    /// Too many levels of symbolic links.
-    LOOP = 32,
-    /// File descriptor value too large.
-    MFILE = 33,
-    /// Too many links.
-    MLINK = 34,
-    /// Message too large.
-    MSGSIZE = 35,
-    /// Reserved.
-    MULTIHOP = 36,
-    /// Filename too long.
-    NAMETOOLONG = 37,
-    /// Network is down.
-    NETDOWN = 38,
-    /// Connection aborted by network.
-    NETRESET = 39,
-    /// Network unreachable.
-    NETUNREACH = 40,
-    /// Too many files open in system.
-    NFILE = 41,
-    /// No buffer space available.
-    NOBUFS = 42,
-    /// No such device.
-    NODEV = 43,
-    /// No such file or directory.
-    NOENT = 44,
-    /// Executable file format error.
-    NOEXEC = 45,
-    /// No locks available.
-    NOLCK = 46,
-    /// Reserved.
-    NOLINK = 47,
-    /// Not enough space.
-    NOMEM = 48,
-    /// No message of the desired type.
-    NOMSG = 49,
-    /// Protocol not available.
-    NOPROTOOPT = 50,
-    /// No space left on device.
-    NOSPC = 51,
-    /// Function not supported.
-    NOSYS = 52,
-    /// The socket is not connected.
-    NOTCONN = 53,
-    /// Not a directory or a symbolic link to a directory.
-    NOTDIR = 54,
-    /// Directory not empty.
-    NOTEMPTY = 55,
-    /// State not recoverable.
-    NOTRECOVERABLE = 56,
-    /// Not a socket.
-    NOTSOCK = 57,
-    /// Not supported, or operation not supported on socket.
-    NOTSUP = 58,
-    /// Inappropriate I/O control operation.
-    NOTTY = 59,
-    /// No such device or address.
-    NXIO = 60,
-    /// Value too large to be stored in data type.
-    OVERFLOW = 61,
-    /// Previous owner died.
-    OWNERDEAD = 62,
-    /// Operation not permitted.
-    PERM = 63,
-    /// Broken pipe.
-    PIPE = 64,
-    /// Protocol error.
-    PROTO = 65,
-    /// Protocol not supported.
-    PROTONOSUPPORT = 66,
-    /// Protocol wrong type for socket.
-    PROTOTYPE = 67,
-    /// Result too large.
-    RANGE = 68,
-    /// Read-only file system.
-    ROFS = 69,
-    /// Invalid seek.
-    SPIPE = 70,
-    /// No such process.
-    SRCH = 71,
-    /// Reserved.
-    STALE = 72,
-    /// Connection timed out.
-    TIMEDOUT = 73,
-    /// Text file busy.
-    TXTBSY = 74,
-    /// Cross-device link.
-    XDEV = 75,
-    /// Extension: Capabilities insufficient.
-    NOTCAPABLE = 76,
-}
-
-bitflags! {
-  /// The state of the file descriptor subscribed to with
-  /// [`FD_READ`](enum.eventtype.html#variant.FD_READ) or [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE).
-  #[repr(C)]
-  pub struct eventrwflags: u16 {
-    /// The peer of this socket has closed or disconnected.
-    const HANGUP = 0x0001;
-  }
-}
-
-/// Type of a subscription to an event or its occurrence.
-#[repr(u8)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-#[non_exhaustive]
-pub enum eventtype {
-    /// The time value of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id)
-    /// has reached timestamp [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout).
-    CLOCK = 1,
-    /// Condition variable [`subscription.union.condvar.condvar`](struct.subscription_condvar.html#structfield.condvar) has
-    /// been woken up and [`subscription.union.condvar.lock`](struct.subscription_condvar.html#structfield.lock) has been
-    /// acquired for writing.
-    CONDVAR = 2,
-    /// File descriptor [`subscription.union.fd_readwrite.fd`](struct.subscription_fd_readwrite.html#structfield.fd) has
-    /// data available for reading. This event always triggers
-    /// for regular files.
-    FD_READ = 3,
-    /// File descriptor [`subscription.union.fd_readwrite.fd`](struct.subscription_fd_readwrite.html#structfield.fd) has
-    /// capacity available for writing. This event always
-    /// triggers for regular files.
-    FD_WRITE = 4,
-    /// Lock [`subscription.union.lock.lock`](struct.subscription_lock.html#structfield.lock) has been acquired for
-    /// reading.
-    LOCK_RDLOCK = 5,
-    /// Lock [`subscription.union.lock.lock`](struct.subscription_lock.html#structfield.lock) has been acquired for
-    /// writing.
-    LOCK_WRLOCK = 6,
-    /// The process associated with process descriptor
-    /// [`subscription.union.proc_terminate.fd`](struct.subscription_proc_terminate.html#structfield.fd) has terminated.
-    PROC_TERMINATE = 7,
-}
-
-/// Exit code generated by a process when exiting.
-pub type exitcode = u32;
-
-/// A file descriptor number.
-///
-/// Unlike on POSIX-compliant systems, none of the file descriptor
-/// numbers are reserved for a purpose (e.g., stdin, stdout,
-/// stderr). Operating systems are not required to allocate new
-/// file descriptors in ascending order.
-#[repr(C)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-pub struct fd(pub u32);
-/// Returned to the child process by [`proc_fork()`](fn.proc_fork.html).
-pub const PROCESS_CHILD: fd = fd(0xffffffff);
-/// Passed to [`mem_map()`](fn.mem_map.html) when creating a mapping to
-/// anonymous memory.
-pub const MAP_ANON_FD: fd = fd(0xffffffff);
-
-bitflags! {
-  /// File descriptor flags.
-  #[repr(C)]
-  pub struct fdflags: u16 {
-    /// Append mode: Data written to the file is always
-    /// appended to the file's end.
-    const APPEND   = 0x0001;
-    /// Write according to synchronized I/O data integrity
-    /// completion. Only the data stored in the file is
-    /// synchronized.
-    const DSYNC    = 0x0002;
-    /// Non-blocking mode.
-    const NONBLOCK = 0x0004;
-    /// Synchronized read I/O operations.
-    const RSYNC    = 0x0008;
-    /// Write according to synchronized I/O file integrity
-    /// completion. In addition to synchronizing the data
-    /// stored in the file, the system may also synchronously
-    /// update the file's metadata.
-    const SYNC     = 0x0010;
-  }
-}
-
-bitflags! {
-  /// Which file descriptor attributes to adjust.
-  #[repr(C)]
-  pub struct fdsflags: u16 {
-    /// Adjust the file descriptor flags stored in
-    /// [`fdstat.fs_flags`](struct.fdstat.html#structfield.fs_flags).
-    const FLAGS  = 0x0001;
-    /// Restrict the rights of the file descriptor to the
-    /// rights stored in [`fdstat.fs_rights_base`](struct.fdstat.html#structfield.fs_rights_base) and
-    /// [`fdstat.fs_rights_inheriting`](struct.fdstat.html#structfield.fs_rights_inheriting).
-    const RIGHTS = 0x0002;
-  }
-}
-
-/// Relative offset within a file.
-pub type filedelta = i64;
-
-/// Non-negative file size or length of a region within a file.
-pub type filesize = u64;
-
-/// The type of a file descriptor or file.
-#[repr(u8)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-#[non_exhaustive]
-pub enum filetype {
-    /// The type of the file descriptor or file is unknown or
-    /// is different from any of the other types specified.
-    UNKNOWN = 0,
-    /// The file descriptor or file refers to a block device
-    /// inode.
-    BLOCK_DEVICE = 16,
-    /// The file descriptor or file refers to a character
-    /// device inode.
-    CHARACTER_DEVICE = 17,
-    /// The file descriptor or file refers to a directory
-    /// inode.
-    DIRECTORY = 32,
-    /// The file descriptor refers to a process handle.
-    PROCESS = 80,
-    /// The file descriptor or file refers to a regular file
-    /// inode.
-    REGULAR_FILE = 96,
-    /// The file descriptor refers to a shared memory object.
-    SHARED_MEMORY = 112,
-    /// The file descriptor or file refers to a datagram
-    /// socket.
-    SOCKET_DGRAM = 128,
-    /// The file descriptor or file refers to a byte-stream
-    /// socket.
-    SOCKET_STREAM = 130,
-    /// The file refers to a symbolic link inode.
-    SYMBOLIC_LINK = 144,
-}
-
-bitflags! {
-  /// Which file attributes to adjust.
-  #[repr(C)]
-  pub struct fsflags: u16 {
-    /// Adjust the last data access timestamp to the value
-    /// stored in [`filestat.st_atim`](struct.filestat.html#structfield.st_atim).
-    const ATIM     = 0x0001;
-    /// Adjust the last data access timestamp to the time
-    /// of clock [`REALTIME`](enum.clockid.html#variant.REALTIME).
-    const ATIM_NOW = 0x0002;
-    /// Adjust the last data modification timestamp to the
-    /// value stored in [`filestat.st_mtim`](struct.filestat.html#structfield.st_mtim).
-    const MTIM     = 0x0004;
-    /// Adjust the last data modification timestamp to the
-    /// time of clock [`REALTIME`](enum.clockid.html#variant.REALTIME).
-    const MTIM_NOW = 0x0008;
-    /// Truncate or extend the file to the size stored in
-    /// [`filestat.st_size`](struct.filestat.html#structfield.st_size).
-    const SIZE     = 0x0010;
-  }
-}
-
-/// File serial number that is unique within its file system.
-#[repr(C)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-pub struct inode(pub u64);
-
-/// Number of hard links to an inode.
-pub type linkcount = u32;
-
-/// A userspace read-recursive readers-writer lock, similar to a
-/// Linux futex or a FreeBSD umtx.
-#[repr(C)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-pub struct lock(pub u32);
-/// Value indicating that the lock is in its initial
-/// unlocked state.
-pub const LOCK_UNLOCKED: lock = lock(0x00000000);
-/// Bitmask indicating that the lock is write-locked. If
-/// set, the lower 30 bits of the lock contain the
-/// identifier of the thread that owns the write lock.
-/// Otherwise, the lower 30 bits of the lock contain the
-/// number of acquired read locks.
-pub const LOCK_WRLOCKED: lock = lock(0x40000000);
-/// Bitmask indicating that the lock is either read locked
-/// or write locked, and that one or more threads have
-/// their execution suspended, waiting to acquire the
-/// lock. The last owner of the lock must call the
-/// kernel to unlock.
-///
-/// When the lock is acquired for reading and this bit is
-/// set, it means that one or more threads are attempting
-/// to acquire this lock for writing. In that case, other
-/// threads should only acquire additional read locks if
-/// suspending execution would cause a deadlock. It is
-/// preferred to suspend execution, as this prevents
-/// starvation of writers.
-pub const LOCK_KERNEL_MANAGED: lock = lock(0x80000000);
-/// Value indicating that the lock is in an incorrect
-/// state. A lock cannot be in its initial unlocked state,
-/// while also managed by the kernel.
-pub const LOCK_BOGUS: lock = lock(0x80000000);
-
-bitflags! {
-  /// Flags determining the method of how paths are resolved.
-  #[repr(C)]
-  pub struct lookupflags: u32 {
-    /// As long as the resolved path corresponds to a symbolic
-    /// link, it is expanded.
-    const SYMLINK_FOLLOW = 0x00000001;
-  }
-}
-
-bitflags! {
-  /// Memory mapping flags.
-  #[repr(C)]
-  pub struct mflags: u8 {
-    /// Instead of mapping the contents of the file provided,
-    /// create a mapping to anonymous memory. The file
-    /// descriptor argument must be set to [`MAP_ANON_FD`](constant.MAP_ANON_FD.html),
-    /// and the offset must be set to zero.
-    const ANON    = 0x01;
-    /// Require that the mapping is performed at the base
-    /// address provided.
-    const FIXED   = 0x02;
-    /// Changes are private.
-    const PRIVATE = 0x04;
-    /// Changes are shared.
-    const SHARED  = 0x08;
-  }
-}
-
-bitflags! {
-  /// Memory page protection options.
-  ///
-  /// This implementation enforces the `W^X` property: Pages cannot be
-  /// mapped for execution while also mapped for writing.
-  #[repr(C)]
-  pub struct mprot: u8 {
-    /// Page can be executed.
-    const EXEC  = 0x01;
-    /// Page can be written.
-    const WRITE = 0x02;
-    /// Page can be read.
-    const READ  = 0x04;
-  }
-}
-
-bitflags! {
-  /// Methods of synchronizing memory with physical storage.
-  #[repr(C)]
-  pub struct msflags: u8 {
-    /// Performs asynchronous writes.
-    const ASYNC      = 0x01;
-    /// Invalidates cached data.
-    const INVALIDATE = 0x02;
-    /// Performs synchronous writes.
-    const SYNC       = 0x04;
-  }
-}
-
-/// Specifies the number of threads sleeping on a condition
-/// variable that should be woken up.
-pub type nthreads = u32;
-
-bitflags! {
-  /// Open flags used by [`file_open()`](fn.file_open.html).
-  #[repr(C)]
-  pub struct oflags: u16 {
-    /// Create file if it does not exist.
-    const CREAT     = 0x0001;
-    /// Fail if not a directory.
-    const DIRECTORY = 0x0002;
-    /// Fail if file already exists.
-    const EXCL      = 0x0004;
-    /// Truncate file to size 0.
-    const TRUNC     = 0x0008;
-  }
-}
-
-bitflags! {
-  /// Flags provided to [`sock_recv()`](fn.sock_recv.html).
-  #[repr(C)]
-  pub struct riflags: u16 {
-    /// Returns the message without removing it from the
-    /// socket's receive queue.
-    const PEEK    = 0x0004;
-    /// On byte-stream sockets, block until the full amount
-    /// of data can be returned.
-    const WAITALL = 0x0010;
-  }
-}
-
-bitflags! {
-  /// File descriptor rights, determining which actions may be
-  /// performed.
-  #[repr(C)]
-  pub struct rights: u64 {
-    /// The right to invoke [`fd_datasync()`](fn.fd_datasync.html).
-    ///
-    /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, includes the right to
-    /// invoke [`file_open()`](fn.file_open.html) with [`DSYNC`](struct.fdflags.html#associatedconstant.DSYNC).
-    const FD_DATASYNC           = 0x0000000000000001;
-    /// The right to invoke [`fd_read()`](fn.fd_read.html) and [`sock_recv()`](fn.sock_recv.html).
-    ///
-    /// If [`MEM_MAP`](struct.rights.html#associatedconstant.MEM_MAP) is set, includes the right to
-    /// invoke [`mem_map()`](fn.mem_map.html) with memory protection option
-    /// [`READ`](struct.mprot.html#associatedconstant.READ).
-    ///
-    /// If [`FD_SEEK`](struct.rights.html#associatedconstant.FD_SEEK) is set, includes the right to invoke
-    /// [`fd_pread()`](fn.fd_pread.html).
-    const FD_READ               = 0x0000000000000002;
-    /// The right to invoke [`fd_seek()`](fn.fd_seek.html). This flag implies
-    /// [`FD_TELL`](struct.rights.html#associatedconstant.FD_TELL).
-    const FD_SEEK               = 0x0000000000000004;
-    /// The right to invoke [`fd_stat_put()`](fn.fd_stat_put.html) with
-    /// [`FLAGS`](struct.fdsflags.html#associatedconstant.FLAGS).
-    const FD_STAT_PUT_FLAGS     = 0x0000000000000008;
-    /// The right to invoke [`fd_sync()`](fn.fd_sync.html).
-    ///
-    /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, includes the right to
-    /// invoke [`file_open()`](fn.file_open.html) with [`RSYNC`](struct.fdflags.html#associatedconstant.RSYNC) and
-    /// [`DSYNC`](struct.fdflags.html#associatedconstant.DSYNC).
-    const FD_SYNC               = 0x0000000000000010;
-    /// The right to invoke [`fd_seek()`](fn.fd_seek.html) in such a way that the
-    /// file offset remains unaltered (i.e., [`CUR`](enum.whence.html#variant.CUR) with
-    /// offset zero).
-    const FD_TELL               = 0x0000000000000020;
-    /// The right to invoke [`fd_write()`](fn.fd_write.html) and [`sock_send()`](fn.sock_send.html).
-    ///
-    /// If [`MEM_MAP`](struct.rights.html#associatedconstant.MEM_MAP) is set, includes the right to
-    /// invoke [`mem_map()`](fn.mem_map.html) with memory protection option
-    /// [`WRITE`](struct.mprot.html#associatedconstant.WRITE).
-    ///
-    /// If [`FD_SEEK`](struct.rights.html#associatedconstant.FD_SEEK) is set, includes the right to
-    /// invoke [`fd_pwrite()`](fn.fd_pwrite.html).
-    const FD_WRITE              = 0x0000000000000040;
-    /// The right to invoke [`file_advise()`](fn.file_advise.html).
-    const FILE_ADVISE           = 0x0000000000000080;
-    /// The right to invoke [`file_allocate()`](fn.file_allocate.html).
-    const FILE_ALLOCATE         = 0x0000000000000100;
-    /// The right to invoke [`file_create()`](fn.file_create.html) with
-    /// [`DIRECTORY`](enum.filetype.html#variant.DIRECTORY).
-    const FILE_CREATE_DIRECTORY = 0x0000000000000200;
-    /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, the right to invoke
-    /// [`file_open()`](fn.file_open.html) with [`CREAT`](struct.oflags.html#associatedconstant.CREAT).
-    const FILE_CREATE_FILE      = 0x0000000000000400;
-    /// The right to invoke [`file_link()`](fn.file_link.html) with the file
-    /// descriptor as the source directory.
-    const FILE_LINK_SOURCE      = 0x0000000000001000;
-    /// The right to invoke [`file_link()`](fn.file_link.html) with the file
-    /// descriptor as the target directory.
-    const FILE_LINK_TARGET      = 0x0000000000002000;
-    /// The right to invoke [`file_open()`](fn.file_open.html).
-    const FILE_OPEN             = 0x0000000000004000;
-    /// The right to invoke [`file_readdir()`](fn.file_readdir.html).
-    const FILE_READDIR          = 0x0000000000008000;
-    /// The right to invoke [`file_readlink()`](fn.file_readlink.html).
-    const FILE_READLINK         = 0x0000000000010000;
-    /// The right to invoke [`file_rename()`](fn.file_rename.html) with the file
-    /// descriptor as the source directory.
-    const FILE_RENAME_SOURCE    = 0x0000000000020000;
-    /// The right to invoke [`file_rename()`](fn.file_rename.html) with the file
-    /// descriptor as the target directory.
-    const FILE_RENAME_TARGET    = 0x0000000000040000;
-    /// The right to invoke [`file_stat_fget()`](fn.file_stat_fget.html).
-    const FILE_STAT_FGET        = 0x0000000000080000;
-    /// The right to invoke [`file_stat_fput()`](fn.file_stat_fput.html) with
-    /// [`SIZE`](struct.fsflags.html#associatedconstant.SIZE).
-    ///
-    /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, includes the right to
-    /// invoke [`file_open()`](fn.file_open.html) with [`TRUNC`](struct.oflags.html#associatedconstant.TRUNC).
-    const FILE_STAT_FPUT_SIZE   = 0x0000000000100000;
-    /// The right to invoke [`file_stat_fput()`](fn.file_stat_fput.html) with
-    /// [`ATIM`](struct.fsflags.html#associatedconstant.ATIM), [`ATIM_NOW`](struct.fsflags.html#associatedconstant.ATIM_NOW), [`MTIM`](struct.fsflags.html#associatedconstant.MTIM),
-    /// and [`MTIM_NOW`](struct.fsflags.html#associatedconstant.MTIM_NOW).
-    const FILE_STAT_FPUT_TIMES  = 0x0000000000200000;
-    /// The right to invoke [`file_stat_get()`](fn.file_stat_get.html).
-    const FILE_STAT_GET         = 0x0000000000400000;
-    /// The right to invoke [`file_stat_put()`](fn.file_stat_put.html) with
-    /// [`ATIM`](struct.fsflags.html#associatedconstant.ATIM), [`ATIM_NOW`](struct.fsflags.html#associatedconstant.ATIM_NOW), [`MTIM`](struct.fsflags.html#associatedconstant.MTIM),
-    /// and [`MTIM_NOW`](struct.fsflags.html#associatedconstant.MTIM_NOW).
-    const FILE_STAT_PUT_TIMES   = 0x0000000000800000;
-    /// The right to invoke [`file_symlink()`](fn.file_symlink.html).
-    const FILE_SYMLINK          = 0x0000000001000000;
-    /// The right to invoke [`file_unlink()`](fn.file_unlink.html).
-    const FILE_UNLINK           = 0x0000000002000000;
-    /// The right to invoke [`mem_map()`](fn.mem_map.html) with [`mprot`] set to
-    /// zero.
-    const MEM_MAP               = 0x0000000004000000;
-    /// If [`MEM_MAP`](struct.rights.html#associatedconstant.MEM_MAP) is set, the right to invoke
-    /// [`mem_map()`](fn.mem_map.html) with [`EXEC`](struct.mprot.html#associatedconstant.EXEC).
-    const MEM_MAP_EXEC          = 0x0000000008000000;
-    /// If [`FD_READ`](struct.rights.html#associatedconstant.FD_READ) is set, includes the right to
-    /// invoke [`poll()`](fn.poll.html) to subscribe to [`FD_READ`](enum.eventtype.html#variant.FD_READ).
-    ///
-    /// If [`FD_WRITE`](struct.rights.html#associatedconstant.FD_WRITE) is set, includes the right to
-    /// invoke [`poll()`](fn.poll.html) to subscribe to [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE).
-    const POLL_FD_READWRITE     = 0x0000000010000000;
-    /// The right to invoke [`poll()`](fn.poll.html) to subscribe to
-    /// [`PROC_TERMINATE`](enum.eventtype.html#variant.PROC_TERMINATE).
-    const POLL_PROC_TERMINATE   = 0x0000000040000000;
-    /// The right to invoke [`proc_exec()`](fn.proc_exec.html).
-    const PROC_EXEC             = 0x0000000100000000;
-    /// The right to invoke [`sock_shutdown()`](fn.sock_shutdown.html).
-    const SOCK_SHUTDOWN         = 0x0000008000000000;
-  }
-}
-
-bitflags! {
-  /// Flags returned by [`sock_recv()`](fn.sock_recv.html).
-  #[repr(C)]
-  pub struct roflags: u16 {
-    /// Returned by [`sock_recv()`](fn.sock_recv.html): List of file descriptors
-    /// has been truncated.
-    const FDS_TRUNCATED  = 0x0001;
-    /// Returned by [`sock_recv()`](fn.sock_recv.html): Message data has been
-    /// truncated.
-    const DATA_TRUNCATED = 0x0008;
-  }
-}
-
-/// Indicates whether an object is stored in private or shared
-/// memory.
-#[repr(u8)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-#[non_exhaustive]
-pub enum scope {
-    /// The object is stored in private memory.
-    PRIVATE = 4,
-    /// The object is stored in shared memory.
-    SHARED = 8,
-}
-
-bitflags! {
-  /// Which channels on a socket need to be shut down.
-  #[repr(C)]
-  pub struct sdflags: u8 {
-    /// Disables further receive operations.
-    const RD = 0x01;
-    /// Disables further send operations.
-    const WR = 0x02;
-  }
-}
-
-bitflags! {
-  /// Flags provided to [`sock_send()`](fn.sock_send.html). As there are currently no flags
-  /// defined, it must be set to zero.
-  #[repr(C)]
-  pub struct siflags: u16 {
-    const DEFAULT = 0;
-  }
-}
-
-/// Signal condition.
-#[repr(u8)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-#[non_exhaustive]
-pub enum signal {
-    /// Process abort signal.
-    ///
-    /// Action: Terminates the process.
-    ABRT = 1,
-    /// Alarm clock.
-    ///
-    /// Action: Terminates the process.
-    ALRM = 2,
-    /// Access to an undefined portion of a memory object.
-    ///
-    /// Action: Terminates the process.
-    BUS = 3,
-    /// Child process terminated, stopped, or continued.
-    ///
-    /// Action: Ignored.
-    CHLD = 4,
-    /// Continue executing, if stopped.
-    ///
-    /// Action: Continues executing, if stopped.
-    CONT = 5,
-    /// Erroneous arithmetic operation.
-    ///
-    /// Action: Terminates the process.
-    FPE = 6,
-    /// Hangup.
-    ///
-    /// Action: Terminates the process.
-    HUP = 7,
-    /// Illegal instruction.
-    ///
-    /// Action: Terminates the process.
-    ILL = 8,
-    /// Terminate interrupt signal.
-    ///
-    /// Action: Terminates the process.
-    INT = 9,
-    /// Kill.
-    ///
-    /// Action: Terminates the process.
-    KILL = 10,
-    /// Write on a pipe with no one to read it.
-    ///
-    /// Action: Ignored.
-    PIPE = 11,
-    /// Terminal quit signal.
-    ///
-    /// Action: Terminates the process.
-    QUIT = 12,
-    /// Invalid memory reference.
-    ///
-    /// Action: Terminates the process.
-    SEGV = 13,
-    /// Stop executing.
-    ///
-    /// Action: Stops executing.
-    STOP = 14,
-    /// Bad system call.
-    ///
-    /// Action: Terminates the process.
-    SYS = 15,
-    /// Termination signal.
-    ///
-    /// Action: Terminates the process.
-    TERM = 16,
-    /// Trace/breakpoint trap.
-    ///
-    /// Action: Terminates the process.
-    TRAP = 17,
-    /// Terminal stop signal.
-    ///
-    /// Action: Stops executing.
-    TSTP = 18,
-    /// Background process attempting read.
-    ///
-    /// Action: Stops executing.
-    TTIN = 19,
-    /// Background process attempting write.
-    ///
-    /// Action: Stops executing.
-    TTOU = 20,
-    /// High bandwidth data is available at a socket.
-    ///
-    /// Action: Ignored.
-    URG = 21,
-    /// User-defined signal 1.
-    ///
-    /// Action: Terminates the process.
-    USR1 = 22,
-    /// User-defined signal 2.
-    ///
-    /// Action: Terminates the process.
-    USR2 = 23,
-    /// Virtual timer expired.
-    ///
-    /// Action: Terminates the process.
-    VTALRM = 24,
-    /// CPU time limit exceeded.
-    ///
-    /// Action: Terminates the process.
-    XCPU = 25,
-    /// File size limit exceeded.
-    ///
-    /// Action: Terminates the process.
-    XFSZ = 26,
-}
-
-bitflags! {
-  /// Flags determining how the timestamp provided in
-  /// [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout) should be interpreted.
-  #[repr(C)]
-  pub struct subclockflags: u16 {
-    /// If set, treat the timestamp provided in
-    /// [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout) as an absolute timestamp
-    /// of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id).
-    ///
-    /// If clear, treat the timestamp provided in
-    /// [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout) relative to the current
-    /// time value of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id).
-    const ABSTIME = 0x0001;
-  }
-}
-
-bitflags! {
-  /// Flags influencing the method of polling for read or writing on
-  /// a file descriptor.
-  #[repr(C)]
-  pub struct subrwflags: u16 {
-    /// Deprecated. Must be set by callers and ignored by
-    /// implementations.
-    const POLL = 0x0001;
-  }
-}
-
-/// Unique system-local identifier of a thread. This identifier is
-/// only valid during the lifetime of the thread.
-///
-/// Threads must be aware of their thread identifier, as it is
-/// written it into locks when acquiring them for writing. It is
-/// not advised to use these identifiers for any other purpose.
-///
-/// As the thread identifier is also stored in [`lock`] when
-/// [`LOCK_WRLOCKED`](constant.LOCK_WRLOCKED.html) is set, the top two bits of the thread
-/// must always be set to zero.
-#[repr(C)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-pub struct tid(pub u32);
-
-/// Timestamp in nanoseconds.
-pub type timestamp = u64;
-
-bitflags! {
-  /// Specifies whether files are unlinked or directories are
-  /// removed.
-  #[repr(C)]
-  pub struct ulflags: u8 {
-    /// If set, removes a directory. Otherwise, unlinks any
-    /// non-directory file.
-    const REMOVEDIR = 0x01;
-  }
-}
-
-/// User-provided value that can be attached to objects that is
-/// retained when extracted from the kernel.
-pub type userdata = u64;
-
-/// Relative to which position the offset of the file descriptor
-/// should be set.
-#[repr(u8)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-#[non_exhaustive]
-pub enum whence {
-    /// Seek relative to current position.
-    CUR = 1,
-    /// Seek relative to end-of-file.
-    END = 2,
-    /// Seek relative to start-of-file.
-    SET = 3,
-}
-
-/// Auxiliary vector entry.
-///
-/// The auxiliary vector is a list of key-value pairs that is
-/// provided to the process on startup. Unlike structures, it is
-/// extensible, as it is possible to add new records later on.
-/// The auxiliary vector is always terminated by an entry having
-/// type [`NULL`](enum.auxtype.html#variant.NULL).
-///
-/// The auxiliary vector is part of the x86-64 ABI, but is used by
-/// this environment on all architectures.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct auxv {
-    /// The type of the auxiliary vector entry.
-    pub a_type: auxtype,
-    pub union: auxv_union,
-}
-/// A union inside `auxv`.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub union auxv_union {
-    /// Used when `a_type` is [`ARGDATALEN`](enum.auxtype.html#variant.ARGDATALEN), [`CANARYLEN`](enum.auxtype.html#variant.CANARYLEN), [`NCPUS`](enum.auxtype.html#variant.NCPUS), [`PAGESZ`](enum.auxtype.html#variant.PAGESZ), [`PHNUM`](enum.auxtype.html#variant.PHNUM), or [`TID`](enum.auxtype.html#variant.TID).
-    /// A numerical value.
-    pub a_val: usize,
-    /// Used when `a_type` is [`ARGDATA`](enum.auxtype.html#variant.ARGDATA), [`BASE`](enum.auxtype.html#variant.BASE), [`CANARY`](enum.auxtype.html#variant.CANARY), [`PHDR`](enum.auxtype.html#variant.PHDR), [`PID`](enum.auxtype.html#variant.PID), or [`SYSINFO_EHDR`](enum.auxtype.html#variant.SYSINFO_EHDR).
-    /// A pointer value.
-    pub a_ptr: *mut (),
-}
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn auxv_layout_test_32() {
-    assert_eq!(core::mem::size_of::<auxv>(), 8);
-    assert_eq!(core::mem::align_of::<auxv>(), 4);
-    unsafe {
-        let obj: auxv = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.a_type as *const _ as usize - base, 0);
-        assert_eq!(&obj.union.a_val as *const _ as usize - base, 4);
-        assert_eq!(&obj.union.a_ptr as *const _ as usize - base, 4);
-    }
-}
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn auxv_layout_test_64() {
-    assert_eq!(core::mem::size_of::<auxv>(), 16);
-    assert_eq!(core::mem::align_of::<auxv>(), 8);
-    unsafe {
-        let obj: auxv = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.a_type as *const _ as usize - base, 0);
-        assert_eq!(&obj.union.a_val as *const _ as usize - base, 8);
-        assert_eq!(&obj.union.a_ptr as *const _ as usize - base, 8);
-    }
-}
-
-/// A region of memory for scatter/gather writes.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct ciovec {
-    /// The address and length of the buffer to be written.
-    pub buf: (*const (), usize),
-}
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn ciovec_layout_test_32() {
-    assert_eq!(core::mem::size_of::<ciovec>(), 8);
-    assert_eq!(core::mem::align_of::<ciovec>(), 4);
-    unsafe {
-        let obj: ciovec = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
-        assert_eq!(&obj.buf.1 as *const _ as usize - base, 4);
-    }
-}
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn ciovec_layout_test_64() {
-    assert_eq!(core::mem::size_of::<ciovec>(), 16);
-    assert_eq!(core::mem::align_of::<ciovec>(), 8);
-    unsafe {
-        let obj: ciovec = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
-        assert_eq!(&obj.buf.1 as *const _ as usize - base, 8);
-    }
-}
-
-/// A directory entry.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct dirent {
-    /// The offset of the next directory entry stored in this
-    /// directory.
-    pub d_next: dircookie,
-    /// The serial number of the file referred to by this
-    /// directory entry.
-    pub d_ino: inode,
-    /// The length of the name of the directory entry.
-    pub d_namlen: u32,
-    /// The type of the file referred to by this directory
-    /// entry.
-    pub d_type: filetype,
-}
-#[test]
-fn dirent_layout_test() {
-    assert_eq!(core::mem::size_of::<dirent>(), 24);
-    assert_eq!(core::mem::align_of::<dirent>(), 8);
-    unsafe {
-        let obj: dirent = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.d_next as *const _ as usize - base, 0);
-        assert_eq!(&obj.d_ino as *const _ as usize - base, 8);
-        assert_eq!(&obj.d_namlen as *const _ as usize - base, 16);
-        assert_eq!(&obj.d_type as *const _ as usize - base, 20);
-    }
-}
-
-/// An event that occurred.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct event {
-    /// User-provided value that got attached to
-    /// [`subscription.userdata`](struct.subscription.html#structfield.userdata).
-    pub userdata: userdata,
-    /// If non-zero, an error that occurred while processing
-    /// the subscription request.
-    pub error: errno,
-    /// The type of the event that occurred.
-    pub type_: eventtype,
-    pub union: event_union,
-}
-/// A union inside `event`.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub union event_union {
-    /// Used when `type_` is [`FD_READ`](enum.eventtype.html#variant.FD_READ) or [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE).
-    pub fd_readwrite: event_fd_readwrite,
-    /// Used when `type_` is [`PROC_TERMINATE`](enum.eventtype.html#variant.PROC_TERMINATE).
-    pub proc_terminate: event_proc_terminate,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct event_fd_readwrite {
-    /// The number of bytes available
-    /// for reading or writing.
-    pub nbytes: filesize,
-    /// Obsolete.
-    pub unused: [u8; 4],
-    /// The state of the file
-    /// descriptor.
-    pub flags: eventrwflags,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct event_proc_terminate {
-    /// Obsolete.
-    pub unused: [u8; 4],
-    /// If zero, the process has
-    /// exited.
-    /// Otherwise, the signal
-    /// condition causing it to
-    /// terminated.
-    pub signal: signal,
-    /// If exited, the exit code of
-    /// the process.
-    pub exitcode: exitcode,
-}
-#[test]
-fn event_layout_test() {
-    assert_eq!(core::mem::size_of::<event>(), 32);
-    assert_eq!(core::mem::align_of::<event>(), 8);
-    unsafe {
-        let obj: event = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.userdata as *const _ as usize - base, 0);
-        assert_eq!(&obj.error as *const _ as usize - base, 8);
-        assert_eq!(&obj.type_ as *const _ as usize - base, 10);
-        assert_eq!(&obj.union.fd_readwrite.nbytes as *const _ as usize - base, 16);
-        assert_eq!(&obj.union.fd_readwrite.unused as *const _ as usize - base, 24);
-        assert_eq!(&obj.union.fd_readwrite.flags as *const _ as usize - base, 28);
-        assert_eq!(&obj.union.proc_terminate.unused as *const _ as usize - base, 16);
-        assert_eq!(&obj.union.proc_terminate.signal as *const _ as usize - base, 20);
-        assert_eq!(&obj.union.proc_terminate.exitcode as *const _ as usize - base, 24);
-    }
-}
-
-/// File descriptor attributes.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct fdstat {
-    /// File type.
-    pub fs_filetype: filetype,
-    /// File descriptor flags.
-    pub fs_flags: fdflags,
-    /// Rights that apply to this file descriptor.
-    pub fs_rights_base: rights,
-    /// Maximum set of rights that can be installed on new
-    /// file descriptors that are created through this file
-    /// descriptor, e.g., through [`file_open()`](fn.file_open.html).
-    pub fs_rights_inheriting: rights,
-}
-#[test]
-fn fdstat_layout_test() {
-    assert_eq!(core::mem::size_of::<fdstat>(), 24);
-    assert_eq!(core::mem::align_of::<fdstat>(), 8);
-    unsafe {
-        let obj: fdstat = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.fs_filetype as *const _ as usize - base, 0);
-        assert_eq!(&obj.fs_flags as *const _ as usize - base, 2);
-        assert_eq!(&obj.fs_rights_base as *const _ as usize - base, 8);
-        assert_eq!(&obj.fs_rights_inheriting as *const _ as usize - base, 16);
-    }
-}
-
-/// File attributes.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct filestat {
-    /// Device ID of device containing the file.
-    pub st_dev: device,
-    /// File serial number.
-    pub st_ino: inode,
-    /// File type.
-    pub st_filetype: filetype,
-    /// Number of hard links to the file.
-    pub st_nlink: linkcount,
-    /// For regular files, the file size in bytes. For
-    /// symbolic links, the length in bytes of the pathname
-    /// contained in the symbolic link.
-    pub st_size: filesize,
-    /// Last data access timestamp.
-    pub st_atim: timestamp,
-    /// Last data modification timestamp.
-    pub st_mtim: timestamp,
-    /// Last file status change timestamp.
-    pub st_ctim: timestamp,
-}
-#[test]
-fn filestat_layout_test() {
-    assert_eq!(core::mem::size_of::<filestat>(), 56);
-    assert_eq!(core::mem::align_of::<filestat>(), 8);
-    unsafe {
-        let obj: filestat = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.st_dev as *const _ as usize - base, 0);
-        assert_eq!(&obj.st_ino as *const _ as usize - base, 8);
-        assert_eq!(&obj.st_filetype as *const _ as usize - base, 16);
-        assert_eq!(&obj.st_nlink as *const _ as usize - base, 20);
-        assert_eq!(&obj.st_size as *const _ as usize - base, 24);
-        assert_eq!(&obj.st_atim as *const _ as usize - base, 32);
-        assert_eq!(&obj.st_mtim as *const _ as usize - base, 40);
-        assert_eq!(&obj.st_ctim as *const _ as usize - base, 48);
-    }
-}
-
-/// A region of memory for scatter/gather reads.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct iovec {
-    /// The address and length of the buffer to be filled.
-    pub buf: (*mut (), usize),
-}
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn iovec_layout_test_32() {
-    assert_eq!(core::mem::size_of::<iovec>(), 8);
-    assert_eq!(core::mem::align_of::<iovec>(), 4);
-    unsafe {
-        let obj: iovec = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
-        assert_eq!(&obj.buf.1 as *const _ as usize - base, 4);
-    }
-}
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn iovec_layout_test_64() {
-    assert_eq!(core::mem::size_of::<iovec>(), 16);
-    assert_eq!(core::mem::align_of::<iovec>(), 8);
-    unsafe {
-        let obj: iovec = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
-        assert_eq!(&obj.buf.1 as *const _ as usize - base, 8);
-    }
-}
-
-/// Path lookup properties.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct lookup {
-    /// The working directory at which the resolution of the
-    /// path starts.
-    pub fd: fd,
-    /// Flags determining the method of how the path is
-    /// resolved.
-    pub flags: lookupflags,
-}
-#[test]
-fn lookup_layout_test() {
-    assert_eq!(core::mem::size_of::<lookup>(), 8);
-    assert_eq!(core::mem::align_of::<lookup>(), 4);
-    unsafe {
-        let obj: lookup = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.fd as *const _ as usize - base, 0);
-        assert_eq!(&obj.flags as *const _ as usize - base, 4);
-    }
-}
-
-/// Entry point for a process (`_start`).
-///
-/// **auxv**:
-/// The auxiliary vector. See [`auxv`].
-pub type processentry = unsafe extern "C" fn(auxv: *const auxv) -> ();
-
-/// Arguments of [`sock_recv()`](fn.sock_recv.html).
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct recv_in {
-    /// List of scatter/gather vectors where message data
-    /// should be stored.
-    pub ri_data: (*const iovec, usize),
-    /// Buffer where numbers of incoming file descriptors
-    /// should be stored.
-    pub ri_fds: (*mut fd, usize),
-    /// Message flags.
-    pub ri_flags: riflags,
-}
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn recv_in_layout_test_32() {
-    assert_eq!(core::mem::size_of::<recv_in>(), 20);
-    assert_eq!(core::mem::align_of::<recv_in>(), 4);
-    unsafe {
-        let obj: recv_in = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.ri_data.0 as *const _ as usize - base, 0);
-        assert_eq!(&obj.ri_data.1 as *const _ as usize - base, 4);
-        assert_eq!(&obj.ri_fds.0 as *const _ as usize - base, 8);
-        assert_eq!(&obj.ri_fds.1 as *const _ as usize - base, 12);
-        assert_eq!(&obj.ri_flags as *const _ as usize - base, 16);
-    }
-}
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn recv_in_layout_test_64() {
-    assert_eq!(core::mem::size_of::<recv_in>(), 40);
-    assert_eq!(core::mem::align_of::<recv_in>(), 8);
-    unsafe {
-        let obj: recv_in = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.ri_data.0 as *const _ as usize - base, 0);
-        assert_eq!(&obj.ri_data.1 as *const _ as usize - base, 8);
-        assert_eq!(&obj.ri_fds.0 as *const _ as usize - base, 16);
-        assert_eq!(&obj.ri_fds.1 as *const _ as usize - base, 24);
-        assert_eq!(&obj.ri_flags as *const _ as usize - base, 32);
-    }
-}
-
-/// Results of [`sock_recv()`](fn.sock_recv.html).
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct recv_out {
-    /// Number of bytes stored in [`recv_in.ri_data`](struct.recv_in.html#structfield.ri_data).
-    pub ro_datalen: usize,
-    /// Number of file descriptors stored in [`recv_in.ri_fds`](struct.recv_in.html#structfield.ri_fds).
-    pub ro_fdslen: usize,
-    /// Fields that were used by previous implementations.
-    pub ro_unused: [u8; 40],
-    /// Message flags.
-    pub ro_flags: roflags,
-}
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn recv_out_layout_test_32() {
-    assert_eq!(core::mem::size_of::<recv_out>(), 52);
-    assert_eq!(core::mem::align_of::<recv_out>(), 4);
-    unsafe {
-        let obj: recv_out = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.ro_datalen as *const _ as usize - base, 0);
-        assert_eq!(&obj.ro_fdslen as *const _ as usize - base, 4);
-        assert_eq!(&obj.ro_unused as *const _ as usize - base, 8);
-        assert_eq!(&obj.ro_flags as *const _ as usize - base, 48);
-    }
-}
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn recv_out_layout_test_64() {
-    assert_eq!(core::mem::size_of::<recv_out>(), 64);
-    assert_eq!(core::mem::align_of::<recv_out>(), 8);
-    unsafe {
-        let obj: recv_out = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.ro_datalen as *const _ as usize - base, 0);
-        assert_eq!(&obj.ro_fdslen as *const _ as usize - base, 8);
-        assert_eq!(&obj.ro_unused as *const _ as usize - base, 16);
-        assert_eq!(&obj.ro_flags as *const _ as usize - base, 56);
-    }
-}
-
-/// Arguments of [`sock_send()`](fn.sock_send.html).
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct send_in {
-    /// List of scatter/gather vectors where message data
-    /// should be retrieved.
-    pub si_data: (*const ciovec, usize),
-    /// File descriptors that need to be attached to the
-    /// message.
-    pub si_fds: (*const fd, usize),
-    /// Message flags.
-    pub si_flags: siflags,
-}
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn send_in_layout_test_32() {
-    assert_eq!(core::mem::size_of::<send_in>(), 20);
-    assert_eq!(core::mem::align_of::<send_in>(), 4);
-    unsafe {
-        let obj: send_in = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.si_data.0 as *const _ as usize - base, 0);
-        assert_eq!(&obj.si_data.1 as *const _ as usize - base, 4);
-        assert_eq!(&obj.si_fds.0 as *const _ as usize - base, 8);
-        assert_eq!(&obj.si_fds.1 as *const _ as usize - base, 12);
-        assert_eq!(&obj.si_flags as *const _ as usize - base, 16);
-    }
-}
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn send_in_layout_test_64() {
-    assert_eq!(core::mem::size_of::<send_in>(), 40);
-    assert_eq!(core::mem::align_of::<send_in>(), 8);
-    unsafe {
-        let obj: send_in = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.si_data.0 as *const _ as usize - base, 0);
-        assert_eq!(&obj.si_data.1 as *const _ as usize - base, 8);
-        assert_eq!(&obj.si_fds.0 as *const _ as usize - base, 16);
-        assert_eq!(&obj.si_fds.1 as *const _ as usize - base, 24);
-        assert_eq!(&obj.si_flags as *const _ as usize - base, 32);
-    }
-}
-
-/// Results of [`sock_send()`](fn.sock_send.html).
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct send_out {
-    /// Number of bytes transmitted.
-    pub so_datalen: usize,
-}
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn send_out_layout_test_32() {
-    assert_eq!(core::mem::size_of::<send_out>(), 4);
-    assert_eq!(core::mem::align_of::<send_out>(), 4);
-    unsafe {
-        let obj: send_out = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.so_datalen as *const _ as usize - base, 0);
-    }
-}
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn send_out_layout_test_64() {
-    assert_eq!(core::mem::size_of::<send_out>(), 8);
-    assert_eq!(core::mem::align_of::<send_out>(), 8);
-    unsafe {
-        let obj: send_out = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.so_datalen as *const _ as usize - base, 0);
-    }
-}
-
-/// Subscription to an event.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct subscription {
-    /// User-provided value that is attached to the
-    /// subscription in the kernel and returned through
-    /// [`event.userdata`](struct.event.html#structfield.userdata).
-    pub userdata: userdata,
-    /// Used by previous implementations. Ignored.
-    pub unused: u16,
-    /// The type of the event to which to subscribe.
-    ///
-    /// Currently, [`CONDVAR`](enum.eventtype.html#variant.CONDVAR),
-    /// [`LOCK_RDLOCK`](enum.eventtype.html#variant.LOCK_RDLOCK), and [`LOCK_WRLOCK`](enum.eventtype.html#variant.LOCK_WRLOCK)
-    /// must be provided as the first subscription and may
-    /// only be followed by up to one other subscription,
-    /// having type [`CLOCK`](enum.eventtype.html#variant.CLOCK).
-    pub type_: eventtype,
-    pub union: subscription_union,
-}
-/// A union inside `subscription`.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub union subscription_union {
-    /// Used when `type_` is [`CLOCK`](enum.eventtype.html#variant.CLOCK).
-    pub clock: subscription_clock,
-    /// Used when `type_` is [`CONDVAR`](enum.eventtype.html#variant.CONDVAR).
-    pub condvar: subscription_condvar,
-    /// Used when `type_` is [`FD_READ`](enum.eventtype.html#variant.FD_READ) or [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE).
-    pub fd_readwrite: subscription_fd_readwrite,
-    /// Used when `type_` is [`LOCK_RDLOCK`](enum.eventtype.html#variant.LOCK_RDLOCK) or [`LOCK_WRLOCK`](enum.eventtype.html#variant.LOCK_WRLOCK).
-    pub lock: subscription_lock,
-    /// Used when `type_` is [`PROC_TERMINATE`](enum.eventtype.html#variant.PROC_TERMINATE).
-    pub proc_terminate: subscription_proc_terminate,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct subscription_clock {
-    /// The user-defined unique
-    /// identifier of the clock.
-    pub identifier: userdata,
-    /// The clock against which the
-    /// timestamp should be compared.
-    pub clock_id: clockid,
-    /// The absolute or relative
-    /// timestamp.
-    pub timeout: timestamp,
-    /// The amount of time that the
-    /// kernel may wait additionally
-    /// to coalesce with other events.
-    pub precision: timestamp,
-    /// Flags specifying whether the
-    /// timeout is absolute or
-    /// relative.
-    pub flags: subclockflags,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct subscription_condvar {
-    /// The condition variable on
-    /// which to wait to be woken up.
-    pub condvar: *mut condvar,
-    /// The lock that will be
-    /// released while waiting.
-    ///
-    /// The lock will be reacquired
-    /// for writing when the condition
-    /// variable triggers.
-    pub lock: *mut lock,
-    /// Whether the condition variable
-    /// is stored in private or shared
-    /// memory.
-    pub condvar_scope: scope,
-    /// Whether the lock is stored in
-    /// private or shared memory.
-    pub lock_scope: scope,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct subscription_fd_readwrite {
-    /// The file descriptor on which
-    /// to wait for it to become ready
-    /// for reading or writing.
-    pub fd: fd,
-    /// Under which conditions to
-    /// trigger.
-    pub flags: subrwflags,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct subscription_lock {
-    /// The lock that will be acquired
-    /// for reading or writing.
-    pub lock: *mut lock,
-    /// Whether the lock is stored in
-    /// private or shared memory.
-    pub lock_scope: scope,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct subscription_proc_terminate {
-    /// The process descriptor on
-    /// which to wait for process
-    /// termination.
-    pub fd: fd,
-}
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn subscription_layout_test_32() {
-    assert_eq!(core::mem::size_of::<subscription>(), 56);
-    assert_eq!(core::mem::align_of::<subscription>(), 8);
-    unsafe {
-        let obj: subscription = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.userdata as *const _ as usize - base, 0);
-        assert_eq!(&obj.unused as *const _ as usize - base, 8);
-        assert_eq!(&obj.type_ as *const _ as usize - base, 10);
-        assert_eq!(&obj.union.clock.identifier as *const _ as usize - base, 16);
-        assert_eq!(&obj.union.clock.clock_id as *const _ as usize - base, 24);
-        assert_eq!(&obj.union.clock.timeout as *const _ as usize - base, 32);
-        assert_eq!(&obj.union.clock.precision as *const _ as usize - base, 40);
-        assert_eq!(&obj.union.clock.flags as *const _ as usize - base, 48);
-        assert_eq!(&obj.union.condvar.condvar as *const _ as usize - base, 16);
-        assert_eq!(&obj.union.condvar.lock as *const _ as usize - base, 20);
-        assert_eq!(&obj.union.condvar.condvar_scope as *const _ as usize - base, 24);
-        assert_eq!(&obj.union.condvar.lock_scope as *const _ as usize - base, 25);
-        assert_eq!(&obj.union.fd_readwrite.fd as *const _ as usize - base, 16);
-        assert_eq!(&obj.union.fd_readwrite.flags as *const _ as usize - base, 20);
-        assert_eq!(&obj.union.lock.lock as *const _ as usize - base, 16);
-        assert_eq!(&obj.union.lock.lock_scope as *const _ as usize - base, 20);
-        assert_eq!(&obj.union.proc_terminate.fd as *const _ as usize - base, 16);
-    }
-}
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn subscription_layout_test_64() {
-    assert_eq!(core::mem::size_of::<subscription>(), 56);
-    assert_eq!(core::mem::align_of::<subscription>(), 8);
-    unsafe {
-        let obj: subscription = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.userdata as *const _ as usize - base, 0);
-        assert_eq!(&obj.unused as *const _ as usize - base, 8);
-        assert_eq!(&obj.type_ as *const _ as usize - base, 10);
-        assert_eq!(&obj.union.clock.identifier as *const _ as usize - base, 16);
-        assert_eq!(&obj.union.clock.clock_id as *const _ as usize - base, 24);
-        assert_eq!(&obj.union.clock.timeout as *const _ as usize - base, 32);
-        assert_eq!(&obj.union.clock.precision as *const _ as usize - base, 40);
-        assert_eq!(&obj.union.clock.flags as *const _ as usize - base, 48);
-        assert_eq!(&obj.union.condvar.condvar as *const _ as usize - base, 16);
-        assert_eq!(&obj.union.condvar.lock as *const _ as usize - base, 24);
-        assert_eq!(&obj.union.condvar.condvar_scope as *const _ as usize - base, 32);
-        assert_eq!(&obj.union.condvar.lock_scope as *const _ as usize - base, 33);
-        assert_eq!(&obj.union.fd_readwrite.fd as *const _ as usize - base, 16);
-        assert_eq!(&obj.union.fd_readwrite.flags as *const _ as usize - base, 20);
-        assert_eq!(&obj.union.lock.lock as *const _ as usize - base, 16);
-        assert_eq!(&obj.union.lock.lock_scope as *const _ as usize - base, 24);
-        assert_eq!(&obj.union.proc_terminate.fd as *const _ as usize - base, 16);
-    }
-}
-
-/// The Thread Control Block (TCB).
-///
-/// After a thread begins execution (at program startup or when
-/// created through [`thread_create()`](fn.thread_create.html)), the CPU's registers
-/// controlling Thread-Local Storage (TLS) will already be
-/// initialized. They will point to an area only containing the
-/// TCB.
-///
-/// If the thread needs space for storing thread-specific
-/// variables, the thread may allocate a larger area and adjust
-/// the CPU's registers to point to that area instead. However, it
-/// does need to make sure that the TCB is copied over to the new
-/// TLS area.
-///
-/// The purpose of the TCB is that it allows light-weight
-/// emulators to store information related to individual threads.
-/// For example, it may be used to store a copy of the CPU
-/// registers prior emulation, so that TLS for the host system
-/// can be restored if needed.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct tcb {
-    /// Pointer that may be freely assigned by the system. Its
-    /// value cannot be interpreted by the application.
-    pub parent: *mut (),
-}
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn tcb_layout_test_32() {
-    assert_eq!(core::mem::size_of::<tcb>(), 4);
-    assert_eq!(core::mem::align_of::<tcb>(), 4);
-    unsafe {
-        let obj: tcb = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.parent as *const _ as usize - base, 0);
-    }
-}
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn tcb_layout_test_64() {
-    assert_eq!(core::mem::size_of::<tcb>(), 8);
-    assert_eq!(core::mem::align_of::<tcb>(), 8);
-    unsafe {
-        let obj: tcb = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.parent as *const _ as usize - base, 0);
-    }
-}
-
-/// Entry point for additionally created threads.
-///
-/// `tid`: thread ID of the current thread.
-///
-/// `aux`: copy of the value stored in
-/// [`threadattr.argument`](struct.threadattr.html#structfield.argument).
-pub type threadentry = unsafe extern "C" fn(tid: tid, aux: *mut ()) -> ();
-
-/// Attributes for thread creation.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct threadattr {
-    /// Initial program counter value.
-    pub entry_point: threadentry,
-    /// Region allocated to serve as stack space.
-    pub stack: (*mut (), usize),
-    /// Argument to be forwarded to the entry point function.
-    pub argument: *mut (),
-}
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn threadattr_layout_test_32() {
-    assert_eq!(core::mem::size_of::<threadattr>(), 16);
-    assert_eq!(core::mem::align_of::<threadattr>(), 4);
-    unsafe {
-        let obj: threadattr = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.entry_point as *const _ as usize - base, 0);
-        assert_eq!(&obj.stack.0 as *const _ as usize - base, 4);
-        assert_eq!(&obj.stack.1 as *const _ as usize - base, 8);
-        assert_eq!(&obj.argument as *const _ as usize - base, 12);
-    }
-}
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn threadattr_layout_test_64() {
-    assert_eq!(core::mem::size_of::<threadattr>(), 32);
-    assert_eq!(core::mem::align_of::<threadattr>(), 8);
-    unsafe {
-        let obj: threadattr = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.entry_point as *const _ as usize - base, 0);
-        assert_eq!(&obj.stack.0 as *const _ as usize - base, 8);
-        assert_eq!(&obj.stack.1 as *const _ as usize - base, 16);
-        assert_eq!(&obj.argument as *const _ as usize - base, 24);
-    }
-}
-
-/// The table with pointers to all syscall implementations.
-#[allow(improper_ctypes)]
-extern "C" {
-    fn cloudabi_sys_clock_res_get(_: clockid, _: *mut timestamp) -> errno;
-    fn cloudabi_sys_clock_time_get(_: clockid, _: timestamp, _: *mut timestamp) -> errno;
-    fn cloudabi_sys_condvar_signal(_: *mut condvar, _: scope, _: nthreads) -> errno;
-    fn cloudabi_sys_fd_close(_: fd) -> errno;
-    fn cloudabi_sys_fd_create1(_: filetype, _: *mut fd) -> errno;
-    fn cloudabi_sys_fd_create2(_: filetype, _: *mut fd, _: *mut fd) -> errno;
-    fn cloudabi_sys_fd_datasync(_: fd) -> errno;
-    fn cloudabi_sys_fd_dup(_: fd, _: *mut fd) -> errno;
-    fn cloudabi_sys_fd_pread(_: fd, _: *const iovec, _: usize, _: filesize, _: *mut usize)
-    -> errno;
-    fn cloudabi_sys_fd_pwrite(
-        _: fd,
-        _: *const ciovec,
-        _: usize,
-        _: filesize,
-        _: *mut usize,
-    ) -> errno;
-    fn cloudabi_sys_fd_read(_: fd, _: *const iovec, _: usize, _: *mut usize) -> errno;
-    fn cloudabi_sys_fd_replace(_: fd, _: fd) -> errno;
-    fn cloudabi_sys_fd_seek(_: fd, _: filedelta, _: whence, _: *mut filesize) -> errno;
-    fn cloudabi_sys_fd_stat_get(_: fd, _: *mut fdstat) -> errno;
-    fn cloudabi_sys_fd_stat_put(_: fd, _: *const fdstat, _: fdsflags) -> errno;
-    fn cloudabi_sys_fd_sync(_: fd) -> errno;
-    fn cloudabi_sys_fd_write(_: fd, _: *const ciovec, _: usize, _: *mut usize) -> errno;
-    fn cloudabi_sys_file_advise(_: fd, _: filesize, _: filesize, _: advice) -> errno;
-    fn cloudabi_sys_file_allocate(_: fd, _: filesize, _: filesize) -> errno;
-    fn cloudabi_sys_file_create(_: fd, _: *const u8, _: usize, _: filetype) -> errno;
-    fn cloudabi_sys_file_link(
-        _: lookup,
-        _: *const u8,
-        _: usize,
-        _: fd,
-        _: *const u8,
-        _: usize,
-    ) -> errno;
-    fn cloudabi_sys_file_open(
-        _: lookup,
-        _: *const u8,
-        _: usize,
-        _: oflags,
-        _: *const fdstat,
-        _: *mut fd,
-    ) -> errno;
-    fn cloudabi_sys_file_readdir(_: fd, _: *mut (), _: usize, _: dircookie, _: *mut usize)
-    -> errno;
-    fn cloudabi_sys_file_readlink(
-        _: fd,
-        _: *const u8,
-        _: usize,
-        _: *mut u8,
-        _: usize,
-        _: *mut usize,
-    ) -> errno;
-    fn cloudabi_sys_file_rename(
-        _: fd,
-        _: *const u8,
-        _: usize,
-        _: fd,
-        _: *const u8,
-        _: usize,
-    ) -> errno;
-    fn cloudabi_sys_file_stat_fget(_: fd, _: *mut filestat) -> errno;
-    fn cloudabi_sys_file_stat_fput(_: fd, _: *const filestat, _: fsflags) -> errno;
-    fn cloudabi_sys_file_stat_get(_: lookup, _: *const u8, _: usize, _: *mut filestat) -> errno;
-    fn cloudabi_sys_file_stat_put(
-        _: lookup,
-        _: *const u8,
-        _: usize,
-        _: *const filestat,
-        _: fsflags,
-    ) -> errno;
-    fn cloudabi_sys_file_symlink(_: *const u8, _: usize, _: fd, _: *const u8, _: usize) -> errno;
-    fn cloudabi_sys_file_unlink(_: fd, _: *const u8, _: usize, _: ulflags) -> errno;
-    fn cloudabi_sys_lock_unlock(_: *mut lock, _: scope) -> errno;
-    fn cloudabi_sys_mem_advise(_: *mut (), _: usize, _: advice) -> errno;
-    fn cloudabi_sys_mem_map(
-        _: *mut (),
-        _: usize,
-        _: mprot,
-        _: mflags,
-        _: fd,
-        _: filesize,
-        _: *mut *mut (),
-    ) -> errno;
-    fn cloudabi_sys_mem_protect(_: *mut (), _: usize, _: mprot) -> errno;
-    fn cloudabi_sys_mem_sync(_: *mut (), _: usize, _: msflags) -> errno;
-    fn cloudabi_sys_mem_unmap(_: *mut (), _: usize) -> errno;
-    fn cloudabi_sys_poll(_: *const subscription, _: *mut event, _: usize, _: *mut usize) -> errno;
-    fn cloudabi_sys_proc_exec(_: fd, _: *const (), _: usize, _: *const fd, _: usize) -> errno;
-    fn cloudabi_sys_proc_exit(_: exitcode) -> !;
-    fn cloudabi_sys_proc_fork(_: *mut fd, _: *mut tid) -> errno;
-    fn cloudabi_sys_proc_raise(_: signal) -> errno;
-    fn cloudabi_sys_random_get(_: *mut (), _: usize) -> errno;
-    fn cloudabi_sys_sock_recv(_: fd, _: *const recv_in, _: *mut recv_out) -> errno;
-    fn cloudabi_sys_sock_send(_: fd, _: *const send_in, _: *mut send_out) -> errno;
-    fn cloudabi_sys_sock_shutdown(_: fd, _: sdflags) -> errno;
-    fn cloudabi_sys_thread_create(_: *mut threadattr, _: *mut tid) -> errno;
-    fn cloudabi_sys_thread_exit(_: *mut lock, _: scope) -> !;
-    fn cloudabi_sys_thread_yield() -> errno;
-}
-
-/// Obtains the resolution of a clock.
-///
-/// ## Parameters
-///
-/// **clock_id**:
-/// The clock for which the resolution needs to be
-/// returned.
-///
-/// **resolution**:
-/// The resolution of the clock.
-#[inline]
-pub unsafe fn clock_res_get(clock_id_: clockid, resolution_: &mut timestamp) -> errno {
-    unsafe { cloudabi_sys_clock_res_get(clock_id_, resolution_) }
-}
-
-/// Obtains the time value of a clock.
-///
-/// ## Parameters
-///
-/// **clock_id**:
-/// The clock for which the time needs to be
-/// returned.
-///
-/// **precision**:
-/// The maximum lag (exclusive) that the returned
-/// time value may have, compared to its actual
-/// value.
-///
-/// **time**:
-/// The time value of the clock.
-#[inline]
-pub unsafe fn clock_time_get(
-    clock_id_: clockid,
-    precision_: timestamp,
-    time_: *mut timestamp,
-) -> errno {
-    unsafe { cloudabi_sys_clock_time_get(clock_id_, precision_, time_) }
-}
-
-/// Wakes up threads waiting on a userspace condition variable.
-///
-/// If an invocation of this system call causes all waiting
-/// threads to be woken up, the value of the condition variable
-/// is set to [`CONDVAR_HAS_NO_WAITERS`](constant.CONDVAR_HAS_NO_WAITERS.html). As long as the condition
-/// variable is set to this value, it is not needed to invoke this
-/// system call.
-///
-/// ## Parameters
-///
-/// **condvar**:
-/// The userspace condition variable that has
-/// waiting threads.
-///
-/// **scope**:
-/// Whether the condition variable is stored in
-/// private or shared memory.
-///
-/// **nwaiters**:
-/// The number of threads that need to be woken
-/// up. If it exceeds the number of waiting
-/// threads, all threads are woken up.
-#[inline]
-pub unsafe fn condvar_signal(condvar_: *mut condvar, scope_: scope, nwaiters_: nthreads) -> errno {
-    unsafe { cloudabi_sys_condvar_signal(condvar_, scope_, nwaiters_) }
-}
-
-/// Closes a file descriptor.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor that needs to be closed.
-#[inline]
-pub unsafe fn fd_close(fd_: fd) -> errno {
-    unsafe { cloudabi_sys_fd_close(fd_) }
-}
-
-/// Creates a file descriptor.
-///
-/// ## Parameters
-///
-/// **type**:
-/// Possible values:
-///
-///   - [`SHARED_MEMORY`](enum.filetype.html#variant.SHARED_MEMORY):
-///     Creates an anonymous shared memory
-///     object.
-///
-/// **fd**:
-/// The file descriptor that has been created.
-#[inline]
-pub unsafe fn fd_create1(type_: filetype, fd_: &mut fd) -> errno {
-    unsafe { cloudabi_sys_fd_create1(type_, fd_) }
-}
-
-/// Creates a pair of file descriptors.
-///
-/// ## Parameters
-///
-/// **type**:
-/// Possible values:
-///
-///   - [`SOCKET_DGRAM`](enum.filetype.html#variant.SOCKET_DGRAM):
-///     Creates a UNIX datagram socket pair.
-///   - [`SOCKET_STREAM`](enum.filetype.html#variant.SOCKET_STREAM):
-///     Creates a UNIX byte-stream socket
-///     pair.
-///
-/// **fd1**:
-/// The first file descriptor of the pair.
-///
-/// **fd2**:
-/// The second file descriptor of the pair.
-#[inline]
-pub unsafe fn fd_create2(type_: filetype, fd1_: &mut fd, fd2_: &mut fd) -> errno {
-    // SAFETY: the caller must uphold the safety contract for `cloudabi_sys_fd_create2`.
-    unsafe { cloudabi_sys_fd_create2(type_, fd1_, fd2_) }
-}
-
-/// Synchronizes the data of a file to disk.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor of the file whose data
-/// needs to be synchronized to disk.
-#[inline]
-pub unsafe fn fd_datasync(fd_: fd) -> errno {
-    // SAFETY: the caller must guarantee that `fd` is valid
-    // for synchronization.
-    unsafe { cloudabi_sys_fd_datasync(fd_) }
-}
-
-/// Duplicates a file descriptor.
-///
-/// ## Parameters
-///
-/// **from**:
-/// The file descriptor that needs to be
-/// duplicated.
-///
-/// **fd**:
-/// The new file descriptor.
-#[inline]
-pub unsafe fn fd_dup(from_: fd, fd_: &mut fd) -> errno {
-    unsafe { cloudabi_sys_fd_dup(from_, fd_) }
-}
-
-/// Reads from a file descriptor, without using and updating the
-/// file descriptor's offset.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor from which data should be
-/// read.
-///
-/// **iovs**:
-/// List of scatter/gather vectors where data
-/// should be stored.
-///
-/// **offset**:
-/// The offset within the file at which reading
-/// should start.
-///
-/// **nread**:
-/// The number of bytes read.
-#[inline]
-pub unsafe fn fd_pread(fd_: fd, iovs_: &[iovec], offset_: filesize, nread_: &mut usize) -> errno {
-    unsafe { cloudabi_sys_fd_pread(fd_, iovs_.as_ptr(), iovs_.len(), offset_, nread_) }
-}
-
-/// Writes to a file descriptor, without using and updating the
-/// file descriptor's offset.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor to which data should be
-/// written.
-///
-/// **iovs**:
-/// List of scatter/gather vectors where data
-/// should be retrieved.
-///
-/// **offset**:
-/// The offset within the file at which writing
-/// should start.
-///
-/// **nwritten**:
-/// The number of bytes written.
-#[inline]
-pub unsafe fn fd_pwrite(
-    fd_: fd,
-    iovs_: &[ciovec],
-    offset_: filesize,
-    nwritten_: &mut usize,
-) -> errno {
-    unsafe { cloudabi_sys_fd_pwrite(fd_, iovs_.as_ptr(), iovs_.len(), offset_, nwritten_) }
-}
-
-/// Reads from a file descriptor.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor from which data should be
-/// read.
-///
-/// **iovs**:
-/// List of scatter/gather vectors where data
-/// should be stored.
-///
-/// **nread**:
-/// The number of bytes read.
-#[inline]
-pub unsafe fn fd_read(fd_: fd, iovs_: &[iovec], nread_: &mut usize) -> errno {
-    unsafe { cloudabi_sys_fd_read(fd_, iovs_.as_ptr(), iovs_.len(), nread_) }
-}
-
-/// Atomically replaces a file descriptor by a copy of another
-/// file descriptor.
-///
-/// Due to the strong focus on thread safety, this environment
-/// does not provide a mechanism to duplicate a file descriptor to
-/// an arbitrary number, like dup2(). This would be prone to race
-/// conditions, as an actual file descriptor with the same number
-/// could be allocated by a different thread at the same time.
-///
-/// This system call provides a way to atomically replace file
-/// descriptors, which would disappear if dup2() were to be
-/// removed entirely.
-///
-/// ## Parameters
-///
-/// **from**:
-/// The file descriptor that needs to be copied.
-///
-/// **to**:
-/// The file descriptor that needs to be
-/// overwritten.
-#[inline]
-pub unsafe fn fd_replace(from_: fd, to_: fd) -> errno {
-    unsafe { cloudabi_sys_fd_replace(from_, to_) }
-}
-
-/// Moves the offset of the file descriptor.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor whose offset has to be
-/// moved.
-///
-/// **offset**:
-/// The number of bytes to move.
-///
-/// **whence**:
-/// Relative to which position the move should
-/// take place.
-///
-/// **newoffset**:
-/// The new offset of the file descriptor,
-/// relative to the start of the file.
-#[inline]
-pub unsafe fn fd_seek(
-    fd_: fd,
-    offset_: filedelta,
-    whence_: whence,
-    newoffset_: &mut filesize,
-) -> errno {
-    unsafe { cloudabi_sys_fd_seek(fd_, offset_, whence_, newoffset_) }
-}
-
-/// Gets attributes of a file descriptor.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor whose attributes have to
-/// be obtained.
-///
-/// **buf**:
-/// The buffer where the file descriptor's
-/// attributes are stored.
-#[inline]
-pub unsafe fn fd_stat_get(fd_: fd, buf_: *mut fdstat) -> errno {
-    unsafe { cloudabi_sys_fd_stat_get(fd_, buf_) }
-}
-
-/// Adjusts attributes of a file descriptor.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor whose attributes have to
-/// be adjusted.
-///
-/// **buf**:
-/// The desired values of the file descriptor
-/// attributes that are adjusted.
-///
-/// **flags**:
-/// A bitmask indicating which attributes have to
-/// be adjusted.
-#[inline]
-pub unsafe fn fd_stat_put(fd_: fd, buf_: *const fdstat, flags_: fdsflags) -> errno {
-    unsafe { cloudabi_sys_fd_stat_put(fd_, buf_, flags_) }
-}
-
-/// Synchronizes the data and metadata of a file to disk.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor of the file whose data
-/// and metadata needs to be synchronized to disk.
-#[inline]
-pub unsafe fn fd_sync(fd_: fd) -> errno {
-    unsafe { cloudabi_sys_fd_sync(fd_) }
-}
-
-/// Writes to a file descriptor.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor to which data should be
-/// written.
-///
-/// **iovs**:
-/// List of scatter/gather vectors where data
-/// should be retrieved.
-///
-/// **nwritten**:
-/// The number of bytes written.
-#[inline]
-pub unsafe fn fd_write(fd_: fd, iovs_: &[ciovec], nwritten_: &mut usize) -> errno {
-    unsafe { cloudabi_sys_fd_write(fd_, iovs_.as_ptr(), iovs_.len(), nwritten_) }
-}
-
-/// Provides file advisory information on a file descriptor.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor for which to provide file
-/// advisory information.
-///
-/// **offset**:
-/// The offset within the file to which the
-/// advisory applies.
-///
-/// **len**:
-/// The length of the region to which the advisory
-/// applies.
-///
-/// **advice**:
-/// The advice.
-#[inline]
-pub unsafe fn file_advise(fd_: fd, offset_: filesize, len_: filesize, advice_: advice) -> errno {
-    unsafe { cloudabi_sys_file_advise(fd_, offset_, len_, advice_) }
-}
-
-/// Forces the allocation of space in a file.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file in which the space should be
-/// allocated.
-///
-/// **offset**:
-/// The offset at which the allocation should
-/// start.
-///
-/// **len**:
-/// The length of the area that is allocated.
-#[inline]
-pub unsafe fn file_allocate(fd_: fd, offset_: filesize, len_: filesize) -> errno {
-    unsafe { cloudabi_sys_file_allocate(fd_, offset_, len_) }
-}
-
-/// Creates a file of a specified type.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The working directory at which the resolution
-/// of the file to be created starts.
-///
-/// **path**:
-/// The path at which the file should be created.
-///
-/// **type**:
-/// Possible values:
-///
-///   - [`DIRECTORY`](enum.filetype.html#variant.DIRECTORY):
-///     Creates a directory.
-#[inline]
-pub unsafe fn file_create(fd_: fd, path_: &[u8], type_: filetype) -> errno {
-    unsafe { cloudabi_sys_file_create(fd_, path_.as_ptr(), path_.len(), type_)}
-}
-
-/// Creates a hard link.
-///
-/// ## Parameters
-///
-/// **fd1**:
-/// The working directory at which the resolution
-/// of the source path starts.
-///
-/// **path1**:
-/// The source path of the file that should be
-/// hard linked.
-///
-/// **fd2**:
-/// The working directory at which the resolution
-/// of the destination path starts.
-///
-/// **path2**:
-/// The destination path at which the hard link
-/// should be created.
-#[inline]
-pub unsafe fn file_link(fd1_: lookup, path1_: &[u8], fd2_: fd, path2_: &[u8]) -> errno {
-    unsafe { cloudabi_sys_file_link(fd1_, path1_.as_ptr(), path1_.len(), fd2_, path2_.as_ptr(), path2_.len()) }
-}
-
-/// Opens a file.
-///
-/// ## Parameters
-///
-/// **dirfd**:
-/// The working directory at which the resolution
-/// of the file to be opened starts.
-///
-/// **path**:
-/// The path of the file that should be opened.
-///
-/// **oflags**:
-/// The method at which the file should be opened.
-///
-/// **fds**:
-/// [`fdstat.fs_rights_base`](struct.fdstat.html#structfield.fs_rights_base) and
-/// [`fdstat.fs_rights_inheriting`](struct.fdstat.html#structfield.fs_rights_inheriting) specify the
-/// initial rights of the newly created file
-/// descriptor. The operating system is allowed to
-/// return a file descriptor with fewer rights
-/// than specified, if and only if those rights do
-/// not apply to the type of file being opened.
-///
-/// [`fdstat.fs_flags`](struct.fdstat.html#structfield.fs_flags) specifies the initial flags
-/// of the file descriptor.
-///
-/// [`fdstat.fs_filetype`](struct.fdstat.html#structfield.fs_filetype) is ignored.
-///
-/// **fd**:
-/// The file descriptor of the file that has been
-/// opened.
-#[inline]
-pub unsafe fn file_open(
-    dirfd_: lookup,
-    path_: &[u8],
-    oflags_: oflags,
-    fds_: *const fdstat,
-    fd_: &mut fd,
-) -> errno {
-    unsafe { cloudabi_sys_file_open(dirfd_, path_.as_ptr(), path_.len(), oflags_, fds_, fd_) }
-}
-
-/// Reads directory entries from a directory.
-///
-/// When successful, the contents of the output buffer consist of
-/// a sequence of directory entries. Each directory entry consists
-/// of a [`dirent`] object, followed by [`dirent.d_namlen`](struct.dirent.html#structfield.d_namlen) bytes
-/// holding the name of the directory entry.
-///
-/// This system call fills the output buffer as much as possible,
-/// potentially truncating the last directory entry. This allows
-/// the caller to grow its read buffer size in case it's too small
-/// to fit a single large directory entry, or skip the oversized
-/// directory entry.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The directory from which to read the directory
-/// entries.
-///
-/// **buf**:
-/// The buffer where directory entries are stored.
-///
-/// **cookie**:
-/// The location within the directory to start
-/// reading.
-///
-/// **bufused**:
-/// The number of bytes stored in the read buffer.
-/// If less than the size of the read buffer, the
-/// end of the directory has been reached.
-#[inline]
-pub unsafe fn file_readdir(
-    fd_: fd,
-    buf_: &mut [u8],
-    cookie_: dircookie,
-    bufused_: &mut usize,
-) -> errno {
-    unsafe { cloudabi_sys_file_readdir(fd_, buf_.as_mut_ptr() as *mut (), buf_.len(), cookie_, bufused_) }
-}
-
-/// Reads the contents of a symbolic link.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The working directory at which the resolution
-/// of the path of the symbolic starts.
-///
-/// **path**:
-/// The path of the symbolic link whose contents
-/// should be read.
-///
-/// **buf**:
-/// The buffer where the contents of the symbolic
-/// link should be stored.
-///
-/// **bufused**:
-/// The number of bytes placed in the buffer.
-#[inline]
-pub unsafe fn file_readlink(fd_: fd, path_: &[u8], buf_: &mut [u8], bufused_: &mut usize) -> errno {
-    unsafe {
-        cloudabi_sys_file_readlink(
-            fd_,
-            path_.as_ptr(),
-            path_.len(),
-            buf_.as_mut_ptr(),
-            buf_.len(),
-            bufused_,
-        )
-    }
-}
-
-/// Renames a file.
-///
-/// ## Parameters
-///
-/// **fd1**:
-/// The working directory at which the resolution
-/// of the source path starts.
-///
-/// **path1**:
-/// The source path of the file that should be
-/// renamed.
-///
-/// **fd2**:
-/// The working directory at which the resolution
-/// of the destination path starts.
-///
-/// **path2**:
-/// The destination path to which the file should
-/// be renamed.
-#[inline]
-pub unsafe fn file_rename(fd1_: fd, path1_: &[u8], fd2_: fd, path2_: &[u8]) -> errno {
-    unsafe {
-        cloudabi_sys_file_rename(
-            fd1_,
-            path1_.as_ptr(),
-            path1_.len(),
-            fd2_,
-            path2_.as_ptr(),
-            path2_.len(),
-        )
-    }
-}
-
-/// Gets attributes of a file by file descriptor.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor whose attributes have to
-/// be obtained.
-///
-/// **buf**:
-/// The buffer where the file's attributes are
-/// stored.
-#[inline]
-pub unsafe fn file_stat_fget(fd_: fd, buf_: *mut filestat) -> errno {
-    unsafe { cloudabi_sys_file_stat_fget(fd_, buf_) }
-}
-
-/// Adjusts attributes of a file by file descriptor.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor whose attributes have to
-/// be adjusted.
-///
-/// **buf**:
-/// The desired values of the file attributes that
-/// are adjusted.
-///
-/// **flags**:
-/// A bitmask indicating which attributes have to
-/// be adjusted.
-#[inline]
-pub unsafe fn file_stat_fput(fd_: fd, buf_: *const filestat, flags_: fsflags) -> errno {
-    unsafe { cloudabi_sys_file_stat_fput(fd_, buf_, flags_) }
-}
-
-/// Gets attributes of a file by path.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The working directory at which the resolution
-/// of the path whose attributes have to be
-/// obtained starts.
-///
-/// **path**:
-/// The path of the file whose attributes have to
-/// be obtained.
-///
-/// **buf**:
-/// The buffer where the file's attributes are
-/// stored.
-#[inline]
-pub unsafe fn file_stat_get(fd_: lookup, path_: &[u8], buf_: *mut filestat) -> errno {
-    unsafe { cloudabi_sys_file_stat_get(fd_, path_.as_ptr(), path_.len(), buf_) }
-}
-
-/// Adjusts attributes of a file by path.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The working directory at which the resolution
-/// of the path whose attributes have to be
-/// adjusted starts.
-///
-/// **path**:
-/// The path of the file whose attributes have to
-/// be adjusted.
-///
-/// **buf**:
-/// The desired values of the file attributes that
-/// are adjusted.
-///
-/// **flags**:
-/// A bitmask indicating which attributes have to
-/// be adjusted.
-#[inline]
-pub unsafe fn file_stat_put(
-    fd_: lookup,
-    path_: &[u8],
-    buf_: *const filestat,
-    flags_: fsflags,
-) -> errno {
-    unsafe { cloudabi_sys_file_stat_put(fd_, path_.as_ptr(), path_.len(), buf_, flags_) }
-}
-
-/// Creates a symbolic link.
-///
-/// ## Parameters
-///
-/// **path1**:
-/// The contents of the symbolic link.
-///
-/// **fd**:
-/// The working directory at which the resolution
-/// of the destination path starts.
-///
-/// **path2**:
-/// The destination path at which the symbolic
-/// link should be created.
-#[inline]
-pub unsafe fn file_symlink(path1_: &[u8], fd_: fd, path2_: &[u8]) -> errno {
-    unsafe { cloudabi_sys_file_symlink(path1_.as_ptr(), path1_.len(), fd_, path2_.as_ptr(), path2_.len()) }
-}
-
-/// Unlinks a file, or removes a directory.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The working directory at which the resolution
-/// of the path starts.
-///
-/// **path**:
-/// The path that needs to be unlinked or removed.
-///
-/// **flags**:
-/// Possible values:
-///
-///   - [`REMOVEDIR`](struct.ulflags.html#associatedconstant.REMOVEDIR):
-///     If set, attempt to remove a directory.
-///     Otherwise, unlink a file.
-#[inline]
-pub unsafe fn file_unlink(fd_: fd, path_: &[u8], flags_: ulflags) -> errno {
-    unsafe { cloudabi_sys_file_unlink(fd_, path_.as_ptr(), path_.len(), flags_) }
-}
-
-/// Unlocks a write-locked userspace lock.
-///
-/// If a userspace lock is unlocked while having its
-/// [`LOCK_KERNEL_MANAGED`](constant.LOCK_KERNEL_MANAGED.html) flag set, the lock cannot be unlocked in
-/// userspace directly. This system call needs to be performed
-/// instead, so that any waiting threads can be woken up.
-///
-/// To prevent spurious invocations of this system call, the lock
-/// must be locked for writing. This prevents other threads from
-/// acquiring additional read locks while the system call is in
-/// progress. If the lock is acquired for reading, it must first
-/// be upgraded to a write lock.
-///
-/// ## Parameters
-///
-/// **lock**:
-/// The userspace lock that is locked for writing
-/// by the calling thread.
-///
-/// **scope**:
-/// Whether the lock is stored in private or
-/// shared memory.
-#[inline]
-pub unsafe fn lock_unlock(lock_: *mut lock, scope_: scope) -> errno {
-    unsafe { cloudabi_sys_lock_unlock(lock_, scope_) }
-}
-
-/// Provides memory advisory information on a region of memory.
-///
-/// ## Parameters
-///
-/// **mapping**:
-/// The pages for which to provide memory advisory
-/// information.
-///
-/// **advice**:
-/// The advice.
-#[inline]
-pub unsafe fn mem_advise(mapping_: &mut [u8], advice_: advice) -> errno {
-    unsafe { cloudabi_sys_mem_advise(mapping_.as_mut_ptr() as *mut (), mapping_.len(), advice_) }
-}
-
-/// Creates a memory mapping, making the contents of a file
-/// accessible through memory.
-///
-/// ## Parameters
-///
-/// **addr**:
-/// If [`FIXED`](struct.mflags.html#associatedconstant.FIXED) is set, specifies to which
-/// address the file region is mapped. Otherwise,
-/// the mapping is performed at an unused
-/// location.
-///
-/// **len**:
-/// The length of the memory mapping to be
-/// created.
-///
-/// **prot**:
-/// Initial memory protection options for the
-/// memory mapping.
-///
-/// **flags**:
-/// Memory mapping flags.
-///
-/// **fd**:
-/// If [`ANON`](struct.mflags.html#associatedconstant.ANON) is set, this argument must be
-/// [`MAP_ANON_FD`](constant.MAP_ANON_FD.html). Otherwise, this argument
-/// specifies the file whose contents need to be
-/// mapped.
-///
-/// **off**:
-/// If [`ANON`](struct.mflags.html#associatedconstant.ANON) is set, this argument must be
-/// zero. Otherwise, this argument specifies the
-/// offset within the file at which the mapping
-/// starts.
-///
-/// **mem**:
-/// The starting address of the memory mapping.
-#[inline]
-pub unsafe fn mem_map(
-    addr_: *mut (),
-    len_: usize,
-    prot_: mprot,
-    flags_: mflags,
-    fd_: fd,
-    off_: filesize,
-    mem_: &mut *mut (),
-) -> errno {
-    unsafe { cloudabi_sys_mem_map(addr_, len_, prot_, flags_, fd_, off_, mem_) }
-}
-
-/// Changes the protection of a memory mapping.
-///
-/// ## Parameters
-///
-/// **mapping**:
-/// The pages that need their protection changed.
-///
-/// **prot**:
-/// New protection options.
-#[inline]
-pub unsafe fn mem_protect(mapping_: &mut [u8], prot_: mprot) -> errno {
-    unsafe { cloudabi_sys_mem_protect(mapping_.as_mut_ptr() as *mut (), mapping_.len(), prot_) }
-}
-
-/// Synchronizes a region of memory with its physical storage.
-///
-/// ## Parameters
-///
-/// **mapping**:
-/// The pages that need to be synchronized.
-///
-/// **flags**:
-/// The method of synchronization.
-#[inline]
-pub unsafe fn mem_sync(mapping_: &mut [u8], flags_: msflags) -> errno {
-    unsafe { cloudabi_sys_mem_sync(mapping_.as_mut_ptr() as *mut (), mapping_.len(), flags_) }
-}
-
-/// Unmaps a region of memory.
-///
-/// ## Parameters
-///
-/// **mapping**:
-/// The pages that needs to be unmapped.
-#[inline]
-pub unsafe fn mem_unmap(mapping_: &mut [u8]) -> errno {
-    unsafe { cloudabi_sys_mem_unmap(mapping_.as_mut_ptr() as *mut (), mapping_.len()) }
-}
-
-/// Concurrently polls for the occurrence of a set of events.
-///
-/// ## Parameters
-///
-/// **in**:
-/// The events to which to subscribe.
-///
-/// **out**:
-/// The events that have occurred.
-///
-/// **nsubscriptions**:
-/// Both the number of subscriptions and events.
-///
-/// **nevents**:
-/// The number of events stored.
-#[inline]
-pub unsafe fn poll(
-    in_: *const subscription,
-    out_: *mut event,
-    nsubscriptions_: usize,
-    nevents_: *mut usize,
-) -> errno {
-    unsafe { cloudabi_sys_poll(in_, out_, nsubscriptions_, nevents_) }
-}
-
-/// Replaces the process by a new executable.
-///
-/// Process execution in CloudABI differs from POSIX in two ways:
-/// handling of arguments and inheritance of file descriptors.
-///
-/// CloudABI does not use string command line arguments. Instead,
-/// a buffer with binary data is copied into the address space of
-/// the new executable. The kernel does not enforce any specific
-/// structure to this data, although CloudABI's C library uses it
-/// to store a tree structure that is semantically identical to
-/// YAML.
-///
-/// Due to the strong focus on thread safety, file descriptors
-/// aren't inherited through close-on-exec flags. An explicit
-/// list of file descriptors that need to be retained needs to be
-/// provided. After execution, file descriptors are placed in the
-/// order in which they are stored in the array. This not only
-/// makes the execution process deterministic. It also prevents
-/// potential information disclosures about the layout of the
-/// original process.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// A file descriptor of the new executable.
-///
-/// **data**:
-/// Binary argument data that is passed on to the
-/// new executable.
-///
-/// **fds**:
-/// The layout of the file descriptor table after
-/// execution.
-#[inline]
-pub unsafe fn proc_exec(fd_: fd, data_: &[u8], fds_: &[fd]) -> errno {
-    unsafe { cloudabi_sys_proc_exec(fd_, data_.as_ptr() as *const (), data_.len(), fds_.as_ptr(), fds_.len()) }
-}
-
-/// Terminates the process normally.
-///
-/// ## Parameters
-///
-/// **rval**:
-/// The exit code returned by the process. The
-/// exit code can be obtained by other processes
-/// through [`event.union.proc_terminate.exitcode`](struct.event_proc_terminate.html#structfield.exitcode).
-#[inline]
-pub unsafe fn proc_exit(rval_: exitcode) -> ! {
-    unsafe { cloudabi_sys_proc_exit(rval_) }
-}
-
-/// Forks the process of the calling thread.
-///
-/// After forking, a new process shall be created, having only a
-/// copy of the calling thread. The parent process will obtain a
-/// process descriptor. When closed, the child process is
-/// automatically signaled with [`KILL`](enum.signal.html#variant.KILL).
-///
-/// ## Parameters
-///
-/// **fd**:
-/// In the parent process: the file descriptor
-/// number of the process descriptor.
-///
-/// In the child process: [`PROCESS_CHILD`](constant.PROCESS_CHILD.html).
-///
-/// **tid**:
-/// In the parent process: undefined.
-///
-/// In the child process: the thread ID of the
-/// initial thread of the child process.
-#[inline]
-pub unsafe fn proc_fork(fd_: &mut fd, tid_: &mut tid) -> errno {
-    unsafe { cloudabi_sys_proc_fork(fd_, tid_) }
-}
-
-/// Sends a signal to the process of the calling thread.
-///
-/// ## Parameters
-///
-/// **sig**:
-/// The signal condition that should be triggered.
-/// If the signal causes the process to terminate,
-/// its condition can be obtained by other
-/// processes through
-/// [`event.union.proc_terminate.signal`](struct.event_proc_terminate.html#structfield.signal).
-#[inline]
-pub unsafe fn proc_raise(sig_: signal) -> errno {
-    unsafe { cloudabi_sys_proc_raise(sig_) }
-}
-
-/// Obtains random data from the kernel random number generator.
-///
-/// As this interface is not guaranteed to be fast, it is advised
-/// that the random data obtained through this system call is used
-/// as the seed for a userspace pseudo-random number generator.
-///
-/// ## Parameters
-///
-/// **buf**:
-/// The buffer that needs to be filled with random
-/// data.
-#[inline]
-pub unsafe fn random_get(buf_: &mut [u8]) -> errno {
-    unsafe { cloudabi_sys_random_get(buf_.as_mut_ptr() as *mut (), buf_.len()) }
-}
-
-/// Receives a message on a socket.
-///
-/// ## Parameters
-///
-/// **sock**:
-/// The socket on which a message should be
-/// received.
-///
-/// **in**:
-/// Input parameters.
-///
-/// **out**:
-/// Output parameters.
-#[inline]
-pub unsafe fn sock_recv(sock_: fd, in_: *const recv_in, out_: *mut recv_out) -> errno {
-    unsafe { cloudabi_sys_sock_recv(sock_, in_, out_) }
-}
-
-/// Sends a message on a socket.
-///
-/// ## Parameters
-///
-/// **sock**:
-/// The socket on which a message should be sent.
-///
-/// **in**:
-/// Input parameters.
-///
-/// **out**:
-/// Output parameters.
-#[inline]
-pub unsafe fn sock_send(sock_: fd, in_: *const send_in, out_: *mut send_out) -> errno {
-    unsafe { cloudabi_sys_sock_send(sock_, in_, out_) }
-}
-
-/// Shuts down socket send and receive channels.
-///
-/// ## Parameters
-///
-/// **sock**:
-/// The socket that needs its channels shut down.
-///
-/// **how**:
-/// Which channels on the socket need to be shut
-/// down.
-#[inline]
-pub unsafe fn sock_shutdown(sock_: fd, how_: sdflags) -> errno {
-    unsafe { cloudabi_sys_sock_shutdown(sock_, how_) }
-}
-
-/// Creates a new thread within the current process.
-///
-/// ## Parameters
-///
-/// **attr**:
-/// The desired attributes of the new thread.
-///
-/// **tid**:
-/// The thread ID of the new thread.
-#[inline]
-pub unsafe fn thread_create(attr_: *mut threadattr, tid_: &mut tid) -> errno {
-    unsafe { cloudabi_sys_thread_create(attr_, tid_) }
-}
-
-/// Terminates the calling thread.
-///
-/// This system call can also unlock a single userspace lock
-/// after termination, which can be used to implement thread
-/// joining.
-///
-/// ## Parameters
-///
-/// **lock**:
-/// Userspace lock that is locked for writing by
-/// the calling thread.
-///
-/// **scope**:
-/// Whether the lock is stored in private or
-/// shared memory.
-#[inline]
-pub unsafe fn thread_exit(lock_: *mut lock, scope_: scope) -> ! {
-    unsafe { cloudabi_sys_thread_exit(lock_, scope_) }
-}
-
-/// Temporarily yields execution of the calling thread.
-#[inline]
-pub unsafe fn thread_yield() -> errno {
-    unsafe { cloudabi_sys_thread_yield() }
-}
diff --git a/library/std/src/sys/cloudabi/abi/mod.rs b/library/std/src/sys/cloudabi/abi/mod.rs
deleted file mode 100644 (file)
index 9d01d24..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#[allow(warnings)]
-mod cloudabi;
-pub use self::cloudabi::*;
diff --git a/library/std/src/sys/cloudabi/args.rs b/library/std/src/sys/cloudabi/args.rs
deleted file mode 100644 (file)
index dea562a..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-pub use crate::sys::cloudabi::shims::args::*;
-
-#[allow(dead_code)]
-pub fn init(_: isize, _: *const *const u8) {}
-
-#[allow(dead_code)]
-pub fn cleanup() {}
diff --git a/library/std/src/sys/cloudabi/condvar.rs b/library/std/src/sys/cloudabi/condvar.rs
deleted file mode 100644 (file)
index f09bc01..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-use crate::mem;
-use crate::sync::atomic::{AtomicU32, Ordering};
-use crate::sys::cloudabi::abi;
-use crate::sys::mutex::{self, Mutex};
-use crate::sys::time::checked_dur2intervals;
-use crate::time::Duration;
-
-extern "C" {
-    #[thread_local]
-    static __pthread_thread_id: abi::tid;
-}
-
-pub struct Condvar {
-    condvar: AtomicU32,
-}
-
-pub type MovableCondvar = Condvar;
-
-unsafe impl Send for Condvar {}
-unsafe impl Sync for Condvar {}
-
-impl Condvar {
-    pub const fn new() -> Condvar {
-        Condvar { condvar: AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0) }
-    }
-
-    pub unsafe fn init(&mut self) {}
-
-    pub unsafe fn notify_one(&self) {
-        if self.condvar.load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
-            let ret = abi::condvar_signal(
-                &self.condvar as *const AtomicU32 as *mut abi::condvar,
-                abi::scope::PRIVATE,
-                1,
-            );
-            assert_eq!(ret, abi::errno::SUCCESS, "Failed to signal on condition variable");
-        }
-    }
-
-    pub unsafe fn notify_all(&self) {
-        if self.condvar.load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
-            let ret = abi::condvar_signal(
-                &self.condvar as *const AtomicU32 as *mut abi::condvar,
-                abi::scope::PRIVATE,
-                abi::nthreads::MAX,
-            );
-            assert_eq!(ret, abi::errno::SUCCESS, "Failed to broadcast on condition variable");
-        }
-    }
-
-    pub unsafe fn wait(&self, mutex: &Mutex) {
-        let mutex = mutex::raw(mutex);
-        assert_eq!(
-            mutex.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
-            __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
-            "This lock is not write-locked by this thread"
-        );
-
-        // Call into the kernel to wait on the condition variable.
-        let subscription = abi::subscription {
-            type_: abi::eventtype::CONDVAR,
-            union: abi::subscription_union {
-                condvar: abi::subscription_condvar {
-                    condvar: &self.condvar as *const AtomicU32 as *mut abi::condvar,
-                    condvar_scope: abi::scope::PRIVATE,
-                    lock: mutex as *const AtomicU32 as *mut abi::lock,
-                    lock_scope: abi::scope::PRIVATE,
-                },
-            },
-            ..mem::zeroed()
-        };
-        let mut event: mem::MaybeUninit<abi::event> = mem::MaybeUninit::uninit();
-        let mut nevents: mem::MaybeUninit<usize> = mem::MaybeUninit::uninit();
-        let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr());
-        assert_eq!(ret, abi::errno::SUCCESS, "Failed to wait on condition variable");
-        assert_eq!(
-            event.assume_init().error,
-            abi::errno::SUCCESS,
-            "Failed to wait on condition variable"
-        );
-    }
-
-    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
-        let mutex = mutex::raw(mutex);
-        assert_eq!(
-            mutex.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
-            __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
-            "This lock is not write-locked by this thread"
-        );
-
-        // Call into the kernel to wait on the condition variable.
-        let timeout =
-            checked_dur2intervals(&dur).expect("overflow converting duration to nanoseconds");
-        let subscriptions = [
-            abi::subscription {
-                type_: abi::eventtype::CONDVAR,
-                union: abi::subscription_union {
-                    condvar: abi::subscription_condvar {
-                        condvar: &self.condvar as *const AtomicU32 as *mut abi::condvar,
-                        condvar_scope: abi::scope::PRIVATE,
-                        lock: mutex as *const AtomicU32 as *mut abi::lock,
-                        lock_scope: abi::scope::PRIVATE,
-                    },
-                },
-                ..mem::zeroed()
-            },
-            abi::subscription {
-                type_: abi::eventtype::CLOCK,
-                union: abi::subscription_union {
-                    clock: abi::subscription_clock {
-                        clock_id: abi::clockid::MONOTONIC,
-                        timeout,
-                        ..mem::zeroed()
-                    },
-                },
-                ..mem::zeroed()
-            },
-        ];
-        let mut events: [mem::MaybeUninit<abi::event>; 2] = [mem::MaybeUninit::uninit(); 2];
-        let mut nevents: mem::MaybeUninit<usize> = mem::MaybeUninit::uninit();
-        let ret = abi::poll(
-            subscriptions.as_ptr(),
-            mem::MaybeUninit::slice_as_mut_ptr(&mut events),
-            2,
-            nevents.as_mut_ptr(),
-        );
-        assert_eq!(ret, abi::errno::SUCCESS, "Failed to wait on condition variable");
-        let nevents = nevents.assume_init();
-        for i in 0..nevents {
-            assert_eq!(
-                events[i].assume_init().error,
-                abi::errno::SUCCESS,
-                "Failed to wait on condition variable"
-            );
-            if events[i].assume_init().type_ == abi::eventtype::CONDVAR {
-                return true;
-            }
-        }
-        false
-    }
-
-    pub unsafe fn destroy(&self) {
-        assert_eq!(
-            self.condvar.load(Ordering::Relaxed),
-            abi::CONDVAR_HAS_NO_WAITERS.0,
-            "Attempted to destroy a condition variable with blocked threads"
-        );
-    }
-}
diff --git a/library/std/src/sys/cloudabi/io.rs b/library/std/src/sys/cloudabi/io.rs
deleted file mode 100644 (file)
index d5f475b..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-use crate::mem;
-
-#[derive(Copy, Clone)]
-pub struct IoSlice<'a>(&'a [u8]);
-
-impl<'a> IoSlice<'a> {
-    #[inline]
-    pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
-        IoSlice(buf)
-    }
-
-    #[inline]
-    pub fn advance(&mut self, n: usize) {
-        self.0 = &self.0[n..]
-    }
-
-    #[inline]
-    pub fn as_slice(&self) -> &[u8] {
-        self.0
-    }
-}
-
-pub struct IoSliceMut<'a>(&'a mut [u8]);
-
-impl<'a> IoSliceMut<'a> {
-    #[inline]
-    pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
-        IoSliceMut(buf)
-    }
-
-    #[inline]
-    pub fn advance(&mut self, n: usize) {
-        let slice = mem::replace(&mut self.0, &mut []);
-        let (_, remaining) = slice.split_at_mut(n);
-        self.0 = remaining;
-    }
-
-    #[inline]
-    pub fn as_slice(&self) -> &[u8] {
-        self.0
-    }
-
-    #[inline]
-    pub fn as_mut_slice(&mut self) -> &mut [u8] {
-        self.0
-    }
-}
diff --git a/library/std/src/sys/cloudabi/mod.rs b/library/std/src/sys/cloudabi/mod.rs
deleted file mode 100644 (file)
index b4a9246..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-#![deny(unsafe_op_in_unsafe_fn)]
-
-use crate::io::ErrorKind;
-use crate::mem;
-
-#[path = "../unix/alloc.rs"]
-pub mod alloc;
-pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
-pub mod condvar;
-pub mod io;
-#[path = "../unix/memchr.rs"]
-pub mod memchr;
-pub mod mutex;
-pub mod os;
-pub mod rwlock;
-pub mod stack_overflow;
-pub mod stdio;
-pub mod thread;
-#[path = "../unix/thread_local_key.rs"]
-pub mod thread_local_key;
-pub mod time;
-
-pub use crate::sys_common::os_str_bytes as os_str;
-
-mod abi;
-
-mod shims;
-pub use self::shims::*;
-
-#[allow(dead_code)]
-pub fn init() {}
-
-pub fn decode_error_kind(errno: i32) -> ErrorKind {
-    match errno {
-        x if x == abi::errno::ACCES as i32 => ErrorKind::PermissionDenied,
-        x if x == abi::errno::ADDRINUSE as i32 => ErrorKind::AddrInUse,
-        x if x == abi::errno::ADDRNOTAVAIL as i32 => ErrorKind::AddrNotAvailable,
-        x if x == abi::errno::AGAIN as i32 => ErrorKind::WouldBlock,
-        x if x == abi::errno::CONNABORTED as i32 => ErrorKind::ConnectionAborted,
-        x if x == abi::errno::CONNREFUSED as i32 => ErrorKind::ConnectionRefused,
-        x if x == abi::errno::CONNRESET as i32 => ErrorKind::ConnectionReset,
-        x if x == abi::errno::EXIST as i32 => ErrorKind::AlreadyExists,
-        x if x == abi::errno::INTR as i32 => ErrorKind::Interrupted,
-        x if x == abi::errno::INVAL as i32 => ErrorKind::InvalidInput,
-        x if x == abi::errno::NOENT as i32 => ErrorKind::NotFound,
-        x if x == abi::errno::NOTCONN as i32 => ErrorKind::NotConnected,
-        x if x == abi::errno::PERM as i32 => ErrorKind::PermissionDenied,
-        x if x == abi::errno::PIPE as i32 => ErrorKind::BrokenPipe,
-        x if x == abi::errno::TIMEDOUT as i32 => ErrorKind::TimedOut,
-        _ => ErrorKind::Other,
-    }
-}
-
-pub fn abort_internal() -> ! {
-    core::intrinsics::abort();
-}
-
-pub use libc::strlen;
-
-pub fn hashmap_random_keys() -> (u64, u64) {
-    unsafe {
-        let mut v: mem::MaybeUninit<(u64, u64)> = mem::MaybeUninit::uninit();
-        libc::arc4random_buf(v.as_mut_ptr() as *mut libc::c_void, mem::size_of_val(&v));
-        v.assume_init()
-    }
-}
-
-#[cfg_attr(feature = "backtrace", link(name = "unwind"))]
-#[link(name = "c")]
-#[link(name = "compiler_rt")]
-extern "C" {}
diff --git a/library/std/src/sys/cloudabi/mutex.rs b/library/std/src/sys/cloudabi/mutex.rs
deleted file mode 100644 (file)
index 9dafcbc..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-use crate::cell::Cell;
-use crate::mem;
-use crate::mem::MaybeUninit;
-use crate::sync::atomic::{AtomicU32, Ordering};
-use crate::sys::cloudabi::abi;
-use crate::sys::rwlock::{self, RWLock};
-
-extern "C" {
-    #[thread_local]
-    static __pthread_thread_id: abi::tid;
-}
-
-// Implement Mutex using an RWLock. This doesn't introduce any
-// performance overhead in this environment, as the operations would be
-// implemented identically.
-pub struct Mutex(RWLock);
-
-pub type MovableMutex = Mutex;
-
-pub unsafe fn raw(m: &Mutex) -> &AtomicU32 {
-    rwlock::raw(&m.0)
-}
-
-impl Mutex {
-    pub const fn new() -> Mutex {
-        Mutex(RWLock::new())
-    }
-
-    pub unsafe fn init(&mut self) {
-        // This function should normally reinitialize the mutex after
-        // moving it to a different memory address. This implementation
-        // does not require adjustments after moving.
-    }
-
-    pub unsafe fn try_lock(&self) -> bool {
-        self.0.try_write()
-    }
-
-    pub unsafe fn lock(&self) {
-        self.0.write()
-    }
-
-    pub unsafe fn unlock(&self) {
-        self.0.write_unlock()
-    }
-
-    pub unsafe fn destroy(&self) {
-        self.0.destroy()
-    }
-}
-
-pub struct ReentrantMutex {
-    lock: AtomicU32,
-    recursion: Cell<u32>,
-}
-
-unsafe impl Send for ReentrantMutex {}
-unsafe impl Sync for ReentrantMutex {}
-
-impl ReentrantMutex {
-    pub const unsafe fn uninitialized() -> ReentrantMutex {
-        ReentrantMutex { lock: AtomicU32::new(abi::LOCK_UNLOCKED.0), recursion: Cell::new(0) }
-    }
-
-    pub unsafe fn init(&self) {}
-
-    pub unsafe fn try_lock(&self) -> bool {
-        // Attempt to acquire the lock.
-        if let Err(old) = self.lock.compare_exchange(
-            abi::LOCK_UNLOCKED.0,
-            __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
-            Ordering::Acquire,
-            Ordering::Relaxed,
-        ) {
-            // If we fail to acquire the lock, it may be the case
-            // that we've already acquired it and may need to recurse.
-            if old & !abi::LOCK_KERNEL_MANAGED.0 == __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0 {
-                self.recursion.set(self.recursion.get() + 1);
-                true
-            } else {
-                false
-            }
-        } else {
-            // Success.
-            assert_eq!(self.recursion.get(), 0, "Mutex has invalid recursion count");
-            true
-        }
-    }
-
-    pub unsafe fn lock(&self) {
-        if !self.try_lock() {
-            // Call into the kernel to acquire a write lock.
-            let lock = &self.lock as *const AtomicU32;
-            let subscription = abi::subscription {
-                type_: abi::eventtype::LOCK_WRLOCK,
-                union: abi::subscription_union {
-                    lock: abi::subscription_lock {
-                        lock: lock as *mut abi::lock,
-                        lock_scope: abi::scope::PRIVATE,
-                    },
-                },
-                ..mem::zeroed()
-            };
-            let mut event = MaybeUninit::<abi::event>::uninit();
-            let mut nevents = MaybeUninit::<usize>::uninit();
-            // SAFE: The caller must to ensure that `event` and `nevents` are initialized.
-            let ret =
-                unsafe { abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr()) };
-            assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire mutex");
-            let event = event.assume_init();
-            assert_eq!(event.error, abi::errno::SUCCESS, "Failed to acquire mutex");
-        }
-    }
-
-    pub unsafe fn unlock(&self) {
-        assert_eq!(
-            self.lock.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
-            __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
-            "This mutex is locked by a different thread"
-        );
-
-        let r = self.recursion.get();
-        if r > 0 {
-            self.recursion.set(r - 1);
-        } else if !self
-            .lock
-            .compare_exchange(
-                __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
-                abi::LOCK_UNLOCKED.0,
-                Ordering::Release,
-                Ordering::Relaxed,
-            )
-            .is_ok()
-        {
-            // Lock is managed by kernelspace. Call into the kernel
-            // to unblock waiting threads.
-            let ret = abi::lock_unlock(
-                &self.lock as *const AtomicU32 as *mut abi::lock,
-                abi::scope::PRIVATE,
-            );
-            assert_eq!(ret, abi::errno::SUCCESS, "Failed to unlock a mutex");
-        }
-    }
-
-    pub unsafe fn destroy(&self) {
-        assert_eq!(
-            self.lock.load(Ordering::Relaxed),
-            abi::LOCK_UNLOCKED.0,
-            "Attempted to destroy locked mutex"
-        );
-        assert_eq!(self.recursion.get(), 0, "Recursion counter invalid");
-    }
-}
diff --git a/library/std/src/sys/cloudabi/os.rs b/library/std/src/sys/cloudabi/os.rs
deleted file mode 100644 (file)
index 326faaa..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-use crate::ffi::CStr;
-use crate::str;
-
-use libc::c_int;
-
-pub use crate::sys::cloudabi::shims::os::*;
-
-pub fn errno() -> i32 {
-    extern "C" {
-        #[thread_local]
-        static errno: c_int;
-    }
-
-    unsafe { errno as i32 }
-}
-
-/// Gets a detailed string description for the given error number.
-pub fn error_string(errno: i32) -> String {
-    // cloudlibc's strerror() is guaranteed to be thread-safe. There is
-    // thus no need to use strerror_r().
-    str::from_utf8(unsafe { CStr::from_ptr(libc::strerror(errno)) }.to_bytes()).unwrap().to_owned()
-}
-
-pub fn exit(code: i32) -> ! {
-    unsafe { libc::exit(code as c_int) }
-}
diff --git a/library/std/src/sys/cloudabi/rwlock.rs b/library/std/src/sys/cloudabi/rwlock.rs
deleted file mode 100644 (file)
index 508de8b..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-use crate::mem;
-use crate::mem::MaybeUninit;
-use crate::sync::atomic::{AtomicU32, Ordering};
-use crate::sys::cloudabi::abi;
-
-extern "C" {
-    #[thread_local]
-    static __pthread_thread_id: abi::tid;
-}
-
-#[thread_local]
-static mut RDLOCKS_ACQUIRED: u32 = 0;
-
-pub struct RWLock {
-    lock: AtomicU32,
-}
-
-pub unsafe fn raw(r: &RWLock) -> &AtomicU32 {
-    &r.lock
-}
-
-unsafe impl Send for RWLock {}
-unsafe impl Sync for RWLock {}
-
-impl RWLock {
-    pub const fn new() -> RWLock {
-        RWLock { lock: AtomicU32::new(abi::LOCK_UNLOCKED.0) }
-    }
-
-    pub unsafe fn try_read(&self) -> bool {
-        let mut old = abi::LOCK_UNLOCKED.0;
-        while let Err(cur) =
-            self.lock.compare_exchange_weak(old, old + 1, Ordering::Acquire, Ordering::Relaxed)
-        {
-            if (cur & abi::LOCK_WRLOCKED.0) != 0 {
-                // Another thread already has a write lock.
-                assert_ne!(
-                    old & !abi::LOCK_KERNEL_MANAGED.0,
-                    __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
-                    "Attempted to acquire a read lock while holding a write lock"
-                );
-                return false;
-            } else if (old & abi::LOCK_KERNEL_MANAGED.0) != 0 && RDLOCKS_ACQUIRED == 0 {
-                // Lock has threads waiting for the lock. Only acquire
-                // the lock if we have already acquired read locks. In
-                // that case, it is justified to acquire this lock to
-                // prevent a deadlock.
-                return false;
-            }
-            old = cur;
-        }
-
-        RDLOCKS_ACQUIRED += 1;
-        true
-    }
-
-    pub unsafe fn read(&self) {
-        if !self.try_read() {
-            // Call into the kernel to acquire a read lock.
-            let subscription = abi::subscription {
-                type_: abi::eventtype::LOCK_RDLOCK,
-                union: abi::subscription_union {
-                    lock: abi::subscription_lock {
-                        lock: &self.lock as *const AtomicU32 as *mut abi::lock,
-                        lock_scope: abi::scope::PRIVATE,
-                    },
-                },
-                ..mem::zeroed()
-            };
-            let mut event = MaybeUninit::<abi::event>::uninit();
-            let mut nevents = MaybeUninit::<usize>::uninit();
-            let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr());
-            assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire read lock");
-            let event = event.assume_init();
-            assert_eq!(event.error, abi::errno::SUCCESS, "Failed to acquire read lock");
-
-            RDLOCKS_ACQUIRED += 1;
-        }
-    }
-
-    pub unsafe fn read_unlock(&self) {
-        // Perform a read unlock. We can do this in userspace, except when
-        // other threads are blocked and we are performing the last unlock.
-        // In that case, call into the kernel.
-        //
-        // Other threads may attempt to increment the read lock count,
-        // meaning that the call into the kernel could be spurious. To
-        // prevent this from happening, upgrade to a write lock first. This
-        // allows us to call into the kernel, having the guarantee that the
-        // lock value will not change in the meantime.
-        assert!(RDLOCKS_ACQUIRED > 0, "Bad lock count");
-        let mut old = 1;
-        loop {
-            if old == 1 | abi::LOCK_KERNEL_MANAGED.0 {
-                // Last read lock while threads are waiting. Attempt to upgrade
-                // to a write lock before calling into the kernel to unlock.
-                if let Err(cur) = self.lock.compare_exchange_weak(
-                    old,
-                    __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0 | abi::LOCK_KERNEL_MANAGED.0,
-                    Ordering::Acquire,
-                    Ordering::Relaxed,
-                ) {
-                    old = cur;
-                } else {
-                    // Call into the kernel to unlock.
-                    let ret = abi::lock_unlock(
-                        &self.lock as *const AtomicU32 as *mut abi::lock,
-                        abi::scope::PRIVATE,
-                    );
-                    assert_eq!(ret, abi::errno::SUCCESS, "Failed to write unlock a rwlock");
-                    break;
-                }
-            } else {
-                // No threads waiting or not the last read lock. Just decrement
-                // the read lock count.
-                assert_ne!(old & !abi::LOCK_KERNEL_MANAGED.0, 0, "This rwlock is not locked");
-                assert_eq!(
-                    old & abi::LOCK_WRLOCKED.0,
-                    0,
-                    "Attempted to read-unlock a write-locked rwlock"
-                );
-                if let Err(cur) = self.lock.compare_exchange_weak(
-                    old,
-                    old - 1,
-                    Ordering::Acquire,
-                    Ordering::Relaxed,
-                ) {
-                    old = cur;
-                } else {
-                    break;
-                }
-            }
-        }
-
-        RDLOCKS_ACQUIRED -= 1;
-    }
-
-    pub unsafe fn try_write(&self) -> bool {
-        // Attempt to acquire the lock.
-        if let Err(old) = self.lock.compare_exchange(
-            abi::LOCK_UNLOCKED.0,
-            __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
-            Ordering::Acquire,
-            Ordering::Relaxed,
-        ) {
-            // Failure. Crash upon recursive acquisition.
-            assert_ne!(
-                old & !abi::LOCK_KERNEL_MANAGED.0,
-                __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
-                "Attempted to recursive write-lock a rwlock",
-            );
-            false
-        } else {
-            // Success.
-            true
-        }
-    }
-
-    pub unsafe fn write(&self) {
-        if !self.try_write() {
-            // Call into the kernel to acquire a write lock.
-            let subscription = abi::subscription {
-                type_: abi::eventtype::LOCK_WRLOCK,
-                union: abi::subscription_union {
-                    lock: abi::subscription_lock {
-                        lock: &self.lock as *const AtomicU32 as *mut abi::lock,
-                        lock_scope: abi::scope::PRIVATE,
-                    },
-                },
-                ..mem::zeroed()
-            };
-            let mut event = MaybeUninit::<abi::event>::uninit();
-            let mut nevents = MaybeUninit::<usize>::uninit();
-            let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr());
-            assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire write lock");
-            let event = event.assume_init();
-            assert_eq!(event.error, abi::errno::SUCCESS, "Failed to acquire write lock");
-        }
-    }
-
-    pub unsafe fn write_unlock(&self) {
-        assert_eq!(
-            self.lock.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
-            __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
-            "This rwlock is not write-locked by this thread"
-        );
-
-        if !self
-            .lock
-            .compare_exchange(
-                __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
-                abi::LOCK_UNLOCKED.0,
-                Ordering::Release,
-                Ordering::Relaxed,
-            )
-            .is_ok()
-        {
-            // Lock is managed by kernelspace. Call into the kernel
-            // to unblock waiting threads.
-            let ret = abi::lock_unlock(
-                &self.lock as *const AtomicU32 as *mut abi::lock,
-                abi::scope::PRIVATE,
-            );
-            assert_eq!(ret, abi::errno::SUCCESS, "Failed to write unlock a rwlock");
-        }
-    }
-
-    pub unsafe fn destroy(&self) {
-        assert_eq!(
-            self.lock.load(Ordering::Relaxed),
-            abi::LOCK_UNLOCKED.0,
-            "Attempted to destroy locked rwlock"
-        );
-    }
-}
diff --git a/library/std/src/sys/cloudabi/shims/args.rs b/library/std/src/sys/cloudabi/shims/args.rs
deleted file mode 100644 (file)
index f5cf71c..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-use crate::ffi::OsString;
-
-pub struct Args(());
-
-impl Args {
-    pub fn inner_debug(&self) -> &[OsString] {
-        &[]
-    }
-}
-
-impl Iterator for Args {
-    type Item = OsString;
-    fn next(&mut self) -> Option<OsString> {
-        None
-    }
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (0, Some(0))
-    }
-}
-
-impl ExactSizeIterator for Args {
-    fn len(&self) -> usize {
-        0
-    }
-}
-
-impl DoubleEndedIterator for Args {
-    fn next_back(&mut self) -> Option<OsString> {
-        None
-    }
-}
-
-pub fn args() -> Args {
-    Args(())
-}
diff --git a/library/std/src/sys/cloudabi/shims/env.rs b/library/std/src/sys/cloudabi/shims/env.rs
deleted file mode 100644 (file)
index de165a8..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-pub mod os {
-    pub const FAMILY: &str = "cloudabi";
-    pub const OS: &str = "cloudabi";
-    pub const DLL_PREFIX: &str = "lib";
-    pub const DLL_SUFFIX: &str = ".so";
-    pub const DLL_EXTENSION: &str = "so";
-    pub const EXE_SUFFIX: &str = "";
-    pub const EXE_EXTENSION: &str = "";
-}
diff --git a/library/std/src/sys/cloudabi/shims/fs.rs b/library/std/src/sys/cloudabi/shims/fs.rs
deleted file mode 100644 (file)
index ecb5b51..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-use crate::ffi::OsString;
-use crate::fmt;
-use crate::hash::{Hash, Hasher};
-use crate::io::{self, IoSlice, IoSliceMut, SeekFrom};
-use crate::path::{Path, PathBuf};
-use crate::sys::time::SystemTime;
-use crate::sys::{unsupported, Void};
-
-pub struct File(Void);
-
-pub struct FileAttr(Void);
-
-pub struct ReadDir(Void);
-
-pub struct DirEntry(Void);
-
-#[derive(Clone, Debug)]
-pub struct OpenOptions {}
-
-pub struct FilePermissions(Void);
-
-pub struct FileType(Void);
-
-#[derive(Debug)]
-pub struct DirBuilder {}
-
-impl FileAttr {
-    pub fn size(&self) -> u64 {
-        match self.0 {}
-    }
-
-    pub fn perm(&self) -> FilePermissions {
-        match self.0 {}
-    }
-
-    pub fn file_type(&self) -> FileType {
-        match self.0 {}
-    }
-
-    pub fn modified(&self) -> io::Result<SystemTime> {
-        match self.0 {}
-    }
-
-    pub fn accessed(&self) -> io::Result<SystemTime> {
-        match self.0 {}
-    }
-
-    pub fn created(&self) -> io::Result<SystemTime> {
-        match self.0 {}
-    }
-}
-
-impl Clone for FileAttr {
-    fn clone(&self) -> FileAttr {
-        match self.0 {}
-    }
-}
-
-impl FilePermissions {
-    pub fn readonly(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn set_readonly(&mut self, _readonly: bool) {
-        match self.0 {}
-    }
-}
-
-impl Clone for FilePermissions {
-    fn clone(&self) -> FilePermissions {
-        match self.0 {}
-    }
-}
-
-impl PartialEq for FilePermissions {
-    fn eq(&self, _other: &FilePermissions) -> bool {
-        match self.0 {}
-    }
-}
-
-impl Eq for FilePermissions {}
-
-impl fmt::Debug for FilePermissions {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-impl FileType {
-    pub fn is_dir(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn is_file(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn is_symlink(&self) -> bool {
-        match self.0 {}
-    }
-}
-
-impl Clone for FileType {
-    fn clone(&self) -> FileType {
-        match self.0 {}
-    }
-}
-
-impl Copy for FileType {}
-
-impl PartialEq for FileType {
-    fn eq(&self, _other: &FileType) -> bool {
-        match self.0 {}
-    }
-}
-
-impl Eq for FileType {}
-
-impl Hash for FileType {
-    fn hash<H: Hasher>(&self, _h: &mut H) {
-        match self.0 {}
-    }
-}
-
-impl fmt::Debug for FileType {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-impl fmt::Debug for ReadDir {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-impl Iterator for ReadDir {
-    type Item = io::Result<DirEntry>;
-
-    fn next(&mut self) -> Option<io::Result<DirEntry>> {
-        match self.0 {}
-    }
-}
-
-impl DirEntry {
-    pub fn path(&self) -> PathBuf {
-        match self.0 {}
-    }
-
-    pub fn file_name(&self) -> OsString {
-        match self.0 {}
-    }
-
-    pub fn metadata(&self) -> io::Result<FileAttr> {
-        match self.0 {}
-    }
-
-    pub fn file_type(&self) -> io::Result<FileType> {
-        match self.0 {}
-    }
-}
-
-impl OpenOptions {
-    pub fn new() -> OpenOptions {
-        OpenOptions {}
-    }
-
-    pub fn read(&mut self, _read: bool) {}
-    pub fn write(&mut self, _write: bool) {}
-    pub fn append(&mut self, _append: bool) {}
-    pub fn truncate(&mut self, _truncate: bool) {}
-    pub fn create(&mut self, _create: bool) {}
-    pub fn create_new(&mut self, _create_new: bool) {}
-}
-
-impl File {
-    pub fn open(_path: &Path, _opts: &OpenOptions) -> io::Result<File> {
-        unsupported()
-    }
-
-    pub fn file_attr(&self) -> io::Result<FileAttr> {
-        match self.0 {}
-    }
-
-    pub fn fsync(&self) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn datasync(&self) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn truncate(&self, _size: u64) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn is_read_vectored(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn is_write_vectored(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn flush(&self) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
-        match self.0 {}
-    }
-
-    pub fn duplicate(&self) -> io::Result<File> {
-        match self.0 {}
-    }
-
-    pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn diverge(&self) -> ! {
-        match self.0 {}
-    }
-}
-
-impl DirBuilder {
-    pub fn new() -> DirBuilder {
-        DirBuilder {}
-    }
-
-    pub fn mkdir(&self, _p: &Path) -> io::Result<()> {
-        unsupported()
-    }
-}
-
-impl fmt::Debug for File {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
-    unsupported()
-}
-
-pub fn unlink(_p: &Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> {
-    match perm.0 {}
-}
-
-pub fn rmdir(_p: &Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub fn stat(_p: &Path) -> io::Result<FileAttr> {
-    unsupported()
-}
-
-pub fn lstat(_p: &Path) -> io::Result<FileAttr> {
-    unsupported()
-}
-
-pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn copy(_from: &Path, _to: &Path) -> io::Result<u64> {
-    unsupported()
-}
diff --git a/library/std/src/sys/cloudabi/shims/mod.rs b/library/std/src/sys/cloudabi/shims/mod.rs
deleted file mode 100644 (file)
index b1b5f14..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-use crate::io;
-
-pub mod args;
-pub mod env;
-pub mod fs;
-pub mod net;
-pub mod os;
-#[path = "../../unix/path.rs"]
-pub mod path;
-pub mod pipe;
-pub mod process;
-
-// This enum is used as the storage for a bunch of types which can't actually exist.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
-pub enum Void {}
-
-pub fn unsupported<T>() -> io::Result<T> {
-    Err(io::Error::new(io::ErrorKind::Other, "This function is not available on CloudABI."))
-}
diff --git a/library/std/src/sys/cloudabi/shims/net.rs b/library/std/src/sys/cloudabi/shims/net.rs
deleted file mode 100644 (file)
index 375aaab..0000000
+++ /dev/null
@@ -1,326 +0,0 @@
-use crate::convert::TryFrom;
-use crate::fmt;
-use crate::io::{self, IoSlice, IoSliceMut};
-use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
-use crate::sys::{unsupported, Void};
-use crate::time::Duration;
-
-#[allow(unused_extern_crates)]
-pub extern crate libc as netc;
-
-pub struct TcpStream(Void);
-
-impl TcpStream {
-    pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
-        unsupported()
-    }
-
-    pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
-        unsupported()
-    }
-
-    pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
-        match self.0 {}
-    }
-
-    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
-        match self.0 {}
-    }
-
-    pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn is_read_vectored(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn write(&self, _: &[u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn is_write_vectored(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
-    }
-
-    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
-    }
-
-    pub fn shutdown(&self, _: Shutdown) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn duplicate(&self) -> io::Result<TcpStream> {
-        match self.0 {}
-    }
-
-    pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn nodelay(&self) -> io::Result<bool> {
-        match self.0 {}
-    }
-
-    pub fn set_ttl(&self, _: u32) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn ttl(&self) -> io::Result<u32> {
-        match self.0 {}
-    }
-
-    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        match self.0 {}
-    }
-
-    pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
-    }
-}
-
-impl fmt::Debug for TcpStream {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-pub struct TcpListener(Void);
-
-impl TcpListener {
-    pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
-        unsupported()
-    }
-
-    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
-    }
-
-    pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
-        match self.0 {}
-    }
-
-    pub fn duplicate(&self) -> io::Result<TcpListener> {
-        match self.0 {}
-    }
-
-    pub fn set_ttl(&self, _: u32) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn ttl(&self) -> io::Result<u32> {
-        match self.0 {}
-    }
-
-    pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn only_v6(&self) -> io::Result<bool> {
-        match self.0 {}
-    }
-
-    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        match self.0 {}
-    }
-
-    pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
-    }
-}
-
-impl fmt::Debug for TcpListener {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-pub struct UdpSocket(Void);
-
-impl UdpSocket {
-    pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
-        unsupported()
-    }
-
-    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
-    }
-
-    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
-    }
-
-    pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
-        match self.0 {}
-    }
-
-    pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
-        match self.0 {}
-    }
-
-    pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn duplicate(&self) -> io::Result<UdpSocket> {
-        match self.0 {}
-    }
-
-    pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
-        match self.0 {}
-    }
-
-    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
-        match self.0 {}
-    }
-
-    pub fn set_broadcast(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn broadcast(&self) -> io::Result<bool> {
-        match self.0 {}
-    }
-
-    pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn multicast_loop_v4(&self) -> io::Result<bool> {
-        match self.0 {}
-    }
-
-    pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
-        match self.0 {}
-    }
-
-    pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn multicast_loop_v6(&self) -> io::Result<bool> {
-        match self.0 {}
-    }
-
-    pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn set_ttl(&self, _: u32) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn ttl(&self) -> io::Result<u32> {
-        match self.0 {}
-    }
-
-    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        match self.0 {}
-    }
-
-    pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn send(&self, _: &[u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
-        match self.0 {}
-    }
-}
-
-impl fmt::Debug for UdpSocket {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-pub struct LookupHost(Void);
-
-impl LookupHost {
-    pub fn port(&self) -> u16 {
-        match self.0 {}
-    }
-}
-
-impl Iterator for LookupHost {
-    type Item = SocketAddr;
-    fn next(&mut self) -> Option<SocketAddr> {
-        match self.0 {}
-    }
-}
-
-impl TryFrom<&str> for LookupHost {
-    type Error = io::Error;
-
-    fn try_from(_v: &str) -> io::Result<LookupHost> {
-        unsupported()
-    }
-}
-
-impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
-    type Error = io::Error;
-
-    fn try_from(_v: (&'a str, u16)) -> io::Result<LookupHost> {
-        unsupported()
-    }
-}
diff --git a/library/std/src/sys/cloudabi/shims/os.rs b/library/std/src/sys/cloudabi/shims/os.rs
deleted file mode 100644 (file)
index 779e6d5..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-use crate::error::Error as StdError;
-use crate::ffi::{OsStr, OsString};
-use crate::fmt;
-use crate::io;
-use crate::iter;
-use crate::path::{self, PathBuf};
-use crate::sys::{unsupported, Void};
-
-pub fn getcwd() -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn chdir(_: &path::Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub type Env = iter::Empty<(OsString, OsString)>;
-
-pub fn env() -> Env {
-    iter::empty()
-}
-
-pub fn getenv(_: &OsStr) -> io::Result<Option<OsString>> {
-    Ok(None)
-}
-
-pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
-    unsupported()
-}
-
-pub fn unsetenv(_: &OsStr) -> io::Result<()> {
-    unsupported()
-}
-
-pub struct SplitPaths<'a>(&'a Void);
-
-pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
-    panic!("unsupported")
-}
-
-impl<'a> Iterator for SplitPaths<'a> {
-    type Item = PathBuf;
-    fn next(&mut self) -> Option<PathBuf> {
-        match *self.0 {}
-    }
-}
-
-#[derive(Debug)]
-pub struct JoinPathsError;
-
-pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
-where
-    I: Iterator<Item = T>,
-    T: AsRef<OsStr>,
-{
-    Err(JoinPathsError)
-}
-
-impl fmt::Display for JoinPathsError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        "not supported on CloudABI yet".fmt(f)
-    }
-}
-
-impl StdError for JoinPathsError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "not supported on CloudABI yet"
-    }
-}
-
-pub fn home_dir() -> Option<PathBuf> {
-    None
-}
-
-pub fn temp_dir() -> PathBuf {
-    PathBuf::from("/tmp")
-}
-
-pub fn current_exe() -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn getpid() -> u32 {
-    1
-}
diff --git a/library/std/src/sys/cloudabi/shims/pipe.rs b/library/std/src/sys/cloudabi/shims/pipe.rs
deleted file mode 100644 (file)
index 10d0925..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-use crate::io::{self, IoSlice, IoSliceMut};
-use crate::sys::Void;
-
-pub struct AnonPipe(Void);
-
-impl AnonPipe {
-    pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn is_read_vectored(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn is_write_vectored(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn diverge(&self) -> ! {
-        match self.0 {}
-    }
-}
-
-pub fn read2(p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> {
-    match p1.0 {}
-}
diff --git a/library/std/src/sys/cloudabi/shims/process.rs b/library/std/src/sys/cloudabi/shims/process.rs
deleted file mode 100644 (file)
index 4702e5c..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-use crate::ffi::OsStr;
-use crate::fmt;
-use crate::io;
-use crate::sys::fs::File;
-use crate::sys::pipe::AnonPipe;
-use crate::sys::{unsupported, Void};
-use crate::sys_common::process::CommandEnv;
-
-pub use crate::ffi::OsString as EnvKey;
-
-////////////////////////////////////////////////////////////////////////////////
-// Command
-////////////////////////////////////////////////////////////////////////////////
-
-pub struct Command {
-    env: CommandEnv,
-}
-
-// passed back to std::process with the pipes connected to the child, if any
-// were requested
-pub struct StdioPipes {
-    pub stdin: Option<AnonPipe>,
-    pub stdout: Option<AnonPipe>,
-    pub stderr: Option<AnonPipe>,
-}
-
-pub enum Stdio {
-    Inherit,
-    Null,
-    MakePipe,
-}
-
-impl Command {
-    pub fn new(_program: &OsStr) -> Command {
-        Command { env: Default::default() }
-    }
-
-    pub fn arg(&mut self, _arg: &OsStr) {}
-
-    pub fn env_mut(&mut self) -> &mut CommandEnv {
-        &mut self.env
-    }
-
-    pub fn cwd(&mut self, _dir: &OsStr) {}
-
-    pub fn stdin(&mut self, _stdin: Stdio) {}
-
-    pub fn stdout(&mut self, _stdout: Stdio) {}
-
-    pub fn stderr(&mut self, _stderr: Stdio) {}
-
-    pub fn spawn(
-        &mut self,
-        _default: Stdio,
-        _needs_stdin: bool,
-    ) -> io::Result<(Process, StdioPipes)> {
-        unsupported()
-    }
-}
-
-impl From<AnonPipe> for Stdio {
-    fn from(pipe: AnonPipe) -> Stdio {
-        pipe.diverge()
-    }
-}
-
-impl From<File> for Stdio {
-    fn from(file: File) -> Stdio {
-        file.diverge()
-    }
-}
-
-impl fmt::Debug for Command {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        Ok(())
-    }
-}
-
-pub struct ExitStatus(Void);
-
-impl ExitStatus {
-    pub fn success(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn code(&self) -> Option<i32> {
-        match self.0 {}
-    }
-}
-
-impl Clone for ExitStatus {
-    fn clone(&self) -> ExitStatus {
-        match self.0 {}
-    }
-}
-
-impl Copy for ExitStatus {}
-
-impl PartialEq for ExitStatus {
-    fn eq(&self, _other: &ExitStatus) -> bool {
-        match self.0 {}
-    }
-}
-
-impl Eq for ExitStatus {}
-
-impl fmt::Debug for ExitStatus {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-impl fmt::Display for ExitStatus {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-#[derive(PartialEq, Eq, Clone, Copy, Debug)]
-pub struct ExitCode(bool);
-
-impl ExitCode {
-    pub const SUCCESS: ExitCode = ExitCode(false);
-    pub const FAILURE: ExitCode = ExitCode(true);
-
-    pub fn as_i32(&self) -> i32 {
-        self.0 as i32
-    }
-}
-
-pub struct Process(Void);
-
-impl Process {
-    pub fn id(&self) -> u32 {
-        match self.0 {}
-    }
-
-    pub fn kill(&mut self) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn wait(&mut self) -> io::Result<ExitStatus> {
-        match self.0 {}
-    }
-
-    pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
-        match self.0 {}
-    }
-}
diff --git a/library/std/src/sys/cloudabi/stack_overflow.rs b/library/std/src/sys/cloudabi/stack_overflow.rs
deleted file mode 100644 (file)
index 9339b14..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#![cfg_attr(test, allow(dead_code))]
-
-pub unsafe fn init() {}
-
-pub unsafe fn cleanup() {}
diff --git a/library/std/src/sys/cloudabi/stdio.rs b/library/std/src/sys/cloudabi/stdio.rs
deleted file mode 100644 (file)
index 7fec473..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-use crate::io;
-use crate::sys::cloudabi::abi;
-
-pub struct Stdin(());
-pub struct Stdout(());
-pub struct Stderr(());
-
-impl Stdin {
-    pub const fn new() -> Stdin {
-        Stdin(())
-    }
-}
-
-impl io::Read for Stdin {
-    fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
-        Ok(0)
-    }
-}
-
-impl Stdout {
-    pub const fn new() -> Stdout {
-        Stdout(())
-    }
-}
-
-impl io::Write for Stdout {
-    fn write(&mut self, _buf: &[u8]) -> io::Result<usize> {
-        Err(io::Error::new(
-            io::ErrorKind::BrokenPipe,
-            "Stdout is not connected to any output in this environment",
-        ))
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        Ok(())
-    }
-}
-
-impl Stderr {
-    pub const fn new() -> Stderr {
-        Stderr(())
-    }
-}
-
-impl io::Write for Stderr {
-    fn write(&mut self, _buf: &[u8]) -> io::Result<usize> {
-        Err(io::Error::new(
-            io::ErrorKind::BrokenPipe,
-            "Stderr is not connected to any output in this environment",
-        ))
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        Ok(())
-    }
-}
-
-pub fn is_ebadf(err: &io::Error) -> bool {
-    err.raw_os_error() == Some(abi::errno::BADF as i32)
-}
-
-pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
-
-pub fn panic_output() -> Option<impl io::Write> {
-    Some(Stderr::new())
-}
diff --git a/library/std/src/sys/cloudabi/thread.rs b/library/std/src/sys/cloudabi/thread.rs
deleted file mode 100644 (file)
index a15dc86..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-use crate::cmp;
-use crate::ffi::CStr;
-use crate::io;
-use crate::mem;
-use crate::ptr;
-use crate::sys::cloudabi::abi;
-use crate::sys::time::checked_dur2intervals;
-use crate::time::Duration;
-
-pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
-
-pub struct Thread {
-    id: libc::pthread_t,
-}
-
-// CloudABI has pthread_t as a pointer in which case we still want
-// a thread to be Send/Sync
-unsafe impl Send for Thread {}
-unsafe impl Sync for Thread {}
-
-impl Thread {
-    // unsafe: see thread::Builder::spawn_unchecked for safety requirements
-    pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
-        let p = Box::into_raw(box p);
-        let mut native: libc::pthread_t = mem::zeroed();
-        let mut attr: libc::pthread_attr_t = mem::zeroed();
-        assert_eq!(libc::pthread_attr_init(&mut attr), 0);
-
-        let stack_size = cmp::max(stack, min_stack_size(&attr));
-        assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0);
-
-        let ret = libc::pthread_create(&mut native, &attr, thread_start, p as *mut _);
-        // Note: if the thread creation fails and this assert fails, then p will
-        // be leaked. However, an alternative design could cause double-free
-        // which is clearly worse.
-        assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
-
-        return if ret != 0 {
-            // The thread failed to start and as a result p was not consumed. Therefore, it is
-            // safe to reconstruct the box so that it gets deallocated.
-            drop(Box::from_raw(p));
-            Err(io::Error::from_raw_os_error(ret))
-        } else {
-            Ok(Thread { id: native })
-        };
-
-        extern "C" fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void {
-            unsafe {
-                // Let's run some code.
-                Box::from_raw(main as *mut Box<dyn FnOnce()>)();
-            }
-            ptr::null_mut()
-        }
-    }
-
-    pub fn yield_now() {
-        let ret = unsafe { abi::thread_yield() };
-        debug_assert_eq!(ret, abi::errno::SUCCESS);
-    }
-
-    pub fn set_name(_name: &CStr) {
-        // CloudABI has no way to set a thread name.
-    }
-
-    pub fn sleep(dur: Duration) {
-        let timeout =
-            checked_dur2intervals(&dur).expect("overflow converting duration to nanoseconds");
-        unsafe {
-            let subscription = abi::subscription {
-                type_: abi::eventtype::CLOCK,
-                union: abi::subscription_union {
-                    clock: abi::subscription_clock {
-                        clock_id: abi::clockid::MONOTONIC,
-                        timeout,
-                        ..mem::zeroed()
-                    },
-                },
-                ..mem::zeroed()
-            };
-            let mut event = mem::MaybeUninit::<abi::event>::uninit();
-            let mut nevents = mem::MaybeUninit::<usize>::uninit();
-            let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr());
-            assert_eq!(ret, abi::errno::SUCCESS);
-            let event = event.assume_init();
-            assert_eq!(event.error, abi::errno::SUCCESS);
-        }
-    }
-
-    pub fn join(self) {
-        unsafe {
-            let ret = libc::pthread_join(self.id, ptr::null_mut());
-            mem::forget(self);
-            assert!(ret == 0, "failed to join thread: {}", io::Error::from_raw_os_error(ret));
-        }
-    }
-}
-
-impl Drop for Thread {
-    fn drop(&mut self) {
-        let ret = unsafe { libc::pthread_detach(self.id) };
-        debug_assert_eq!(ret, 0);
-    }
-}
-
-#[cfg_attr(test, allow(dead_code))]
-pub mod guard {
-    pub type Guard = !;
-    pub unsafe fn current() -> Option<Guard> {
-        None
-    }
-    pub unsafe fn init() -> Option<Guard> {
-        None
-    }
-}
-
-fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
-    libc::PTHREAD_STACK_MIN
-}
diff --git a/library/std/src/sys/cloudabi/time.rs b/library/std/src/sys/cloudabi/time.rs
deleted file mode 100644 (file)
index c209231..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-use crate::mem;
-use crate::sys::cloudabi::abi;
-use crate::time::Duration;
-
-const NSEC_PER_SEC: abi::timestamp = 1_000_000_000;
-
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
-pub struct Instant {
-    t: abi::timestamp,
-}
-
-pub fn checked_dur2intervals(dur: &Duration) -> Option<abi::timestamp> {
-    dur.as_secs().checked_mul(NSEC_PER_SEC)?.checked_add(dur.subsec_nanos() as abi::timestamp)
-}
-
-impl Instant {
-    pub fn now() -> Instant {
-        unsafe {
-            let mut t: mem::MaybeUninit<abi::timestamp> = mem::MaybeUninit::uninit();
-            let ret = abi::clock_time_get(abi::clockid::MONOTONIC, 0, t.as_mut_ptr());
-            assert_eq!(ret, abi::errno::SUCCESS);
-            Instant { t: t.assume_init() }
-        }
-    }
-
-    pub fn actually_monotonic() -> bool {
-        true
-    }
-
-    pub const fn zero() -> Instant {
-        Instant { t: 0 }
-    }
-
-    pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
-        let diff = self.t.checked_sub(other.t)?;
-        Some(Duration::new(diff / NSEC_PER_SEC, (diff % NSEC_PER_SEC) as u32))
-    }
-
-    pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
-        Some(Instant { t: self.t.checked_add(checked_dur2intervals(other)?)? })
-    }
-
-    pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
-        Some(Instant { t: self.t.checked_sub(checked_dur2intervals(other)?)? })
-    }
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
-pub struct SystemTime {
-    t: abi::timestamp,
-}
-
-impl SystemTime {
-    pub fn now() -> SystemTime {
-        unsafe {
-            let mut t: mem::MaybeUninit<abi::timestamp> = mem::MaybeUninit::uninit();
-            let ret = abi::clock_time_get(abi::clockid::REALTIME, 0, t.as_mut_ptr());
-            assert_eq!(ret, abi::errno::SUCCESS);
-            SystemTime { t: t.assume_init() }
-        }
-    }
-
-    pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
-        if self.t >= other.t {
-            let diff = self.t - other.t;
-            Ok(Duration::new(diff / NSEC_PER_SEC, (diff % NSEC_PER_SEC) as u32))
-        } else {
-            let diff = other.t - self.t;
-            Err(Duration::new(diff / NSEC_PER_SEC, (diff % NSEC_PER_SEC) as u32))
-        }
-    }
-
-    pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
-        Some(SystemTime { t: self.t.checked_add(checked_dur2intervals(other)?)? })
-    }
-
-    pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
-        Some(SystemTime { t: self.t.checked_sub(checked_dur2intervals(other)?)? })
-    }
-}
-
-pub const UNIX_EPOCH: SystemTime = SystemTime { t: 0 };
index 829d4c943f11b2b33d743def77331af5136e1270..1807655e97170cd2973e72fffbbc22cba7a370b1 100644 (file)
@@ -377,11 +377,11 @@ pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
     unsupported()
 }
 
-pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> {
+pub fn symlink(_original: &Path, _link: &Path) -> io::Result<()> {
     unsupported()
 }
 
-pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
+pub fn link(_original: &Path, _link: &Path) -> io::Result<()> {
     unsupported()
 }
 
index b4628b649117ed6b353afd45025a9d697e3da818..d48d9cb0efce02c63dedfe7ecd86269bed2e9aa3 100644 (file)
@@ -32,9 +32,6 @@
     } else if #[cfg(windows)] {
         mod windows;
         pub use self::windows::*;
-    } else if #[cfg(target_os = "cloudabi")] {
-        mod cloudabi;
-        pub use self::cloudabi::*;
     } else if #[cfg(target_os = "hermit")] {
         mod hermit;
         pub use self::hermit::*;
         // On unix we'll document what's already available
         #[stable(feature = "rust1", since = "1.0.0")]
         pub use self::ext as unix_ext;
-    } else if #[cfg(any(target_os = "cloudabi",
-                        target_os = "hermit",
+    } else if #[cfg(any(target_os = "hermit",
                         target_arch = "wasm32",
                         all(target_vendor = "fortanix", target_env = "sgx")))] {
-        // On CloudABI and wasm right now the module below doesn't compile
+        // On wasm right now the module below doesn't compile
         // (missing things in `libc` which is empty) so just omit everything
         // with an empty module
         #[unstable(issue = "none", feature = "std_internals")]
@@ -88,11 +84,10 @@ pub mod unix_ext {}
         #[allow(missing_docs)]
         #[stable(feature = "rust1", since = "1.0.0")]
         pub use self::ext as windows_ext;
-    } else if #[cfg(any(target_os = "cloudabi",
-                        target_os = "hermit",
+    } else if #[cfg(any(target_os = "hermit",
                         target_arch = "wasm32",
                         all(target_vendor = "fortanix", target_env = "sgx")))] {
-        // On CloudABI and wasm right now the shim below doesn't compile, so
+        // On wasm right now the shim below doesn't compile, so
         // just omit it
         #[unstable(issue = "none", feature = "std_internals")]
         #[allow(missing_docs)]
index f79874a4aec9724b6432b029ba356710ce668ed5..795a4d190cf4ebab7c060b53fa323a7079f5ad28 100644 (file)
@@ -25,8 +25,11 @@ pub trait AsRawFd {
 /// descriptor.
 #[unstable(feature = "sgx_platform", issue = "56975")]
 pub trait FromRawFd {
+    /// An associated type that contains relevant metadata for `Self`.
+    type Metadata: Default;
+
     /// Constructs a new instance of `Self` from the given raw file
-    /// descriptor.
+    /// descriptor and metadata.
     ///
     /// This function **consumes ownership** of the specified file
     /// descriptor. The returned object will take responsibility for closing
@@ -38,7 +41,7 @@ pub trait FromRawFd {
     /// accidentally allow violating this contract which can cause memory
     /// unsafety in code that relies on it being true.
     #[unstable(feature = "sgx_platform", issue = "56975")]
-    unsafe fn from_raw_fd(fd: RawFd) -> Self;
+    unsafe fn from_raw_fd(fd: RawFd, metadata: Self::Metadata) -> Self;
 }
 
 /// A trait to express the ability to consume an object and acquire ownership of
@@ -71,18 +74,40 @@ fn as_raw_fd(&self) -> RawFd {
     }
 }
 
+/// Metadata for `TcpStream`.
+#[derive(Debug, Clone, Default)]
+#[unstable(feature = "sgx_platform", issue = "56975")]
+pub struct TcpStreamMetadata {
+    /// Local address of the TCP stream
+    pub local_addr: Option<String>,
+    /// Peer address of the TCP stream
+    pub peer_addr: Option<String>,
+}
+
 impl FromRawFd for net::TcpStream {
-    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
+    type Metadata = TcpStreamMetadata;
+
+    unsafe fn from_raw_fd(fd: RawFd, metadata: Self::Metadata) -> net::TcpStream {
         let fd = sys::fd::FileDesc::from_inner(fd);
-        let socket = sys::net::Socket::from_inner(fd);
-        net::TcpStream::from_inner(sys::net::TcpStream::from_inner((socket, None)))
+        let socket = sys::net::Socket::from_inner((fd, metadata.local_addr));
+        net::TcpStream::from_inner(sys::net::TcpStream::from_inner((socket, metadata.peer_addr)))
     }
 }
 
+/// Metadata for `TcpListener`.
+#[derive(Debug, Clone, Default)]
+#[unstable(feature = "sgx_platform", issue = "56975")]
+pub struct TcpListenerMetadata {
+    /// Local address of the TCP listener
+    pub local_addr: Option<String>,
+}
+
 impl FromRawFd for net::TcpListener {
-    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
+    type Metadata = TcpListenerMetadata;
+
+    unsafe fn from_raw_fd(fd: RawFd, metadata: Self::Metadata) -> net::TcpListener {
         let fd = sys::fd::FileDesc::from_inner(fd);
-        let socket = sys::net::Socket::from_inner(fd);
+        let socket = sys::net::Socket::from_inner((fd, metadata.local_addr));
         net::TcpListener::from_inner(sys::net::TcpListener::from_inner(socket))
     }
 }
index 666a157b09cd0e88ebaf79709bbc0b5a164d015e..3dd8267921e5e3153d0000f6592202e187677d9a 100644 (file)
@@ -37,9 +37,9 @@ fn try_into_inner(self) -> Result<FileDesc, Socket> {
     }
 }
 
-impl FromInner<FileDesc> for Socket {
-    fn from_inner(inner: FileDesc) -> Socket {
-        Socket { inner: Arc::new(inner), local_addr: None }
+impl FromInner<(FileDesc, Option<String>)> for Socket {
+    fn from_inner((inner, local_addr): (FileDesc, Option<String>)) -> Socket {
+        Socket { inner: Arc::new(inner), local_addr }
     }
 }
 
index 66bbc1c585413906067b8372804ffd948f978829..ba75b9bac803593006ffb16b3e2af83604975b91 100644 (file)
@@ -841,7 +841,7 @@ fn ino(&self) -> u64 {
 
 /// Creates a new symbolic link on the filesystem.
 ///
-/// The `dst` path will be a symbolic link pointing to the `src` path.
+/// The `link` path will be a symbolic link pointing to the `original` path.
 ///
 /// # Examples
 ///
@@ -854,8 +854,8 @@ fn ino(&self) -> u64 {
 /// }
 /// ```
 #[stable(feature = "symlink", since = "1.1.0")]
-pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
-    sys::fs::symlink(src.as_ref(), dst.as_ref())
+pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
+    sys::fs::symlink(original.as_ref(), link.as_ref())
 }
 
 /// Unix-specific extensions to [`fs::DirBuilder`].
index 13cf930379cbca9666c2ecd6e7750e04a0b51b71..e2f0870ef0e398c5ee06ee82ede85d157f301c5a 100644 (file)
@@ -1071,28 +1071,28 @@ pub fn readlink(p: &Path) -> io::Result<PathBuf> {
     }
 }
 
-pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
-    let src = cstr(src)?;
-    let dst = cstr(dst)?;
-    cvt(unsafe { libc::symlink(src.as_ptr(), dst.as_ptr()) })?;
+pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
+    let original = cstr(original)?;
+    let link = cstr(link)?;
+    cvt(unsafe { libc::symlink(original.as_ptr(), link.as_ptr()) })?;
     Ok(())
 }
 
-pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
-    let src = cstr(src)?;
-    let dst = cstr(dst)?;
+pub fn link(original: &Path, link: &Path) -> io::Result<()> {
+    let original = cstr(original)?;
+    let link = cstr(link)?;
     cfg_if::cfg_if! {
         if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android"))] {
             // VxWorks, Redox, and old versions of Android lack `linkat`, so use
             // `link` instead. POSIX leaves it implementation-defined whether
             // `link` follows symlinks, so rely on the `symlink_hard_link` test
             // in library/std/src/fs/tests.rs to check the behavior.
-            cvt(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })?;
+            cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?;
         } else {
             // Use `linkat` with `AT_FDCWD` instead of `link` as `linkat` gives
             // us a flag to specify how symlinks should be handled. Pass 0 as
             // the flags argument, meaning don't follow symlinks.
-            cvt(unsafe { libc::linkat(libc::AT_FDCWD, src.as_ptr(), libc::AT_FDCWD, dst.as_ptr(), 0) })?;
+            cvt(unsafe { libc::linkat(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?;
         }
     }
     Ok(())
index 53d95dca4cd8272b27f3f1894db27e230d0320b8..e93a4972caa3ed9b43d19627e6926460ee5159de 100644 (file)
@@ -135,7 +135,7 @@ unsafe fn $name($($arg_name:$t),*) -> $ret {
             } else {
                 syscall(
                     concat_idents!(SYS_, $name),
-                    $($arg_name as c_long),*
+                    $($arg_name),*
                 ) as $ret
             }
         }
index faa53b6a74422ddff884dec7a850c37252798d58..4271d9b334588b888d8cbca52a9e0ad2aba2c15c 100644 (file)
@@ -279,7 +279,7 @@ pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
     unsupported()
 }
 
-pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> {
+pub fn symlink(_original: &Path, _link: &Path) -> io::Result<()> {
     unsupported()
 }
 
index 93a92b49cfc01bad1b8b663b0d5ee6715f681052..120b9f59f1e991e48aa05e571ef641db0d62734e 100644 (file)
@@ -549,19 +549,19 @@ fn read_link(fd: &WasiFd, file: &Path) -> io::Result<PathBuf> {
     }
 }
 
-pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
-    let (dst, dst_file) = open_parent(dst)?;
-    dst.symlink(osstr2str(src.as_ref())?, osstr2str(dst_file.as_ref())?)
+pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
+    let (link, link_file) = open_parent(link)?;
+    link.symlink(osstr2str(original.as_ref())?, osstr2str(link_file.as_ref())?)
 }
 
-pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
-    let (src, src_file) = open_parent(src)?;
-    let (dst, dst_file) = open_parent(dst)?;
-    src.link(
+pub fn link(original: &Path, link: &Path) -> io::Result<()> {
+    let (original, original_file) = open_parent(original)?;
+    let (link, link_file) = open_parent(link)?;
+    original.link(
         wasi::LOOKUPFLAGS_SYMLINK_FOLLOW,
-        osstr2str(src_file.as_ref())?,
-        &dst,
-        osstr2str(dst_file.as_ref())?,
+        osstr2str(original_file.as_ref())?,
+        &link,
+        osstr2str(link_file.as_ref())?,
     )
 }
 
index 3f25f05e1b9a7e479ce7f8cd766af19e9a532cf8..dd1523b422ccb945b5f1638f4f7389f8d7cc75a6 100644 (file)
@@ -90,6 +90,7 @@ pub unsafe fn call($($argname: $argtype),*) -> $rettype {
             }
         }
 
+        $(#[$meta])*
         pub use $symbol::call as $symbol;
     )*)
 }
index e0615f2d33431953283a15a23a7b8ab135bb3647..b20eafb4d53a59396a629ea903fda96b33e5e7a0 100644 (file)
@@ -519,7 +519,7 @@ fn is_symlink_file(&self) -> bool {
 
 /// Creates a new file symbolic link on the filesystem.
 ///
-/// The `dst` path will be a file symbolic link pointing to the `src`
+/// The `link` path will be a file symbolic link pointing to the `original`
 /// path.
 ///
 /// # Examples
@@ -533,13 +533,13 @@ fn is_symlink_file(&self) -> bool {
 /// }
 /// ```
 #[stable(feature = "symlink", since = "1.1.0")]
-pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
-    sys::fs::symlink_inner(src.as_ref(), dst.as_ref(), false)
+pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
+    sys::fs::symlink_inner(original.as_ref(), link.as_ref(), false)
 }
 
 /// Creates a new directory symlink on the filesystem.
 ///
-/// The `dst` path will be a directory symbolic link pointing to the `src`
+/// The `link` path will be a directory symbolic link pointing to the `original`
 /// path.
 ///
 /// # Examples
@@ -553,6 +553,6 @@ pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Resul
 /// }
 /// ```
 #[stable(feature = "symlink", since = "1.1.0")]
-pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
-    sys::fs::symlink_inner(src.as_ref(), dst.as_ref(), true)
+pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
+    sys::fs::symlink_inner(original.as_ref(), link.as_ref(), true)
 }
index cdbfac267b9a1ac60722998f49df00165116f88b..307a47678c6a2832c94f53eccdfdf2fc563983d0 100644 (file)
@@ -759,13 +759,13 @@ pub fn readlink(path: &Path) -> io::Result<PathBuf> {
     file.readlink()
 }
 
-pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
-    symlink_inner(src, dst, false)
+pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
+    symlink_inner(original, link, false)
 }
 
-pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> {
-    let src = to_u16s(src)?;
-    let dst = to_u16s(dst)?;
+pub fn symlink_inner(original: &Path, link: &Path, dir: bool) -> io::Result<()> {
+    let original = to_u16s(original)?;
+    let link = to_u16s(link)?;
     let flags = if dir { c::SYMBOLIC_LINK_FLAG_DIRECTORY } else { 0 };
     // Formerly, symlink creation required the SeCreateSymbolicLink privilege. For the Windows 10
     // Creators Update, Microsoft loosened this to allow unprivileged symlink creation if the
@@ -773,8 +773,8 @@ pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> {
     // added to dwFlags to opt into this behaviour.
     let result = cvt(unsafe {
         c::CreateSymbolicLinkW(
-            dst.as_ptr(),
-            src.as_ptr(),
+            link.as_ptr(),
+            original.as_ptr(),
             flags | c::SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE,
         ) as c::BOOL
     });
@@ -782,7 +782,9 @@ pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> {
         if err.raw_os_error() == Some(c::ERROR_INVALID_PARAMETER as i32) {
             // Older Windows objects to SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE,
             // so if we encounter ERROR_INVALID_PARAMETER, retry without that flag.
-            cvt(unsafe { c::CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) as c::BOOL })?;
+            cvt(unsafe {
+                c::CreateSymbolicLinkW(link.as_ptr(), original.as_ptr(), flags) as c::BOOL
+            })?;
         } else {
             return Err(err);
         }
@@ -791,15 +793,15 @@ pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> {
 }
 
 #[cfg(not(target_vendor = "uwp"))]
-pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
-    let src = to_u16s(src)?;
-    let dst = to_u16s(dst)?;
-    cvt(unsafe { c::CreateHardLinkW(dst.as_ptr(), src.as_ptr(), ptr::null_mut()) })?;
+pub fn link(original: &Path, link: &Path) -> io::Result<()> {
+    let original = to_u16s(original)?;
+    let link = to_u16s(link)?;
+    cvt(unsafe { c::CreateHardLinkW(link.as_ptr(), original.as_ptr(), ptr::null_mut()) })?;
     Ok(())
 }
 
 #[cfg(target_vendor = "uwp")]
-pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
+pub fn link(_original: &Path, _link: &Path) -> io::Result<()> {
     return Err(io::Error::new(io::ErrorKind::Other, "hard link are not supported on UWP"));
 }
 
@@ -883,8 +885,11 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
 }
 
 #[allow(dead_code)]
-pub fn symlink_junction<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
-    symlink_junction_inner(src.as_ref(), dst.as_ref())
+pub fn symlink_junction<P: AsRef<Path>, Q: AsRef<Path>>(
+    original: P,
+    junction: Q,
+) -> io::Result<()> {
+    symlink_junction_inner(original.as_ref(), junction.as_ref())
 }
 
 // Creating a directory junction on windows involves dealing with reparse
@@ -893,7 +898,7 @@ pub fn symlink_junction<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::R
 //
 // http://www.flexhex.com/docs/articles/hard-links.phtml
 #[allow(dead_code)]
-fn symlink_junction_inner(target: &Path, junction: &Path) -> io::Result<()> {
+fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> {
     let d = DirBuilder::new();
     d.mkdir(&junction)?;
 
@@ -911,7 +916,7 @@ fn symlink_junction_inner(target: &Path, junction: &Path) -> io::Result<()> {
         // FIXME: this conversion is very hacky
         let v = br"\??\";
         let v = v.iter().map(|x| *x as u16);
-        for c in v.chain(target.as_os_str().encode_wide()) {
+        for c in v.chain(original.as_os_str().encode_wide()) {
             *buf.offset(i) = c;
             i += 1;
         }
index 234b257aa926e834666398a9a27796e05b12a871..660f0e0df973235455333c6a86cc418241d6def5 100644 (file)
@@ -71,8 +71,7 @@ macro_rules! rtunwrap {
 pub mod wtf8;
 
 cfg_if::cfg_if! {
-    if #[cfg(any(target_os = "cloudabi",
-                 target_os = "l4re",
+    if #[cfg(any(target_os = "l4re",
                  target_os = "hermit",
                  feature = "restricted-std",
                  all(target_arch = "wasm32", not(target_os = "emscripten")),
index 4e805e4f599a85239aa3f01b1ec72afa37d2fbfb..64a5f89890a31d48a54a6f6ad139d77ab7105bb6 100644 (file)
@@ -70,7 +70,6 @@ struct SYSTEM_INFO {
         }
     } else if #[cfg(any(
         target_os = "android",
-        target_os = "cloudabi",
         target_os = "emscripten",
         target_os = "fuchsia",
         target_os = "ios",
index e433f69a8b0bb4066ce975b04b9fc8cebbc724c1..89addae078948708f7abfe574a21c575760588ec 100644 (file)
@@ -83,7 +83,6 @@
 ///
 /// |  Platform |               System call                                            |
 /// |:---------:|:--------------------------------------------------------------------:|
-/// | CloudABI  | [clock_time_get (Monotonic Clock)]                                   |
 /// | SGX       | [`insecure_time` usercall]. More information on [timekeeping in SGX] |
 /// | UNIX      | [clock_gettime (Monotonic Clock)]                                    |
 /// | Darwin    | [mach_absolute_time]                                                 |
@@ -97,7 +96,6 @@
 /// [__wasi_clock_time_get (Monotonic Clock)]: https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/docs.md#clock_time_get
 /// [clock_gettime (Monotonic Clock)]: https://linux.die.net/man/3/clock_gettime
 /// [mach_absolute_time]: https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/services/services.html
-/// [clock_time_get (Monotonic Clock)]: https://nuxi.nl/cloudabi/#clock_time_get
 ///
 /// **Disclaimer:** These system calls might change over time.
 ///
 ///
 /// |  Platform |               System call                                            |
 /// |:---------:|:--------------------------------------------------------------------:|
-/// | CloudABI  | [clock_time_get (Realtime Clock)]                                    |
 /// | SGX       | [`insecure_time` usercall]. More information on [timekeeping in SGX] |
 /// | UNIX      | [clock_gettime (Realtime Clock)]                                     |
 /// | Darwin    | [gettimeofday]                                                       |
 /// | WASI      | [__wasi_clock_time_get (Realtime Clock)]                             |
 /// | Windows   | [GetSystemTimePreciseAsFileTime] / [GetSystemTimeAsFileTime]         |
 ///
-/// [clock_time_get (Realtime Clock)]: https://nuxi.nl/cloudabi/#clock_time_get
 /// [`insecure_time` usercall]: https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#method.insecure_time
 /// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode
 /// [gettimeofday]: http://man7.org/linux/man-pages/man2/gettimeofday.2.html
index 3d6910b107dd5a8377020f58039748229e68c7b1..d5804cc3dd86274a3e82bf1cde7ad4a58dd5257c 100644 (file)
@@ -26,6 +26,8 @@ default = ["std_detect_file_io", "std_detect_dlsym_getauxval", "panic-unwind"]
 backtrace = ["std/backtrace"]
 compiler-builtins-c = ["std/compiler-builtins-c"]
 compiler-builtins-mem = ["std/compiler-builtins-mem"]
+compiler-builtins-asm = ["std/compiler-builtins-asm"]
+compiler-builtins-mangled-names = ["std/compiler-builtins-mangled-names"]
 llvm-libunwind = ["std/llvm-libunwind"]
 system-llvm-libunwind = ["std/system-llvm-libunwind"]
 panic-unwind = ["std/panic_unwind"]
index 816b4d51188034cf97afea7097942b04df5113f5..5c12a54eef1208e83fcbc63fae0ab31712d4b568 100644 (file)
 #![crate_name = "test"]
 #![unstable(feature = "test", issue = "50297")]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))]
-#![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc))]
+#![cfg_attr(unix, feature(libc))]
 #![feature(rustc_private)]
 #![feature(nll)]
-#![feature(bool_to_option)]
 #![feature(available_concurrency)]
 #![feature(internal_output_capture)]
 #![feature(panic_unwind)]
@@ -266,14 +265,14 @@ fn get_timed_out_tests(running_tests: &mut TestMap) -> Vec<TestDesc> {
             running_tests.remove(test);
         }
         timed_out
-    };
+    }
 
     fn calc_timeout(running_tests: &TestMap) -> Option<Duration> {
         running_tests.values().min().map(|next_timeout| {
             let now = Instant::now();
             if *next_timeout >= now { *next_timeout - now } else { Duration::new(0, 0) }
         })
-    };
+    }
 
     if concurrency == 1 {
         while !remaining.is_empty() {
index 24bcd40c3a8eee89af9fe84691754af102debe56..fae760c4a4e6b814ef3a551ffa022c726c180fbf 100644 (file)
@@ -44,8 +44,6 @@ fn main() {
         println!("cargo:rustc-link-lib=gcc_s");
     } else if target.contains("redox") {
         // redox is handled in lib.rs
-    } else if target.contains("cloudabi") {
-        println!("cargo:rustc-link-lib=unwind");
     }
 }
 
index dbdefa471a9ed24a44268a3f2f9e459953ac2e5d..d145c6767ec267d5f3a04d9cc0127d07060d4f74 100644 (file)
@@ -20,7 +20,6 @@
         unix,
         windows,
         target_os = "psp",
-        target_os = "cloudabi",
         all(target_vendor = "fortanix", target_env = "sgx"),
     ))] {
         mod libunwind;
index 2b1c516cf7720aa947f5014062ee934eb8031b1c..45cce186c09969b9dc597b6da531c63438a96f6c 100644 (file)
@@ -32,7 +32,4 @@ ignore = [
     "src/tools/rust-analyzer",
     "src/tools/rustfmt",
     "src/tools/rust-installer",
-
-    # We do not format this file as it is externally sourced and auto-generated.
-    "library/std/src/sys/cloudabi/abi/cloudabi.rs",
 ]
index 4fb58034ce2166ceb061f83a25365213eb1538db..a819e1b6e2f1ebe1c53e520fa13a35cf756fea74 100644 (file)
@@ -437,12 +437,15 @@ class RustBuild(object):
             #
             # This works even in a repository that has not yet initialized
             # submodules.
+            top_level = subprocess.check_output([
+                "git", "rev-parse", "--show-toplevel",
+            ]).decode(sys.getdefaultencoding()).strip()
             llvm_sha = subprocess.check_output([
                 "git", "log", "--author=bors", "--format=%H", "-n1",
                 "-m", "--first-parent",
                 "--",
-                "src/llvm-project",
-                "src/bootstrap/download-ci-llvm-stamp",
+                "{}/src/llvm-project".format(top_level),
+                "{}/src/bootstrap/download-ci-llvm-stamp".format(top_level),
             ]).decode(sys.getdefaultencoding()).strip()
             llvm_assertions = self.get_toml('assertions', 'llvm') == 'true'
             if self.program_out_of_date(self.llvm_stamp(), llvm_sha + str(llvm_assertions)):
index 94319a6d1e9e2d06680eee52d4fe1cd28dae204f..9fcbe8e1e3564c7a67948d6025b0a927d3531dc3 100644 (file)
@@ -152,6 +152,7 @@ pub struct Config {
     // misc
     pub low_priority: bool,
     pub channel: String,
+    pub description: Option<String>,
     pub verbose_tests: bool,
     pub save_toolstates: Option<PathBuf>,
     pub print_step_timings: bool,
@@ -280,8 +281,8 @@ pub struct Target {
     pub ranlib: Option<PathBuf>,
     pub linker: Option<PathBuf>,
     pub ndk: Option<PathBuf>,
-    pub sanitizers: bool,
-    pub profiler: bool,
+    pub sanitizers: Option<bool>,
+    pub profiler: Option<bool>,
     pub crt_static: Option<bool>,
     pub musl_root: Option<PathBuf>,
     pub musl_libdir: Option<PathBuf>,
@@ -470,6 +471,7 @@ struct Rust {
     parallel_compiler: Option<bool>,
     default_linker: Option<String>,
     channel: Option<String>,
+    description: Option<String>,
     musl_root: Option<String>,
     rpath: Option<bool>,
     verbose_tests: Option<bool>,
@@ -841,6 +843,7 @@ pub fn parse(args: &[String]) -> Config {
                 .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));
             set(&mut config.backtrace, rust.backtrace);
             set(&mut config.channel, rust.channel);
+            config.description = rust.description;
             set(&mut config.rust_dist_src, rust.dist_src);
             set(&mut config.verbose_tests, rust.verbose_tests);
             // in the case "false" is set explicitly, do not overwrite the command line args
@@ -896,8 +899,8 @@ pub fn parse(args: &[String]) -> Config {
                 target.musl_libdir = cfg.musl_libdir.map(PathBuf::from);
                 target.wasi_root = cfg.wasi_root.map(PathBuf::from);
                 target.qemu_rootfs = cfg.qemu_rootfs.map(PathBuf::from);
-                target.sanitizers = cfg.sanitizers.unwrap_or(build.sanitizers.unwrap_or_default());
-                target.profiler = cfg.profiler.unwrap_or(build.profiler.unwrap_or_default());
+                target.sanitizers = cfg.sanitizers;
+                target.profiler = cfg.profiler;
 
                 config.target_config.insert(TargetSelection::from_user(&triple), target);
             }
@@ -1008,19 +1011,19 @@ pub fn very_verbose(&self) -> bool {
     }
 
     pub fn sanitizers_enabled(&self, target: TargetSelection) -> bool {
-        self.target_config.get(&target).map(|t| t.sanitizers).unwrap_or(self.sanitizers)
+        self.target_config.get(&target).map(|t| t.sanitizers).flatten().unwrap_or(self.sanitizers)
     }
 
     pub fn any_sanitizers_enabled(&self) -> bool {
-        self.target_config.values().any(|t| t.sanitizers) || self.sanitizers
+        self.target_config.values().any(|t| t.sanitizers == Some(true)) || self.sanitizers
     }
 
     pub fn profiler_enabled(&self, target: TargetSelection) -> bool {
-        self.target_config.get(&target).map(|t| t.profiler).unwrap_or(self.profiler)
+        self.target_config.get(&target).map(|t| t.profiler).flatten().unwrap_or(self.profiler)
     }
 
     pub fn any_profiler_enabled(&self) -> bool {
-        self.target_config.values().any(|t| t.profiler) || self.profiler
+        self.target_config.values().any(|t| t.profiler == Some(true)) || self.profiler
     }
 
     pub fn llvm_enabled(&self) -> bool {
index 322e9d6923295fbc11d70747969fb459687caabc..42f00ce9621743cb3a283355074b07a10b7f4e77 100755 (executable)
@@ -146,6 +146,7 @@ v("qemu-riscv64-rootfs", "target.riscv64gc-unknown-linux-gnu.qemu-rootfs",
 v("experimental-targets", "llvm.experimental-targets",
   "experimental LLVM targets to build")
 v("release-channel", "rust.channel", "the name of the release channel to build")
+v("release-description", "rust.description", "optional descriptive string for version output")
 
 # Used on systems where "cc" is unavailable
 v("default-linker", "rust.default-linker", "the default linker")
index ca140b9d278287911d6277f84cb7d25d4c698f9b..06ccd72186dd1edf67f8139cb4883911710a9c65 100644 (file)
@@ -1082,7 +1082,13 @@ fn llvm_link_tools_dynamically(&self, target: TargetSelection) -> bool {
     /// Note that this is a descriptive string which includes the commit date,
     /// sha, version, etc.
     fn rust_version(&self) -> String {
-        self.rust_info.version(self, &self.version)
+        let mut version = self.rust_info.version(self, &self.version);
+        if let Some(ref s) = self.config.description {
+            version.push_str(" (");
+            version.push_str(s);
+            version.push_str(")");
+        }
+        version
     }
 
     /// Returns the full commit hash.
index 60808dcba6144ac950d9188fc260a1bf6d058574..e087e2b8ff1531b952c35dcc5a6e7736af7467ad 100644 (file)
@@ -484,10 +484,13 @@ fn run(self, builder: &Builder<'_>) {
         let host = self.host;
         let compiler = builder.compiler(0, host);
 
+        // We need `ToolStd` for the locally-built sysroot because
+        // compiletest uses unstable features of the `test` crate.
+        builder.ensure(compile::Std { compiler, target: host });
         let cargo = tool::prepare_tool_cargo(
             builder,
             compiler,
-            Mode::ToolBootstrap,
+            Mode::ToolStd,
             host,
             "test",
             "src/tools/compiletest",
index f866a24287f9e6d9aed7b0758bd4ee258f37ee1c..f78d2b7d1e843272e6c0d2832736acaf436e2931 100755 (executable)
@@ -14,9 +14,11 @@ SYSROOT=/usr/local/$TARGET/sysroot
 mkdir -p $SYSROOT
 pushd $SYSROOT
 
-centos_base=http://vault.centos.org/altarch/7.3.1611/os/ppc64le/Packages/
-glibc_v=2.17-157.el7
-kernel_v=3.10.0-514.el7
+# centos_base=http://vault.centos.org/altarch/7.3.1611/os/ppc64le/Packages/
+# Mirrored from centos_base above
+centos_base=https://ci-mirrors.rust-lang.org/rustc
+glibc_v=2.17-157-2020-11-25.el7
+kernel_v=3.10.0-514-2020-11-25.el7
 for package in glibc{,-devel,-headers}-$glibc_v kernel-headers-$kernel_v; do
   curl $centos_base/$package.ppc64le.rpm | \
     rpm2cpio - | cpio -idm
diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-cloudabi-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-cloudabi-toolchain.sh
deleted file mode 100755 (executable)
index b7ff6cd..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/bash
-
-set -eux
-
-# Install prerequisites.
-apt-get update
-apt-get install -y --no-install-recommends \
-  apt-transport-https \
-  ca-certificates \
-  clang-5.0 \
-  cmake \
-  curl \
-  file \
-  g++ \
-  gdb \
-  git \
-  lld-5.0 \
-  make \
-  ninja-build \
-  python \
-  sudo \
-  xz-utils
-
-# Set up a Clang-based cross compiler toolchain.
-# Based on the steps described at https://nuxi.nl/cloudabi/debian/
-target=$1
-for tool in ar nm objdump ranlib size; do
-  ln -s ../lib/llvm-5.0/bin/llvm-${tool} /usr/bin/${target}-${tool}
-done
-ln -s ../lib/llvm-5.0/bin/clang /usr/bin/${target}-cc
-ln -s ../lib/llvm-5.0/bin/clang /usr/bin/${target}-c++
-ln -s ../lib/llvm-5.0/bin/lld /usr/bin/${target}-ld
-ln -s ../../${target} /usr/lib/llvm-5.0/${target}
-
-# Install the C++ runtime libraries from CloudABI Ports.
-apt-key adv --batch --yes --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 0DA51B8531344B15
-add-apt-repository -y 'deb https://nuxi.nl/distfiles/cloudabi-ports/debian/ cloudabi cloudabi'
-
-apt-get update
-apt-get install -y "${target//_/-}-cxx-runtime"
index 57013e9194bc110d070bf463ef69f5d4b00f0139..dd1986157366761f28b60fce17dfa48d20f07bb3 100644 (file)
@@ -18,4 +18,5 @@
     - [Known Issues](targets/known-issues.md)
 - [Profile-guided Optimization](profile-guided-optimization.md)
 - [Linker-plugin based LTO](linker-plugin-lto.md)
+- [Exploit Mitigations](exploit-mitigations.md)
 - [Contributing to `rustc`](contributing.md)
diff --git a/src/doc/rustc/src/exploit-mitigations.md b/src/doc/rustc/src/exploit-mitigations.md
new file mode 100644 (file)
index 0000000..44d5d95
--- /dev/null
@@ -0,0 +1,693 @@
+# Exploit Mitigations
+
+This chapter documents the exploit mitigations supported by the Rust
+compiler, and is by no means an extensive survey of the Rust programming
+language’s security features.
+
+This chapter is for software engineers working with the Rust programming
+language, and assumes prior knowledge of the Rust programming language and
+its toolchain.
+
+
+## Introduction
+
+The Rust programming language provides memory[1] and thread[2] safety
+guarantees via its ownership[3], references and borrowing[4], and slice
+types[5] features. However, Unsafe Rust[6] introduces unsafe blocks, unsafe
+functions and methods, unsafe traits, and new types that are not subject to
+the borrowing rules.
+
+Parts of the Rust standard library are implemented as safe abstractions over
+unsafe code (and historically have been vulnerable to memory corruption[7]).
+Furthermore, the Rust code and documentation encourage creating safe
+abstractions over unsafe code. This can cause a false sense of security if
+unsafe code is not properly reviewed and tested.
+
+Unsafe Rust introduces features that do not provide the same memory and
+thread safety guarantees. This causes programs or libraries to be
+susceptible to memory corruption (CWE-119)[8] and concurrency issues
+(CWE-557)[9]. Modern C and C++ compilers provide exploit mitigations to
+increase the difficulty to exploit vulnerabilities resulting from these
+issues. Therefore, the Rust compiler must also support these exploit
+mitigations in order to mitigate vulnerabilities resulting from the use of
+Unsafe Rust. This chapter documents these exploit mitigations and how they
+apply to Rust.
+
+This chapter does not discuss the effectiveness of these exploit mitigations
+as they vary greatly depending on several factors besides their design and
+implementation, but rather describe what they do, so their effectiveness can
+be understood within a given context.
+
+
+## Exploit mitigations
+
+This section documents the exploit mitigations applicable to the Rust
+compiler when building programs for the Linux operating system on the AMD64
+architecture and equivalent.<sup id="fnref:1" role="doc-noteref"><a
+href="#fn:1" class="footnote">1</a></sup>
+
+The Rust Programming Language currently has no specification. The Rust
+compiler (i.e., rustc) is the language reference implementation. All
+references to “the Rust compiler” in this chapter refer to the language
+reference implementation.
+
+Table I \
+Summary of exploit mitigations supported by the Rust compiler when building
+programs for the Linux operating system on the AMD64 architecture and
+equivalent.
+<table class="table">
+  <tr>
+   <td><strong>Exploit mitigation</strong>
+   </td>
+   <td><strong>Supported and enabled by default</strong>
+   </td>
+   <td><strong>Since</strong>
+   </td>
+  </tr>
+  <tr>
+   <td>Position-independent executable
+   </td>
+   <td>Yes
+   </td>
+   <td>0.12.0 (2014-10-09)
+   </td>
+  </tr>
+  <tr>
+   <td>Integer overflow checks
+   </td>
+   <td>Yes (enabled when debug assertions are enabled, and disabled when debug assertions are disabled)
+   </td>
+   <td>1.1.0 (2015-06-25)
+   </td>
+  </tr>
+  <tr>
+   <td>Non-executable memory regions
+   </td>
+   <td>Yes
+   </td>
+   <td>1.8.0 (2016-04-14)
+   </td>
+  </tr>
+  <tr>
+   <td>Stack clashing protection
+   </td>
+   <td>Yes
+   </td>
+   <td>1.20.0 (2017-08-31)
+   </td>
+  </tr>
+  <tr>
+   <td>Read-only relocations and immediate binding
+   </td>
+   <td>Yes
+   </td>
+   <td>1.21.0 (2017-10-12)
+   </td>
+  </tr>
+  <tr>
+   <td>Heap corruption protection
+   </td>
+   <td>Yes
+   </td>
+   <td>1.32.0 (2019-01-17) (via operating system default or specified allocator)
+   </td>
+  </tr>
+  <tr>
+   <td>Stack smashing protection
+   </td>
+   <td>No
+   </td>
+   <td>
+   </td>
+  </tr>
+  <tr>
+   <td>Forward-edge control flow protection
+   </td>
+   <td>No
+   </td>
+   <td>
+   </td>
+  </tr>
+  <tr>
+   <td>Backward-edge control flow protection (e.g., shadow and safe stack)
+   </td>
+   <td>No
+   </td>
+   <td>
+   </td>
+  </tr>
+</table>
+
+<small id="fn:1">1\. See
+<https://github.com/rust-lang/rust/tree/master/compiler/rustc_target/src/spec>
+for a list of targets and their default options. <a href="#fnref:1"
+class="reversefootnote" role="doc-backlink">↩</a></small>
+
+
+### Position-independent executable
+
+Position-independent executable increases the difficulty of the use of code
+reuse exploitation techniques, such as return-oriented programming (ROP) and
+variants, by generating position-independent code for the executable, and
+instructing the dynamic linker to load it similarly to a shared object at a
+random load address, thus also benefiting from address-space layout
+randomization (ASLR). This is also referred to as “full ASLR”.
+
+The Rust compiler supports position-independent executable, and enables it
+by default since version 0.12.0 (2014-10-09)[10]–[13].
+
+```text
+$ readelf -h target/release/hello-rust | grep Type:
+  Type:                              DYN (Shared object file)
+```
+Fig. 1. Checking if an executable is a position-independent executable.
+
+An executable with an object type of `ET_DYN` (i.e., shared object) and not
+`ET_EXEC` (i.e., executable) is a position-independent executable (see Fig.
+1).
+
+
+### Integer overflow checks
+
+Integer overflow checks protects programs from undefined and unintended
+behavior (which may cause vulnerabilities) by checking for results of signed
+and unsigned integer computations that cannot be represented in their type,
+resulting in an overflow or wraparound.
+
+The Rust compiler supports integer overflow checks, and enables it when
+debug assertions are enabled since version 1.1.0 (2015-06-25)[14]–[20].
+
+```compile_fail
+fn main() {
+    let u: u8 = 255;
+    println!("u: {}", u + 1);
+}
+```
+Fig. 2. hello-rust-integer program.
+
+```text
+$ cargo run
+   Compiling hello-rust-integer v0.1.0 (/home/rcvalle/hello-rust-integer)
+    Finished dev [unoptimized + debuginfo] target(s) in 0.23s
+     Running `target/debug/hello-rust-integer`
+thread 'main' panicked at 'attempt to add with overflow', src/main.rs:3:23
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
+```
+Fig. 3. Build and execution of hello-rust-integer with debug assertions
+enabled.
+
+```text
+$ cargo run --release
+   Compiling hello-rust-integer v0.1.0 (/home/rcvalle/hello-rust-integer)
+    Finished release [optimized] target(s) in 0.23s
+     Running `target/release/hello-rust-integer`
+u: 0
+```
+Fig. 4. Build and execution of hello-rust-integer with debug assertions
+disabled.
+
+Integer overflow checks are enabled when debug assertions are enabled (see
+Fig. 3), and disabled when debug assertions are disabled (see Fig. 4). To
+enable integer overflow checks independently, use the option to control
+integer overflow checks, scoped attributes, or explicit checking methods
+such as `checked_add`<sup id="fnref:2" role="doc-noteref"><a href="#fn:2"
+class="footnote">2</a></sup>.
+
+It is recommended that explicit wrapping methods such as `wrapping_add` be
+used when wrapping semantics are intended, and that explicit checking and
+wrapping methods always be used when using Unsafe Rust.
+
+<small id="fn:2">2\. See <https://doc.rust-lang.org/std/primitive.u32.html>
+for more information on the checked, overflowing, saturating, and wrapping
+methods (using u32 as an example). <a href="#fnref:2"
+class="reversefootnote" role="doc-backlink">↩</a></small>
+
+
+### Non-executable memory regions
+
+Non-executable memory regions increase the difficulty of exploitation by
+limiting the memory regions that can be used to execute arbitrary code. Most
+modern processors provide support for the operating system to mark memory
+regions as non executable, but it was previously emulated by software, such
+as in grsecurity/PaX's
+[PAGEEXEC](https://pax.grsecurity.net/docs/pageexec.txt) and
+[SEGMEXEC](https://pax.grsecurity.net/docs/segmexec.txt), on processors that
+did not provide support for it. This is also known as “No Execute (NX) Bit”,
+“Execute Disable (XD) Bit”, “Execute Never (XN) Bit”, and others.
+
+The Rust compiler supports non-executable memory regions, and enables it by
+default since its initial release, version 0.1 (2012-01-20)[21], [22], but
+has regressed since then[23]–[25], and enforced by default since version
+1.8.0 (2016-04-14)[25].
+
+```text
+$ readelf -l target/release/hello-rust | grep -A 1 GNU_STACK
+  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
+                 0x0000000000000000 0x0000000000000000  RW     0x10
+```
+Fig. 5. Checking if non-executable memory regions are enabled for a given
+binary.
+
+The presence of an element of type `PT_GNU_STACK` in the program header
+table with the `PF_X` (i.e., executable) flag unset indicates non-executable
+memory regions<sup id="fnref:3" role="doc-noteref"><a href="#fn:3"
+class="footnote">3</a></sup> are enabled for a given binary (see Fig. 5).
+Conversely, the presence of an element of type `PT_GNU_STACK` in the program
+header table with the `PF_X` flag set or the absence of an element of type
+`PT_GNU_STACK` in the program header table indicates non-executable memory
+regions are not enabled for a given binary.
+
+<small id="fn:3">3\. See the Appendix section for more information on why it
+affects other memory regions besides the stack. <a href="#fnref:3"
+class="reversefootnote" role="doc-backlink">↩</a></small>
+
+
+### Stack clashing protection
+
+Stack clashing protection protects the stack from overlapping with another
+memory region—allowing arbitrary data in both to be overwritten using each
+other—by reading from the stack pages as the stack grows to cause a page
+fault when attempting to read from the guard page/region. This is also
+referred to as “stack probes” or “stack probing”.
+
+The Rust compiler supports stack clashing protection via stack probing, and
+enables it by default since version 1.20.0 (2017-08-31)[26]–[29].
+
+![Screenshot of IDA Pro listing cross references to __rust_probestack in hello-rust.](images/image1.png "Cross references to __rust_probestack in hello-rust.")
+Fig. 6. IDA Pro listing cross references to `__rust_probestack` in
+hello-rust.
+
+```rust
+fn hello() {
+    println!("Hello, world!");
+}
+
+fn main() {
+    let _: [u64; 1024] = [0; 1024];
+    hello();
+}
+```
+Fig 7. Modified hello-rust.
+
+![Screenshot of IDA Pro listing cross references to __rust_probestack in modified hello-rust.](images/image2.png "Cross references to __rust_probestack in modified hello-rust.")
+Fig. 8. IDA Pro listing cross references to `__rust_probestack` in modified
+hello-rust.
+
+To check if stack clashing protection is enabled for a given binary, search
+for cross references to `__rust_probestack`. The `__rust_probestack` is
+called in the prologue of functions whose stack size is larger than a page
+size (see Fig. 6), and can be forced for illustration purposes by modifying
+the hello-rust example as seen in Fig. 7 and Fig. 8.
+
+
+### Read-only relocations and immediate binding
+
+**Read-only relocations** protect segments containing relocations and
+relocation information (i.e., `.init_array`, `.fini_array`, `.dynamic`, and
+`.got`) from being overwritten by marking these segments read only. This is
+also referred to as “partial RELRO”.
+
+The Rust compiler supports read-only relocations, and enables it by default
+since version 1.21.0 (2017-10-12)[30], [31].
+
+```text
+$ readelf -l target/release/hello-rust | grep GNU_RELRO
+  GNU_RELRO      0x000000000002ee00 0x000000000002fe00 0x000000000002fe00
+```
+Fig. 9. Checking if read-only relocations is enabled for a given binary.
+
+The presence of an element of type `PT_GNU_RELRO` in the program header
+table indicates read-only relocations are enabled for a given binary (see
+Fig. 9). Conversely, the absence of an element of type `PT_GNU_RELRO` in the
+program header table indicates read-only relocations are not enabled for a
+given binary.
+
+**Immediate binding** protects additional segments containing relocations
+(i.e., `.got.plt`) from being overwritten by instructing the dynamic linker
+to perform all relocations before transferring control to the program during
+startup, so all segments containing relocations can be marked read only
+(when combined with read-only relocations). This is also referred to as
+“full RELRO”.
+
+The Rust compiler supports immediate binding, and enables it by default
+since version 1.21.0 (2017-10-12)[30], [31].
+
+```text
+$ readelf -d target/release/hello-rust | grep BIND_NOW
+ 0x000000000000001e (FLAGS)              BIND_NOW
+```
+Fig. 10. Checking if immediate binding is enabled for a given binary.
+
+The presence of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW`
+flag<sup id="fnref:4" role="doc-noteref"><a href="#fn:4"
+class="footnote">4</a></sup> in the dynamic section indicates immediate
+binding is enabled for a given binary (see Fig. 10). Conversely, the absence
+of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` flag in the
+dynamic section indicates immediate binding is not enabled for a given
+binary.
+
+The presence of both an element of type `PT_GNU_RELRO` in the program header
+table and of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW`
+flag in the dynamic section indicates full RELRO is enabled for a given
+binary (see Fig. 9 and Fig. 10).
+
+<small id="fn:4">4\. And the `DF_1_NOW` flag for some link editors. <a
+href="#fnref:4" class="reversefootnote" role="doc-backlink">↩</a></small>
+
+
+### Heap corruption protection
+
+Heap corruption protection protects memory allocated dynamically by
+performing several checks, such as checks for corrupted links between list
+elements, invalid pointers, invalid sizes, double/multiple “frees” of the
+same memory allocated, and many corner cases of these. These checks are
+implementation specific, and vary per allocator.
+
+[ARM Memory Tagging Extension
+(MTE)](https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/enhancing-memory-safety),
+when available, will provide hardware assistance for a probabilistic
+mitigation to detect memory safety violations by tagging memory allocations,
+and automatically checking that the correct tag is used on every memory
+access.
+
+Rust’s default allocator has historically been
+[jemalloc](http://jemalloc.net/), and it has long been the cause of issues
+and the subject of much discussion[32]–[38]. Consequently, it has been
+removed as the default allocator in favor of the operating system’s standard
+C library default allocator<sup id="fnref:5" role="doc-noteref"><a
+href="#fn:5" class="footnote">5</a></sup> since version 1.32.0
+(2019-01-17)[39].
+
+```ignore
+fn main() {
+    let mut x = Box::new([0; 1024]);
+
+    for i in 0..1026 {
+        unsafe {
+            let elem = x.get_unchecked_mut(i);
+            *elem = 0x4141414141414141u64;
+        }
+    }
+}
+```
+Fig. 11. hello-rust-heap program.
+
+```text
+$ cargo run
+   Compiling hello-rust-heap v0.1.0 (/home/rcvalle/hello-rust-heap)
+    Finished dev [unoptimized + debuginfo] target(s) in 0.25s
+     Running `target/debug/hello-rust-heap`
+free(): invalid next size (normal)
+Aborted
+```
+Fig. 12. Build and execution of hello-rust-heap with debug assertions
+enabled.
+
+```text
+$ cargo run --release
+   Compiling hello-rust-heap v0.1.0 (/home/rcvalle/hello-rust-heap)
+    Finished release [optimized] target(s) in 0.25s
+     Running `target/release/hello-rust-heap`
+free(): invalid next size (normal)
+Aborted
+```
+Fig. 13. Build and execution of hello-rust-heap with debug assertions
+disabled.
+
+Heap corruption checks are being performed when using the default allocator
+(i.e., the GNU Allocator) as seen in Fig. 12 and Fig. 13.
+
+<small id="fn:5">5\. Linux's standard C library default allocator is the GNU
+Allocator, which is derived from ptmalloc (pthreads malloc) by Wolfram
+Gloger, which in turn is derived from dlmalloc (Doug Lea malloc) by Doug
+Lea. <a href="#fnref:5" class="reversefootnote"
+role="doc-backlink">↩</a></small>
+
+
+### Stack smashing protection
+
+Stack smashing protection protects programs from stack-based buffer
+overflows by inserting a random guard value between local variables and the
+saved return instruction pointer, and checking if this value has changed
+when returning from a function. This is also known as “Stack Protector” or
+“Stack Smashing Protector (SSP)”.
+
+The Rust compiler does not support stack smashing protection. However, more
+comprehensive alternatives to stack smashing protection exist, such as
+shadow and safe stack (see backward-edge control flow protection).
+
+![Screenshot of IDA Pro listing cross references to __stack_chk_fail in hello-rust.](images/image3.png "Cross references to __stack_chk_fail in hello-rust.")
+Fig. 14. IDA Pro listing cross references to `__stack_chk_fail` in
+hello-rust.
+
+To check if stack smashing protection is enabled for a given binary, search
+for cross references to `__stack_chk_fail`. The only cross references to
+`__stack_chk_fail` in hello-rust are from the statically-linked libbacktrace
+library (see Fig. 14).
+
+
+### Forward-edge control flow protection
+
+Forward-edge control flow protection protects programs from having its
+control flow changed/hijacked by performing checks to ensure that
+destinations of indirect branches are one of their valid destinations in the
+control flow graph. The comprehensiveness of these checks vary per
+implementation. This is also known as “forward-edge control flow integrity
+(CFI)”.
+
+Newer processors provide hardware assistance for forward-edge control flow
+protection, such as ARM Branch Target Identification (BTI), ARM Pointer
+Authentication, and Intel Indirect Branch Tracking (IBT) as part of Intel
+Control-flow Enforcement Technology (CET). However, ARM BTI and Intel IBT
+-based implementations are less comprehensive than software-based
+implementations such as [LLVM ControlFlowIntegrity
+(CFI)](https://clang.llvm.org/docs/ControlFlowIntegrity.html), and the
+commercially available [grsecurity/PaX Reuse Attack Protector
+(RAP)](https://grsecurity.net/rap_faq).
+
+The Rust compiler does not support forward-edge control flow protection on
+Linux<sup id="fnref:6" role="doc-noteref"><a href="#fn:6"
+class="footnote">6</a></sup>. There is work currently ongoing to add support
+for the [sanitizers](https://github.com/google/sanitizers)[40], which may or
+may not include support for LLVM CFI.
+
+```text
+$ readelf -s target/release/hello-rust | grep __cfi_init
+```
+Fig. 15. Checking if LLVM CFI is enabled for a given binary.
+
+The presence of the `__cfi_init` symbol (and references to `__cfi_check`)
+indicates that LLVM CFI (i.e., forward-edge control flow protection) is
+enabled for a given binary. Conversely, the absence of the `__cfi_init`
+symbol (and references to `__cfi_check`) indicates that LLVM CFI is not
+enabled for a given binary (see Fig. 15).
+
+<small id="fn:6">6\. It supports Control Flow Guard (CFG) on Windows (see
+<https://github.com/rust-lang/rust/issues/68793>). <a href="#fnref:6"
+class="reversefootnote" role="doc-backlink">↩</a></small>
+
+
+### Backward-edge control flow protection
+
+**Shadow stack** protects saved return instruction pointers from being
+overwritten by storing a copy of them on a separate (shadow) stack, and
+using these copies as authoritative values when returning from functions.
+This is also known as “ShadowCallStack” and “Return Flow Guard”, and is
+considered an implementation of backward-edge control flow protection (or
+“backward-edge CFI”).
+
+**Safe stack** protects not only the saved return instruction pointers, but
+also register spills and some local variables from being overwritten by
+storing unsafe variables, such as large arrays, on a separate (unsafe)
+stack, and using these unsafe variables on the separate stack instead. This
+is also known as “SafeStack”, and is also considered an implementation of
+backward-edge control flow protection.
+
+Both shadow and safe stack are intended to be a more comprehensive
+alternatives to stack smashing protection as they protect the saved return
+instruction pointers (and other data in the case of safe stack) from
+arbitrary writes and non-linear out-of-bounds writes.
+
+Newer processors provide hardware assistance for backward-edge control flow
+protection, such as ARM Pointer Authentication, and Intel Shadow Stack as
+part of Intel CET.
+
+The Rust compiler does not support shadow or safe stack. There is work
+currently ongoing to add support for the sanitizers[40], which may or may
+not include support for safe stack<sup id="fnref:7" role="doc-noteref"><a
+href="#fn:7" class="footnote">7</a></sup>.
+
+```text
+$ readelf -s target/release/hello-rust | grep __safestack_init
+```
+Fig. 16. Checking if LLVM SafeStack is enabled for a given binary.
+
+The presence of the `__safestack_init` symbol indicates that LLVM SafeStack
+is enabled for a given binary. Conversely, the absence of the
+`__safestack_init` symbol indicates that LLVM SafeStack is not enabled for a
+given binary (see Fig. 16).
+
+<small id="fn:7">7\. The shadow stack implementation for the AMD64
+architecture and equivalent in LLVM was removed due to performance and
+security issues. <a href="#fnref:7" class="reversefootnote"
+role="doc-backlink">↩</a></small>
+
+
+## Appendix
+
+As of the latest version of the [Linux Standard Base (LSB) Core
+Specification](https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/progheader.html),
+the `PT_GNU_STACK` program header indicates whether the stack should be
+executable, and the absence of this header indicates that the stack should
+be executable. However, the Linux kernel currently sets the
+`READ_IMPLIES_EXEC` personality upon loading any executable with the
+`PT_GNU_STACK` program header and the `PF_X `flag set or with the absence of
+this header, resulting in not only the stack, but also all readable virtual
+memory mappings being executable.
+
+An attempt to fix this [was made in
+2012](https://lore.kernel.org/lkml/f298f914-2239-44e4-8aa1-a51282e7fac0@zmail15.collab.prod.int.phx2.redhat.com/),
+and another [was made in
+2020](https://lore.kernel.org/kernel-hardening/20200327064820.12602-1-keescook@chromium.org/).
+The former never landed, and the latter partially fixed it, but introduced
+other issues—the absence of the `PT_GNU_STACK` program header still causes
+not only the stack, but also all readable virtual memory mappings to be
+executable in some architectures, such as IA-32 and equivalent (or causes
+the stack to be non-executable in some architectures, such as AMD64 and
+equivalent, contradicting the LSB).
+
+The `READ_IMPLIES_EXEC` personality needs to be completely separated from
+the `PT_GNU_STACK` program header by having a separate option for it (or
+setarch -X could just be used whenever `READ_IMPLIES_EXEC` is needed), and
+the absence of the `PT_GNU_STACK` program header needs to have more secure
+defaults (unrelated to `READ_IMPLIES_EXEC`).
+
+
+## References
+
+1. D. Hosfelt. “Fearless security: memory safety.” Mozilla Hacks.
+   <https://hacks.mozilla.org/2019/01/fearless-security-memory-safety/>.
+
+2. D. Hosfelt. “Fearless security: thread safety.” Mozilla Hacks.
+   <https://hacks.mozilla.org/2019/02/fearless-security-thread-safety/>.
+
+3. S. Klabnik and C. Nichols. “What Is Ownership?.” The Rust Programming
+   Language. <https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html>.
+
+4. S. Klabnik and C. Nichols. “References and Borrowing.” The Rust
+   Programming Language.
+   <https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html>.
+
+5. S. Klabnik and C. Nichols. “The Slice Type.” The Rust Programming
+   Language. <https://doc.rust-lang.org/book/ch04-03-slices.html>.
+
+6. S. Klabnik and C. Nichols. “Unsafe Rust.” The Rust Programming Language.
+   <https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html>.
+
+7. S. Davidoff. “How Rust’s standard library was vulnerable for years and
+   nobody noticed.” Medium.
+   <https://medium.com/@shnatsel/how-rusts-standard-library-was-vulnerable-for-years-and-nobody-noticed-aebf0503c3d6>.
+
+8. “Improper restriction of operations within the bounds of a memory buffer
+   (CWE-119).” MITRE CWE List.
+   <https://cwe.mitre.org/data/definitions/119.html>.
+
+9. “Concurrency issues (CWE-557).” MITRE CWE List.
+   <https://cwe.mitre.org/data/definitions/557.html>.
+
+10. K. McAllister. “Memory exploit mitigations #15179.” GitHub.
+    <https://github.com/rust-lang/rust/issues/15179>.
+
+11. K. McAllister. “RFC: Memory exploit mitigation #145.” GitHub.
+    <https://github.com/rust-lang/rfcs/pull/145>.
+
+12. K. McAllister. “RFC: Memory exploit mitigation.” GitHub.
+    <https://github.com/kmcallister/rfcs/blob/hardening/active/0000-memory-exploit-mitigation.md>.
+
+13. D. Micay. “Enable PIE by default on Linux for full ASLR #16340.” GitHub.
+    <https://github.com/rust-lang/rust/pull/16340>.
+
+14. N. Matsakis. “Integer overflow #560.” GitHub.
+    <https://github.com/rust-lang/rfcs/pull/560>.
+
+15. G. Lehel and N. Matsakis. “Integer overflow.” GitHub.
+    <https://rust-lang.github.io/rfcs/0560-integer-overflow.html>.
+
+16. A. Turon. “Tracking issue for integer overflow (RFC 560) #22020.”
+    GitHub. <https://github.com/rust-lang/rust/issues/22020>.
+
+17. H. Wilson. “Myths and legends about integer overflow in Rust.” Huon on
+    the Internet.
+    <http://huonw.github.io/blog/2016/04/myths-and-legends-about-integer-overflow-in-rust/>.
+
+18. B. Anderson. “Stabilize -C overflow-checks #1535.” GitHub.
+    <https://github.com/rust-lang/rfcs/pull/1535>.
+
+19. B. Anderson. “Stable overflow checks.” GitHub.
+    <https://github.com/brson/rfcs/blob/overflow/text/0000-stable-overflow-checks.md>.
+
+20. N. Froyd. “Add -C overflow-checks option #40037.” GitHub.
+    <https://github.com/rust-lang/rust/pull/40037>.
+
+21. R. Á. de Espíndola. “rustc requires executable stack #798.” GitHub.
+    <https://github.com/rust-lang/rust/issues/798>.
+
+22. A. Seipp. “Make sure librustrt.so is linked with a non-executable stack.
+    #1066.” GitHub. <https://github.com/rust-lang/rust/pull/1066>.
+
+23. D. Micay. “Rust binaries should not have an executable stack #5643.”
+    GitHub. <https://github.com/rust-lang/rust/issues/5643>.
+
+24. D. Micay. “Mark the assembly object stacks as non-executable #5647.”
+    GitHub. <https://github.com/rust-lang/rust/pull/5647>.
+
+25. A. Clark. “Explicitly disable stack execution on linux and bsd #30859.”
+    GitHub. <https://github.com/rust-lang/rust/pull/30859>.
+
+26. “Replace stack overflow checking with stack probes #16012.” GitHub.
+    <https://github.com/rust-lang/rust/issues/16012>.
+
+27. B. Striegel. “Extend stack probe support to non-tier-1 platforms, and
+    clarify policy for mitigating LLVM-dependent unsafety #43241.” GitHub.
+    <https://github.com/rust-lang/rust/issues/43241>.
+
+28. A. Crichton. “rustc: Implement stack probes for x86 #42816.” GitHub.
+    <https://github.com/rust-lang/rust/pull/42816>.
+
+29. A. Crichton. “Add \_\_rust\_probestack intrinsic #175.” GitHub.
+    <https://github.com/rust-lang/compiler-builtins/pull/175>.
+
+30. B. Anderson. “Consider applying -Wl,-z,relro or -Wl,-z,relro,-z,now by
+    default #29877.” GitHub. <https://github.com/rust-lang/rust/issues/29877>.
+
+31. J. Löthberg. “Add support for full RELRO #43170.” GitHub.
+    <https://github.com/rust-lang/rust/pull/43170>.
+
+32. N. Matsakis. “Allocators in Rust.” Baby Steps.
+    <http://smallcultfollowing.com/babysteps/blog/2014/11/14/allocators-in-rust/>.
+
+33. A. Crichton. “RFC: Allow changing the default allocator #1183.” GitHub.
+    <https://github.com/rust-lang/rfcs/pull/1183>.
+
+34. A. Crichton. “RFC: Swap out jemalloc.” GitHub.
+    <https://rust-lang.github.io/rfcs/1183-swap-out-jemalloc.html>.
+
+35. A. Crichton. “Tracking issue for changing the global, default allocator
+    (RFC 1974) #27389.” GitHub.
+    <https://github.com/rust-lang/rust/issues/27389>.
+
+36. S. Fackler. “Prepare global allocators for stabilization #1974.” GitHub.
+    <https://github.com/rust-lang/rfcs/pull/1974>.
+
+37. A. Crichton. “RFC: Global allocators.” GitHub.
+    <https://rust-lang.github.io/rfcs/1974-global-allocators.html>.
+
+38. B. Anderson. “Switch the default global allocator to System, remove
+    alloc\_jemalloc, use jemallocator in rustc #36963.” GitHub.
+    <https://github.com/rust-lang/rust/issues/36963>.
+
+39. A. Crichton. “Remove the alloc\_jemalloc crate #55238.” GitHub.
+    <https://github.com/rust-lang/rust/pull/55238>.
+
+40. J. Aparicio. 2017. “Tracking issue for sanitizer support #39699.”
+    <https://github.com/rust-lang/rust/issues/39699>.
diff --git a/src/doc/rustc/src/images/image1.png b/src/doc/rustc/src/images/image1.png
new file mode 100644 (file)
index 0000000..ee2d3fd
Binary files /dev/null and b/src/doc/rustc/src/images/image1.png differ
diff --git a/src/doc/rustc/src/images/image2.png b/src/doc/rustc/src/images/image2.png
new file mode 100644 (file)
index 0000000..03061e1
Binary files /dev/null and b/src/doc/rustc/src/images/image2.png differ
diff --git a/src/doc/rustc/src/images/image3.png b/src/doc/rustc/src/images/image3.png
new file mode 100644 (file)
index 0000000..a49e14b
Binary files /dev/null and b/src/doc/rustc/src/images/image3.png differ
index 215e5d3d1043ae2f12fc0f6986496b7e55e3193f..99e0a2b177fc08a60b072ae78af4cce7fb928b4c 100644 (file)
@@ -152,8 +152,8 @@ not available.
 
 target | std | host | notes
 -------|-----|------|-------
+`aarch64-apple-ios-macabi` | ? |  | Apple Catalyst on ARM64
 `aarch64-apple-tvos` | * |  | ARM64 tvOS
-`aarch64-unknown-cloudabi` | ✓ |  | ARM64 CloudABI
 `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD
 `aarch64-unknown-hermit` | ? |  |
 `aarch64-unknown-netbsd` | ? |  |
@@ -165,7 +165,6 @@ target | std | host | notes
 `armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD
 `armv6-unknown-netbsd-eabihf` | ? |  |
 `armv7-apple-ios` | ✓ |  | ARMv7 iOS, Cortex-a8
-`armv7-unknown-cloudabi-eabihf` | ✓ |  | ARMv7 CloudABI, hardfloat
 `armv7-unknown-freebsd` | ✓ | ✓ | ARMv7 FreeBSD
 `armv7-unknown-netbsd-eabihf` | ? |  |
 `armv7-wrs-vxworks-eabihf` | ? |  |
@@ -176,7 +175,6 @@ target | std | host | notes
 `i386-apple-ios` | ✓ |  | 32-bit x86 iOS
 `i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.7+, Lion+)
 `i686-pc-windows-msvc` | ✓ |  | 32-bit Windows XP support
-`i686-unknown-cloudabi` | ✓ |  | 32-bit CloudABI
 `i686-unknown-uefi` | ? |  | 32-bit UEFI
 `i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku
 `i686-unknown-netbsd` | ✓ |  | NetBSD/i386 with SSE2
@@ -210,12 +208,11 @@ target | std | host | notes
 `thumbv7a-uwp-windows-msvc` | ✓ |  |
 `thumbv7neon-unknown-linux-musleabihf` | ? |  | Thumb2-mode ARMv7a Linux with NEON, MUSL
 `thumbv4t-none-eabi` | * |  | ARMv4T T32
-`x86_64-apple-ios-macabi` | ✓ |  | Apple Catalyst
+`x86_64-apple-ios-macabi` | ✓ |  | Apple Catalyst on x86_64
 `x86_64-apple-tvos` | * | | x86 64-bit tvOS
 `x86_64-linux-kernel` | * |  | Linux kernel modules
 `x86_64-pc-solaris` | ? |  |
 `x86_64-pc-windows-msvc` | ✓ |  | 64-bit Windows XP support
-`x86_64-unknown-cloudabi` | ✓ |  | 64-bit CloudABI
 `x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD
 `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku
 `x86_64-unknown-hermit` | ? |  |
diff --git a/src/doc/unstable-book/src/language-features/auto-traits.md b/src/doc/unstable-book/src/language-features/auto-traits.md
new file mode 100644 (file)
index 0000000..0ca6dd6
--- /dev/null
@@ -0,0 +1,107 @@
+# `auto_traits`
+
+The tracking issue for this feature is [#13231] 
+
+[#13231]: https://github.com/rust-lang/rust/issues/13231
+
+----
+
+The `auto_traits` feature gate allows you to define auto traits.
+
+Auto traits, like [`Send`] or [`Sync`] in the standard library, are marker traits
+that are automatically implemented for every type, unless the type, or a type it contains, 
+has explicitly opted out via a negative impl. (Negative impls are separately controlled
+by the `negative_impls` feature.)
+
+[`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
+[`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
+
+```rust,ignore
+impl !Trait for Type
+```
+
+Example:
+
+```rust
+#![feature(negative_impls)]
+#![feature(auto_traits)]
+
+auto trait Valid {}
+
+struct True;
+struct False;
+
+impl !Valid for False {}
+
+struct MaybeValid<T>(T);
+
+fn must_be_valid<T: Valid>(_t: T) { }
+
+fn main() {
+    // works
+    must_be_valid( MaybeValid(True) );
+                
+    // compiler error - trait bound not satisfied
+    // must_be_valid( MaybeValid(False) );
+}
+```
+
+## Automatic trait implementations
+
+When a type is declared as an `auto trait`, we will automatically
+create impls for every struct/enum/union, unless an explicit impl is
+provided. These automatic impls contain a where clause for each field
+of the form `T: AutoTrait`, where `T` is the type of the field and
+`AutoTrait` is the auto trait in question. As an example, consider the
+struct `List` and the auto trait `Send`:
+
+```rust
+struct List<T> {
+  data: T,
+  next: Option<Box<List<T>>>,
+}
+```
+
+Presuming that there is no explicit impl of `Send` for `List`, the
+compiler will supply an automatic impl of the form:
+
+```rust
+struct List<T> {
+  data: T,
+  next: Option<Box<List<T>>>,
+}
+
+unsafe impl<T> Send for List<T>
+where
+  T: Send, // from the field `data`
+  Option<Box<List<T>>>: Send, // from the field `next`
+{ }
+```
+
+Explicit impls may be either positive or negative. They take the form:
+
+```rust,ignore
+impl<...> AutoTrait for StructName<..> { }
+impl<...> !AutoTrait for StructName<..> { }
+```
+
+## Coinduction: Auto traits permit cyclic matching
+
+Unlike ordinary trait matching, auto traits are **coinductive**. This
+means, in short, that cycles which occur in trait matching are
+considered ok. As an example, consider the recursive struct `List`
+introduced in the previous section. In attempting to determine whether
+`List: Send`, we would wind up in a cycle: to apply the impl, we must
+show that `Option<Box<List>>: Send`, which will in turn require
+`Box<List>: Send` and then finally `List: Send` again. Under ordinary
+trait matching, this cycle would be an error, but for an auto trait it
+is considered a successful match.
+
+## Items
+
+Auto traits cannot have any trait items, such as methods or associated types. This ensures that we can generate default implementations.
+
+## Supertraits
+
+Auto traits cannot have supertraits. This is for soundness reasons, as the interaction of coinduction with implied bounds is difficult to reconcile.
+
diff --git a/src/doc/unstable-book/src/language-features/optin-builtin-traits.md b/src/doc/unstable-book/src/language-features/optin-builtin-traits.md
deleted file mode 100644 (file)
index 6f0f0cf..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-# `optin_builtin_traits`
-
-The tracking issue for this feature is [#13231] 
-
-[#13231]: https://github.com/rust-lang/rust/issues/13231
-
-----
-
-The `optin_builtin_traits` feature gate allows you to define auto traits.
-
-Auto traits, like [`Send`] or [`Sync`] in the standard library, are marker traits
-that are automatically implemented for every type, unless the type, or a type it contains, 
-has explicitly opted out via a negative impl. (Negative impls are separately controlled
-by the `negative_impls` feature.)
-
-[`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
-[`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
-
-```rust,ignore
-impl !Trait for Type
-```
-
-Example:
-
-```rust
-#![feature(negative_impls)]
-#![feature(optin_builtin_traits)]
-
-auto trait Valid {}
-
-struct True;
-struct False;
-
-impl !Valid for False {}
-
-struct MaybeValid<T>(T);
-
-fn must_be_valid<T: Valid>(_t: T) { }
-
-fn main() {
-    // works
-    must_be_valid( MaybeValid(True) );
-                
-    // compiler error - trait bound not satisfied
-    // must_be_valid( MaybeValid(False) );
-}
-```
-
-## Automatic trait implementations
-
-When a type is declared as an `auto trait`, we will automatically
-create impls for every struct/enum/union, unless an explicit impl is
-provided. These automatic impls contain a where clause for each field
-of the form `T: AutoTrait`, where `T` is the type of the field and
-`AutoTrait` is the auto trait in question. As an example, consider the
-struct `List` and the auto trait `Send`:
-
-```rust
-struct List<T> {
-  data: T,
-  next: Option<Box<List<T>>>,
-}
-```
-
-Presuming that there is no explicit impl of `Send` for `List`, the
-compiler will supply an automatic impl of the form:
-
-```rust
-struct List<T> {
-  data: T,
-  next: Option<Box<List<T>>>,
-}
-
-unsafe impl<T> Send for List<T>
-where
-  T: Send, // from the field `data`
-  Option<Box<List<T>>>: Send, // from the field `next`
-{ }
-```
-
-Explicit impls may be either positive or negative. They take the form:
-
-```rust,ignore
-impl<...> AutoTrait for StructName<..> { }
-impl<...> !AutoTrait for StructName<..> { }
-```
-
-## Coinduction: Auto traits permit cyclic matching
-
-Unlike ordinary trait matching, auto traits are **coinductive**. This
-means, in short, that cycles which occur in trait matching are
-considered ok. As an example, consider the recursive struct `List`
-introduced in the previous section. In attempting to determine whether
-`List: Send`, we would wind up in a cycle: to apply the impl, we must
-show that `Option<Box<List>>: Send`, which will in turn require
-`Box<List>: Send` and then finally `List: Send` again. Under ordinary
-trait matching, this cycle would be an error, but for an auto trait it
-is considered a successful match.
-
-## Items
-
-Auto traits cannot have any trait items, such as methods or associated types. This ensures that we can generate default implementations.
-
-## Supertraits
-
-Auto traits cannot have supertraits. This is for soundness reasons, as the interaction of coinduction with implied bounds is difficult to reconcile.
-
index eec3027085c91290b67805b535db184bce259d3b..b74d47a80027ad5dc455f29a94d402a1a9e12be5 100644 (file)
@@ -207,42 +207,43 @@ class StdRefCellProvider:
         yield "borrow", self.borrow
 
 
-# Yields children (in a provider's sense of the word) for a tree headed by a BoxedNode.
-# In particular, yields each key/value pair in the node and in any child nodes.
-def children_of_node(boxed_node, height):
-    def cast_to_internal(node):
-        internal_type_name = node.type.target().name.replace("LeafNode", "InternalNode", 1)
-        internal_type = lookup_type(internal_type_name)
-        return node.cast(internal_type.pointer())
-
-    node_ptr = unwrap_unique_or_non_null(boxed_node["ptr"])
-    leaf = node_ptr.dereference()
-    keys = leaf["keys"]
-    vals = leaf["vals"]
-    edges = cast_to_internal(node_ptr)["edges"] if height > 0 else None
-    length = int(leaf["len"])
-
-    for i in xrange(0, length + 1):
-        if height > 0:
-            boxed_child_node = edges[i]["value"]["value"]
-            for child in children_of_node(boxed_child_node, height - 1):
-                yield child
-        if i < length:
-            # Avoid "Cannot perform pointer math on incomplete type" on zero-sized arrays.
-            key = keys[i]["value"]["value"] if keys.type.sizeof > 0 else "()"
-            val = vals[i]["value"]["value"] if vals.type.sizeof > 0 else "()"
-            yield key, val
-
-
-# Yields children for a BTreeMap.
-def children_of_map(map):
+# Yields children (in a provider's sense of the word) for a BTreeMap.
+def children_of_btree_map(map):
+    # Yields each key/value pair in the node and in any child nodes.
+    def children_of_node(node_ptr, height):
+        def cast_to_internal(node):
+            internal_type_name = node.type.target().name.replace("LeafNode", "InternalNode", 1)
+            internal_type = lookup_type(internal_type_name)
+            return node.cast(internal_type.pointer())
+
+        if node_ptr.type.name.startswith("alloc::collections::btree::node::BoxedNode<"):
+            # BACKCOMPAT: rust 1.49
+            node_ptr = node_ptr["ptr"]
+        node_ptr = unwrap_unique_or_non_null(node_ptr)
+        leaf = node_ptr.dereference()
+        keys = leaf["keys"]
+        vals = leaf["vals"]
+        edges = cast_to_internal(node_ptr)["edges"] if height > 0 else None
+        length = leaf["len"]
+
+        for i in xrange(0, length + 1):
+            if height > 0:
+                child_ptr = edges[i]["value"]["value"]
+                for child in children_of_node(child_ptr, height - 1):
+                    yield child
+            if i < length:
+                # Avoid "Cannot perform pointer math on incomplete type" on zero-sized arrays.
+                key = keys[i]["value"]["value"] if keys.type.sizeof > 0 else "()"
+                val = vals[i]["value"]["value"] if vals.type.sizeof > 0 else "()"
+                yield key, val
+
     if map["length"] > 0:
         root = map["root"]
         if root.type.name.startswith("core::option::Option<"):
             root = root.cast(gdb.lookup_type(root.type.name[21:-1]))
-        boxed_root_node = root["node"]
+        node_ptr = root["node"]
         height = root["height"]
-        for child in children_of_node(boxed_root_node, height):
+        for child in children_of_node(node_ptr, height):
             yield child
 
 
@@ -255,7 +256,7 @@ class StdBTreeSetProvider:
 
     def children(self):
         inner_map = self.valobj["map"]
-        for i, (child, _) in enumerate(children_of_map(inner_map)):
+        for i, (child, _) in enumerate(children_of_btree_map(inner_map)):
             yield "[{}]".format(i), child
 
     @staticmethod
@@ -271,7 +272,7 @@ class StdBTreeMapProvider:
         return "BTreeMap(size={})".format(self.valobj["length"])
 
     def children(self):
-        for i, (key, val) in enumerate(children_of_map(self.valobj)):
+        for i, (key, val) in enumerate(children_of_btree_map(self.valobj)):
             yield "key{}".format(i), key
             yield "val{}".format(i), val
 
index cc3e8707e52768fcbf981d0a07509d963d378274..61121c776f491884d169cac4c505e85035af6dcd 100644 (file)
     let attrs = merge_attrs(cx, Some(parent_module), target_attrs, attrs_clone);
 
     cx.renderinfo.borrow_mut().inlined.insert(did);
-    let what_rustc_thinks = clean::Item::from_def_id_and_parts(did, Some(name), kind, cx);
+    let what_rustc_thinks = clean::Item::from_def_id_and_parts(did, Some(name.clean(cx)), kind, cx);
     ret.push(clean::Item { attrs, ..what_rustc_thinks });
     Some(ret)
 }
index 9d84089eb405c46633a543e8458c463ee0ee2416..13643fbf3d3fbd7f0655edd501270de48918f6d4 100644 (file)
@@ -14,7 +14,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::{CrateNum, DefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
 use rustc_middle::bug;
@@ -122,7 +122,7 @@ fn clean(&self, cx: &DocContext<'_>) -> ExternalCrate {
                         }
                     }
                 }
-                return prim.map(|p| (def_id, p, attrs));
+                return prim.map(|p| (def_id, p));
             }
             None
         };
@@ -144,9 +144,9 @@ fn clean(&self, cx: &DocContext<'_>) -> ExternalCrate {
                         hir::ItemKind::Use(ref path, hir::UseKind::Single)
                             if item.vis.node.is_pub() =>
                         {
-                            as_primitive(path.res).map(|(_, prim, attrs)| {
+                            as_primitive(path.res).map(|(_, prim)| {
                                 // Pretend the primitive is local.
-                                (cx.tcx.hir().local_def_id(id.id).to_def_id(), prim, attrs)
+                                (cx.tcx.hir().local_def_id(id.id).to_def_id(), prim)
                             })
                         }
                         _ => None,
@@ -177,7 +177,7 @@ fn clean(&self, cx: &DocContext<'_>) -> ExternalCrate {
                         }
                     }
                 }
-                return keyword.map(|p| (def_id, p, attrs));
+                return keyword.map(|p| (def_id, p));
             }
             None
         };
@@ -199,8 +199,8 @@ fn clean(&self, cx: &DocContext<'_>) -> ExternalCrate {
                         hir::ItemKind::Use(ref path, hir::UseKind::Single)
                             if item.vis.node.is_pub() =>
                         {
-                            as_keyword(path.res).map(|(_, prim, attrs)| {
-                                (cx.tcx.hir().local_def_id(id.id).to_def_id(), prim, attrs)
+                            as_keyword(path.res).map(|(_, prim)| {
+                                (cx.tcx.hir().local_def_id(id.id).to_def_id(), prim)
                             })
                         }
                         _ => None,
@@ -229,23 +229,11 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
         let attrs = self.attrs.clean(cx);
 
         let mut items: Vec<Item> = vec![];
-        items.extend(self.extern_crates.iter().flat_map(|x| x.clean(cx)));
         items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
-        items.extend(self.structs.iter().map(|x| x.clean(cx)));
-        items.extend(self.unions.iter().map(|x| x.clean(cx)));
-        items.extend(self.enums.iter().map(|x| x.clean(cx)));
-        items.extend(self.fns.iter().map(|x| x.clean(cx)));
         items.extend(self.foreigns.iter().map(|x| x.clean(cx)));
         items.extend(self.mods.iter().map(|x| x.clean(cx)));
-        items.extend(self.typedefs.iter().map(|x| x.clean(cx)));
-        items.extend(self.opaque_tys.iter().map(|x| x.clean(cx)));
-        items.extend(self.statics.iter().map(|x| x.clean(cx)));
-        items.extend(self.constants.iter().map(|x| x.clean(cx)));
-        items.extend(self.traits.iter().map(|x| x.clean(cx)));
-        items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
+        items.extend(self.items.iter().map(|x| x.clean(cx)).flatten());
         items.extend(self.macros.iter().map(|x| x.clean(cx)));
-        items.extend(self.proc_macros.iter().map(|x| x.clean(cx)));
-        items.extend(self.trait_aliases.iter().map(|x| x.clean(cx)));
 
         // determine if we should display the inner contents or
         // the outer `mod` item for the source code.
@@ -879,6 +867,66 @@ fn clean(&self, cx: &DocContext<'_>) -> Generics {
     }
 }
 
+fn clean_fn_or_proc_macro(
+    item: &hir::Item<'_>,
+    sig: &'a hir::FnSig<'a>,
+    generics: &'a hir::Generics<'a>,
+    body_id: hir::BodyId,
+    name: &mut Symbol,
+    cx: &DocContext<'_>,
+) -> ItemKind {
+    let macro_kind = item.attrs.iter().find_map(|a| {
+        if a.has_name(sym::proc_macro) {
+            Some(MacroKind::Bang)
+        } else if a.has_name(sym::proc_macro_derive) {
+            Some(MacroKind::Derive)
+        } else if a.has_name(sym::proc_macro_attribute) {
+            Some(MacroKind::Attr)
+        } else {
+            None
+        }
+    });
+    match macro_kind {
+        Some(kind) => {
+            if kind == MacroKind::Derive {
+                *name = item
+                    .attrs
+                    .lists(sym::proc_macro_derive)
+                    .find_map(|mi| mi.ident())
+                    .expect("proc-macro derives require a name")
+                    .name;
+            }
+
+            let mut helpers = Vec::new();
+            for mi in item.attrs.lists(sym::proc_macro_derive) {
+                if !mi.has_name(sym::attributes) {
+                    continue;
+                }
+
+                if let Some(list) = mi.meta_item_list() {
+                    for inner_mi in list {
+                        if let Some(ident) = inner_mi.ident() {
+                            helpers.push(ident.name);
+                        }
+                    }
+                }
+            }
+            ProcMacroItem(ProcMacro { kind, helpers: helpers.clean(cx) })
+        }
+        None => {
+            let mut func = (sig, generics, body_id).clean(cx);
+            let def_id = cx.tcx.hir().local_def_id(item.hir_id).to_def_id();
+            func.header.constness =
+                if is_const_fn(cx.tcx, def_id) && is_unstable_const_fn(cx.tcx, def_id).is_none() {
+                    hir::Constness::Const
+                } else {
+                    hir::Constness::NotConst
+                };
+            FunctionItem(func)
+        }
+    }
+}
+
 impl<'a> Clean<Function> for (&'a hir::FnSig<'a>, &'a hir::Generics<'a>, hir::BodyId) {
     fn clean(&self, cx: &DocContext<'_>) -> Function {
         let (generics, decl) =
@@ -888,34 +936,6 @@ fn clean(&self, cx: &DocContext<'_>) -> Function {
     }
 }
 
-impl Clean<Item> for doctree::Function<'_> {
-    fn clean(&self, cx: &DocContext<'_>) -> Item {
-        let (generics, decl) =
-            enter_impl_trait(cx, || (self.generics.clean(cx), (self.decl, self.body).clean(cx)));
-
-        let did = cx.tcx.hir().local_def_id(self.id).to_def_id();
-        let constness = if is_const_fn(cx.tcx, did) && !is_unstable_const_fn(cx.tcx, did).is_some()
-        {
-            hir::Constness::Const
-        } else {
-            hir::Constness::NotConst
-        };
-        let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
-        Item::from_def_id_and_parts(
-            did,
-            Some(self.name),
-            FunctionItem(Function {
-                decl,
-                generics,
-                header: hir::FnHeader { constness, ..self.header },
-                all_types,
-                ret_types,
-            }),
-            cx,
-        )
-    }
-}
-
 impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], &'a [Ident]) {
     fn clean(&self, cx: &DocContext<'_>) -> Arguments {
         Arguments {
@@ -1000,40 +1020,6 @@ fn clean(&self, cx: &DocContext<'_>) -> FnRetTy {
     }
 }
 
-impl Clean<Item> for doctree::Trait<'_> {
-    fn clean(&self, cx: &DocContext<'_>) -> Item {
-        let attrs = self.attrs.clean(cx);
-        let is_spotlight = attrs.has_doc_flag(sym::spotlight);
-        Item::from_hir_id_and_parts(
-            self.id,
-            Some(self.name),
-            TraitItem(Trait {
-                unsafety: self.unsafety,
-                items: self.items.iter().map(|ti| ti.clean(cx)).collect(),
-                generics: self.generics.clean(cx),
-                bounds: self.bounds.clean(cx),
-                is_spotlight,
-                is_auto: self.is_auto.clean(cx),
-            }),
-            cx,
-        )
-    }
-}
-
-impl Clean<Item> for doctree::TraitAlias<'_> {
-    fn clean(&self, cx: &DocContext<'_>) -> Item {
-        Item::from_hir_id_and_parts(
-            self.id,
-            Some(self.name),
-            TraitAliasItem(TraitAlias {
-                generics: self.generics.clean(cx),
-                bounds: self.bounds.clean(cx),
-            }),
-            cx,
-        )
-    }
-}
-
 impl Clean<bool> for hir::IsAuto {
     fn clean(&self, _: &DocContext<'_>) -> bool {
         match *self {
@@ -1081,63 +1067,68 @@ fn clean(&self, _: &DocContext<'_>) -> TypeKind {
 impl Clean<Item> for hir::TraitItem<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let local_did = cx.tcx.hir().local_def_id(self.hir_id).to_def_id();
-        let inner = match self.kind {
-            hir::TraitItemKind::Const(ref ty, default) => {
-                AssocConstItem(ty.clean(cx), default.map(|e| print_const_expr(cx, e)))
-            }
-            hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
-                let mut m = (sig, &self.generics, body).clean(cx);
-                if m.header.constness == hir::Constness::Const
-                    && is_unstable_const_fn(cx.tcx, local_did).is_some()
-                {
-                    m.header.constness = hir::Constness::NotConst;
+        cx.with_param_env(local_did, || {
+            let inner = match self.kind {
+                hir::TraitItemKind::Const(ref ty, default) => {
+                    AssocConstItem(ty.clean(cx), default.map(|e| print_const_expr(cx, e)))
                 }
-                MethodItem(m, None)
-            }
-            hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref names)) => {
-                let (generics, decl) = enter_impl_trait(cx, || {
-                    (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
-                });
-                let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
-                let mut t = Function { header: sig.header, decl, generics, all_types, ret_types };
-                if t.header.constness == hir::Constness::Const
-                    && is_unstable_const_fn(cx.tcx, local_did).is_some()
-                {
-                    t.header.constness = hir::Constness::NotConst;
+                hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
+                    let mut m = (sig, &self.generics, body).clean(cx);
+                    if m.header.constness == hir::Constness::Const
+                        && is_unstable_const_fn(cx.tcx, local_did).is_some()
+                    {
+                        m.header.constness = hir::Constness::NotConst;
+                    }
+                    MethodItem(m, None)
                 }
-                TyMethodItem(t)
-            }
-            hir::TraitItemKind::Type(ref bounds, ref default) => {
-                AssocTypeItem(bounds.clean(cx), default.clean(cx))
-            }
-        };
-        Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx)
+                hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref names)) => {
+                    let (generics, decl) = enter_impl_trait(cx, || {
+                        (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
+                    });
+                    let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
+                    let mut t =
+                        Function { header: sig.header, decl, generics, all_types, ret_types };
+                    if t.header.constness == hir::Constness::Const
+                        && is_unstable_const_fn(cx.tcx, local_did).is_some()
+                    {
+                        t.header.constness = hir::Constness::NotConst;
+                    }
+                    TyMethodItem(t)
+                }
+                hir::TraitItemKind::Type(ref bounds, ref default) => {
+                    AssocTypeItem(bounds.clean(cx), default.clean(cx))
+                }
+            };
+            Item::from_def_id_and_parts(local_did, Some(self.ident.name.clean(cx)), inner, cx)
+        })
     }
 }
 
 impl Clean<Item> for hir::ImplItem<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let local_did = cx.tcx.hir().local_def_id(self.hir_id).to_def_id();
-        let inner = match self.kind {
-            hir::ImplItemKind::Const(ref ty, expr) => {
-                AssocConstItem(ty.clean(cx), Some(print_const_expr(cx, expr)))
-            }
-            hir::ImplItemKind::Fn(ref sig, body) => {
-                let mut m = (sig, &self.generics, body).clean(cx);
-                if m.header.constness == hir::Constness::Const
-                    && is_unstable_const_fn(cx.tcx, local_did).is_some()
-                {
-                    m.header.constness = hir::Constness::NotConst;
+        cx.with_param_env(local_did, || {
+            let inner = match self.kind {
+                hir::ImplItemKind::Const(ref ty, expr) => {
+                    AssocConstItem(ty.clean(cx), Some(print_const_expr(cx, expr)))
                 }
-                MethodItem(m, Some(self.defaultness))
-            }
-            hir::ImplItemKind::TyAlias(ref ty) => {
-                let type_ = ty.clean(cx);
-                let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
-                TypedefItem(Typedef { type_, generics: Generics::default(), item_type }, true)
-            }
-        };
-        Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx)
+                hir::ImplItemKind::Fn(ref sig, body) => {
+                    let mut m = (sig, &self.generics, body).clean(cx);
+                    if m.header.constness == hir::Constness::Const
+                        && is_unstable_const_fn(cx.tcx, local_did).is_some()
+                    {
+                        m.header.constness = hir::Constness::NotConst;
+                    }
+                    MethodItem(m, Some(self.defaultness))
+                }
+                hir::ImplItemKind::TyAlias(ref ty) => {
+                    let type_ = ty.clean(cx);
+                    let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
+                    TypedefItem(Typedef { type_, generics: Generics::default(), item_type }, true)
+                }
+            };
+            Item::from_def_id_and_parts(local_did, Some(self.ident.name.clean(cx)), inner, cx)
+        })
     }
 }
 
@@ -1293,7 +1284,158 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
             }
         };
 
-        Item::from_def_id_and_parts(self.def_id, Some(self.ident.name), kind, cx)
+        Item::from_def_id_and_parts(self.def_id, Some(self.ident.name.clean(cx)), kind, cx)
+    }
+}
+
+fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &DocContext<'_>) -> Type {
+    use rustc_hir::GenericParamCount;
+    let hir::Ty { hir_id, span, ref kind } = *hir_ty;
+    let qpath = match kind {
+        hir::TyKind::Path(qpath) => qpath,
+        _ => unreachable!(),
+    };
+
+    match qpath {
+        hir::QPath::Resolved(None, ref path) => {
+            if let Res::Def(DefKind::TyParam, did) = path.res {
+                if let Some(new_ty) = cx.ty_substs.borrow().get(&did).cloned() {
+                    return new_ty;
+                }
+                if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did.into()) {
+                    return ImplTrait(bounds);
+                }
+            }
+
+            let mut alias = None;
+            if let Res::Def(DefKind::TyAlias, def_id) = path.res {
+                // Substitute private type aliases
+                if let Some(def_id) = def_id.as_local() {
+                    let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
+                    if !cx.renderinfo.borrow().access_levels.is_exported(def_id.to_def_id()) {
+                        alias = Some(&cx.tcx.hir().expect_item(hir_id).kind);
+                    }
+                }
+            };
+
+            if let Some(&hir::ItemKind::TyAlias(ref ty, ref generics)) = alias {
+                let provided_params = &path.segments.last().expect("segments were empty");
+                let mut ty_substs = FxHashMap::default();
+                let mut lt_substs = FxHashMap::default();
+                let mut ct_substs = FxHashMap::default();
+                let generic_args = provided_params.generic_args();
+                {
+                    let mut indices: GenericParamCount = Default::default();
+                    for param in generics.params.iter() {
+                        match param.kind {
+                            hir::GenericParamKind::Lifetime { .. } => {
+                                let mut j = 0;
+                                let lifetime = generic_args.args.iter().find_map(|arg| match arg {
+                                    hir::GenericArg::Lifetime(lt) => {
+                                        if indices.lifetimes == j {
+                                            return Some(lt);
+                                        }
+                                        j += 1;
+                                        None
+                                    }
+                                    _ => None,
+                                });
+                                if let Some(lt) = lifetime.cloned() {
+                                    let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
+                                    let cleaned = if !lt.is_elided() {
+                                        lt.clean(cx)
+                                    } else {
+                                        self::types::Lifetime::elided()
+                                    };
+                                    lt_substs.insert(lt_def_id.to_def_id(), cleaned);
+                                }
+                                indices.lifetimes += 1;
+                            }
+                            hir::GenericParamKind::Type { ref default, .. } => {
+                                let ty_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
+                                let mut j = 0;
+                                let type_ = generic_args.args.iter().find_map(|arg| match arg {
+                                    hir::GenericArg::Type(ty) => {
+                                        if indices.types == j {
+                                            return Some(ty);
+                                        }
+                                        j += 1;
+                                        None
+                                    }
+                                    _ => None,
+                                });
+                                if let Some(ty) = type_ {
+                                    ty_substs.insert(ty_param_def_id.to_def_id(), ty.clean(cx));
+                                } else if let Some(default) = *default {
+                                    ty_substs
+                                        .insert(ty_param_def_id.to_def_id(), default.clean(cx));
+                                }
+                                indices.types += 1;
+                            }
+                            hir::GenericParamKind::Const { .. } => {
+                                let const_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
+                                let mut j = 0;
+                                let const_ = generic_args.args.iter().find_map(|arg| match arg {
+                                    hir::GenericArg::Const(ct) => {
+                                        if indices.consts == j {
+                                            return Some(ct);
+                                        }
+                                        j += 1;
+                                        None
+                                    }
+                                    _ => None,
+                                });
+                                if let Some(ct) = const_ {
+                                    ct_substs.insert(const_param_def_id.to_def_id(), ct.clean(cx));
+                                }
+                                // FIXME(const_generics:defaults)
+                                indices.consts += 1;
+                            }
+                        }
+                    }
+                }
+                return cx.enter_alias(ty_substs, lt_substs, ct_substs, || ty.clean(cx));
+            }
+            resolve_type(cx, path.clean(cx), hir_id)
+        }
+        hir::QPath::Resolved(Some(ref qself), ref p) => {
+            // Try to normalize `<X as Y>::T` to a type
+            let ty = hir_ty_to_ty(cx.tcx, hir_ty);
+            if let Some(normalized_value) = normalize(cx, ty) {
+                return normalized_value.clean(cx);
+            }
+
+            let segments = if p.is_global() { &p.segments[1..] } else { &p.segments };
+            let trait_segments = &segments[..segments.len() - 1];
+            let trait_path = self::Path {
+                global: p.is_global(),
+                res: Res::Def(
+                    DefKind::Trait,
+                    cx.tcx.associated_item(p.res.def_id()).container.id(),
+                ),
+                segments: trait_segments.clean(cx),
+            };
+            Type::QPath {
+                name: p.segments.last().expect("segments were empty").ident.name.clean(cx),
+                self_type: box qself.clean(cx),
+                trait_: box resolve_type(cx, trait_path, hir_id),
+            }
+        }
+        hir::QPath::TypeRelative(ref qself, ref segment) => {
+            let ty = hir_ty_to_ty(cx.tcx, hir_ty);
+            let res = if let ty::Projection(proj) = ty.kind() {
+                Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id)
+            } else {
+                Res::Err
+            };
+            let trait_path = hir::Path { span, res, segments: &[] };
+            Type::QPath {
+                name: segment.ident.name.clean(cx),
+                self_type: box qself.clean(cx),
+                trait_: box resolve_type(cx, trait_path.clean(cx), hir_id),
+            }
+        }
+        hir::QPath::LangItem(..) => bug!("clean: requiring documentation of lang item"),
     }
 }
 
@@ -1332,145 +1474,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Type {
                     unreachable!()
                 }
             }
-            TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
-                if let Res::Def(DefKind::TyParam, did) = path.res {
-                    if let Some(new_ty) = cx.ty_substs.borrow().get(&did).cloned() {
-                        return new_ty;
-                    }
-                    if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did.into()) {
-                        return ImplTrait(bounds);
-                    }
-                }
-
-                let mut alias = None;
-                if let Res::Def(DefKind::TyAlias, def_id) = path.res {
-                    // Substitute private type aliases
-                    if let Some(def_id) = def_id.as_local() {
-                        let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
-                        if !cx.renderinfo.borrow().access_levels.is_exported(def_id.to_def_id()) {
-                            alias = Some(&cx.tcx.hir().expect_item(hir_id).kind);
-                        }
-                    }
-                };
-
-                if let Some(&hir::ItemKind::TyAlias(ref ty, ref generics)) = alias {
-                    let provided_params = &path.segments.last().expect("segments were empty");
-                    let mut ty_substs = FxHashMap::default();
-                    let mut lt_substs = FxHashMap::default();
-                    let mut ct_substs = FxHashMap::default();
-                    let generic_args = provided_params.generic_args();
-                    {
-                        let mut indices: GenericParamCount = Default::default();
-                        for param in generics.params.iter() {
-                            match param.kind {
-                                hir::GenericParamKind::Lifetime { .. } => {
-                                    let mut j = 0;
-                                    let lifetime =
-                                        generic_args.args.iter().find_map(|arg| match arg {
-                                            hir::GenericArg::Lifetime(lt) => {
-                                                if indices.lifetimes == j {
-                                                    return Some(lt);
-                                                }
-                                                j += 1;
-                                                None
-                                            }
-                                            _ => None,
-                                        });
-                                    if let Some(lt) = lifetime.cloned() {
-                                        let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
-                                        let cleaned = if !lt.is_elided() {
-                                            lt.clean(cx)
-                                        } else {
-                                            self::types::Lifetime::elided()
-                                        };
-                                        lt_substs.insert(lt_def_id.to_def_id(), cleaned);
-                                    }
-                                    indices.lifetimes += 1;
-                                }
-                                hir::GenericParamKind::Type { ref default, .. } => {
-                                    let ty_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
-                                    let mut j = 0;
-                                    let type_ =
-                                        generic_args.args.iter().find_map(|arg| match arg {
-                                            hir::GenericArg::Type(ty) => {
-                                                if indices.types == j {
-                                                    return Some(ty);
-                                                }
-                                                j += 1;
-                                                None
-                                            }
-                                            _ => None,
-                                        });
-                                    if let Some(ty) = type_ {
-                                        ty_substs.insert(ty_param_def_id.to_def_id(), ty.clean(cx));
-                                    } else if let Some(default) = *default {
-                                        ty_substs
-                                            .insert(ty_param_def_id.to_def_id(), default.clean(cx));
-                                    }
-                                    indices.types += 1;
-                                }
-                                hir::GenericParamKind::Const { .. } => {
-                                    let const_param_def_id =
-                                        cx.tcx.hir().local_def_id(param.hir_id);
-                                    let mut j = 0;
-                                    let const_ =
-                                        generic_args.args.iter().find_map(|arg| match arg {
-                                            hir::GenericArg::Const(ct) => {
-                                                if indices.consts == j {
-                                                    return Some(ct);
-                                                }
-                                                j += 1;
-                                                None
-                                            }
-                                            _ => None,
-                                        });
-                                    if let Some(ct) = const_ {
-                                        ct_substs
-                                            .insert(const_param_def_id.to_def_id(), ct.clean(cx));
-                                    }
-                                    // FIXME(const_generics:defaults)
-                                    indices.consts += 1;
-                                }
-                            }
-                        }
-                    }
-                    return cx.enter_alias(ty_substs, lt_substs, ct_substs, || ty.clean(cx));
-                }
-                resolve_type(cx, path.clean(cx), self.hir_id)
-            }
-            TyKind::Path(hir::QPath::Resolved(Some(ref qself), ref p)) => {
-                let segments = if p.is_global() { &p.segments[1..] } else { &p.segments };
-                let trait_segments = &segments[..segments.len() - 1];
-                let trait_path = self::Path {
-                    global: p.is_global(),
-                    res: Res::Def(
-                        DefKind::Trait,
-                        cx.tcx.associated_item(p.res.def_id()).container.id(),
-                    ),
-                    segments: trait_segments.clean(cx),
-                };
-                Type::QPath {
-                    name: p.segments.last().expect("segments were empty").ident.name.clean(cx),
-                    self_type: box qself.clean(cx),
-                    trait_: box resolve_type(cx, trait_path, self.hir_id),
-                }
-            }
-            TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
-                let mut res = Res::Err;
-                let ty = hir_ty_to_ty(cx.tcx, self);
-                if let ty::Projection(proj) = ty.kind() {
-                    res = Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id);
-                }
-                let trait_path = hir::Path { span: self.span, res, segments: &[] };
-                Type::QPath {
-                    name: segment.ident.name.clean(cx),
-                    self_type: box qself.clean(cx),
-                    trait_: box resolve_type(cx, trait_path.clean(cx), self.hir_id),
-                }
-            }
-            TyKind::Path(hir::QPath::LangItem(..)) => {
-                bug!("clean: requiring documentation of lang item")
-            }
+            TyKind::Path(_) => clean_qpath(&self, cx),
             TyKind::TraitObject(ref bounds, ref lifetime) => {
                 match bounds[0].clean(cx).trait_ {
                     ResolvedPath { path, param_names: None, did, is_generic } => {
@@ -1498,10 +1502,39 @@ fn clean(&self, cx: &DocContext<'_>) -> Type {
     }
 }
 
+/// Returns `None` if the type could not be normalized
+#[allow(unreachable_code, unused_variables)]
+fn normalize(cx: &DocContext<'tcx>, ty: Ty<'_>) -> Option<Ty<'tcx>> {
+    return None; // HACK: low-churn fix for #79459 while we wait for a trait normalization fix
+    use crate::rustc_trait_selection::infer::TyCtxtInferExt;
+    use crate::rustc_trait_selection::traits::query::normalize::AtExt;
+    use rustc_middle::traits::ObligationCause;
+
+    // Try to normalize `<X as Y>::T` to a type
+    let lifted = ty.lift_to_tcx(cx.tcx).unwrap();
+    let normalized = cx.tcx.infer_ctxt().enter(|infcx| {
+        infcx
+            .at(&ObligationCause::dummy(), cx.param_env.get())
+            .normalize(lifted)
+            .map(|resolved| infcx.resolve_vars_if_possible(resolved.value))
+    });
+    match normalized {
+        Ok(normalized_value) => {
+            debug!("normalized {:?} to {:?}", ty, normalized_value);
+            Some(normalized_value)
+        }
+        Err(err) => {
+            debug!("failed to normalize {:?}: {:?}", ty, err);
+            None
+        }
+    }
+}
+
 impl<'tcx> Clean<Type> for Ty<'tcx> {
     fn clean(&self, cx: &DocContext<'_>) -> Type {
         debug!("cleaning type: {:?}", self);
-        match *self.kind() {
+        let ty = normalize(cx, self).unwrap_or(self);
+        match *ty.kind() {
             ty::Never => Never,
             ty::Bool => Primitive(PrimitiveType::Bool),
             ty::Char => Primitive(PrimitiveType::Char),
@@ -1738,7 +1771,7 @@ impl Clean<Item> for ty::FieldDef {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let what_rustc_thinks = Item::from_def_id_and_parts(
             self.did,
-            Some(self.ident.name),
+            Some(self.ident.name.clean(cx)),
             StructFieldItem(cx.tcx.type_of(self.did).clean(cx)),
             cx,
         );
@@ -1777,38 +1810,6 @@ fn clean(&self, cx: &DocContext<'_>) -> Visibility {
     }
 }
 
-impl Clean<Item> for doctree::Struct<'_> {
-    fn clean(&self, cx: &DocContext<'_>) -> Item {
-        Item::from_hir_id_and_parts(
-            self.id,
-            Some(self.name),
-            StructItem(Struct {
-                struct_type: self.struct_type,
-                generics: self.generics.clean(cx),
-                fields: self.fields.clean(cx),
-                fields_stripped: false,
-            }),
-            cx,
-        )
-    }
-}
-
-impl Clean<Item> for doctree::Union<'_> {
-    fn clean(&self, cx: &DocContext<'_>) -> Item {
-        Item::from_hir_id_and_parts(
-            self.id,
-            Some(self.name),
-            UnionItem(Union {
-                struct_type: self.struct_type,
-                generics: self.generics.clean(cx),
-                fields: self.fields.clean(cx),
-                fields_stripped: false,
-            }),
-            cx,
-        )
-    }
-}
-
 impl Clean<VariantStruct> for rustc_hir::VariantData<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> VariantStruct {
         VariantStruct {
@@ -1819,21 +1820,6 @@ fn clean(&self, cx: &DocContext<'_>) -> VariantStruct {
     }
 }
 
-impl Clean<Item> for doctree::Enum<'_> {
-    fn clean(&self, cx: &DocContext<'_>) -> Item {
-        Item::from_hir_id_and_parts(
-            self.id,
-            Some(self.name),
-            EnumItem(Enum {
-                variants: self.variants.iter().map(|v| v.clean(cx)).collect(),
-                generics: self.generics.clean(cx),
-                variants_stripped: false,
-            }),
-            cx,
-        )
-    }
-}
-
 impl Clean<Item> for doctree::Variant<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let what_rustc_thinks = Item::from_hir_id_and_parts(
@@ -1860,22 +1846,20 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
                 fields: self
                     .fields
                     .iter()
-                    .map(|field| Item {
-                        source: cx.tcx.def_span(field.did).clean(cx),
-                        name: Some(field.ident.name.clean(cx)),
-                        attrs: cx.tcx.get_attrs(field.did).clean(cx),
-                        visibility: Visibility::Inherited,
-                        def_id: field.did,
-                        stability: get_stability(cx, field.did),
-                        deprecation: get_deprecation(cx, field.did),
-                        kind: StructFieldItem(cx.tcx.type_of(field.did).clean(cx)),
+                    .map(|field| {
+                        let name = Some(field.ident.name.clean(cx));
+                        let kind = StructFieldItem(cx.tcx.type_of(field.did).clean(cx));
+                        let what_rustc_thinks =
+                            Item::from_def_id_and_parts(field.did, name, kind, cx);
+                        // don't show `pub` for fields, which are always public
+                        Item { visibility: Visibility::Inherited, ..what_rustc_thinks }
                     })
                     .collect(),
             }),
         };
         let what_rustc_thinks = Item::from_def_id_and_parts(
             self.def_id,
-            Some(self.ident.name),
+            Some(self.ident.name.clean(cx)),
             VariantItem(Variant { kind }),
             cx,
         );
@@ -1981,33 +1965,6 @@ fn clean(&self, _: &DocContext<'_>) -> String {
     }
 }
 
-impl Clean<Item> for doctree::Typedef<'_> {
-    fn clean(&self, cx: &DocContext<'_>) -> Item {
-        let type_ = self.ty.clean(cx);
-        let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
-        Item::from_hir_id_and_parts(
-            self.id,
-            Some(self.name),
-            TypedefItem(Typedef { type_, generics: self.gen.clean(cx), item_type }, false),
-            cx,
-        )
-    }
-}
-
-impl Clean<Item> for doctree::OpaqueTy<'_> {
-    fn clean(&self, cx: &DocContext<'_>) -> Item {
-        Item::from_hir_id_and_parts(
-            self.id,
-            Some(self.name),
-            OpaqueTyItem(OpaqueTy {
-                bounds: self.opaque_ty.bounds.clean(cx),
-                generics: self.opaque_ty.generics.clean(cx),
-            }),
-            cx,
-        )
-    }
-}
-
 impl Clean<BareFunctionDecl> for hir::BareFnTy<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> BareFunctionDecl {
         let (generic_params, decl) = enter_impl_trait(cx, || {
@@ -2017,37 +1974,101 @@ fn clean(&self, cx: &DocContext<'_>) -> BareFunctionDecl {
     }
 }
 
-impl Clean<Item> for doctree::Static<'_> {
-    fn clean(&self, cx: &DocContext<'_>) -> Item {
-        debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
-        Item::from_hir_id_and_parts(
-            self.id,
-            Some(self.name),
-            StaticItem(Static {
-                type_: self.type_.clean(cx),
-                mutability: self.mutability,
-                expr: print_const_expr(cx, self.expr),
-            }),
-            cx,
-        )
+impl Clean<Vec<Item>> for (&hir::Item<'_>, Option<Ident>) {
+    fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
+        use hir::ItemKind;
+
+        let (item, renamed) = self;
+        let def_id = cx.tcx.hir().local_def_id(item.hir_id).to_def_id();
+        let mut name = match renamed {
+            Some(ident) => ident.name,
+            None => cx.tcx.hir().name(item.hir_id),
+        };
+        cx.with_param_env(def_id, || {
+            let kind = match item.kind {
+                ItemKind::Static(ty, mutability, body_id) => StaticItem(Static {
+                    type_: ty.clean(cx),
+                    mutability,
+                    expr: print_const_expr(cx, body_id),
+                }),
+                ItemKind::Const(ty, body_id) => ConstantItem(Constant {
+                    type_: ty.clean(cx),
+                    expr: print_const_expr(cx, body_id),
+                    value: print_evaluated_const(cx, def_id),
+                    is_literal: is_literal_expr(cx, body_id.hir_id),
+                }),
+                ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
+                    bounds: ty.bounds.clean(cx),
+                    generics: ty.generics.clean(cx),
+                }),
+                ItemKind::TyAlias(ty, ref generics) => {
+                    let rustdoc_ty = ty.clean(cx);
+                    let item_type = rustdoc_ty.def_id().and_then(|did| inline::build_ty(cx, did));
+                    TypedefItem(
+                        Typedef { type_: rustdoc_ty, generics: generics.clean(cx), item_type },
+                        false,
+                    )
+                }
+                ItemKind::Enum(ref def, ref generics) => EnumItem(Enum {
+                    variants: def.variants.iter().map(|v| v.clean(cx)).collect(),
+                    generics: generics.clean(cx),
+                    variants_stripped: false,
+                }),
+                ItemKind::TraitAlias(ref generics, bounds) => TraitAliasItem(TraitAlias {
+                    generics: generics.clean(cx),
+                    bounds: bounds.clean(cx),
+                }),
+                ItemKind::Union(ref variant_data, ref generics) => UnionItem(Union {
+                    struct_type: doctree::struct_type_from_def(&variant_data),
+                    generics: generics.clean(cx),
+                    fields: variant_data.fields().clean(cx),
+                    fields_stripped: false,
+                }),
+                ItemKind::Struct(ref variant_data, ref generics) => StructItem(Struct {
+                    struct_type: doctree::struct_type_from_def(&variant_data),
+                    generics: generics.clean(cx),
+                    fields: variant_data.fields().clean(cx),
+                    fields_stripped: false,
+                }),
+                ItemKind::Impl { .. } => return clean_impl(item, cx),
+                // proc macros can have a name set by attributes
+                ItemKind::Fn(ref sig, ref generics, body_id) => {
+                    clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
+                }
+                hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => {
+                    let items = item_ids
+                        .iter()
+                        .map(|ti| cx.tcx.hir().trait_item(ti.id).clean(cx))
+                        .collect();
+                    let attrs = item.attrs.clean(cx);
+                    let is_spotlight = attrs.has_doc_flag(sym::spotlight);
+                    TraitItem(Trait {
+                        unsafety,
+                        items,
+                        generics: generics.clean(cx),
+                        bounds: bounds.clean(cx),
+                        is_spotlight,
+                        is_auto: is_auto.clean(cx),
+                    })
+                }
+                ItemKind::ExternCrate(orig_name) => {
+                    return clean_extern_crate(item, name, orig_name, cx);
+                }
+                _ => unreachable!("not yet converted"),
+            };
+
+            vec![Item::from_def_id_and_parts(def_id, Some(name.clean(cx)), kind, cx)]
+        })
     }
 }
 
-impl Clean<Item> for doctree::Constant<'_> {
+impl Clean<Item> for hir::Variant<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
-        let def_id = cx.tcx.hir().local_def_id(self.id).to_def_id();
-
-        Item::from_def_id_and_parts(
-            def_id,
-            Some(self.name),
-            ConstantItem(Constant {
-                type_: self.type_.clean(cx),
-                expr: print_const_expr(cx, self.expr),
-                value: print_evaluated_const(cx, def_id),
-                is_literal: is_literal_expr(cx, self.expr.hir_id),
-            }),
-            cx,
-        )
+        let kind = VariantItem(Variant { kind: self.data.clean(cx) });
+        let what_rustc_thinks =
+            Item::from_hir_id_and_parts(self.id, Some(self.ident.name), kind, cx);
+        // don't show `pub` for variants, which are always public
+        Item { visibility: Inherited, ..what_rustc_thinks }
     }
 }
 
@@ -2062,98 +2083,103 @@ fn clean(&self, _: &DocContext<'_>) -> ImplPolarity {
     }
 }
 
-impl Clean<Vec<Item>> for doctree::Impl<'_> {
-    fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
-        let mut ret = Vec::new();
-        let trait_ = self.trait_.clean(cx);
-        let items = self.items.iter().map(|ii| ii.clean(cx)).collect::<Vec<_>>();
-        let def_id = cx.tcx.hir().local_def_id(self.id);
-
-        // If this impl block is an implementation of the Deref trait, then we
-        // need to try inlining the target's inherent impl blocks as well.
-        if trait_.def_id() == cx.tcx.lang_items().deref_trait() {
-            build_deref_target_impls(cx, &items, &mut ret);
+fn clean_impl(impl_: &hir::Item<'_>, cx: &DocContext<'_>) -> Vec<Item> {
+    let mut ret = Vec::new();
+    let (trait_, items, for_, unsafety, generics) = match &impl_.kind {
+        hir::ItemKind::Impl { of_trait, items, self_ty, unsafety, generics, .. } => {
+            (of_trait, items, self_ty, *unsafety, generics)
         }
-
-        let provided: FxHashSet<String> = trait_
-            .def_id()
-            .map(|did| {
-                cx.tcx.provided_trait_methods(did).map(|meth| meth.ident.to_string()).collect()
-            })
-            .unwrap_or_default();
-
-        let for_ = self.for_.clean(cx);
-        let type_alias = for_.def_id().and_then(|did| match cx.tcx.def_kind(did) {
-            DefKind::TyAlias => Some(cx.tcx.type_of(did).clean(cx)),
-            _ => None,
+        _ => unreachable!(),
+    };
+    let trait_ = trait_.clean(cx);
+    let items = items.iter().map(|ii| cx.tcx.hir().impl_item(ii.id).clean(cx)).collect::<Vec<_>>();
+    let def_id = cx.tcx.hir().local_def_id(impl_.hir_id);
+
+    // If this impl block is an implementation of the Deref trait, then we
+    // need to try inlining the target's inherent impl blocks as well.
+    if trait_.def_id() == cx.tcx.lang_items().deref_trait() {
+        build_deref_target_impls(cx, &items, &mut ret);
+    }
+
+    let provided: FxHashSet<String> = trait_
+        .def_id()
+        .map(|did| cx.tcx.provided_trait_methods(did).map(|meth| meth.ident.to_string()).collect())
+        .unwrap_or_default();
+
+    let for_ = for_.clean(cx);
+    let type_alias = for_.def_id().and_then(|did| match cx.tcx.def_kind(did) {
+        DefKind::TyAlias => Some(cx.tcx.type_of(did).clean(cx)),
+        _ => None,
+    });
+    let make_item = |trait_: Option<Type>, for_: Type, items: Vec<Item>| {
+        let kind = ImplItem(Impl {
+            unsafety,
+            generics: generics.clean(cx),
+            provided_trait_methods: provided.clone(),
+            trait_,
+            for_,
+            items,
+            polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)),
+            synthetic: false,
+            blanket_impl: None,
+        });
+        Item::from_hir_id_and_parts(impl_.hir_id, None, kind, cx)
+    };
+    if let Some(type_alias) = type_alias {
+        ret.push(make_item(trait_.clone(), type_alias, items.clone()));
+    }
+    ret.push(make_item(trait_, for_, items));
+    ret
+}
+
+fn clean_extern_crate(
+    krate: &hir::Item<'_>,
+    name: Symbol,
+    orig_name: Option<Symbol>,
+    cx: &DocContext<'_>,
+) -> Vec<Item> {
+    // this is the ID of the `extern crate` statement
+    let def_id = cx.tcx.hir().local_def_id(krate.hir_id);
+    let cnum = cx.tcx.extern_mod_stmt_cnum(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 please_inline = krate.vis.node.is_pub()
+        && krate.attrs.iter().any(|a| {
+            a.has_name(sym::doc)
+                && match a.meta_item_list() {
+                    Some(l) => attr::list_contains_name(&l, sym::inline),
+                    None => false,
+                }
         });
-        let make_item = |trait_: Option<Type>, for_: Type, items: Vec<Item>| Item {
-            name: None,
-            attrs: self.attrs.clean(cx),
-            source: self.span.clean(cx),
-            def_id: def_id.to_def_id(),
-            visibility: self.vis.clean(cx),
-            stability: cx.stability(self.id),
-            deprecation: cx.deprecation(self.id).clean(cx),
-            kind: ImplItem(Impl {
-                unsafety: self.unsafety,
-                generics: self.generics.clean(cx),
-                provided_trait_methods: provided.clone(),
-                trait_,
-                for_,
-                items,
-                polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)),
-                synthetic: false,
-                blanket_impl: None,
-            }),
-        };
-        if let Some(type_alias) = type_alias {
-            ret.push(make_item(trait_.clone(), type_alias, items.clone()));
-        }
-        ret.push(make_item(trait_, for_, items));
-        ret
-    }
-}
-
-impl Clean<Vec<Item>> for doctree::ExternCrate<'_> {
-    fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
-        let please_inline = self.vis.node.is_pub()
-            && self.attrs.iter().any(|a| {
-                a.has_name(sym::doc)
-                    && match a.meta_item_list() {
-                        Some(l) => attr::list_contains_name(&l, sym::inline),
-                        None => false,
-                    }
-            });
 
-        if please_inline {
-            let mut visited = FxHashSet::default();
+    if please_inline {
+        let mut visited = FxHashSet::default();
 
-            let res = Res::Def(DefKind::Mod, DefId { krate: self.cnum, index: CRATE_DEF_INDEX });
+        let res = Res::Def(DefKind::Mod, crate_def_id);
 
-            if let Some(items) = inline::try_inline(
-                cx,
-                cx.tcx.parent_module(self.hir_id).to_def_id(),
-                res,
-                self.name,
-                Some(self.attrs),
-                &mut visited,
-            ) {
-                return items;
-            }
+        if let Some(items) = inline::try_inline(
+            cx,
+            cx.tcx.parent_module(krate.hir_id).to_def_id(),
+            res,
+            name,
+            Some(krate.attrs),
+            &mut visited,
+        ) {
+            return items;
         }
-
-        vec![Item {
-            name: None,
-            attrs: self.attrs.clean(cx),
-            source: self.span.clean(cx),
-            def_id: DefId { krate: self.cnum, index: CRATE_DEF_INDEX },
-            visibility: self.vis.clean(cx),
-            stability: None,
-            deprecation: None,
-            kind: ExternCrateItem(self.name.clean(cx), self.path.clone()),
-        }]
     }
+    let path = orig_name.map(|x| x.to_string());
+    // FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason
+    vec![Item {
+        name: None,
+        attrs: krate.attrs.clean(cx),
+        source: krate.span.clean(cx),
+        def_id: crate_def_id,
+        visibility: krate.vis.clean(cx),
+        stability: None,
+        deprecation: None,
+        kind: ExternCrateItem(name.clean(cx), path),
+    }]
 }
 
 impl Clean<Vec<Item>> for doctree::Import<'_> {
@@ -2247,36 +2273,45 @@ fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
     }
 }
 
-impl Clean<Item> for doctree::ForeignItem<'_> {
+impl Clean<Item> for (&hir::ForeignItem<'_>, Option<Ident>) {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
-        let kind = match self.kind {
-            hir::ForeignItemKind::Fn(ref decl, ref names, ref generics) => {
-                let abi = cx.tcx.hir().get_foreign_abi(self.id);
-                let (generics, decl) =
-                    enter_impl_trait(cx, || (generics.clean(cx), (&**decl, &names[..]).clean(cx)));
-                let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
-                ForeignFunctionItem(Function {
-                    decl,
-                    generics,
-                    header: hir::FnHeader {
-                        unsafety: hir::Unsafety::Unsafe,
-                        abi,
-                        constness: hir::Constness::NotConst,
-                        asyncness: hir::IsAsync::NotAsync,
-                    },
-                    all_types,
-                    ret_types,
-                })
-            }
-            hir::ForeignItemKind::Static(ref ty, mutbl) => ForeignStaticItem(Static {
-                type_: ty.clean(cx),
-                mutability: *mutbl,
-                expr: String::new(),
-            }),
-            hir::ForeignItemKind::Type => ForeignTypeItem,
-        };
+        let (item, renamed) = self;
+        cx.with_param_env(cx.tcx.hir().local_def_id(item.hir_id).to_def_id(), || {
+            let kind = match item.kind {
+                hir::ForeignItemKind::Fn(ref decl, ref names, ref generics) => {
+                    let abi = cx.tcx.hir().get_foreign_abi(item.hir_id);
+                    let (generics, decl) = enter_impl_trait(cx, || {
+                        (generics.clean(cx), (&**decl, &names[..]).clean(cx))
+                    });
+                    let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
+                    ForeignFunctionItem(Function {
+                        decl,
+                        generics,
+                        header: hir::FnHeader {
+                            unsafety: hir::Unsafety::Unsafe,
+                            abi,
+                            constness: hir::Constness::NotConst,
+                            asyncness: hir::IsAsync::NotAsync,
+                        },
+                        all_types,
+                        ret_types,
+                    })
+                }
+                hir::ForeignItemKind::Static(ref ty, mutability) => ForeignStaticItem(Static {
+                    type_: ty.clean(cx),
+                    mutability,
+                    expr: String::new(),
+                }),
+                hir::ForeignItemKind::Type => ForeignTypeItem,
+            };
 
-        Item::from_hir_id_and_parts(self.id, Some(self.name), kind, cx)
+            Item::from_hir_id_and_parts(
+                item.hir_id,
+                Some(renamed.unwrap_or(item.ident).name),
+                kind,
+                cx,
+            )
+        })
     }
 }
 
@@ -2284,7 +2319,7 @@ impl Clean<Item> for doctree::Macro {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         Item::from_def_id_and_parts(
             self.def_id,
-            Some(self.name),
+            Some(self.name.clean(cx)),
             MacroItem(Macro {
                 source: format!(
                     "macro_rules! {} {{\n{}}}",
@@ -2301,17 +2336,6 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
     }
 }
 
-impl Clean<Item> for doctree::ProcMacro {
-    fn clean(&self, cx: &DocContext<'_>) -> Item {
-        Item::from_hir_id_and_parts(
-            self.id,
-            Some(self.name),
-            ProcMacroItem(ProcMacro { kind: self.kind, helpers: self.helpers.clean(cx) }),
-            cx,
-        )
-    }
-}
-
 impl Clean<Deprecation> for attr::Deprecation {
     fn clean(&self, _: &DocContext<'_>) -> Deprecation {
         Deprecation {
index 43b986aae1c321155e1ea5880814717db7824d34..2283b71a94fefa2dbc5207a2454ab563d7f82946 100644 (file)
@@ -34,6 +34,7 @@
 use crate::clean::external_path;
 use crate::clean::inline;
 use crate::clean::types::Type::{QPath, ResolvedPath};
+use crate::clean::Clean;
 use crate::core::DocContext;
 use crate::doctree;
 use crate::formats::cache::cache;
@@ -54,7 +55,7 @@
     crate src: FileName,
     crate module: Option<Item>,
     crate externs: Vec<(CrateNum, ExternalCrate)>,
-    crate primitives: Vec<(DefId, PrimitiveType, Attributes)>,
+    crate primitives: Vec<(DefId, PrimitiveType)>,
     // These are later on moved into `CACHEKEY`, leaving the map empty.
     // Only here so that they can be filtered through the rustdoc passes.
     crate external_traits: Rc<RefCell<FxHashMap<DefId, Trait>>>,
@@ -67,8 +68,8 @@
     crate name: String,
     crate src: FileName,
     crate attrs: Attributes,
-    crate primitives: Vec<(DefId, PrimitiveType, Attributes)>,
-    crate keywords: Vec<(DefId, String, Attributes)>,
+    crate primitives: Vec<(DefId, PrimitiveType)>,
+    crate keywords: Vec<(DefId, String)>,
 }
 
 /// Anything with a source location and set of attributes and, optionally, a
@@ -120,17 +121,20 @@ pub fn from_hir_id_and_parts(
         kind: ItemKind,
         cx: &DocContext<'_>,
     ) -> Item {
-        Item::from_def_id_and_parts(cx.tcx.hir().local_def_id(hir_id).to_def_id(), name, kind, cx)
+        Item::from_def_id_and_parts(
+            cx.tcx.hir().local_def_id(hir_id).to_def_id(),
+            name.clean(cx),
+            kind,
+            cx,
+        )
     }
 
     pub fn from_def_id_and_parts(
         def_id: DefId,
-        name: Option<Symbol>,
+        name: Option<String>,
         kind: ItemKind,
         cx: &DocContext<'_>,
     ) -> Item {
-        use super::Clean;
-
         debug!("name={:?}, def_id={:?}", name, def_id);
 
         // `span_if_local()` lies about functions and only gives the span of the function signature
@@ -145,7 +149,7 @@ pub fn from_def_id_and_parts(
         Item {
             def_id,
             kind,
-            name: name.clean(cx),
+            name,
             source: source.clean(cx),
             attrs: cx.tcx.get_attrs(def_id).clean(cx),
             visibility: cx.tcx.visibility(def_id).clean(cx),
index 22917fbceb48a12dcb0fa773a8a1328fc6b8f341..1b22d26f49bd80b7787748151a2dea0d4d964b0a 100644 (file)
@@ -1,15 +1,14 @@
 use crate::clean::auto_trait::AutoTraitFinder;
 use crate::clean::blanket_impl::BlanketImplFinder;
 use crate::clean::{
-    inline, Clean, Crate, Deprecation, ExternalCrate, FnDecl, FnRetTy, Generic, GenericArg,
-    GenericArgs, GenericBound, Generics, GetDefId, ImportSource, Item, ItemKind, Lifetime,
-    MacroKind, Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Span, Type, TypeBinding,
-    TypeKind, Visibility, WherePredicate,
+    inline, Clean, Crate, ExternalCrate, FnDecl, FnRetTy, Generic, GenericArg, GenericArgs,
+    GenericBound, Generics, GetDefId, ImportSource, Item, ItemKind, Lifetime, MacroKind, Path,
+    PathSegment, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding, TypeKind,
+    WherePredicate,
 };
 use crate::core::DocContext;
 
 use itertools::Itertools;
-use rustc_attr::Stability;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
             ItemKind::ModuleItem(ref mut m) => m,
             _ => unreachable!(),
         };
-        m.items.extend(primitives.iter().map(|&(def_id, prim, ref attrs)| Item {
-            source: Span::empty(),
-            name: Some(prim.to_url_str().to_string()),
-            attrs: attrs.clone(),
-            visibility: Visibility::Public,
-            stability: get_stability(cx, def_id),
-            deprecation: get_deprecation(cx, def_id),
-            def_id,
-            kind: ItemKind::PrimitiveItem(prim),
+        m.items.extend(primitives.iter().map(|&(def_id, prim)| {
+            Item::from_def_id_and_parts(
+                def_id,
+                Some(prim.to_url_str().to_owned()),
+                ItemKind::PrimitiveItem(prim),
+                cx,
+            )
         }));
-        m.items.extend(keywords.into_iter().map(|(def_id, kw, attrs)| Item {
-            source: Span::empty(),
-            name: Some(kw.clone()),
-            attrs,
-            visibility: Visibility::Public,
-            stability: get_stability(cx, def_id),
-            deprecation: get_deprecation(cx, def_id),
-            def_id,
-            kind: ItemKind::KeywordItem(kw),
+        m.items.extend(keywords.into_iter().map(|(def_id, kw)| {
+            Item::from_def_id_and_parts(def_id, Some(kw.clone()), ItemKind::KeywordItem(kw), cx)
         }));
     }
 
     }
 }
 
-// extract the stability index for a node from tcx, if possible
-crate fn get_stability(cx: &DocContext<'_>, def_id: DefId) -> Option<Stability> {
-    cx.tcx.lookup_stability(def_id).cloned()
-}
-
-crate fn get_deprecation(cx: &DocContext<'_>, def_id: DefId) -> Option<Deprecation> {
-    cx.tcx.lookup_deprecation(def_id).clean(cx)
-}
-
 fn external_generic_args(
     cx: &DocContext<'_>,
     trait_did: Option<DefId>,
index 413f5bdf5214b912a41d065c3d43f9706b519db3..b63acdc114e89cec6299b8bcb35c1f1ba56ae958 100644 (file)
@@ -1,4 +1,3 @@
-use rustc_attr as attr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::{self, Lrc};
 use rustc_driver::abort_on_err;
@@ -16,7 +15,7 @@
 use rustc_middle::hir::map::Map;
 use rustc_middle::middle::cstore::CrateStore;
 use rustc_middle::middle::privacy::AccessLevels;
-use rustc_middle::ty::{Ty, TyCtxt};
+use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
 use rustc_resolve as resolve;
 use rustc_session::config::{self, CrateType, ErrorOutputType};
 use rustc_session::lint;
@@ -26,7 +25,7 @@
 use rustc_span::symbol::sym;
 use rustc_span::DUMMY_SP;
 
-use std::cell::RefCell;
+use std::cell::{Cell, RefCell};
 use std::mem;
 use std::rc::Rc;
 
 crate struct DocContext<'tcx> {
     crate tcx: TyCtxt<'tcx>,
     crate resolver: Rc<RefCell<interface::BoxedResolver>>,
+    /// Used for normalization.
+    ///
+    /// Most of this logic is copied from rustc_lint::late.
+    crate param_env: Cell<ParamEnv<'tcx>>,
     /// Later on moved into `CACHE_KEY`
     crate renderinfo: RefCell<RenderInfo>,
     /// Later on moved through `clean::Crate` into `CACHE_KEY`
@@ -80,6 +83,13 @@ impl<'tcx> DocContext<'tcx> {
         &self.tcx.sess
     }
 
+    crate fn with_param_env<T, F: FnOnce() -> T>(&self, def_id: DefId, f: F) -> T {
+        let old_param_env = self.param_env.replace(self.tcx.param_env(def_id));
+        let ret = f();
+        self.param_env.set(old_param_env);
+        ret
+    }
+
     crate fn enter_resolver<F, R>(&self, f: F) -> R
     where
         F: FnOnce(&mut resolve::Resolver<'_>) -> R,
@@ -156,21 +166,6 @@ impl<'tcx> DocContext<'tcx> {
             def_id.as_local().map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id))
         }
     }
-
-    crate fn stability(&self, id: HirId) -> Option<attr::Stability> {
-        self.tcx
-            .hir()
-            .opt_local_def_id(id)
-            .and_then(|def_id| self.tcx.lookup_stability(def_id.to_def_id()))
-            .cloned()
-    }
-
-    crate fn deprecation(&self, id: HirId) -> Option<attr::Deprecation> {
-        self.tcx
-            .hir()
-            .opt_local_def_id(id)
-            .and_then(|def_id| self.tcx.lookup_deprecation(def_id.to_def_id()))
-    }
 }
 
 /// Creates a new diagnostic `Handler` that can be used to emit warnings and errors.
@@ -540,6 +535,7 @@ fn run_global_ctxt(
     let mut ctxt = DocContext {
         tcx,
         resolver,
+        param_env: Cell::new(ParamEnv::empty()),
         external_traits: Default::default(),
         active_extern_traits: Default::default(),
         renderinfo: RefCell::new(renderinfo),
index 9f35e57df418b36f7cf6b5f287eca9c5a83f4f97..a615701f253d322b7fa3767571bf183649d946a7 100644 (file)
@@ -754,12 +754,14 @@ fn add_test(&mut self, test: String, config: LangString, line: usize) {
             let folder_name = filename
                 .to_string()
                 .chars()
-                .map(|c| if c == '/' || c == '.' { '_' } else { c })
+                .map(|c| if c == '\\' || c == '/' || c == '.' { '_' } else { c })
                 .collect::<String>();
 
             path.push(format!(
-                "{name}_{line}_{number}",
-                name = folder_name,
+                "{krate}_{file}_{line}_{number}",
+                krate = cratename,
+                file = folder_name,
+                line = line,
                 number = {
                     // Increases the current test number, if this file already
                     // exists or it creates a new entry with a test number of 0.
@@ -768,7 +770,6 @@ fn add_test(&mut self, test: String, config: LangString, line: usize) {
                         .and_modify(|v| *v += 1)
                         .or_insert(0)
                 },
-                line = line,
             ));
 
             std::fs::create_dir_all(&path)
index bd9262191356f5e577fda51d1c59ffa1cbe5de21..20f747e2014158b3712c0501e078055c9db93d0e 100644 (file)
@@ -3,36 +3,22 @@
 crate use self::StructType::*;
 
 use rustc_ast as ast;
-use rustc_span::hygiene::MacroKind;
-use rustc_span::{self, Span, Symbol};
+use rustc_span::{self, symbol::Ident, Span, Symbol};
 
 use rustc_hir as hir;
-use rustc_hir::def_id::CrateNum;
-use rustc_hir::HirId;
 
 crate struct Module<'hir> {
     crate name: Option<Symbol>,
     crate attrs: &'hir [ast::Attribute],
     crate where_outer: Span,
     crate where_inner: Span,
-    crate extern_crates: Vec<ExternCrate<'hir>>,
     crate imports: Vec<Import<'hir>>,
-    crate structs: Vec<Struct<'hir>>,
-    crate unions: Vec<Union<'hir>>,
-    crate enums: Vec<Enum<'hir>>,
-    crate fns: Vec<Function<'hir>>,
     crate mods: Vec<Module<'hir>>,
     crate id: hir::HirId,
-    crate typedefs: Vec<Typedef<'hir>>,
-    crate opaque_tys: Vec<OpaqueTy<'hir>>,
-    crate statics: Vec<Static<'hir>>,
-    crate constants: Vec<Constant<'hir>>,
-    crate traits: Vec<Trait<'hir>>,
-    crate impls: Vec<Impl<'hir>>,
-    crate foreigns: Vec<ForeignItem<'hir>>,
+    // (item, renamed)
+    crate items: Vec<(&'hir hir::Item<'hir>, Option<Ident>)>,
+    crate foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option<Ident>)>,
     crate macros: Vec<Macro>,
-    crate proc_macros: Vec<ProcMacro>,
-    crate trait_aliases: Vec<TraitAlias<'hir>>,
     crate is_crate: bool,
 }
 
@@ -44,23 +30,11 @@ impl Module<'hir> {
             where_outer: rustc_span::DUMMY_SP,
             where_inner: rustc_span::DUMMY_SP,
             attrs,
-            extern_crates: Vec::new(),
             imports: Vec::new(),
-            structs: Vec::new(),
-            unions: Vec::new(),
-            enums: Vec::new(),
-            fns: Vec::new(),
             mods: Vec::new(),
-            typedefs: Vec::new(),
-            opaque_tys: Vec::new(),
-            statics: Vec::new(),
-            constants: Vec::new(),
-            traits: Vec::new(),
-            impls: Vec::new(),
+            items: Vec::new(),
             foreigns: Vec::new(),
             macros: Vec::new(),
-            proc_macros: Vec::new(),
-            trait_aliases: Vec::new(),
             is_crate: false,
         }
     }
@@ -76,116 +50,12 @@ impl Module<'hir> {
     Unit,
 }
 
-crate struct Struct<'hir> {
-    crate id: hir::HirId,
-    crate struct_type: StructType,
-    crate name: Symbol,
-    crate generics: &'hir hir::Generics<'hir>,
-    crate fields: &'hir [hir::StructField<'hir>],
-}
-
-crate struct Union<'hir> {
-    crate id: hir::HirId,
-    crate struct_type: StructType,
-    crate name: Symbol,
-    crate generics: &'hir hir::Generics<'hir>,
-    crate fields: &'hir [hir::StructField<'hir>],
-}
-
-crate struct Enum<'hir> {
-    crate variants: Vec<Variant<'hir>>,
-    crate generics: &'hir hir::Generics<'hir>,
-    crate id: hir::HirId,
-    crate name: Symbol,
-}
-
 crate struct Variant<'hir> {
     crate name: Symbol,
     crate id: hir::HirId,
     crate def: &'hir hir::VariantData<'hir>,
 }
 
-crate struct Function<'hir> {
-    crate decl: &'hir hir::FnDecl<'hir>,
-    crate id: hir::HirId,
-    crate name: Symbol,
-    crate header: hir::FnHeader,
-    crate generics: &'hir hir::Generics<'hir>,
-    crate body: hir::BodyId,
-}
-
-crate struct Typedef<'hir> {
-    crate ty: &'hir hir::Ty<'hir>,
-    crate gen: &'hir hir::Generics<'hir>,
-    crate name: Symbol,
-    crate id: hir::HirId,
-}
-
-crate struct OpaqueTy<'hir> {
-    crate opaque_ty: &'hir hir::OpaqueTy<'hir>,
-    crate name: Symbol,
-    crate id: hir::HirId,
-}
-
-#[derive(Debug)]
-crate struct Static<'hir> {
-    crate type_: &'hir hir::Ty<'hir>,
-    crate mutability: hir::Mutability,
-    crate expr: hir::BodyId,
-    crate name: Symbol,
-    crate attrs: &'hir [ast::Attribute],
-    crate vis: &'hir hir::Visibility<'hir>,
-    crate id: hir::HirId,
-    crate span: Span,
-}
-
-crate struct Constant<'hir> {
-    crate type_: &'hir hir::Ty<'hir>,
-    crate expr: hir::BodyId,
-    crate name: Symbol,
-    crate id: hir::HirId,
-}
-
-crate struct Trait<'hir> {
-    crate is_auto: hir::IsAuto,
-    crate unsafety: hir::Unsafety,
-    crate name: Symbol,
-    crate items: Vec<&'hir hir::TraitItem<'hir>>,
-    crate generics: &'hir hir::Generics<'hir>,
-    crate bounds: &'hir [hir::GenericBound<'hir>],
-    crate attrs: &'hir [ast::Attribute],
-    crate id: hir::HirId,
-}
-
-crate struct TraitAlias<'hir> {
-    crate name: Symbol,
-    crate generics: &'hir hir::Generics<'hir>,
-    crate bounds: &'hir [hir::GenericBound<'hir>],
-    crate id: hir::HirId,
-}
-
-#[derive(Debug)]
-crate struct Impl<'hir> {
-    crate unsafety: hir::Unsafety,
-    crate polarity: hir::ImplPolarity,
-    crate defaultness: hir::Defaultness,
-    crate constness: hir::Constness,
-    crate generics: &'hir hir::Generics<'hir>,
-    crate trait_: &'hir Option<hir::TraitRef<'hir>>,
-    crate for_: &'hir hir::Ty<'hir>,
-    crate items: Vec<&'hir hir::ImplItem<'hir>>,
-    crate attrs: &'hir [ast::Attribute],
-    crate span: Span,
-    crate vis: &'hir hir::Visibility<'hir>,
-    crate id: hir::HirId,
-}
-
-crate struct ForeignItem<'hir> {
-    crate id: hir::HirId,
-    crate name: Symbol,
-    crate kind: &'hir hir::ForeignItemKind<'hir>,
-}
-
 // For Macro we store the DefId instead of the NodeId, since we also create
 // these imported macro_rules (which only have a DUMMY_NODE_ID).
 crate struct Macro {
@@ -195,16 +65,6 @@ impl Module<'hir> {
     crate imported_from: Option<Symbol>,
 }
 
-crate struct ExternCrate<'hir> {
-    crate name: Symbol,
-    crate hir_id: HirId,
-    crate cnum: CrateNum,
-    crate path: Option<String>,
-    crate vis: &'hir hir::Visibility<'hir>,
-    crate attrs: &'hir [ast::Attribute],
-    crate span: Span,
-}
-
 #[derive(Debug)]
 crate struct Import<'hir> {
     crate name: Symbol,
@@ -216,13 +76,6 @@ impl Module<'hir> {
     crate span: Span,
 }
 
-crate struct ProcMacro {
-    crate name: Symbol,
-    crate id: hir::HirId,
-    crate kind: MacroKind,
-    crate helpers: Vec<Symbol>,
-}
-
 crate fn struct_type_from_def(vdata: &hir::VariantData<'_>) -> StructType {
     match *vdata {
         hir::VariantData::Struct(..) => Plain,
index a72860ef0a8fd1f01c3f4cf0bf48842ef6e9999d..285fabdc3723040d86124f21c78f7e00d13d2ade 100644 (file)
@@ -16,7 +16,7 @@ impl StripItem {
 
 crate trait DocFolder: Sized {
     fn fold_item(&mut self, item: Item) -> Option<Item> {
-        self.fold_item_recur(item)
+        Some(self.fold_item_recur(item))
     }
 
     /// don't override!
@@ -71,15 +71,12 @@ fn fold_inner_recur(&mut self, kind: ItemKind) -> ItemKind {
     }
 
     /// don't override!
-    fn fold_item_recur(&mut self, item: Item) -> Option<Item> {
-        let Item { attrs, name, source, visibility, def_id, kind, stability, deprecation } = item;
-
-        let kind = match kind {
+    fn fold_item_recur(&mut self, mut item: Item) -> Item {
+        item.kind = match item.kind {
             StrippedItem(box i) => StrippedItem(box self.fold_inner_recur(i)),
-            _ => self.fold_inner_recur(kind),
+            _ => self.fold_inner_recur(item.kind),
         };
-
-        Some(Item { attrs, name, source, kind, visibility, stability, deprecation, def_id })
+        item
     }
 
     fn fold_mod(&mut self, m: Module) -> Module {
index 917c1a95fdbf5c5e1f3050ea374e8f1b2c9c7d73..c3153f2d4b6ff5e7a106c1aea183a10c17ab9d2f 100644 (file)
@@ -187,11 +187,11 @@ impl Cache {
         // Favor linking to as local extern as possible, so iterate all crates in
         // reverse topological order.
         for &(_, ref e) in krate.externs.iter().rev() {
-            for &(def_id, prim, _) in &e.primitives {
+            for &(def_id, prim) in &e.primitives {
                 cache.primitive_locations.insert(prim, def_id);
             }
         }
-        for &(def_id, prim, _) in &krate.primitives {
+        for &(def_id, prim) in &krate.primitives {
             cache.primitive_locations.insert(prim, def_id);
         }
 
@@ -421,55 +421,52 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
 
         // Once we've recursively found all the generics, hoard off all the
         // implementations elsewhere.
-        let ret = self.fold_item_recur(item).and_then(|item| {
-            if let clean::Item { kind: clean::ImplItem(_), .. } = item {
-                // Figure out the id of this impl. This may map to a
-                // primitive rather than always to a struct/enum.
-                // Note: matching twice to restrict the lifetime of the `i` borrow.
-                let mut dids = FxHashSet::default();
-                if let clean::Item { kind: clean::ImplItem(ref i), .. } = item {
-                    match i.for_ {
-                        clean::ResolvedPath { did, .. }
-                        | clean::BorrowedRef {
-                            type_: box clean::ResolvedPath { did, .. }, ..
-                        } => {
-                            dids.insert(did);
-                        }
-                        ref t => {
-                            let did = t
-                                .primitive_type()
-                                .and_then(|t| self.primitive_locations.get(&t).cloned());
+        let item = self.fold_item_recur(item);
+        let ret = if let clean::Item { kind: clean::ImplItem(_), .. } = item {
+            // Figure out the id of this impl. This may map to a
+            // primitive rather than always to a struct/enum.
+            // Note: matching twice to restrict the lifetime of the `i` borrow.
+            let mut dids = FxHashSet::default();
+            if let clean::Item { kind: clean::ImplItem(ref i), .. } = item {
+                match i.for_ {
+                    clean::ResolvedPath { did, .. }
+                    | clean::BorrowedRef { type_: box clean::ResolvedPath { did, .. }, .. } => {
+                        dids.insert(did);
+                    }
+                    ref t => {
+                        let did = t
+                            .primitive_type()
+                            .and_then(|t| self.primitive_locations.get(&t).cloned());
 
-                            if let Some(did) = did {
-                                dids.insert(did);
-                            }
+                        if let Some(did) = did {
+                            dids.insert(did);
                         }
                     }
+                }
 
-                    if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) {
-                        for bound in generics {
-                            if let Some(did) = bound.def_id() {
-                                dids.insert(did);
-                            }
+                if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) {
+                    for bound in generics {
+                        if let Some(did) = bound.def_id() {
+                            dids.insert(did);
                         }
                     }
-                } else {
-                    unreachable!()
-                };
-                let impl_item = Impl { impl_item: item };
-                if impl_item.trait_did().map_or(true, |d| self.traits.contains_key(&d)) {
-                    for did in dids {
-                        self.impls.entry(did).or_insert(vec![]).push(impl_item.clone());
-                    }
-                } else {
-                    let trait_did = impl_item.trait_did().expect("no trait did");
-                    self.orphan_trait_impls.push((trait_did, dids, impl_item));
                 }
-                None
             } else {
-                Some(item)
+                unreachable!()
+            };
+            let impl_item = Impl { impl_item: item };
+            if impl_item.trait_did().map_or(true, |d| self.traits.contains_key(&d)) {
+                for did in dids {
+                    self.impls.entry(did).or_insert(vec![]).push(impl_item.clone());
+                }
+            } else {
+                let trait_did = impl_item.trait_did().expect("no trait did");
+                self.orphan_trait_impls.push((trait_did, dids, impl_item));
             }
-        });
+            None
+        } else {
+            Some(item)
+        };
 
         if pushed {
             self.stack.pop().expect("stack already empty");
index 880c859dd1b23e8fd5642bd38e23cf0bb374bad2..8ce686c65502f5b549e97603c4338a316a272267 100644 (file)
 #[cfg(test)]
 mod tests;
 
+/// Options for rendering Markdown in the main body of documentation.
 pub(crate) fn opts() -> Options {
     Options::ENABLE_TABLES | Options::ENABLE_FOOTNOTES | Options::ENABLE_STRIKETHROUGH
 }
 
+/// A subset of [`opts()`] used for rendering summaries.
+pub(crate) fn summary_opts() -> Options {
+    Options::ENABLE_STRIKETHROUGH
+}
+
 /// When `to_string` is called, this struct will emit the HTML corresponding to
 /// the rendered version of the contained markdown string.
 pub struct Markdown<'a>(
@@ -1021,11 +1027,7 @@ impl MarkdownSummaryLine<'_> {
             }
         };
 
-        let p = Parser::new_with_broken_link_callback(
-            md,
-            Options::ENABLE_STRIKETHROUGH,
-            Some(&mut replacer),
-        );
+        let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer));
 
         let mut s = String::new();
 
@@ -1047,7 +1049,7 @@ impl MarkdownSummaryLine<'_> {
 
     let mut s = String::with_capacity(md.len() * 3 / 2);
 
-    for event in Parser::new_ext(md, Options::ENABLE_STRIKETHROUGH) {
+    for event in Parser::new_ext(md, summary_opts()) {
         match &event {
             Event::Text(text) => s.push_str(text),
             Event::Code(code) => {
index 28f7a4d3162489714892bd5d49e954c817105f46..147a8d33765af4574f391668595a95944e80091f 100644 (file)
@@ -1194,6 +1194,16 @@ fn write_minify(
     }
 }
 
+fn write_srclink(cx: &Context, item: &clean::Item, buf: &mut Buffer, cache: &Cache) {
+    if let Some(l) = cx.src_href(item, cache) {
+        write!(
+            buf,
+            "<a class=\"srclink\" href=\"{}\" title=\"{}\">[src]</a>",
+            l, "goto source code"
+        )
+    }
+}
+
 #[derive(Debug, Eq, PartialEq, Hash)]
 struct ItemEntry {
     url: String,
@@ -1706,13 +1716,7 @@ fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer, cache: &Cache)
     // this page, and this link will be auto-clicked. The `id` attribute is
     // used to find the link to auto-click.
     if cx.shared.include_sources && !item.is_primitive() {
-        if let Some(l) = cx.src_href(item, cache) {
-            write!(
-                buf,
-                "<a class=\"srclink\" href=\"{}\" title=\"{}\">[src]</a>",
-                l, "goto source code"
-            );
-        }
+        write_srclink(cx, item, buf, cache);
     }
 
     write!(buf, "</span>"); // out-of-band
@@ -2624,7 +2628,7 @@ fn write_loading_content(w: &mut Buffer, extra_content: &str) {
         write!(w, "{}<span class=\"loading-content\">Loading content...</span>", extra_content)
     }
 
-    fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) {
+    fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item, cache: &Cache) {
         let name = m.name.as_ref().unwrap();
         info!("Documenting {} on {}", name, t.name.as_deref().unwrap_or_default());
         let item_type = m.type_();
@@ -2633,6 +2637,7 @@ fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) {
         render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl);
         write!(w, "</code>");
         render_stability_since(w, m, t);
+        write_srclink(cx, m, w, cache);
         write!(w, "</h3>");
         document(w, cx, m, Some(t));
     }
@@ -2644,8 +2649,8 @@ fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) {
             "Associated Types",
             "<div class=\"methods\">",
         );
-        for t in &types {
-            trait_item(w, cx, *t, it);
+        for t in types {
+            trait_item(w, cx, t, it, cache);
         }
         write_loading_content(w, "</div>");
     }
@@ -2657,8 +2662,8 @@ fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) {
             "Associated Constants",
             "<div class=\"methods\">",
         );
-        for t in &consts {
-            trait_item(w, cx, *t, it);
+        for t in consts {
+            trait_item(w, cx, t, it, cache);
         }
         write_loading_content(w, "</div>");
     }
@@ -2671,8 +2676,8 @@ fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) {
             "Required methods",
             "<div class=\"methods\">",
         );
-        for m in &required {
-            trait_item(w, cx, *m, it);
+        for m in required {
+            trait_item(w, cx, m, it, cache);
         }
         write_loading_content(w, "</div>");
     }
@@ -2683,8 +2688,8 @@ fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) {
             "Provided methods",
             "<div class=\"methods\">",
         );
-        for m in &provided {
-            trait_item(w, cx, *m, it);
+        for m in provided {
+            trait_item(w, cx, m, it, cache);
         }
         write_loading_content(w, "</div>");
     }
@@ -3693,13 +3698,7 @@ fn render_impl(
             StabilityLevel::Unstable { .. } => None,
         });
         render_stability_since_raw(w, since.as_deref(), outer_version);
-        if let Some(l) = cx.src_href(&i.impl_item, cache) {
-            write!(
-                w,
-                "<a class=\"srclink\" href=\"{}\" title=\"{}\">[src]</a>",
-                l, "goto source code"
-            );
-        }
+        write_srclink(cx, &i.impl_item, w, cache);
         write!(w, "</h3>");
 
         if trait_.is_some() {
@@ -3765,13 +3764,7 @@ fn doc_impl_item(
                     render_assoc_item(w, item, link.anchor(&id), ItemType::Impl);
                     write!(w, "</code>");
                     render_stability_since_raw(w, item.stable_since().as_deref(), outer_version);
-                    if let Some(l) = cx.src_href(item, cache) {
-                        write!(
-                            w,
-                            "<a class=\"srclink\" href=\"{}\" title=\"{}\">[src]</a>",
-                            l, "goto source code"
-                        );
-                    }
+                    write_srclink(cx, item, w, cache);
                     write!(w, "</h4>");
                 }
             }
@@ -3787,13 +3780,7 @@ fn doc_impl_item(
                 assoc_const(w, item, ty, default.as_ref(), link.anchor(&id), "");
                 write!(w, "</code>");
                 render_stability_since_raw(w, item.stable_since().as_deref(), outer_version);
-                if let Some(l) = cx.src_href(item, cache) {
-                    write!(
-                        w,
-                        "<a class=\"srclink\" href=\"{}\" title=\"{}\">[src]</a>",
-                        l, "goto source code"
-                    );
-                }
+                write_srclink(cx, item, w, cache);
                 write!(w, "</h4>");
             }
             clean::AssocTypeItem(ref bounds, ref default) => {
index 0f82649409f360ef83495821afac70a946832c18..e7b5a90d84df0c311be9973f911dfb95e154b714 100644 (file)
@@ -60,7 +60,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                 }
             };
         }
-        self.fold_item_recur(item)
+        Some(self.fold_item_recur(item))
     }
 }
 
index b8377dc15696dd77cb15df97dd5ca9ef6ed04ed3..b11bd66709327ca20f005035c3395391226ae7dd 100644 (file)
@@ -2332,12 +2332,18 @@ function defocusSearchBar() {
             var dontApplyBlockRule = toggle.parentNode.parentNode.id !== "main";
             if (action === "show") {
                 removeClass(relatedDoc, "fns-now-collapsed");
-                removeClass(docblock, "hidden-by-usual-hider");
+                // Stability information is never hidden.
+                if (hasClass(docblock, "stability") === false) {
+                    removeClass(docblock, "hidden-by-usual-hider");
+                }
                 onEachLazy(toggle.childNodes, adjustToggle(false, dontApplyBlockRule));
                 onEachLazy(relatedDoc.childNodes, implHider(false, dontApplyBlockRule));
             } else if (action === "hide") {
                 addClass(relatedDoc, "fns-now-collapsed");
-                addClass(docblock, "hidden-by-usual-hider");
+                // Stability information should be shown even when detailed info is hidden.
+                if (hasClass(docblock, "stability") === false) {
+                    addClass(docblock, "hidden-by-usual-hider");
+                }
                 onEachLazy(toggle.childNodes, adjustToggle(true, dontApplyBlockRule));
                 onEachLazy(relatedDoc.childNodes, implHider(true, dontApplyBlockRule));
             }
index 7eccb09b073670fa93abf0656593142b2df7163c..7d22913b99de909028c83571a3324e0efff4ac11 100644 (file)
@@ -659,7 +659,7 @@ a {
        text-decoration: underline;
 }
 
-.invisible > .srclink, h4 > code + .srclink {
+.invisible > .srclink, h4 > code + .srclink, h3 > code + .srclink {
        position: absolute;
        top: 0;
        right: 0;
@@ -857,25 +857,25 @@ body.blur > :not(#help) {
        top: 0;
 }
 
-.impl-items .since, .impl .since {
+.impl-items .since, .impl .since, .methods .since {
        flex-grow: 0;
        padding-left: 12px;
        padding-right: 2px;
        position: initial;
 }
 
-.impl-items .srclink, .impl .srclink {
+.impl-items .srclink, .impl .srclink, .methods .srclink {
        flex-grow: 0;
        /* Override header settings otherwise it's too bold */
        font-size: 17px;
        font-weight: normal;
 }
 
-.impl-items code, .impl code {
+.impl-items code, .impl code, .methods code {
        flex-grow: 1;
 }
 
-.impl-items h4, h4.impl, h3.impl {
+.impl-items h4, h4.impl, h3.impl, .methods h3 {
        display: flex;
        flex-basis: 100%;
        font-size: 16px;
index a88efba77b41cc7efb0406d4971166a098c0022e..751f2301053926ae189b19c16d9acaf068bcad6d 100644 (file)
@@ -513,7 +513,7 @@ fn main_options(options: config::Options) -> MainResult {
     }
 
     // need to move these items separately because we lose them by the time the closure is called,
-    // but we can't crates the Handler ahead of time because it's not Send
+    // but we can't create the Handler ahead of time because it's not Send
     let diag_opts = (options.error_format, options.edition, options.debugging_opts.clone());
     let show_coverage = options.show_coverage;
     let run_check = options.run_check;
index aca218e538165c87b0c758c4e355ab7facd83590..3f9978c8fca84ef1df1c33b34aaf4d7b944595e4 100644 (file)
@@ -268,6 +268,6 @@ fn fold_item(&mut self, i: clean::Item) -> Option<clean::Item> {
             }
         }
 
-        self.fold_item_recur(i)
+        Some(self.fold_item_recur(i))
     }
 }
index a48fa738e3b727cc944500e82bc5c0006e92be88..0c76dc571beee1406cbdf25cad38f0587c358d6c 100644 (file)
@@ -105,7 +105,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
             }
         }
 
-        self.fold_item_recur(item)
+        Some(self.fold_item_recur(item))
     }
 }
 
index 1f9f5c58e5a93279277231a38c2edf09c6bc6d2f..e1ba75baa0fa48ac47e6e9355716a436921a7e1e 100644 (file)
@@ -23,7 +23,7 @@
 impl fold::DocFolder for Collapser {
     fn fold_item(&mut self, mut i: Item) -> Option<Item> {
         i.attrs.collapse_doc_comments();
-        self.fold_item_recur(i)
+        Some(self.fold_item_recur(i))
     }
 }
 
index 895414b1d7e4c8c1e280ad6681fca0192ff2d356..6aa46b24a0e96df442f56ca1689f922eea05c737 100644 (file)
@@ -492,7 +492,14 @@ fn resolve<'path>(
             Res::PrimTy(prim) => Some(
                 self.resolve_primitive_associated_item(prim, ns, module_id, item_name, item_str),
             ),
-            Res::Def(DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::TyAlias, did) => {
+            Res::Def(
+                DefKind::Struct
+                | DefKind::Union
+                | DefKind::Enum
+                | DefKind::TyAlias
+                | DefKind::ForeignTy,
+                did,
+            ) => {
                 debug!("looking for associated item named {} for item {:?}", item_name, did);
                 // Checks if item_name belongs to `impl SomeItem`
                 let assoc_item = cx
@@ -851,7 +858,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
             // we don't display docs on `extern crate` items anyway, so don't process them.
             clean::ExternCrateItem(..) => {
                 debug!("ignoring extern crate item {:?}", item.def_id);
-                return self.fold_item_recur(item);
+                return Some(self.fold_item_recur(item));
             }
             clean::ImportItem(Import { kind: clean::ImportKind::Simple(ref name, ..), .. }) => {
                 Some(name.clone())
@@ -951,7 +958,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
             }
         }
 
-        if item.is_mod() {
+        Some(if item.is_mod() {
             if !item.attrs.inner_docs {
                 self.mod_ids.push(item.def_id);
             }
@@ -961,7 +968,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
             ret
         } else {
             self.fold_item_recur(item)
-        }
+        })
     }
 }
 
@@ -1015,7 +1022,7 @@ fn resolve_link(
             (link.trim(), None)
         };
 
-        if path_str.contains(|ch: char| !(ch.is_alphanumeric() || ":_<>, ".contains(ch))) {
+        if path_str.contains(|ch: char| !(ch.is_alphanumeric() || ":_<>, !".contains(ch))) {
             return None;
         }
 
index 2946db1f46206d2acbcd6128deba7c2aea461fda..4c3defabc3294bb8f95bda70fcf8bca9635c2721 100644 (file)
@@ -133,7 +133,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
             }
         }
 
-        self.fold_item_recur(i)
+        Some(self.fold_item_recur(i))
     }
 }
 
@@ -152,7 +152,7 @@ impl DocFolder for ItemCollector {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
         self.items.insert(i.def_id);
 
-        self.fold_item_recur(i)
+        Some(self.fold_item_recur(i))
     }
 }
 
index 60fe8080f56b41dc817c8f5714788c3cfb0d270a..299a73c8a0112453f6d1f87f3c62607c35125b5c 100644 (file)
@@ -41,7 +41,7 @@ fn fold_item(&mut self, item: Item) -> Option<Item> {
 
         look_for_tests(&cx, &dox, &item);
 
-        self.fold_item_recur(item)
+        Some(self.fold_item_recur(item))
     }
 }
 
index 70748633117fb27e2bf0185b0dcb27f2920712e5..a7a1ba1118d1fdca65a325bdfe1be69709719c24 100644 (file)
@@ -178,7 +178,7 @@ fn fold_item(&mut self, item: Item) -> Option<Item> {
             Some(hir_id) => hir_id,
             None => {
                 // If non-local, no need to check anything.
-                return self.fold_item_recur(item);
+                return Some(self.fold_item_recur(item));
             }
         };
         let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
@@ -223,6 +223,6 @@ fn fold_item(&mut self, item: Item) -> Option<Item> {
             }
         }
 
-        self.fold_item_recur(item)
+        Some(self.fold_item_recur(item))
     }
 }
index c9c49968b93e1be6b1918147cb33d586ff7c6294..1f411b997f80250e5734e55f8151091f0d7674bc 100644 (file)
@@ -68,7 +68,7 @@ fn fold_item(&mut self, item: Item) -> Option<Item> {
             Some(hir_id) => hir_id,
             None => {
                 // If non-local, no need to check anything.
-                return self.fold_item_recur(item);
+                return Some(self.fold_item_recur(item));
             }
         };
         let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
@@ -133,6 +133,6 @@ fn fold_item(&mut self, item: Item) -> Option<Item> {
             }
         }
 
-        self.fold_item_recur(item)
+        Some(self.fold_item_recur(item))
     }
 }
index fbfc693c5347de06801e391469df798a1fee6f87..6722d7c2fc9feaa998c9e3857b9e17ba6a5b3725 100644 (file)
@@ -39,6 +39,6 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
         let result = self.fold_item_recur(item);
         self.parent_cfg = old_parent_cfg;
 
-        result
+        Some(result)
     }
 }
index 6da753ea6e695b91c5bd7271a752c2e34513ff22..6b59eb8cf288a8246ad06462d92e1c9e93fc41d2 100644 (file)
@@ -47,7 +47,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
                     // strip things like impl methods but when doing so
                     // we must not add any items to the `retained` set.
                     let old = mem::replace(&mut self.update_retained, false);
-                    let ret = StripItem(self.fold_item_recur(i).unwrap()).strip();
+                    let ret = StripItem(self.fold_item_recur(i)).strip();
                     self.update_retained = old;
                     return ret;
                 }
@@ -58,6 +58,6 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
                 self.retained.insert(i.def_id);
             }
         }
-        self.fold_item_recur(i)
+        Some(self.fold_item_recur(i))
     }
 }
index eb5a61a9d202a669ad45b8639e4aa61953ac1d0e..444fd593ec9c9856bef17f84fca3cfe3fdbb4f7d 100644 (file)
@@ -22,7 +22,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
                 let old = mem::replace(&mut self.update_retained, false);
                 let ret = self.fold_item_recur(i);
                 self.update_retained = old;
-                return ret;
+                return Some(ret);
             }
             // These items can all get re-exported
             clean::OpaqueTyItem(..)
@@ -59,7 +59,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
                 if i.def_id.is_local() && !i.visibility.is_public() {
                     debug!("Stripper: stripping module {:?}", i.name);
                     let old = mem::replace(&mut self.update_retained, false);
-                    let ret = StripItem(self.fold_item_recur(i).unwrap()).strip();
+                    let ret = StripItem(self.fold_item_recur(i)).strip();
                     self.update_retained = old;
                     return ret;
                 }
@@ -107,12 +107,10 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
             self.fold_item_recur(i)
         };
 
-        if let Some(ref i) = i {
-            if self.update_retained {
-                self.retained.insert(i.def_id);
-            }
+        if self.update_retained {
+            self.retained.insert(i.def_id);
         }
-        i
+        Some(i)
     }
 }
 
@@ -153,7 +151,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
                 }
             }
         }
-        self.fold_item_recur(i)
+        Some(self.fold_item_recur(i))
     }
 }
 
@@ -164,7 +162,7 @@ impl DocFolder for ImportStripper {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
         match i.kind {
             clean::ExternCrateItem(..) | clean::ImportItem(..) if !i.visibility.is_public() => None,
-            _ => self.fold_item_recur(i),
+            _ => Some(self.fold_item_recur(i)),
         }
     }
 }
index eb2f066bbdebb1afb64a2e4d34863275e520e5cb..d0345d1e48cb5958726d3cbcecb182bd58aa5be8 100644 (file)
@@ -23,7 +23,7 @@
 impl fold::DocFolder for CommentCleaner {
     fn fold_item(&mut self, mut i: Item) -> Option<Item> {
         i.attrs.unindent_doc_comments();
-        self.fold_item_recur(i)
+        Some(self.fold_item_recur(i))
     }
 }
 
index 76fae11291805604cb88cc0ccd6adbd2b42ad74e..02152edbbc21c95a98b341e106d85feb0123df4b 100644 (file)
@@ -5,11 +5,10 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::def_id::DefId;
 use rustc_hir::Node;
 use rustc_middle::middle::privacy::AccessLevel;
 use rustc_middle::ty::TyCtxt;
-use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{self, Span};
@@ -82,107 +81,6 @@ fn store_path(&mut self, did: DefId) {
         module
     }
 
-    fn visit_variant_data(
-        &mut self,
-        item: &'tcx hir::Item<'_>,
-        name: Symbol,
-        sd: &'tcx hir::VariantData<'_>,
-        generics: &'tcx hir::Generics<'_>,
-    ) -> Struct<'tcx> {
-        debug!("visiting struct");
-        let struct_type = struct_type_from_def(&*sd);
-        Struct { id: item.hir_id, struct_type, name, generics, fields: sd.fields() }
-    }
-
-    fn visit_union_data(
-        &mut self,
-        item: &'tcx hir::Item<'_>,
-        name: Symbol,
-        sd: &'tcx hir::VariantData<'_>,
-        generics: &'tcx hir::Generics<'_>,
-    ) -> Union<'tcx> {
-        debug!("visiting union");
-        let struct_type = struct_type_from_def(&*sd);
-        Union { id: item.hir_id, struct_type, name, generics, fields: sd.fields() }
-    }
-
-    fn visit_enum_def(
-        &mut self,
-        it: &'tcx hir::Item<'_>,
-        name: Symbol,
-        def: &'tcx hir::EnumDef<'_>,
-        generics: &'tcx hir::Generics<'_>,
-    ) -> Enum<'tcx> {
-        debug!("visiting enum");
-        Enum {
-            name,
-            variants: def
-                .variants
-                .iter()
-                .map(|v| Variant { name: v.ident.name, id: v.id, def: &v.data })
-                .collect(),
-            generics,
-            id: it.hir_id,
-        }
-    }
-
-    fn visit_fn(
-        &mut self,
-        om: &mut Module<'tcx>,
-        item: &'tcx hir::Item<'_>,
-        name: Symbol,
-        decl: &'tcx hir::FnDecl<'_>,
-        header: hir::FnHeader,
-        generics: &'tcx hir::Generics<'_>,
-        body: hir::BodyId,
-    ) {
-        debug!("visiting fn");
-        let macro_kind = item.attrs.iter().find_map(|a| {
-            if a.has_name(sym::proc_macro) {
-                Some(MacroKind::Bang)
-            } else if a.has_name(sym::proc_macro_derive) {
-                Some(MacroKind::Derive)
-            } else if a.has_name(sym::proc_macro_attribute) {
-                Some(MacroKind::Attr)
-            } else {
-                None
-            }
-        });
-        match macro_kind {
-            Some(kind) => {
-                let name = if kind == MacroKind::Derive {
-                    item.attrs
-                        .lists(sym::proc_macro_derive)
-                        .find_map(|mi| mi.ident())
-                        .expect("proc-macro derives require a name")
-                        .name
-                } else {
-                    name
-                };
-
-                let mut helpers = Vec::new();
-                for mi in item.attrs.lists(sym::proc_macro_derive) {
-                    if !mi.has_name(sym::attributes) {
-                        continue;
-                    }
-
-                    if let Some(list) = mi.meta_item_list() {
-                        for inner_mi in list {
-                            if let Some(ident) = inner_mi.ident() {
-                                helpers.push(ident.name);
-                            }
-                        }
-                    }
-                }
-
-                om.proc_macros.push(ProcMacro { name, id: item.hir_id, kind, helpers });
-            }
-            None => {
-                om.fns.push(Function { id: item.hir_id, decl, name, generics, header, body });
-            }
-        }
-    }
-
     fn visit_mod_contents(
         &mut self,
         span: Span,
@@ -342,26 +240,15 @@ fn visit_item(
         }
 
         match item.kind {
-            hir::ItemKind::ForeignMod(ref fm) => {
-                for item in fm.items {
+            hir::ItemKind::ForeignMod { items, .. } => {
+                for item in items {
+                    let item = self.cx.tcx.hir().foreign_item(item.id);
                     self.visit_foreign_item(item, None, om);
                 }
             }
             // If we're inlining, skip private items.
             _ if self.inlining && !item.vis.node.is_pub() => {}
             hir::ItemKind::GlobalAsm(..) => {}
-            hir::ItemKind::ExternCrate(orig_name) => {
-                let def_id = self.cx.tcx.hir().local_def_id(item.hir_id);
-                om.extern_crates.push(ExternCrate {
-                    cnum: self.cx.tcx.extern_mod_stmt_cnum(def_id).unwrap_or(LOCAL_CRATE),
-                    name: ident.name,
-                    hir_id: item.hir_id,
-                    path: orig_name.map(|x| x.to_string()),
-                    vis: &item.vis,
-                    attrs: &item.attrs,
-                    span: item.span,
-                })
-            }
             hir::ItemKind::Use(_, hir::UseKind::ListStem) => {}
             hir::ItemKind::Use(ref path, kind) => {
                 let is_glob = kind == hir::UseKind::Glob;
@@ -414,97 +301,28 @@ fn visit_item(
                     Some(ident.name),
                 ));
             }
-            hir::ItemKind::Enum(ref ed, ref gen) => {
-                om.enums.push(self.visit_enum_def(item, ident.name, ed, gen))
-            }
-            hir::ItemKind::Struct(ref sd, ref gen) => {
-                om.structs.push(self.visit_variant_data(item, ident.name, sd, gen))
-            }
-            hir::ItemKind::Union(ref sd, ref gen) => {
-                om.unions.push(self.visit_union_data(item, ident.name, sd, gen))
-            }
-            hir::ItemKind::Fn(ref sig, ref gen, body) => {
-                self.visit_fn(om, item, ident.name, &sig.decl, sig.header, gen, body)
-            }
-            hir::ItemKind::TyAlias(ty, ref gen) => {
-                let t = Typedef { ty, gen, name: ident.name, id: item.hir_id };
-                om.typedefs.push(t);
-            }
-            hir::ItemKind::OpaqueTy(ref opaque_ty) => {
-                let t = OpaqueTy { opaque_ty, name: ident.name, id: item.hir_id };
-                om.opaque_tys.push(t);
-            }
-            hir::ItemKind::Static(type_, mutability, expr) => {
-                let s = Static {
-                    type_,
-                    mutability,
-                    expr,
-                    id: item.hir_id,
-                    name: ident.name,
-                    attrs: &item.attrs,
-                    span: item.span,
-                    vis: &item.vis,
-                };
-                om.statics.push(s);
-            }
-            hir::ItemKind::Const(type_, expr) => {
+            hir::ItemKind::Fn(..)
+            | hir::ItemKind::ExternCrate(..)
+            | hir::ItemKind::Enum(..)
+            | hir::ItemKind::Struct(..)
+            | hir::ItemKind::Union(..)
+            | hir::ItemKind::TyAlias(..)
+            | hir::ItemKind::OpaqueTy(..)
+            | hir::ItemKind::Static(..)
+            | hir::ItemKind::Trait(..)
+            | hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed)),
+            hir::ItemKind::Const(..) => {
                 // Underscore constants do not correspond to a nameable item and
                 // so are never useful in documentation.
                 if ident.name != kw::Underscore {
-                    let s = Constant { type_, expr, id: item.hir_id, name: ident.name };
-                    om.constants.push(s);
+                    om.items.push((item, renamed));
                 }
             }
-            hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => {
-                let items = item_ids.iter().map(|ti| self.cx.tcx.hir().trait_item(ti.id)).collect();
-                let t = Trait {
-                    is_auto,
-                    unsafety,
-                    name: ident.name,
-                    items,
-                    generics,
-                    bounds,
-                    id: item.hir_id,
-                    attrs: &item.attrs,
-                };
-                om.traits.push(t);
-            }
-            hir::ItemKind::TraitAlias(ref generics, ref bounds) => {
-                let t = TraitAlias { name: ident.name, generics, bounds, id: item.hir_id };
-                om.trait_aliases.push(t);
-            }
-
-            hir::ItemKind::Impl {
-                unsafety,
-                polarity,
-                defaultness,
-                constness,
-                defaultness_span: _,
-                ref generics,
-                ref of_trait,
-                self_ty,
-                ref items,
-            } => {
+            hir::ItemKind::Impl { ref of_trait, .. } => {
                 // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
                 // them up regardless of where they're located.
                 if !self.inlining && of_trait.is_none() {
-                    let items =
-                        items.iter().map(|item| self.cx.tcx.hir().impl_item(item.id)).collect();
-                    let i = Impl {
-                        unsafety,
-                        polarity,
-                        defaultness,
-                        constness,
-                        generics,
-                        trait_: of_trait,
-                        for_: self_ty,
-                        items,
-                        attrs: &item.attrs,
-                        id: item.hir_id,
-                        span: item.span,
-                        vis: &item.vis,
-                    };
-                    om.impls.push(i);
+                    om.items.push((item, None));
                 }
             }
         }
@@ -517,15 +335,9 @@ fn visit_foreign_item(
         om: &mut Module<'tcx>,
     ) {
         // If inlining we only want to include public functions.
-        if self.inlining && !item.vis.node.is_pub() {
-            return;
+        if !self.inlining || item.vis.node.is_pub() {
+            om.foreigns.push((item, renamed));
         }
-
-        om.foreigns.push(ForeignItem {
-            id: item.hir_id,
-            name: renamed.unwrap_or(item.ident).name,
-            kind: &item.kind,
-        });
     }
 
     // Convert each `exported_macro` into a doc item.
index dae9d219b7b9be9bb41a3682d791d2c55eb4e004..6e05b66c3fe4acdc1babb334a2e1bb350e11038b 100644 (file)
 # stable release's version number. `date` is the date where the release we're
 # bootstrapping off was released.
 
-date: 2020-10-16
+date: 2020-11-18
 rustc: beta
 
 # We use a nightly rustfmt to format the source because it solves some
 # bootstrapping issues with use of new syntax in this repo. If you're looking at
 # the beta/stable branch, this key should be omitted, as we don't want to depend
 # on rustfmt from nightly there.
-rustfmt: nightly-2020-10-12
+rustfmt: nightly-2020-11-19
 
 # When making a stable release the process currently looks like:
 #
index 73631b92c1f33463271646907d46abd71540a40b..bb3134e81c930719e059774f3b7060389a9c61cc 100644 (file)
@@ -1,6 +1,5 @@
 // This test is for *-windows-msvc only.
 // ignore-android
-// ignore-cloudabi
 // ignore-dragonfly
 // ignore-emscripten
 // ignore-freebsd
diff --git a/src/test/codegen/fewer-names.rs b/src/test/codegen/fewer-names.rs
new file mode 100644 (file)
index 0000000..53a926d
--- /dev/null
@@ -0,0 +1,20 @@
+// no-system-llvm
+// compile-flags: -Coverflow-checks=no -O
+// revisions: YES NO
+// [YES]compile-flags: -Zfewer-names=yes
+// [NO] compile-flags: -Zfewer-names=no
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn sum(x: u32, y: u32) -> u32 {
+// YES-LABEL: define i32 @sum(i32 %0, i32 %1)
+// YES-NEXT:    %3 = add i32 %1, %0
+// YES-NEXT:    ret i32 %3
+
+// NO-LABEL: define i32 @sum(i32 %x, i32 %y)
+// NO-NEXT:  start:
+// NO-NEXT:    %z = add i32 %y, %x
+// NO-NEXT:    ret i32 %z
+    let z = x + y;
+    z
+}
index 5e76f1d67e6f7ea9d7d1912fa4ffacfcd75b3fac..43a6be465bcf83291264975f4b414fc2eec967e6 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -C no-prepopulate-passes -Zmir-opt-level=0
+// compile-flags: -C no-prepopulate-passes
 
 #![crate_type = "lib"]
 #![feature(naked_functions)]
@@ -15,11 +15,9 @@ pub fn naked_empty() {
 // CHECK: Function Attrs: naked
 #[no_mangle]
 #[naked]
-// CHECK-NEXT: define void @naked_with_args(i{{[0-9]+( %0)?}})
+// CHECK-NEXT: define void @naked_with_args(i{{[0-9]+( %a)?}})
 pub fn naked_with_args(a: isize) {
     // CHECK-NEXT: {{.+}}:
-    // CHECK-NEXT: %a = alloca i{{[0-9]+}}
-    &a; // keep variable in an alloca
     // CHECK: ret void
 }
 
@@ -34,53 +32,11 @@ pub fn naked_with_return() -> isize {
 }
 
 // CHECK: Function Attrs: naked
-// CHECK-NEXT: define i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+( %0)?}})
+// CHECK-NEXT: define i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+( %a)?}})
 #[no_mangle]
 #[naked]
 pub fn naked_with_args_and_return(a: isize) -> isize {
     // CHECK-NEXT: {{.+}}:
-    // CHECK-NEXT: %a = alloca i{{[0-9]+}}
-    &a; // keep variable in an alloca
-    // CHECK: ret i{{[0-9]+}} %{{[0-9]+}}
-    a
-}
-
-// CHECK: Function Attrs: naked
-// CHECK-NEXT: define void @naked_recursive()
-#[no_mangle]
-#[naked]
-pub fn naked_recursive() {
-    // CHECK-NEXT: {{.+}}:
-    // CHECK-NEXT: call void @naked_empty()
-
-    // FIXME(#39685) Avoid one block per call.
-    // CHECK-NEXT: br label %bb1
-    // CHECK: bb1:
-
-    naked_empty();
-
-    // CHECK-NEXT: %_4 = call i{{[0-9]+}} @naked_with_return()
-
-    // FIXME(#39685) Avoid one block per call.
-    // CHECK-NEXT: br label %bb2
-    // CHECK: bb2:
-
-    // CHECK-NEXT: %_3 = call i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}} %_4)
-
-    // FIXME(#39685) Avoid one block per call.
-    // CHECK-NEXT: br label %bb3
-    // CHECK: bb3:
-
-    // CHECK-NEXT: call void @naked_with_args(i{{[0-9]+}} %_3)
-
-    // FIXME(#39685) Avoid one block per call.
-    // CHECK-NEXT: br label %bb4
-    // CHECK: bb4:
-
-    naked_with_args(
-        naked_with_args_and_return(
-            naked_with_return()
-        )
-    );
-    // CHECK-NEXT: ret void
+    // CHECK: ret i{{[0-9]+}} 0
+    0
 }
diff --git a/src/test/codegen/naked-noinline.rs b/src/test/codegen/naked-noinline.rs
new file mode 100644 (file)
index 0000000..2a2208d
--- /dev/null
@@ -0,0 +1,30 @@
+// Checks that naked functions are never inlined.
+// compile-flags: -O -Zmir-opt-level=2
+// ignore-wasm32
+#![crate_type = "lib"]
+#![feature(asm)]
+#![feature(naked_functions)]
+
+#[inline(always)]
+#[naked]
+#[no_mangle]
+pub unsafe extern "C" fn f() {
+// Check that f has naked and noinline attributes.
+//
+// CHECK:       define void @f() unnamed_addr [[ATTR:#[0-9]+]]
+// CHECK-NEXT:  start:
+// CHECK-NEXT:    call void asm
+    asm!("", options(noreturn));
+}
+
+#[no_mangle]
+pub unsafe fn g() {
+// Check that call to f is not inlined.
+//
+// CHECK-LABEL: define void @g()
+// CHECK-NEXT:  start:
+// CHECK-NEXT:    call void @f()
+    f();
+}
+
+// CHECK: attributes [[ATTR]] = { naked noinline{{.*}} }
index 8e38245267d41381ae9bc6a3cb179dd79dbbf1f5..9ee4bfc4711683dd63ec8e8845dcb3b4b6e67a19 100644 (file)
@@ -1,6 +1,5 @@
 // This test is for *-windows-msvc only.
 // ignore-android
-// ignore-cloudabi
 // ignore-dragonfly
 // ignore-emscripten
 // ignore-freebsd
diff --git a/src/test/codegen/to_vec.rs b/src/test/codegen/to_vec.rs
new file mode 100644 (file)
index 0000000..60dc4ef
--- /dev/null
@@ -0,0 +1,10 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @copy_to_vec
+#[no_mangle]
+fn copy_to_vec(s: &[u64]) -> Vec<u64> {
+  s.to_vec()
+  // CHECK: call void @llvm.memcpy
+}
index cc2a3a345102aace498beff496b51269d4145ced..8026550882d0015bd603ff0d4a3555dd7d51aebf 100644 (file)
@@ -2,6 +2,7 @@
 // ignore-windows failing on win32 bot
 // ignore-freebsd: gdb package too new
 // ignore-android: FIXME(#10381)
+// ignore-macos: FIXME(#78665)
 // compile-flags:-g
 
 // The pretty printers being tested here require the patch from
@@ -101,7 +102,7 @@ fn main() {
         btree_set.insert(i);
     }
 
-    let mut empty_btree_set: BTreeSet<i32> = BTreeSet::new();
+    let empty_btree_set: BTreeSet<i32> = BTreeSet::new();
 
     // BTreeMap
     let mut btree_map = BTreeMap::new();
@@ -109,7 +110,7 @@ fn main() {
         btree_map.insert(i, i);
     }
 
-    let mut empty_btree_map: BTreeMap<i32, u32> = BTreeMap::new();
+    let empty_btree_map: BTreeMap<i32, u32> = BTreeMap::new();
 
     let mut option_btree_map: BTreeMap<bool, Option<bool>> = BTreeMap::new();
     option_btree_map.insert(false, None);
index 7ae82d522b09dc37dfe588b52b7da46a4d428501..6632488171dad9fbab3218dfb65c62307b2e8f26 100644 (file)
@@ -13,7 +13,7 @@
 // gdb-check:$1 = &[i32](len: 4) = {0, 1, 2, 3}
 
 // gdb-command: print vec
-// gdb-check:$2 = Vec<u64>(len: 4, cap: [...]) = {4, 5, 6, 7}
+// gdb-check:$2 = Vec<u64, alloc::alloc::Global>(len: 4, cap: [...]) = {4, 5, 6, 7}
 
 // gdb-command: print str_slice
 // gdb-check:$3 = "IAMA string slice!"
@@ -74,7 +74,7 @@
 // NOTE: While slices have a .natvis entry that works in VS & VS Code, it fails in CDB 10.0.18362.1
 
 // cdb-command: dx vec,d
-// cdb-check:vec,d [...] : { size=4 } [Type: [...]::Vec<u64>]
+// cdb-check:vec,d [...] : { size=4 } [Type: [...]::Vec<u64, alloc::alloc::Global>]
 // cdb-check:    [size]           : 4 [Type: [...]]
 // cdb-check:    [capacity]       : [...] [Type: [...]]
 // cdb-check:    [0]              : 4 [Type: unsigned __int64]
index 2af72f0e98764838b2241b6c6537ed2267e70a87..f698f8835a26ad0c5ce3b9b6160bc063b407d409 100644 (file)
@@ -5,7 +5,7 @@
 // revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
 // aux-build:point.rs
-// build-pass (FIXME(62277): could be check-pass?)
+// build-pass
 
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
index 89699bce209f0e8cfae4d5fcebeb2890b6b67df9..8d98cfac8a4d250870ad58df34fcea4834e85377 100644 (file)
@@ -5,7 +5,7 @@
 
 // revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
-// build-pass (FIXME(62277): could be check-pass?)
+// build-pass
 
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
index 5c024ed91a3bfb1717938bec35a1130b57ed72ff..11ba96a8c8d5f0a03b3852a0554125f32cadf2d7 100644 (file)
@@ -3,7 +3,7 @@
 
 // revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
-// build-pass (FIXME(62277): could be check-pass?)
+// build-pass
 
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
index c944901e34542ecdcbbc81702f41b45e69c434a7..a192dff19e9f3aa103f259a3095a8b20189cff1a 100644 (file)
@@ -2,7 +2,7 @@
 
 // revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
-// build-pass (FIXME(62277): could be check-pass?)
+// build-pass
 
 #![crate_type = "rlib"]
 #![feature(rustc_attrs)]
index 4a5aac682f5aaa173f3b4e63f73467c2deef25df..b0476168555869d68c0242acfc3ad3d9bb5db0b5 100644 (file)
@@ -2,7 +2,7 @@
 
 // revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
-// build-pass (FIXME(62277): could be check-pass?)
+// build-pass
 
 #![crate_type = "rlib"]
 #![feature(rustc_attrs)]
index 0b9a0fd79451a1ea1db4d9e61bd6d28d2ea3b70d..dd7751677579c2404e936fcfb08dc87c27438f6e 100644 (file)
 #![feature(rustc_attrs)]
 #![feature(unboxed_closures)]
 #![feature(link_args)]
-#![crate_type="rlib"]
-
+#![crate_type = "rlib"]
 
 // Change function name --------------------------------------------------------
 #[cfg(cfail1)]
-extern {
+extern "C" {
     pub fn change_function_name1(c: i64) -> i32;
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-extern {
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+extern "C" {
     pub fn change_function_name2(c: i64) -> i32;
 }
 
-
-
 // Change parameter name -------------------------------------------------------
 #[cfg(cfail1)]
-extern {
+extern "C" {
     pub fn change_parameter_name(c: i64) -> i32;
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-extern {
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+extern "C" {
     pub fn change_parameter_name(d: i64) -> i32;
 }
 
-
-
 // Change parameter type -------------------------------------------------------
 #[cfg(cfail1)]
-extern {
+extern "C" {
     pub fn change_parameter_type(c: i64) -> i32;
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-extern {
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+extern "C" {
     pub fn change_parameter_type(c: i32) -> i32;
 }
 
-
-
 // Change return type ----------------------------------------------------------
 #[cfg(cfail1)]
-extern {
+extern "C" {
     pub fn change_return_type(c: i32) -> i32;
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-extern {
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+extern "C" {
     pub fn change_return_type(c: i32) -> i8;
 }
 
-
-
 // Add parameter ---------------------------------------------------------------
 #[cfg(cfail1)]
-extern {
+extern "C" {
     pub fn add_parameter(c: i32) -> i32;
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-extern {
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+extern "C" {
     pub fn add_parameter(c: i32, d: i32) -> i32;
 }
 
-
-
 // Add return type -------------------------------------------------------------
 #[cfg(cfail1)]
-extern {
+extern "C" {
     pub fn add_return_type(c: i32);
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-extern {
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+extern "C" {
     pub fn add_return_type(c: i32) -> i32;
 }
 
-
-
 // Make function variadic ------------------------------------------------------
 #[cfg(cfail1)]
-extern {
+extern "C" {
     pub fn make_function_variadic(c: i32);
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-extern {
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+extern "C" {
     pub fn make_function_variadic(c: i32, ...);
 }
 
-
-
 // Change calling convention ---------------------------------------------------
 #[cfg(cfail1)]
 extern "C" {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
 extern "rust-call" {
     pub fn change_calling_convention(c: i32);
 }
 
-
-
 // Make function public --------------------------------------------------------
 #[cfg(cfail1)]
-extern {
+extern "C" {
     fn make_function_public(c: i32);
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-extern {
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+extern "C" {
     pub fn make_function_public(c: i32);
 }
 
-
-
 // Add function ----------------------------------------------------------------
 #[cfg(cfail1)]
-extern {
+extern "C" {
     pub fn add_function1(c: i32);
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-extern {
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+extern "C" {
     pub fn add_function1(c: i32);
     pub fn add_function2();
 }
 
-
-
 // Change link-args ------------------------------------------------------------
 #[cfg(cfail1)]
 #[link_args = "-foo -bar"]
-extern {
+extern "C" {
     pub fn change_link_args(c: i32);
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
 #[link_args = "-foo -bar -baz"]
-extern {
+extern "C" {
     pub fn change_link_args(c: i32);
 }
 
-
-
 // Change link-name ------------------------------------------------------------
 #[cfg(cfail1)]
 #[link(name = "foo")]
-extern {
+extern "C" {
     pub fn change_link_name(c: i32);
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
 #[link(name = "bar")]
-extern {
+extern "C" {
     pub fn change_link_name(c: i32);
 }
 
@@ -209,15 +186,13 @@ mod indirectly_change_parameter_type {
     #[cfg(not(cfail1))]
     use super::c_i64 as c_int;
 
-    #[rustc_dirty(cfg="cfail2")]
-    #[rustc_clean(cfg="cfail3")]
-    extern {
+    #[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+    #[rustc_clean(cfg = "cfail3")]
+    extern "C" {
         pub fn indirectly_change_parameter_type(c: c_int);
     }
 }
 
-
-
 // Indirectly change return type --------------------------------------------
 mod indirectly_change_return_type {
     #[cfg(cfail1)]
@@ -225,9 +200,9 @@ mod indirectly_change_return_type {
     #[cfg(not(cfail1))]
     use super::c_i64 as c_int;
 
-    #[rustc_dirty(cfg="cfail2")]
-    #[rustc_clean(cfg="cfail3")]
-    extern {
+    #[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+    #[rustc_clean(cfg = "cfail3")]
+    extern "C" {
         pub fn indirectly_change_return_type() -> c_int;
     }
 }
index ab4d76eef364c7ad1484c44217bf8eb5b889ff2f..7b1096a64c1d6eedb96e57d86cbc0e5ead781e85 100644 (file)
@@ -1,6 +1,6 @@
 // revisions:cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph --test
-// build-pass (FIXME(62277): could be check-pass?)
+// build-pass
 
 #![feature(rustc_attrs)]
 #![crate_type = "rlib"]
index 23c18bde2262b277d7ccef651ff1b8c4671eee01..dac9ec3b443d769fbf01856ae5eccfcee05198ac 100644 (file)
@@ -10,7 +10,7 @@
       let mut _8: bool;                    // in scope 0 at $DIR/inst_combine_deref.rs:60:5: 60:23
       let mut _9: bool;                    // in scope 0 at $DIR/inst_combine_deref.rs:60:13: 60:21
       let mut _10: i32;                    // in scope 0 at $DIR/inst_combine_deref.rs:60:13: 60:15
-      let mut _11: !;                      // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _11: !;                      // in scope 0 at $DIR/inst_combine_deref.rs:60:5: 60:23
       scope 1 {
           debug x => _1;                   // in scope 1 at $DIR/inst_combine_deref.rs:55:9: 55:10
           let _2: i32;                     // in scope 1 at $DIR/inst_combine_deref.rs:56:9: 56:10
       }
   
       bb2: {
-          StorageLive(_11);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          begin_panic::<&str>(const "assertion failed: *y == 99"); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_11);                // scope 4 at $DIR/inst_combine_deref.rs:60:5: 60:23
+          core::panicking::panic(const "assertion failed: *y == 99"); // scope 4 at $DIR/inst_combine_deref.rs:60:5: 60:23
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
-                                           // + literal: Const { ty: fn(&str) -> ! {std::rt::begin_panic::<&str>}, val: Value(Scalar(<ZST>)) }
+                                           // + span: $DIR/inst_combine_deref.rs:60:5: 60:23
+                                           // + literal: Const { ty: fn(&'static str) -> ! {core::panicking::panic}, val: Value(Scalar(<ZST>)) }
                                            // ty::Const
                                            // + ty: &str
                                            // + val: Value(Slice { data: Allocation { bytes: [97, 115, 115, 101, 114, 116, 105, 111, 110, 32, 102, 97, 105, 108, 101, 100, 58, 32, 42, 121, 32, 61, 61, 32, 57, 57], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [67108863], len: Size { raw: 26 } }, size: Size { raw: 26 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 26 })
index f9f30ccb20e250f88b7e2cf0c937cb2c5bf705cb..4db83c5c683d25a7b9937f26c8e42c22555a5d3e 100644 (file)
       let mut _9: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       let mut _10: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       let mut _11: i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _12: &std::fmt::Arguments;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _13: std::fmt::Arguments;        // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _14: &[&str; 3];             // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _15: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _16: [std::fmt::ArgumentV1; 2];  // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _17: (&&i32, &&i32);         // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _18: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _19: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _20: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _21: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _22: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _12: std::fmt::Arguments;    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _13: &[&str; 3];             // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _14: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _15: [std::fmt::ArgumentV1; 2];  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _16: (&&i32, &&i32);         // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _17: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _18: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _19: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _20: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _21: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       scope 1 {
           debug split => _1;               // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14
           let _4: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14
                   debug left_val => _7;    // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                   debug right_val => _8;   // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                   scope 5 {
-                      debug arg0 => _25;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                      debug arg1 => _28;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                      scope 6 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/std/src/macros.rs:LL:COL
-                          debug x => _25;  // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          debug f => _24;  // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _23: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _24: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _25: &&i32; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
+                      debug arg0 => _24;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      debug arg1 => _27;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      scope 6 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          debug x => _24;  // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          debug f => _23;  // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _22: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _23: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _24: &&i32; // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                           scope 7 {
                           }
                       }
-                      scope 8 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/std/src/macros.rs:LL:COL
-                          debug x => _28;  // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          debug f => _27;  // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _26: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _27: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _28: &&i32; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
+                      scope 8 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          debug x => _27;  // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          debug f => _26;  // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _25: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _26: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _27: &&i32; // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                           scope 9 {
                           }
                       }
                   }
-                  scope 10 (inlined Arguments::new_v1) { // at $SRC_DIR/std/src/macros.rs:LL:COL
-                      debug pieces => _29; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-                      debug args => _31;   // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-                      let mut _29: &[&str]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-                      let mut _30: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-                      let mut _31: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
+                  scope 10 (inlined Arguments::new_v1) { // at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      debug pieces => (_12.0: &[&str]); // in scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      debug args => _29;   // in scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      let mut _28: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      let mut _29: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                   }
               }
           }
       }
   
       bb2: {
-          StorageLive(_13);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _14 = const main::promoted[0];   // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _13 = const main::promoted[0];   // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &[&str; 3]
                                            // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: &[&str; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) }
-          _29 = move _14 as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_16);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          (_12.0: &[&str]) = move _13 as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_15);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_17);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _17 = _7;                        // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_16.0: &&i32) = &_17;           // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_18);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _18 = _7;                        // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_17.0: &&i32) = &_18;           // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_19);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_20);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _20 = _8;                        // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _19 = &_20;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_17.1: &&i32) = move _19;       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_19);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _25 = (_17.0: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _28 = (_17.1: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _24 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _19 = _8;                        // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _18 = &_19;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_16.1: &&i32) = move _18;       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_18);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _24 = (_16.0: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _27 = (_16.1: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _23 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
-          StorageLive(_23);                // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _23 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _24) -> bb3; // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_22);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _22 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _23) -> bb3; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb3: {
-          (_21.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _25) -> bb4; // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
+          (_20.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _24) -> bb4; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb4: {
-          (_21.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _23; // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_23);                // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _27 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_20.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _22; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_22);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _26 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
-          StorageLive(_26);                // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _26 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _27) -> bb5; // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_25);                // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _25 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _26) -> bb5; // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb5: {
-          (_22.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _28) -> bb6; // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
+          (_21.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _27) -> bb6; // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb6: {
-          (_22.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _26; // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_26);                // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _16 = [move _21, move _22];      // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _15 = &_16;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _31 = move _15 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_30);                // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          discriminant(_30) = 0;           // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_13.0: &[&str]) = move _29;     // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_13.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _30; // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_13.2: &[std::fmt::ArgumentV1]) = move _31; // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_30);                // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _12 = &_13;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          begin_panic_fmt(move _12);       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          (_21.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _25; // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_25);                // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _15 = [move _20, move _21];      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _14 = &_15;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _29 = move _14 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_28);                // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          discriminant(_28) = 0;           // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_12.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _28; // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_12.2: &[std::fmt::ArgumentV1]) = move _29; // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_28);                // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          core::panicking::panic_fmt(move _12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
-                                           // + literal: Const { ty: for<'r, 's> fn(&'r std::fmt::Arguments<'s>) -> ! {std::rt::begin_panic_fmt}, val: Value(Scalar(<ZST>)) }
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                                           // + literal: Const { ty: for<'r> fn(std::fmt::Arguments<'r>) -> ! {core::panicking::panic_fmt}, val: Value(Scalar(<ZST>)) }
       }
   }
   
index f9f30ccb20e250f88b7e2cf0c937cb2c5bf705cb..4db83c5c683d25a7b9937f26c8e42c22555a5d3e 100644 (file)
       let mut _9: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       let mut _10: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       let mut _11: i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _12: &std::fmt::Arguments;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _13: std::fmt::Arguments;        // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _14: &[&str; 3];             // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _15: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _16: [std::fmt::ArgumentV1; 2];  // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _17: (&&i32, &&i32);         // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _18: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _19: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _20: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _21: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _22: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _12: std::fmt::Arguments;    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _13: &[&str; 3];             // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _14: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _15: [std::fmt::ArgumentV1; 2];  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _16: (&&i32, &&i32);         // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _17: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _18: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _19: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _20: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _21: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       scope 1 {
           debug split => _1;               // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14
           let _4: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14
                   debug left_val => _7;    // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                   debug right_val => _8;   // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                   scope 5 {
-                      debug arg0 => _25;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                      debug arg1 => _28;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                      scope 6 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/std/src/macros.rs:LL:COL
-                          debug x => _25;  // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          debug f => _24;  // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _23: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _24: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _25: &&i32; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
+                      debug arg0 => _24;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      debug arg1 => _27;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      scope 6 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          debug x => _24;  // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          debug f => _23;  // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _22: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _23: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _24: &&i32; // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                           scope 7 {
                           }
                       }
-                      scope 8 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/std/src/macros.rs:LL:COL
-                          debug x => _28;  // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          debug f => _27;  // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _26: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _27: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _28: &&i32; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
+                      scope 8 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          debug x => _27;  // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          debug f => _26;  // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _25: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _26: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _27: &&i32; // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                           scope 9 {
                           }
                       }
                   }
-                  scope 10 (inlined Arguments::new_v1) { // at $SRC_DIR/std/src/macros.rs:LL:COL
-                      debug pieces => _29; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-                      debug args => _31;   // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-                      let mut _29: &[&str]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-                      let mut _30: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-                      let mut _31: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
+                  scope 10 (inlined Arguments::new_v1) { // at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      debug pieces => (_12.0: &[&str]); // in scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      debug args => _29;   // in scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      let mut _28: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      let mut _29: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                   }
               }
           }
       }
   
       bb2: {
-          StorageLive(_13);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _14 = const main::promoted[0];   // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _13 = const main::promoted[0];   // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &[&str; 3]
                                            // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: &[&str; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) }
-          _29 = move _14 as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_16);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          (_12.0: &[&str]) = move _13 as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_15);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_17);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _17 = _7;                        // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_16.0: &&i32) = &_17;           // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_18);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _18 = _7;                        // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_17.0: &&i32) = &_18;           // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_19);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_20);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _20 = _8;                        // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _19 = &_20;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_17.1: &&i32) = move _19;       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_19);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _25 = (_17.0: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _28 = (_17.1: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _24 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _19 = _8;                        // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _18 = &_19;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_16.1: &&i32) = move _18;       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_18);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _24 = (_16.0: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _27 = (_16.1: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _23 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
-          StorageLive(_23);                // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _23 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _24) -> bb3; // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_22);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _22 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _23) -> bb3; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb3: {
-          (_21.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _25) -> bb4; // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
+          (_20.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _24) -> bb4; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb4: {
-          (_21.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _23; // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_23);                // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _27 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_20.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _22; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_22);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _26 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
-          StorageLive(_26);                // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _26 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _27) -> bb5; // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_25);                // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _25 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _26) -> bb5; // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb5: {
-          (_22.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _28) -> bb6; // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
+          (_21.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _27) -> bb6; // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb6: {
-          (_22.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _26; // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_26);                // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _16 = [move _21, move _22];      // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _15 = &_16;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _31 = move _15 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_30);                // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          discriminant(_30) = 0;           // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_13.0: &[&str]) = move _29;     // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_13.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _30; // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_13.2: &[std::fmt::ArgumentV1]) = move _31; // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_30);                // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _12 = &_13;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          begin_panic_fmt(move _12);       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          (_21.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _25; // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_25);                // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _15 = [move _20, move _21];      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _14 = &_15;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _29 = move _14 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_28);                // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          discriminant(_28) = 0;           // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_12.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _28; // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_12.2: &[std::fmt::ArgumentV1]) = move _29; // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_28);                // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          core::panicking::panic_fmt(move _12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
-                                           // + literal: Const { ty: for<'r, 's> fn(&'r std::fmt::Arguments<'s>) -> ! {std::rt::begin_panic_fmt}, val: Value(Scalar(<ZST>)) }
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                                           // + literal: Const { ty: for<'r> fn(std::fmt::Arguments<'r>) -> ! {core::panicking::panic_fmt}, val: Value(Scalar(<ZST>)) }
       }
   }
   
index a9425224ce475b176d8ea0d69a9da1fc5fbb8526..4e362f3556b208de12c4e8bd62983216cd3bdae2 100644 (file)
       let mut _16: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       let mut _17: i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       let mut _18: i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _19: !;                      // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _20: &std::fmt::Arguments;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _21: &std::fmt::Arguments;       // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _22: std::fmt::Arguments;        // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _23: &[&str];                // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _24: &[&str; 3];             // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _25: &[&str; 3];                 // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _26: [&str; 3];                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _27: &[std::fmt::ArgumentV1]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _28: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _29: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _30: [std::fmt::ArgumentV1; 2];  // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _31: (&&i32, &&i32);         // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _19: !;                      // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _20: std::fmt::Arguments;    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _21: &[&str];                // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _22: &[&str; 3];             // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _23: &[&str; 3];                 // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _24: [&str; 3];                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _25: &[std::fmt::ArgumentV1]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _26: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _27: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _28: [std::fmt::ArgumentV1; 2];  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _29: (&&i32, &&i32);         // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _30: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _31: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       let mut _32: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       let _33: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _34: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _35: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _38: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _39: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _40: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _41: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _42: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _43: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _36: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _37: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _38: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _39: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _40: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _41: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       scope 1 {
           debug split => _1;               // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14
           let _6: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14
               debug _prev => _6;           // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14
               let _13: &i32;               // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
               let _14: &i32;               // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-              let mut _45: &i32;           // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+              let mut _43: &i32;           // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
               scope 4 {
                   debug left_val => _13;   // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                   debug right_val => _14;  // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  let _36: &&i32;          // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  let _37: &&i32;          // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  let mut _44: &[&str; 3]; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                  let _34: &&i32;          // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                  let _35: &&i32;          // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                  let mut _42: &[&str; 3]; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                   scope 5 {
-                      debug arg0 => _36;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                      debug arg1 => _37;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                      scope 6 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/std/src/macros.rs:LL:COL
-                          debug x => _39;  // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          debug f => _40;  // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _46: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _47: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _48: &core::fmt::Opaque; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _49: &&i32; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
+                      debug arg0 => _34;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      debug arg1 => _35;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      scope 6 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          debug x => _37;  // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          debug f => _38;  // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _44: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _45: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _46: &core::fmt::Opaque; // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _47: &&i32; // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                           scope 7 {
                           }
                       }
-                      scope 8 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/std/src/macros.rs:LL:COL
-                          debug x => _42;  // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          debug f => _43;  // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _50: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _51: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _52: &core::fmt::Opaque; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _53: &&i32; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
+                      scope 8 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          debug x => _40;  // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          debug f => _41;  // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _48: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _49: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _50: &core::fmt::Opaque; // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _51: &&i32; // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                           scope 9 {
                           }
                       }
                   }
-                  scope 10 (inlined Arguments::new_v1) { // at $SRC_DIR/std/src/macros.rs:LL:COL
-                      debug pieces => _23; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-                      debug args => _27;   // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-                      let mut _54: &[&str]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-                      let mut _55: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-                      let mut _56: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
+                  scope 10 (inlined Arguments::new_v1) { // at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      debug pieces => _21; // in scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      debug args => _25;   // in scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      let mut _52: &[&str]; // in scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      let mut _53: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      let mut _54: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                   }
               }
           }
           StorageLive(_10);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _10 = &_1;                       // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_11);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _45 = const main::promoted[1];   // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _43 = const main::promoted[1];   // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &i32
                                            // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[1]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[1])) }
-          _11 = _45;                       // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _11 = _43;                       // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_9.0: &i32) = move _10;         // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_9.1: &i32) = move _11;         // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageDead(_11);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       }
   
       bb4: {
-          StorageLive(_19);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_20);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_21);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_22);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_19);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_20);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_21);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_22);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_23);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_24);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_25);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _44 = const main::promoted[0];   // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _42 = const main::promoted[0];   // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &[&str; 3]
                                            // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: &[&str; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) }
-          _25 = _44;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _24 = _25;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _23 = move _24 as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_24);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_27);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_28);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_29);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_30);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_31);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _23 = _42;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _22 = _23;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _21 = move _22 as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_22);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_25);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_26);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_27);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_28);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_29);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_30);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_31);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _31 = _13;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _30 = &_31;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_32);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_33);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _33 = _13;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _33 = _14;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _32 = &_33;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_29.0: &&i32) = move _30;       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_29.1: &&i32) = move _32;       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_32);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_30);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_34);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _34 = (_29.0: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_35);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _35 = _14;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _34 = &_35;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_31.0: &&i32) = move _32;       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_31.1: &&i32) = move _34;       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_34);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_32);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_36);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _36 = (_31.0: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_37);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _37 = (_31.1: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_38);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_39);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _39 = _36;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_40);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _40 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _35 = (_29.1: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_36);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_37);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _37 = _34;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_38);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _38 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
-          StorageLive(_46);                // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_47);                // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _47 = _40;                       // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _46 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _47) -> bb5; // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_44);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_45);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _45 = _38;                       // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _44 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _45) -> bb5; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb5: {
-          StorageDead(_47);                // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_48);                // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_49);                // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _49 = _39;                       // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _48 = transmute::<&&i32, &core::fmt::Opaque>(move _49) -> bb6; // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageDead(_45);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_46);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_47);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _47 = _37;                       // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _46 = transmute::<&&i32, &core::fmt::Opaque>(move _47) -> bb6; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb6: {
-          StorageDead(_49);                // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_38.0: &core::fmt::Opaque) = move _48; // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_38.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _46; // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_48);                // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_46);                // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_40);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_39);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_41);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_42);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _42 = _37;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_43);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _43 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_47);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_36.0: &core::fmt::Opaque) = move _46; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_36.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _44; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_46);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_44);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_38);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_37);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_39);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_40);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _40 = _35;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_41);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _41 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
-          StorageLive(_50);                // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_51);                // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _51 = _43;                       // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _50 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _51) -> bb7; // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_48);                // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_49);                // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _49 = _41;                       // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _48 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _49) -> bb7; // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb7: {
-          StorageDead(_51);                // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_52);                // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_53);                // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _53 = _42;                       // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _52 = transmute::<&&i32, &core::fmt::Opaque>(move _53) -> bb8; // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageDead(_49);                // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_50);                // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_51);                // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _51 = _40;                       // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _50 = transmute::<&&i32, &core::fmt::Opaque>(move _51) -> bb8; // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb8: {
-          StorageDead(_53);                // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_41.0: &core::fmt::Opaque) = move _52; // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_41.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _50; // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_52);                // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_50);                // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_43);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_42);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _30 = [move _38, move _41];      // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_41);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_38);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_37);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_36);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _29 = &_30;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _28 = _29;                       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _27 = move _28 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_28);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_54);                // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _54 = _23;                       // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_55);                // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          discriminant(_55) = 0;           // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_56);                // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _56 = _27;                       // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_22.0: &[&str]) = move _54;     // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_22.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _55; // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_22.2: &[std::fmt::ArgumentV1]) = move _56; // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_56);                // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_55);                // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_54);                // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_27);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_23);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _21 = &_22;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _20 = _21;                       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          begin_panic_fmt(move _20);       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageDead(_51);                // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_39.0: &core::fmt::Opaque) = move _50; // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_39.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _48; // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_50);                // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_48);                // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_41);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_40);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _28 = [move _36, move _39];      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_39);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_36);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_35);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_34);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _27 = &_28;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _26 = _27;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _25 = move _26 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_26);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_52);                // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _52 = _21;                       // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_53);                // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          discriminant(_53) = 0;           // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_54);                // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _54 = _25;                       // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_20.0: &[&str]) = move _52;     // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_20.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _53; // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_20.2: &[std::fmt::ArgumentV1]) = move _54; // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_54);                // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_53);                // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_52);                // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_25);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_21);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          core::panicking::panic_fmt(move _20); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
-                                           // + literal: Const { ty: for<'r, 's> fn(&'r std::fmt::Arguments<'s>) -> ! {std::rt::begin_panic_fmt}, val: Value(Scalar(<ZST>)) }
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                                           // + literal: Const { ty: for<'r> fn(std::fmt::Arguments<'r>) -> ! {core::panicking::panic_fmt}, val: Value(Scalar(<ZST>)) }
       }
   }
   
index a9425224ce475b176d8ea0d69a9da1fc5fbb8526..4e362f3556b208de12c4e8bd62983216cd3bdae2 100644 (file)
       let mut _16: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       let mut _17: i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       let mut _18: i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _19: !;                      // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _20: &std::fmt::Arguments;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _21: &std::fmt::Arguments;       // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _22: std::fmt::Arguments;        // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _23: &[&str];                // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _24: &[&str; 3];             // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _25: &[&str; 3];                 // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _26: [&str; 3];                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _27: &[std::fmt::ArgumentV1]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _28: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _29: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _30: [std::fmt::ArgumentV1; 2];  // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _31: (&&i32, &&i32);         // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _19: !;                      // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _20: std::fmt::Arguments;    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _21: &[&str];                // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _22: &[&str; 3];             // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _23: &[&str; 3];                 // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _24: [&str; 3];                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _25: &[std::fmt::ArgumentV1]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _26: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _27: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _28: [std::fmt::ArgumentV1; 2];  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _29: (&&i32, &&i32);         // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _30: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _31: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       let mut _32: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       let _33: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _34: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _35: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _38: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _39: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _40: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _41: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _42: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _43: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _36: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _37: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _38: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _39: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _40: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _41: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       scope 1 {
           debug split => _1;               // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14
           let _6: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14
               debug _prev => _6;           // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14
               let _13: &i32;               // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
               let _14: &i32;               // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-              let mut _45: &i32;           // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+              let mut _43: &i32;           // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
               scope 4 {
                   debug left_val => _13;   // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                   debug right_val => _14;  // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  let _36: &&i32;          // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  let _37: &&i32;          // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  let mut _44: &[&str; 3]; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                  let _34: &&i32;          // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                  let _35: &&i32;          // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                  let mut _42: &[&str; 3]; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                   scope 5 {
-                      debug arg0 => _36;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                      debug arg1 => _37;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                      scope 6 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/std/src/macros.rs:LL:COL
-                          debug x => _39;  // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          debug f => _40;  // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _46: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _47: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _48: &core::fmt::Opaque; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _49: &&i32; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
+                      debug arg0 => _34;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      debug arg1 => _35;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      scope 6 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          debug x => _37;  // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          debug f => _38;  // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _44: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _45: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _46: &core::fmt::Opaque; // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _47: &&i32; // in scope 6 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                           scope 7 {
                           }
                       }
-                      scope 8 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/std/src/macros.rs:LL:COL
-                          debug x => _42;  // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          debug f => _43;  // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _50: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _51: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _52: &core::fmt::Opaque; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _53: &&i32; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
+                      scope 8 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          debug x => _40;  // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          debug f => _41;  // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _48: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _49: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _50: &core::fmt::Opaque; // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                          let mut _51: &&i32; // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                           scope 9 {
                           }
                       }
                   }
-                  scope 10 (inlined Arguments::new_v1) { // at $SRC_DIR/std/src/macros.rs:LL:COL
-                      debug pieces => _23; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-                      debug args => _27;   // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-                      let mut _54: &[&str]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-                      let mut _55: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-                      let mut _56: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
+                  scope 10 (inlined Arguments::new_v1) { // at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      debug pieces => _21; // in scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      debug args => _25;   // in scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      let mut _52: &[&str]; // in scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      let mut _53: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      let mut _54: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                   }
               }
           }
           StorageLive(_10);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _10 = &_1;                       // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_11);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _45 = const main::promoted[1];   // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _43 = const main::promoted[1];   // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &i32
                                            // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[1]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[1])) }
-          _11 = _45;                       // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _11 = _43;                       // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_9.0: &i32) = move _10;         // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_9.1: &i32) = move _11;         // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageDead(_11);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       }
   
       bb4: {
-          StorageLive(_19);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_20);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_21);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_22);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_19);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_20);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_21);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_22);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_23);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_24);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_25);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _44 = const main::promoted[0];   // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _42 = const main::promoted[0];   // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &[&str; 3]
                                            // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: &[&str; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) }
-          _25 = _44;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _24 = _25;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _23 = move _24 as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_24);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_27);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_28);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_29);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_30);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_31);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _23 = _42;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _22 = _23;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _21 = move _22 as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_22);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_25);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_26);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_27);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_28);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_29);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_30);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_31);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _31 = _13;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _30 = &_31;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_32);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_33);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _33 = _13;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _33 = _14;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _32 = &_33;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_29.0: &&i32) = move _30;       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_29.1: &&i32) = move _32;       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_32);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_30);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_34);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _34 = (_29.0: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_35);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _35 = _14;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _34 = &_35;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_31.0: &&i32) = move _32;       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_31.1: &&i32) = move _34;       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_34);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_32);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_36);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _36 = (_31.0: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_37);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _37 = (_31.1: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_38);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_39);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _39 = _36;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_40);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _40 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _35 = (_29.1: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_36);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_37);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _37 = _34;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_38);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _38 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
-          StorageLive(_46);                // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_47);                // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _47 = _40;                       // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _46 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _47) -> bb5; // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_44);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_45);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _45 = _38;                       // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _44 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _45) -> bb5; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb5: {
-          StorageDead(_47);                // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_48);                // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_49);                // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _49 = _39;                       // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _48 = transmute::<&&i32, &core::fmt::Opaque>(move _49) -> bb6; // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageDead(_45);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_46);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_47);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _47 = _37;                       // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _46 = transmute::<&&i32, &core::fmt::Opaque>(move _47) -> bb6; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb6: {
-          StorageDead(_49);                // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_38.0: &core::fmt::Opaque) = move _48; // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_38.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _46; // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_48);                // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_46);                // scope 7 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_40);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_39);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_41);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_42);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _42 = _37;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_43);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _43 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_47);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_36.0: &core::fmt::Opaque) = move _46; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_36.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _44; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_46);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_44);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_38);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_37);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_39);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_40);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _40 = _35;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_41);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _41 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
-          StorageLive(_50);                // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_51);                // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _51 = _43;                       // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _50 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _51) -> bb7; // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_48);                // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_49);                // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _49 = _41;                       // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _48 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _49) -> bb7; // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb7: {
-          StorageDead(_51);                // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_52);                // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_53);                // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _53 = _42;                       // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _52 = transmute::<&&i32, &core::fmt::Opaque>(move _53) -> bb8; // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageDead(_49);                // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_50);                // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_51);                // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _51 = _40;                       // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _50 = transmute::<&&i32, &core::fmt::Opaque>(move _51) -> bb8; // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb8: {
-          StorageDead(_53);                // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_41.0: &core::fmt::Opaque) = move _52; // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_41.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _50; // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_52);                // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_50);                // scope 9 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_43);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_42);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _30 = [move _38, move _41];      // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_41);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_38);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_37);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_36);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _29 = &_30;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _28 = _29;                       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _27 = move _28 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_28);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_54);                // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _54 = _23;                       // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_55);                // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          discriminant(_55) = 0;           // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_56);                // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _56 = _27;                       // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_22.0: &[&str]) = move _54;     // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_22.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _55; // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_22.2: &[std::fmt::ArgumentV1]) = move _56; // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_56);                // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_55);                // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_54);                // scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_27);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_23);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _21 = &_22;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _20 = _21;                       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          begin_panic_fmt(move _20);       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageDead(_51);                // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_39.0: &core::fmt::Opaque) = move _50; // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_39.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _48; // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_50);                // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_48);                // scope 9 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_41);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_40);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _28 = [move _36, move _39];      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_39);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_36);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_35);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_34);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _27 = &_28;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _26 = _27;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _25 = move _26 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_26);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_52);                // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _52 = _21;                       // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_53);                // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          discriminant(_53) = 0;           // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_54);                // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _54 = _25;                       // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_20.0: &[&str]) = move _52;     // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_20.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _53; // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_20.2: &[std::fmt::ArgumentV1]) = move _54; // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_54);                // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_53);                // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_52);                // scope 10 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_25);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_21);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          core::panicking::panic_fmt(move _20); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
-                                           // + literal: Const { ty: for<'r, 's> fn(&'r std::fmt::Arguments<'s>) -> ! {std::rt::begin_panic_fmt}, val: Value(Scalar(<ZST>)) }
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                                           // + literal: Const { ty: for<'r> fn(std::fmt::Arguments<'r>) -> ! {core::panicking::panic_fmt}, val: Value(Scalar(<ZST>)) }
       }
   }
   
index 499134b69919fa11a7e822276aaa878bac2188fc..6450a2a22c6ca5eb1dede892c4f446388f05cd5d 100644 (file)
@@ -21,7 +21,7 @@
       let mut _19: *const T;               // in scope 0 at $DIR/issue_76432.rs:9:54: 9:68
       let mut _20: *const T;               // in scope 0 at $DIR/issue_76432.rs:9:70: 9:84
       let mut _21: *const T;               // in scope 0 at $DIR/issue_76432.rs:9:70: 9:84
-      let mut _22: !;                      // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _22: !;                      // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       scope 1 {
           debug v => _2;                   // in scope 1 at $DIR/issue_76432.rs:7:9: 7:10
           let _13: &T;                     // in scope 1 at $DIR/issue_76432.rs:9:10: 9:16
       }
   
       bb1: {
-          StorageLive(_22);                // scope 1 at $SRC_DIR/std/src/macros.rs:LL:COL
-          begin_panic::<&str>(const "internal error: entered unreachable code"); // scope 1 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_22);                // scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          core::panicking::panic(const "internal error: entered unreachable code"); // scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
-                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
-                                           // + literal: Const { ty: fn(&str) -> ! {std::rt::begin_panic::<&str>}, val: Value(Scalar(<ZST>)) }
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                                           // + literal: Const { ty: fn(&'static str) -> ! {core::panicking::panic}, val: Value(Scalar(<ZST>)) }
                                            // ty::Const
                                            // + ty: &str
                                            // + val: Value(Slice { data: Allocation { bytes: [105, 110, 116, 101, 114, 110, 97, 108, 32, 101, 114, 114, 111, 114, 58, 32, 101, 110, 116, 101, 114, 101, 100, 32, 117, 110, 114, 101, 97, 99, 104, 97, 98, 108, 101, 32, 99, 111, 100, 101], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1099511627775], len: Size { raw: 40 } }, size: Size { raw: 40 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 40 })
diff --git a/src/test/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff
new file mode 100644 (file)
index 0000000..e973014
--- /dev/null
@@ -0,0 +1,31 @@
+- // MIR for `non_const` before LowerIntrinsics
++ // MIR for `non_const` after LowerIntrinsics
+  
+  fn non_const() -> usize {
+      let mut _0: usize;                   // return place in scope 0 at $DIR/lower_intrinsics.rs:55:26: 55:31
+      let _1: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}; // in scope 0 at $DIR/lower_intrinsics.rs:57:9: 57:18
+      let mut _2: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}; // in scope 0 at $DIR/lower_intrinsics.rs:58:5: 58:14
+      scope 1 {
+          debug size_of_t => _1;           // in scope 1 at $DIR/lower_intrinsics.rs:57:9: 57:18
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:57:9: 57:18
+          _1 = std::intrinsics::size_of::<T>; // scope 0 at $DIR/lower_intrinsics.rs:57:21: 57:51
+                                           // mir::Constant
+                                           // + span: $DIR/lower_intrinsics.rs:57:21: 57:51
+                                           // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}, val: Value(Scalar(<ZST>)) }
+          StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:14
+          _2 = _1;                         // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:14
+-         _0 = move _2() -> bb1;           // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:16
++         _0 = SizeOf(T);                  // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:16
++         goto -> bb1;                     // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:16
+      }
+  
+      bb1: {
+          StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:58:15: 58:16
+          StorageDead(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:59:1: 59:2
+          return;                          // scope 0 at $DIR/lower_intrinsics.rs:59:2: 59:2
+      }
+  }
+  
index e08d620c4b13f9ead6ed9eed55eca632b1d508ac..de5f692b7da28d9e015b2c1dca6089a39f6313b3 100644 (file)
@@ -50,3 +50,10 @@ pub fn f_zst<T>(t: T) {
 
 #[inline(never)]
 pub fn f_non_zst<T>(t: T) {}
+
+// EMIT_MIR lower_intrinsics.non_const.LowerIntrinsics.diff
+pub fn non_const<T>() -> usize {
+    // Check that lowering works with non-const operand as a func.
+    let size_of_t = core::intrinsics::size_of::<T>;
+    size_of_t()
+}
index 2eb4d3390be57bc487faad3698edf0428343fa3c..61644e7df09ae5f64304666f7ed1c82b3d637906 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 
 // pp-exact
 
index e84642922d93484cd6f65e5afec2f108567b8629..219ba15ad116dd2d68027e8e00bb1b2185d94c63 100644 (file)
@@ -12,10 +12,12 @@ ifeq ($(UNAME),Darwin)
        INSTR_PROF_DATA_SUFFIX=,regular,live_support
        DATA_SECTION_PREFIX=__DATA,
        LLVM_COV_SECTION_PREFIX=__LLVM_COV,
+       COMDAT_IF_SUPPORTED=
 else
        INSTR_PROF_DATA_SUFFIX=
        DATA_SECTION_PREFIX=
        LLVM_COV_SECTION_PREFIX=
+       COMDAT_IF_SUPPORTED=, comdat
 endif
 
 ifeq ($(LINK_DEAD_CODE),yes)
@@ -29,28 +31,39 @@ ifdef IS_WINDOWS
                -check-prefixes=CHECK,WINDOWS \
                -DPRIVATE_GLOBAL='internal global' \
                -DDEFINE_INTERNAL='$(DEFINE_INTERNAL)' \
+               -DCOMDAT_IF_SUPPORTED='$(COMDAT_IF_SUPPORTED)' \
                -DINSTR_PROF_DATA='.lprfd$$M' \
                -DINSTR_PROF_NAME='.lprfn$$M' \
                -DINSTR_PROF_CNTS='.lprfc$$M' \
                -DINSTR_PROF_VALS='.lprfv$$M' \
                -DINSTR_PROF_VNODES='.lprfnd$$M' \
                -DINSTR_PROF_COVMAP='.lcovmap$$M' \
+               -DINSTR_PROF_COVFUN='.lcovfun$$M' \
                -DINSTR_PROF_ORDERFILE='.lorderfile$$M'
 else
        LLVM_FILECHECK_OPTIONS=\
                -check-prefixes=CHECK \
                -DPRIVATE_GLOBAL='private global' \
                -DDEFINE_INTERNAL='$(DEFINE_INTERNAL)' \
+               -DCOMDAT_IF_SUPPORTED='$(COMDAT_IF_SUPPORTED)' \
                -DINSTR_PROF_DATA='$(DATA_SECTION_PREFIX)__llvm_prf_data$(INSTR_PROF_DATA_SUFFIX)' \
                -DINSTR_PROF_NAME='$(DATA_SECTION_PREFIX)__llvm_prf_names' \
                -DINSTR_PROF_CNTS='$(DATA_SECTION_PREFIX)__llvm_prf_cnts' \
                -DINSTR_PROF_VALS='$(DATA_SECTION_PREFIX)__llvm_prf_vals' \
                -DINSTR_PROF_VNODES='$(DATA_SECTION_PREFIX)__llvm_prf_vnds' \
                -DINSTR_PROF_COVMAP='$(LLVM_COV_SECTION_PREFIX)__llvm_covmap' \
+               -DINSTR_PROF_COVFUN='$(LLVM_COV_SECTION_PREFIX)__llvm_covfun' \
                -DINSTR_PROF_ORDERFILE='$(DATA_SECTION_PREFIX)__llvm_orderfile'
 endif
 
+ifeq ($(LLVM_VERSION_11_PLUS),true)
+all: test_llvm_ir
+else
+$(info Rust option `-Z instrument-coverage` requires LLVM 11 or higher. Test skipped.)
 all:
+endif
+
+test_llvm_ir:
        # Compile the test program with non-experimental coverage instrumentation, and generate LLVM IR
        #
        # Note: `-Clink-dead-code=no` disables the option, needed because the option is automatically
@@ -62,4 +75,5 @@ all:
                        -Clink-dead-code=$(LINK_DEAD_CODE) \
                        --emit=llvm-ir
 
-       cat "$(TMPDIR)"/testprog.ll | "$(LLVM_FILECHECK)" $(BASEDIR)/filecheck.testprog.txt $(LLVM_FILECHECK_OPTIONS)
+       cat "$(TMPDIR)"/testprog.ll | \
+                       "$(LLVM_FILECHECK)" $(BASEDIR)/filecheck.testprog.txt $(LLVM_FILECHECK_OPTIONS)
index bd2a2475d9e1050c4e39591692997f8556a358f9..a312ec48e8498fb3bf8aa58907705c68942ae3fb 100644 (file)
@@ -3,7 +3,10 @@
 
 WINDOWS:      $__llvm_profile_runtime_user = comdat any
 
-CHECK:        @__llvm_coverage_mapping = internal constant
+CHECK:        @__covrec_{{[A-F0-9]+}}u = linkonce_odr hidden constant
+CHECK-SAME:   section "[[INSTR_PROF_COVFUN]]"[[COMDAT_IF_SUPPORTED]], align 8
+
+CHECK:        @__llvm_coverage_mapping = private constant
 CHECK-SAME:   section "[[INSTR_PROF_COVMAP]]", align 8
 
 WINDOWS:      @__llvm_profile_runtime = external global i32
index 1e2aa056e400888d5f0730bc3a5bd50a62c8fb8d..2dac8fc2225bf5010f86979c7950ea6b85b0c72b 100644 (file)
@@ -18,7 +18,10 @@ SOURCEDIR=../coverage
 # `llvm/release_debuginfo`. Note that some CI builds disable debug assertions (by setting
 # `NO_LLVM_ASSERTIONS=1`), so it is not OK to fail the test, but `bless`ed test results cannot be
 # generated without debug assertions.
-LLVM_COV_DEBUG := $(shell "$(LLVM_BIN_DIR)"/llvm-cov show --debug 2>&1 | grep -q "Unknown command line argument '--debug'"; echo $$?)
+LLVM_COV_DEBUG := $(shell \
+               "$(LLVM_BIN_DIR)"/llvm-cov show --debug 2>&1 | \
+               grep -q "Unknown command line argument '--debug'"; \
+               echo $$?)
 ifeq ($(LLVM_COV_DEBUG), 1)
 DEBUG_FLAG=--debug
 endif
@@ -30,7 +33,12 @@ ifdef RUSTC_BLESS_TEST
 DEBUG_FLAG=--debug
 endif
 
+ifeq ($(LLVM_VERSION_11_PLUS),true)
 all: $(patsubst $(SOURCEDIR)/%.rs,%,$(wildcard $(SOURCEDIR)/*.rs))
+else
+$(info Rust option `-Z instrument-coverage` requires LLVM 11 or higher. Test skipped.)
+all:
+endif
 
 # Ensure there are no `expected` results for tests that may have been removed or renamed
 .PHONY: clear_expected_if_blessed
index 03ef04776a03b2bc12161aec14ade6ea9da9fb5c..9f9440340e0eddfd7f4aee505f8e3caf31d74c8e 100644 (file)
@@ -24,7 +24,12 @@ For revisions in Pull Requests (PR):
 endef
 export SPANVIEW_HEADER
 
+ifeq ($(LLVM_VERSION_11_PLUS),true)
 all: $(patsubst $(SOURCEDIR)/%.rs,%,$(wildcard $(SOURCEDIR)/*.rs))
+else
+$(info Rust option `-Z instrument-coverage` requires LLVM 11 or higher. Test skipped.)
+all:
+endif
 
 # Ensure there are no `expected` results for tests that may have been removed or renamed
 .PHONY: clear_expected_if_blessed
index 17f7696a8cf1dc0ccbe70821d37a590ff8d2008d..99a2e0ba9523e874c658326865df9505bfacf73d 100644 (file)
@@ -38,6 +38,13 @@ endif
 
 UNAME = $(shell uname)
 
+# Rust option `-Z instrument-coverage` uses LLVM Coverage Mapping Format version 4,
+# which requires LLVM 11 or greater.
+LLVM_VERSION_11_PLUS := $(shell \
+               LLVM_VERSION=$$("$(LLVM_BIN_DIR)"/llvm-config --version) && \
+               LLVM_VERSION_MAJOR=$${LLVM_VERSION/.*/} && \
+               [ $$LLVM_VERSION_MAJOR -ge 11 ] && echo true || echo false)
+
 # FIXME(richkadel): Can any of the features tested by `run-make-fulldeps/coverage-*` tests be tested
 # just as completely by more focused unit tests of the code logic itself, to reduce the number of
 # test result files generated and maintained, and to help identify specific test failures and root
index c63fe4ddce214aa9874a7d6a8495f608fab4cc4d..717da367feec559e19d4e26245642e686f3cd449 100644 (file)
@@ -2,7 +2,7 @@
 #![crate_type = "lib"]
 // we can compile to a variety of platforms, because we don't need
 // cross-compiled standard libraries.
-#![feature(no_core, optin_builtin_traits)]
+#![feature(no_core, auto_traits)]
 #![no_core]
 #![feature(repr_simd, simd_ffi, link_llvm_intrinsics, lang_items, rustc_attrs)]
 
index 421300686955ccd18dba354539951a75dc357a4f..ee443eb0aa32bbf6fe426a97d02fe7c1f0da5a13 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(lang_items, no_core, optin_builtin_traits)]
+#![feature(lang_items, no_core, auto_traits)]
 #![no_core]
 
 #[lang="copy"]
index a68c6f3355644695b4e03afdac489a6cacdf4cf6..9daf487d39feb6476628f72cba63fd8bfb9a4017 100644 (file)
@@ -1,4 +1,3 @@
-// ignore-cloudabi
 // ignore-emscripten
 // ignore-sgx no processes
 // ignore-macos this needs valgrind 3.11 or higher; see
index 815e8cedd16da69084332de95c19060d32e65d00..3f0c094794e4121372a14d75e0c518a9207bbafb 100644 (file)
@@ -1,4 +1,2 @@
-#![feature(doc_alias)]
-
 #[doc(alias = "true")]
 pub struct Foo;
index 8887f8c2b0149403c80a599d0324fe0baf85301e..d5227814c06a808d60efdd8086e423abbf8af751 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(doc_alias)]
-
 #[doc(alias = "true")]
 pub struct Foo;
 
index bea3e382ae4b07c5551ad7543d922104b73a8029..16c022c7498906994340e3b66455608f8ceb12bf 100644 (file)
@@ -1,4 +1,2 @@
-#![feature(doc_alias)]
-
 #[doc(alias = "Demon Lord")]
 pub struct Struct;
index 41caa98643cdd4339de1ccc0621ad3055769aed6..750b7b757bc3551de39017bf7aa5ab1fad57979b 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(doc_alias)]
-
 #[doc(alias = "StructItem")]
 pub struct Struct {
     #[doc(alias = "StructFieldItem")]
index 545964c7bd61b4017f0a2f9344ca399f04b14c97..7de2caa189dc724d62db4cbb443c5b31b0018c10 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(doc_alias)]
-
 pub struct Bar;
 pub trait Foo {
     type X;
index a66e9939eaf18060a370627c079d7869d46fce35..175626f49dcac74bd2758d1179df2087a1ebe56e 100644 (file)
@@ -1,23 +1,23 @@
 error: `#[doc(alias = "...")]` isn't allowed on extern block
-  --> $DIR/check-doc-alias-attr-location.rs:9:7
+  --> $DIR/check-doc-alias-attr-location.rs:7:7
    |
 LL | #[doc(alias = "foo")]
    |       ^^^^^^^^^^^^^
 
 error: `#[doc(alias = "...")]` isn't allowed on implementation block
-  --> $DIR/check-doc-alias-attr-location.rs:12:7
+  --> $DIR/check-doc-alias-attr-location.rs:10:7
    |
 LL | #[doc(alias = "bar")]
    |       ^^^^^^^^^^^^^
 
 error: `#[doc(alias = "...")]` isn't allowed on implementation block
-  --> $DIR/check-doc-alias-attr-location.rs:18:7
+  --> $DIR/check-doc-alias-attr-location.rs:16:7
    |
 LL | #[doc(alias = "foobar")]
    |       ^^^^^^^^^^^^^^^^
 
 error: `#[doc(alias = "...")]` isn't allowed on type alias in implementation block
-  --> $DIR/check-doc-alias-attr-location.rs:20:11
+  --> $DIR/check-doc-alias-attr-location.rs:18:11
    |
 LL |     #[doc(alias = "assoc")]
    |           ^^^^^^^^^^^^^^^
index 0ca2349a43b0fdefdb9e7680fea465b2b283de1f..912e35f9165454defd8e64648cbc19c80488bb12 100644 (file)
@@ -1,5 +1,4 @@
 #![crate_type = "lib"]
-#![feature(doc_alias)]
 
 #[doc(alias = "foo")] // ok!
 pub struct Bar;
index 2c417a3bb65b5a82bd3a0d896123a2b1b4b90d47..8a729b02e72bf08892b2e4f49b38c5bcc2acafdd 100644 (file)
@@ -1,35 +1,35 @@
 error: doc alias attribute expects a string: #[doc(alias = "0")]
-  --> $DIR/check-doc-alias-attr.rs:7:7
+  --> $DIR/check-doc-alias-attr.rs:6:7
    |
 LL | #[doc(alias)]
    |       ^^^^^
 
 error: doc alias attribute expects a string: #[doc(alias = "0")]
-  --> $DIR/check-doc-alias-attr.rs:8:7
+  --> $DIR/check-doc-alias-attr.rs:7:7
    |
 LL | #[doc(alias = 0)]
    |       ^^^^^^^^^
 
 error: doc alias attribute expects a string: #[doc(alias = "0")]
-  --> $DIR/check-doc-alias-attr.rs:9:7
+  --> $DIR/check-doc-alias-attr.rs:8:7
    |
 LL | #[doc(alias("bar"))]
    |       ^^^^^^^^^^^^
 
 error: '\"' character isn't allowed in `#[doc(alias = "...")]`
-  --> $DIR/check-doc-alias-attr.rs:10:7
+  --> $DIR/check-doc-alias-attr.rs:9:7
    |
 LL | #[doc(alias = "\"")]
    |       ^^^^^^^^^^^^
 
 error: '\n' character isn't allowed in `#[doc(alias = "...")]`
-  --> $DIR/check-doc-alias-attr.rs:11:7
+  --> $DIR/check-doc-alias-attr.rs:10:7
    |
 LL | #[doc(alias = "\n")]
    |       ^^^^^^^^^^^^
 
 error: '\n' character isn't allowed in `#[doc(alias = "...")]`
-  --> $DIR/check-doc-alias-attr.rs:12:7
+  --> $DIR/check-doc-alias-attr.rs:11:7
    |
 LL |   #[doc(alias = "
    |  _______^
@@ -37,19 +37,19 @@ LL | | ")]
    | |_^
 
 error: '\t' character isn't allowed in `#[doc(alias = "...")]`
-  --> $DIR/check-doc-alias-attr.rs:14:7
+  --> $DIR/check-doc-alias-attr.rs:13:7
    |
 LL | #[doc(alias = "\t")]
    |       ^^^^^^^^^^^^
 
 error: `#[doc(alias = "...")]` cannot start or end with ' '
-  --> $DIR/check-doc-alias-attr.rs:15:7
+  --> $DIR/check-doc-alias-attr.rs:14:7
    |
 LL | #[doc(alias = " hello")]
    |       ^^^^^^^^^^^^^^^^
 
 error: `#[doc(alias = "...")]` cannot start or end with ' '
-  --> $DIR/check-doc-alias-attr.rs:16:7
+  --> $DIR/check-doc-alias-attr.rs:15:7
    |
 LL | #[doc(alias = "hello ")]
    |       ^^^^^^^^^^^^^^^^
index e282ff128437513e3a88564d4c564db7ce263d8c..27798b813101e2cf326d4fbfe01db257bb7aa89d 100644 (file)
@@ -1,8 +1,7 @@
 +-------------------------------------+------------+------------+------------+------------+
 | File                                | Documented | Percentage |   Examples | Percentage |
 +-------------------------------------+------------+------------+------------+------------+
-| ...st/rustdoc-ui/coverage/exotic.rs |          1 |     100.0% |          0 |       0.0% |
-| <anon>                              |          2 |     100.0% |          0 |       0.0% |
+| ...st/rustdoc-ui/coverage/exotic.rs |          3 |     100.0% |          0 |       0.0% |
 +-------------------------------------+------------+------------+------------+------------+
 | Total                               |          3 |     100.0% |          0 |       0.0% |
 +-------------------------------------+------------+------------+------------+------------+
index 73e23c152f268c665f50a9bf6317bf58e88d6531..d95324734be47ac498bc1e9eb0e4352c4379b800 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(doc_alias)]
 #![feature(trait_alias)]
 
 pub struct Foo;
index 3c64548cc204dc2f6fca01f7ed9528925d81d34c..cbca40e1364fa34508a8a317ad472e3717400e40 100644 (file)
@@ -1,5 +1,5 @@
 error: `#[doc(alias = "...")]` isn't allowed on associated constant in trait implementation block
-  --> $DIR/doc-alias-assoc-const.rs:11:11
+  --> $DIR/doc-alias-assoc-const.rs:10:11
    |
 LL |     #[doc(alias = "CONST_BAZ")]
    |           ^^^^^^^^^^^^^^^^^^^
index 9a79fb88383516ea7491aa7299c7451b8d2432e5..2798804880ad01e7f1e47d727622242be6ea14a4 100644 (file)
@@ -2,13 +2,10 @@
 // compile-flags:--test
 // normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
 
-#![feature(cfg_doctest)]
-
 // Make sure `cfg(doctest)` is set when finding doctests but not inside
 // the doctests.
 
 /// ```
-/// #![feature(cfg_doctest)]
 /// assert!(!cfg!(doctest));
 /// ```
 #[cfg(doctest)]
index 75d29fab17d0d35b6807610a3cb596f8b92c55f3..b1cd74bf8520ae6fdc94cabcf129b700ebd50487 100644 (file)
@@ -1,6 +1,6 @@
 
 running 1 test
-test $DIR/doc-test-doctest-feature.rs - Foo (line 10) ... ok
+test $DIR/doc-test-doctest-feature.rs - Foo (line 8) ... ok
 
 test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
 
index f2b2328322a7b9ddc2b3f75eca3366114f356067..3372304f44a3dc72c916957910e823f3d817bb2f 100644 (file)
@@ -16,12 +16,6 @@ note: the lint level is defined here
 LL | #![deny(missing_doc_code_examples)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: missing code example in this documentation
-  --> $DIR/doc-without-codeblock.rs:3:1
-   |
-LL | /// Some docs.
-   | ^^^^^^^^^^^^^^
-
 error: missing code example in this documentation
   --> $DIR/doc-without-codeblock.rs:7:1
    |
@@ -34,5 +28,11 @@ error: missing code example in this documentation
 LL |     /// Or maybe not because she saved herself!
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: missing code example in this documentation
+  --> $DIR/doc-without-codeblock.rs:3:1
+   |
+LL | /// Some docs.
+   | ^^^^^^^^^^^^^^
+
 error: aborting due to 4 previous errors
 
index 31e7fc48afde5cec42a12f9c4ef457cfde679ae2..be98cac94ece71e522fd97a923b02b48e12c238f 100644 (file)
@@ -106,6 +106,15 @@ LL | /// [S!]
    |      this link resolves to the struct `S`, which is not in the macro namespace
    |      help: to link to the struct, prefix with `struct@`: `struct@S`
 
+error: unresolved link to `S::h`
+  --> $DIR/intra-link-errors.rs:78:6
+   |
+LL | /// [type@S::h]
+   |      ^^^^^^^^^
+   |      |
+   |      this link resolves to the associated function `h`, which is not in the type namespace
+   |      help: to link to the associated function, add parentheses: `S::h()`
+
 error: unresolved link to `T::g`
   --> $DIR/intra-link-errors.rs:86:6
    |
@@ -121,15 +130,6 @@ error: unresolved link to `T::h`
 LL | /// [T::h!]
    |      ^^^^^ the trait `T` has no macro named `h`
 
-error: unresolved link to `S::h`
-  --> $DIR/intra-link-errors.rs:78:6
-   |
-LL | /// [type@S::h]
-   |      ^^^^^^^^^
-   |      |
-   |      this link resolves to the associated function `h`, which is not in the type namespace
-   |      help: to link to the associated function, add parentheses: `S::h()`
-
 error: unresolved link to `m`
   --> $DIR/intra-link-errors.rs:98:6
    |
index 21b92a9673755bbea2d24d516478d8f2628bc8ec..936055da01cf741be71a7e3e0455cc60c2581d9e 100644 (file)
@@ -1,14 +1,29 @@
-error: `ambiguous` is both a struct and a function
-  --> $DIR/intra-links-ambiguity.rs:27:6
+error: `true` is both a module and a builtin type
+  --> $DIR/intra-links-ambiguity.rs:38:6
    |
-LL | /// [`ambiguous`] is ambiguous.
-   |      ^^^^^^^^^^^ ambiguous link
+LL | /// [true]
+   |      ^^^^ ambiguous link
    |
 note: the lint level is defined here
   --> $DIR/intra-links-ambiguity.rs:1:9
    |
 LL | #![deny(broken_intra_doc_links)]
    |         ^^^^^^^^^^^^^^^^^^^^^^
+help: to link to the module, prefix with `mod@`
+   |
+LL | /// [mod@true]
+   |      ^^^^^^^^
+help: to link to the builtin type, prefix with `prim@`
+   |
+LL | /// [prim@true]
+   |      ^^^^^^^^^
+
+error: `ambiguous` is both a struct and a function
+  --> $DIR/intra-links-ambiguity.rs:27:6
+   |
+LL | /// [`ambiguous`] is ambiguous.
+   |      ^^^^^^^^^^^ ambiguous link
+   |
 help: to link to the struct, prefix with `struct@`
    |
 LL | /// [`struct@ambiguous`] is ambiguous.
@@ -82,20 +97,5 @@ help: to link to the function, add parentheses
 LL | /// Ambiguous non-implied shortcut link [`foo::bar()`].
    |                                          ^^^^^^^^^^^^
 
-error: `true` is both a module and a builtin type
-  --> $DIR/intra-links-ambiguity.rs:38:6
-   |
-LL | /// [true]
-   |      ^^^^ ambiguous link
-   |
-help: to link to the module, prefix with `mod@`
-   |
-LL | /// [mod@true]
-   |      ^^^^^^^^
-help: to link to the builtin type, prefix with `prim@`
-   |
-LL | /// [prim@true]
-   |      ^^^^^^^^^
-
 error: aborting due to 6 previous errors
 
index 4cdb8bbdde782ba90503a070b5736c0969bb31e7..0b074e9d53e3d640313aa06e10fc00becfc39df6 100644 (file)
@@ -44,6 +44,60 @@ LL |        /// [Qux:Y]
    |
    = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
+warning: unresolved link to `BarA`
+  --> $DIR/intra-links-warning.rs:21:10
+   |
+LL | /// bar [BarA] bar
+   |          ^^^^ no item named `BarA` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `BarB`
+  --> $DIR/intra-links-warning.rs:27:9
+   |
+LL |  * bar [BarB] bar
+   |         ^^^^ no item named `BarB` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `BarC`
+  --> $DIR/intra-links-warning.rs:34:6
+   |
+LL | bar [BarC] bar
+   |      ^^^^ no item named `BarC` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `BarD`
+  --> $DIR/intra-links-warning.rs:45:1
+   |
+LL | #[doc = "Foo\nbar [BarD] bar\nbaz"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the link appears in this line:
+           
+           bar [BarD] bar
+                ^^^^
+   = note: no item named `BarD` in scope
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `BarF`
+  --> $DIR/intra-links-warning.rs:50:9
+   |
+LL |         #[doc = $f]
+   |         ^^^^^^^^^^^
+...
+LL | f!("Foo\nbar [BarF] bar\nbaz");
+   | ------------------------------- in this macro invocation
+   |
+   = note: the link appears in this line:
+           
+           bar [BarF] bar
+                ^^^^
+   = note: no item named `BarF` in scope
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+   = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
 warning: unresolved link to `error`
   --> $DIR/intra-links-warning.rs:58:30
    |
@@ -117,59 +171,5 @@ LL | /// docs [error2]
    |
    = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: unresolved link to `BarA`
-  --> $DIR/intra-links-warning.rs:21:10
-   |
-LL | /// bar [BarA] bar
-   |          ^^^^ no item named `BarA` in scope
-   |
-   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
-
-warning: unresolved link to `BarB`
-  --> $DIR/intra-links-warning.rs:27:9
-   |
-LL |  * bar [BarB] bar
-   |         ^^^^ no item named `BarB` in scope
-   |
-   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
-
-warning: unresolved link to `BarC`
-  --> $DIR/intra-links-warning.rs:34:6
-   |
-LL | bar [BarC] bar
-   |      ^^^^ no item named `BarC` in scope
-   |
-   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
-
-warning: unresolved link to `BarD`
-  --> $DIR/intra-links-warning.rs:45:1
-   |
-LL | #[doc = "Foo\nbar [BarD] bar\nbaz"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: the link appears in this line:
-           
-           bar [BarD] bar
-                ^^^^
-   = note: no item named `BarD` in scope
-   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
-
-warning: unresolved link to `BarF`
-  --> $DIR/intra-links-warning.rs:50:9
-   |
-LL |         #[doc = $f]
-   |         ^^^^^^^^^^^
-...
-LL | f!("Foo\nbar [BarF] bar\nbaz");
-   | ------------------------------- in this macro invocation
-   |
-   = note: the link appears in this line:
-           
-           bar [BarF] bar
-                ^^^^
-   = note: no item named `BarF` in scope
-   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
-   = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
 warning: 19 warnings emitted
 
index 32756c99e7f9fde9822c46b2829ebdb58a872eb9..e02ed4a056c128503dec0c5b2af88067fe8d2eae 100644 (file)
@@ -1,8 +1,9 @@
 error: missing code example in this documentation
-  --> $DIR/lint-missing-doc-code-example.rs:49:1
+  --> $DIR/lint-missing-doc-code-example.rs:19:1
    |
-LL | /// Doc
-   | ^^^^^^^
+LL | / mod module1 {
+LL | | }
+   | |_^
    |
 note: the lint level is defined here
   --> $DIR/lint-missing-doc-code-example.rs:2:9
@@ -11,29 +12,28 @@ LL | #![deny(missing_doc_code_examples)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing code example in this documentation
-  --> $DIR/lint-missing-doc-code-example.rs:63:1
+  --> $DIR/lint-missing-doc-code-example.rs:37:3
    |
-LL | /// Doc
-   | ^^^^^^^
+LL |   /// doc
+   |   ^^^^^^^
 
 error: missing code example in this documentation
-  --> $DIR/lint-missing-doc-code-example.rs:56:1
+  --> $DIR/lint-missing-doc-code-example.rs:49:1
    |
 LL | /// Doc
    | ^^^^^^^
 
 error: missing code example in this documentation
-  --> $DIR/lint-missing-doc-code-example.rs:19:1
+  --> $DIR/lint-missing-doc-code-example.rs:56:1
    |
-LL | / mod module1 {
-LL | | }
-   | |_^
+LL | /// Doc
+   | ^^^^^^^
 
 error: missing code example in this documentation
-  --> $DIR/lint-missing-doc-code-example.rs:37:3
+  --> $DIR/lint-missing-doc-code-example.rs:63:1
    |
-LL |   /// doc
-   |   ^^^^^^^
+LL | /// Doc
+   | ^^^^^^^
 
 error: aborting due to 5 previous errors
 
index a1fa611994f1a4bb5039824d1dcf1016bb30eca4..93d4bf2f656a3262a86d25a6ffe05adc7a1faedd 100644 (file)
@@ -1,6 +1,6 @@
 // aux-build:auto-traits.rs
 
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 
 #![crate_name = "foo"]
 
index 7b52a69f5609f218c562b665643734589fb4feff..b8f3527510cc99fe587d959fb44ca592e2df5a2d 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 
 // @has auto_aliases/trait.Bar.html '//h3[@aliases="auto_aliases::Foo"]' 'impl Bar for Foo'
 pub struct Foo;
index f52210613888d18af71a96de4490768018ffcbac..84976c73beed525e2fc37eb17b329ae52204c719 100644 (file)
@@ -1,3 +1,3 @@
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 
 pub unsafe auto trait Bar {}
diff --git a/src/test/rustdoc/auxiliary/normalize-assoc-item.rs b/src/test/rustdoc/auxiliary/normalize-assoc-item.rs
new file mode 100644 (file)
index 0000000..fbd111c
--- /dev/null
@@ -0,0 +1,12 @@
+#![crate_name = "inner"]
+pub trait MyTrait {
+    type Y;
+}
+
+impl MyTrait for u32 {
+    type Y = i32;
+}
+
+pub fn foo() -> <u32 as MyTrait>::Y {
+    0
+}
index 36e2821c5a8b92ca112b00dc1c7ff3a481d8d903..032db3b25e673c5c8cf5d8c4f52766676c237bb3 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 
 pub mod bar {
     use std::marker;
index 869aebc774ad4c51ddc30fbc34336b49874e6ed4..135987fc00d517333ca3ef5d846223b76b44c572 100644 (file)
@@ -1,3 +1,3 @@
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 
-pub auto trait AnOibit {}
+pub auto trait AnAutoTrait {}
index c5248c52fb973313eefda0ff4143312fef01cbcd..7db8cc60281794ceb82945925ea037b3f02e7cdf 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(deprecated)]
-
 // @has deprecated_future/index.html '//*[@class="stab deprecated"]' \
 //      'Deprecated'
 // @has deprecated_future/struct.S.html '//*[@class="stab deprecated"]' \
index 18a33438a23461526bc2ece44b97bef31df21fa9..a286856b2c3c1db62d3633254795bb2909241d5e 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(deprecated)]
-
 // @has deprecated/index.html '//*[@class="docblock-short"]/span[@class="stab deprecated"]' \
 //      'Deprecated'
 // @has - '//*[@class="docblock-short"]' 'Deprecated docs'
index a68db9c70ad2daa6eec4d6ccf1818f4b0941bd89..6c5e79d5aa32380bb781b3221dd6540f9ee66c00 100644 (file)
@@ -12,9 +12,9 @@ pub struct Bar<T> { t: T }
 // full impl string.  Instead, just make sure something from each part
 // is mentioned.
 
-// @has implementors/rustdoc_impl_parts_crosscrate/trait.AnOibit.js Bar
+// @has implementors/rustdoc_impl_parts_crosscrate/trait.AnAutoTrait.js Bar
 // @has - Send
-// @has - !AnOibit
+// @has - !AnAutoTrait
 // @has - Copy
-impl<T: Send> !rustdoc_impl_parts_crosscrate::AnOibit for Bar<T>
+impl<T: Send> !rustdoc_impl_parts_crosscrate::AnAutoTrait for Bar<T>
     where T: Copy {}
index 68baca9a04e9aaed63e472caaaa9b62b60967f25..90110babea75fc5417842b0a2a53495d1858a878 100644 (file)
@@ -1,12 +1,12 @@
 #![feature(negative_impls)]
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 
-pub auto trait AnOibit {}
+pub auto trait AnAutoTrait {}
 
 pub struct Foo<T> { field: T }
 
 // @has impl_parts/struct.Foo.html '//*[@class="impl"]//code' \
-//     "impl<T: Clone> !AnOibit for Foo<T> where T: Sync,"
-// @has impl_parts/trait.AnOibit.html '//*[@class="item-list"]//code' \
-//     "impl<T: Clone> !AnOibit for Foo<T> where T: Sync,"
-impl<T: Clone> !AnOibit for Foo<T> where T: Sync {}
+//     "impl<T: Clone> !AnAutoTrait for Foo<T> where T: Sync,"
+// @has impl_parts/trait.AnAutoTrait.html '//*[@class="item-list"]//code' \
+//     "impl<T: Clone> !AnAutoTrait for Foo<T> where T: Sync,"
+impl<T: Clone> !AnAutoTrait for Foo<T> where T: Sync {}
index e3a166b3d0e5fba8709f14b999b21d904f3443de..0ab2fa99f877fa3cf7feeff83fa07200a3cbf05e 100644 (file)
@@ -1,10 +1,11 @@
 // aux-build:impl_trait_aux.rs
 // edition:2018
+// ignore-tidy-linelength
 
 extern crate impl_trait_aux;
 
 // @has impl_trait/fn.func.html
-// @has - '//pre[@class="rust fn"]' "pub fn func<'a>(_x: impl Clone + Into<Vec<u8>> + 'a)"
+// @has - '//pre[@class="rust fn"]' "pub fn func<'a>(_x: impl Clone + Into<Vec<u8, Global>> + 'a)"
 // @!has - '//pre[@class="rust fn"]' 'where'
 pub use impl_trait_aux::func;
 
@@ -31,7 +32,7 @@
 pub use impl_trait_aux::async_fn;
 
 // @has impl_trait/struct.Foo.html
-// @has - '//*[@id="method.method"]//code' "pub fn method<'a>(_x: impl Clone + Into<Vec<u8>> + 'a)"
+// @has - '//*[@id="method.method"]//code' "pub fn method<'a>(_x: impl Clone + Into<Vec<u8, Global>> + 'a)"
 // @!has - '//*[@id="method.method"]//code' 'where'
 pub use impl_trait_aux::Foo;
 
index 7d7289437ff8afe411d27cc9405abc12258fed2d..1de6410f10c430c2c4520d639349230a7f22112d 100644 (file)
 // @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/option/enum.Option.html"]' 'with the generic, Option<T>'
 
 //! We should also try linking to [`Result<T, E>`]; it has *two* generics!
+//! And [`Result<T, !>`] and [`Result<!, E>`].
 //!
 // @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/result/enum.Result.html"]' 'Result<T, E>'
+// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/result/enum.Result.html"]' 'Result<T, !>'
+// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/result/enum.Result.html"]' 'Result<!, E>'
 
 //! Now let's test a trickier case: [`Vec::<T>::new`], or you could write it
 //! [with parentheses as `Vec::<T>::new()`][Vec::<T>::new()].
diff --git a/src/test/rustdoc/intra-link-extern-type.rs b/src/test/rustdoc/intra-link-extern-type.rs
new file mode 100644 (file)
index 0000000..418e0d9
--- /dev/null
@@ -0,0 +1,18 @@
+#![feature(extern_types)]
+
+extern {
+    pub type ExternType;
+}
+
+impl ExternType {
+    pub fn f(&self) {
+
+    }
+}
+
+// @has 'intra_link_extern_type/foreigntype.ExternType.html'
+// @has 'intra_link_extern_type/fn.links_to_extern_type.html' \
+// 'href="../intra_link_extern_type/foreigntype.ExternType.html#method.f"'
+/// See also [ExternType::f]
+pub fn links_to_extern_type() {
+}
index 605059fe0dd8dd65a5a72159c8c05e46a8b9d68c..d468f35e28003242d91df42bb55fce9947c3b566 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(const_fn)]
-
 // @has 'issue_76501/fn.bloop.html' '//pre' 'pub const fn bloop() -> i32'
 /// A useless function that always returns 1.
 pub const fn bloop() -> i32 {
diff --git a/src/test/rustdoc/normalize-assoc-item.rs b/src/test/rustdoc/normalize-assoc-item.rs
new file mode 100644 (file)
index 0000000..70b3c66
--- /dev/null
@@ -0,0 +1,69 @@
+// ignore-tidy-linelength
+// aux-build:normalize-assoc-item.rs
+// build-aux-docs
+// ignore-test
+
+pub trait Trait {
+    type X;
+}
+
+impl Trait for usize {
+    type X = isize;
+}
+
+// @has 'normalize_assoc_item/fn.f.html' '//pre[@class="rust fn"]' 'pub fn f() -> isize'
+pub fn f() -> <usize as Trait>::X {
+    0
+}
+
+pub struct S {
+    // @has 'normalize_assoc_item/struct.S.html' '//span[@id="structfield.box_me_up"]' 'box_me_up: Box<S, Global>'
+    pub box_me_up: <S as Trait>::X,
+    // @has 'normalize_assoc_item/struct.S.html' '//span[@id="structfield.generic"]' 'generic: (usize, isize)'
+    pub generic: <Generic<usize> as Trait>::X,
+}
+
+impl Trait for S {
+    type X = Box<S>;
+}
+
+pub struct Generic<Inner>(Inner);
+
+impl<Inner: Trait> Trait for Generic<Inner> {
+    type X = (Inner, Inner::X);
+}
+
+// These can't be normalized because they depend on a generic parameter.
+// However the user can choose whether the text should be displayed as `Inner::X` or `<Inner as Trait>::X`.
+
+// @has 'normalize_assoc_item/struct.Unknown.html' '//pre[@class="rust struct"]' 'pub struct Unknown<Inner: Trait>(pub <Inner as Trait>::X);'
+pub struct Unknown<Inner: Trait>(pub <Inner as Trait>::X);
+
+// @has 'normalize_assoc_item/struct.Unknown2.html' '//pre[@class="rust struct"]' 'pub struct Unknown2<Inner: Trait>(pub Inner::X);'
+pub struct Unknown2<Inner: Trait>(pub Inner::X);
+
+trait Lifetimes<'a> {
+    type Y;
+}
+
+impl<'a> Lifetimes<'a> for usize {
+    type Y = &'a isize;
+}
+
+// @has 'normalize_assoc_item/fn.g.html' '//pre[@class="rust fn"]' "pub fn g() -> &isize"
+pub fn g() -> <usize as Lifetimes<'static>>::Y {
+    &0
+}
+
+// @has 'normalize_assoc_item/constant.A.html' '//pre[@class="rust const"]' "pub const A: &isize"
+pub const A: <usize as Lifetimes<'static>>::Y = &0;
+
+// test cross-crate re-exports
+extern crate inner;
+// @has 'normalize_assoc_item/fn.foo.html' '//pre[@class="rust fn"]' "pub fn foo() -> i32"
+pub use inner::foo;
+
+// @has 'normalize_assoc_item/fn.h.html' '//pre[@class="rust fn"]' "pub fn h<T>() -> IntoIter<T, Global>"
+pub fn h<T>() -> <Vec<T> as IntoIterator>::IntoIter {
+    vec![].into_iter()
+}
index 7de56080e52b913a466fee75474fa9c5674db99a..504c0687c8dc299a6dc1580308c12a246947c795 100644 (file)
@@ -4,6 +4,10 @@ mod hidden {
     // @has foo/hidden/struct.Foo.html
     // @has - '//p/a' '../../foo/struct.FooBar.html'
     pub struct Foo {}
+    pub union U { a: usize }
+    pub enum Empty {}
+    pub const C: usize = 1;
+    pub static S: usize = 1;
 
     // @has foo/hidden/bar/index.html
     // @has - '//p/a' '../../foo/baz/index.html'
@@ -16,6 +20,14 @@ pub struct Thing {}
 
 // @has foo/struct.FooBar.html
 pub use hidden::Foo as FooBar;
+// @has foo/union.FooU.html
+pub use hidden::U as FooU;
+// @has foo/enum.FooEmpty.html
+pub use hidden::Empty as FooEmpty;
+// @has foo/constant.FooC.html
+pub use hidden::C as FooC;
+// @has foo/static.FooS.html
+pub use hidden::S as FooS;
 
 // @has foo/baz/index.html
 // @has foo/baz/struct.Thing.html
index 341dd572f81c8802ff73e747eda4ac4a95753843..3346ac05ffe47dbef9412a5d345f141248d588c4 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 
 pub auto trait Banana {}
 
diff --git a/src/test/rustdoc/trait-src-link.rs b/src/test/rustdoc/trait-src-link.rs
new file mode 100644 (file)
index 0000000..7711669
--- /dev/null
@@ -0,0 +1,26 @@
+#![crate_name = "quix"]
+pub trait Foo {
+    // @has quix/trait.Foo.html '//a[@href="../src/quix/trait-src-link.rs.html#4"]' '[src]'
+    fn required();
+
+    // @has quix/trait.Foo.html '//a[@href="../src/quix/trait-src-link.rs.html#7"]' '[src]'
+    fn provided() {}
+}
+
+pub struct Bar;
+
+impl Foo for Bar {
+    // @has quix/struct.Bar.html '//a[@href="../src/quix/trait-src-link.rs.html#14"]' '[src]'
+    fn required() {}
+    // @has quix/struct.Bar.html '//a[@href="../src/quix/trait-src-link.rs.html#7"]' '[src]'
+}
+
+pub struct Baz;
+
+impl Foo for Baz {
+    // @has quix/struct.Baz.html '//a[@href="../src/quix/trait-src-link.rs.html#22"]' '[src]'
+    fn required() {}
+
+    // @has quix/struct.Baz.html '//a[@href="../src/quix/trait-src-link.rs.html#25"]' '[src]'
+    fn provided() {}
+}
diff --git a/src/test/ui/abi/issues/issue-22565-rust-call.rs b/src/test/ui/abi/issues/issue-22565-rust-call.rs
new file mode 100644 (file)
index 0000000..055d959
--- /dev/null
@@ -0,0 +1,8 @@
+#![feature(unboxed_closures)]
+
+extern "rust-call" fn b(_i: i32) {}
+//~^ ERROR A function with the "rust-call" ABI must take a single non-self argument that is a tuple
+
+fn main () {
+    b(10);
+}
diff --git a/src/test/ui/abi/issues/issue-22565-rust-call.stderr b/src/test/ui/abi/issues/issue-22565-rust-call.stderr
new file mode 100644 (file)
index 0000000..31fb035
--- /dev/null
@@ -0,0 +1,8 @@
+error: A function with the "rust-call" ABI must take a single non-self argument that is a tuple
+  --> $DIR/issue-22565-rust-call.rs:3:1
+   |
+LL | extern "rust-call" fn b(_i: i32) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/abi/rustcall-generic.rs b/src/test/ui/abi/rustcall-generic.rs
new file mode 100644 (file)
index 0000000..2fa41a7
--- /dev/null
@@ -0,0 +1,9 @@
+// check-pass
+#![feature(unboxed_closures)]
+
+extern "rust-call" fn foo<T>(_: T) {}
+
+fn main() {
+    foo(());
+    foo((1, 2));
+}
index 626de4ed5b6635e48a65142edfbbd838d9b80c48..0128e5e636d3411082dabe50e27e94c659bc5e89 100644 (file)
@@ -1,7 +1,6 @@
 // run-pass
 
 #![allow(unused_imports)]
-// ignore-cloudabi can't run commands
 // ignore-emscripten can't run commands
 // ignore-sgx no processes
 
index 9018ff4bfc2e16fcf6bcbf831554e07e89032564..90df1f3f53e800364259d9817758caa96c4dddbe 100644 (file)
@@ -8,7 +8,6 @@
 // ignore-sparc
 // ignore-sparc64
 // ignore-wasm
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 // ignore-musl FIXME #31506
index a52c285f9f0b4279f65a37448937b88a33f3ff28..6c83e01d4cdb5dc1ae61f89ee5bfad8e5ca7f003 100644 (file)
@@ -8,7 +8,6 @@
 // ignore-sparc
 // ignore-sparc64
 // ignore-wasm
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
index f09fafbc98a18dfb79f5ceeba044b09c0dcbbfca..4d40c7d0d2237cd22c2e1e81006078b43eab7cde 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 // ignore-android no libc
-// ignore-cloudabi no libc
 // ignore-emscripten no libc
 // ignore-sgx no libc
 // ignore-wasm32 no libc
index 4d68160379d9cdc5b001e7c3f276466414feec4e..4f8c44f1763c8e87d644be80c99d5fec955153f2 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 // ignore-android no libc
-// ignore-cloudabi no libc
 // ignore-emscripten no libc
 // ignore-sgx no libc
 // ignore-wasm32 no libc
diff --git a/src/test/ui/asm/naked-invalid-attr.rs b/src/test/ui/asm/naked-invalid-attr.rs
new file mode 100644 (file)
index 0000000..cdb6c17
--- /dev/null
@@ -0,0 +1,51 @@
+// Checks that #[naked] attribute can be placed on function definitions only.
+//
+// ignore-wasm32 asm unsupported
+#![feature(asm)]
+#![feature(naked_functions)]
+#![naked] //~ ERROR should be applied to a function definition
+
+extern "C" {
+    #[naked] //~ ERROR should be applied to a function definition
+    fn f();
+}
+
+#[naked] //~ ERROR should be applied to a function definition
+#[repr(C)]
+struct S {
+    a: u32,
+    b: u32,
+}
+
+trait Invoke {
+    #[naked] //~ ERROR should be applied to a function definition
+    extern "C" fn invoke(&self);
+}
+
+impl Invoke for S {
+    #[naked]
+    extern "C" fn invoke(&self) {
+        unsafe { asm!("", options(noreturn)) }
+    }
+}
+
+#[naked]
+extern "C" fn ok() {
+    unsafe { asm!("", options(noreturn)) }
+}
+
+impl S {
+    #[naked]
+    extern "C" fn g() {
+        unsafe { asm!("", options(noreturn)) }
+    }
+
+    #[naked]
+    extern "C" fn h(&self) {
+        unsafe { asm!("", options(noreturn)) }
+    }
+}
+
+fn main() {
+    #[naked] || {}; //~ ERROR should be applied to a function definition
+}
diff --git a/src/test/ui/asm/naked-invalid-attr.stderr b/src/test/ui/asm/naked-invalid-attr.stderr
new file mode 100644 (file)
index 0000000..565c298
--- /dev/null
@@ -0,0 +1,42 @@
+error: attribute should be applied to a function definition
+  --> $DIR/naked-invalid-attr.rs:13:1
+   |
+LL |   #[naked]
+   |   ^^^^^^^^
+LL |   #[repr(C)]
+LL | / struct S {
+LL | |     a: u32,
+LL | |     b: u32,
+LL | | }
+   | |_- not a function definition
+
+error: attribute should be applied to a function definition
+  --> $DIR/naked-invalid-attr.rs:50:5
+   |
+LL |     #[naked] || {};
+   |     ^^^^^^^^ ----- not a function definition
+
+error: attribute should be applied to a function definition
+  --> $DIR/naked-invalid-attr.rs:21:5
+   |
+LL |     #[naked]
+   |     ^^^^^^^^
+LL |     extern "C" fn invoke(&self);
+   |     ---------------------------- not a function definition
+
+error: attribute should be applied to a function definition
+  --> $DIR/naked-invalid-attr.rs:9:5
+   |
+LL |     #[naked]
+   |     ^^^^^^^^
+LL |     fn f();
+   |     ------- not a function definition
+
+error: attribute should be applied to a function definition
+  --> $DIR/naked-invalid-attr.rs:6:1
+   |
+LL | #![naked]
+   | ^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/asm/naked-params.rs b/src/test/ui/asm/naked-params.rs
new file mode 100644 (file)
index 0000000..46a4fc1
--- /dev/null
@@ -0,0 +1,51 @@
+// Check that use of function parameters is validate in naked functions.
+//
+// ignore-wasm32 asm unsupported
+#![feature(asm)]
+#![feature(naked_functions)]
+#![feature(or_patterns)]
+#![crate_type = "lib"]
+
+#[repr(C)]
+pub struct P { x: u8, y: u16 }
+
+#[naked]
+pub unsafe extern "C" fn f(
+    mut a: u32,
+    //~^ ERROR patterns not allowed in naked function parameters
+    &b: &i32,
+    //~^ ERROR patterns not allowed in naked function parameters
+    (None | Some(_)): Option<std::ptr::NonNull<u8>>,
+    //~^ ERROR patterns not allowed in naked function parameters
+    P { x, y }: P,
+    //~^ ERROR patterns not allowed in naked function parameters
+) {
+    asm!("", options(noreturn))
+}
+
+#[naked]
+pub unsafe extern "C" fn inc(a: u32) -> u32 {
+    a + 1
+    //~^ ERROR use of parameters not allowed inside naked functions
+}
+
+#[naked]
+pub unsafe extern "C" fn inc_asm(a: u32) -> u32 {
+    asm!("/* {0} */", in(reg) a, options(noreturn));
+    //~^ ERROR use of parameters not allowed inside naked functions
+}
+
+#[naked]
+pub unsafe extern "C" fn sum(x: u32, y: u32) -> u32 {
+    // FIXME: Should be detected by asm-only check.
+    (|| { x + y})()
+}
+
+pub fn outer(x: u32) -> extern "C" fn(usize) -> usize {
+    #[naked]
+    pub extern "C" fn inner(y: usize) -> usize {
+        *&y
+        //~^ ERROR use of parameters not allowed inside naked functions
+    }
+    inner
+}
diff --git a/src/test/ui/asm/naked-params.stderr b/src/test/ui/asm/naked-params.stderr
new file mode 100644 (file)
index 0000000..1a99e51
--- /dev/null
@@ -0,0 +1,44 @@
+error: patterns not allowed in naked function parameters
+  --> $DIR/naked-params.rs:14:5
+   |
+LL |     mut a: u32,
+   |     ^^^^^
+
+error: patterns not allowed in naked function parameters
+  --> $DIR/naked-params.rs:16:5
+   |
+LL |     &b: &i32,
+   |     ^^
+
+error: patterns not allowed in naked function parameters
+  --> $DIR/naked-params.rs:18:6
+   |
+LL |     (None | Some(_)): Option<std::ptr::NonNull<u8>>,
+   |      ^^^^^^^^^^^^^^
+
+error: patterns not allowed in naked function parameters
+  --> $DIR/naked-params.rs:20:5
+   |
+LL |     P { x, y }: P,
+   |     ^^^^^^^^^^
+
+error: use of parameters not allowed inside naked functions
+  --> $DIR/naked-params.rs:28:5
+   |
+LL |     a + 1
+   |     ^
+
+error: use of parameters not allowed inside naked functions
+  --> $DIR/naked-params.rs:34:31
+   |
+LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
+   |                               ^
+
+error: use of parameters not allowed inside naked functions
+  --> $DIR/naked-params.rs:47:11
+   |
+LL |         *&y
+   |           ^
+
+error: aborting due to 7 previous errors
+
index fd9e52a6ff2f9eac8591419161b375c9427bd61f..a8d00803a534a3c6cd892e202f2fca42f19cc5e5 100644 (file)
@@ -30,7 +30,7 @@ fn def_et3() -> Et3 {
     impl Tr1 for A {
         type As1 = core::ops::Range<u8>;
         fn mk(&self) -> Self::As1 { 0..10 }
-    };
+    }
     Box::new(A)
 }
 pub fn use_et3() {
index c936fe0550ac98568e07efcee78f360cd4c405b1..b7869e22b4a14c585a0596f60f0104284743cbb9 100644 (file)
@@ -33,7 +33,7 @@ fn assert_forall_tr2<T: for<'a> Tr2<'a>>(_: T) {}
     impl Tr1 for A {
         type As1 = core::ops::Range<u8>;
         fn mk(&self) -> Self::As1 { 0..10 }
-    };
+    }
     &A
 };
 pub fn use_et3() {
index f22a6c44cb84d8994c39a6fab0c65dbce7acdc88..08f965452ef48a30e5b3941bf34f7559fc03edeb 100644 (file)
@@ -35,7 +35,7 @@ fn def_et3() -> Box<dyn Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>
     impl Tr1 for A {
         type As1 = core::ops::Range<u8>;
         fn mk(&self) -> Self::As1 { 0..10 }
-    };
+    }
     let x /* : Box<dyn Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>>> */
         = Box::new(A);
     x
index 497205f9f189ac56d2ca11a2bb9837e6ac5fa6a8..5364f25f89a1154061fc7b9b51183e3b03dfeada 100644 (file)
@@ -39,7 +39,7 @@ fn assert_forall_tr2<T: for<'a> Tr2<'a>>(_: T) {}
     impl Tr1 for A {
         type As1 = core::ops::Range<u8>;
         fn mk(&self) -> Self::As1 { 0..10 }
-    };
+    }
     let x: impl Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>> = A;
     x
 };
index 7b640d5a457dfceb283376a4c64c5b70d354fcf3..47cadf3310bd8612c448661d189fb5b36b16915b 100644 (file)
@@ -27,7 +27,7 @@ fn def_et3() -> impl Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>>
     impl Tr1 for A {
         type As1 = core::ops::Range<u8>;
         fn mk(self) -> Self::As1 { 0..10 }
-    };
+    }
     A
 }
 
index 9ee33e4149aafa3ef13f6baf4e1203cd60dd272e..025540ce20070b21be2ab627008b0436f022e818 100644 (file)
@@ -31,7 +31,7 @@ fn def_et3() -> Et3 {
     impl Tr1 for A {
         type As1 = core::ops::Range<u8>;
         fn mk(self) -> Self::As1 { 0..10 }
-    };
+    }
     A
 }
 pub fn use_et3() {
index f9044c2ea1b6658a26f3c3b1a20c0d269f1218ae..26c852601941a6637d4cef03eb7c64aad4d18b2e 100644 (file)
@@ -6,7 +6,7 @@ LL |     type Ty = Vec<[u8]>;
    | 
   ::: $SRC_DIR/alloc/src/vec.rs:LL:COL
    |
-LL | pub struct Vec<T> {
+LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: AllocRef = Global> {
    |                - required by this bound in `Vec`
    |
    = help: the trait `Sized` is not implemented for `[u8]`
index 133152c309a83ef7ba46ae59bfb803ea0d139d66..7f2e3db6d60f20914a9d37112b6fd6ae9415d632 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 #![feature(negative_impls)]
 // edition:2018
 
index ef3453da6891fb51e3362ce6494b39a24c610969..fe57910530f85ae08adaa502bcc3b347b83edefe 100644 (file)
@@ -2,7 +2,6 @@
 
 #![allow(unused_must_use)]
 #![allow(deprecated)]
-// ignore-cloudabi no process support
 // ignore-emscripten no threads support
 // ignore-sgx no processes
 
index a38b3cfa6665ec35ee8c3b994a95642f64a45886..8770fb1ded8eba4214175209601c9a9e18494e40 100644 (file)
@@ -1,12 +1,12 @@
 enum FooEnum {
     #[test]
-    //~^ ERROR expected an inert attribute, found an attribute macro
+    //~^ ERROR expected non-macro attribute, found attribute macro
     Bar(i32),
 }
 
 struct FooStruct {
     #[test]
-    //~^ ERROR expected an inert attribute, found an attribute macro
+    //~^ ERROR expected non-macro attribute, found attribute macro
     bar: i32,
 }
 
@@ -21,20 +21,20 @@ fn main() {
     match foo_struct {
         FooStruct {
             #[test] bar
-            //~^ ERROR expected an inert attribute, found an attribute macro
+            //~^ ERROR expected non-macro attribute, found attribute macro
         } => {}
     }
 
     match 1 {
         0 => {}
         #[test]
-        //~^ ERROR expected an inert attribute, found an attribute macro
+        //~^ ERROR expected non-macro attribute, found attribute macro
         _ => {}
     }
 
     let _another_foo_strunct = FooStruct {
         #[test]
-        //~^ ERROR expected an inert attribute, found an attribute macro
+        //~^ ERROR expected non-macro attribute, found attribute macro
         bar: 1,
     };
 }
index 31f2a74edb33316e70bd73f3358357986c469c9b..883f96e5c193163ac2311d5bfbf1e41be3ad8729 100644 (file)
@@ -1,32 +1,32 @@
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/attrs-resolution-errors.rs:2:5
+error: expected non-macro attribute, found attribute macro `test`
+  --> $DIR/attrs-resolution-errors.rs:2:7
    |
 LL |     #[test]
-   |     ^^^^^^^
+   |       ^^^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/attrs-resolution-errors.rs:8:5
+error: expected non-macro attribute, found attribute macro `test`
+  --> $DIR/attrs-resolution-errors.rs:8:7
    |
 LL |     #[test]
-   |     ^^^^^^^
+   |       ^^^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/attrs-resolution-errors.rs:23:13
+error: expected non-macro attribute, found attribute macro `test`
+  --> $DIR/attrs-resolution-errors.rs:23:15
    |
 LL |             #[test] bar
-   |             ^^^^^^^
+   |               ^^^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/attrs-resolution-errors.rs:30:9
+error: expected non-macro attribute, found attribute macro `test`
+  --> $DIR/attrs-resolution-errors.rs:30:11
    |
 LL |         #[test]
-   |         ^^^^^^^
+   |           ^^^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/attrs-resolution-errors.rs:36:9
+error: expected non-macro attribute, found attribute macro `test`
+  --> $DIR/attrs-resolution-errors.rs:36:11
    |
 LL |         #[test]
-   |         ^^^^^^^
+   |           ^^^^ not a non-macro attribute
 
 error: aborting due to 5 previous errors
 
index 34d6c3da00ee3308486f6aebcfa127ea1837b591..a997b044c8ff8f21b435d2d4fba66ddf9e654d56 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 
 auto trait Generic<T> {}
 //~^ auto traits cannot have generic parameters [E0567]
index 15fdddc5f3f5c3b779de91a6e2df28ade5d9bee8..567b86c276274dfc4610dd90e388f99780ba1139 100644 (file)
@@ -1,6 +1,6 @@
 // run-pass
 #![allow(unused_doc_comments)]
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 #![feature(negative_impls)]
 
 auto trait Auto {}
index 867f24f8cb45e6088a34a4e0154c199ad1bec208..cb4cf6de1efe976de9bd93fbc45e7cc186c22a64 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 #![feature(negative_impls)]
 
 unsafe auto trait Trait {
index 035db82ba5de0df26ec58513fda41d04993525f8..84e2ce66f9dbd743c9a9c1a4fe4579cd71800689 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 #![feature(negative_impls)]
 
 unsafe auto trait Trait {
index 8824a6d2767f74cc76ade01e05d7e42276651799..6cceaf821f6bfeba8321c543728dfe918d12052e 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 #![feature(negative_impls)]
 
 auto trait Magic : Sized where Option<Self> : Magic {} //~ ERROR E0568
index edbca9151248672a02a63bfb50170fb44ee57c6a..2a76893febc79a775a63e2b70c34b35803652580 100644 (file)
@@ -22,7 +22,7 @@
 //    println!("{:?} {:?}", a, b);
 // }
 
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 #![feature(negative_impls)]
 
 auto trait Magic: Copy {} //~ ERROR E0568
index 71ac2b466c10a191ee0dfff89bdc9970a25ae475..f2fb67f1108f9c70b46785dd55a5448c784cbeaf 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 #![feature(negative_impls)]
 
 auto trait MyTrait {}
index 6483b9213dc5303f4dfb68caf1339a7a3b2aa39d..73ff46d05e46645bf5725f0680ebbaecc6eccd09 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 #![feature(negative_impls)]
 
 auto trait MyTrait {}
index 47cab60625dce59c6b2593b99cef0c2343f26763..f7f56f97f614e78523ff50e71cbe59cac2430fad 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 #![feature(negative_impls)]
 
 auto trait MyTrait {}
index 614a5ff55b1ed0e95d03d85849c955d87e01bc7d..2bbe82270bd06a16c2d4732a74ae95fd6e14c93d 100644 (file)
@@ -3,7 +3,7 @@
 // other words, the auto impl only applies if there are no existing
 // impls whose types unify.
 
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 #![feature(negative_impls)]
 
 auto trait Defaulted { }
diff --git a/src/test/ui/auxiliary/fancy-panic.rs b/src/test/ui/auxiliary/fancy-panic.rs
new file mode 100644 (file)
index 0000000..e5a25a1
--- /dev/null
@@ -0,0 +1,6 @@
+#[macro_export]
+macro_rules! fancy_panic {
+    ($msg:expr) => {
+        panic!($msg)
+    };
+}
index 0f31842b3b783e9c7f8f0c602d303e9a33e43dd6..4862883fd96bdc2c7decd8dcdaa26d8de0066bd2 100644 (file)
@@ -9,7 +9,6 @@
 // compile-flags:-g -Cllvm-args=-enable-tail-merge=0 -Cllvm-args=-opt-bisect-limit=0
 // compile-flags:-Cforce-frame-pointers=yes
 // ignore-pretty issue #37195
-// ignore-cloudabi spawning processes is not supported
 // ignore-emscripten spawning processes is not supported
 // ignore-sgx no processes
 // normalize-stderr-test ".*\n" -> ""
index 234a7f801c04ff19feef6c9b7ec695e721bbeec6..a7d17c43f05176c39c0ba66dc864fd9c0f95c89b 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 // ignore-android FIXME #17520
-// ignore-cloudabi spawning processes is not supported
 // ignore-emscripten spawning processes is not supported
 // ignore-openbsd no support for libbacktrace without filename
 // ignore-sgx no processes
index b9bce7fb5f49bd46df48b85bc65e0ab20ee1245e..10d12a09b257972ebf6715af913e281cfe2e6afc 100644 (file)
@@ -17,7 +17,7 @@ LL |     let x: Vec<dyn Trait + Sized> = Vec::new();
    | 
   ::: $SRC_DIR/alloc/src/vec.rs:LL:COL
    |
-LL | pub struct Vec<T> {
+LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: AllocRef = Global> {
    |                - required by this bound in `Vec`
    |
    = help: the trait `Sized` is not implemented for `dyn Trait`
index 9fb7c7669219d2007fa7aa8a3770b52b7d401f2f..912bda4b5e5000af10f9072de419b363f2781a8c 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 // pretty-expanded FIXME #23616
-// ignore-cloudabi no target_family
 // ignore-wasm32-bare no target_family
 // ignore-sgx
 
index ecf802f7281482d1a7381d97a809d667b42311f2..b4dc1b738638c0b2657989bdec5f58a29f460b72 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no target_family
 // ignore-wasm32-bare no target_family
 // ignore-sgx
 
index 19d774079ab7f9e9563ab7638808880b0eec37cf..4f5197a5ba9b8c2ce36455cff4c9229d29bace59 100644 (file)
@@ -2,7 +2,6 @@
 // Test that cleanups for the RHS of shortcircuiting operators work.
 
 // pretty-expanded FIXME #23616
-// ignore-cloudabi no std::env support
 
 use std::env;
 
index 4115ba34e17b2fca9f504336b254eeba2014dd6f..d57fb4777540394a8c87b9351a0b6f90f815acd6 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 #![feature(negative_impls)]
 
 auto trait MySafeTrait {}
index a9c8d20a79d75f59fe79d2a75de34f5bc642bbe9..50d9a480ad1e59060bf9b41cc8441d46f55a2f35 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 #![feature(negative_impls)]
 
 // Test for issue #56934 - that it is impossible to redundantly
index c565f9c83e89ef3e575b499c178a634d06cfacee..faac6d983f31e7e8783678c3ac2c7246ea9fe539 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 #![feature(negative_impls)]
 
 // Test for issue #56934 - that it is impossible to redundantly
index cb948a91c1054babcbbabe8e3b793cfbe92a4246..4aba1229f29a822f29995579a8b0ef84822cb4be 100644 (file)
@@ -1,7 +1,6 @@
 // run-pass
 
 // ignore-windows - this is a unix-specific test
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 use std::os::unix::process::CommandExt;
index e3394e0567cb857be3ffff16c9e7f2630a1a9ca7..b782a4fd3d1db195575c157e5b65ccc31abef05f 100644 (file)
@@ -1,7 +1,6 @@
 // run-pass
 
 // ignore-windows - this is a unix-specific test
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 use std::env;
index 568be67abe372bf106e50f3ca9b4b598abf8d75c..0af87214f9523bae6366e92d348d64cf4ccc3312 100644 (file)
@@ -3,7 +3,6 @@
 #![allow(stable_features)]
 // ignore-windows - this is a unix-specific test
 // ignore-pretty issue #37199
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
index c0fc554183a43fa1262d94c5eeeed7d2590a50fa..8fc6a220331f0d6b73d98f4e9fba54b1ff120634 100644 (file)
@@ -2,7 +2,6 @@
 
 #![allow(stable_features)]
 // ignore-windows - this is a unix-specific test
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 #![feature(process_exec, rustc_private)]
index f867106c35d0789f289f9e8482fb8f7ce2dd9373..e1eb4b1405b1f89b495ded14dfb1607ec88e959c 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 // ignore-android
-// ignore-cloudabi
 // ignore-emscripten
 // ignore-sgx
 
index d9e29c8262c638e0e25f3547651c4c170fab2e34..4d6560e96e513ef967eb5fd629d5e3f703d4ee4d 100644 (file)
@@ -17,16 +17,16 @@ LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy;
    |                                                      ^
 
 error: cannot find attribute `unknown` in this scope
-  --> $DIR/cfg-generic-params.rs:34:43
+  --> $DIR/cfg-generic-params.rs:19:29
    |
-LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
-   |                                           ^^^^^^^
+LL | fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {}
+   |                             ^^^^^^^
 
 error: cannot find attribute `unknown` in this scope
-  --> $DIR/cfg-generic-params.rs:30:40
+  --> $DIR/cfg-generic-params.rs:22:29
    |
-LL | type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy;
-   |                                        ^^^^^^^
+LL | fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {}
+   |                             ^^^^^^^
 
 error: cannot find attribute `unknown` in this scope
   --> $DIR/cfg-generic-params.rs:26:34
@@ -35,16 +35,16 @@ LL | type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn();
    |                                  ^^^^^^^
 
 error: cannot find attribute `unknown` in this scope
-  --> $DIR/cfg-generic-params.rs:22:29
+  --> $DIR/cfg-generic-params.rs:30:40
    |
-LL | fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {}
-   |                             ^^^^^^^
+LL | type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy;
+   |                                        ^^^^^^^
 
 error: cannot find attribute `unknown` in this scope
-  --> $DIR/cfg-generic-params.rs:19:29
+  --> $DIR/cfg-generic-params.rs:34:43
    |
-LL | fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {}
-   |                             ^^^^^^^
+LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
+   |                                           ^^^^^^^
 
 error: aborting due to 8 previous errors
 
index 8bc93fa324378391446dee53883b51c7e4b39ecc..50504a44c95183b78de472e16b1bd886fb5869ed 100644 (file)
@@ -1,6 +1,6 @@
 #![feature(cfg_accessible)]
 
-#[cfg_accessible(Z)] //~ ERROR cannot determine whether the path is accessible or not
+#[cfg_accessible(Z)] // OK, recovered after the other `cfg_accessible` produces an error.
 struct S;
 
 #[cfg_accessible(S)] //~ ERROR cannot determine whether the path is accessible or not
index 9641441a819b0cb0d2d38ff35d80698a5bb7e15e..33af7d62548ec2687b4bb0bb58459f0df6a86763 100644 (file)
@@ -4,11 +4,5 @@ error: cannot determine whether the path is accessible or not
 LL | #[cfg_accessible(S)]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: cannot determine whether the path is accessible or not
-  --> $DIR/cfg_accessible-stuck.rs:3:1
-   |
-LL | #[cfg_accessible(Z)]
-   | ^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
index cfaacf7a5be337d308b571bb0abf9921e1862729..73c9ea59c955bddc4f9f1c4005afc148899f0f7f 100644 (file)
@@ -5,6 +5,7 @@ LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]);
    |                                                ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/array-size-in-generic-struct-param.rs:20:15
@@ -13,6 +14,7 @@ LL |     arr: [u8; CFG.arr_size],
    |               ^^^ cannot perform const operation using `CFG`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `CFG`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: `Config` is forbidden as the type of a const generic parameter
   --> $DIR/array-size-in-generic-struct-param.rs:18:21
@@ -21,7 +23,7 @@ LL | struct B<const CFG: Config> {
    |                     ^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to 3 previous errors
 
index 7dfe250b78e00cd663f361cf3c2753214e8fc122..042fa9ad958b18d4bf22026d20a774c949c867d9 100644 (file)
@@ -5,6 +5,7 @@ LL |     let _: [u8; foo::<T>()];
    |                       ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/const-arg-in-const-arg.rs:15:23
@@ -13,6 +14,7 @@ LL |     let _: [u8; bar::<N>()];
    |                       ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/const-arg-in-const-arg.rs:25:23
@@ -21,6 +23,7 @@ LL |     let _ = [0; bar::<N>()];
    |                       ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/const-arg-in-const-arg.rs:30:24
@@ -29,6 +32,7 @@ LL |     let _: Foo<{ foo::<T>() }>;
    |                        ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/const-arg-in-const-arg.rs:31:24
@@ -37,6 +41,7 @@ LL |     let _: Foo<{ bar::<N>() }>;
    |                        ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/const-arg-in-const-arg.rs:36:27
@@ -45,6 +50,7 @@ LL |     let _ = Foo::<{ foo::<T>() }>;
    |                           ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/const-arg-in-const-arg.rs:37:27
@@ -53,6 +59,7 @@ LL |     let _ = Foo::<{ bar::<N>() }>;
    |                           ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error[E0658]: a non-static lifetime is not allowed in a `const`
   --> $DIR/const-arg-in-const-arg.rs:16:23
index bce701ade8651f22c40c8956a30c0f88fb9a3e2a..8a1074392a5cbd09bf65f568cda92eb9a791a432 100644 (file)
@@ -5,6 +5,7 @@ LL |     pad: [u8; is_zst::<T>()],
    |                        ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error[E0277]: the size for values of type `T` cannot be known at compilation time
   --> $DIR/const-argument-if-length.rs:17:12
index c7e6d1be421610b19a7fde14478d6c6f68bac6c3..354c6d0615f1b5947db9ce8c41be1cb3050224b5 100644 (file)
@@ -17,7 +17,7 @@ LL | fn bar<const X: (), 'a>(_: &'a ()) {
    |                 ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `()` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-before-other-params.rs:11:17
@@ -26,7 +26,7 @@ LL | fn foo<const X: (), T>(_: &T) {}
    |                 ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to 4 previous errors
 
index 81dbaee0ec514ff062cd597731958f1d6d483e59..ed30182690a7abb2f1113e9a071a9658136b6bb3 100644 (file)
@@ -35,7 +35,7 @@ LL | struct A<const N: &u8>;
    |                   ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-elided-lifetime.rs:16:15
@@ -44,7 +44,7 @@ LL | impl<const N: &u8> A<N> {
    |               ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-elided-lifetime.rs:24:15
@@ -53,7 +53,7 @@ LL | impl<const N: &u8> B for A<N> {}
    |               ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-elided-lifetime.rs:28:17
@@ -62,7 +62,7 @@ LL | fn bar<const N: &u8>() {}
    |                 ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-elided-lifetime.rs:19:21
@@ -71,7 +71,7 @@ LL |     fn foo<const M: &u8>(&self) {}
    |                     ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to 10 previous errors
 
index b00a160787629a1be9be1ba90b4de8e57d82592a..6b7a218ada5ddef7b805b7e354056f63ac8f40d7 100644 (file)
@@ -17,7 +17,7 @@ LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
    |                                               ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `[u8; _]` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-type-depends-on-const-param.rs:16:35
@@ -26,7 +26,7 @@ LL | pub struct SelfDependent<const N: [u8; N]>;
    |                                   ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to 4 previous errors
 
index 359c2d2a22f02b672257a665e3dc1780bf74461a..573bc66b7c7e86afa88c1e272e76aad6806b4d73 100644 (file)
@@ -5,6 +5,7 @@ LL | type Arr<const N: usize> = [u8; N - 1];
    |                                 ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: aborting due to previous error
 
index 46485262cc46eab2606aab57e8818647ce607ef9..d476a7eb6455cb95882da003faf9c2724d0f480a 100644 (file)
@@ -5,6 +5,7 @@ LL | fn test<const N: usize>() -> [u8; N - 1] where [u8; N - 1]: Default {
    |                                                     ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/simple.rs:8:35
@@ -13,6 +14,7 @@ LL | fn test<const N: usize>() -> [u8; N - 1] where [u8; N - 1]: Default {
    |                                   ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: aborting due to 2 previous errors
 
index 981d993f58976460988c182404cd31cc11ce2a09..bd81e0bc5a8cfa6d46ba33db138e346df1668d20 100644 (file)
@@ -5,6 +5,7 @@ LL | type Arr<const N: usize> = [u8; N - 1];
    |                                 ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: aborting due to previous error
 
index 050b28abe5088168cdc1c8f402489ed3d7a1d6f9..e5b393ffe99ebb5c152685fd456973ecf77fcb95 100644 (file)
@@ -5,7 +5,7 @@ LL | struct Const<const V: [usize; 1]> {}
    |                       ^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to previous error
 
index 40d8f44cafc04c8f5dc1d678c4e6849de2b30ce8..014200178b9ca5ad8a37bac466a364d2d33c8f9b 100644 (file)
@@ -5,7 +5,7 @@ LL | struct B<const X: A>; // ok
    |                   ^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `C` is forbidden as the type of a const generic parameter
   --> $DIR/forbid-non-structural_match-types.rs:15:19
@@ -14,7 +14,7 @@ LL | struct D<const X: C>;
    |                   ^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error[E0741]: `C` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
   --> $DIR/forbid-non-structural_match-types.rs:15:19
index 84449018e4609971b1768a10e97f30baf8c49e83..526f98fe8cd4f3e182b13c636c606df744797baf 100644 (file)
@@ -5,6 +5,7 @@ LL | fn bar<const N: usize>() -> [u32; foo(N)] {
    |                                       ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/generic-function-call-in-array-length.rs:12:13
@@ -13,6 +14,7 @@ LL |     [0; foo(N)]
    |             ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: aborting due to 2 previous errors
 
index d3f7143327ead8f5023faff290ae4468be4eb9b3..e531b612b5609d5dfe7d5215c578ad7701edd3e1 100644 (file)
@@ -5,6 +5,7 @@ LL | fn foo<const A: usize, const B: usize>(bar: [usize; A + B]) {}
    |                                                     ^ cannot perform const operation using `A`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `A`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/generic-sum-in-array-length.rs:7:57
@@ -13,6 +14,7 @@ LL | fn foo<const A: usize, const B: usize>(bar: [usize; A + B]) {}
    |                                                         ^ cannot perform const operation using `B`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `B`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: aborting due to 2 previous errors
 
index b438ed3ad6508cb2100bc1ea060ba5f56368b264..05bf67a5ff7c6c1bf16da16dd882f02adc496bb3 100644 (file)
@@ -3,6 +3,11 @@ error[E0282]: type annotations needed
    |
 LL |     foo();
    |     ^^^ cannot infer the value of const parameter `X` declared on the function `foo`
+   |
+help: consider specifying the const argument
+   |
+LL |     foo::<X>();
+   |     ^^^^^^^^
 
 error: aborting due to previous error
 
index b438ed3ad6508cb2100bc1ea060ba5f56368b264..05bf67a5ff7c6c1bf16da16dd882f02adc496bb3 100644 (file)
@@ -3,6 +3,11 @@ error[E0282]: type annotations needed
    |
 LL |     foo();
    |     ^^^ cannot infer the value of const parameter `X` declared on the function `foo`
+   |
+help: consider specifying the const argument
+   |
+LL |     foo::<X>();
+   |     ^^^^^^^^
 
 error: aborting due to previous error
 
index 63facbf3b8c0f3f23106d0bedf5c569f3a065a01..99894173bc8f60c7bf88299def65e2e706b2591e 100644 (file)
@@ -3,6 +3,11 @@ error[E0282]: type annotations needed
    |
 LL |         println!("{:?}", take_array_from_mut(&mut arr, i));
    |                          ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `take_array_from_mut`
+   |
+help: consider specifying the const argument
+   |
+LL |         println!("{:?}", take_array_from_mut::<N>(&mut arr, i));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 1fb0b23cf11574d7e997fea6e607e4ac12c00a83..7aa3bd44df84436a69d77774e66fb1baec42bd55 100644 (file)
@@ -3,6 +3,11 @@ error[E0282]: type annotations needed
    |
 LL |     Foo.bar().bar().bar().bar().baz();
    |                                 ^^^ cannot infer the value of const parameter `N` declared on the associated function `baz`
+   |
+help: consider specifying the const argument
+   |
+LL |     Foo.bar().bar().bar().bar().baz::<N>();
+   |                                 ^^^^^^^^
 
 error: aborting due to previous error
 
index 1fb0b23cf11574d7e997fea6e607e4ac12c00a83..7aa3bd44df84436a69d77774e66fb1baec42bd55 100644 (file)
@@ -3,6 +3,11 @@ error[E0282]: type annotations needed
    |
 LL |     Foo.bar().bar().bar().bar().baz();
    |                                 ^^^ cannot infer the value of const parameter `N` declared on the associated function `baz`
+   |
+help: consider specifying the const argument
+   |
+LL |     Foo.bar().bar().bar().bar().baz::<N>();
+   |                                 ^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/infer/one-param-uninferred.full.stderr b/src/test/ui/const-generics/infer/one-param-uninferred.full.stderr
new file mode 100644 (file)
index 0000000..cc6c9a4
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/one-param-uninferred.rs:15:23
+   |
+LL |     let _: [u8; 17] = foo();
+   |                       ^^^ cannot infer the value of const parameter `M` declared on the function `foo`
+   |
+help: consider specifying the const argument
+   |
+LL |     let _: [u8; 17] = foo::<M>();
+   |                       ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/infer/one-param-uninferred.min.stderr b/src/test/ui/const-generics/infer/one-param-uninferred.min.stderr
new file mode 100644 (file)
index 0000000..cc6c9a4
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/one-param-uninferred.rs:15:23
+   |
+LL |     let _: [u8; 17] = foo();
+   |                       ^^^ cannot infer the value of const parameter `M` declared on the function `foo`
+   |
+help: consider specifying the const argument
+   |
+LL |     let _: [u8; 17] = foo::<M>();
+   |                       ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/infer/one-param-uninferred.rs b/src/test/ui/const-generics/infer/one-param-uninferred.rs
new file mode 100644 (file)
index 0000000..0e94713
--- /dev/null
@@ -0,0 +1,17 @@
+// Test that we emit an error if we cannot properly infer a constant.
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
+
+fn foo<const N: usize, const M: usize>() -> [u8; N] {
+    todo!()
+}
+
+fn main() {
+    // FIXME(const_generics): Currently this only suggests one const parameter,
+    // but instead it should suggest to provide all parameters.
+    let _: [u8; 17] = foo();
+                  //~^ ERROR type annotations needed
+}
index 7a451903e9630581760706173e315db758c6dfce..4be625ba90930f475c8ceff6470a339ea13e3a0f 100644 (file)
@@ -2,7 +2,12 @@ error[E0282]: type annotations needed
   --> $DIR/uninferred-consts.rs:14:9
    |
 LL |     Foo.foo();
-   |         ^^^ cannot infer the value of const parameter `N` declared on the associated function `foo`
+   |         ^^^ cannot infer the value of const parameter `A` declared on the associated function `foo`
+   |
+help: consider specifying the const argument
+   |
+LL |     Foo.foo::<A>();
+   |         ^^^^^^^^
 
 error: aborting due to previous error
 
index 7a451903e9630581760706173e315db758c6dfce..4be625ba90930f475c8ceff6470a339ea13e3a0f 100644 (file)
@@ -2,7 +2,12 @@ error[E0282]: type annotations needed
   --> $DIR/uninferred-consts.rs:14:9
    |
 LL |     Foo.foo();
-   |         ^^^ cannot infer the value of const parameter `N` declared on the associated function `foo`
+   |         ^^^ cannot infer the value of const parameter `A` declared on the associated function `foo`
+   |
+help: consider specifying the const argument
+   |
+LL |     Foo.foo::<A>();
+   |         ^^^^^^^^
 
 error: aborting due to previous error
 
index ec5b3ffe5440bca973d7657e38d86ceed9562c71..00fb6eac9920810466362d7d3bdbb32696a9b8d9 100644 (file)
@@ -8,7 +8,7 @@
 // taken from https://github.com/rust-lang/rust/issues/70507#issuecomment-615268893
 struct Foo;
 impl Foo {
-    fn foo<const N: usize>(self) {}
+    fn foo<const A: usize, const B: usize>(self) {}
 }
 fn main() {
     Foo.foo();
index 20a8d9fdaab53c5001082a5ba291f46ebb6ceb7e..02467df193c39d380ffb3d952dff3959edac3339 100644 (file)
@@ -5,6 +5,7 @@ LL |     T: Trait<{std::intrinsics::type_name::<T>()}>
    |                                            ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: `&'static str` is forbidden as the type of a const generic parameter
   --> $DIR/intrinsics-type_name-as-const-argument.rs:10:22
@@ -13,7 +14,7 @@ LL | trait Trait<const S: &'static str> {}
    |                      ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to 2 previous errors
 
index 38ad510e5d7f0d4ca587a832c14f15b72de6e8d5..0bd9cbf4f4708eb547d620190946a5584a895ad8 100644 (file)
@@ -1,4 +1,6 @@
+use std::cell::Cell;
+
 fn main() {
-    let _: Vec<&str, "a"> = Vec::new();
+    let _: Cell<&str, "a"> = Cell::new("");
     //~^ ERROR wrong number of generic arguments
 }
index 5111815e002f11b914a999833de143403199b2b9..9b8a5d1ae4f20f46e5bc82a2423ff834cbea9812 100644 (file)
@@ -1,8 +1,8 @@
 error[E0107]: wrong number of generic arguments: expected 1, found 2
-  --> $DIR/invalid-constant-in-args.rs:2:22
+  --> $DIR/invalid-constant-in-args.rs:4:23
    |
-LL |     let _: Vec<&str, "a"> = Vec::new();
-   |                      ^^^ unexpected const argument
+LL |     let _: Cell<&str, "a"> = Cell::new("");
+   |                       ^^^ unexpected const argument
 
 error: aborting due to previous error
 
index 526807f0a247469e728ae6f6e32cae0697a99401..2eaef95c2321607a80a97921dd641b6cec3cdfcc 100644 (file)
@@ -5,6 +5,7 @@ LL | pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
    |                                             ^^^^^ cannot perform const operation using `COUNT`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `COUNT`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/issue-61522-array-len-succ.rs:12:30
@@ -13,6 +14,7 @@ LL |     fn inner(&self) -> &[u8; COUNT + 1] {
    |                              ^^^^^ cannot perform const operation using `COUNT`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `COUNT`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: aborting due to 2 previous errors
 
index 786ded3c2fe42aabc4b2201d3fcb021fd410db84..1c2e7e069a1819948f57a09462b876647c6a8f16 100644 (file)
@@ -5,7 +5,7 @@ LL | trait Trait<const NAME: &'static str> {
    |                         ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to previous error
 
index 3c344edbf1d15f33329187968c9cd8c0ff13aadc..da96b5374a57dfd8acad7e85417099d6cf14dcbf 100644 (file)
@@ -5,6 +5,7 @@ LL |     inner: [(); { [|_: &T| {}; 0].len() }],
    |                         ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error[E0392]: parameter `T` is never used
   --> $DIR/issue-67375.rs:7:12
index 804236c30bd8153fa9e63d5caef60bc1e6c9d416..8fea130baa57c50afe47fbfded37c471f46c6f1d 100644 (file)
@@ -5,6 +5,7 @@ LL |         let x: S = MaybeUninit::uninit();
    |                ^ cannot perform const operation using `S`
    |
    = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/issue-67945-1.rs:17:45
@@ -13,6 +14,7 @@ LL |         let b = &*(&x as *const _ as *const S);
    |                                             ^ cannot perform const operation using `S`
    |
    = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error[E0392]: parameter `S` is never used
   --> $DIR/issue-67945-1.rs:11:12
index 2de942c1220cd636c43358e10bcdd4612bb2274a..50633772b75a91c3062cb9207176f21240c8a5d3 100644 (file)
@@ -5,6 +5,7 @@ LL |         let x: S = MaybeUninit::uninit();
    |                ^ cannot perform const operation using `S`
    |
    = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/issue-67945-2.rs:15:45
@@ -13,6 +14,7 @@ LL |         let b = &*(&x as *const _ as *const S);
    |                                             ^ cannot perform const operation using `S`
    |
    = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error[E0392]: parameter `S` is never used
   --> $DIR/issue-67945-2.rs:9:12
index b176f9d1c75aa95d2b0ecfa8a567aa73c3ecf79e..1de9e71b6eb008021eda8525827033770a8f6907 100644 (file)
@@ -5,6 +5,7 @@ LL |     fn successor() -> Const<{C + 1}> {
    |                              ^ cannot perform const operation using `C`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `C`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: aborting due to previous error
 
index 9e31466259fd9a607957c278a49e26f3e19f3cee..b1d92056a544c259b0438dd606047f924142386d 100644 (file)
@@ -5,6 +5,7 @@ LL |         Self:FooImpl<{N==0}>
    |                       ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: aborting due to previous error
 
index 3bd127ee74a592c401b72f3d9cd30f8e1d931e0c..b338cdb87e1e5ee03e868329e36c3e5adc68dd11 100644 (file)
@@ -5,6 +5,7 @@ LL | pub type TruncatedVector<T, const N: usize> = Vector<T, { N - 1 }>;
    |                                                           ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: aborting due to previous error
 
index c73f62a4a07d9a2141ca5ef1c2c98eedac98c7bd..a4b501a7bb109f343a1965b020ec9af07f768cea 100644 (file)
@@ -5,6 +5,7 @@ LL |     let _ = [0u64; N + 1];
    |                    ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: aborting due to previous error
 
index 6903b20fad63c076690be4d6635c376a720183fb..5117e20d6266b5a26dc0ed999d6a6c876fa942d8 100644 (file)
@@ -5,7 +5,7 @@ LL | fn foo<const T: NoMatch>() -> bool {
    |                 ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to previous error
 
index 34edd09b5156535bbd8338f23d2f8698bd685d58..9f95e5d88623e13bd21e0d3661a302a30fafa5b5 100644 (file)
@@ -11,7 +11,7 @@ LL | fn foo<const N: usize, const A: [u8; N]>() {}
    |                                 ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to 2 previous errors
 
index e6d9fb7a246836c763aa8ae4d87b77406cd86578..5dbfdc6d652b6708f817ddc15f9890c4d498f0f1 100644 (file)
@@ -5,7 +5,7 @@ LL | fn test<const T: &'static dyn A>() {
    |                  ^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error[E0741]: `&'static (dyn A + 'static)` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
   --> $DIR/issue-63322-forbid-dyn.rs:10:18
index 8b02fd108bd5bbc427aa1a8effbe700326b1d300..681166b1d2b94b7d270dfc9c361913bba2896d83 100644 (file)
@@ -5,6 +5,7 @@ LL | impl<T: Foo> MyTrait for T where Is<{T::VAL == 5}>: True {}
    |                                      ^^^^^^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/issue-64494.rs:19:38
@@ -13,6 +14,7 @@ LL | impl<T: Foo> MyTrait for T where Is<{T::VAL == 6}>: True {}
    |                                      ^^^^^^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error[E0119]: conflicting implementations of trait `MyTrait`:
   --> $DIR/issue-64494.rs:19:1
index 282f72be6da6e3bc2e139123e90271824caeb544..ecd96ac37e404c059329b91d632ff0023a91d563 100644 (file)
@@ -5,6 +5,7 @@ LL |     fact::<{ N - 1 }>();
    |              ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: aborting due to previous error
 
index b900a0d096ac2d71642415634ab95d9a48d3aea3..acaf4a33ee0a88548c34a6fd72e23f9d0e4009e9 100644 (file)
@@ -5,6 +5,7 @@ LL | impl <const N: usize> Collatz<{Some(N)}> {}
    |                                     ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates
   --> $DIR/issue-68366.rs:12:13
index 81c8f4392c735e9288633ea15796f998485f4959..59653114a6b61f81582fc39526532c5de1b629ab 100644 (file)
@@ -5,7 +5,7 @@ LL | struct Const<const V: [usize; 0]> {}
    |                       ^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to previous error
 
index 8f55a92fce9af58abfb5dbd297ff12f06374c315..1ee881b96ec6037185bae03f24373e21f3ccd244 100644 (file)
@@ -5,7 +5,7 @@ LL | struct Foo<const V: [usize; 0] > {}
    |                     ^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to previous error
 
index 7828d859394979e5841696d97a9bb668f06d1e03..ea91df1e0bf4db0c171bcf4a80a4a240188d4eee 100644 (file)
@@ -5,6 +5,7 @@ LL |     PhantomU8<{(INT_BITS + FRAC_BITS + 7) / 8}>;
    |                 ^^^^^^^^ cannot perform const operation using `INT_BITS`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `INT_BITS`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/issue-68977.rs:29:28
@@ -13,6 +14,7 @@ LL |     PhantomU8<{(INT_BITS + FRAC_BITS + 7) / 8}>;
    |                            ^^^^^^^^^ cannot perform const operation using `FRAC_BITS`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `FRAC_BITS`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: aborting due to 2 previous errors
 
index 79d63443351ff6045f0a65feb0f1e6818cc2769b..9b0a2946ca6cfa14dff6f1593f1d8fd2cb81e2d9 100644 (file)
@@ -11,7 +11,7 @@ LL | fn foo<const LEN: usize, const DATA: [u8; LEN]>() {}
    |                                      ^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to 2 previous errors
 
index d960d9513b7528e8a083944e5a3e9d30b91bc3c6..27bbc28011f2e5c9e84fcb69b216d41577dbdfb1 100644 (file)
@@ -5,6 +5,7 @@ LL |     Condition<{ LHS <= RHS }>: True
    |                 ^^^ cannot perform const operation using `LHS`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `LHS`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/issue-72787.rs:11:24
@@ -13,6 +14,7 @@ LL |     Condition<{ LHS <= RHS }>: True
    |                        ^^^ cannot perform const operation using `RHS`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `RHS`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/issue-72787.rs:26:25
@@ -21,6 +23,7 @@ LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
    |                         ^ cannot perform const operation using `I`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `I`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/issue-72787.rs:26:36
@@ -29,6 +32,7 @@ LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
    |                                    ^ cannot perform const operation using `J`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `J`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error[E0283]: type annotations needed
   --> $DIR/issue-72787.rs:22:26
index 9fec3eb946d8313c92ce512338444a72da4101de..2394b23d7995be7ed55ed882353dbc1c1229c3a0 100644 (file)
@@ -5,6 +5,7 @@ LL | where Assert::<{N < usize::max_value() / 2}>: IsTrue,
    |                 ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: aborting due to previous error
 
index 5bf3671d38be354af5306ac7484a50a05a0c523d..3ff0563acc77d0281e3be0cd128ff5a33b0cb8f9 100644 (file)
@@ -5,7 +5,7 @@ LL | fn hoge<const IN: [u32; LEN]>() {}
    |                   ^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to previous error
 
index 8062faefbe60b25ea5bbdd3cd21da3ef6c495f87..1351246667e9bb9802b24898fb1454c243799d46 100644 (file)
@@ -5,7 +5,7 @@ LL | fn test<const N: [u8; 1 + 2]>() {}
    |                  ^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `[u8; _]` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74101.rs:10:21
@@ -14,7 +14,7 @@ LL | struct Foo<const N: [u8; 1 + 2]>;
    |                     ^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to 2 previous errors
 
index 86937d715c9739b11dc9a4396a1d95918b0f9ab9..e3e8502ae6349312f0528b86ec1cc2c19f48733b 100644 (file)
@@ -5,7 +5,7 @@ LL |     fn ice_struct_fn<const I: IceEnum>() {}
    |                               ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to previous error
 
index f093e6651bc2826bd14c7536ea3264f3a32e31c4..12947a2ab37583497d7dd27645b14a6c206be47c 100644 (file)
@@ -5,7 +5,7 @@ LL | struct Outer<const I: Inner>;
    |                       ^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `Inner` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74950.rs:18:23
@@ -14,7 +14,7 @@ LL | struct Outer<const I: Inner>;
    |                       ^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `Inner` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74950.rs:18:23
@@ -23,7 +23,7 @@ LL | struct Outer<const I: Inner>;
    |                       ^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `Inner` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74950.rs:18:23
@@ -32,7 +32,7 @@ LL | struct Outer<const I: Inner>;
    |                       ^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `Inner` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74950.rs:18:23
@@ -41,7 +41,7 @@ LL | struct Outer<const I: Inner>;
    |                       ^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to 5 previous errors
 
index edc54b082dbcbcde8d5f02accb1ef04994233ffc..b87bb18a5a6830cdd8d1e904700d02187b25e8ab 100644 (file)
@@ -5,7 +5,7 @@ LL | struct Foo<const N: [u8; Bar::<u32>::value()]>;
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to previous error
 
index c10db84ea6ecc1c1fc36e22907cf0c2f2c70302c..551b8e43e1d4c00298f8f733f4ad74320400a615 100644 (file)
@@ -5,6 +5,7 @@ LL | fn ty_param<T>() -> [u8; std::mem::size_of::<T>()] {
    |                                              ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/issue-76701-ty-param-in-const.rs:12:42
@@ -13,6 +14,7 @@ LL | fn const_param<const N: usize>() -> [u8; N + 1] {
    |                                          ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: aborting due to 2 previous errors
 
index e5b67f61a25b7463c315ebb2fb29d51c003b9b83..3c9d4c9b4700f24f96be6d2840f46b391b147ea3 100644 (file)
@@ -1,16 +1,16 @@
 error: expressions must be enclosed in braces to be used as const generic arguments
-  --> $DIR/macro_rules-braces.rs:34:17
+  --> $DIR/macro_rules-braces.rs:49:17
    |
-LL |     let _: baz!(N);
-   |                 ^
+LL |     let _: baz!(m::P);
+   |                 ^^^^
    |
 help: enclose the `const` expression in braces
    |
-LL |     let _: baz!({ N });
-   |                 ^   ^
+LL |     let _: baz!({ m::P });
+   |                 ^      ^
 
 error: expressions must be enclosed in braces to be used as const generic arguments
-  --> $DIR/macro_rules-braces.rs:54:17
+  --> $DIR/macro_rules-braces.rs:69:17
    |
 LL |     let _: baz!(10 + 7);
    |                 ^^^^^^
@@ -21,7 +21,7 @@ LL |     let _: baz!({ 10 + 7 });
    |                 ^        ^
 
 error: constant expression depends on a generic parameter
-  --> $DIR/macro_rules-braces.rs:10:13
+  --> $DIR/macro_rules-braces.rs:16:13
    |
 LL |             [u8; $x]
    |             ^^^^^^^^
@@ -33,7 +33,7 @@ LL |     let _: foo!({{ N }});
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: constant expression depends on a generic parameter
-  --> $DIR/macro_rules-braces.rs:15:13
+  --> $DIR/macro_rules-braces.rs:21:13
    |
 LL |             [u8; { $x }]
    |             ^^^^^^^^^^^^
@@ -45,7 +45,7 @@ LL |     let _: bar!({ N });
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: constant expression depends on a generic parameter
-  --> $DIR/macro_rules-braces.rs:20:13
+  --> $DIR/macro_rules-braces.rs:26:13
    |
 LL |             Foo<$x>
    |             ^^^^^^^
@@ -57,7 +57,7 @@ LL |     let _: baz!({{ N }});
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: constant expression depends on a generic parameter
-  --> $DIR/macro_rules-braces.rs:25:13
+  --> $DIR/macro_rules-braces.rs:31:13
    |
 LL |             Foo<{ $x }>
    |             ^^^^^^^^^^^
index a4ef732017dd531448afbc3773fb60e830a01abd..c400e2c814dd70a872ec58e3a18dff04eff140ce 100644 (file)
@@ -1,16 +1,16 @@
 error: expressions must be enclosed in braces to be used as const generic arguments
-  --> $DIR/macro_rules-braces.rs:34:17
+  --> $DIR/macro_rules-braces.rs:49:17
    |
-LL |     let _: baz!(N);
-   |                 ^
+LL |     let _: baz!(m::P);
+   |                 ^^^^
    |
 help: enclose the `const` expression in braces
    |
-LL |     let _: baz!({ N });
-   |                 ^   ^
+LL |     let _: baz!({ m::P });
+   |                 ^      ^
 
 error: expressions must be enclosed in braces to be used as const generic arguments
-  --> $DIR/macro_rules-braces.rs:54:17
+  --> $DIR/macro_rules-braces.rs:69:17
    |
 LL |     let _: baz!(10 + 7);
    |                 ^^^^^^
@@ -21,36 +21,40 @@ LL |     let _: baz!({ 10 + 7 });
    |                 ^        ^
 
 error: generic parameters may not be used in const operations
-  --> $DIR/macro_rules-braces.rs:31:20
+  --> $DIR/macro_rules-braces.rs:37:20
    |
 LL |     let _: foo!({{ N }});
    |                    ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
-  --> $DIR/macro_rules-braces.rs:33:19
+  --> $DIR/macro_rules-braces.rs:41:19
    |
 LL |     let _: bar!({ N });
    |                   ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
-  --> $DIR/macro_rules-braces.rs:36:20
+  --> $DIR/macro_rules-braces.rs:46:20
    |
 LL |     let _: baz!({{ N }});
    |                    ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
-  --> $DIR/macro_rules-braces.rs:38:19
+  --> $DIR/macro_rules-braces.rs:51:19
    |
 LL |     let _: biz!({ N });
    |                   ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: aborting due to 6 previous errors
 
index bc67d464f11bb0170c8cd045225e9b52bb6e75c2..c6b43bec243f4d46c6a85f805833840d14fed8aa 100644 (file)
@@ -3,6 +3,12 @@
 #![cfg_attr(full, feature(const_generics))]
 #![cfg_attr(min, feature(min_const_generics))]
 
+mod m {
+    pub const P: usize = 0;
+}
+
+const Q: usize = 0;
+
 fn test<const N: usize>() {
     struct Foo<const M: usize>;
     macro_rules! foo {
@@ -29,13 +35,22 @@ macro_rules! biz {
     let _: foo!(N);
     let _: foo!({ N });
     let _: foo!({{ N }}); //[min]~ ERROR generic parameters may not
+    let _: foo!(Q);
+    let _: foo!(m::P);
     let _: bar!(N);
     let _: bar!({ N }); //[min]~ ERROR generic parameters may not
-    let _: baz!(N); //~ ERROR expressions must be enclosed in braces
+    let _: bar!(Q);
+    let _: bar!(m::P);
+    let _: baz!(N);
     let _: baz!({ N });
     let _: baz!({{ N }}); //[min]~ ERROR generic parameters may not
+    let _: baz!(Q);
+    let _: baz!({ m::P });
+    let _: baz!(m::P); //~ ERROR expressions must be enclosed in braces
     let _: biz!(N);
     let _: biz!({ N }); //[min]~ ERROR generic parameters may not
+    let _: biz!(Q);
+    let _: biz!(m::P);
     let _: foo!(3);
     let _: foo!({ 3 });
     let _: foo!({{ 3 }});
index a8de987e1675ed2f2939c0a71a17f29c188be6e6..2ea66279d460881ed3c97f73bb90d01f91269a96 100644 (file)
@@ -5,6 +5,7 @@ LL | struct Break0<const N: usize>([u8; { N + 1 }]);
    |                                      ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/complex-expression.rs:14:40
@@ -13,6 +14,7 @@ LL | struct Break1<const N: usize>([u8; { { N } }]);
    |                                        ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/complex-expression.rs:18:17
@@ -21,6 +23,7 @@ LL |     let _: [u8; N + 1];
    |                 ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/complex-expression.rs:23:17
@@ -29,6 +32,7 @@ LL |     let _ = [0; N + 1];
    |                 ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/complex-expression.rs:27:45
@@ -37,6 +41,7 @@ LL | struct BreakTy0<T>(T, [u8; { size_of::<*mut T>() }]);
    |                                             ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/complex-expression.rs:30:47
@@ -45,6 +50,7 @@ LL | struct BreakTy1<T>(T, [u8; { { size_of::<*mut T>() } }]);
    |                                               ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/complex-expression.rs:34:32
@@ -53,6 +59,7 @@ LL |     let _: [u8; size_of::<*mut T>() + 1];
    |                                ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 warning: cannot use constants which depend on generic parameters in types
   --> $DIR/complex-expression.rs:39:17
index 52ed3c1c6ee8c80341234a9a915fb9997218a947..5d473f1f8769fa8d477fd7770b888a3a57296d9b 100644 (file)
@@ -5,7 +5,7 @@ LL | struct Foo<const N: [u8; 0]>;
    |                     ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `()` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:7:21
@@ -14,7 +14,7 @@ LL | struct Bar<const N: ()>;
    |                     ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `No` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:12:21
@@ -23,7 +23,7 @@ LL | struct Fez<const N: No>;
    |                     ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:15:21
@@ -32,7 +32,7 @@ LL | struct Faz<const N: &'static u8>;
    |                     ^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `!` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:18:21
@@ -41,7 +41,7 @@ LL | struct Fiz<const N: !>;
    |                     ^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `()` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:21:19
@@ -50,7 +50,7 @@ LL | enum Goo<const N: ()> { A, B }
    |                   ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `()` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:24:20
@@ -59,7 +59,7 @@ LL | union Boo<const N: ()> { a: () }
    |                    ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to 7 previous errors
 
index 85ecce551d405f06d2d5ea805deb7326f13a44c2..575fbd33572f094f5a284faf76ab9bb5499a68fa 100644 (file)
@@ -15,14 +15,14 @@ impl<const N: usize> Marker<N> for Example<N> {}
 
 fn make_marker() -> impl Marker<{
     #[macro_export]
-    macro_rules! const_macro { () => {{ 3 }} }; inline!()
+    macro_rules! const_macro { () => {{ 3 }} } inline!()
 }> {
   Example::<{ const_macro!() }>
 }
 
 fn from_marker(_: impl Marker<{
     #[macro_export]
-    macro_rules! inline { () => {{ 3 }} }; inline!()
+    macro_rules! inline { () => {{ 3 }} } inline!()
 }>) {}
 
 fn main() {
@@ -30,7 +30,7 @@ fn main() {
     #[macro_export]
     macro_rules! gimme_a_const {
       ($rusty: ident) => {{ let $rusty = 3; *&$rusty }}
-    };
+    }
     gimme_a_const!(run)
   }>;
 
@@ -42,13 +42,13 @@ macro_rules! gimme_a_const {
 
   let _ok: [u8; {
     #[macro_export]
-    macro_rules! const_two { () => {{ 2 }} };
+    macro_rules! const_two { () => {{ 2 }} }
     const_two!()
   }];
 
   let _ok = [0; {
     #[macro_export]
-    macro_rules! const_three { () => {{ 3 }} };
+    macro_rules! const_three { () => {{ 3 }} }
     const_three!()
   }];
   let _ok = [0; const_three!()];
index 64da5e07df2f4bbfb354cfdb1801d5f55fb35f55..40c73f0b95136bdb9114fa69939eef0c5591afe5 100644 (file)
@@ -5,6 +5,7 @@ LL |     fn t1() -> [u8; std::mem::size_of::<Self>()];
    |                                         ^^^^ cannot perform const operation using `Self`
    |
    = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic `Self` types are currently not permitted in anonymous constants
   --> $DIR/self-ty-in-const-1.rs:14:41
index cc32d8a67fed01fac7e9a9294be521b149d2606c..6c39f6b4c1dc3b8c9f623f0bc3a400fb20e4a480 100644 (file)
@@ -5,7 +5,7 @@ LL | fn a<const X: &'static [u32]>() {}
    |               ^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to previous error
 
index 063120ad074a0afe7c78a5e1d74d291c9926a330..6b90329b72cee19b193cfe3ea3e0776ecd96119d 100644 (file)
@@ -5,7 +5,7 @@ LL | struct Const<const P: &'static ()>;
    |                       ^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to previous error
 
index 4f76ec6e02b22acd19094a46aa59b2d2dfe86ffd..369e387508e9fc46275fa292dd4362a582f4182d 100644 (file)
@@ -12,7 +12,7 @@ LL | | }]>;
    | |__^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
   --> $DIR/nested-type.rs:16:5
index 39aa8087cec50a5fff1ff06003597fda61947205..9e0837a0a620c656254809b597f0d020f4f260b7 100644 (file)
@@ -13,6 +13,7 @@ LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
    |                                            ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: constant values inside of type parameter defaults must not depend on generic parameters
   --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:12:21
index 1f711bef4aa633bed823f9ec73383956e8d4ce6a..46997fed770ac34fb0390fc647d9df383eb337ad 100644 (file)
@@ -5,7 +5,7 @@ LL | struct ConstString<const T: &'static str>;
    |                             ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `&'static [u8]` is forbidden as the type of a const generic parameter
   --> $DIR/slice-const-param-mismatch.rs:10:28
@@ -14,7 +14,7 @@ LL | struct ConstBytes<const T: &'static [u8]>;
    |                            ^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to 2 previous errors
 
index 2a49619e6614ae308b4f554b9dab88001f6299c1..7a9f65233e7937d3b82858313dca05bb0cd4a513 100644 (file)
@@ -5,7 +5,7 @@ LL | pub fn function_with_str<const STRING: &'static str>() -> &'static str {
    |                                        ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `&'static [u8]` is forbidden as the type of a const generic parameter
   --> $DIR/slice-const-param.rs:13:41
@@ -14,7 +14,7 @@ LL | pub fn function_with_bytes<const BYTES: &'static [u8]>() -> &'static [u8] {
    |                                         ^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to 2 previous errors
 
index 97be6ee64457dceff761a6462b40091658a8cee8..9274ccd2b921a9965a621ee0676168c58f6bf4a3 100644 (file)
@@ -5,7 +5,7 @@ LL | struct _Range<const R: std::ops::Range<usize>>;
    |                        ^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `RangeFrom<usize>` is forbidden as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:13:28
@@ -14,7 +14,7 @@ LL | struct _RangeFrom<const R: std::ops::RangeFrom<usize>>;
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `RangeFull` is forbidden as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:18:28
@@ -23,7 +23,7 @@ LL | struct _RangeFull<const R: std::ops::RangeFull>;
    |                            ^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `RangeInclusive<usize>` is forbidden as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:24:33
@@ -32,7 +32,7 @@ LL | struct _RangeInclusive<const R: std::ops::RangeInclusive<usize>>;
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `RangeTo<usize>` is forbidden as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:29:26
@@ -41,7 +41,7 @@ LL | struct _RangeTo<const R: std::ops::RangeTo<usize>>;
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `RangeToInclusive<usize>` is forbidden as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:34:35
@@ -50,7 +50,7 @@ LL | struct _RangeToInclusive<const R: std::ops::RangeToInclusive<usize>>;
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to 6 previous errors
 
index 8656239605dfd8cb1c1fa5576a19dcc7ea73c922..8f240f0d930a4ba7d2bcb04e58b02c91f5f59018 100644 (file)
@@ -5,7 +5,7 @@ LL | trait Get<'a, const N: &'static str> {
    |                        ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: `&'static str` is forbidden as the type of a const generic parameter
   --> $DIR/issue-71348.rs:19:25
@@ -14,7 +14,7 @@ LL |     fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Ta
    |                         ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = note: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#[feature(const_generics)]`
 
 error: aborting due to 2 previous errors
 
index 935f12dd2c3048e8c8f077653e303619d7fdee1a..99142cb6ce7a585d959109023fb87942596d6796 100644 (file)
@@ -5,6 +5,7 @@ LL |     let _: [u8; N + 1];
    |                 ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/wf-misc.rs:17:21
@@ -13,6 +14,7 @@ LL |     let _: Const::<{N + 1}>;
    |                     ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: aborting due to 2 previous errors
 
index 4f936236dbb206470025ebe13aa3e714a4f51b04..30bcb78bcf2701d95da8cc60f4f8a0fcd2fc66d5 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 
-#![feature(const_int_pow)]
 #![feature(wrapping_next_power_of_two)]
 
 const IS_POWER_OF_TWO_A: bool = 0u32.is_power_of_two();
diff --git a/src/test/ui/consts/issue-79137-monomorphic.rs b/src/test/ui/consts/issue-79137-monomorphic.rs
new file mode 100644 (file)
index 0000000..58e0c38
--- /dev/null
@@ -0,0 +1,19 @@
+// check-pass
+
+// Verify that variant count intrinsic can still evaluate for types like `Option<T>`.
+
+#![feature(variant_count)]
+
+pub struct GetVariantCount<T>(T);
+
+impl<T> GetVariantCount<T> {
+    pub const VALUE: usize = std::mem::variant_count::<T>();
+}
+
+const fn check_variant_count<T>() -> bool {
+    matches!(GetVariantCount::<Option<T>>::VALUE, GetVariantCount::<Option<()>>::VALUE)
+}
+
+fn main() {
+    assert!(check_variant_count::<()>());
+}
diff --git a/src/test/ui/consts/issue-79137-toogeneric.rs b/src/test/ui/consts/issue-79137-toogeneric.rs
new file mode 100644 (file)
index 0000000..4560354
--- /dev/null
@@ -0,0 +1,19 @@
+// Test that `variant_count` only gets evaluated once the type is concrete enough.
+
+#![feature(variant_count)]
+
+pub struct GetVariantCount<T>(T);
+
+impl<T> GetVariantCount<T> {
+    pub const VALUE: usize = std::mem::variant_count::<T>();
+}
+
+const fn check_variant_count<T>() -> bool {
+    matches!(GetVariantCount::<T>::VALUE, GetVariantCount::<T>::VALUE)
+    //~^ ERROR constant pattern depends on a generic parameter
+    //~| ERROR constant pattern depends on a generic parameter
+}
+
+fn main() {
+    assert!(check_variant_count::<Option<()>>());
+}
diff --git a/src/test/ui/consts/issue-79137-toogeneric.stderr b/src/test/ui/consts/issue-79137-toogeneric.stderr
new file mode 100644 (file)
index 0000000..579e6aa
--- /dev/null
@@ -0,0 +1,14 @@
+error: constant pattern depends on a generic parameter
+  --> $DIR/issue-79137-toogeneric.rs:12:43
+   |
+LL |     matches!(GetVariantCount::<T>::VALUE, GetVariantCount::<T>::VALUE)
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: constant pattern depends on a generic parameter
+  --> $DIR/issue-79137-toogeneric.rs:12:43
+   |
+LL |     matches!(GetVariantCount::<T>::VALUE, GetVariantCount::<T>::VALUE)
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/consts/issue-79152-const-array-index.rs b/src/test/ui/consts/issue-79152-const-array-index.rs
new file mode 100644 (file)
index 0000000..95518e1
--- /dev/null
@@ -0,0 +1,11 @@
+// check-pass
+// Regression test for issue #79152
+//
+// Tests that we can index an array in a const function
+
+const fn foo() {
+    let mut array = [[0; 1]; 1];
+    array[0][0] = 1;
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/std/net/ip.rs b/src/test/ui/consts/std/net/ip.rs
new file mode 100644 (file)
index 0000000..6730946
--- /dev/null
@@ -0,0 +1,13 @@
+// run-pass
+
+use std::net::{IpAddr, Ipv4Addr};
+
+fn main() {
+    const IP_ADDRESS : IpAddr = IpAddr::V4(Ipv4Addr::LOCALHOST);
+
+    const IS_IP_V4 : bool = IP_ADDRESS.is_ipv4();
+    assert!(IS_IP_V4);
+
+    const IS_IP_V6 : bool = IP_ADDRESS.is_ipv6();
+    assert!(!IS_IP_V6);
+}
index b3614bfd5b6e5a08a7878cdc4ea980f88abe429f..5fd418e6c86c1f86d748f7c446eef68a378bebbc 100644 (file)
@@ -5,7 +5,6 @@
 #![allow(deprecated)]
 #![allow(unused_imports)]
 // compile-flags:--test
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 // ignore-vxworks no 'cat' and 'sleep'
index 6871977c79831c544e15c7f36c51a201bead3c67..100e974977c91b0159bb3018c9c95fc7e1018c41 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
diff --git a/src/test/ui/destructuring-assignment/drop-order.rs b/src/test/ui/destructuring-assignment/drop-order.rs
new file mode 100644 (file)
index 0000000..d06b31c
--- /dev/null
@@ -0,0 +1,44 @@
+// run-pass
+
+//! Test that let bindings and destructuring assignments have consistent drop orders
+
+#![feature(destructuring_assignment)]
+#![allow(unused_variables, unused_assignments)]
+
+use std::cell::RefCell;
+
+thread_local! {
+    static DROP_ORDER: RefCell<Vec<usize>> = RefCell::new(Vec::new());
+}
+
+struct DropRecorder(usize);
+impl Drop for DropRecorder {
+    fn drop(&mut self) {
+        DROP_ORDER.with(|d| d.borrow_mut().push(self.0));
+    }
+}
+
+fn main() {
+    let expected_drop_order = vec![1, 4, 5, 3, 2];
+    // Check the drop order for let bindings:
+    {
+        let _ = DropRecorder(1);
+        let _val = DropRecorder(2);
+        let (x, _) = (DropRecorder(3), DropRecorder(4));
+        drop(DropRecorder(5));
+    }
+    DROP_ORDER.with(|d| {
+        assert_eq!(&*d.borrow(), &expected_drop_order);
+        d.borrow_mut().clear();
+    });
+    // Check that the drop order for destructuring assignment is the same:
+    {
+        let _val;
+        let x;
+        _ = DropRecorder(1);
+        _val = DropRecorder(2);
+        (x, _) = (DropRecorder(3), DropRecorder(4));
+        drop(DropRecorder(5));
+    }
+    DROP_ORDER.with(|d| assert_eq!(&*d.borrow(), &expected_drop_order));
+}
index 0ffd74f87ab6c0bc6ea84a747ce8f3e42841506d..7f06718c038b50f97fc808acdcc3053570a7e694 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
index c5c824ac58d30423fa866ff145418d3717429e70..4548d3339472d60c0c0596bafaef94a0e6305149 100644 (file)
@@ -3,7 +3,6 @@
 
 // ignore-android
 // ignore-windows
-// ignore-cloudabi no execve
 // ignore-emscripten no execve
 // ignore-sgx no execve
 // ignore-vxworks no execve
index a75be48fd5532380c7baa71e178eba94fb4ed5a3..c597b4732d15861c52035059abcc39570fd46d1b 100644 (file)
@@ -2,7 +2,6 @@
 
 #![allow(unused_variables)]
 #![allow(deprecated)]
-// ignore-cloudabi no environment variables present
 // ignore-emscripten env vars don't work?
 // ignore-sgx env vars cannot be modified
 
index 2ea906788e802924a8df40c20ed09e8b907381ba..f73902c40066df552b4fee5f18b6ea57903b4231 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no env vars
 // ignore-wasm32-bare no env vars
 
 use std::env::*;
index 2692fe6945e09ce61ebb5c9e8f3e244e5d7ef5e5..46966f22b6d1e7d6557a84617cb2d33a76e9cf7f 100644 (file)
@@ -9,132 +9,7 @@ LL | impl<T> Foo for T where Bar<T>: Foo {}
    |
    = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`E0275`)
    = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<T>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<T>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<T>>>`
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<T>>`
+   = note: 127 redundant requirements hidden
    = note: required because of the requirements on the impl of `Foo` for `Bar<T>`
 
 error: aborting due to previous error
index e60d83098b9d564e3ceec8461a7a7db8ff2f4b78..f0de4e3deb10fcda1ca24954ce86f205790fcedc 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-cloudabi no std::path
-
 use std::path::Path;
 
 trait Foo {
index 647e0c7d76ff2da1505c07dadbdca668a07a49b1..1f54af4d154e4524e942d8704ee35dfaabe803c0 100644 (file)
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/E0277.rs:13:6
+  --> $DIR/E0277.rs:11:6
    |
 LL | fn f(p: Path) { }
    |      ^ doesn't have a size known at compile-time
@@ -13,7 +13,7 @@ LL | fn f(&p: Path) { }
    |      ^
 
 error[E0277]: the trait bound `i32: Foo` is not satisfied
-  --> $DIR/E0277.rs:17:15
+  --> $DIR/E0277.rs:15:15
    |
 LL | fn some_func<T: Foo>(foo: T) {
    |                 --- required by this bound in `some_func`
index 230fac10d3357fe0c890162819a8ce06d8a44e06..d7f15bcae7d2c4cf19393e64ce14ae72c276547a 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 // exec-env:TEST_EXEC_ENV=22
-// ignore-cloudabi no env vars
 // ignore-emscripten FIXME: issue #31622
 // ignore-sgx unsupported
 
diff --git a/src/test/ui/expr/compound-assignment/eval-order.rs b/src/test/ui/expr/compound-assignment/eval-order.rs
new file mode 100644 (file)
index 0000000..658adae
--- /dev/null
@@ -0,0 +1,76 @@
+// Test evaluation order of operands of the compound assignment operators
+
+// run-pass
+
+use std::ops::AddAssign;
+
+enum Side {
+    Lhs,
+    Rhs,
+}
+
+// In the following tests, we place our value into a wrapper type so that we
+// can do an element access as the outer place expression. If we just had the
+// block expression, it'd be a value expression and not compile.
+struct Wrapper<T>(T);
+
+// Evaluation order for `a op= b` where typeof(a) and typeof(b) are primitives
+// is first `b` then `a`.
+fn primitive_compound() {
+    let mut side_order = vec![];
+    let mut int = Wrapper(0);
+
+    {
+        side_order.push(Side::Lhs);
+        int
+    }.0 += {
+        side_order.push(Side::Rhs);
+        0
+    };
+
+    assert!(matches!(side_order[..], [Side::Rhs, Side::Lhs]));
+}
+
+// Evaluation order for `a op=b` otherwise is first `a` then `b`.
+fn generic_compound<T: AddAssign<T> + Default>() {
+    let mut side_order = vec![];
+    let mut add_assignable: Wrapper<T> = Wrapper(Default::default());
+
+    {
+        side_order.push(Side::Lhs);
+        add_assignable
+    }.0 += {
+        side_order.push(Side::Rhs);
+        Default::default()
+    };
+
+    assert!(matches!(side_order[..], [Side::Lhs, Side::Rhs]));
+}
+
+fn custom_compound() {
+    struct Custom;
+
+    impl AddAssign<()> for Custom {
+        fn add_assign(&mut self, _: ()) {
+            // this block purposely left blank
+        }
+    }
+
+    let mut side_order = vec![];
+    let mut custom = Wrapper(Custom);
+
+    {
+        side_order.push(Side::Lhs);
+        custom
+    }.0 += {
+        side_order.push(Side::Rhs);
+    };
+
+    assert!(matches!(side_order[..], [Side::Lhs, Side::Rhs]));
+}
+
+fn main() {
+    primitive_compound();
+    generic_compound::<i32>();
+    custom_compound();
+}
index 2010b5b668074027a9fdec05b62b760dcd0f683f..4482b7032a75a19b075591cece6eef3c7677147d 100644 (file)
@@ -1,7 +1,6 @@
 // run-pass
 // ignore-windows
 // ignore-android
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-haiku
 // ignore-sgx no processes
index d343746955f3974342b2a1641bf9336f2edf0783..ee3fe712e36e5b944056ace8f272e449553cb13c 100644 (file)
@@ -1,5 +1,6 @@
 // The non-crate level cases are in issue-43106-gating-of-builtin-attrs.rs.
 
+#![allow(soft_unstable)]
 #![test                    = "4200"]
 //~^ ERROR cannot determine resolution for the attribute macro `test`
 
index a7d3a1e16840e39661d6ff27c415c56db1c93f77..335af5e7905f22079f7963ec6979a43f8bdc9af4 100644 (file)
@@ -1,5 +1,5 @@
 error: cannot determine resolution for the attribute macro `test`
-  --> $DIR/issue-43106-gating-of-test.rs:3:4
+  --> $DIR/issue-43106-gating-of-test.rs:4:4
    |
 LL | #![test                    = "4200"]
    |    ^^^^
index e89dc4d5a05a572207d8f683b5f74124277edaf8..31f09cc61f9ac5faa6f6428229c0e098bd6ab351 100644 (file)
@@ -15,7 +15,7 @@ extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change
 extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental
 //~^ ERROR intrinsic must be in
 extern "vectorcall" fn f3() {} //~ ERROR vectorcall is experimental and subject to change
-extern "rust-call" fn f4() {} //~ ERROR rust-call ABI is subject to change
+extern "rust-call" fn f4(_: ()) {} //~ ERROR rust-call ABI is subject to change
 extern "msp430-interrupt" fn f5() {} //~ ERROR msp430-interrupt ABI is experimental
 extern "ptx-kernel" fn f6() {} //~ ERROR PTX ABIs are experimental and subject to change
 extern "x86-interrupt" fn f7() {} //~ ERROR x86-interrupt ABI is experimental
@@ -30,7 +30,7 @@ trait Tr {
     extern "platform-intrinsic" fn m2(); //~ ERROR platform intrinsics are experimental
     //~^ ERROR intrinsic must be in
     extern "vectorcall" fn m3(); //~ ERROR vectorcall is experimental and subject to change
-    extern "rust-call" fn m4(); //~ ERROR rust-call ABI is subject to change
+    extern "rust-call" fn m4(_: ()); //~ ERROR rust-call ABI is subject to change
     extern "msp430-interrupt" fn m5(); //~ ERROR msp430-interrupt ABI is experimental
     extern "ptx-kernel" fn m6(); //~ ERROR PTX ABIs are experimental and subject to change
     extern "x86-interrupt" fn m7(); //~ ERROR x86-interrupt ABI is experimental
@@ -39,7 +39,7 @@ trait Tr {
     extern "efiapi" fn m10(); //~ ERROR efiapi ABI is experimental and subject to change
 
     extern "vectorcall" fn dm3() {} //~ ERROR vectorcall is experimental and subject to change
-    extern "rust-call" fn dm4() {} //~ ERROR rust-call ABI is subject to change
+    extern "rust-call" fn dm4(_: ()) {} //~ ERROR rust-call ABI is subject to change
     extern "msp430-interrupt" fn dm5() {} //~ ERROR msp430-interrupt ABI is experimental
     extern "ptx-kernel" fn dm6() {} //~ ERROR PTX ABIs are experimental and subject to change
     extern "x86-interrupt" fn dm7() {} //~ ERROR x86-interrupt ABI is experimental
@@ -57,7 +57,7 @@ extern "rust-intrinsic" fn m1() {} //~ ERROR intrinsics are subject to change
     extern "platform-intrinsic" fn m2() {} //~ ERROR platform intrinsics are experimental
     //~^ ERROR intrinsic must be in
     extern "vectorcall" fn m3() {} //~ ERROR vectorcall is experimental and subject to change
-    extern "rust-call" fn m4() {} //~ ERROR rust-call ABI is subject to change
+    extern "rust-call" fn m4(_: ()) {} //~ ERROR rust-call ABI is subject to change
     extern "msp430-interrupt" fn m5() {} //~ ERROR msp430-interrupt ABI is experimental
     extern "ptx-kernel" fn m6() {} //~ ERROR PTX ABIs are experimental and subject to change
     extern "x86-interrupt" fn m7() {} //~ ERROR x86-interrupt ABI is experimental
@@ -73,7 +73,7 @@ extern "rust-intrinsic" fn im1() {} //~ ERROR intrinsics are subject to change
     extern "platform-intrinsic" fn im2() {} //~ ERROR platform intrinsics are experimental
     //~^ ERROR intrinsic must be in
     extern "vectorcall" fn im3() {} //~ ERROR vectorcall is experimental and subject to change
-    extern "rust-call" fn im4() {} //~ ERROR rust-call ABI is subject to change
+    extern "rust-call" fn im4(_: ()) {} //~ ERROR rust-call ABI is subject to change
     extern "msp430-interrupt" fn im5() {} //~ ERROR msp430-interrupt ABI is experimental
     extern "ptx-kernel" fn im6() {} //~ ERROR PTX ABIs are experimental and subject to change
     extern "x86-interrupt" fn im7() {} //~ ERROR x86-interrupt ABI is experimental
@@ -86,7 +86,7 @@ extern "efiapi" fn im10() {} //~ ERROR efiapi ABI is experimental and subject to
 type A1 = extern "rust-intrinsic" fn(); //~ ERROR intrinsics are subject to change
 type A2 = extern "platform-intrinsic" fn(); //~ ERROR platform intrinsics are experimental
 type A3 = extern "vectorcall" fn(); //~ ERROR vectorcall is experimental and subject to change
-type A4 = extern "rust-call" fn(); //~ ERROR rust-call ABI is subject to change
+type A4 = extern "rust-call" fn(_: ()); //~ ERROR rust-call ABI is subject to change
 type A5 = extern "msp430-interrupt" fn(); //~ ERROR msp430-interrupt ABI is experimental
 type A6 = extern "ptx-kernel" fn (); //~ ERROR PTX ABIs are experimental and subject to change
 type A7 = extern "x86-interrupt" fn(); //~ ERROR x86-interrupt ABI is experimental
index 50cd8bc68a2a2928a4f45ffb3d745c535f79f5b1..25f0c259d111cb9cdf6c1c9a7daf68132c616fd1 100644 (file)
@@ -26,7 +26,7 @@ LL | extern "vectorcall" fn f3() {}
 error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-abi.rs:18:8
    |
-LL | extern "rust-call" fn f4() {}
+LL | extern "rust-call" fn f4(_: ()) {}
    |        ^^^^^^^^^^^
    |
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
@@ -113,7 +113,7 @@ LL |     extern "vectorcall" fn m3();
 error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-abi.rs:33:12
    |
-LL |     extern "rust-call" fn m4();
+LL |     extern "rust-call" fn m4(_: ());
    |            ^^^^^^^^^^^
    |
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
@@ -183,7 +183,7 @@ LL |     extern "vectorcall" fn dm3() {}
 error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-abi.rs:42:12
    |
-LL |     extern "rust-call" fn dm4() {}
+LL |     extern "rust-call" fn dm4(_: ()) {}
    |            ^^^^^^^^^^^
    |
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
@@ -270,7 +270,7 @@ LL |     extern "vectorcall" fn m3() {}
 error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-abi.rs:60:12
    |
-LL |     extern "rust-call" fn m4() {}
+LL |     extern "rust-call" fn m4(_: ()) {}
    |            ^^^^^^^^^^^
    |
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
@@ -357,7 +357,7 @@ LL |     extern "vectorcall" fn im3() {}
 error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-abi.rs:76:12
    |
-LL |     extern "rust-call" fn im4() {}
+LL |     extern "rust-call" fn im4(_: ()) {}
    |            ^^^^^^^^^^^
    |
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
@@ -444,7 +444,7 @@ LL | type A3 = extern "vectorcall" fn();
 error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-abi.rs:89:18
    |
-LL | type A4 = extern "rust-call" fn();
+LL | type A4 = extern "rust-call" fn(_: ());
    |                  ^^^^^^^^^^^
    |
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
diff --git a/src/test/ui/feature-gates/feature-gate-auto-traits.rs b/src/test/ui/feature-gates/feature-gate-auto-traits.rs
new file mode 100644 (file)
index 0000000..80cfa9c
--- /dev/null
@@ -0,0 +1,12 @@
+// Test that default and negative trait implementations are gated by
+// `auto_traits` feature gate
+
+struct DummyStruct;
+
+auto trait AutoDummyTrait {}
+//~^ ERROR auto traits are experimental and possibly buggy
+
+impl !AutoDummyTrait for DummyStruct {}
+//~^ ERROR negative trait bounds are not yet fully implemented; use marker types for now
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-auto-traits.stderr b/src/test/ui/feature-gates/feature-gate-auto-traits.stderr
new file mode 100644 (file)
index 0000000..e015418
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0658]: auto traits are experimental and possibly buggy
+  --> $DIR/feature-gate-auto-traits.rs:6:1
+   |
+LL | auto trait AutoDummyTrait {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #13231 <https://github.com/rust-lang/rust/issues/13231> for more information
+   = help: add `#![feature(auto_traits)]` to the crate attributes to enable
+
+error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now
+  --> $DIR/feature-gate-auto-traits.rs:9:6
+   |
+LL | impl !AutoDummyTrait for DummyStruct {}
+   |      ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #68318 <https://github.com/rust-lang/rust/issues/68318> for more information
+   = help: add `#![feature(negative_impls)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
index b33710ce04958da3e4902985d8595f78bb23626b..f2287111719bcca3183c778e4781dd766ebc9193 100644 (file)
@@ -1,50 +1,50 @@
-error: cannot find attribute `lt_hof` in this scope
-  --> $DIR/feature-gate-custom_attribute2.rs:51:21
+error: cannot find attribute `lt_struct` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:4:15
    |
-LL |     where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
-   |                     ^^^^^^
+LL | struct StLt<#[lt_struct] 'a>(&'a u32);
+   |               ^^^^^^^^^
 
-error: cannot find attribute `ty_meth` in this scope
-  --> $DIR/feature-gate-custom_attribute2.rs:46:15
+error: cannot find attribute `ty_struct` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:6:15
    |
-LL |     fn m_ty<#[ty_meth] P>(_: P) { }
-   |               ^^^^^^^
+LL | struct StTy<#[ty_struct] I>(I);
+   |               ^^^^^^^^^
 
-error: cannot find attribute `lt_meth` in this scope
-  --> $DIR/feature-gate-custom_attribute2.rs:44:15
+error: cannot find attribute `lt_enum` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:9:13
    |
-LL |     fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
-   |               ^^^^^^^
+LL | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B }
+   |             ^^^^^^^
 
-error: cannot find attribute `ty_fn` in this scope
-  --> $DIR/feature-gate-custom_attribute2.rs:40:11
+error: cannot find attribute `ty_enum` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:11:13
    |
-LL | fn f_ty<#[ty_fn] O>(_: O) { }
-   |           ^^^^^
+LL | enum EnTy<#[ty_enum] J> { A(J), B }
+   |             ^^^^^^^
 
-error: cannot find attribute `lt_fn` in this scope
-  --> $DIR/feature-gate-custom_attribute2.rs:38:11
+error: cannot find attribute `lt_trait` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:14:14
    |
-LL | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
-   |           ^^^^^
+LL | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
+   |              ^^^^^^^^
 
-error: cannot find attribute `ty_impl_for` in this scope
-  --> $DIR/feature-gate-custom_attribute2.rs:33:8
+error: cannot find attribute `ty_trait` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:16:14
    |
-LL | impl<#[ty_impl_for] N> TrTy<N> for StTy<N> {
-   |        ^^^^^^^^^^^
+LL | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); }
+   |              ^^^^^^^^
 
-error: cannot find attribute `lt_impl_for` in this scope
-  --> $DIR/feature-gate-custom_attribute2.rs:29:8
+error: cannot find attribute `lt_type` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:19:13
    |
-LL | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
-   |        ^^^^^^^^^^^
+LL | type TyLt<#[lt_type] 'd> = &'d u32;
+   |             ^^^^^^^
 
-error: cannot find attribute `ty_inherent` in this scope
-  --> $DIR/feature-gate-custom_attribute2.rs:26:8
+error: cannot find attribute `ty_type` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:21:13
    |
-LL | impl<#[ty_inherent] M> StTy<M> { }
-   |        ^^^^^^^^^^^
+LL | type TyTy<#[ty_type] L> = (L, );
+   |             ^^^^^^^
 
 error: cannot find attribute `lt_inherent` in this scope
   --> $DIR/feature-gate-custom_attribute2.rs:24:8
@@ -52,53 +52,53 @@ error: cannot find attribute `lt_inherent` in this scope
 LL | impl<#[lt_inherent] 'e> StLt<'e> { }
    |        ^^^^^^^^^^^
 
-error: cannot find attribute `ty_type` in this scope
-  --> $DIR/feature-gate-custom_attribute2.rs:21:13
+error: cannot find attribute `ty_inherent` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:26:8
    |
-LL | type TyTy<#[ty_type] L> = (L, );
-   |             ^^^^^^^
+LL | impl<#[ty_inherent] M> StTy<M> { }
+   |        ^^^^^^^^^^^
 
-error: cannot find attribute `lt_type` in this scope
-  --> $DIR/feature-gate-custom_attribute2.rs:19:13
+error: cannot find attribute `lt_impl_for` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:29:8
    |
-LL | type TyLt<#[lt_type] 'd> = &'d u32;
-   |             ^^^^^^^
+LL | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
+   |        ^^^^^^^^^^^
 
-error: cannot find attribute `ty_trait` in this scope
-  --> $DIR/feature-gate-custom_attribute2.rs:16:14
+error: cannot find attribute `ty_impl_for` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:33:8
    |
-LL | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); }
-   |              ^^^^^^^^
+LL | impl<#[ty_impl_for] N> TrTy<N> for StTy<N> {
+   |        ^^^^^^^^^^^
 
-error: cannot find attribute `lt_trait` in this scope
-  --> $DIR/feature-gate-custom_attribute2.rs:14:14
+error: cannot find attribute `lt_fn` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:38:11
    |
-LL | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
-   |              ^^^^^^^^
+LL | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
+   |           ^^^^^
 
-error: cannot find attribute `ty_enum` in this scope
-  --> $DIR/feature-gate-custom_attribute2.rs:11:13
+error: cannot find attribute `ty_fn` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:40:11
    |
-LL | enum EnTy<#[ty_enum] J> { A(J), B }
-   |             ^^^^^^^
+LL | fn f_ty<#[ty_fn] O>(_: O) { }
+   |           ^^^^^
 
-error: cannot find attribute `lt_enum` in this scope
-  --> $DIR/feature-gate-custom_attribute2.rs:9:13
+error: cannot find attribute `lt_meth` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:44:15
    |
-LL | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B }
-   |             ^^^^^^^
+LL |     fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
+   |               ^^^^^^^
 
-error: cannot find attribute `ty_struct` in this scope
-  --> $DIR/feature-gate-custom_attribute2.rs:6:15
+error: cannot find attribute `ty_meth` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:46:15
    |
-LL | struct StTy<#[ty_struct] I>(I);
-   |               ^^^^^^^^^
+LL |     fn m_ty<#[ty_meth] P>(_: P) { }
+   |               ^^^^^^^
 
-error: cannot find attribute `lt_struct` in this scope
-  --> $DIR/feature-gate-custom_attribute2.rs:4:15
+error: cannot find attribute `lt_hof` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:51:21
    |
-LL | struct StLt<#[lt_struct] 'a>(&'a u32);
-   |               ^^^^^^^^^
+LL |     where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
+   |                     ^^^^^^
 
 error: aborting due to 17 previous errors
 
diff --git a/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.rs b/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.rs
deleted file mode 100644 (file)
index 35c05b7..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// Test that default and negative trait implementations are gated by
-// `optin_builtin_traits` feature gate
-
-struct DummyStruct;
-
-auto trait AutoDummyTrait {}
-//~^ ERROR auto traits are experimental and possibly buggy
-
-impl !AutoDummyTrait for DummyStruct {}
-//~^ ERROR negative trait bounds are not yet fully implemented; use marker types for now
-
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr b/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr
deleted file mode 100644 (file)
index 1553d05..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0658]: auto traits are experimental and possibly buggy
-  --> $DIR/feature-gate-optin-builtin-traits.rs:6:1
-   |
-LL | auto trait AutoDummyTrait {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #13231 <https://github.com/rust-lang/rust/issues/13231> for more information
-   = help: add `#![feature(optin_builtin_traits)]` to the crate attributes to enable
-
-error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now
-  --> $DIR/feature-gate-optin-builtin-traits.rs:9:6
-   |
-LL | impl !AutoDummyTrait for DummyStruct {}
-   |      ^^^^^^^^^^^^^^^
-   |
-   = note: see issue #68318 <https://github.com/rust-lang/rust/issues/68318> for more information
-   = help: add `#![feature(negative_impls)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
index 1208552d256376b26926cc98dc462502dd81619e..d42fbf22938c0503f3dd859f84d10cbb41dca0f7 100644 (file)
@@ -1,14 +1,19 @@
-#![feature(exclusive_range_pattern)]
-
-use std::usize::MAX;
+use std::{isize, usize};
 
 fn main() {
-    match 0usize { //~ERROR non-exhaustive patterns: `_` not covered
-        0..=MAX => {}
+    match 0usize {
+        //~^ ERROR non-exhaustive patterns: `_` not covered
+        //~| NOTE pattern `_` not covered
+        //~| NOTE the matched value is of type `usize`
+        //~| NOTE `usize` does not have a fixed maximum value
+        0..=usize::MAX => {}
     }
 
-    match 0isize { //~ERROR non-exhaustive patterns: `_` not covered
-        1..=20 => {}
-        -5..3 => {}
+    match 0isize {
+        //~^ ERROR non-exhaustive patterns: `_` not covered
+        //~| NOTE pattern `_` not covered
+        //~| NOTE the matched value is of type `isize`
+        //~| NOTE `isize` does not have a fixed maximum value
+        isize::MIN..=isize::MAX => {}
     }
 }
index c7a63e5d50252cc02765ee334de9ee95e727c203..da308c292dfab954c0cd045885a5128a64f67eb0 100644 (file)
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/feature-gate-precise_pointer_size_matching.rs:6:11
+  --> $DIR/feature-gate-precise_pointer_size_matching.rs:4:11
    |
 LL |     match 0usize {
    |           ^^^^^^ pattern `_` not covered
@@ -10,7 +10,7 @@ LL |     match 0usize {
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/feature-gate-precise_pointer_size_matching.rs:10:11
+  --> $DIR/feature-gate-precise_pointer_size_matching.rs:12:11
    |
 LL |     match 0isize {
    |           ^^^^^^ pattern `_` not covered
index 9348bb46dfe34e6ffd3b229232f24bea461337c6..4e3fa9a3c589ae9f2c053f1cc460ddc4af99dde7 100644 (file)
@@ -31,6 +31,7 @@ fn panic_with_single_argument_does_not_get_formatted() {
     // RFC #2795 suggests that this may need to change so that captured arguments are formatted.
     // For stability reasons this will need to part of an edition change.
 
+    #[allow(panic_fmt)]
     let msg = std::panic::catch_unwind(|| {
         panic!("{foo}");
     }).unwrap_err();
index 1e77d8058a72b6ec9576871e8eaa1700ed4f0796..8f1e4f1b66f48cc56bdc7a5cb61302cb4bb9b0a2 100644 (file)
@@ -1,5 +1,5 @@
 #![feature(generators)]
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 #![feature(negative_impls)]
 
 auto trait Foo {}
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-expected-token.rs b/src/test/ui/generic-associated-types/parse/trait-path-expected-token.rs
new file mode 100644 (file)
index 0000000..b10bfea
--- /dev/null
@@ -0,0 +1,11 @@
+#![feature(generic_associated_types)]
+//~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait X {
+    type Y<'a>;
+}
+
+fn f1<'a>(arg : Box<dyn X<Y = B = &'a ()>>) {}
+    //~^ ERROR: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=`
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-expected-token.stderr b/src/test/ui/generic-associated-types/parse/trait-path-expected-token.stderr
new file mode 100644 (file)
index 0000000..051253c
--- /dev/null
@@ -0,0 +1,17 @@
+error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=`
+  --> $DIR/trait-path-expected-token.rs:8:33
+   |
+LL | fn f1<'a>(arg : Box<dyn X<Y = B = &'a ()>>) {}
+   |                                 ^ expected one of 7 possible tokens
+
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/trait-path-expected-token.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-expressions.rs b/src/test/ui/generic-associated-types/parse/trait-path-expressions.rs
new file mode 100644 (file)
index 0000000..de61cfa
--- /dev/null
@@ -0,0 +1,23 @@
+#![feature(generic_associated_types)]
+//~^ WARNING: the feature `generic_associated_types` is incomplete
+
+mod error1 {
+  trait X {
+      type Y<'a>;
+  }
+
+  fn f1<'a>(arg : Box<dyn X< 1 = 32 >>) {}
+      //~^ ERROR: expected expression, found `)`
+}
+
+mod error2 {
+
+  trait X {
+      type Y<'a>;
+  }
+
+  fn f2<'a>(arg : Box<dyn X< { 1 } = 32 >>) {}
+    //~^ ERROR: only types can be used in associated type constraints
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr b/src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr
new file mode 100644 (file)
index 0000000..a9ba8ad
--- /dev/null
@@ -0,0 +1,25 @@
+error: expected expression, found `)`
+  --> $DIR/trait-path-expressions.rs:9:39
+   |
+LL |   fn f1<'a>(arg : Box<dyn X< 1 = 32 >>) {}
+   |                              -        ^ expected expression
+   |                              |
+   |                              while parsing a const generic argument starting here
+
+error: only types can be used in associated type constraints
+  --> $DIR/trait-path-expressions.rs:19:30
+   |
+LL |   fn f2<'a>(arg : Box<dyn X< { 1 } = 32 >>) {}
+   |                              ^^^^^
+
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/trait-path-expressions.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs b/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs
new file mode 100644 (file)
index 0000000..dad8c2a
--- /dev/null
@@ -0,0 +1,21 @@
+#![feature(generic_associated_types)]
+//~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait X {
+    type Y<'a>;
+}
+
+const _: () = {
+  fn f1<'a>(arg : Box<dyn X< : 32 >>) {}
+      //~^ ERROR: expected one of `>`, const, lifetime, or type, found `:`
+      //~| ERROR: expected parameter name, found `>`
+      //~| ERROR: expected one of `!`, `)`, `+`, `,`, or `::`, found `>`
+      //~| ERROR: constant provided when a type was expected
+};
+
+const _: () = {
+  fn f1<'a>(arg : Box<dyn X< = 32 >>) {}
+      //~^ ERROR: expected one of `>`, const, lifetime, or type, found `=`
+};
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr b/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr
new file mode 100644 (file)
index 0000000..583697f
--- /dev/null
@@ -0,0 +1,50 @@
+error: expected one of `>`, const, lifetime, or type, found `:`
+  --> $DIR/trait-path-missing-gen_arg.rs:9:30
+   |
+LL |   fn f1<'a>(arg : Box<dyn X< : 32 >>) {}
+   |                              ^ expected one of `>`, const, lifetime, or type
+   |
+help: expressions must be enclosed in braces to be used as const generic arguments
+   |
+LL |   fn f1<'a>(arg : Box<{ dyn X< : 32 } >>) {}
+   |                       ^             ^
+
+error: expected parameter name, found `>`
+  --> $DIR/trait-path-missing-gen_arg.rs:9:36
+   |
+LL |   fn f1<'a>(arg : Box<dyn X< : 32 >>) {}
+   |                                    ^ expected parameter name
+
+error: expected one of `!`, `)`, `+`, `,`, or `::`, found `>`
+  --> $DIR/trait-path-missing-gen_arg.rs:9:36
+   |
+LL |   fn f1<'a>(arg : Box<dyn X< : 32 >>) {}
+   |                                    ^
+   |                                    |
+   |                                    expected one of `!`, `)`, `+`, `,`, or `::`
+   |                                    help: missing `,`
+
+error: expected one of `>`, const, lifetime, or type, found `=`
+  --> $DIR/trait-path-missing-gen_arg.rs:17:30
+   |
+LL |   fn f1<'a>(arg : Box<dyn X< = 32 >>) {}
+   |                              ^ expected one of `>`, const, lifetime, or type
+
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/trait-path-missing-gen_arg.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0747]: constant provided when a type was expected
+  --> $DIR/trait-path-missing-gen_arg.rs:9:23
+   |
+LL |   fn f1<'a>(arg : Box<dyn X< : 32 >>) {}
+   |                       ^^^^^^^^^^^
+
+error: aborting due to 5 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0747`.
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-segments.rs b/src/test/ui/generic-associated-types/parse/trait-path-segments.rs
new file mode 100644 (file)
index 0000000..0bf48b1
--- /dev/null
@@ -0,0 +1,35 @@
+#![feature(generic_associated_types)]
+//~^ WARNING: the feature `generic_associated_types` is incomplete
+
+const _: () = {
+    trait X {
+        type Y<'a>;
+    }
+
+    fn f1<'a>(arg : Box<dyn X<X::Y = u32>>) {}
+        //~^ ERROR: paths with multiple segments cannot be used in associated type constraints
+  };
+
+const _: () = {
+    trait X {
+        type Y<'a>;
+    }
+
+    trait Z {}
+
+    impl<T : X<<Self as X>::Y<'a> = &'a u32>> Z for T {}
+        //~^ ERROR: qualified paths cannot be used in associated type constraints
+};
+
+const _: () = {
+    trait X {
+      type Y<'a>;
+    }
+
+    trait Z {}
+
+    impl<T : X<X::Y<'a> = &'a u32>> Z for T {}
+        //~^ ERROR: paths with multiple segments cannot be used in associated type constraints
+};
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-segments.stderr b/src/test/ui/generic-associated-types/parse/trait-path-segments.stderr
new file mode 100644 (file)
index 0000000..4e2b84d
--- /dev/null
@@ -0,0 +1,31 @@
+error: paths with multiple segments cannot be used in associated type constraints
+  --> $DIR/trait-path-segments.rs:9:31
+   |
+LL |     fn f1<'a>(arg : Box<dyn X<X::Y = u32>>) {}
+   |                               ^^^^
+
+error: qualified paths cannot be used in associated type constraints
+  --> $DIR/trait-path-segments.rs:20:16
+   |
+LL |     impl<T : X<<Self as X>::Y<'a> = &'a u32>> Z for T {}
+   |                ^^^^^^^^^-^^^^^^^^
+   |                         |
+   |                         not allowed in associated type constraints
+
+error: paths with multiple segments cannot be used in associated type constraints
+  --> $DIR/trait-path-segments.rs:31:16
+   |
+LL |     impl<T : X<X::Y<'a> = &'a u32>> Z for T {}
+   |                ^^^^^^^^
+
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/trait-path-segments.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error: aborting due to 3 previous errors; 1 warning emitted
+
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs
new file mode 100644 (file)
index 0000000..e203a5e
--- /dev/null
@@ -0,0 +1,10 @@
+#![feature(generic_associated_types)]
+
+trait X {
+    type Y<'a>;
+}
+
+const _: () = {
+  fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {}
+      //~^  ERROR: generic associated types in trait paths are currently not implemented
+};
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr
new file mode 100644 (file)
index 0000000..e59a72a
--- /dev/null
@@ -0,0 +1,8 @@
+error: generic associated types in trait paths are currently not implemented
+  --> $DIR/trait-path-type-error-once-implemented.rs:8:30
+   |
+LL |   fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {}
+   |                              ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-types.rs b/src/test/ui/generic-associated-types/parse/trait-path-types.rs
new file mode 100644 (file)
index 0000000..6cdb501
--- /dev/null
@@ -0,0 +1,23 @@
+#![feature(generic_associated_types)]
+//~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait X {
+    type Y<'a>;
+}
+
+const _: () = {
+  fn f<'a>(arg : Box<dyn X< [u8; 1] = u32>>) {}
+      //~^ ERROR: only path types can be used in associated type constraints
+};
+
+const _: () = {
+  fn f1<'a>(arg : Box<dyn X<(Y<'a>) = &'a ()>>) {}
+      //~^ ERROR: only path types can be used in associated type constraints
+};
+
+const _: () = {
+  fn f1<'a>(arg : Box<dyn X< 'a = u32 >>) {}
+      //~^ ERROR: only types can be used in associated type constraints
+};
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-types.stderr b/src/test/ui/generic-associated-types/parse/trait-path-types.stderr
new file mode 100644 (file)
index 0000000..f5be084
--- /dev/null
@@ -0,0 +1,29 @@
+error: only path types can be used in associated type constraints
+  --> $DIR/trait-path-types.rs:9:29
+   |
+LL |   fn f<'a>(arg : Box<dyn X< [u8; 1] = u32>>) {}
+   |                             ^^^^^^^
+
+error: only path types can be used in associated type constraints
+  --> $DIR/trait-path-types.rs:14:29
+   |
+LL |   fn f1<'a>(arg : Box<dyn X<(Y<'a>) = &'a ()>>) {}
+   |                             ^^^^^^^
+
+error: only types can be used in associated type constraints
+  --> $DIR/trait-path-types.rs:19:30
+   |
+LL |   fn f1<'a>(arg : Box<dyn X< 'a = u32 >>) {}
+   |                              ^^
+
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/trait-path-types.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error: aborting due to 3 previous errors; 1 warning emitted
+
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.rs b/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.rs
new file mode 100644 (file)
index 0000000..02d53d5
--- /dev/null
@@ -0,0 +1,17 @@
+#![feature(generic_associated_types)]
+
+trait X {
+    type Y<'a>;
+}
+
+const _: () = {
+  fn f1<'a>(arg : Box<dyn X<Y<'a> = &'a ()>>) {}
+      //~^  ERROR: generic associated types in trait paths are currently not implemented
+};
+
+const _: () = {
+  fn f1<'a>(arg : Box<dyn X<Y('a) = &'a ()>>) {}
+      //~^  ERROR: lifetime in trait object type must be followed by `+`
+};
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.stderr b/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.stderr
new file mode 100644 (file)
index 0000000..1fba9ce
--- /dev/null
@@ -0,0 +1,14 @@
+error: lifetime in trait object type must be followed by `+`
+  --> $DIR/trait-path-unimplemented.rs:13:31
+   |
+LL |   fn f1<'a>(arg : Box<dyn X<Y('a) = &'a ()>>) {}
+   |                               ^^
+
+error: generic associated types in trait paths are currently not implemented
+  --> $DIR/trait-path-unimplemented.rs:8:30
+   |
+LL |   fn f1<'a>(arg : Box<dyn X<Y<'a> = &'a ()>>) {}
+   |                              ^^^^
+
+error: aborting due to 2 previous errors
+
index 204e7b248797afcb6b3725874a1d5574e3abf2f4..e23826e9d4ef604f62f919920528eefda374bdd8 100644 (file)
@@ -1,7 +1,7 @@
 #![feature(decl_macro)]
 
 mod foo {
-    pub macro m() { Vec::new(); ().clone() }
+    pub macro m() { Vec::<i32>::new(); ().clone() }
     fn f() { ::bar::m!(); }
 }
 
@@ -13,7 +13,7 @@ mod bar {
     }
     fn f() {
         ::foo::m!();
-        assert_eq!(0, 0); //~ ERROR cannot find macro `panic` in this scope
+        assert!(true);
     }
 }
 
index 843dee2478b3ff8b983a17714dfb908aa53989a6..835ecce94b97a759346f0855eafc2a628a6b2cdf 100644 (file)
@@ -1,14 +1,3 @@
-error: cannot find macro `panic` in this scope
-  --> $DIR/no_implicit_prelude.rs:16:9
-   |
-LL |         assert_eq!(0, 0);
-   |         ^^^^^^^^^^^^^^^^^
-   |
-   = note: consider importing one of these items:
-           core::panic
-           std::panic
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
 error[E0433]: failed to resolve: use of undeclared type `Vec`
   --> $DIR/no_implicit_prelude.rs:11:9
    |
@@ -38,7 +27,7 @@ LL |         ().clone()
            `use std::clone::Clone;`
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0433, E0599.
 For more information about an error, try `rustc --explain E0433`.
diff --git a/src/test/ui/impl-trait/issues/issue-78721.rs b/src/test/ui/impl-trait/issues/issue-78721.rs
new file mode 100644 (file)
index 0000000..f7dbef9
--- /dev/null
@@ -0,0 +1,15 @@
+// edition:2018
+
+#![feature(impl_trait_in_bindings)]
+//~^ WARN the feature `impl_trait_in_bindings` is incomplete
+
+struct Bug {
+    V1: [(); {
+        let f: impl core::future::Future<Output = u8> = async { 1 };
+        //~^ ERROR `async` blocks are not allowed in constants
+        //~| ERROR destructors cannot be evaluated at compile-time
+        1
+    }],
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-78721.stderr b/src/test/ui/impl-trait/issues/issue-78721.stderr
new file mode 100644 (file)
index 0000000..353e882
--- /dev/null
@@ -0,0 +1,27 @@
+warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-78721.rs:3:12
+   |
+LL | #![feature(impl_trait_in_bindings)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
+
+error: `async` blocks are not allowed in constants
+  --> $DIR/issue-78721.rs:8:57
+   |
+LL |         let f: impl core::future::Future<Output = u8> = async { 1 };
+   |                                                         ^^^^^^^^^^^
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/issue-78721.rs:8:13
+   |
+LL |         let f: impl core::future::Future<Output = u8> = async { 1 };
+   |             ^ constants cannot evaluate destructors
+...
+LL |     }],
+   |     - value is dropped here
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0493`.
diff --git a/src/test/ui/impl-trait/issues/issue-78722.rs b/src/test/ui/impl-trait/issues/issue-78722.rs
new file mode 100644 (file)
index 0000000..58734d3
--- /dev/null
@@ -0,0 +1,21 @@
+// edition:2018
+
+#![feature(type_alias_impl_trait)]
+#![feature(impl_trait_in_bindings)]
+//~^ WARN the feature `impl_trait_in_bindings` is incomplete
+
+type F = impl core::future::Future<Output = u8>;
+
+struct Bug {
+    V1: [(); {
+        fn concrete_use() -> F {
+            async {}
+        }
+        let f: F = async { 1 };
+        //~^ ERROR `async` blocks are not allowed in constants
+        //~| ERROR destructors cannot be evaluated at compile-time
+        1
+    }],
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-78722.stderr b/src/test/ui/impl-trait/issues/issue-78722.stderr
new file mode 100644 (file)
index 0000000..0e1e92b
--- /dev/null
@@ -0,0 +1,27 @@
+warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-78722.rs:4:12
+   |
+LL | #![feature(impl_trait_in_bindings)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
+
+error: `async` blocks are not allowed in constants
+  --> $DIR/issue-78722.rs:14:20
+   |
+LL |         let f: F = async { 1 };
+   |                    ^^^^^^^^^^^
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/issue-78722.rs:14:13
+   |
+LL |         let f: F = async { 1 };
+   |             ^ constants cannot evaluate destructors
+...
+LL |     }],
+   |     - value is dropped here
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0493`.
index 896651361be2ae3533c607694a4ba240fe1087fa..2bf40db5ad290056272a6b50018d40dc02c8c3f0 100644 (file)
@@ -11,7 +11,6 @@ mod rusti {
 }
 
 #[cfg(any(target_os = "android",
-          target_os = "cloudabi",
           target_os = "dragonfly",
           target_os = "emscripten",
           target_os = "freebsd",
index 78fa8b7c6fb0722e18b895fbc7b606e53cc70d95..696a2dd1657657114edbe68f3e9b0217692bfca7 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
index fa10f073b4576dbf33c121b4179119b6ffa0944b..f40815fdbdbc5626ad3ccb166cf28d2c867523eb 100644 (file)
@@ -5,6 +5,6 @@
 
 pub fn main() {
     fn f() {
-    };
+    }
     let _: Box<fn()> = box (f as fn());
 }
diff --git a/src/test/ui/issues/issue-12116.rs b/src/test/ui/issues/issue-12116.rs
deleted file mode 100644 (file)
index 8b391cd..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#![feature(box_patterns)]
-#![feature(box_syntax)]
-#![allow(dead_code)]
-#![allow(unused_variables)]
-#![deny(unreachable_patterns)]
-
-enum IntList {
-    Cons(isize, Box<IntList>),
-    Nil
-}
-
-fn tail(source_list: &IntList) -> IntList {
-    match source_list {
-        &IntList::Cons(val, box ref next_list) => tail(next_list),
-        &IntList::Cons(val, box IntList::Nil)  => IntList::Cons(val, box IntList::Nil),
-//~^ ERROR unreachable pattern
-        _                          => panic!()
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-12116.stderr b/src/test/ui/issues/issue-12116.stderr
deleted file mode 100644 (file)
index 4d162eb..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: unreachable pattern
-  --> $DIR/issue-12116.rs:15:9
-   |
-LL |         &IntList::Cons(val, box IntList::Nil)  => IntList::Cons(val, box IntList::Nil),
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/issue-12116.rs:5:9
-   |
-LL | #![deny(unreachable_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
index c8aa9bf46491faedd1c221f33124f7dae2e43182..e6b16e2da1dca51cf4b40cd8a4195ab5b7ed3a13 100644 (file)
@@ -2,7 +2,6 @@
 // aux-build:issue-12133-rlib.rs
 // aux-build:issue-12133-dylib.rs
 // aux-build:issue-12133-dylib2.rs
-// ignore-cloudabi no dylib support
 // ignore-emscripten no dylib support
 // ignore-musl
 // ignore-sgx no dylib support
diff --git a/src/test/ui/issues/issue-12369.rs b/src/test/ui/issues/issue-12369.rs
deleted file mode 100644 (file)
index 0481c1f..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#![deny(unreachable_patterns)]
-
-fn main() {
-    let sl = vec![1,2,3];
-    let v: isize = match &*sl {
-        &[] => 0,
-        &[a,b,c] => 3,
-        &[a, ref rest @ ..] => a,
-        &[10,a, ref rest @ ..] => 10 //~ ERROR: unreachable pattern
-    };
-}
diff --git a/src/test/ui/issues/issue-12369.stderr b/src/test/ui/issues/issue-12369.stderr
deleted file mode 100644 (file)
index aab2be7..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: unreachable pattern
-  --> $DIR/issue-12369.rs:9:9
-   |
-LL |         &[10,a, ref rest @ ..] => 10
-   |         ^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/issue-12369.rs:1:9
-   |
-LL | #![deny(unreachable_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
index 5698536ab5d050496835772c4cc93bd6ca33fad3..b10f6d57255de148a594170c19e6c8caeaab57ce 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 #![allow(unused_mut)]
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
diff --git a/src/test/ui/issues/issue-13727.rs b/src/test/ui/issues/issue-13727.rs
deleted file mode 100644 (file)
index 7fb565e..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#![allow(overflowing_literals)]
-#![deny(unreachable_patterns)]
-
-fn test(val: u8) {
-  match val {
-    256 => print!("0b1110\n"),
-    512 => print!("0b1111\n"),
-    //~^ ERROR: unreachable pattern
-    _   => print!("fail\n"),
-  }
-}
-
-fn main() {
-  test(1);
-}
diff --git a/src/test/ui/issues/issue-13727.stderr b/src/test/ui/issues/issue-13727.stderr
deleted file mode 100644 (file)
index 07ca56a..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: unreachable pattern
-  --> $DIR/issue-13727.rs:7:5
-   |
-LL |     512 => print!("0b1111\n"),
-   |     ^^^
-   |
-note: the lint level is defined here
-  --> $DIR/issue-13727.rs:2:9
-   |
-LL | #![deny(unreachable_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
index 164d7ef8af27d5bdb1f1aaac6ce33ce1252a107d..52a56eb77f78e613224b2d9bf0df6c4e95da276e 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 #![allow(unused_mut)]
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
index 785ad6a2c49dae59818c0428150a947bdb295d5d..98a4af0c467a33acf42b804238fe8e4f9507c95c 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
diff --git a/src/test/ui/issues/issue-15129.rs b/src/test/ui/issues/issue-15129.rs
deleted file mode 100644 (file)
index ed134c1..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-pub enum T {
-    T1(()),
-    T2(())
-}
-
-pub enum V {
-    V1(isize),
-    V2(bool)
-}
-
-fn main() {
-    match (T::T1(()), V::V2(true)) {
-    //~^ ERROR non-exhaustive patterns: `(T1(()), V2(_))` not covered
-        (T::T1(()), V::V1(i)) => (),
-        (T::T2(()), V::V2(b)) => ()
-    }
-}
diff --git a/src/test/ui/issues/issue-15129.stderr b/src/test/ui/issues/issue-15129.stderr
deleted file mode 100644 (file)
index aa4434e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0004]: non-exhaustive patterns: `(T1(()), V2(_))` not covered
-  --> $DIR/issue-15129.rs:12:11
-   |
-LL |     match (T::T1(()), V::V2(true)) {
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `(T1(()), V2(_))` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `(T, V)`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0004`.
index 3ba2483f4306d7d146dc8ebbbd369f854afec9de..5cf3fd949282635bb3d277561752188238f5ca56 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
index 34b1e2099be3f6d9c786c9773ca9b2a364f4650f..1e7b9f015b96940c6cc4b9895b55a402a0016d67 100644 (file)
@@ -1,7 +1,6 @@
 // check-pass
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
-// ignore-cloudabi no std::fs
 
 use std::fs::File;
 use std::io::{self, BufReader, Read};
index 35fa5fde0ad6fa3571855b6965ba3cd50c9671a3..3bd9c656e8bd55d1d281006390f25141dbc70c66 100644 (file)
@@ -6,133 +6,7 @@ LL |     0.contains(bits);
    |
    = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_18400`)
    = note: required because of the requirements on the impl of `Set<&[_]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[_]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[_]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[_]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[_]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[_]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[_]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[_]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[_]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: 128 redundant requirements hidden
    = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
 
 error: aborting due to previous error
index 90db44fa02d42c4f3e1967623381fabf7ac7fdce..86cc79d6b4244f1d0fa8082229d756c1374c7656 100644 (file)
@@ -1,7 +1,6 @@
 // run-pass
 #![allow(stable_features)]
 
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
index 19ef52af65736369a6e38b0be7d1e03d8315a29e..a4345ccdfbe81b6afdf6394f7731ae7f84264292 100644 (file)
@@ -13,4 +13,32 @@ fn answer(self) {
   }
 }
 
+trait Bar {
+  fn answer(self);
+}
+
+trait Baz {
+  fn answer(self);
+}
+
+struct AlmostNoData<T>(Option<T>);
+
+struct EvenLessData<T>(Option<T>);
+
+impl<T> Bar for T where EvenLessData<T>: Baz {
+//~^ ERROR: overflow evaluating the requirement
+//~| ERROR: overflow evaluating the requirement
+  fn answer(self) {
+    let val: EvenLessData<T> = EvenLessData(None);
+  }
+}
+
+impl<T> Baz for T where AlmostNoData<T>: Bar {
+//~^ ERROR: overflow evaluating the requirement
+//~| ERROR: overflow evaluating the requirement
+  fn answer(self) {
+    let val: NoData<T> = AlmostNoData(None);
+  }
+}
+
 fn main() {}
index 3f96f0bfcd3a87b622d4202354adfbfe75c2f677..b167bb77b510108a30ce30358aa19553f69601f5 100644 (file)
@@ -17,134 +17,39 @@ LL | impl<T> Foo for T where NoData<T>: Foo {
    |
    = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`)
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<T>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<T>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<T>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<T>>`
+   = note: 127 redundant requirements hidden
    = note: required because of the requirements on the impl of `Foo` for `NoData<T>`
 
+error[E0275]: overflow evaluating the requirement `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Baz`
+  --> $DIR/issue-20413.rs:28:42
+   |
+LL | trait Baz {
+   | --------- required by this bound in `Baz`
+...
+LL | impl<T> Bar for T where EvenLessData<T>: Baz {
+   |                                          ^^^
+   |
+   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`)
+   = note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: 126 redundant requirements hidden
+   = note: required because of the requirements on the impl of `Baz` for `EvenLessData<T>`
+
+error[E0275]: overflow evaluating the requirement `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Bar`
+  --> $DIR/issue-20413.rs:36:42
+   |
+LL | trait Bar {
+   | --------- required by this bound in `Bar`
+...
+LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
+   |                                          ^^^
+   |
+   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`)
+   = note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: 126 redundant requirements hidden
+   = note: required because of the requirements on the impl of `Bar` for `AlmostNoData<T>`
+
 error[E0275]: overflow evaluating the requirement `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
   --> $DIR/issue-20413.rs:8:36
    |
@@ -156,135 +61,40 @@ LL | impl<T> Foo for T where NoData<T>: Foo {
    |
    = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`)
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<T>>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<T>>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<T>>>`
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<T>>`
+   = note: 127 redundant requirements hidden
    = note: required because of the requirements on the impl of `Foo` for `NoData<T>`
 
-error: aborting due to 3 previous errors
+error[E0275]: overflow evaluating the requirement `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Baz`
+  --> $DIR/issue-20413.rs:28:42
+   |
+LL | trait Baz {
+   | --------- required by this bound in `Baz`
+...
+LL | impl<T> Bar for T where EvenLessData<T>: Baz {
+   |                                          ^^^
+   |
+   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`)
+   = note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: 126 redundant requirements hidden
+   = note: required because of the requirements on the impl of `Baz` for `EvenLessData<T>`
+
+error[E0275]: overflow evaluating the requirement `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Bar`
+  --> $DIR/issue-20413.rs:36:42
+   |
+LL | trait Bar {
+   | --------- required by this bound in `Bar`
+...
+LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
+   |                                          ^^^
+   |
+   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`)
+   = note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: 126 redundant requirements hidden
+   = note: required because of the requirements on the impl of `Bar` for `AlmostNoData<T>`
+
+error: aborting due to 7 previous errors
 
 Some errors have detailed explanations: E0275, E0392.
 For more information about an error, try `rustc --explain E0275`.
index 3c14226b7347220b1a210a3b743056e5d078d7ce..d40946ae03f50f42947ad7412036f4a185df0462 100644 (file)
@@ -6,7 +6,7 @@ LL |     fn iceman(c: Vec<[i32]>) {}
    | 
   ::: $SRC_DIR/alloc/src/vec.rs:LL:COL
    |
-LL | pub struct Vec<T> {
+LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: AllocRef = Global> {
    |                - required by this bound in `Vec`
    |
    = help: the trait `Sized` is not implemented for `[i32]`
index 2f2c6903a9f4c515acf71cf45a2375a90fc67aba..f108ae5de1483cf219ebe129b9f8a58472dce51c 100644 (file)
@@ -9,7 +9,7 @@
 //type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
 
 
-type Type_2 = Type_1_<'static ()>; //~ error: expected one of `,` or `>`, found `(`
+type Type_2 = Type_1_<'static ()>; //~ error: expected one of `,`, `:`, `=`, or `>`, found `(`
 
 
 //type Type_3<T> = Box<T,,>; // error: expected type, found `,`
index 50ec7a304c5c161811b48b178ff0bda05ab23aeb..01e3d3dd7ccf03f0600c15e5239595c97827befd 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `,` or `>`, found `(`
+error: expected one of `,`, `:`, `=`, or `>`, found `(`
   --> $DIR/issue-20616-2.rs:12:31
    |
 LL | type Type_2 = Type_1_<'static ()>;
-   |                               ^ expected one of `,` or `>`
+   |                               ^ expected one of `,`, `:`, `=`, or `>`
 
 error: aborting due to previous error
 
index 9bfd5bf23130210476c6e46ba4a9f0bdfba67a28..780038c11b8089aa2d9ad95e3b66ad5290bd8eea 100644 (file)
@@ -11,7 +11,7 @@
 
 
 type Type_3<T> = Box<T,,>;
-//~^ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+//~^ error: expected one of `>`, const, lifetime, or type, found `,`
 
 
 //type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
index cc4d79484e7a4538578516a9ded668e5d370e494..2f8cf8a79ed9439544dcdf9ac33092d6ffc311d1 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+error: expected one of `>`, const, lifetime, or type, found `,`
   --> $DIR/issue-20616-3.rs:13:24
    |
 LL | type Type_3<T> = Box<T,,>;
-   |                        ^ expected one of `>`, const, identifier, lifetime, or type
+   |                        ^ expected one of `>`, const, lifetime, or type
 
 error: aborting due to previous error
 
index e9a34a04667b0937a950fba0e37bfbadeb17373b..85aa9c1146d67982dbd11011eb3855493f494970 100644 (file)
@@ -14,7 +14,7 @@
 
 
 type Type_4<T> = Type_1_<'static,, T>;
-//~^ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+//~^ error: expected one of `>`, const, lifetime, or type, found `,`
 
 
 type Type_5_<'a> = Type_1_<'a, ()>;
index 254e4d6a34dc5e1b96df1bdd59581afd4971382e..3be6c2e78ced00995ffe0688224ea46312811da2 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+error: expected one of `>`, const, lifetime, or type, found `,`
   --> $DIR/issue-20616-4.rs:16:34
    |
 LL | type Type_4<T> = Type_1_<'static,, T>;
-   |                                  ^ expected one of `>`, const, identifier, lifetime, or type
+   |                                  ^ expected one of `>`, const, lifetime, or type
 
 error: aborting due to previous error
 
index 23862516d2cbfb35d97edbbc8bb0c7c14cc13124..c0c6bc6dd97fee24d90de55e7fb7cf1970628653 100644 (file)
@@ -20,7 +20,7 @@
 
 
 type Type_5<'a> = Type_1_<'a, (),,>;
-//~^ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+//~^ error: expected one of `>`, const, lifetime, or type, found `,`
 
 
 //type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
index aee8bf01a4321fde707ceb93bd806ee030c099a8..b90fbf60051476412dc84c36e55655a8e9ab7066 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+error: expected one of `>`, const, lifetime, or type, found `,`
   --> $DIR/issue-20616-5.rs:22:34
    |
 LL | type Type_5<'a> = Type_1_<'a, (),,>;
-   |                                  ^ expected one of `>`, const, identifier, lifetime, or type
+   |                                  ^ expected one of `>`, const, lifetime, or type
 
 error: aborting due to previous error
 
index dc327f3f788247631e872e62916b7b4adf79384c..73c75bdc45fb1dc72f59e2e89acab98345b4a8a6 100644 (file)
@@ -23,7 +23,7 @@
 
 
 type Type_6 = Type_5_<'a,,>;
-//~^ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+//~^ error: expected one of `>`, const, lifetime, or type, found `,`
 
 
 //type Type_7 = Box<(),,>; // error: expected type, found `,`
index 7192a87bc18f5636b6d329456a39a2d07a1f70aa..ea1c15ba4233773e7216ecc02fee562f7162ebff 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+error: expected one of `>`, const, lifetime, or type, found `,`
   --> $DIR/issue-20616-6.rs:25:26
    |
 LL | type Type_6 = Type_5_<'a,,>;
-   |                          ^ expected one of `>`, const, identifier, lifetime, or type
+   |                          ^ expected one of `>`, const, lifetime, or type
 
 error: aborting due to previous error
 
index ffd1620c1d306fca9e86aeeb44f002341ec9555e..8beeebd7a9550f63341b519b78106a479066c9a4 100644 (file)
@@ -26,7 +26,7 @@
 
 
 type Type_7 = Box<(),,>;
-//~^ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+//~^ error: expected one of `>`, const, lifetime, or type, found `,`
 
 
 //type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
index 123dc1e2b7d9c996bb0fe88840472b2b80ca46ca..dcd199902fc0b5643710ad34e0a745c849298170 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+error: expected one of `>`, const, lifetime, or type, found `,`
   --> $DIR/issue-20616-7.rs:28:22
    |
 LL | type Type_7 = Box<(),,>;
-   |                      ^ expected one of `>`, const, identifier, lifetime, or type
+   |                      ^ expected one of `>`, const, lifetime, or type
 
 error: aborting due to previous error
 
index 36eac3824966462381ba23e6029c901c9bdd49f2..71c6746e0e04059f761981cad47234156eae2988 100644 (file)
@@ -7,7 +7,6 @@
 // had to do with codegen ignoring binders.
 
 // pretty-expanded FIXME #23616
-// ignore-cloudabi no std::fs
 
 #![feature(os)]
 
index bd5f015cca0dc55e190361ee878007b0e0447499..a6bea38580477303c0cd61d328232d10d76fd505 100644 (file)
@@ -5,11 +5,11 @@
 
 pub fn main() {
     let one = || {
-        enum r { a };
+        enum r { a }
         r::a as usize
     };
     let two = || {
-        enum r { a };
+        enum r { a }
         r::a as usize
     };
     one(); two();
index 5d82592e5ea57569be23da47b402e48fc29bfec9..ef0e72571efb2e683cde5d67727a1d476c7f8289 100644 (file)
@@ -1,5 +1,4 @@
 // build-pass
-// ignore-cloudabi no std::fs
 
 // Regression test for #20797.
 
diff --git a/src/test/ui/issues/issue-2111.rs b/src/test/ui/issues/issue-2111.rs
deleted file mode 100644 (file)
index 7e5835e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-fn foo(a: Option<usize>, b: Option<usize>) {
-  match (a,b) {
-  //~^ ERROR: non-exhaustive patterns: `(None, None)` not covered
-    (Some(a), Some(b)) if a == b => { }
-    (Some(_), None) |
-    (None, Some(_)) => { }
-  }
-}
-
-fn main() {
-  foo(None, None);
-}
diff --git a/src/test/ui/issues/issue-2111.stderr b/src/test/ui/issues/issue-2111.stderr
deleted file mode 100644 (file)
index a39a479..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0004]: non-exhaustive patterns: `(None, None)` not covered
-  --> $DIR/issue-2111.rs:2:9
-   |
-LL |   match (a,b) {
-   |         ^^^^^ pattern `(None, None)` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `(Option<usize>, Option<usize>)`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0004`.
index 9b7c4485418537d5b3492d53975838d8da3bbfab..52ab29f423533987e3da23cc67ed8ca97e3713ef 100644 (file)
@@ -24,7 +24,7 @@ mod m {
     use libc::{c_double, c_int};
 
     extern {
-        #[cfg(any(all(unix, not(target_os = "vxworks")), target_os = "cloudabi"))]
+        #[cfg(all(unix, not(target_os = "vxworks")))]
         #[link_name="lgamma_r"]
         pub fn lgamma(n: c_double, sign: &mut c_int) -> c_double;
         #[cfg(windows)]
index 24f4f60aa2f4e436e1e0b8e860135fae36a577f4..8aca21bf10fe4693f42e1aed05f90d4b62ce57e4 100644 (file)
@@ -1,7 +1,6 @@
 // run-pass
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
-// ignore-cloudabi no std::fs
 
 use std::{fs, net};
 
index a307e7eed959e2f1216269c763741014a9208e6d..d67f184720e6cb82be639057fdc5bc888390bdcd 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no std::path
 
 use std::collections::HashMap;
 use std::path::Path;
index f5fb8b650201a4dd8984cc536e2466a0c58f6401..ce7d8e3a7554730ed152a40661fa6ad592fe86d8 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no std::path
 
 use std::collections::HashMap;
 use std::path::{Path, PathBuf};
index 2c420dc056fdad4176eacfcbeef1899b7c8f59f8..c28b4ca96014b691c16d3bdd592fca745c402a38 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no processes
 // ignore-emscripten no threads
 // ignore-sgx no processes
 
index 259d706fa2a172ef469baa926872398b215a50b7..233670681f375279af5c37877737abacb7160034 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no std::env
 // ignore-wasm32 issue 42629
 
 #[inline(never)]
index fa692db4bf66ca11af9184361e415ce44ff1f750..1ed2d330b5123e4517869adc3a10f09f1beb2128 100644 (file)
@@ -1,3 +1,4 @@
 // compile-flags: --test
 
+#![allow(soft_unstable)]
 #![test] //~ ERROR cannot determine resolution for the attribute macro `test`
index 5f8d27dd043b1c408512b6f62299b9abe7eae89f..8ed4d015f3216658d06911f3b06c294cb73b8b2e 100644 (file)
@@ -1,5 +1,5 @@
 error: cannot determine resolution for the attribute macro `test`
-  --> $DIR/issue-28134.rs:3:4
+  --> $DIR/issue-28134.rs:4:4
    |
 LL | #![test]
    |    ^^^^
index 035f904b15bb34a571d1afc0a394369531201c5c..6779d508dd6c67a668b49f96560c3c5014431897 100644 (file)
@@ -1,5 +1,5 @@
 // check-pass
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 #![feature(negative_impls)]
 
 auto trait NotSame {}
diff --git a/src/test/ui/issues/issue-30240-b.rs b/src/test/ui/issues/issue-30240-b.rs
deleted file mode 100644 (file)
index 01a6e7d..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#![deny(unreachable_patterns)]
-
-fn main() {
-    match "world" {
-        "hello" => {}
-        _ => {},
-    }
-
-    match "world" {
-        ref _x if false => {}
-        "hello" => {}
-        "hello" => {} //~ ERROR unreachable pattern
-        _ => {},
-    }
-}
diff --git a/src/test/ui/issues/issue-30240-b.stderr b/src/test/ui/issues/issue-30240-b.stderr
deleted file mode 100644 (file)
index 59d64bc..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: unreachable pattern
-  --> $DIR/issue-30240-b.rs:12:9
-   |
-LL |         "hello" => {}
-   |         ^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/issue-30240-b.rs:1:9
-   |
-LL | #![deny(unreachable_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-30240-rpass.rs b/src/test/ui/issues/issue-30240-rpass.rs
deleted file mode 100644 (file)
index ab16614..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// run-pass
-fn main() {
-    let &ref a = &[0i32] as &[_];
-    assert_eq!(a, &[0i32] as &[_]);
-
-    let &ref a = "hello";
-    assert_eq!(a, "hello");
-
-    match "foo" {
-        "fool" => unreachable!(),
-        "foo" => {},
-        ref _x => unreachable!()
-    }
-}
diff --git a/src/test/ui/issues/issue-30240.rs b/src/test/ui/issues/issue-30240.rs
deleted file mode 100644 (file)
index a0c0d16..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-fn main() {
-    match "world" { //~ ERROR non-exhaustive patterns: `&_`
-        "hello" => {}
-    }
-
-    match "world" { //~ ERROR non-exhaustive patterns: `&_`
-        ref _x if false => {}
-        "hello" => {}
-    }
-}
diff --git a/src/test/ui/issues/issue-30240.stderr b/src/test/ui/issues/issue-30240.stderr
deleted file mode 100644 (file)
index a2c58d6..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0004]: non-exhaustive patterns: `&_` not covered
-  --> $DIR/issue-30240.rs:2:11
-   |
-LL |     match "world" {
-   |           ^^^^^^^ pattern `&_` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `&str`
-
-error[E0004]: non-exhaustive patterns: `&_` not covered
-  --> $DIR/issue-30240.rs:6:11
-   |
-LL |     match "world" {
-   |           ^^^^^^^ pattern `&_` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `&str`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0004`.
index 76e72246887b6941c6bb183969e39f4d65a241f1..47c17e362ae0bacca5af274e384a88340970364f 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
diff --git a/src/test/ui/issues/issue-3096-1.rs b/src/test/ui/issues/issue-3096-1.rs
deleted file mode 100644 (file)
index edc3b32..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-fn main() {
-    match () { } //~ ERROR non-exhaustive
-}
diff --git a/src/test/ui/issues/issue-3096-1.stderr b/src/test/ui/issues/issue-3096-1.stderr
deleted file mode 100644 (file)
index 97c3475..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0004]: non-exhaustive patterns: type `()` is non-empty
-  --> $DIR/issue-3096-1.rs:2:11
-   |
-LL |     match () { }
-   |           ^^
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `()`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/issues/issue-3096-2.rs b/src/test/ui/issues/issue-3096-2.rs
deleted file mode 100644 (file)
index a26e425..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-enum Bottom { }
-
-fn main() {
-    let x = &() as *const () as *const Bottom;
-    match x { } //~ ERROR non-exhaustive patterns
-}
diff --git a/src/test/ui/issues/issue-3096-2.stderr b/src/test/ui/issues/issue-3096-2.stderr
deleted file mode 100644 (file)
index 472d1a9..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0004]: non-exhaustive patterns: type `*const Bottom` is non-empty
-  --> $DIR/issue-3096-2.rs:5:11
-   |
-LL |     match x { }
-   |           ^
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `*const Bottom`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0004`.
index 818e004ffc8e6e471f75262ee3d2867464c68a7f..d371703e29587379387388a4358bccce21f255fb 100644 (file)
@@ -13,11 +13,13 @@ error[E0599]: no method named `collect` found for struct `Cloned<TakeWhile<&mut
 LL |         .collect();
    |          ^^^^^^^ method not found in `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6]>>`
    | 
-  ::: $SRC_DIR/core/src/iter/adapters/mod.rs:LL:COL
+  ::: $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL
    |
 LL | pub struct Cloned<I> {
    | -------------------- doesn't satisfy `_: Iterator`
-...
+   | 
+  ::: $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL
+   |
 LL | pub struct TakeWhile<I, P> {
    | -------------------------- doesn't satisfy `<_ as Iterator>::Item = &_`
    |
diff --git a/src/test/ui/issues/issue-31221.rs b/src/test/ui/issues/issue-31221.rs
deleted file mode 100644 (file)
index e03f1ec..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#![allow(dead_code)]
-#![allow(unused_variables)]
-#![allow(non_snake_case)]
-#![deny(unreachable_patterns)]
-
-#[derive(Clone, Copy)]
-enum Enum {
-    Var1,
-    Var2,
-}
-
-fn main() {
-    use Enum::*;
-    let s = Var1;
-    match s {
-        Var1 => (),
-        Var3 => (),
-        Var2 => (),
-        //~^ ERROR unreachable pattern
-    };
-    match &s {
-        &Var1 => (),
-        &Var3 => (),
-        &Var2 => (),
-        //~^ ERROR unreachable pattern
-    };
-    let t = (Var1, Var1);
-    match t {
-        (Var1, b) => (),
-        (c, d) => (),
-        anything => ()
-        //~^ ERROR unreachable pattern
-    };
-}
diff --git a/src/test/ui/issues/issue-31221.stderr b/src/test/ui/issues/issue-31221.stderr
deleted file mode 100644 (file)
index 7d34914..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-error: unreachable pattern
-  --> $DIR/issue-31221.rs:18:9
-   |
-LL |         Var3 => (),
-   |         ---- matches any value
-LL |         Var2 => (),
-   |         ^^^^ unreachable pattern
-   |
-note: the lint level is defined here
-  --> $DIR/issue-31221.rs:4:9
-   |
-LL | #![deny(unreachable_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error: unreachable pattern
-  --> $DIR/issue-31221.rs:24:9
-   |
-LL |         &Var3 => (),
-   |         ----- matches any value
-LL |         &Var2 => (),
-   |         ^^^^^ unreachable pattern
-
-error: unreachable pattern
-  --> $DIR/issue-31221.rs:31:9
-   |
-LL |         (c, d) => (),
-   |         ------ matches any value
-LL |         anything => ()
-   |         ^^^^^^^^ unreachable pattern
-
-error: aborting due to 3 previous errors
-
diff --git a/src/test/ui/issues/issue-31561.rs b/src/test/ui/issues/issue-31561.rs
deleted file mode 100644 (file)
index 813b240..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-enum Thing {
-    Foo(u8),
-    Bar,
-    Baz
-}
-
-fn main() {
-    let Thing::Foo(y) = Thing::Foo(1);
-    //~^ ERROR refutable pattern in local binding: `Bar` and `Baz` not covered
-}
diff --git a/src/test/ui/issues/issue-31561.stderr b/src/test/ui/issues/issue-31561.stderr
deleted file mode 100644 (file)
index 2f562b2..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-error[E0005]: refutable pattern in local binding: `Bar` and `Baz` not covered
-  --> $DIR/issue-31561.rs:8:9
-   |
-LL | / enum Thing {
-LL | |     Foo(u8),
-LL | |     Bar,
-   | |     --- not covered
-LL | |     Baz
-   | |     --- not covered
-LL | | }
-   | |_- `Thing` defined here
-...
-LL |       let Thing::Foo(y) = Thing::Foo(1);
-   |           ^^^^^^^^^^^^^ patterns `Bar` and `Baz` not covered
-   |
-   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
-   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
-   = note: the matched value is of type `Thing`
-help: you might want to use `if let` to ignore the variant that isn't matched
-   |
-LL |     if let Thing::Foo(y) = Thing::Foo(1) { /* */ }
-   |
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0005`.
index 39ae009c99650f3e1c4e0437057f851cff592ed7..f3c99015b6d82f9c07408b5ebd97b42d2b9b9465 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
index bf2d091a01e958c67f7091ff99ef29579abc2c0e..b45c00f694321227064f2fe67d81206fa7a3d028 100644 (file)
@@ -1,6 +1,6 @@
 fn main () {
     let sr: Vec<(u32, _, _) = vec![];
-    //~^ ERROR expected one of `,` or `>`, found `=`
+    //~^ ERROR only path types can be used in associated type constraints
     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
     //~^ ERROR a value of type `Vec<(u32, _, _)>` cannot be built
 }
index c10a41443050a4a1e25124ea310870fdd447acd7..a9b9bf06d7f420a98092fdf59af9fda8cc65f01f 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `,` or `>`, found `=`
-  --> $DIR/issue-34334.rs:2:29
+error: only path types can be used in associated type constraints
+  --> $DIR/issue-34334.rs:2:17
    |
 LL |     let sr: Vec<(u32, _, _) = vec![];
-   |         --                  ^ expected one of `,` or `>`
+   |         --      ^^^^^^^^^^^
    |         |
    |         while parsing the type for `sr`
 
diff --git a/src/test/ui/issues/issue-3601.rs b/src/test/ui/issues/issue-3601.rs
deleted file mode 100644 (file)
index e33359b..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#![feature(box_patterns)]
-#![feature(box_syntax)]
-
-struct HTMLImageData {
-    image: Option<String>
-}
-
-struct ElementData {
-    kind: Box<ElementKind>
-}
-
-enum ElementKind {
-    HTMLImageElement(HTMLImageData)
-}
-
-enum NodeKind {
-    Element(ElementData)
-}
-
-struct NodeData {
-    kind: Box<NodeKind>,
-}
-
-fn main() {
-    let mut id = HTMLImageData { image: None };
-    let ed = ElementData { kind: box ElementKind::HTMLImageElement(id) };
-    let n = NodeData {kind : box NodeKind::Element(ed)};
-    // n.b. span could be better
-    match n.kind {
-        box NodeKind::Element(ed) => match ed.kind { //~ ERROR non-exhaustive patterns
-            box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => { true }
-        },
-    };
-}
diff --git a/src/test/ui/issues/issue-3601.stderr b/src/test/ui/issues/issue-3601.stderr
deleted file mode 100644 (file)
index c873c20..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0004]: non-exhaustive patterns: `Box(_, _)` not covered
-  --> $DIR/issue-3601.rs:30:44
-   |
-LL |         box NodeKind::Element(ed) => match ed.kind {
-   |                                            ^^^^^^^ pattern `Box(_, _)` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `Box<ElementKind>`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0004`.
index 58f44f42524bc2cf9777298504af0e93fe0205f4..1102f3c4640a188a3b0adb5785b4a11cc25cdb60 100644 (file)
@@ -1,5 +1,4 @@
 #![derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions
                  //~| ERROR cannot determine resolution for the derive macro `Copy`
-                 //~| ERROR cannot determine resolution for the derive macro `Copy`
 
 fn main() {}
index 586dcf2cea675feb7481380b89501f228032d712..dc6ef1692591382f51290e50c1d22e05a9acd775 100644 (file)
@@ -12,14 +12,6 @@ LL | #![derive(Copy)]
    |
    = note: import resolution is stuck, try simplifying macro imports
 
-error: cannot determine resolution for the derive macro `Copy`
-  --> $DIR/issue-36617.rs:1:11
-   |
-LL | #![derive(Copy)]
-   |           ^^^^
-   |
-   = note: import resolution is stuck, try simplifying macro imports
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0774`.
index c20782a7eb4b852a08bdc2b731bf290a571c2e6d..81ff478aabc636feb284f3d55c098a6c30b0724e 100644 (file)
@@ -1,5 +1,4 @@
 // compile-flags: -Z unpretty=mir
-// ignore-cloudabi no std::path
 
 use std::path::MAIN_SEPARATOR;
 
index 1e191a620af02525bd1ffdc28e7c80e70a52501d..1e1f451b450af2c4cbbf2209eb1cdca41423f7f5 100644 (file)
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-37665.rs:10:17
+  --> $DIR/issue-37665.rs:9:17
    |
 LL |     let x: () = 0;
    |            --   ^ expected `()`, found integer
index 3ba2a9d40bec4352cd58acacaa3ca6dedbd1cd23..3866e0651c302f68e2605db0da6384a123bd039b 100644 (file)
@@ -4,7 +4,6 @@
 // these platforms also.
 
 // ignore-windows
-// ignore-cloudabi
 // ignore-emscripten
 // ignore-sgx no processes
 
index dbb334e7b9599371c3cbf68c6cd45f2794188849..afceae82e68becc5fadc63a6796f2c960dd26015 100644 (file)
@@ -1,5 +1,5 @@
 error[E0599]: no method named `exec` found for mutable reference `&mut Command` in the current scope
-  --> $DIR/issue-39175.rs:15:39
+  --> $DIR/issue-39175.rs:14:39
    |
 LL |     Command::new("echo").arg("hello").exec();
    |                                       ^^^^ method not found in `&mut Command`
diff --git a/src/test/ui/issues/issue-39362.rs b/src/test/ui/issues/issue-39362.rs
deleted file mode 100644 (file)
index ea3c8f8..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-enum Foo {
-    Bar { bar: Bar, id: usize }
-}
-
-enum Bar {
-    A, B, C, D, E, F
-}
-
-fn test(f: Foo) {
-    match f {
-        //~^ ERROR non-exhaustive patterns
-        //~| patterns
-        Foo::Bar { bar: Bar::A, .. } => (),
-        Foo::Bar { bar: Bar::B, .. } => (),
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-39362.stderr b/src/test/ui/issues/issue-39362.stderr
deleted file mode 100644 (file)
index 8c162e5..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0004]: non-exhaustive patterns: `Bar { bar: C, .. }`, `Bar { bar: D, .. }`, `Bar { bar: E, .. }` and 1 more not covered
-  --> $DIR/issue-39362.rs:10:11
-   |
-LL | / enum Foo {
-LL | |     Bar { bar: Bar, id: usize }
-LL | | }
-   | |_- `Foo` defined here
-...
-LL |       match f {
-   |             ^ patterns `Bar { bar: C, .. }`, `Bar { bar: D, .. }`, `Bar { bar: E, .. }` and 1 more not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `Foo`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0004`.
index 2744330a4e58e83ab3d884cb3a3767199887d87a..66bf053204c088e621b60a504dc81cc37c73aae8 100644 (file)
@@ -1,14 +1,14 @@
-error: cannot find macro `m` in this scope
-  --> $DIR/issue-40845.rs:4:10
-   |
-LL | impl S { m!(); }
-   |          ^
-
 error: cannot find macro `m` in this scope
   --> $DIR/issue-40845.rs:1:11
    |
 LL | trait T { m!(); }
    |           ^
 
+error: cannot find macro `m` in this scope
+  --> $DIR/issue-40845.rs:4:10
+   |
+LL | impl S { m!(); }
+   |          ^
+
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-4321.rs b/src/test/ui/issues/issue-4321.rs
deleted file mode 100644 (file)
index 9715f2e..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-fn main() {
-    let tup = (true, true);
-    println!("foo {:}", match tup { //~ ERROR non-exhaustive patterns: `(true, false)` not covered
-        (false, false) => "foo",
-        (false, true) => "bar",
-        (true, true) => "baz"
-    });
-}
diff --git a/src/test/ui/issues/issue-4321.stderr b/src/test/ui/issues/issue-4321.stderr
deleted file mode 100644 (file)
index 1e88525..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0004]: non-exhaustive patterns: `(true, false)` not covered
-  --> $DIR/issue-4321.rs:3:31
-   |
-LL |     println!("foo {:}", match tup {
-   |                               ^^^ pattern `(true, false)` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `(bool, bool)`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0004`.
index 1f871fcf6134255c4ffd684d6d62c6a2aeae5184..e7f26d021515c3b7d217096d8ca2cd1513e2d5c0 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no std::env
 
 fn parse_args() -> String {
     let args: Vec<_> = ::std::env::args().collect();
index 24752114e9f5c51e5205277a2fc7375b658fc059..2386561c39d261575f28693f58f2d6c521ef7182 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 // pretty-expanded FIXME #23616
-// ignore-cloudabi no std::env
 
 use std::env;
 
index 821d2724bc3e3358d7e2c34a7a4157012825bbf5..15f458f38445f30be50438e6449457819840aa74 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-cloudabi no std::fs support
-
 #![allow(dead_code)]
 #![deny(unused_imports)]
 
index 1e5e730ee649fd997411903477b938b253adb388..6f4d97068b353647a13ea00dd9cff2e216bafb3c 100644 (file)
@@ -1,11 +1,11 @@
 error: unused import: `BufRead`
-  --> $DIR/issue-46576.rs:7:15
+  --> $DIR/issue-46576.rs:5:15
    |
 LL | use std::io::{BufRead, BufReader, Read};
    |               ^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/issue-46576.rs:4:9
+  --> $DIR/issue-46576.rs:2:9
    |
 LL | #![deny(unused_imports)]
    |         ^^^^^^^^^^^^^^
index 6fa5f01ffd926c58a1efb69944c124bd8e3b2957..bf95f8fa7e1ec8fbcfb388efed713b96be520c49 100644 (file)
@@ -1,10 +1,8 @@
 fn foo<#[derive(Debug)] T>() {
 //~^ ERROR `derive` may only be applied to structs, enums and unions
-//~| ERROR expected an inert attribute, found a derive macro
     match 0 {
         #[derive(Debug)]
         //~^ ERROR `derive` may only be applied to structs, enums and unions
-        //~| ERROR expected an inert attribute, found a derive macro
         _ => (),
     }
 }
index 3befb38a208824fbfdf3968f334d07db814cffe9..71cd2d30342438c5a713e5bbf3b84669c7bd0ab8 100644 (file)
@@ -4,24 +4,12 @@ error[E0774]: `derive` may only be applied to structs, enums and unions
 LL | fn foo<#[derive(Debug)] T>() {
    |        ^^^^^^^^^^^^^^^^
 
-error: expected an inert attribute, found a derive macro
-  --> $DIR/issue-49934-errors.rs:1:17
-   |
-LL | fn foo<#[derive(Debug)] T>() {
-   |                 ^^^^^
-
 error[E0774]: `derive` may only be applied to structs, enums and unions
-  --> $DIR/issue-49934-errors.rs:5:9
+  --> $DIR/issue-49934-errors.rs:4:9
    |
 LL |         #[derive(Debug)]
    |         ^^^^^^^^^^^^^^^^
 
-error: expected an inert attribute, found a derive macro
-  --> $DIR/issue-49934-errors.rs:5:18
-   |
-LL |         #[derive(Debug)]
-   |                  ^^^^^
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0774`.
index f3a51b415facac0719b55f2e6f27f624def40e4b..fb4bf2b8b44e7642e5f68244b9057cd2234e4f8f 100644 (file)
@@ -1,3 +1,7 @@
+// revisions: default miropt
+//[miropt]compile-flags: -Z mir-opt-level=2
+// ~^ This flag is for #77668, it used to be ICE.
+
 #![crate_type = "lib"]
 
 pub fn bar<P>( // Error won't happen if "bar" is not generic
diff --git a/src/test/ui/issues/issue-57472.rs b/src/test/ui/issues/issue-57472.rs
deleted file mode 100644 (file)
index 1131006..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#![crate_type="lib"]
-#![deny(unreachable_patterns)]
-
-mod test_struct {
-    // Test the exact copy of the minimal example
-    // posted in the issue.
-    pub struct Punned {
-        foo: [u8; 1],
-        bar: [u8; 1],
-    }
-
-    pub fn test(punned: Punned) {
-        match punned {
-            Punned { foo: [_], .. } => println!("foo"),
-            Punned { bar: [_], .. } => println!("bar"),
-            //~^ ERROR unreachable pattern [unreachable_patterns]
-        }
-    }
-}
-
-mod test_union {
-    // Test the same thing using a union.
-    pub union Punned {
-        foo: [u8; 1],
-        bar: [u8; 1],
-    }
-
-    pub fn test(punned: Punned) {
-        match punned {
-            Punned { foo: [_] } => println!("foo"),
-            Punned { bar: [_] } => println!("bar"),
-            //~^ ERROR unreachable pattern [unreachable_patterns]
-        }
-    }
-}
diff --git a/src/test/ui/issues/issue-57472.stderr b/src/test/ui/issues/issue-57472.stderr
deleted file mode 100644 (file)
index 26efdf6..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error: unreachable pattern
-  --> $DIR/issue-57472.rs:15:13
-   |
-LL |             Punned { bar: [_], .. } => println!("bar"),
-   |             ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/issue-57472.rs:2:9
-   |
-LL | #![deny(unreachable_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error: unreachable pattern
-  --> $DIR/issue-57472.rs:31:13
-   |
-LL |             Punned { bar: [_] } => println!("bar"),
-   |             ^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/issues/issue-73899.rs b/src/test/ui/issues/issue-73899.rs
new file mode 100644 (file)
index 0000000..2a3a5ab
--- /dev/null
@@ -0,0 +1,21 @@
+// run-pass
+#![feature(const_evaluatable_checked)]
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+trait Foo {}
+
+impl<const N: usize> Foo for [(); N] where Self: FooImpl<{ N == 0 }> {}
+
+trait FooImpl<const IS_ZERO: bool> {}
+
+impl FooImpl<{ 0u8 == 0u8 }> for [(); 0] {}
+
+impl<const N: usize> FooImpl<{ 0u8 != 0u8 }> for [(); N] {}
+
+fn foo<T: Foo>(_v: T) {}
+
+fn main() {
+    foo([]);
+    foo([()]);
+}
index b755bb554f4418da870a96d5426d8c0fc2fddd69..c38755db87ebf321f56392d1c684ebdb15d8aab9 100644 (file)
@@ -2,7 +2,6 @@
 // only-32bit too impatient for 2⁶⁴ items
 // compile-flags: -C debug_assertions=no -C opt-level=3
 
-use std::panic;
 use std::usize::MAX;
 
 fn main() {
index 368f9c0c02b07d3ab933f0123dd330c5f78da774..3b0c245a5c2a18369ff8ad0d2833a88d405f9880 100644 (file)
@@ -2,7 +2,6 @@
 // only-32bit too impatient for 2⁶⁴ items
 // compile-flags: -C debug_assertions=no -C opt-level=3
 
-use std::panic;
 use std::usize::MAX;
 
 fn main() {
index ae04612a4dd69aa536f27640786b8821dd773b0b..6ac884c12ceb9a7df3455f0d8d7dcae478ad3e87 100644 (file)
@@ -1,19 +1,3 @@
-error[E0518]: attribute should be applied to function or closure
-  --> $DIR/inline-trait-and-foreign-items.rs:30:5
-   |
-LL |     #[inline]
-   |     ^^^^^^^^^
-LL |     static X: u32;
-   |     -------------- not a function or closure
-
-error[E0518]: attribute should be applied to function or closure
-  --> $DIR/inline-trait-and-foreign-items.rs:33:5
-   |
-LL |     #[inline]
-   |     ^^^^^^^^^
-LL |     type T;
-   |     ------- not a function or closure
-
 warning: `#[inline]` is ignored on constants
   --> $DIR/inline-trait-and-foreign-items.rs:7:5
    |
@@ -61,6 +45,22 @@ LL |     #[inline]
 LL |     type U = impl Trait;
    |     -------------------- not a function or closure
 
+error[E0518]: attribute should be applied to function or closure
+  --> $DIR/inline-trait-and-foreign-items.rs:30:5
+   |
+LL |     #[inline]
+   |     ^^^^^^^^^
+LL |     static X: u32;
+   |     -------------- not a function or closure
+
+error[E0518]: attribute should be applied to function or closure
+  --> $DIR/inline-trait-and-foreign-items.rs:33:5
+   |
+LL |     #[inline]
+   |     ^^^^^^^^^
+LL |     type T;
+   |     ------- not a function or closure
+
 error: could not find defining uses
   --> $DIR/inline-trait-and-foreign-items.rs:26:14
    |
diff --git a/src/test/ui/lint/redundant-semicolon/item-stmt-semi.rs b/src/test/ui/lint/redundant-semicolon/item-stmt-semi.rs
new file mode 100644 (file)
index 0000000..4592bc3
--- /dev/null
@@ -0,0 +1,10 @@
+// check-pass
+// This test should stop compiling
+// we decide to enable this lint for item statements.
+
+#![deny(redundant_semicolons)]
+
+fn main() {
+    fn inner() {};
+    struct Bar {};
+}
diff --git a/src/test/ui/lint/special-upper-lower-cases.rs b/src/test/ui/lint/special-upper-lower-cases.rs
new file mode 100644 (file)
index 0000000..71ebf05
--- /dev/null
@@ -0,0 +1,24 @@
+// (#77273) These characters are in the general categories of
+// "Uppercase/Lowercase Letter".
+// The diagnostics don't provide meaningful suggestions for them
+// as we cannot convert them properly.
+
+// check-pass
+
+#![feature(non_ascii_idents)]
+#![allow(uncommon_codepoints, unused)]
+
+struct 𝕟𝕠𝕥𝕒𝕔𝕒𝕞𝕖𝕝;
+//~^ WARN: type `𝕟𝕠𝕥𝕒𝕔𝕒𝕞𝕖𝕝` should have an upper camel case name
+
+// FIXME: How we should handle this?
+struct 𝕟𝕠𝕥_𝕒_𝕔𝕒𝕞𝕖𝕝;
+//~^ WARN: type `𝕟𝕠𝕥_𝕒_𝕔𝕒𝕞𝕖𝕝` should have an upper camel case name
+
+static 𝗻𝗼𝗻𝘂𝗽𝗽𝗲𝗿𝗰𝗮𝘀𝗲: i32 = 1;
+//~^ WARN: static variable `𝗻𝗼𝗻𝘂𝗽𝗽𝗲𝗿𝗰𝗮𝘀𝗲` should have an upper case name
+
+fn main() {
+    let 𝓢𝓝𝓐𝓐𝓐𝓐𝓚𝓔𝓢 = 1;
+    //~^ WARN: variable `𝓢𝓝𝓐𝓐𝓐𝓐𝓚𝓔𝓢` should have a snake case name
+}
diff --git a/src/test/ui/lint/special-upper-lower-cases.stderr b/src/test/ui/lint/special-upper-lower-cases.stderr
new file mode 100644 (file)
index 0000000..f32193a
--- /dev/null
@@ -0,0 +1,32 @@
+warning: type `𝕟𝕠𝕥𝕒𝕔𝕒𝕞𝕖𝕝` should have an upper camel case name
+  --> $DIR/special-upper-lower-cases.rs:11:8
+   |
+LL | struct 𝕟𝕠𝕥𝕒𝕔𝕒𝕞𝕖𝕝;
+   |        ^^^^^^^^^
+   |
+   = note: `#[warn(non_camel_case_types)]` on by default
+
+warning: type `𝕟𝕠𝕥_𝕒_𝕔𝕒𝕞𝕖𝕝` should have an upper camel case name
+  --> $DIR/special-upper-lower-cases.rs:15:8
+   |
+LL | struct 𝕟𝕠𝕥_𝕒_𝕔𝕒𝕞𝕖𝕝;
+   |        ^^^^^^^^^^^ help: convert the identifier to upper camel case: `𝕟𝕠𝕥𝕒𝕔𝕒𝕞𝕖𝕝`
+
+warning: static variable `𝗻𝗼𝗻𝘂𝗽𝗽𝗲𝗿𝗰𝗮𝘀𝗲` should have an upper case name
+  --> $DIR/special-upper-lower-cases.rs:18:8
+   |
+LL | static 𝗻𝗼𝗻𝘂𝗽𝗽𝗲𝗿𝗰𝗮𝘀𝗲: i32 = 1;
+   |        ^^^^^^^^^^^^
+   |
+   = note: `#[warn(non_upper_case_globals)]` on by default
+
+warning: variable `𝓢𝓝𝓐𝓐𝓐𝓐𝓚𝓔𝓢` should have a snake case name
+  --> $DIR/special-upper-lower-cases.rs:22:9
+   |
+LL |     let 𝓢𝓝𝓐𝓐𝓐𝓐𝓚𝓔𝓢 = 1;
+   |         ^^^^^^^^^
+   |
+   = note: `#[warn(non_snake_case)]` on by default
+
+warning: 4 warnings emitted
+
index d7efa4aac6516a4eac23d1b74590b02878596994..7d641e08bf0127573b8965f422b7af9c4605017f 100644 (file)
@@ -1,4 +1,3 @@
-// ignore-cloudabi
 // ignore-windows
 // ignore-sgx std::os::fortanix_sgx::usercalls::alloc::Iter changes compiler suggestions
 // compile-flags: --error-format pretty-json --json=diagnostic-rendered-ansi
index d0d91bb61f45706a5c6d45edd8137eef37f32848..21342e2ef37a02e01900a3f6a7cde276f1d1d687 100644 (file)
@@ -72,10 +72,10 @@ mod foo {
   "spans": [
     {
       "file_name": "$DIR/use_suggestion_json.rs",
-      "byte_start": 560,
-      "byte_end": 564,
-      "line_start": 13,
-      "line_end": 13,
+      "byte_start": 541,
+      "byte_end": 545,
+      "line_start": 12,
+      "line_end": 12,
       "column_start": 12,
       "column_end": 16,
       "is_primary": true,
@@ -100,10 +100,10 @@ mod foo {
       "spans": [
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 537,
-          "byte_end": 537,
-          "line_start": 12,
-          "line_end": 12,
+          "byte_start": 518,
+          "byte_end": 518,
+          "line_start": 11,
+          "line_end": 11,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -123,10 +123,10 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 537,
-          "byte_end": 537,
-          "line_start": 12,
-          "line_end": 12,
+          "byte_start": 518,
+          "byte_end": 518,
+          "line_start": 11,
+          "line_end": 11,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -146,10 +146,10 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 537,
-          "byte_end": 537,
-          "line_start": 12,
-          "line_end": 12,
+          "byte_start": 518,
+          "byte_end": 518,
+          "line_start": 11,
+          "line_end": 11,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -169,10 +169,10 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 537,
-          "byte_end": 537,
-          "line_start": 12,
-          "line_end": 12,
+          "byte_start": 518,
+          "byte_end": 518,
+          "line_start": 11,
+          "line_end": 11,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -192,10 +192,10 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 537,
-          "byte_end": 537,
-          "line_start": 12,
-          "line_end": 12,
+          "byte_start": 518,
+          "byte_end": 518,
+          "line_start": 11,
+          "line_end": 11,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -215,10 +215,10 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 537,
-          "byte_end": 537,
-          "line_start": 12,
-          "line_end": 12,
+          "byte_start": 518,
+          "byte_end": 518,
+          "line_start": 11,
+          "line_end": 11,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -238,10 +238,10 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 537,
-          "byte_end": 537,
-          "line_start": 12,
-          "line_end": 12,
+          "byte_start": 518,
+          "byte_end": 518,
+          "line_start": 11,
+          "line_end": 11,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -261,10 +261,10 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 537,
-          "byte_end": 537,
-          "line_start": 12,
-          "line_end": 12,
+          "byte_start": 518,
+          "byte_end": 518,
+          "line_start": 11,
+          "line_end": 11,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -284,10 +284,10 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 537,
-          "byte_end": 537,
-          "line_start": 12,
-          "line_end": 12,
+          "byte_start": 518,
+          "byte_end": 518,
+          "line_start": 11,
+          "line_end": 11,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -307,10 +307,10 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 537,
-          "byte_end": 537,
-          "line_start": 12,
-          "line_end": 12,
+          "byte_start": 518,
+          "byte_end": 518,
+          "line_start": 11,
+          "line_end": 11,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -330,10 +330,10 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 537,
-          "byte_end": 537,
-          "line_start": 12,
-          "line_end": 12,
+          "byte_start": 518,
+          "byte_end": 518,
+          "line_start": 11,
+          "line_end": 11,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -353,10 +353,10 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 537,
-          "byte_end": 537,
-          "line_start": 12,
-          "line_end": 12,
+          "byte_start": 518,
+          "byte_end": 518,
+          "line_start": 11,
+          "line_end": 11,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -380,7 +380,7 @@ mod foo {
     }
   ],
   "rendered": "\u001b[0m\u001b[1m\u001b[38;5;9merror[E0412]\u001b[0m\u001b[0m\u001b[1m: cannot find type `Iter` in this scope\u001b[0m
-\u001b[0m  \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0m$DIR/use_suggestion_json.rs:13:12\u001b[0m
+\u001b[0m  \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0m$DIR/use_suggestion_json.rs:12:12\u001b[0m
 \u001b[0m   \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m
 \u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0m    let x: Iter;\u001b[0m
 \u001b[0m   \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0m           \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9m^^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9mnot found in this scope\u001b[0m
index 843db8ce8150266e2f0ab9660db89ad5002b7911..ab19d80e7327c56a5cd84ceb511c379656def9da 100644 (file)
@@ -1,5 +1,5 @@
 error: `#[inline]` is ignored on function prototypes
-  --> $DIR/warn-unused-inline-on-fn-prototypes.rs:9:5
+  --> $DIR/warn-unused-inline-on-fn-prototypes.rs:4:5
    |
 LL |     #[inline]
    |     ^^^^^^^^^
@@ -11,7 +11,7 @@ LL | #![deny(unused_attributes)]
    |         ^^^^^^^^^^^^^^^^^
 
 error: `#[inline]` is ignored on function prototypes
-  --> $DIR/warn-unused-inline-on-fn-prototypes.rs:4:5
+  --> $DIR/warn-unused-inline-on-fn-prototypes.rs:9:5
    |
 LL |     #[inline]
    |     ^^^^^^^^^
diff --git a/src/test/ui/macros/issue-78333.rs b/src/test/ui/macros/issue-78333.rs
new file mode 100644 (file)
index 0000000..c376f20
--- /dev/null
@@ -0,0 +1,13 @@
+// build-pass
+
+#![no_implicit_prelude]
+
+fn main() {
+    ::std::panic!();
+    ::std::todo!();
+    ::std::unimplemented!();
+    ::std::assert_eq!(0, 0);
+    ::std::assert_ne!(0, 1);
+    ::std::dbg!(123);
+    ::std::unreachable!();
+}
index 4890c991dcd7baafb303ace32b9ed43959aa9817..a315981b6a69fdda98d50d7152a990088a598012 100644 (file)
@@ -3,7 +3,7 @@ pub fn main() {
 
     macro_rules! mylambda_tt {
         ($x:ident, $body:expr) => ({
-            fn f($x: isize) -> isize { return $body; };
+            fn f($x: isize) -> isize { return $body; }
             f
         })
     }
index 32cf59294e7603e7fc4d158c4be511a05f09bf24..e5e656de6fa7f339b968f53acb1cc9d68f49e287 100644 (file)
@@ -57,6 +57,7 @@ fn writeln_1arg() {
 //
 // (Example: Issue #48042)
 #[test]
+#[allow(panic_fmt)]
 fn to_format_or_not_to_format() {
     // ("{}" is the easiest string to test because if this gets
     // sent to format_args!, it'll simply fail to compile.
index be59d8d139bb59b49755dd6aff4a23ce773532eb..6c011c897da50ffd7e6c397ff74a334aa3ddc83d 100644 (file)
@@ -8,7 +8,7 @@ mod m {
 
 macro_rules! foo {
     ($p:path) => ({
-        fn f() -> $p { 10 };
+        fn f() -> $p { 10 }
         f()
     })
 }
index 24692f7cf52e1e262920471fec86f9ddc9f37c8d..1fd7cddc7c937b6c007396d9271938494af6a145 100644 (file)
@@ -4,7 +4,6 @@ struct CLI {
     #[derive(parse())]
     //~^ ERROR traits in `#[derive(...)]` don't accept arguments
     //~| ERROR cannot find derive macro `parse` in this scope
-    //~| ERROR cannot find derive macro `parse` in this scope
     path: (),
     //~^ ERROR `derive` may only be applied to structs, enums and unions
 }
index c4532a375a75ebde3b998a9a34551214273eea9f..db40ce07530450db1c91cd47642a21dae4d26873 100644 (file)
@@ -5,7 +5,7 @@ LL |     #[derive(parse())]
    |                   ^^ help: remove the arguments
 
 error[E0774]: `derive` may only be applied to structs, enums and unions
-  --> $DIR/issue-69341-malformed-derive-inert.rs:8:5
+  --> $DIR/issue-69341-malformed-derive-inert.rs:7:5
    |
 LL |     path: (),
    |     ^^^^^^^^
@@ -16,12 +16,6 @@ error: cannot find derive macro `parse` in this scope
 LL |     #[derive(parse())]
    |              ^^^^^
 
-error: cannot find derive macro `parse` in this scope
-  --> $DIR/issue-69341-malformed-derive-inert.rs:4:14
-   |
-LL |     #[derive(parse())]
-   |              ^^^^^
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0774`.
diff --git a/src/test/ui/match/issue-50900.rs b/src/test/ui/match/issue-50900.rs
deleted file mode 100644 (file)
index 27135af..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#[derive(PartialEq, Eq)]
-pub struct Tag(pub Context, pub u16);
-
-#[derive(PartialEq, Eq)]
-pub enum Context {
-    Tiff,
-    Exif,
-}
-
-impl Tag {
-    const ExifIFDPointer: Tag = Tag(Context::Tiff, 34665);
-}
-
-fn main() {
-    match Tag::ExifIFDPointer {
-    //~^ ERROR: non-exhaustive patterns: `Tag(Exif, _)` not covered
-        Tag::ExifIFDPointer => {}
-    }
-}
diff --git a/src/test/ui/match/issue-50900.stderr b/src/test/ui/match/issue-50900.stderr
deleted file mode 100644 (file)
index d378b6e..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0004]: non-exhaustive patterns: `Tag(Exif, _)` not covered
-  --> $DIR/issue-50900.rs:15:11
-   |
-LL | pub struct Tag(pub Context, pub u16);
-   | ------------------------------------- `Tag` defined here
-...
-LL |     match Tag::ExifIFDPointer {
-   |           ^^^^^^^^^^^^^^^^^^^ pattern `Tag(Exif, _)` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `Tag`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/match/type_polymorphic_byte_str_literals.rs b/src/test/ui/match/type_polymorphic_byte_str_literals.rs
deleted file mode 100644 (file)
index cb44c1d..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#[deny(unreachable_patterns)]
-
-fn parse_data1(data: &[u8]) -> u32 {
-    match data {
-        b"" => 1,
-        _ => 2,
-    }
-}
-
-fn parse_data2(data: &[u8]) -> u32 {
-    match data { //~ ERROR non-exhaustive patterns: `&[_, ..]` not covered
-        b"" => 1,
-    }
-}
-
-fn parse_data3(data: &[u8; 0]) -> u8 {
-    match data {
-        b"" => 1,
-    }
-}
-
-fn parse_data4(data: &[u8]) -> u8 {
-    match data { //~ ERROR non-exhaustive patterns
-        b"aaa" => 0,
-        [_, _, _] => 1,
-    }
-}
-
-fn parse_data5(data: &[u8; 3]) -> u8 {
-    match data {
-        b"aaa" => 0,
-        [_, _, _] => 1,
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/match/type_polymorphic_byte_str_literals.stderr b/src/test/ui/match/type_polymorphic_byte_str_literals.stderr
deleted file mode 100644 (file)
index 6ce53a4..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
-  --> $DIR/type_polymorphic_byte_str_literals.rs:11:11
-   |
-LL |     match data {
-   |           ^^^^ pattern `&[_, ..]` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `&[u8]`
-
-error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 1 more not covered
-  --> $DIR/type_polymorphic_byte_str_literals.rs:23:11
-   |
-LL |     match data {
-   |           ^^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 1 more not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `&[u8]`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0004`.
index b24faa6f885c78b078289086ecc8a54073fa40dd..fff303495e75b98b5d64efda87a7cef8325df278 100644 (file)
@@ -1,5 +1,4 @@
 // compile-flags: -Z mir-opt-level=2
-// ignore-cloudabi no std::fs
 // build-pass
 
 use std::fs::File;
diff --git a/src/test/ui/mir/mir-inlining/array-clone-with-generic-size.rs b/src/test/ui/mir/mir-inlining/array-clone-with-generic-size.rs
new file mode 100644 (file)
index 0000000..8a96303
--- /dev/null
@@ -0,0 +1,13 @@
+// Checks that we can build a clone shim for array with generic size.
+// Regression test for issue #79269.
+//
+// build-pass
+// compile-flags: -Zmir-opt-level=2 -Zvalidate-mir
+#![feature(min_const_generics)]
+
+#[derive(Clone)]
+struct Array<T, const N: usize>([T; N]);
+
+fn main() {
+    let _ = Array([0u32, 1u32, 2u32]).clone();
+}
index ccb279f7fa212c076a65348238bba678d7bc94f7..4d083bf23215599a16ecf1c8f16cabcf6a678488 100644 (file)
@@ -1,27 +1,17 @@
-// Regression test for various issues related to normalization & inlining.
-// * #68347, #77306, #77668 - missed normalization during inlining.
-// * #78442 - missed normalization in validator after inlining.
-//
-// build-pass
+// run-pass
 // compile-flags:-Zmir-opt-level=2
 
+// Previously ICEd because we did not normalize during inlining,
+// see https://github.com/rust-lang/rust/pull/77306 for more discussion.
+
 pub fn write() {
     create()()
 }
 
-pub fn write_generic<T>(_t: T) {
-    hide()();
-}
-
 pub fn create() -> impl FnOnce() {
    || ()
 }
 
-pub fn hide() -> impl Fn() {
-    write
-}
-
 fn main() {
     write();
-    write_generic(());
 }
index a77b2368d3baa571821e1b746ec889733060ff4f..2b33b616600bea4f9ca398ac2c552b7c31fe8ad5 100644 (file)
@@ -1,7 +1,6 @@
 // run-fail
 // error-pattern:drop 1
 // error-pattern:drop 2
-// ignore-cloudabi no std::process
 // ignore-emscripten no processes
 
 /// Structure which will not allow to be dropped twice.
index 088a16d338787c69db0cba7b837d4bbe4c591d25..c883efdabc3f68a917bb6926e00e805bf206e506 100644 (file)
@@ -1,6 +1,5 @@
 // run-fail
 // error-pattern:drop 1
-// ignore-cloudabi no std::process
 // ignore-emscripten no processes
 
 /// Structure which will not allow to be dropped twice.
index 029bdcd9a15909109aa1825a43696942ec67930e..eb76fdff88647b7474b1a7c7a0d1d2b5549dd63a 100644 (file)
@@ -3,7 +3,6 @@
 // error-pattern:drop 3
 // error-pattern:drop 2
 // error-pattern:drop 1
-// ignore-cloudabi no std::process
 // ignore-emscripten no processes
 
 /// Structure which will not allow to be dropped twice.
index 0b1fcf58e2e001185d93bba320277b1f38d55d22..2efd37b4738a5130bafa0bd3d255e9116d55fa94 100644 (file)
@@ -15,7 +15,7 @@ LL |     once::<&str>("str").fuse().filter(|a: &str| true).count();
    |                                       doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool`
    |                                       doesn't satisfy `_: FnMut<(&&str,)>`
    | 
-  ::: $SRC_DIR/core/src/iter/adapters/mod.rs:LL:COL
+  ::: $SRC_DIR/core/src/iter/adapters/filter.rs:LL:COL
    |
 LL | pub struct Filter<I, P> {
    | ----------------------- doesn't satisfy `_: Iterator`
index cb8ad8092dd82e3d44d9bd0d83ca63ceb3cd6931..b230b47d35d37d08451e1e73cbbc1c189565b3a7 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-cloudabi no std::env support
-
 use std::env;
 
 pub struct Foo {
index 525d09b8fc1c16df6b3029b1bc8550c19d8ac643..f2b8404a328e28af7e0159d3e5a7935501b54b1d 100644 (file)
@@ -1,5 +1,5 @@
 error: missing `struct` for struct definition
-  --> $DIR/recovered-block.rs:13:8
+  --> $DIR/recovered-block.rs:11:8
    |
 LL |     pub Foo { text }
    |        ^
@@ -10,7 +10,7 @@ LL |     pub struct Foo { text }
    |         ^^^^^^
 
 error: expected one of `(` or `<`, found `{`
-  --> $DIR/recovered-block.rs:19:9
+  --> $DIR/recovered-block.rs:17:9
    |
 LL |     Foo { text: "".to_string() }
    |         ^ expected one of `(` or `<`
diff --git a/src/test/ui/missing/missing-items/issue-40221.rs b/src/test/ui/missing/missing-items/issue-40221.rs
deleted file mode 100644 (file)
index e1f7e97..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-enum P {
-    C(PC),
-}
-
-enum PC {
-    Q,
-    QA,
-}
-
-fn test(proto: P) {
-    match proto { //~ ERROR non-exhaustive patterns
-        P::C(PC::Q) => (),
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/missing/missing-items/issue-40221.stderr b/src/test/ui/missing/missing-items/issue-40221.stderr
deleted file mode 100644 (file)
index 98efe80..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error[E0004]: non-exhaustive patterns: `C(QA)` not covered
-  --> $DIR/issue-40221.rs:11:11
-   |
-LL | / enum P {
-LL | |     C(PC),
-   | |     - not covered
-LL | | }
-   | |_- `P` defined here
-...
-LL |       match proto {
-   |             ^^^^^ pattern `C(QA)` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `P`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0004`.
index 0f8bddf27fe088e9f15f184730d5a804a8dc1eeb..37e8b99c2f69744ee272355fa9c6d08a6b4a5c90 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
index 84c8db4053e4f76dc892ac6e01af6cfeef047e94..42ede708e66df7abf9cf5ab782a3fe7e36db4e7a 100644 (file)
@@ -1,6 +1,6 @@
 // check-pass
 
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 #![feature(negative_impls)]
 #![feature(never_type)]
 
index e6995be27d20e728c68b03c262bde9a259296077..9c884a33c5fec253e47a20b1467024194db685b4 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-cloudabi no std::process
-
 fn foo(_: Box<dyn FnMut()>) {}
 
 fn main() {
index 93c792a72ec6842c8e6a6ca462d58697e60c8211..b98f6c93923b99287edd4e8c63336c69b9745c82 100644 (file)
@@ -1,5 +1,5 @@
 error[E0277]: cannot add `()` to `usize`
-  --> $DIR/issue-13352.rs:9:13
+  --> $DIR/issue-13352.rs:7:13
    |
 LL |     2_usize + (loop {});
    |             ^ no implementation for `usize + ()`
index 1b0ad930da6d7f571b51bf8a224659d9c325f173..68e6fa838b4e283f286c628bb75401b1d18adca5 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 // ignore-android
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
index 6beafc0732ba3174774ea77af304818508b213c8..2d59c9f29b12b732dd91bd06225d200b410d431f 100644 (file)
@@ -3,7 +3,6 @@
 #![allow(unused_must_use)]
 #![allow(unconditional_recursion)]
 // ignore-android: FIXME (#20004)
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
index 62a7130ddebd1deb635fa9b3e94638aa358b3669..76b114c55925b7f215bb6529465e61d09349b9c6 100644 (file)
@@ -11,11 +11,13 @@ impl FnMut<isize> for S {
     extern "rust-call" fn call_mut(&mut self, z: isize) -> isize {
         self.x + self.y + z
     }
+    //~^^^ ERROR A function with the "rust-call" ABI must take a single non-self argument
 }
 
 impl FnOnce<isize> for S {
     type Output = isize;
     extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) }
+    //~^ ERROR A function with the "rust-call" ABI must take a single non-self argument
 }
 
 fn main() {
index 82c12c4b6e19c9c32c79e3af536274c0435f0725..bdadb95db29477eb784f1290d951b65e3b384f4b 100644 (file)
@@ -1,9 +1,21 @@
+error: A function with the "rust-call" ABI must take a single non-self argument that is a tuple
+  --> $DIR/overloaded-calls-nontuple.rs:11:5
+   |
+LL |     extern "rust-call" fn call_mut(&mut self, z: isize) -> isize {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: A function with the "rust-call" ABI must take a single non-self argument that is a tuple
+  --> $DIR/overloaded-calls-nontuple.rs:19:5
+   |
+LL |     extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit
-  --> $DIR/overloaded-calls-nontuple.rs:26:10
+  --> $DIR/overloaded-calls-nontuple.rs:28:10
    |
 LL |     drop(s(3))
    |          ^^^^
 
-error: aborting due to previous error
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0059`.
diff --git a/src/test/ui/panic-brace.rs b/src/test/ui/panic-brace.rs
new file mode 100644 (file)
index 0000000..754dcc2
--- /dev/null
@@ -0,0 +1,31 @@
+// build-pass (FIXME(62277): should be check-pass)
+// aux-build:fancy-panic.rs
+
+extern crate fancy_panic;
+
+const C: &str = "abc {}";
+static S: &str = "{bla}";
+
+#[allow(unreachable_code)]
+fn main() {
+    panic!("here's a brace: {"); //~ WARN panic message contains a brace
+    std::panic!("another one: }"); //~ WARN panic message contains a brace
+    core::panic!("Hello {}"); //~ WARN panic message contains an unused formatting placeholder
+    assert!(false, "{:03x} {test} bla");
+    //~^ WARN panic message contains unused formatting placeholders
+    debug_assert!(false, "{{}} bla"); //~ WARN panic message contains braces
+    panic!(C); // No warning (yet)
+    panic!(S); // No warning (yet)
+    panic!(concat!("{", "}")); //~ WARN panic message contains an unused formatting placeholder
+    panic!(concat!("{", "{")); //~ WARN panic message contains braces
+
+    fancy_panic::fancy_panic!("test {} 123");
+    //~^ WARN panic message contains an unused formatting placeholder
+
+    // Check that the lint only triggers for std::panic and core::panic,
+    // not any panic macro:
+    macro_rules! panic {
+        ($e:expr) => ();
+    }
+    panic!("{}"); // OK
+}
diff --git a/src/test/ui/panic-brace.stderr b/src/test/ui/panic-brace.stderr
new file mode 100644 (file)
index 0000000..9380889
--- /dev/null
@@ -0,0 +1,107 @@
+warning: panic message contains a brace
+  --> $DIR/panic-brace.rs:11:29
+   |
+LL |     panic!("here's a brace: {");
+   |                             ^
+   |
+   = note: `#[warn(panic_fmt)]` on by default
+   = note: this message is not used as a format string, but will be in a future Rust edition
+help: add a "{}" format string to use the message literally
+   |
+LL |     panic!("{}", "here's a brace: {");
+   |            ^^^^^
+
+warning: panic message contains a brace
+  --> $DIR/panic-brace.rs:12:31
+   |
+LL |     std::panic!("another one: }");
+   |                               ^
+   |
+   = note: this message is not used as a format string, but will be in a future Rust edition
+help: add a "{}" format string to use the message literally
+   |
+LL |     std::panic!("{}", "another one: }");
+   |                 ^^^^^
+
+warning: panic message contains an unused formatting placeholder
+  --> $DIR/panic-brace.rs:13:25
+   |
+LL |     core::panic!("Hello {}");
+   |                         ^^
+   |
+   = note: this message is not used as a format string when given without arguments, but will be in a future Rust edition
+help: add the missing argument
+   |
+LL |     core::panic!("Hello {}", ...);
+   |                            ^^^^^
+help: or add a "{}" format string to use the message literally
+   |
+LL |     core::panic!("{}", "Hello {}");
+   |                  ^^^^^
+
+warning: panic message contains unused formatting placeholders
+  --> $DIR/panic-brace.rs:14:21
+   |
+LL |     assert!(false, "{:03x} {test} bla");
+   |                     ^^^^^^ ^^^^^^
+   |
+   = note: this message is not used as a format string when given without arguments, but will be in a future Rust edition
+help: add the missing arguments
+   |
+LL |     assert!(false, "{:03x} {test} bla", ...);
+   |                                       ^^^^^
+help: or add a "{}" format string to use the message literally
+   |
+LL |     assert!(false, "{}", "{:03x} {test} bla");
+   |                    ^^^^^
+
+warning: panic message contains braces
+  --> $DIR/panic-brace.rs:16:27
+   |
+LL |     debug_assert!(false, "{{}} bla");
+   |                           ^^^^
+   |
+   = note: this message is not used as a format string, but will be in a future Rust edition
+help: add a "{}" format string to use the message literally
+   |
+LL |     debug_assert!(false, "{}", "{{}} bla");
+   |                          ^^^^^
+
+warning: panic message contains an unused formatting placeholder
+  --> $DIR/panic-brace.rs:19:12
+   |
+LL |     panic!(concat!("{", "}"));
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: this message is not used as a format string when given without arguments, but will be in a future Rust edition
+help: add the missing argument
+   |
+LL |     panic!(concat!("{", "}"), ...);
+   |                             ^^^^^
+help: or add a "{}" format string to use the message literally
+   |
+LL |     panic!("{}", concat!("{", "}"));
+   |            ^^^^^
+
+warning: panic message contains braces
+  --> $DIR/panic-brace.rs:20:5
+   |
+LL |     panic!(concat!("{", "{"));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this message is not used as a format string, but will be in a future Rust edition
+help: add a "{}" format string to use the message literally
+   |
+LL |     panic!("{}", concat!("{", "{"));
+   |            ^^^^^
+
+warning: panic message contains an unused formatting placeholder
+  --> $DIR/panic-brace.rs:22:37
+   |
+LL |     fancy_panic::fancy_panic!("test {} 123");
+   |                                     ^^
+   |
+   = note: this message is not used as a format string when given without arguments, but will be in a future Rust edition
+
+warning: 8 warnings emitted
+
index 4b0f92456e0d19156411f3f2d1188ad64fd26cfa..f8368ff69008f02f5ea144e127d2e716db4d1843 100644 (file)
@@ -1,7 +1,6 @@
 // build-fail
 // compile-flags:-C panic=abort -C prefer-dynamic
 // ignore-musl - no dylibs here
-// ignore-cloudabi
 // ignore-emscripten
 // ignore-sgx no dynamic lib support
 // error-pattern:`panic_unwind` is not compiled with this crate's panic strategy
index 9c099911eab4d39e578eddf4ba65f02cd1daee48..566626513ef2dd2785261069bdcefcc07110fe7e 100644 (file)
@@ -3,7 +3,6 @@
 // compile-flags:-C panic=abort
 // aux-build:exit-success-if-unwind.rs
 // no-prefer-dynamic
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 // ignore-macos
index f625fe35d7205367eb7dfe749ba31c97aa54ecc5..dcc4061fde7a98da313856e3b22dc2c0ce388042 100644 (file)
@@ -2,7 +2,6 @@
 #![allow(unused_variables)]
 // compile-flags:-C panic=abort
 // no-prefer-dynamic
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 // ignore-macos
index 8fff71a629a49e00ff4afcf83d63c6ff5ff22518..5cc4c0132353274c0b366812f777976b144c644d 100644 (file)
@@ -2,7 +2,6 @@
 #![allow(unused_variables)]
 // compile-flags:-C lto -C panic=abort
 // no-prefer-dynamic
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
index 94a0b596e4a7114da6e971c7cfdace2b857ad092..6f39b76526b64aae9a63dbcd99e3468b2dee7394 100644 (file)
@@ -3,7 +3,6 @@
 
 // compile-flags:-C lto -C panic=unwind
 // no-prefer-dynamic
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
index c6e8dbf012cf3d42d6443ba7435e9f6cb80eb81a..f34cf6a9cbf6d91824c912c5acf4033b99891822 100644 (file)
@@ -5,7 +5,6 @@
 // Since we mark some ABIs as "nounwind" to LLVM, we must make sure that
 // we never unwind through them.
 
-// ignore-cloudabi no env and process
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
index 1e8c38cc3424b3db37ca8b5fa8a0e07b21405126..015ab8fdd80df6b234e034992bc574ba1b44c559 100644 (file)
@@ -7,7 +7,6 @@
 
 // ignore-msvc see #62897 and `backtrace-debuginfo.rs` test
 // ignore-android FIXME #17520
-// ignore-cloudabi spawning processes is not supported
 // ignore-openbsd no support for libbacktrace without filename
 // ignore-wasm no panic or subprocess support
 // ignore-emscripten no panic or subprocess support
index 99ee26fe55e331ccbdce41eb166d5c53e0e82c00..3287963890706af240bcce21e5597cbfbd8f0abd 100644 (file)
@@ -1,4 +1,4 @@
-thread 'main' panicked at 'explicit panic', $DIR/issue-47429-short-backtraces.rs:17:5
+thread 'main' panicked at 'explicit panic', $DIR/issue-47429-short-backtraces.rs:16:5
 stack backtrace:
    0: std::panicking::begin_panic
    1: issue_47429_short_backtraces::main
index c8d1769cb5a2a23f2bf7efcbb47b5612a96ceae9..ee35fded99ec971d799e25388f220fd7f76a331e 100644 (file)
@@ -39,13 +39,13 @@ LL | }
    | - item list ends here
 
 error: cannot find macro `default` in this scope
-  --> $DIR/default-unmatched-assoc.rs:12:5
+  --> $DIR/default-unmatched-assoc.rs:4:5
    |
 LL |     default!();
    |     ^^^^^^^
 
 error: cannot find macro `default` in this scope
-  --> $DIR/default-unmatched-assoc.rs:4:5
+  --> $DIR/default-unmatched-assoc.rs:12:5
    |
 LL |     default!();
    |     ^^^^^^^
index 4193b3ee695bcfd8ed1d4aba67057af38c5c9c46..2f11f95bf4a7fea6611f0158647f54e5aeff804f 100644 (file)
@@ -108,9 +108,12 @@ error: functions in `extern` blocks cannot have qualifiers
 LL |     extern {
    |     ------ in this `extern` block
 LL |         async fn fe1();
-   |         ---------^^^
-   |         |
-   |         help: remove the qualifiers: `fn`
+   |                  ^^^
+   |
+help: remove the qualifiers
+   |
+LL |         fn fe1();
+   |         ^^
 
 error: functions in `extern` blocks cannot have qualifiers
   --> $DIR/fn-header-semantic-fail.rs:52:19
@@ -119,9 +122,12 @@ LL |     extern {
    |     ------ in this `extern` block
 LL |         async fn fe1();
 LL |         unsafe fn fe2();
-   |         ----------^^^
-   |         |
-   |         help: remove the qualifiers: `fn`
+   |                   ^^^
+   |
+help: remove the qualifiers
+   |
+LL |         fn fe2();
+   |         ^^
 
 error: functions in `extern` blocks cannot have qualifiers
   --> $DIR/fn-header-semantic-fail.rs:53:18
@@ -130,9 +136,12 @@ LL |     extern {
    |     ------ in this `extern` block
 ...
 LL |         const fn fe3();
-   |         ---------^^^
-   |         |
-   |         help: remove the qualifiers: `fn`
+   |                  ^^^
+   |
+help: remove the qualifiers
+   |
+LL |         fn fe3();
+   |         ^^
 
 error: functions in `extern` blocks cannot have qualifiers
   --> $DIR/fn-header-semantic-fail.rs:54:23
@@ -141,9 +150,12 @@ LL |     extern {
    |     ------ in this `extern` block
 ...
 LL |         extern "C" fn fe4();
-   |         --------------^^^
-   |         |
-   |         help: remove the qualifiers: `fn`
+   |                       ^^^
+   |
+help: remove the qualifiers
+   |
+LL |         fn fe4();
+   |         ^^
 
 error: functions in `extern` blocks cannot have qualifiers
   --> $DIR/fn-header-semantic-fail.rs:55:42
@@ -152,9 +164,12 @@ LL |     extern {
    |     ------ in this `extern` block
 ...
 LL |         const async unsafe extern "C" fn fe5();
-   |         ---------------------------------^^^
-   |         |
-   |         help: remove the qualifiers: `fn`
+   |                                          ^^^
+   |
+help: remove the qualifiers
+   |
+LL |         fn fe5();
+   |         ^^
 
 error: functions cannot be both `const` and `async`
   --> $DIR/fn-header-semantic-fail.rs:55:9
index 33c8a9fa328ca2ee696ec3e88907f6f14c1f0069..4f866b78976612a1e0ebaba7f5efbc64ec4d614e 100644 (file)
@@ -5,7 +5,7 @@
 
 impl Foo {
     pub fn foo(_: i32, self: Box<Self) {}
-    //~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `)`
+    //~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `)`
 }
 
 fn main() {}
index 0844da1bd92a94150743c45dda5d5d48fe921cf4..a50ada9056b977560903f6e2c9ef7402fe78353a 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `)`
+error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `)`
   --> $DIR/issue-62660.rs:7:38
    |
 LL |     pub fn foo(_: i32, self: Box<Self) {}
-   |                                      ^ expected one of 7 possible tokens
+   |                                      ^ expected one of 9 possible tokens
 
 error: aborting due to previous error
 
index 80a450dbd36912aeb08858c428308af1e5670629..e249a93df92a2174b4ab221f7c07788560667f9f 100644 (file)
@@ -12,7 +12,7 @@ error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `;`
 LL | impl W <s(f;Y(;]
    |            ^ expected one of 7 possible tokens
 
-error: expected one of `!`, `&&`, `&`, `(`, `)`, `*`, `+`, `,`, `->`, `...`, `::`, `<`, `>`, `?`, `[`, `_`, `async`, `const`, `dyn`, `extern`, `fn`, `for`, `impl`, `unsafe`, lifetime, or path, found `;`
+error: expected one of `!`, `&&`, `&`, `(`, `)`, `*`, `+`, `,`, `->`, `...`, `::`, `:`, `<`, `=`, `>`, `?`, `[`, `_`, `async`, `const`, `dyn`, `extern`, `fn`, `for`, `impl`, `unsafe`, lifetime, or path, found `;`
   --> $DIR/issue-63116.rs:3:15
    |
 LL | impl W <s(f;Y(;]
index 40599d228b27ad187854892560cd0b03eaec30a2..16a08b9b85607cb582f410aded39dcac4dc4a275 100644 (file)
@@ -34,15 +34,15 @@ LL |     mac2! { does_not_exist!() }
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: cannot find macro `does_not_exist` in this scope
-  --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:20:13
+  --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:22:13
    |
-LL |     mac1! { does_not_exist!() }
+LL |     mac2! { does_not_exist!() }
    |             ^^^^^^^^^^^^^^
 
 error: cannot find macro `does_not_exist` in this scope
-  --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:22:13
+  --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:20:13
    |
-LL |     mac2! { does_not_exist!() }
+LL |     mac1! { does_not_exist!() }
    |             ^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
index 1f147216ea62efafe4937c5f66eef3b2a1ee9058..7cc14971f633f619a1c3f21c10126ee711fb5e6f 100644 (file)
@@ -3,6 +3,6 @@ struct Foo<'a, 'b> {
 }
 
 fn foo<'a, 'b>(x: &mut Foo<'a; 'b>) {}
-//~^ ERROR expected one of `,` or `>`, found `;`
+//~^ ERROR expected one of `,`, `:`, `=`, or `>`, found `;`
 
 fn main() {}
index 4641c286cb80821880ab34f3f2cbd9534b64d74c..3b67705aae9f2446e6dc088f9db14b8efc2debd1 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `,` or `>`, found `;`
+error: expected one of `,`, `:`, `=`, or `>`, found `;`
   --> $DIR/lifetime-semicolon.rs:5:30
    |
 LL | fn foo<'a, 'b>(x: &mut Foo<'a; 'b>) {}
-   |                              ^ expected one of `,` or `>`
+   |                              ^ expected one of `,`, `:`, `=`, or `>`
 
 error: aborting due to previous error
 
index de653987e406d772f8d01616539236b1183367bd..af92f2d94f2cc1003e1943588328eb87e022eaf7 100644 (file)
@@ -4,9 +4,12 @@ error: functions in `extern` blocks cannot have qualifiers
 LL | extern {
    | ------ in this `extern` block
 LL |     const fn foo();
-   |     ---------^^^
-   |     |
-   |     help: remove the qualifiers: `fn`
+   |              ^^^
+   |
+help: remove the qualifiers
+   |
+LL |     fn foo();
+   |     ^^
 
 error: functions in `extern` blocks cannot have qualifiers
   --> $DIR/no-const-fn-in-extern-block.rs:4:21
@@ -15,9 +18,12 @@ LL | extern {
    | ------ in this `extern` block
 ...
 LL |     const unsafe fn bar();
-   |     ----------------^^^
-   |     |
-   |     help: remove the qualifiers: `fn`
+   |                     ^^^
+   |
+help: remove the qualifiers
+   |
+LL |     fn bar();
+   |     ^^
 
 error: aborting due to 2 previous errors
 
index ceac94080062d0b6a459a5d8287ce4e4eba61d73..e807a179473c4ecd2ebb63a53123d0d6f36fb42f 100644 (file)
@@ -1,2 +1,2 @@
 type closure = Box<lt/fn()>;
-//~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `/`
+//~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `/`
index a100f689fb8d2c75a18cb9ac3c533d53bc7e4b64..63b6e138ce5f6cc29a9244d81f77138b8f4fcb45 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `/`
+error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `/`
   --> $DIR/removed-syntax-closure-lifetime.rs:1:22
    |
 LL | type closure = Box<lt/fn()>;
-   |                      ^ expected one of 7 possible tokens
+   |                      ^ expected one of 9 possible tokens
 
 error: aborting due to previous error
 
index 0a2836d691f5f03154e7199ce16e5e99b5ecebe3..8e267c7448feb4bccdbfd6ece54b48355524d36a 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 #![feature(negative_impls)]
 #![allow(bare_trait_objects)]
 
index e9510b53feab8686322262366a7b67ed9721f8ef..cb40c4f6fbf91a2649601336e947b54e0418b0eb 100644 (file)
@@ -1,7 +1,6 @@
 // run-pass
 
 #![allow(deprecated)]
-// ignore-cloudabi no files or I/O
 // ignore-wasm32-bare no files or I/O
 // ignore-emscripten no files
 // ignore-sgx no files
diff --git a/src/test/ui/pattern/const-pat-ice.rs b/src/test/ui/pattern/const-pat-ice.rs
deleted file mode 100644 (file)
index abfacf3..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// check-pass
-
-const FOO: &&&u32 = &&&42;
-
-fn main() {
-    match unimplemented!() {
-        &&&42 => {},
-        FOO => {},
-        _ => {},
-    }
-}
diff --git a/src/test/ui/pattern/deny-irrefutable-let-patterns.rs b/src/test/ui/pattern/deny-irrefutable-let-patterns.rs
deleted file mode 100644 (file)
index 14040c8..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#![deny(irrefutable_let_patterns)]
-
-fn main() {
-    if let _ = 5 {} //~ ERROR irrefutable if-let pattern
-
-    while let _ = 5 { //~ ERROR irrefutable while-let pattern
-        break;
-    }
-}
diff --git a/src/test/ui/pattern/deny-irrefutable-let-patterns.stderr b/src/test/ui/pattern/deny-irrefutable-let-patterns.stderr
deleted file mode 100644 (file)
index 308a6c7..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-error: irrefutable if-let pattern
-  --> $DIR/deny-irrefutable-let-patterns.rs:4:5
-   |
-LL |     if let _ = 5 {}
-   |     ^^^^^^^^^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/deny-irrefutable-let-patterns.rs:1:9
-   |
-LL | #![deny(irrefutable_let_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: irrefutable while-let pattern
-  --> $DIR/deny-irrefutable-let-patterns.rs:6:5
-   |
-LL | /     while let _ = 5 {
-LL | |         break;
-LL | |     }
-   | |_____^
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/pattern/integer-range-binding.rs b/src/test/ui/pattern/integer-range-binding.rs
new file mode 100644 (file)
index 0000000..ff06588
--- /dev/null
@@ -0,0 +1,8 @@
+// run-pass
+
+fn main() {
+    let -2147483648..=2147483647 = 1;
+    let 0..=255 = 0u8;
+    let -128..=127 = 0i8;
+    let '\u{0000}'..='\u{10FFFF}' = 'v';
+}
diff --git a/src/test/ui/pattern/irrefutable-let-patterns.rs b/src/test/ui/pattern/irrefutable-let-patterns.rs
deleted file mode 100644 (file)
index d400ef0..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// run-pass
-
-#![allow(irrefutable_let_patterns)]
-
-fn main() {
-    if let _ = 5 {}
-
-    while let _ = 5 {
-        break;
-    }
-}
diff --git a/src/test/ui/pattern/issue-66501.rs b/src/test/ui/pattern/issue-66501.rs
deleted file mode 100644 (file)
index ffcfd4a..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// check-pass
-
-#![allow(unreachable_patterns)]
-
-fn main() {
-    const CONST: &[Option<()>; 1] = &[Some(())];
-    match &[Some(())] {
-        &[None] => {}
-        CONST => {}
-        &[Some(())] => {}
-    }
-}
diff --git a/src/test/ui/pattern/usefulness/const-pat-ice.rs b/src/test/ui/pattern/usefulness/const-pat-ice.rs
new file mode 100644 (file)
index 0000000..abfacf3
--- /dev/null
@@ -0,0 +1,11 @@
+// check-pass
+
+const FOO: &&&u32 = &&&42;
+
+fn main() {
+    match unimplemented!() {
+        &&&42 => {},
+        FOO => {},
+        _ => {},
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.rs b/src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.rs
new file mode 100644 (file)
index 0000000..14040c8
--- /dev/null
@@ -0,0 +1,9 @@
+#![deny(irrefutable_let_patterns)]
+
+fn main() {
+    if let _ = 5 {} //~ ERROR irrefutable if-let pattern
+
+    while let _ = 5 { //~ ERROR irrefutable while-let pattern
+        break;
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr b/src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr
new file mode 100644 (file)
index 0000000..308a6c7
--- /dev/null
@@ -0,0 +1,22 @@
+error: irrefutable if-let pattern
+  --> $DIR/deny-irrefutable-let-patterns.rs:4:5
+   |
+LL |     if let _ = 5 {}
+   |     ^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/deny-irrefutable-let-patterns.rs:1:9
+   |
+LL | #![deny(irrefutable_let_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: irrefutable while-let pattern
+  --> $DIR/deny-irrefutable-let-patterns.rs:6:5
+   |
+LL | /     while let _ = 5 {
+LL | |         break;
+LL | |     }
+   | |_____^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.rs b/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.rs
deleted file mode 100644 (file)
index 78cc0d2..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-#![feature(precise_pointer_size_matching)]
-#![feature(exclusive_range_pattern)]
-#![deny(unreachable_patterns)]
-#![deny(overlapping_patterns)]
-
-use std::{char, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128};
-
-fn main() {
-    let x: u8 = 0;
-
-    // A single range covering the entire domain.
-    match x {
-        0 ..= 255 => {} // ok
-    }
-
-    // A combination of ranges and values.
-    // These are currently allowed to be overlapping.
-    match x {
-        0 ..= 32 => {}
-        33 => {}
-        34 .. 128 => {}
-        100 ..= 200 => {}
-        200 => {} //~ ERROR unreachable pattern
-        201 ..= 255 => {}
-    }
-
-    // An incomplete set of values.
-    match x { //~ ERROR non-exhaustive patterns
-        0 .. 128 => {}
-    }
-
-    // A more incomplete set of values.
-    match x { //~ ERROR non-exhaustive patterns
-        0 ..= 10 => {}
-        20 ..= 30 => {}
-        35 => {}
-        70 .. 255 => {}
-    }
-
-    let x: i8 = 0;
-    match x { //~ ERROR non-exhaustive patterns
-        -7 => {}
-        -5..=120 => {}
-        -2..=20 => {}
-        //~^ ERROR unreachable pattern
-        125 => {}
-    }
-
-    // Let's test other types too!
-    let c: char = '\u{0}';
-    match c {
-        '\u{0}' ..= char::MAX => {} // ok
-    }
-
-    // We can actually get away with just covering the
-    // following two ranges, which correspond to all
-    // valid Unicode Scalar Values.
-    match c {
-        '\u{0000}' ..= '\u{D7FF}' => {}
-        '\u{E000}' ..= '\u{10_FFFF}' => {}
-    }
-
-    match 0u16 {
-        0 ..= u16::MAX => {} // ok
-    }
-
-    match 0u32 {
-        0 ..= u32::MAX => {} // ok
-    }
-
-    match 0u64 {
-        0 ..= u64::MAX => {} // ok
-    }
-
-    match 0u128 {
-        0 ..= u128::MAX => {} // ok
-    }
-
-    match 0i8 {
-        -128 ..= 127 => {} // ok
-    }
-
-    match 0i8 { //~ ERROR non-exhaustive patterns
-        -127 ..= 127 => {}
-    }
-
-    match 0i16 {
-        i16::MIN ..= i16::MAX => {} // ok
-    }
-
-    match 0i16 { //~ ERROR non-exhaustive patterns
-        i16::MIN ..= -1 => {}
-        1 ..= i16::MAX => {}
-    }
-
-    match 0i32 {
-        i32::MIN ..= i32::MAX => {} // ok
-    }
-
-    match 0i64 {
-        i64::MIN ..= i64::MAX => {} // ok
-    }
-
-    match 0i128 {
-        i128::MIN ..= i128::MAX => {} // ok
-    }
-
-    // Make sure that guards don't factor into the exhaustiveness checks.
-    match 0u8 { //~ ERROR non-exhaustive patterns
-        0 .. 128 => {}
-        128 ..= 255 if true => {}
-    }
-
-    match 0u8 {
-        0 .. 128 => {}
-        128 ..= 255 if false => {}
-        128 ..= 255 => {} // ok, because previous arm was guarded
-    }
-
-    // Now things start getting a bit more interesting. Testing products!
-    match (0u8, Some(())) { //~ ERROR non-exhaustive patterns
-        (1, _) => {}
-        (_, None) => {}
-    }
-
-    match (0u8, true) { //~ ERROR non-exhaustive patterns
-        (0 ..= 125, false) => {}
-        (128 ..= 255, false) => {}
-        (0 ..= 255, true) => {}
-    }
-
-    match (0u8, true) { // ok
-        (0 ..= 125, false) => {}
-        (128 ..= 255, false) => {}
-        (0 ..= 255, true) => {}
-        (125 .. 128, false) => {}
-    }
-
-    match 0u8 {
-        0 .. 2 => {}
-        1 ..= 2 => {} //~ ERROR multiple patterns covering the same range
-        _ => {}
-    }
-
-    const LIM: u128 = u128::MAX - 1;
-    match 0u128 { //~ ERROR non-exhaustive patterns
-        0 ..= LIM => {}
-    }
-
-    match 0u128 { //~ ERROR non-exhaustive patterns
-        0 ..= 4 => {}
-    }
-
-    match 0u128 { //~ ERROR non-exhaustive patterns
-        4 ..= u128::MAX => {}
-    }
-
-    const FOO: i32 = 42;
-    const BAR: &i32 = &42;
-    match &0 {
-        &42 => {}
-        &FOO => {} //~ ERROR unreachable pattern
-        BAR => {} //~ ERROR unreachable pattern
-        _ => {}
-    }
-
-    // Regression test, see https://github.com/rust-lang/rust/pull/66326#issuecomment-552889933
-    match &0 {
-        BAR => {} // ok
-        _ => {}
-    }
-}
diff --git a/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.stderr b/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.stderr
deleted file mode 100644 (file)
index 9f076c5..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-error: unreachable pattern
-  --> $DIR/exhaustive_integer_patterns.rs:23:9
-   |
-LL |         200 => {}
-   |         ^^^
-   |
-note: the lint level is defined here
-  --> $DIR/exhaustive_integer_patterns.rs:3:9
-   |
-LL | #![deny(unreachable_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error[E0004]: non-exhaustive patterns: `128_u8..=u8::MAX` not covered
-  --> $DIR/exhaustive_integer_patterns.rs:28:11
-   |
-LL |     match x {
-   |           ^ pattern `128_u8..=u8::MAX` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `u8`
-
-error[E0004]: non-exhaustive patterns: `11_u8..=19_u8`, `31_u8..=34_u8`, `36_u8..=69_u8` and 1 more not covered
-  --> $DIR/exhaustive_integer_patterns.rs:33:11
-   |
-LL |     match x {
-   |           ^ patterns `11_u8..=19_u8`, `31_u8..=34_u8`, `36_u8..=69_u8` and 1 more not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `u8`
-
-error: unreachable pattern
-  --> $DIR/exhaustive_integer_patterns.rs:44:9
-   |
-LL |         -2..=20 => {}
-   |         ^^^^^^^
-
-error[E0004]: non-exhaustive patterns: `i8::MIN..=-8_i8`, `-6_i8`, `121_i8..=124_i8` and 1 more not covered
-  --> $DIR/exhaustive_integer_patterns.rs:41:11
-   |
-LL |     match x {
-   |           ^ patterns `i8::MIN..=-8_i8`, `-6_i8`, `121_i8..=124_i8` and 1 more not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `i8`
-
-error[E0004]: non-exhaustive patterns: `i8::MIN` not covered
-  --> $DIR/exhaustive_integer_patterns.rs:83:11
-   |
-LL |     match 0i8 {
-   |           ^^^ pattern `i8::MIN` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `i8`
-
-error[E0004]: non-exhaustive patterns: `0_i16` not covered
-  --> $DIR/exhaustive_integer_patterns.rs:91:11
-   |
-LL |     match 0i16 {
-   |           ^^^^ pattern `0_i16` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `i16`
-
-error[E0004]: non-exhaustive patterns: `128_u8..=u8::MAX` not covered
-  --> $DIR/exhaustive_integer_patterns.rs:109:11
-   |
-LL |     match 0u8 {
-   |           ^^^ pattern `128_u8..=u8::MAX` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `u8`
-
-error[E0004]: non-exhaustive patterns: `(0_u8, Some(_))` and `(2_u8..=u8::MAX, Some(_))` not covered
-  --> $DIR/exhaustive_integer_patterns.rs:121:11
-   |
-LL |     match (0u8, Some(())) {
-   |           ^^^^^^^^^^^^^^^ patterns `(0_u8, Some(_))` and `(2_u8..=u8::MAX, Some(_))` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `(u8, Option<()>)`
-
-error[E0004]: non-exhaustive patterns: `(126_u8..=127_u8, false)` not covered
-  --> $DIR/exhaustive_integer_patterns.rs:126:11
-   |
-LL |     match (0u8, true) {
-   |           ^^^^^^^^^^^ pattern `(126_u8..=127_u8, false)` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `(u8, bool)`
-
-error: multiple patterns covering the same range
-  --> $DIR/exhaustive_integer_patterns.rs:141:9
-   |
-LL |         0 .. 2 => {}
-   |         ------ this range overlaps on `1_u8`
-LL |         1 ..= 2 => {}
-   |         ^^^^^^^ overlapping patterns
-   |
-note: the lint level is defined here
-  --> $DIR/exhaustive_integer_patterns.rs:4:9
-   |
-LL | #![deny(overlapping_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error[E0004]: non-exhaustive patterns: `u128::MAX` not covered
-  --> $DIR/exhaustive_integer_patterns.rs:146:11
-   |
-LL |     match 0u128 {
-   |           ^^^^^ pattern `u128::MAX` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `u128`
-
-error[E0004]: non-exhaustive patterns: `5_u128..=u128::MAX` not covered
-  --> $DIR/exhaustive_integer_patterns.rs:150:11
-   |
-LL |     match 0u128 {
-   |           ^^^^^ pattern `5_u128..=u128::MAX` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `u128`
-
-error[E0004]: non-exhaustive patterns: `0_u128..=3_u128` not covered
-  --> $DIR/exhaustive_integer_patterns.rs:154:11
-   |
-LL |     match 0u128 {
-   |           ^^^^^ pattern `0_u128..=3_u128` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `u128`
-
-error: unreachable pattern
-  --> $DIR/exhaustive_integer_patterns.rs:162:9
-   |
-LL |         &FOO => {}
-   |         ^^^^
-
-error: unreachable pattern
-  --> $DIR/exhaustive_integer_patterns.rs:163:9
-   |
-LL |         BAR => {}
-   |         ^^^
-
-error: aborting due to 16 previous errors
-
-For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/floats.rs b/src/test/ui/pattern/usefulness/floats.rs
new file mode 100644 (file)
index 0000000..095f5ac
--- /dev/null
@@ -0,0 +1,19 @@
+#![allow(illegal_floating_point_literal_pattern)]
+#![deny(unreachable_patterns)]
+
+fn main() {
+    match 0.0 {
+      0.0..=1.0 => {}
+      _ => {} // ok
+    }
+
+    match 0.0 { //~ ERROR non-exhaustive patterns
+      0.0..=1.0 => {}
+    }
+
+    match 1.0f64 {
+      0.01f64 ..= 6.5f64 => {}
+      0.02f64 => {} //~ ERROR unreachable pattern
+      _ => {}
+    };
+}
diff --git a/src/test/ui/pattern/usefulness/floats.stderr b/src/test/ui/pattern/usefulness/floats.stderr
new file mode 100644 (file)
index 0000000..464bfbd
--- /dev/null
@@ -0,0 +1,24 @@
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/floats.rs:10:11
+   |
+LL |     match 0.0 {
+   |           ^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `f64`
+
+error: unreachable pattern
+  --> $DIR/floats.rs:16:7
+   |
+LL |       0.02f64 => {}
+   |       ^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/floats.rs:2:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/guards-not-exhaustive.rs b/src/test/ui/pattern/usefulness/guards-not-exhaustive.rs
deleted file mode 100644 (file)
index b74f162..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// run-pass
-
-#![allow(non_snake_case)]
-
-#[derive(Copy, Clone)]
-enum Q { R(Option<usize>) }
-
-fn xyzzy(q: Q) -> usize {
-    match q {
-        Q::R(S) if S.is_some() => { 0 }
-        _ => 1
-    }
-}
-
-
-pub fn main() {
-    assert_eq!(xyzzy(Q::R(Some(5))), 0);
-}
diff --git a/src/test/ui/pattern/usefulness/guards.rs b/src/test/ui/pattern/usefulness/guards.rs
new file mode 100644 (file)
index 0000000..b15440c
--- /dev/null
@@ -0,0 +1,22 @@
+#![feature(exclusive_range_pattern)]
+#![deny(unreachable_patterns)]
+
+enum Q { R(Option<usize>) }
+
+pub fn main() {
+    match Q::R(None) {
+        Q::R(S) if S.is_some() => {}
+        _ => {}
+    }
+
+    match 0u8 { //~ ERROR non-exhaustive patterns
+        0 .. 128 => {}
+        128 ..= 255 if true => {}
+    }
+
+    match 0u8 {
+        0 .. 128 => {}
+        128 ..= 255 if false => {}
+        128 ..= 255 => {} // ok, because previous arm was guarded
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/guards.stderr b/src/test/ui/pattern/usefulness/guards.stderr
new file mode 100644 (file)
index 0000000..61f7fac
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0004]: non-exhaustive patterns: `128_u8..=u8::MAX` not covered
+  --> $DIR/guards.rs:12:11
+   |
+LL |     match 0u8 {
+   |           ^^^ pattern `128_u8..=u8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `u8`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs b/src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs
new file mode 100644 (file)
index 0000000..5a44dfc
--- /dev/null
@@ -0,0 +1,101 @@
+#![feature(exclusive_range_pattern)]
+#![feature(assoc_char_consts)]
+#![deny(unreachable_patterns)]
+
+macro_rules! m {
+    ($s:expr, $($t:tt)+) => {
+        match $s { $($t)+ => {} }
+    }
+}
+
+macro_rules! test_int {
+    ($s:expr, $min:path, $max:path) => {
+        m!($s, $min..=$max);
+        m!($s, $min..5 | 5..=$max);
+        m!($s, $min..=4 | 5..=$max);
+        m!($s, $min..$max | $max);
+        m!(($s, true), ($min..5, true) | (5..=$max, true) | ($min..=$max, false));
+    }
+}
+
+fn main() {
+    test_int!(0u8, u8::MIN, u8::MAX);
+    test_int!(0u16, u16::MIN, u16::MAX);
+    test_int!(0u32, u32::MIN, u32::MAX);
+    test_int!(0u64, u64::MIN, u64::MAX);
+    test_int!(0u128, u128::MIN, u128::MAX);
+
+    test_int!(0i8, i8::MIN, i8::MAX);
+    test_int!(0i16, i16::MIN, i16::MAX);
+    test_int!(0i32, i32::MIN, i32::MAX);
+    test_int!(0i64, i64::MIN, i64::MAX);
+    test_int!(0i128, i128::MIN, i128::MAX);
+
+    m!('a', '\u{0}'..=char::MAX);
+    m!('a', '\u{0}'..='\u{10_FFFF}');
+    // We can get away with just covering the following two ranges, which correspond to all valid
+    // Unicode Scalar Values.
+    m!('a', '\u{0}'..='\u{D7FF}' | '\u{E000}'..=char::MAX);
+    m!('a', '\u{0}'..'\u{D7FF}' | '\u{D7FF}' | '\u{E000}'..=char::MAX);
+
+    let 0..=255 = 0u8;
+    let -128..=127 = 0i8;
+    let -2147483648..=2147483647 = 0i32;
+    let '\u{0000}'..='\u{10FFFF}' = 'v';
+
+    // Almost exhaustive
+    m!(0u8, 0..255); //~ ERROR non-exhaustive patterns
+    m!(0u8, 0..=254); //~ ERROR non-exhaustive patterns
+    m!(0u8, 1..=255); //~ ERROR non-exhaustive patterns
+    m!(0u8, 0..42 | 43..=255); //~ ERROR non-exhaustive patterns
+    m!(0i8, -128..127); //~ ERROR non-exhaustive patterns
+    m!(0i8, -128..=126); //~ ERROR non-exhaustive patterns
+    m!(0i8, -127..=127); //~ ERROR non-exhaustive patterns
+    match 0i8 { //~ ERROR non-exhaustive patterns
+        i8::MIN ..= -1 => {}
+        1 ..= i8::MAX => {}
+    }
+    const ALMOST_MAX: u128 = u128::MAX - 1;
+    m!(0u128, 0..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+    m!(0u128, 0..=4); //~ ERROR non-exhaustive patterns
+    m!(0u128, 1..=u128::MAX); //~ ERROR non-exhaustive patterns
+
+    // More complicatedly (non-)exhaustive
+    match 0u8 {
+        0 ..= 30 => {}
+        20 ..= 70 => {}
+        50 ..= 255 => {}
+    }
+    match (0u8, true) { //~ ERROR non-exhaustive patterns
+        (0 ..= 125, false) => {}
+        (128 ..= 255, false) => {}
+        (0 ..= 255, true) => {}
+    }
+    match (0u8, true) { // ok
+        (0 ..= 125, false) => {}
+        (128 ..= 255, false) => {}
+        (0 ..= 255, true) => {}
+        (125 .. 128, false) => {}
+    }
+    match (true, 0u8) {
+        (true, 0 ..= 255) => {}
+        (false, 0 ..= 125) => {}
+        (false, 128 ..= 255) => {}
+        (false, 125 .. 128) => {}
+    }
+    match Some(0u8) {
+        None => {}
+        Some(0 ..= 125) => {}
+        Some(128 ..= 255) => {}
+        Some(125 .. 128) => {}
+    }
+    const FOO: u8 = 41;
+    const BAR: &u8 = &42;
+    match &0u8 {
+        0..41 => {}
+        &FOO => {}
+        BAR => {}
+        43..=255 => {}
+    }
+
+}
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr b/src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr
new file mode 100644 (file)
index 0000000..2e00233
--- /dev/null
@@ -0,0 +1,111 @@
+error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
+  --> $DIR/exhaustiveness.rs:47:8
+   |
+LL |     m!(0u8, 0..255);
+   |        ^^^ pattern `u8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `u8`
+
+error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
+  --> $DIR/exhaustiveness.rs:48:8
+   |
+LL |     m!(0u8, 0..=254);
+   |        ^^^ pattern `u8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `u8`
+
+error[E0004]: non-exhaustive patterns: `0_u8` not covered
+  --> $DIR/exhaustiveness.rs:49:8
+   |
+LL |     m!(0u8, 1..=255);
+   |        ^^^ pattern `0_u8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `u8`
+
+error[E0004]: non-exhaustive patterns: `42_u8` not covered
+  --> $DIR/exhaustiveness.rs:50:8
+   |
+LL |     m!(0u8, 0..42 | 43..=255);
+   |        ^^^ pattern `42_u8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `u8`
+
+error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
+  --> $DIR/exhaustiveness.rs:51:8
+   |
+LL |     m!(0i8, -128..127);
+   |        ^^^ pattern `i8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `i8`
+
+error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
+  --> $DIR/exhaustiveness.rs:52:8
+   |
+LL |     m!(0i8, -128..=126);
+   |        ^^^ pattern `i8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `i8`
+
+error[E0004]: non-exhaustive patterns: `i8::MIN` not covered
+  --> $DIR/exhaustiveness.rs:53:8
+   |
+LL |     m!(0i8, -127..=127);
+   |        ^^^ pattern `i8::MIN` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `i8`
+
+error[E0004]: non-exhaustive patterns: `0_i8` not covered
+  --> $DIR/exhaustiveness.rs:54:11
+   |
+LL |     match 0i8 {
+   |           ^^^ pattern `0_i8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `i8`
+
+error[E0004]: non-exhaustive patterns: `u128::MAX` not covered
+  --> $DIR/exhaustiveness.rs:59:8
+   |
+LL |     m!(0u128, 0..=ALMOST_MAX);
+   |        ^^^^^ pattern `u128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `u128`
+
+error[E0004]: non-exhaustive patterns: `5_u128..=u128::MAX` not covered
+  --> $DIR/exhaustiveness.rs:60:8
+   |
+LL |     m!(0u128, 0..=4);
+   |        ^^^^^ pattern `5_u128..=u128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `u128`
+
+error[E0004]: non-exhaustive patterns: `0_u128` not covered
+  --> $DIR/exhaustiveness.rs:61:8
+   |
+LL |     m!(0u128, 1..=u128::MAX);
+   |        ^^^^^ pattern `0_u128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `u128`
+
+error[E0004]: non-exhaustive patterns: `(126_u8..=127_u8, false)` not covered
+  --> $DIR/exhaustiveness.rs:69:11
+   |
+LL |     match (0u8, true) {
+   |           ^^^^^^^^^^^ pattern `(126_u8..=127_u8, false)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `(u8, bool)`
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs b/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs
new file mode 100644 (file)
index 0000000..af720a0
--- /dev/null
@@ -0,0 +1,53 @@
+#![feature(exclusive_range_pattern)]
+#![deny(overlapping_patterns)]
+
+macro_rules! m {
+    ($s:expr, $t1:pat, $t2:pat) => {
+        match $s {
+            $t1 => {}
+            $t2 => {}
+            _ => {}
+        }
+    }
+}
+
+fn main() {
+    m!(0u8, 20..=30, 30..=40); //~ ERROR multiple patterns covering the same range
+    m!(0u8, 30..=40, 20..=30); //~ ERROR multiple patterns covering the same range
+    m!(0u8, 20..=30, 31..=40);
+    m!(0u8, 20..=30, 29..=40);
+    m!(0u8, 20.. 30, 29..=40); //~ ERROR multiple patterns covering the same range
+    m!(0u8, 20.. 30, 28..=40);
+    m!(0u8, 20.. 30, 30..=40);
+    m!(0u8, 20..=30, 30..=30);
+    m!(0u8, 20..=30, 30..=31); //~ ERROR multiple patterns covering the same range
+    m!(0u8, 20..=30, 29..=30);
+    m!(0u8, 20..=30, 20..=20);
+    m!(0u8, 20..=30, 20..=21);
+    m!(0u8, 20..=30, 19..=20); //~ ERROR multiple patterns covering the same range
+    m!(0u8, 20..=30, 20);
+    m!(0u8, 20..=30, 25);
+    m!(0u8, 20..=30, 30);
+    m!(0u8, 20.. 30, 29);
+    m!(0u8, 20, 20..=30); //~ ERROR multiple patterns covering the same range
+    m!(0u8, 25, 20..=30);
+    m!(0u8, 30, 20..=30); //~ ERROR multiple patterns covering the same range
+
+    match (0u8, true) {
+        (0..=10, true) => {}
+        (10..20, true) => {} // not detected
+        (10..20, false) => {}
+        _ => {}
+    }
+    match (true, 0u8) {
+        (true, 0..=10) => {}
+        (true, 10..20) => {} //~ ERROR multiple patterns covering the same range
+        (false, 10..20) => {}
+        _ => {}
+    }
+    match Some(0u8) {
+        Some(0..=10) => {}
+        Some(10..20) => {} //~ ERROR multiple patterns covering the same range
+        _ => {}
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr b/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr
new file mode 100644 (file)
index 0000000..7bb747c
--- /dev/null
@@ -0,0 +1,80 @@
+error: multiple patterns covering the same range
+  --> $DIR/overlapping_range_endpoints.rs:15:22
+   |
+LL |     m!(0u8, 20..=30, 30..=40);
+   |             -------  ^^^^^^^ overlapping patterns
+   |             |
+   |             this range overlaps on `30_u8`
+   |
+note: the lint level is defined here
+  --> $DIR/overlapping_range_endpoints.rs:2:9
+   |
+LL | #![deny(overlapping_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: multiple patterns covering the same range
+  --> $DIR/overlapping_range_endpoints.rs:16:22
+   |
+LL |     m!(0u8, 30..=40, 20..=30);
+   |             -------  ^^^^^^^ overlapping patterns
+   |             |
+   |             this range overlaps on `30_u8`
+
+error: multiple patterns covering the same range
+  --> $DIR/overlapping_range_endpoints.rs:19:22
+   |
+LL |     m!(0u8, 20.. 30, 29..=40);
+   |             -------  ^^^^^^^ overlapping patterns
+   |             |
+   |             this range overlaps on `29_u8`
+
+error: multiple patterns covering the same range
+  --> $DIR/overlapping_range_endpoints.rs:23:22
+   |
+LL |     m!(0u8, 20..=30, 30..=31);
+   |             -------  ^^^^^^^ overlapping patterns
+   |             |
+   |             this range overlaps on `30_u8`
+
+error: multiple patterns covering the same range
+  --> $DIR/overlapping_range_endpoints.rs:27:22
+   |
+LL |     m!(0u8, 20..=30, 19..=20);
+   |             -------  ^^^^^^^ overlapping patterns
+   |             |
+   |             this range overlaps on `20_u8`
+
+error: multiple patterns covering the same range
+  --> $DIR/overlapping_range_endpoints.rs:32:17
+   |
+LL |     m!(0u8, 20, 20..=30);
+   |             --  ^^^^^^^ overlapping patterns
+   |             |
+   |             this range overlaps on `20_u8`
+
+error: multiple patterns covering the same range
+  --> $DIR/overlapping_range_endpoints.rs:34:17
+   |
+LL |     m!(0u8, 30, 20..=30);
+   |             --  ^^^^^^^ overlapping patterns
+   |             |
+   |             this range overlaps on `30_u8`
+
+error: multiple patterns covering the same range
+  --> $DIR/overlapping_range_endpoints.rs:44:16
+   |
+LL |         (true, 0..=10) => {}
+   |                ------ this range overlaps on `10_u8`
+LL |         (true, 10..20) => {}
+   |                ^^^^^^ overlapping patterns
+
+error: multiple patterns covering the same range
+  --> $DIR/overlapping_range_endpoints.rs:50:14
+   |
+LL |         Some(0..=10) => {}
+   |              ------ this range overlaps on `10_u8`
+LL |         Some(10..20) => {}
+   |              ^^^^^^ overlapping patterns
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-allow.rs b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-allow.rs
new file mode 100644 (file)
index 0000000..6173053
--- /dev/null
@@ -0,0 +1,38 @@
+#![feature(precise_pointer_size_matching)]
+#![feature(exclusive_range_pattern)]
+
+macro_rules! m {
+    ($s:expr, $($t:tt)+) => {
+        match $s { $($t)+ => {} }
+    }
+}
+
+fn main() {
+    match 0usize {
+        0 ..= usize::MAX => {}
+    }
+
+    match 0isize {
+        isize::MIN ..= isize::MAX => {}
+    }
+
+    m!(0usize, 0..=usize::MAX);
+    m!(0usize, 0..5 | 5..=usize::MAX);
+    m!(0usize, 0..usize::MAX | usize::MAX);
+    m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false));
+
+    m!(0isize, isize::MIN..=isize::MAX);
+    m!(0isize, isize::MIN..5 | 5..=isize::MAX);
+    m!(0isize, isize::MIN..isize::MAX | isize::MAX);
+    m!((0isize, true), (isize::MIN..5, true)
+        | (5..=isize::MAX, true) | (isize::MIN..=isize::MAX, false));
+
+    match 0isize {
+        isize::MIN ..= -1 => {}
+        0 => {}
+        1 ..= isize::MAX => {}
+    }
+
+    match 7usize {}
+    //~^ ERROR non-exhaustive patterns
+}
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-allow.stderr b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-allow.stderr
new file mode 100644 (file)
index 0000000..0b3c651
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0004]: non-exhaustive patterns: type `usize` is non-empty
+  --> $DIR/pointer-sized-int-allow.rs:36:11
+   |
+LL |     match 7usize {}
+   |           ^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `usize`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-deny.rs b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-deny.rs
new file mode 100644 (file)
index 0000000..9292f22
--- /dev/null
@@ -0,0 +1,48 @@
+#![feature(exclusive_range_pattern)]
+
+macro_rules! m {
+    ($s:expr, $($t:tt)+) => {
+        match $s { $($t)+ => {} }
+    }
+}
+
+fn main() {
+    match 0usize {
+        //~^ ERROR non-exhaustive patterns
+        0 ..= usize::MAX => {}
+    }
+
+    match 0isize {
+        //~^ ERROR non-exhaustive patterns
+        isize::MIN ..= isize::MAX => {}
+    }
+
+    m!(0usize, 0..=usize::MAX);
+    //~^ ERROR non-exhaustive patterns
+    m!(0usize, 0..5 | 5..=usize::MAX);
+    //~^ ERROR non-exhaustive patterns
+    m!(0usize, 0..usize::MAX | usize::MAX);
+    //~^ ERROR non-exhaustive patterns
+    m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false));
+    //~^ ERROR non-exhaustive patterns
+
+    m!(0isize, isize::MIN..=isize::MAX);
+    //~^ ERROR non-exhaustive patterns
+    m!(0isize, isize::MIN..5 | 5..=isize::MAX);
+    //~^ ERROR non-exhaustive patterns
+    m!(0isize, isize::MIN..isize::MAX | isize::MAX);
+    //~^ ERROR non-exhaustive patterns
+    m!((0isize, true), (isize::MIN..5, true)
+        | (5..=isize::MAX, true) | (isize::MIN..=isize::MAX, false));
+    //~^^ ERROR non-exhaustive patterns
+
+    match 0isize {
+        //~^ ERROR non-exhaustive patterns
+        isize::MIN ..= -1 => {}
+        0 => {}
+        1 ..= isize::MAX => {}
+    }
+
+    match 7usize {}
+    //~^ ERROR non-exhaustive patterns
+}
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-deny.stderr b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-deny.stderr
new file mode 100644 (file)
index 0000000..9d566b0
--- /dev/null
@@ -0,0 +1,129 @@
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/pointer-sized-int-deny.rs:10:11
+   |
+LL |     match 0usize {
+   |           ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `usize`
+   = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+   = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/pointer-sized-int-deny.rs:15:11
+   |
+LL |     match 0isize {
+   |           ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `isize`
+   = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+   = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/pointer-sized-int-deny.rs:20:8
+   |
+LL |     m!(0usize, 0..=usize::MAX);
+   |        ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `usize`
+   = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+   = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/pointer-sized-int-deny.rs:22:8
+   |
+LL |     m!(0usize, 0..5 | 5..=usize::MAX);
+   |        ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `usize`
+   = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+   = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/pointer-sized-int-deny.rs:24:8
+   |
+LL |     m!(0usize, 0..usize::MAX | usize::MAX);
+   |        ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `usize`
+   = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+   = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
+
+error[E0004]: non-exhaustive patterns: `(_, _)` not covered
+  --> $DIR/pointer-sized-int-deny.rs:26:8
+   |
+LL |     m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false));
+   |        ^^^^^^^^^^^^^^ pattern `(_, _)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `(usize, bool)`
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/pointer-sized-int-deny.rs:29:8
+   |
+LL |     m!(0isize, isize::MIN..=isize::MAX);
+   |        ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `isize`
+   = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+   = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/pointer-sized-int-deny.rs:31:8
+   |
+LL |     m!(0isize, isize::MIN..5 | 5..=isize::MAX);
+   |        ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `isize`
+   = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+   = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/pointer-sized-int-deny.rs:33:8
+   |
+LL |     m!(0isize, isize::MIN..isize::MAX | isize::MAX);
+   |        ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `isize`
+   = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+   = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
+
+error[E0004]: non-exhaustive patterns: `(_, _)` not covered
+  --> $DIR/pointer-sized-int-deny.rs:35:8
+   |
+LL |     m!((0isize, true), (isize::MIN..5, true)
+   |        ^^^^^^^^^^^^^^ pattern `(_, _)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `(isize, bool)`
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/pointer-sized-int-deny.rs:39:11
+   |
+LL |     match 0isize {
+   |           ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `isize`
+   = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+   = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
+
+error[E0004]: non-exhaustive patterns: type `usize` is non-empty
+  --> $DIR/pointer-sized-int-deny.rs:46:11
+   |
+LL |     match 7usize {}
+   |           ^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `usize`
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.rs b/src/test/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.rs
new file mode 100644 (file)
index 0000000..a2aa655
--- /dev/null
@@ -0,0 +1,18 @@
+// This tests that the lint message explains the reason for the error.
+fn main() {
+    match 0usize {
+        //~^ ERROR non-exhaustive patterns: `_` not covered
+        //~| NOTE pattern `_` not covered
+        //~| NOTE the matched value is of type `usize`
+        //~| NOTE `usize` does not have a fixed maximum value
+        0..=usize::MAX => {}
+    }
+
+    match 0isize {
+        //~^ ERROR non-exhaustive patterns: `_` not covered
+        //~| NOTE pattern `_` not covered
+        //~| NOTE the matched value is of type `isize`
+        //~| NOTE `isize` does not have a fixed maximum value
+        isize::MIN..=isize::MAX => {}
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr b/src/test/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr
new file mode 100644 (file)
index 0000000..37e73a6
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/precise_pointer_matching-message.rs:3:11
+   |
+LL |     match 0usize {
+   |           ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `usize`
+   = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+   = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/precise_pointer_matching-message.rs:11:11
+   |
+LL |     match 0isize {
+   |           ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `isize`
+   = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+   = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/reachability.rs b/src/test/ui/pattern/usefulness/integer-ranges/reachability.rs
new file mode 100644 (file)
index 0000000..9078e65
--- /dev/null
@@ -0,0 +1,112 @@
+#![feature(exclusive_range_pattern)]
+#![deny(unreachable_patterns)]
+
+macro_rules! m {
+    ($s:expr, $t1:pat, $t2:pat) => {
+        match $s {
+            $t1 => {}
+            $t2 => {}
+            _ => {}
+        }
+    }
+}
+
+fn main() {
+    m!(0u8, 42, 41);
+    m!(0u8, 42, 42); //~ ERROR unreachable pattern
+    m!(0u8, 42, 43);
+
+    m!(0u8, 20..=30, 19);
+    m!(0u8, 20..=30, 20); //~ ERROR unreachable pattern
+    m!(0u8, 20..=30, 21); //~ ERROR unreachable pattern
+    m!(0u8, 20..=30, 25); //~ ERROR unreachable pattern
+    m!(0u8, 20..=30, 29); //~ ERROR unreachable pattern
+    m!(0u8, 20..=30, 30); //~ ERROR unreachable pattern
+    m!(0u8, 20..=30, 31);
+    m!(0u8, 20..30, 19);
+    m!(0u8, 20..30, 20); //~ ERROR unreachable pattern
+    m!(0u8, 20..30, 21); //~ ERROR unreachable pattern
+    m!(0u8, 20..30, 25); //~ ERROR unreachable pattern
+    m!(0u8, 20..30, 29); //~ ERROR unreachable pattern
+    m!(0u8, 20..30, 30);
+    m!(0u8, 20..30, 31);
+
+    m!(0u8, 20..=30, 20..=30); //~ ERROR unreachable pattern
+    m!(0u8, 20.. 30, 20.. 30); //~ ERROR unreachable pattern
+    m!(0u8, 20..=30, 20.. 30); //~ ERROR unreachable pattern
+    m!(0u8, 20..=30, 19..=30);
+    m!(0u8, 20..=30, 21..=30); //~ ERROR unreachable pattern
+    m!(0u8, 20..=30, 20..=29); //~ ERROR unreachable pattern
+    m!(0u8, 20..=30, 20..=31);
+    m!('a', 'A'..='z', 'a'..='z'); //~ ERROR unreachable pattern
+
+    match 0u8 {
+        5 => {},
+        6 => {},
+        7 => {},
+        8 => {},
+        5..=8 => {}, //~ ERROR unreachable pattern
+        _ => {},
+    }
+    match 0u8 {
+        0..10 => {},
+        10..20 => {},
+        5..15 => {}, //~ ERROR unreachable pattern
+        _ => {},
+    }
+    match 0u8 {
+        0..10 => {},
+        10..20 => {},
+        20..30 => {},
+        5..25 => {}, //~ ERROR unreachable pattern
+        _ => {},
+    }
+    match 0u8 {
+        0..10 => {},
+        10 => {},
+        11..=23 => {},
+        19..30 => {},
+        5..25 => {}, //~ ERROR unreachable pattern
+        _ => {},
+    }
+    match 0usize {
+        0..10 => {},
+        10..20 => {},
+        5..15 => {}, // FIXME: should be unreachable
+        _ => {},
+    }
+    // Chars between '\u{D7FF}' and '\u{E000}' are invalid even though ranges that contain them are
+    // allowed.
+    match 'a' {
+        _ => {},
+        '\u{D7FF}'..='\u{E000}' => {}, //~ ERROR unreachable pattern
+    }
+    match 'a' {
+        '\u{0}'..='\u{D7FF}' => {},
+        '\u{E000}'..='\u{10_FFFF}' => {},
+        '\u{D7FF}'..='\u{E000}' => {}, // FIXME should be unreachable
+    }
+
+    match (0u8, true) {
+        (0..=255, false) => {}
+        (0..=255, true) => {} // ok
+    }
+    match (true, 0u8) {
+        (false, 0..=255) => {}
+        (true, 0..=255) => {} // ok
+    }
+
+    const FOO: i32 = 42;
+    const BAR: &i32 = &42;
+    match &0 {
+        &42 => {}
+        &FOO => {} //~ ERROR unreachable pattern
+        BAR => {} //~ ERROR unreachable pattern
+        _ => {}
+    }
+    // Regression test, see https://github.com/rust-lang/rust/pull/66326#issuecomment-552889933
+    match &0 {
+        BAR => {} // ok
+        _ => {}
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr b/src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr
new file mode 100644 (file)
index 0000000..8baf0d5
--- /dev/null
@@ -0,0 +1,146 @@
+error: unreachable pattern
+  --> $DIR/reachability.rs:16:17
+   |
+LL |     m!(0u8, 42, 42);
+   |                 ^^
+   |
+note: the lint level is defined here
+  --> $DIR/reachability.rs:2:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:20:22
+   |
+LL |     m!(0u8, 20..=30, 20);
+   |                      ^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:21:22
+   |
+LL |     m!(0u8, 20..=30, 21);
+   |                      ^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:22:22
+   |
+LL |     m!(0u8, 20..=30, 25);
+   |                      ^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:23:22
+   |
+LL |     m!(0u8, 20..=30, 29);
+   |                      ^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:24:22
+   |
+LL |     m!(0u8, 20..=30, 30);
+   |                      ^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:27:21
+   |
+LL |     m!(0u8, 20..30, 20);
+   |                     ^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:28:21
+   |
+LL |     m!(0u8, 20..30, 21);
+   |                     ^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:29:21
+   |
+LL |     m!(0u8, 20..30, 25);
+   |                     ^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:30:21
+   |
+LL |     m!(0u8, 20..30, 29);
+   |                     ^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:34:22
+   |
+LL |     m!(0u8, 20..=30, 20..=30);
+   |                      ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:35:22
+   |
+LL |     m!(0u8, 20.. 30, 20.. 30);
+   |                      ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:36:22
+   |
+LL |     m!(0u8, 20..=30, 20.. 30);
+   |                      ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:38:22
+   |
+LL |     m!(0u8, 20..=30, 21..=30);
+   |                      ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:39:22
+   |
+LL |     m!(0u8, 20..=30, 20..=29);
+   |                      ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:41:24
+   |
+LL |     m!('a', 'A'..='z', 'a'..='z');
+   |                        ^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:48:9
+   |
+LL |         5..=8 => {},
+   |         ^^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:54:9
+   |
+LL |         5..15 => {},
+   |         ^^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:61:9
+   |
+LL |         5..25 => {},
+   |         ^^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:69:9
+   |
+LL |         5..25 => {},
+   |         ^^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:82:9
+   |
+LL |         '\u{D7FF}'..='\u{E000}' => {},
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:103:9
+   |
+LL |         &FOO => {}
+   |         ^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:104:9
+   |
+LL |         BAR => {}
+   |         ^^^
+
+error: aborting due to 23 previous errors
+
diff --git a/src/test/ui/pattern/usefulness/irrefutable-exhaustive-integer-binding.rs b/src/test/ui/pattern/usefulness/irrefutable-exhaustive-integer-binding.rs
deleted file mode 100644 (file)
index ff06588..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-pass
-
-fn main() {
-    let -2147483648..=2147483647 = 1;
-    let 0..=255 = 0u8;
-    let -128..=127 = 0i8;
-    let '\u{0000}'..='\u{10FFFF}' = 'v';
-}
diff --git a/src/test/ui/pattern/usefulness/irrefutable-let-patterns.rs b/src/test/ui/pattern/usefulness/irrefutable-let-patterns.rs
new file mode 100644 (file)
index 0000000..d400ef0
--- /dev/null
@@ -0,0 +1,11 @@
+// run-pass
+
+#![allow(irrefutable_let_patterns)]
+
+fn main() {
+    if let _ = 5 {}
+
+    while let _ = 5 {
+        break;
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/issue-12116.rs b/src/test/ui/pattern/usefulness/issue-12116.rs
new file mode 100644 (file)
index 0000000..8b391cd
--- /dev/null
@@ -0,0 +1,21 @@
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![deny(unreachable_patterns)]
+
+enum IntList {
+    Cons(isize, Box<IntList>),
+    Nil
+}
+
+fn tail(source_list: &IntList) -> IntList {
+    match source_list {
+        &IntList::Cons(val, box ref next_list) => tail(next_list),
+        &IntList::Cons(val, box IntList::Nil)  => IntList::Cons(val, box IntList::Nil),
+//~^ ERROR unreachable pattern
+        _                          => panic!()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/pattern/usefulness/issue-12116.stderr b/src/test/ui/pattern/usefulness/issue-12116.stderr
new file mode 100644 (file)
index 0000000..4d162eb
--- /dev/null
@@ -0,0 +1,14 @@
+error: unreachable pattern
+  --> $DIR/issue-12116.rs:15:9
+   |
+LL |         &IntList::Cons(val, box IntList::Nil)  => IntList::Cons(val, box IntList::Nil),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-12116.rs:5:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pattern/usefulness/issue-12369.rs b/src/test/ui/pattern/usefulness/issue-12369.rs
new file mode 100644 (file)
index 0000000..0481c1f
--- /dev/null
@@ -0,0 +1,11 @@
+#![deny(unreachable_patterns)]
+
+fn main() {
+    let sl = vec![1,2,3];
+    let v: isize = match &*sl {
+        &[] => 0,
+        &[a,b,c] => 3,
+        &[a, ref rest @ ..] => a,
+        &[10,a, ref rest @ ..] => 10 //~ ERROR: unreachable pattern
+    };
+}
diff --git a/src/test/ui/pattern/usefulness/issue-12369.stderr b/src/test/ui/pattern/usefulness/issue-12369.stderr
new file mode 100644 (file)
index 0000000..aab2be7
--- /dev/null
@@ -0,0 +1,14 @@
+error: unreachable pattern
+  --> $DIR/issue-12369.rs:9:9
+   |
+LL |         &[10,a, ref rest @ ..] => 10
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-12369.rs:1:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pattern/usefulness/issue-13727.rs b/src/test/ui/pattern/usefulness/issue-13727.rs
new file mode 100644 (file)
index 0000000..7fb565e
--- /dev/null
@@ -0,0 +1,15 @@
+#![allow(overflowing_literals)]
+#![deny(unreachable_patterns)]
+
+fn test(val: u8) {
+  match val {
+    256 => print!("0b1110\n"),
+    512 => print!("0b1111\n"),
+    //~^ ERROR: unreachable pattern
+    _   => print!("fail\n"),
+  }
+}
+
+fn main() {
+  test(1);
+}
diff --git a/src/test/ui/pattern/usefulness/issue-13727.stderr b/src/test/ui/pattern/usefulness/issue-13727.stderr
new file mode 100644 (file)
index 0000000..07ca56a
--- /dev/null
@@ -0,0 +1,14 @@
+error: unreachable pattern
+  --> $DIR/issue-13727.rs:7:5
+   |
+LL |     512 => print!("0b1111\n"),
+   |     ^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-13727.rs:2:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pattern/usefulness/issue-15129.rs b/src/test/ui/pattern/usefulness/issue-15129.rs
new file mode 100644 (file)
index 0000000..ed134c1
--- /dev/null
@@ -0,0 +1,17 @@
+pub enum T {
+    T1(()),
+    T2(())
+}
+
+pub enum V {
+    V1(isize),
+    V2(bool)
+}
+
+fn main() {
+    match (T::T1(()), V::V2(true)) {
+    //~^ ERROR non-exhaustive patterns: `(T1(()), V2(_))` not covered
+        (T::T1(()), V::V1(i)) => (),
+        (T::T2(()), V::V2(b)) => ()
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/issue-15129.stderr b/src/test/ui/pattern/usefulness/issue-15129.stderr
new file mode 100644 (file)
index 0000000..aa4434e
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0004]: non-exhaustive patterns: `(T1(()), V2(_))` not covered
+  --> $DIR/issue-15129.rs:12:11
+   |
+LL |     match (T::T1(()), V::V2(true)) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `(T1(()), V2(_))` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `(T, V)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/issue-2111.rs b/src/test/ui/pattern/usefulness/issue-2111.rs
new file mode 100644 (file)
index 0000000..7e5835e
--- /dev/null
@@ -0,0 +1,12 @@
+fn foo(a: Option<usize>, b: Option<usize>) {
+  match (a,b) {
+  //~^ ERROR: non-exhaustive patterns: `(None, None)` not covered
+    (Some(a), Some(b)) if a == b => { }
+    (Some(_), None) |
+    (None, Some(_)) => { }
+  }
+}
+
+fn main() {
+  foo(None, None);
+}
diff --git a/src/test/ui/pattern/usefulness/issue-2111.stderr b/src/test/ui/pattern/usefulness/issue-2111.stderr
new file mode 100644 (file)
index 0000000..a39a479
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0004]: non-exhaustive patterns: `(None, None)` not covered
+  --> $DIR/issue-2111.rs:2:9
+   |
+LL |   match (a,b) {
+   |         ^^^^^ pattern `(None, None)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `(Option<usize>, Option<usize>)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/issue-30240-b.rs b/src/test/ui/pattern/usefulness/issue-30240-b.rs
new file mode 100644 (file)
index 0000000..01a6e7d
--- /dev/null
@@ -0,0 +1,15 @@
+#![deny(unreachable_patterns)]
+
+fn main() {
+    match "world" {
+        "hello" => {}
+        _ => {},
+    }
+
+    match "world" {
+        ref _x if false => {}
+        "hello" => {}
+        "hello" => {} //~ ERROR unreachable pattern
+        _ => {},
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/issue-30240-b.stderr b/src/test/ui/pattern/usefulness/issue-30240-b.stderr
new file mode 100644 (file)
index 0000000..59d64bc
--- /dev/null
@@ -0,0 +1,14 @@
+error: unreachable pattern
+  --> $DIR/issue-30240-b.rs:12:9
+   |
+LL |         "hello" => {}
+   |         ^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-30240-b.rs:1:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pattern/usefulness/issue-30240-rpass.rs b/src/test/ui/pattern/usefulness/issue-30240-rpass.rs
new file mode 100644 (file)
index 0000000..ab16614
--- /dev/null
@@ -0,0 +1,14 @@
+// run-pass
+fn main() {
+    let &ref a = &[0i32] as &[_];
+    assert_eq!(a, &[0i32] as &[_]);
+
+    let &ref a = "hello";
+    assert_eq!(a, "hello");
+
+    match "foo" {
+        "fool" => unreachable!(),
+        "foo" => {},
+        ref _x => unreachable!()
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/issue-30240.rs b/src/test/ui/pattern/usefulness/issue-30240.rs
new file mode 100644 (file)
index 0000000..a0c0d16
--- /dev/null
@@ -0,0 +1,10 @@
+fn main() {
+    match "world" { //~ ERROR non-exhaustive patterns: `&_`
+        "hello" => {}
+    }
+
+    match "world" { //~ ERROR non-exhaustive patterns: `&_`
+        ref _x if false => {}
+        "hello" => {}
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/issue-30240.stderr b/src/test/ui/pattern/usefulness/issue-30240.stderr
new file mode 100644 (file)
index 0000000..a2c58d6
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0004]: non-exhaustive patterns: `&_` not covered
+  --> $DIR/issue-30240.rs:2:11
+   |
+LL |     match "world" {
+   |           ^^^^^^^ pattern `&_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `&str`
+
+error[E0004]: non-exhaustive patterns: `&_` not covered
+  --> $DIR/issue-30240.rs:6:11
+   |
+LL |     match "world" {
+   |           ^^^^^^^ pattern `&_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `&str`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/issue-3096-1.rs b/src/test/ui/pattern/usefulness/issue-3096-1.rs
new file mode 100644 (file)
index 0000000..edc3b32
--- /dev/null
@@ -0,0 +1,3 @@
+fn main() {
+    match () { } //~ ERROR non-exhaustive
+}
diff --git a/src/test/ui/pattern/usefulness/issue-3096-1.stderr b/src/test/ui/pattern/usefulness/issue-3096-1.stderr
new file mode 100644 (file)
index 0000000..97c3475
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0004]: non-exhaustive patterns: type `()` is non-empty
+  --> $DIR/issue-3096-1.rs:2:11
+   |
+LL |     match () { }
+   |           ^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/issue-3096-2.rs b/src/test/ui/pattern/usefulness/issue-3096-2.rs
new file mode 100644 (file)
index 0000000..a26e425
--- /dev/null
@@ -0,0 +1,6 @@
+enum Bottom { }
+
+fn main() {
+    let x = &() as *const () as *const Bottom;
+    match x { } //~ ERROR non-exhaustive patterns
+}
diff --git a/src/test/ui/pattern/usefulness/issue-3096-2.stderr b/src/test/ui/pattern/usefulness/issue-3096-2.stderr
new file mode 100644 (file)
index 0000000..472d1a9
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0004]: non-exhaustive patterns: type `*const Bottom` is non-empty
+  --> $DIR/issue-3096-2.rs:5:11
+   |
+LL |     match x { }
+   |           ^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `*const Bottom`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/issue-31221.rs b/src/test/ui/pattern/usefulness/issue-31221.rs
new file mode 100644 (file)
index 0000000..e03f1ec
--- /dev/null
@@ -0,0 +1,34 @@
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(non_snake_case)]
+#![deny(unreachable_patterns)]
+
+#[derive(Clone, Copy)]
+enum Enum {
+    Var1,
+    Var2,
+}
+
+fn main() {
+    use Enum::*;
+    let s = Var1;
+    match s {
+        Var1 => (),
+        Var3 => (),
+        Var2 => (),
+        //~^ ERROR unreachable pattern
+    };
+    match &s {
+        &Var1 => (),
+        &Var3 => (),
+        &Var2 => (),
+        //~^ ERROR unreachable pattern
+    };
+    let t = (Var1, Var1);
+    match t {
+        (Var1, b) => (),
+        (c, d) => (),
+        anything => ()
+        //~^ ERROR unreachable pattern
+    };
+}
diff --git a/src/test/ui/pattern/usefulness/issue-31221.stderr b/src/test/ui/pattern/usefulness/issue-31221.stderr
new file mode 100644 (file)
index 0000000..7d34914
--- /dev/null
@@ -0,0 +1,32 @@
+error: unreachable pattern
+  --> $DIR/issue-31221.rs:18:9
+   |
+LL |         Var3 => (),
+   |         ---- matches any value
+LL |         Var2 => (),
+   |         ^^^^ unreachable pattern
+   |
+note: the lint level is defined here
+  --> $DIR/issue-31221.rs:4:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/issue-31221.rs:24:9
+   |
+LL |         &Var3 => (),
+   |         ----- matches any value
+LL |         &Var2 => (),
+   |         ^^^^^ unreachable pattern
+
+error: unreachable pattern
+  --> $DIR/issue-31221.rs:31:9
+   |
+LL |         (c, d) => (),
+   |         ------ matches any value
+LL |         anything => ()
+   |         ^^^^^^^^ unreachable pattern
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/pattern/usefulness/issue-31561.rs b/src/test/ui/pattern/usefulness/issue-31561.rs
new file mode 100644 (file)
index 0000000..813b240
--- /dev/null
@@ -0,0 +1,10 @@
+enum Thing {
+    Foo(u8),
+    Bar,
+    Baz
+}
+
+fn main() {
+    let Thing::Foo(y) = Thing::Foo(1);
+    //~^ ERROR refutable pattern in local binding: `Bar` and `Baz` not covered
+}
diff --git a/src/test/ui/pattern/usefulness/issue-31561.stderr b/src/test/ui/pattern/usefulness/issue-31561.stderr
new file mode 100644 (file)
index 0000000..2f562b2
--- /dev/null
@@ -0,0 +1,26 @@
+error[E0005]: refutable pattern in local binding: `Bar` and `Baz` not covered
+  --> $DIR/issue-31561.rs:8:9
+   |
+LL | / enum Thing {
+LL | |     Foo(u8),
+LL | |     Bar,
+   | |     --- not covered
+LL | |     Baz
+   | |     --- not covered
+LL | | }
+   | |_- `Thing` defined here
+...
+LL |       let Thing::Foo(y) = Thing::Foo(1);
+   |           ^^^^^^^^^^^^^ patterns `Bar` and `Baz` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+   = note: the matched value is of type `Thing`
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let Thing::Foo(y) = Thing::Foo(1) { /* */ }
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/pattern/usefulness/issue-3601.rs b/src/test/ui/pattern/usefulness/issue-3601.rs
new file mode 100644 (file)
index 0000000..e33359b
--- /dev/null
@@ -0,0 +1,34 @@
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+
+struct HTMLImageData {
+    image: Option<String>
+}
+
+struct ElementData {
+    kind: Box<ElementKind>
+}
+
+enum ElementKind {
+    HTMLImageElement(HTMLImageData)
+}
+
+enum NodeKind {
+    Element(ElementData)
+}
+
+struct NodeData {
+    kind: Box<NodeKind>,
+}
+
+fn main() {
+    let mut id = HTMLImageData { image: None };
+    let ed = ElementData { kind: box ElementKind::HTMLImageElement(id) };
+    let n = NodeData {kind : box NodeKind::Element(ed)};
+    // n.b. span could be better
+    match n.kind {
+        box NodeKind::Element(ed) => match ed.kind { //~ ERROR non-exhaustive patterns
+            box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => { true }
+        },
+    };
+}
diff --git a/src/test/ui/pattern/usefulness/issue-3601.stderr b/src/test/ui/pattern/usefulness/issue-3601.stderr
new file mode 100644 (file)
index 0000000..c873c20
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0004]: non-exhaustive patterns: `Box(_, _)` not covered
+  --> $DIR/issue-3601.rs:30:44
+   |
+LL |         box NodeKind::Element(ed) => match ed.kind {
+   |                                            ^^^^^^^ pattern `Box(_, _)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `Box<ElementKind>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/issue-39362.rs b/src/test/ui/pattern/usefulness/issue-39362.rs
new file mode 100644 (file)
index 0000000..ea3c8f8
--- /dev/null
@@ -0,0 +1,18 @@
+enum Foo {
+    Bar { bar: Bar, id: usize }
+}
+
+enum Bar {
+    A, B, C, D, E, F
+}
+
+fn test(f: Foo) {
+    match f {
+        //~^ ERROR non-exhaustive patterns
+        //~| patterns
+        Foo::Bar { bar: Bar::A, .. } => (),
+        Foo::Bar { bar: Bar::B, .. } => (),
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/pattern/usefulness/issue-39362.stderr b/src/test/ui/pattern/usefulness/issue-39362.stderr
new file mode 100644 (file)
index 0000000..8c162e5
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0004]: non-exhaustive patterns: `Bar { bar: C, .. }`, `Bar { bar: D, .. }`, `Bar { bar: E, .. }` and 1 more not covered
+  --> $DIR/issue-39362.rs:10:11
+   |
+LL | / enum Foo {
+LL | |     Bar { bar: Bar, id: usize }
+LL | | }
+   | |_- `Foo` defined here
+...
+LL |       match f {
+   |             ^ patterns `Bar { bar: C, .. }`, `Bar { bar: D, .. }`, `Bar { bar: E, .. }` and 1 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/issue-40221.rs b/src/test/ui/pattern/usefulness/issue-40221.rs
new file mode 100644 (file)
index 0000000..e1f7e97
--- /dev/null
@@ -0,0 +1,16 @@
+enum P {
+    C(PC),
+}
+
+enum PC {
+    Q,
+    QA,
+}
+
+fn test(proto: P) {
+    match proto { //~ ERROR non-exhaustive patterns
+        P::C(PC::Q) => (),
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/pattern/usefulness/issue-40221.stderr b/src/test/ui/pattern/usefulness/issue-40221.stderr
new file mode 100644 (file)
index 0000000..98efe80
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0004]: non-exhaustive patterns: `C(QA)` not covered
+  --> $DIR/issue-40221.rs:11:11
+   |
+LL | / enum P {
+LL | |     C(PC),
+   | |     - not covered
+LL | | }
+   | |_- `P` defined here
+...
+LL |       match proto {
+   |             ^^^^^ pattern `C(QA)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `P`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/issue-4321.rs b/src/test/ui/pattern/usefulness/issue-4321.rs
new file mode 100644 (file)
index 0000000..9715f2e
--- /dev/null
@@ -0,0 +1,8 @@
+fn main() {
+    let tup = (true, true);
+    println!("foo {:}", match tup { //~ ERROR non-exhaustive patterns: `(true, false)` not covered
+        (false, false) => "foo",
+        (false, true) => "bar",
+        (true, true) => "baz"
+    });
+}
diff --git a/src/test/ui/pattern/usefulness/issue-4321.stderr b/src/test/ui/pattern/usefulness/issue-4321.stderr
new file mode 100644 (file)
index 0000000..1e88525
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0004]: non-exhaustive patterns: `(true, false)` not covered
+  --> $DIR/issue-4321.rs:3:31
+   |
+LL |     println!("foo {:}", match tup {
+   |                               ^^^ pattern `(true, false)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `(bool, bool)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/issue-43253.rs b/src/test/ui/pattern/usefulness/issue-43253.rs
deleted file mode 100644 (file)
index 349ba11..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-// check-pass
-#![feature(exclusive_range_pattern)]
-#![warn(unreachable_patterns)]
-#![warn(overlapping_patterns)]
-
-fn main() {
-    // These cases should generate no warning.
-    match 10 {
-        1..10 => {},
-        10 => {},
-        _ => {},
-    }
-
-    match 10 {
-        1..10 => {},
-        9..=10 => {}, //~ WARNING multiple patterns covering the same range
-        _ => {},
-    }
-
-    match 10 {
-        1..10 => {},
-        10..=10 => {},
-        _ => {},
-    }
-
-    // These cases should generate "unreachable pattern" warnings.
-    match 10 {
-        1..10 => {},
-        9 => {}, //~ WARNING unreachable pattern
-        _ => {},
-    }
-
-    match 10 {
-        1..10 => {},
-        8..=9 => {}, //~ WARNING unreachable pattern
-        _ => {},
-    }
-
-    match 10 {
-        5..7 => {},
-        6 => {}, //~ WARNING unreachable pattern
-        1..10 => {},
-        9..=9 => {}, //~ WARNING unreachable pattern
-        6 => {}, //~ WARNING unreachable pattern
-        _ => {},
-    }
-}
diff --git a/src/test/ui/pattern/usefulness/issue-43253.stderr b/src/test/ui/pattern/usefulness/issue-43253.stderr
deleted file mode 100644 (file)
index 04feef1..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-warning: multiple patterns covering the same range
-  --> $DIR/issue-43253.rs:16:9
-   |
-LL |         1..10 => {},
-   |         ----- this range overlaps on `9_i32`
-LL |         9..=10 => {},
-   |         ^^^^^^ overlapping patterns
-   |
-note: the lint level is defined here
-  --> $DIR/issue-43253.rs:4:9
-   |
-LL | #![warn(overlapping_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-warning: unreachable pattern
-  --> $DIR/issue-43253.rs:29:9
-   |
-LL |         9 => {},
-   |         ^
-   |
-note: the lint level is defined here
-  --> $DIR/issue-43253.rs:3:9
-   |
-LL | #![warn(unreachable_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-warning: unreachable pattern
-  --> $DIR/issue-43253.rs:35:9
-   |
-LL |         8..=9 => {},
-   |         ^^^^^
-
-warning: unreachable pattern
-  --> $DIR/issue-43253.rs:41:9
-   |
-LL |         6 => {},
-   |         ^
-
-warning: unreachable pattern
-  --> $DIR/issue-43253.rs:43:9
-   |
-LL |         9..=9 => {},
-   |         ^^^^^
-
-warning: unreachable pattern
-  --> $DIR/issue-43253.rs:44:9
-   |
-LL |         6 => {},
-   |         ^
-
-warning: 6 warnings emitted
-
diff --git a/src/test/ui/pattern/usefulness/issue-50900.rs b/src/test/ui/pattern/usefulness/issue-50900.rs
new file mode 100644 (file)
index 0000000..27135af
--- /dev/null
@@ -0,0 +1,19 @@
+#[derive(PartialEq, Eq)]
+pub struct Tag(pub Context, pub u16);
+
+#[derive(PartialEq, Eq)]
+pub enum Context {
+    Tiff,
+    Exif,
+}
+
+impl Tag {
+    const ExifIFDPointer: Tag = Tag(Context::Tiff, 34665);
+}
+
+fn main() {
+    match Tag::ExifIFDPointer {
+    //~^ ERROR: non-exhaustive patterns: `Tag(Exif, _)` not covered
+        Tag::ExifIFDPointer => {}
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/issue-50900.stderr b/src/test/ui/pattern/usefulness/issue-50900.stderr
new file mode 100644 (file)
index 0000000..d378b6e
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0004]: non-exhaustive patterns: `Tag(Exif, _)` not covered
+  --> $DIR/issue-50900.rs:15:11
+   |
+LL | pub struct Tag(pub Context, pub u16);
+   | ------------------------------------- `Tag` defined here
+...
+LL |     match Tag::ExifIFDPointer {
+   |           ^^^^^^^^^^^^^^^^^^^ pattern `Tag(Exif, _)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `Tag`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/issue-57472.rs b/src/test/ui/pattern/usefulness/issue-57472.rs
new file mode 100644 (file)
index 0000000..1131006
--- /dev/null
@@ -0,0 +1,35 @@
+#![crate_type="lib"]
+#![deny(unreachable_patterns)]
+
+mod test_struct {
+    // Test the exact copy of the minimal example
+    // posted in the issue.
+    pub struct Punned {
+        foo: [u8; 1],
+        bar: [u8; 1],
+    }
+
+    pub fn test(punned: Punned) {
+        match punned {
+            Punned { foo: [_], .. } => println!("foo"),
+            Punned { bar: [_], .. } => println!("bar"),
+            //~^ ERROR unreachable pattern [unreachable_patterns]
+        }
+    }
+}
+
+mod test_union {
+    // Test the same thing using a union.
+    pub union Punned {
+        foo: [u8; 1],
+        bar: [u8; 1],
+    }
+
+    pub fn test(punned: Punned) {
+        match punned {
+            Punned { foo: [_] } => println!("foo"),
+            Punned { bar: [_] } => println!("bar"),
+            //~^ ERROR unreachable pattern [unreachable_patterns]
+        }
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/issue-57472.stderr b/src/test/ui/pattern/usefulness/issue-57472.stderr
new file mode 100644 (file)
index 0000000..26efdf6
--- /dev/null
@@ -0,0 +1,20 @@
+error: unreachable pattern
+  --> $DIR/issue-57472.rs:15:13
+   |
+LL |             Punned { bar: [_], .. } => println!("bar"),
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-57472.rs:2:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/issue-57472.rs:31:13
+   |
+LL |             Punned { bar: [_] } => println!("bar"),
+   |             ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/pattern/usefulness/issue-66501.rs b/src/test/ui/pattern/usefulness/issue-66501.rs
new file mode 100644 (file)
index 0000000..ffcfd4a
--- /dev/null
@@ -0,0 +1,12 @@
+// check-pass
+
+#![allow(unreachable_patterns)]
+
+fn main() {
+    const CONST: &[Option<()>; 1] = &[Some(())];
+    match &[Some(())] {
+        &[None] => {}
+        CONST => {}
+        &[Some(())] => {}
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/match-range-fail-dominate.rs b/src/test/ui/pattern/usefulness/match-range-fail-dominate.rs
deleted file mode 100644 (file)
index 37c4ccd..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#![deny(unreachable_patterns, overlapping_patterns)]
-
-fn main() {
-    match 5 {
-      1 ..= 10 => { }
-      5 ..= 6 => { }
-      //~^ ERROR unreachable pattern
-      _ => {}
-    };
-
-    match 5 {
-      3 ..= 6 => { }
-      4 ..= 6 => { }
-      //~^ ERROR unreachable pattern
-      _ => {}
-    };
-
-    match 5 {
-      4 ..= 6 => { }
-      4 ..= 6 => { }
-      //~^ ERROR unreachable pattern
-      _ => {}
-    };
-
-    match 'c' {
-      'A' ..= 'z' => {}
-      'a' ..= 'z' => {}
-      //~^ ERROR unreachable pattern
-      _ => {}
-    };
-
-    match 1.0f64 {
-      0.01f64 ..= 6.5f64 => {}
-      //~^ WARNING floating-point types cannot be used in patterns
-      //~| WARNING floating-point types cannot be used in patterns
-      //~| WARNING floating-point types cannot be used in patterns
-      //~| WARNING floating-point types cannot be used in patterns
-      //~| WARNING this was previously accepted by the compiler
-      //~| WARNING this was previously accepted by the compiler
-      //~| WARNING this was previously accepted by the compiler
-      //~| WARNING this was previously accepted by the compiler
-      0.02f64 => {} //~ ERROR unreachable pattern
-      //~^ WARNING floating-point types cannot be used in patterns
-      //~| WARNING floating-point types cannot be used in patterns
-      //~| WARNING this was previously accepted by the compiler
-      //~| WARNING this was previously accepted by the compiler
-      _ => {}
-    };
-}
diff --git a/src/test/ui/pattern/usefulness/match-range-fail-dominate.stderr b/src/test/ui/pattern/usefulness/match-range-fail-dominate.stderr
deleted file mode 100644 (file)
index 6922170..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-error: unreachable pattern
-  --> $DIR/match-range-fail-dominate.rs:6:7
-   |
-LL |       5 ..= 6 => { }
-   |       ^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/match-range-fail-dominate.rs:1:9
-   |
-LL | #![deny(unreachable_patterns, overlapping_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error: unreachable pattern
-  --> $DIR/match-range-fail-dominate.rs:13:7
-   |
-LL |       4 ..= 6 => { }
-   |       ^^^^^^^
-
-error: unreachable pattern
-  --> $DIR/match-range-fail-dominate.rs:20:7
-   |
-LL |       4 ..= 6 => { }
-   |       ^^^^^^^
-
-error: unreachable pattern
-  --> $DIR/match-range-fail-dominate.rs:27:7
-   |
-LL |       'a' ..= 'z' => {}
-   |       ^^^^^^^^^^^
-
-warning: floating-point types cannot be used in patterns
-  --> $DIR/match-range-fail-dominate.rs:33:7
-   |
-LL |       0.01f64 ..= 6.5f64 => {}
-   |       ^^^^^^^
-   |
-   = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-warning: floating-point types cannot be used in patterns
-  --> $DIR/match-range-fail-dominate.rs:33:19
-   |
-LL |       0.01f64 ..= 6.5f64 => {}
-   |                   ^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-warning: floating-point types cannot be used in patterns
-  --> $DIR/match-range-fail-dominate.rs:42:7
-   |
-LL |       0.02f64 => {}
-   |       ^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: unreachable pattern
-  --> $DIR/match-range-fail-dominate.rs:42:7
-   |
-LL |       0.02f64 => {}
-   |       ^^^^^^^
-
-warning: floating-point types cannot be used in patterns
-  --> $DIR/match-range-fail-dominate.rs:33:7
-   |
-LL |       0.01f64 ..= 6.5f64 => {}
-   |       ^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-warning: floating-point types cannot be used in patterns
-  --> $DIR/match-range-fail-dominate.rs:33:19
-   |
-LL |       0.01f64 ..= 6.5f64 => {}
-   |                   ^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-warning: floating-point types cannot be used in patterns
-  --> $DIR/match-range-fail-dominate.rs:42:7
-   |
-LL |       0.02f64 => {}
-   |       ^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: aborting due to 5 previous errors; 6 warnings emitted
-
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.rs b/src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.rs
deleted file mode 100644 (file)
index 588fecb..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#![allow(illegal_floating_point_literal_pattern)]
-#![deny(unreachable_patterns)]
-
-fn main() {
-    match 0.0 {
-      0.0..=1.0 => {}
-      _ => {} // ok
-    }
-
-    match 0.0 { //~ ERROR non-exhaustive patterns
-      0.0..=1.0 => {}
-    }
-}
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.stderr
deleted file mode 100644 (file)
index 4835fa8..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/non-exhaustive-float-range-match.rs:10:11
-   |
-LL |     match 0.0 {
-   |           ^^^ pattern `_` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `f64`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.rs b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.rs
deleted file mode 100644 (file)
index 0c52876..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-use std::{usize, isize};
-
-fn main() {
-    match 0usize {
-        //~^ ERROR non-exhaustive patterns
-        //~| NOTE pattern `_` not covered
-        //~| NOTE the matched value is of type `usize`
-        //~| NOTE `usize` does not have a fixed maximum value
-        0 ..= usize::MAX => {}
-    }
-
-    match 0isize {
-        //~^ ERROR non-exhaustive patterns
-        //~| NOTE pattern `_` not covered
-        //~| NOTE the matched value is of type `isize`
-        //~| NOTE `isize` does not have a fixed maximum value
-        isize::MIN ..= isize::MAX => {}
-    }
-
-    match 7usize {}
-    //~^ ERROR non-exhaustive patterns
-    //~| NOTE the matched value is of type `usize`
-}
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.stderr
deleted file mode 100644 (file)
index d0aa452..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/non-exhaustive-pattern-pointer-size-int.rs:4:11
-   |
-LL |     match 0usize {
-   |           ^^^^^^ pattern `_` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `usize`
-   = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
-   = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
-
-error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/non-exhaustive-pattern-pointer-size-int.rs:12:11
-   |
-LL |     match 0isize {
-   |           ^^^^^^ pattern `_` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `isize`
-   = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
-   = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
-
-error[E0004]: non-exhaustive patterns: type `usize` is non-empty
-  --> $DIR/non-exhaustive-pattern-pointer-size-int.rs:20:11
-   |
-LL |     match 7usize {}
-   |           ^^^^^^
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `usize`
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/type_polymorphic_byte_str_literals.rs b/src/test/ui/pattern/usefulness/type_polymorphic_byte_str_literals.rs
new file mode 100644 (file)
index 0000000..cb44c1d
--- /dev/null
@@ -0,0 +1,36 @@
+#[deny(unreachable_patterns)]
+
+fn parse_data1(data: &[u8]) -> u32 {
+    match data {
+        b"" => 1,
+        _ => 2,
+    }
+}
+
+fn parse_data2(data: &[u8]) -> u32 {
+    match data { //~ ERROR non-exhaustive patterns: `&[_, ..]` not covered
+        b"" => 1,
+    }
+}
+
+fn parse_data3(data: &[u8; 0]) -> u8 {
+    match data {
+        b"" => 1,
+    }
+}
+
+fn parse_data4(data: &[u8]) -> u8 {
+    match data { //~ ERROR non-exhaustive patterns
+        b"aaa" => 0,
+        [_, _, _] => 1,
+    }
+}
+
+fn parse_data5(data: &[u8; 3]) -> u8 {
+    match data {
+        b"aaa" => 0,
+        [_, _, _] => 1,
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/pattern/usefulness/type_polymorphic_byte_str_literals.stderr b/src/test/ui/pattern/usefulness/type_polymorphic_byte_str_literals.stderr
new file mode 100644 (file)
index 0000000..6ce53a4
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
+  --> $DIR/type_polymorphic_byte_str_literals.rs:11:11
+   |
+LL |     match data {
+   |           ^^^^ pattern `&[_, ..]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `&[u8]`
+
+error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 1 more not covered
+  --> $DIR/type_polymorphic_byte_str_literals.rs:23:11
+   |
+LL |     match data {
+   |           ^^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 1 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `&[u8]`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/phantom-auto-trait.rs b/src/test/ui/phantom-auto-trait.rs
new file mode 100644 (file)
index 0000000..0172ca3
--- /dev/null
@@ -0,0 +1,30 @@
+// Ensure that auto trait checks `T` when it encounters a `PhantomData<T>` field, instead of
+// checking the `PhantomData<T>` type itself (which almost always implements an auto trait).
+
+#![feature(auto_traits)]
+
+use std::marker::{PhantomData};
+
+unsafe auto trait Zen {}
+
+unsafe impl<'a, T: 'a> Zen for &'a T where T: Sync {}
+
+struct Guard<'a, T: 'a> {
+    _marker: PhantomData<&'a T>,
+}
+
+struct Nested<T>(T);
+
+fn is_zen<T: Zen>(_: T) {}
+
+fn not_sync<T>(x: Guard<T>) {
+    is_zen(x)
+    //~^ ERROR `T` cannot be shared between threads safely [E0277]
+}
+
+fn nested_not_sync<T>(x: Nested<Guard<T>>) {
+    is_zen(x)
+    //~^ ERROR `T` cannot be shared between threads safely [E0277]
+}
+
+fn main() {}
diff --git a/src/test/ui/phantom-auto-trait.stderr b/src/test/ui/phantom-auto-trait.stderr
new file mode 100644 (file)
index 0000000..779919f
--- /dev/null
@@ -0,0 +1,38 @@
+error[E0277]: `T` cannot be shared between threads safely
+  --> $DIR/phantom-auto-trait.rs:21:12
+   |
+LL | fn is_zen<T: Zen>(_: T) {}
+   |              --- required by this bound in `is_zen`
+...
+LL |     is_zen(x)
+   |            ^ `T` cannot be shared between threads safely
+   |
+   = note: required because of the requirements on the impl of `Zen` for `&T`
+   = note: required because it appears within the type `PhantomData<&T>`
+   = note: required because it appears within the type `Guard<'_, T>`
+help: consider restricting type parameter `T`
+   |
+LL | fn not_sync<T: Sync>(x: Guard<T>) {
+   |              ^^^^^^
+
+error[E0277]: `T` cannot be shared between threads safely
+  --> $DIR/phantom-auto-trait.rs:26:12
+   |
+LL | fn is_zen<T: Zen>(_: T) {}
+   |              --- required by this bound in `is_zen`
+...
+LL |     is_zen(x)
+   |            ^ `T` cannot be shared between threads safely
+   |
+   = note: required because of the requirements on the impl of `Zen` for `&T`
+   = note: required because it appears within the type `PhantomData<&T>`
+   = note: required because it appears within the type `Guard<'_, T>`
+   = note: required because it appears within the type `Nested<Guard<'_, T>>`
+help: consider restricting type parameter `T`
+   |
+LL | fn nested_not_sync<T: Sync>(x: Nested<Guard<T>>) {
+   |                     ^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/phantom-oibit.rs b/src/test/ui/phantom-oibit.rs
deleted file mode 100644 (file)
index 04291a7..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// Ensure that OIBIT checks `T` when it encounters a `PhantomData<T>` field, instead of checking
-// the `PhantomData<T>` type itself (which almost always implements an auto trait)
-
-#![feature(optin_builtin_traits)]
-
-use std::marker::{PhantomData};
-
-unsafe auto trait Zen {}
-
-unsafe impl<'a, T: 'a> Zen for &'a T where T: Sync {}
-
-struct Guard<'a, T: 'a> {
-    _marker: PhantomData<&'a T>,
-}
-
-struct Nested<T>(T);
-
-fn is_zen<T: Zen>(_: T) {}
-
-fn not_sync<T>(x: Guard<T>) {
-    is_zen(x)
-    //~^ ERROR `T` cannot be shared between threads safely [E0277]
-}
-
-fn nested_not_sync<T>(x: Nested<Guard<T>>) {
-    is_zen(x)
-    //~^ ERROR `T` cannot be shared between threads safely [E0277]
-}
-
-fn main() {}
diff --git a/src/test/ui/phantom-oibit.stderr b/src/test/ui/phantom-oibit.stderr
deleted file mode 100644 (file)
index 8a02f23..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-error[E0277]: `T` cannot be shared between threads safely
-  --> $DIR/phantom-oibit.rs:21:12
-   |
-LL | fn is_zen<T: Zen>(_: T) {}
-   |              --- required by this bound in `is_zen`
-...
-LL |     is_zen(x)
-   |            ^ `T` cannot be shared between threads safely
-   |
-   = note: required because of the requirements on the impl of `Zen` for `&T`
-   = note: required because it appears within the type `PhantomData<&T>`
-   = note: required because it appears within the type `Guard<'_, T>`
-help: consider restricting type parameter `T`
-   |
-LL | fn not_sync<T: Sync>(x: Guard<T>) {
-   |              ^^^^^^
-
-error[E0277]: `T` cannot be shared between threads safely
-  --> $DIR/phantom-oibit.rs:26:12
-   |
-LL | fn is_zen<T: Zen>(_: T) {}
-   |              --- required by this bound in `is_zen`
-...
-LL |     is_zen(x)
-   |            ^ `T` cannot be shared between threads safely
-   |
-   = note: required because of the requirements on the impl of `Zen` for `&T`
-   = note: required because it appears within the type `PhantomData<&T>`
-   = note: required because it appears within the type `Guard<'_, T>`
-   = note: required because it appears within the type `Nested<Guard<'_, T>>`
-help: consider restricting type parameter `T`
-   |
-LL | fn nested_not_sync<T: Sync>(x: Nested<Guard<T>>) {
-   |                     ^^^^^^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/precise_pointer_size_matching.rs b/src/test/ui/precise_pointer_size_matching.rs
deleted file mode 100644 (file)
index 54aeb86..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-// normalize-stderr-32bit: "-2147483648isize" -> "$$ISIZE_MIN"
-// normalize-stderr-64bit: "-9223372036854775808isize" -> "$$ISIZE_MIN"
-// normalize-stderr-32bit: "2147483647isize" -> "$$ISIZE_MAX"
-// normalize-stderr-64bit: "9223372036854775807isize" -> "$$ISIZE_MAX"
-// normalize-stderr-32bit: "4294967295usize" -> "$$USIZE_MAX"
-// normalize-stderr-64bit: "18446744073709551615usize" -> "$$USIZE_MAX"
-
-#![feature(precise_pointer_size_matching)]
-#![feature(exclusive_range_pattern)]
-
-#![deny(unreachable_patterns, overlapping_patterns)]
-
-use std::{usize, isize};
-
-fn main() {
-    match 0isize {
-        isize::MIN ..= isize::MAX => {} // ok
-    }
-
-    match 0usize {
-        0 ..= usize::MAX => {} // ok
-    }
-
-    match 0isize { //~ ERROR non-exhaustive patterns
-        1 ..= 8 => {}
-        -5 ..= 20 => {}
-    }
-
-    match 0usize { //~ ERROR non-exhaustive patterns
-        1 ..= 8 => {}
-        5 ..= 20 => {}
-    }
-}
diff --git a/src/test/ui/precise_pointer_size_matching.stderr b/src/test/ui/precise_pointer_size_matching.stderr
deleted file mode 100644 (file)
index 9a34171..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0004]: non-exhaustive patterns: `isize::MIN..=-6_isize` and `21_isize..=isize::MAX` not covered
-  --> $DIR/precise_pointer_size_matching.rs:24:11
-   |
-LL |     match 0isize {
-   |           ^^^^^^ patterns `isize::MIN..=-6_isize` and `21_isize..=isize::MAX` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `isize`
-
-error[E0004]: non-exhaustive patterns: `0_usize` and `21_usize..=usize::MAX` not covered
-  --> $DIR/precise_pointer_size_matching.rs:29:11
-   |
-LL |     match 0usize {
-   |           ^^^^^^ patterns `0_usize` and `21_usize..=usize::MAX` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `usize`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0004`.
index e4434695446174e1f426d5c9f4dd77904e87c657..f68de00b9b5915bc4c9220fc0bf78f56a6c9d915 100644 (file)
@@ -2,8 +2,8 @@
 #![allow(dead_code)]
 
 // (#55495: The --error-format is to sidestep an issue in our test harness)
-// compile-flags: --error-format human -Z print-fuel=foo
-// build-pass (FIXME(62277): could be check-pass?)
+// compile-flags: -C opt-level=0 --error-format human -Z print-fuel=foo
+// check-pass
 
 struct S1(u8, u16, u8);
 struct S2(u8, u16, u8);
index 70c083e0800cee97c1000d9aca168be77745c4fa..cfa9aec80685801f3c8e218d0a430cd40962da4e 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi spawning processes is not supported
 // ignore-emscripten spawning processes is not supported
 // ignore-sgx no processes
 
index effcb508e276ed3262fbd66ca1dce7b497a9106c..db451d33429b31fce2832de62b3aa2d90b7ca59b 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 #![feature(negative_impls)]
 
 #[allow(private_in_public)]
index aa946f5c0ac05aa5b3707cc0156c2000382a9976..ac1d5a9e6a20261c7c02441d8e3ea47c8374e873 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 #![feature(negative_impls)]
 
 pub trait PubPrincipal {}
diff --git a/src/test/ui/proc-macro/allowed-attr-stmt-expr.rs b/src/test/ui/proc-macro/allowed-attr-stmt-expr.rs
new file mode 100644 (file)
index 0000000..25243ae
--- /dev/null
@@ -0,0 +1,78 @@
+// aux-build:attr-stmt-expr.rs
+// aux-build:test-macros.rs
+// compile-flags: -Z span-debug
+// check-pass
+
+#![feature(proc_macro_hygiene)]
+#![feature(stmt_expr_attributes)]
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+extern crate attr_stmt_expr;
+extern crate test_macros;
+use attr_stmt_expr::{expect_let, expect_my_macro_stmt, expect_expr, expect_my_macro_expr};
+use test_macros::print_attr;
+
+// We don't use `std::println` so that we avoid loading hygiene
+// information from libstd, which would affect the SyntaxContext ids
+macro_rules! my_macro {
+    ($($tt:tt)*) => { () }
+}
+
+
+fn print_str(string: &'static str) {
+    // macros are handled a bit differently
+    #[expect_my_macro_expr]
+    my_macro!("{}", string)
+}
+
+macro_rules! make_stmt {
+    ($stmt:stmt) => {
+        #[print_attr]
+        #[rustc_dummy]
+        $stmt; // This semicolon is *not* passed to the macro,
+               // since `$stmt` is already a statement.
+    }
+}
+
+macro_rules! second_make_stmt {
+    ($stmt:stmt) => {
+        make_stmt!($stmt);
+    }
+}
+
+// The macro will see a semicolon here
+#[print_attr]
+struct ItemWithSemi;
+
+
+fn main() {
+    make_stmt!(struct Foo {});
+
+    #[print_attr]
+    #[expect_let]
+    let string = "Hello, world!";
+
+    #[print_attr]
+    #[expect_my_macro_stmt]
+    my_macro!("{}", string);
+
+    #[print_attr]
+    second_make_stmt!(#[allow(dead_code)] struct Bar {});
+
+    #[print_attr]
+    #[rustc_dummy]
+    struct Other {};
+
+    // The macro also sees a semicolon,
+    // for consistency with the `ItemWithSemi` case above.
+    #[print_attr]
+    #[rustc_dummy]
+    struct NonBracedStruct;
+
+    #[expect_expr]
+    print_str("string")
+}
diff --git a/src/test/ui/proc-macro/allowed-attr-stmt-expr.stdout b/src/test/ui/proc-macro/allowed-attr-stmt-expr.stdout
new file mode 100644 (file)
index 0000000..6cf864f
--- /dev/null
@@ -0,0 +1,321 @@
+PRINT-ATTR INPUT (DISPLAY): struct ItemWithSemi ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "struct",
+        span: $DIR/allowed-attr-stmt-expr.rs:49:1: 49:7 (#0),
+    },
+    Ident {
+        ident: "ItemWithSemi",
+        span: $DIR/allowed-attr-stmt-expr.rs:49:8: 49:20 (#0),
+    },
+    Punct {
+        ch: ';',
+        spacing: Alone,
+        span: $DIR/allowed-attr-stmt-expr.rs:49:20: 49:21 (#0),
+    },
+]
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Foo { }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Punct {
+        ch: '#',
+        spacing: Alone,
+        span: $DIR/allowed-attr-stmt-expr.rs:35:9: 35:10 (#11),
+    },
+    Group {
+        delimiter: Bracket,
+        stream: TokenStream [
+            Ident {
+                ident: "rustc_dummy",
+                span: $DIR/allowed-attr-stmt-expr.rs:35:11: 35:22 (#11),
+            },
+        ],
+        span: $DIR/allowed-attr-stmt-expr.rs:35:10: 35:23 (#11),
+    },
+    Ident {
+        ident: "struct",
+        span: $DIR/allowed-attr-stmt-expr.rs:53:16: 53:22 (#0),
+    },
+    Ident {
+        ident: "Foo",
+        span: $DIR/allowed-attr-stmt-expr.rs:53:23: 53:26 (#0),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [],
+        span: $DIR/allowed-attr-stmt-expr.rs:53:27: 53:29 (#0),
+    },
+]
+PRINT-ATTR INPUT (DISPLAY): #[expect_let] let string = "Hello, world!" ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Punct {
+        ch: '#',
+        spacing: Alone,
+        span: $DIR/allowed-attr-stmt-expr.rs:56:5: 56:6 (#0),
+    },
+    Group {
+        delimiter: Bracket,
+        stream: TokenStream [
+            Ident {
+                ident: "expect_let",
+                span: $DIR/allowed-attr-stmt-expr.rs:56:7: 56:17 (#0),
+            },
+        ],
+        span: $DIR/allowed-attr-stmt-expr.rs:56:6: 56:18 (#0),
+    },
+    Ident {
+        ident: "let",
+        span: $DIR/allowed-attr-stmt-expr.rs:57:5: 57:8 (#0),
+    },
+    Ident {
+        ident: "string",
+        span: $DIR/allowed-attr-stmt-expr.rs:57:9: 57:15 (#0),
+    },
+    Punct {
+        ch: '=',
+        spacing: Alone,
+        span: $DIR/allowed-attr-stmt-expr.rs:57:16: 57:17 (#0),
+    },
+    Literal {
+        kind: Str,
+        symbol: "Hello, world!",
+        suffix: None,
+        span: $DIR/allowed-attr-stmt-expr.rs:57:18: 57:33 (#0),
+    },
+    Punct {
+        ch: ';',
+        spacing: Alone,
+        span: $DIR/allowed-attr-stmt-expr.rs:57:33: 57:34 (#0),
+    },
+]
+PRINT-ATTR INPUT (DISPLAY): #[expect_my_macro_stmt] my_macro ! ("{}", string) ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Punct {
+        ch: '#',
+        spacing: Alone,
+        span: $DIR/allowed-attr-stmt-expr.rs:60:5: 60:6 (#0),
+    },
+    Group {
+        delimiter: Bracket,
+        stream: TokenStream [
+            Ident {
+                ident: "expect_my_macro_stmt",
+                span: $DIR/allowed-attr-stmt-expr.rs:60:7: 60:27 (#0),
+            },
+        ],
+        span: $DIR/allowed-attr-stmt-expr.rs:60:6: 60:28 (#0),
+    },
+    Ident {
+        ident: "my_macro",
+        span: $DIR/allowed-attr-stmt-expr.rs:61:5: 61:13 (#0),
+    },
+    Punct {
+        ch: '!',
+        spacing: Alone,
+        span: $DIR/allowed-attr-stmt-expr.rs:61:13: 61:14 (#0),
+    },
+    Group {
+        delimiter: Parenthesis,
+        stream: TokenStream [
+            Literal {
+                kind: Str,
+                symbol: "{}",
+                suffix: None,
+                span: $DIR/allowed-attr-stmt-expr.rs:61:15: 61:19 (#0),
+            },
+            Punct {
+                ch: ',',
+                spacing: Alone,
+                span: $DIR/allowed-attr-stmt-expr.rs:61:19: 61:20 (#0),
+            },
+            Ident {
+                ident: "string",
+                span: $DIR/allowed-attr-stmt-expr.rs:61:21: 61:27 (#0),
+            },
+        ],
+        span: $DIR/allowed-attr-stmt-expr.rs:61:14: 61:28 (#0),
+    },
+    Punct {
+        ch: ';',
+        spacing: Alone,
+        span: $DIR/allowed-attr-stmt-expr.rs:61:28: 61:29 (#0),
+    },
+]
+PRINT-ATTR INPUT (DISPLAY): second_make_stmt ! (#[allow(dead_code)] struct Bar { }) ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "second_make_stmt",
+        span: $DIR/allowed-attr-stmt-expr.rs:64:5: 64:21 (#0),
+    },
+    Punct {
+        ch: '!',
+        spacing: Alone,
+        span: $DIR/allowed-attr-stmt-expr.rs:64:21: 64:22 (#0),
+    },
+    Group {
+        delimiter: Parenthesis,
+        stream: TokenStream [
+            Punct {
+                ch: '#',
+                spacing: Alone,
+                span: $DIR/allowed-attr-stmt-expr.rs:64:23: 64:24 (#0),
+            },
+            Group {
+                delimiter: Bracket,
+                stream: TokenStream [
+                    Ident {
+                        ident: "allow",
+                        span: $DIR/allowed-attr-stmt-expr.rs:64:25: 64:30 (#0),
+                    },
+                    Group {
+                        delimiter: Parenthesis,
+                        stream: TokenStream [
+                            Ident {
+                                ident: "dead_code",
+                                span: $DIR/allowed-attr-stmt-expr.rs:64:31: 64:40 (#0),
+                            },
+                        ],
+                        span: $DIR/allowed-attr-stmt-expr.rs:64:30: 64:41 (#0),
+                    },
+                ],
+                span: $DIR/allowed-attr-stmt-expr.rs:64:24: 64:42 (#0),
+            },
+            Ident {
+                ident: "struct",
+                span: $DIR/allowed-attr-stmt-expr.rs:64:43: 64:49 (#0),
+            },
+            Ident {
+                ident: "Bar",
+                span: $DIR/allowed-attr-stmt-expr.rs:64:50: 64:53 (#0),
+            },
+            Group {
+                delimiter: Brace,
+                stream: TokenStream [],
+                span: $DIR/allowed-attr-stmt-expr.rs:64:54: 64:56 (#0),
+            },
+        ],
+        span: $DIR/allowed-attr-stmt-expr.rs:64:22: 64:57 (#0),
+    },
+    Punct {
+        ch: ';',
+        spacing: Alone,
+        span: $DIR/allowed-attr-stmt-expr.rs:64:57: 64:58 (#0),
+    },
+]
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] #[allow(dead_code)] struct Bar { }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Punct {
+        ch: '#',
+        spacing: Alone,
+        span: $DIR/allowed-attr-stmt-expr.rs:35:9: 35:10 (#32),
+    },
+    Group {
+        delimiter: Bracket,
+        stream: TokenStream [
+            Ident {
+                ident: "rustc_dummy",
+                span: $DIR/allowed-attr-stmt-expr.rs:35:11: 35:22 (#32),
+            },
+        ],
+        span: $DIR/allowed-attr-stmt-expr.rs:35:10: 35:23 (#32),
+    },
+    Punct {
+        ch: '#',
+        spacing: Alone,
+        span: $DIR/allowed-attr-stmt-expr.rs:64:23: 64:24 (#0),
+    },
+    Group {
+        delimiter: Bracket,
+        stream: TokenStream [
+            Ident {
+                ident: "allow",
+                span: $DIR/allowed-attr-stmt-expr.rs:64:25: 64:30 (#0),
+            },
+            Group {
+                delimiter: Parenthesis,
+                stream: TokenStream [
+                    Ident {
+                        ident: "dead_code",
+                        span: $DIR/allowed-attr-stmt-expr.rs:64:31: 64:40 (#0),
+                    },
+                ],
+                span: $DIR/allowed-attr-stmt-expr.rs:64:30: 64:41 (#0),
+            },
+        ],
+        span: $DIR/allowed-attr-stmt-expr.rs:64:24: 64:42 (#0),
+    },
+    Ident {
+        ident: "struct",
+        span: $DIR/allowed-attr-stmt-expr.rs:64:43: 64:49 (#0),
+    },
+    Ident {
+        ident: "Bar",
+        span: $DIR/allowed-attr-stmt-expr.rs:64:50: 64:53 (#0),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [],
+        span: $DIR/allowed-attr-stmt-expr.rs:64:54: 64:56 (#0),
+    },
+]
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Other { }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Punct {
+        ch: '#',
+        spacing: Alone,
+        span: $DIR/allowed-attr-stmt-expr.rs:67:5: 67:6 (#0),
+    },
+    Group {
+        delimiter: Bracket,
+        stream: TokenStream [
+            Ident {
+                ident: "rustc_dummy",
+                span: $DIR/allowed-attr-stmt-expr.rs:67:7: 67:18 (#0),
+            },
+        ],
+        span: $DIR/allowed-attr-stmt-expr.rs:67:6: 67:19 (#0),
+    },
+    Ident {
+        ident: "struct",
+        span: $DIR/allowed-attr-stmt-expr.rs:68:5: 68:11 (#0),
+    },
+    Ident {
+        ident: "Other",
+        span: $DIR/allowed-attr-stmt-expr.rs:68:12: 68:17 (#0),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [],
+        span: $DIR/allowed-attr-stmt-expr.rs:68:18: 68:20 (#0),
+    },
+]
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct NonBracedStruct ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Punct {
+        ch: '#',
+        spacing: Alone,
+        span: $DIR/allowed-attr-stmt-expr.rs:73:5: 73:6 (#0),
+    },
+    Group {
+        delimiter: Bracket,
+        stream: TokenStream [
+            Ident {
+                ident: "rustc_dummy",
+                span: $DIR/allowed-attr-stmt-expr.rs:73:7: 73:18 (#0),
+            },
+        ],
+        span: $DIR/allowed-attr-stmt-expr.rs:73:6: 73:19 (#0),
+    },
+    Ident {
+        ident: "struct",
+        span: $DIR/allowed-attr-stmt-expr.rs:74:5: 74:11 (#0),
+    },
+    Ident {
+        ident: "NonBracedStruct",
+        span: $DIR/allowed-attr-stmt-expr.rs:74:12: 74:27 (#0),
+    },
+    Punct {
+        ch: ';',
+        spacing: Alone,
+        span: $DIR/allowed-attr-stmt-expr.rs:74:27: 74:28 (#0),
+    },
+]
index 14a392db4e11835fbfa5704e5c449c79876760c0..0403684cda004febfbb194321e846782b051a6a5 100644 (file)
@@ -1,24 +1,63 @@
 // aux-build:attr-stmt-expr.rs
+// aux-build:test-macros.rs
+// compile-flags: -Z span-debug
 
 #![feature(proc_macro_hygiene)]
+#![feature(rustc_attrs)]
 
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+extern crate test_macros;
 extern crate attr_stmt_expr;
-use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr};
+
+use test_macros::print_attr;
+use attr_stmt_expr::{expect_let, expect_my_macro_stmt, expect_expr, expect_my_macro_expr};
+
+// We don't use `std::println` so that we avoid loading hygiene
+// information from libstd, which would affect the SyntaxContext ids
+macro_rules! my_macro {
+    ($($tt:tt)*) => { () }
+}
 
 fn print_str(string: &'static str) {
     // macros are handled a bit differently
-    #[expect_print_expr]
+    #[expect_my_macro_expr]
     //~^ ERROR attributes on expressions are experimental
     //~| HELP add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
-    println!("{}", string)
+    my_macro!("{}", string)
+}
+
+macro_rules! make_stmt {
+    ($stmt:stmt) => {
+        #[print_attr]
+        #[rustc_dummy]
+        $stmt
+    }
+}
+
+macro_rules! second_make_stmt {
+    ($stmt:stmt) => {
+        make_stmt!($stmt);
+    }
 }
 
 fn main() {
+    make_stmt!(struct Foo {});
+
+    #[print_attr]
     #[expect_let]
     let string = "Hello, world!";
 
-    #[expect_print_stmt]
-    println!("{}", string);
+    #[print_attr]
+    #[expect_my_macro_stmt]
+    my_macro!("{}", string);
+
+    #[print_attr]
+    second_make_stmt!(#[allow(dead_code)] struct Bar {});
+
+    #[print_attr]
+    #[rustc_dummy]
+    struct Other {}
 
     #[expect_expr]
     //~^ ERROR attributes on expressions are experimental
index 0d6f247cf835975a251ac665f2d8383f5d62cc7a..56178259d4352ff6502b2a652308c6de9bbe6674 100644 (file)
@@ -1,14 +1,14 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/attr-stmt-expr.rs:10:5
+  --> $DIR/attr-stmt-expr.rs:24:5
    |
-LL |     #[expect_print_expr]
-   |     ^^^^^^^^^^^^^^^^^^^^
+LL |     #[expect_my_macro_expr]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
    = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
 
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/attr-stmt-expr.rs:23:5
+  --> $DIR/attr-stmt-expr.rs:62:5
    |
 LL |     #[expect_expr]
    |     ^^^^^^^^^^^^^^
diff --git a/src/test/ui/proc-macro/attr-stmt-expr.stdout b/src/test/ui/proc-macro/attr-stmt-expr.stdout
new file mode 100644 (file)
index 0000000..f75309e
--- /dev/null
@@ -0,0 +1,274 @@
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Foo { }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Punct {
+        ch: '#',
+        spacing: Alone,
+        span: $DIR/attr-stmt-expr.rs:33:9: 33:10 (#8),
+    },
+    Group {
+        delimiter: Bracket,
+        stream: TokenStream [
+            Ident {
+                ident: "rustc_dummy",
+                span: $DIR/attr-stmt-expr.rs:33:11: 33:22 (#8),
+            },
+        ],
+        span: $DIR/attr-stmt-expr.rs:33:10: 33:23 (#8),
+    },
+    Ident {
+        ident: "struct",
+        span: $DIR/attr-stmt-expr.rs:45:16: 45:22 (#0),
+    },
+    Ident {
+        ident: "Foo",
+        span: $DIR/attr-stmt-expr.rs:45:23: 45:26 (#0),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [],
+        span: $DIR/attr-stmt-expr.rs:45:27: 45:29 (#0),
+    },
+]
+PRINT-ATTR INPUT (DISPLAY): #[expect_let] let string = "Hello, world!" ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Punct {
+        ch: '#',
+        spacing: Alone,
+        span: $DIR/attr-stmt-expr.rs:48:5: 48:6 (#0),
+    },
+    Group {
+        delimiter: Bracket,
+        stream: TokenStream [
+            Ident {
+                ident: "expect_let",
+                span: $DIR/attr-stmt-expr.rs:48:7: 48:17 (#0),
+            },
+        ],
+        span: $DIR/attr-stmt-expr.rs:48:6: 48:18 (#0),
+    },
+    Ident {
+        ident: "let",
+        span: $DIR/attr-stmt-expr.rs:49:5: 49:8 (#0),
+    },
+    Ident {
+        ident: "string",
+        span: $DIR/attr-stmt-expr.rs:49:9: 49:15 (#0),
+    },
+    Punct {
+        ch: '=',
+        spacing: Alone,
+        span: $DIR/attr-stmt-expr.rs:49:16: 49:17 (#0),
+    },
+    Literal {
+        kind: Str,
+        symbol: "Hello, world!",
+        suffix: None,
+        span: $DIR/attr-stmt-expr.rs:49:18: 49:33 (#0),
+    },
+    Punct {
+        ch: ';',
+        spacing: Alone,
+        span: $DIR/attr-stmt-expr.rs:49:33: 49:34 (#0),
+    },
+]
+PRINT-ATTR INPUT (DISPLAY): #[expect_my_macro_stmt] my_macro ! ("{}", string) ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Punct {
+        ch: '#',
+        spacing: Alone,
+        span: $DIR/attr-stmt-expr.rs:52:5: 52:6 (#0),
+    },
+    Group {
+        delimiter: Bracket,
+        stream: TokenStream [
+            Ident {
+                ident: "expect_my_macro_stmt",
+                span: $DIR/attr-stmt-expr.rs:52:7: 52:27 (#0),
+            },
+        ],
+        span: $DIR/attr-stmt-expr.rs:52:6: 52:28 (#0),
+    },
+    Ident {
+        ident: "my_macro",
+        span: $DIR/attr-stmt-expr.rs:53:5: 53:13 (#0),
+    },
+    Punct {
+        ch: '!',
+        spacing: Alone,
+        span: $DIR/attr-stmt-expr.rs:53:13: 53:14 (#0),
+    },
+    Group {
+        delimiter: Parenthesis,
+        stream: TokenStream [
+            Literal {
+                kind: Str,
+                symbol: "{}",
+                suffix: None,
+                span: $DIR/attr-stmt-expr.rs:53:15: 53:19 (#0),
+            },
+            Punct {
+                ch: ',',
+                spacing: Alone,
+                span: $DIR/attr-stmt-expr.rs:53:19: 53:20 (#0),
+            },
+            Ident {
+                ident: "string",
+                span: $DIR/attr-stmt-expr.rs:53:21: 53:27 (#0),
+            },
+        ],
+        span: $DIR/attr-stmt-expr.rs:53:14: 53:28 (#0),
+    },
+    Punct {
+        ch: ';',
+        spacing: Alone,
+        span: $DIR/attr-stmt-expr.rs:53:28: 53:29 (#0),
+    },
+]
+PRINT-ATTR INPUT (DISPLAY): second_make_stmt ! (#[allow(dead_code)] struct Bar { }) ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "second_make_stmt",
+        span: $DIR/attr-stmt-expr.rs:56:5: 56:21 (#0),
+    },
+    Punct {
+        ch: '!',
+        spacing: Alone,
+        span: $DIR/attr-stmt-expr.rs:56:21: 56:22 (#0),
+    },
+    Group {
+        delimiter: Parenthesis,
+        stream: TokenStream [
+            Punct {
+                ch: '#',
+                spacing: Alone,
+                span: $DIR/attr-stmt-expr.rs:56:23: 56:24 (#0),
+            },
+            Group {
+                delimiter: Bracket,
+                stream: TokenStream [
+                    Ident {
+                        ident: "allow",
+                        span: $DIR/attr-stmt-expr.rs:56:25: 56:30 (#0),
+                    },
+                    Group {
+                        delimiter: Parenthesis,
+                        stream: TokenStream [
+                            Ident {
+                                ident: "dead_code",
+                                span: $DIR/attr-stmt-expr.rs:56:31: 56:40 (#0),
+                            },
+                        ],
+                        span: $DIR/attr-stmt-expr.rs:56:30: 56:41 (#0),
+                    },
+                ],
+                span: $DIR/attr-stmt-expr.rs:56:24: 56:42 (#0),
+            },
+            Ident {
+                ident: "struct",
+                span: $DIR/attr-stmt-expr.rs:56:43: 56:49 (#0),
+            },
+            Ident {
+                ident: "Bar",
+                span: $DIR/attr-stmt-expr.rs:56:50: 56:53 (#0),
+            },
+            Group {
+                delimiter: Brace,
+                stream: TokenStream [],
+                span: $DIR/attr-stmt-expr.rs:56:54: 56:56 (#0),
+            },
+        ],
+        span: $DIR/attr-stmt-expr.rs:56:22: 56:57 (#0),
+    },
+    Punct {
+        ch: ';',
+        spacing: Alone,
+        span: $DIR/attr-stmt-expr.rs:56:57: 56:58 (#0),
+    },
+]
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] #[allow(dead_code)] struct Bar { }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Punct {
+        ch: '#',
+        spacing: Alone,
+        span: $DIR/attr-stmt-expr.rs:33:9: 33:10 (#29),
+    },
+    Group {
+        delimiter: Bracket,
+        stream: TokenStream [
+            Ident {
+                ident: "rustc_dummy",
+                span: $DIR/attr-stmt-expr.rs:33:11: 33:22 (#29),
+            },
+        ],
+        span: $DIR/attr-stmt-expr.rs:33:10: 33:23 (#29),
+    },
+    Punct {
+        ch: '#',
+        spacing: Alone,
+        span: $DIR/attr-stmt-expr.rs:56:23: 56:24 (#0),
+    },
+    Group {
+        delimiter: Bracket,
+        stream: TokenStream [
+            Ident {
+                ident: "allow",
+                span: $DIR/attr-stmt-expr.rs:56:25: 56:30 (#0),
+            },
+            Group {
+                delimiter: Parenthesis,
+                stream: TokenStream [
+                    Ident {
+                        ident: "dead_code",
+                        span: $DIR/attr-stmt-expr.rs:56:31: 56:40 (#0),
+                    },
+                ],
+                span: $DIR/attr-stmt-expr.rs:56:30: 56:41 (#0),
+            },
+        ],
+        span: $DIR/attr-stmt-expr.rs:56:24: 56:42 (#0),
+    },
+    Ident {
+        ident: "struct",
+        span: $DIR/attr-stmt-expr.rs:56:43: 56:49 (#0),
+    },
+    Ident {
+        ident: "Bar",
+        span: $DIR/attr-stmt-expr.rs:56:50: 56:53 (#0),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [],
+        span: $DIR/attr-stmt-expr.rs:56:54: 56:56 (#0),
+    },
+]
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Other { }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Punct {
+        ch: '#',
+        spacing: Alone,
+        span: $DIR/attr-stmt-expr.rs:59:5: 59:6 (#0),
+    },
+    Group {
+        delimiter: Bracket,
+        stream: TokenStream [
+            Ident {
+                ident: "rustc_dummy",
+                span: $DIR/attr-stmt-expr.rs:59:7: 59:18 (#0),
+            },
+        ],
+        span: $DIR/attr-stmt-expr.rs:59:6: 59:19 (#0),
+    },
+    Ident {
+        ident: "struct",
+        span: $DIR/attr-stmt-expr.rs:60:5: 60:11 (#0),
+    },
+    Ident {
+        ident: "Other",
+        span: $DIR/attr-stmt-expr.rs:60:12: 60:17 (#0),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [],
+        span: $DIR/attr-stmt-expr.rs:60:18: 60:20 (#0),
+    },
+]
index 213f999e9d0eaa080783f80d99fec8f9258ddcda..19183c616516acf316149b15d89531adcddbc873 100644 (file)
@@ -15,9 +15,9 @@ pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream {
 }
 
 #[proc_macro_attribute]
-pub fn expect_print_stmt(attr: TokenStream, item: TokenStream) -> TokenStream {
+pub fn expect_my_macro_stmt(attr: TokenStream, item: TokenStream) -> TokenStream {
     assert!(attr.to_string().is_empty());
-    assert_eq!(item.to_string(), "println ! (\"{}\", string) ;");
+    assert_eq!(item.to_string(), "my_macro ! (\"{}\", string) ;");
     item
 }
 
@@ -29,9 +29,9 @@ pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
 }
 
 #[proc_macro_attribute]
-pub fn expect_print_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
+pub fn expect_my_macro_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
     assert!(attr.to_string().is_empty());
-    assert_eq!(item.to_string(), "println ! (\"{}\", string)");
+    assert_eq!(item.to_string(), "my_macro ! (\"{}\", string)");
     item
 }
 
diff --git a/src/test/ui/proc-macro/auxiliary/issue-79242.rs b/src/test/ui/proc-macro/auxiliary/issue-79242.rs
new file mode 100644 (file)
index 0000000..e586980
--- /dev/null
@@ -0,0 +1,16 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn dummy(input: TokenStream) -> TokenStream {
+    // Iterate to force internal conversion of nonterminals
+    // to `proc_macro` structs
+    for _ in input {}
+    TokenStream::new()
+}
diff --git a/src/test/ui/proc-macro/issue-79242-slow-retokenize-check.rs b/src/test/ui/proc-macro/issue-79242-slow-retokenize-check.rs
new file mode 100644 (file)
index 0000000..b68f19c
--- /dev/null
@@ -0,0 +1,34 @@
+// check-pass
+// aux-build:issue-79242.rs
+
+// Regression test for issue #79242
+// Tests that compilation time doesn't blow up for a proc-macro
+// invocation with deeply nested nonterminals
+
+#![allow(unused)]
+
+extern crate issue_79242;
+
+macro_rules! declare_nats {
+    ($prev:ty) => {};
+    ($prev:ty, $n:literal$(, $tail:literal)*) => {
+
+        issue_79242::dummy! {
+            $prev
+        }
+
+        declare_nats!(Option<$prev>$(, $tail)*);
+    };
+    (0, $($n:literal),+) => {
+        pub struct N0;
+        declare_nats!(N0, $($n),+);
+    };
+}
+
+declare_nats! {
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+    17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28
+}
+
+
+fn main() {}
index 888785363cfe62d016706761d82d90d77eb21401..0bf889a855d01e15893e4b52d1e8ed24c452e79c 100644 (file)
@@ -1,7 +1,12 @@
 // aux-build:test-macros.rs
+// compile-flags: -Z span-debug
 
 #![feature(stmt_expr_attributes)]
 #![feature(proc_macro_hygiene)]
+#![feature(rustc_attrs)]
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
 
 extern crate test_macros;
 
@@ -12,4 +17,8 @@ fn main() {
     for item in missing_fn() {} //~ ERROR cannot find
 
     (#[recollect_attr] #[recollect_attr] ((#[recollect_attr] bad))); //~ ERROR cannot
+
+    #[test_macros::print_attr]
+    #[rustc_dummy]
+    { 1 +1; } // Don't change the weird spacing of the '+'
 }
index 2be8c0184da1c6c744ee7499858360fda4b6ddd3..11052d11c25089abc373b6eec738218d8f848d84 100644 (file)
@@ -1,11 +1,11 @@
 error[E0425]: cannot find function `missing_fn` in this scope
-  --> $DIR/keep-expr-tokens.rs:12:17
+  --> $DIR/keep-expr-tokens.rs:17:17
    |
 LL |     for item in missing_fn() {}
    |                 ^^^^^^^^^^ not found in this scope
 
 error[E0425]: cannot find value `bad` in this scope
-  --> $DIR/keep-expr-tokens.rs:14:62
+  --> $DIR/keep-expr-tokens.rs:19:62
    |
 LL |     (#[recollect_attr] #[recollect_attr] ((#[recollect_attr] bad)));
    |                                                              ^^^ not found in this scope
diff --git a/src/test/ui/proc-macro/keep-expr-tokens.stdout b/src/test/ui/proc-macro/keep-expr-tokens.stdout
new file mode 100644 (file)
index 0000000..fcd72a0
--- /dev/null
@@ -0,0 +1,46 @@
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] { 1 + 1 ; }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Punct {
+        ch: '#',
+        spacing: Alone,
+        span: $DIR/keep-expr-tokens.rs:22:5: 22:6 (#0),
+    },
+    Group {
+        delimiter: Bracket,
+        stream: TokenStream [
+            Ident {
+                ident: "rustc_dummy",
+                span: $DIR/keep-expr-tokens.rs:22:7: 22:18 (#0),
+            },
+        ],
+        span: $DIR/keep-expr-tokens.rs:22:6: 22:19 (#0),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [
+            Literal {
+                kind: Integer,
+                symbol: "1",
+                suffix: None,
+                span: $DIR/keep-expr-tokens.rs:23:7: 23:8 (#0),
+            },
+            Punct {
+                ch: '+',
+                spacing: Alone,
+                span: $DIR/keep-expr-tokens.rs:23:9: 23:10 (#0),
+            },
+            Literal {
+                kind: Integer,
+                symbol: "1",
+                suffix: None,
+                span: $DIR/keep-expr-tokens.rs:23:10: 23:11 (#0),
+            },
+            Punct {
+                ch: ';',
+                spacing: Alone,
+                span: $DIR/keep-expr-tokens.rs:23:11: 23:12 (#0),
+            },
+        ],
+        span: $DIR/keep-expr-tokens.rs:23:5: 23:14 (#0),
+    },
+]
index b3b677fa7ffed06647d53fc42f659bfa4ea804f8..e2cf4e73987561332f8c7ba6daf9f33ed6b9556f 100644 (file)
@@ -7,11 +7,11 @@
 extern crate test_macros;
 
 fn _test_inner() {
-    #![empty_attr] //~ ERROR: non-builtin inner attributes are unstable
+    #![empty_attr] //~ ERROR: inner macro attributes are unstable
 }
 
 mod _test2_inner {
-    #![empty_attr] //~ ERROR: non-builtin inner attributes are unstable
+    #![empty_attr] //~ ERROR: inner macro attributes are unstable
 }
 
 #[empty_attr = "y"] //~ ERROR: key-value macro attributes are not supported
@@ -45,4 +45,9 @@ fn attrs() {
     //~^ ERROR: custom attributes cannot be applied to expressions
 }
 
+fn test_case() {
+    #![test] //~ ERROR inner macro attributes are unstable
+             //~| WARN this was previously accepted
+}
+
 fn main() {}
index c0343495531775b7b2c2f57d44109e1bc24ac4b2..118213a17d4626cadc02afb39e105594e7903d33 100644 (file)
@@ -1,17 +1,17 @@
-error[E0658]: non-builtin inner attributes are unstable
-  --> $DIR/proc-macro-gates.rs:10:5
+error[E0658]: inner macro attributes are unstable
+  --> $DIR/proc-macro-gates.rs:10:8
    |
 LL |     #![empty_attr]
-   |     ^^^^^^^^^^^^^^
+   |        ^^^^^^^^^^
    |
    = note: see issue #54726 <https://github.com/rust-lang/rust/issues/54726> for more information
    = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable
 
-error[E0658]: non-builtin inner attributes are unstable
-  --> $DIR/proc-macro-gates.rs:14:5
+error[E0658]: inner macro attributes are unstable
+  --> $DIR/proc-macro-gates.rs:14:8
    |
 LL |     #![empty_attr]
-   |     ^^^^^^^^^^^^^^
+   |        ^^^^^^^^^^
    |
    = note: see issue #54726 <https://github.com/rust-lang/rust/issues/54726> for more information
    = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable
@@ -76,6 +76,16 @@ LL |     let _x = #[identity_attr] println!();
    = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information
    = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
 
-error: aborting due to 9 previous errors
+error: inner macro attributes are unstable
+  --> $DIR/proc-macro-gates.rs:49:8
+   |
+LL |     #![test]
+   |        ^^^^
+   |
+   = note: `#[deny(soft_unstable)]` 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 #64266 <https://github.com/rust-lang/rust/issues/64266>
+
+error: aborting due to 10 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 2fd5efd71f041c4739971ac1340e29d1cb2c8f25..38fbd4733d5cbe8a59935fc003fe3d6d750af12b 100644 (file)
 // should either require a feature gate or not be allowed on stable.
 
 fn _test6<#[empty_attr] T>() {}
-//~^ ERROR: expected an inert attribute, found an attribute macro
+//~^ ERROR: expected non-macro attribute, found attribute macro
 
 fn _test7() {
     match 1 {
-        #[empty_attr] //~ ERROR: expected an inert attribute, found an attribute macro
+        #[empty_attr] //~ ERROR: expected non-macro attribute, found attribute macro
         0 => {}
         _ => {}
     }
index fd271da61553a19682cc8e7f3ed7d362822bcfcc..64df34e7ce390b1a581beaa1f7c75c18cca3f0eb 100644 (file)
@@ -1,14 +1,14 @@
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-gates2.rs:12:11
+error: expected non-macro attribute, found attribute macro `empty_attr`
+  --> $DIR/proc-macro-gates2.rs:12:13
    |
 LL | fn _test6<#[empty_attr] T>() {}
-   |           ^^^^^^^^^^^^^
+   |             ^^^^^^^^^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-gates2.rs:17:9
+error: expected non-macro attribute, found attribute macro `empty_attr`
+  --> $DIR/proc-macro-gates2.rs:17:11
    |
 LL |         #[empty_attr]
-   |         ^^^^^^^^^^^^^
+   |           ^^^^^^^^^^ not a non-macro attribute
 
 error: aborting due to 2 previous errors
 
index 62a4733f89a0354c24890cf2e2896755d13ba67d..8fc99b23fd210bdf97a156d8d568e6f933c4146b 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 // ignore-vxworks no 'env'
index da3b4ca85c2a3076c8d16b54376ca58380b63608..d193e073e7f0737f64943200c8a16224afcc5952 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 #![allow(unused_imports)]
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
index 3fee9e2abb9f8e93d82ea3a962c5bc64726b1593..af4e49dfdbb5b3e406a2b3565809d50bc43a7f33 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 // ignore-vxworks no 'env'
index 36303440ee9d0277bae2f4417678f020d7170b70..ecf5e93c99ee50464b137c4ca8669d22f34ebb2c 100644 (file)
@@ -12,7 +12,6 @@
 // (instead of running forever), and that it does not print an error
 // message about a broken pipe.
 
-// ignore-cloudabi no subprocesses support
 // ignore-emscripten no threads support
 // ignore-vxworks no 'sh'
 
index 182cf1748fec68e1d28fca99c4b652c13bb50c85..70de7316a817035af679bd0eb5337fdf0f5d71b0 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
index edd3cb26ec362919f6a46752d35ae51df5463d44..6e9229b62936c9176ef9ca79efdae61732217881 100644 (file)
@@ -7,7 +7,6 @@
 // non-ASCII characters.  The child process ensures all the strings are
 // intact.
 
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
index f9b2da7e401eea35abcc32a60c357d331f4a8773..7719dd9ad85570f9ab9c8cbb6117b8fc06565136 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
index 36d6aff9e7730f71937284532c28d3ca3295858f..6296e5042d28031e039a570089627db95dcd9b93 100644 (file)
@@ -1,7 +1,6 @@
 // run-fail
 // error-pattern:nonzero
 // exec-env:RUST_NEWRT=1
-// ignore-cloudabi no std::env
 // ignore-emscripten no processes
 
 use std::env;
diff --git a/src/test/ui/resolve/macro-determinacy-non-module.rs b/src/test/ui/resolve/macro-determinacy-non-module.rs
new file mode 100644 (file)
index 0000000..3215e0c
--- /dev/null
@@ -0,0 +1,7 @@
+// check-pass
+
+use std as line;
+
+const C: u32 = line!();
+
+fn main() {}
index 5b08234c0adc5e4b070048eebae2793e2d4797f7..52934085fa1423c5142622d910a526f297190a5e 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-cloudabi no std::fs support
-
 // Test that we do some basic error correction in the tokeniser (and don't spew
 // too many bogus errors).
 
index dd0e2597850378cf4608c98461372205f8e1a7a7..31087e394adfe4a6fef782ba219fc8ca2b9e03d2 100644 (file)
@@ -1,5 +1,5 @@
 error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;`
-  --> $DIR/token-error-correct-3.rs:15:35
+  --> $DIR/token-error-correct-3.rs:13:35
    |
 LL |             callback(path.as_ref();
    |                     -             ^ help: `)` may belong here
@@ -7,7 +7,7 @@ LL |             callback(path.as_ref();
    |                     unclosed delimiter
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `)`
-  --> $DIR/token-error-correct-3.rs:18:9
+  --> $DIR/token-error-correct-3.rs:16:9
    |
 LL |             fs::create_dir_all(path.as_ref()).map(|()| true)
    |                                                             - expected one of `.`, `;`, `?`, `}`, or an operator
@@ -15,7 +15,7 @@ LL |         } else {
    |         ^ unexpected token
 
 error[E0425]: cannot find function `is_directory` in this scope
-  --> $DIR/token-error-correct-3.rs:13:13
+  --> $DIR/token-error-correct-3.rs:11:13
    |
 LL |         if !is_directory(path.as_ref()) {
    |             ^^^^^^^^^^^^ not found in this scope
index 9b8b9d88c7989e59a024eed112f568439ea20924..56d4b8d6d11cfcd978986db7c2bcb94839f10d29 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-cloudabi no std::path support
-
 macro_rules! y {
     () => {}
 }
index 3f91760fe216b59c37beccfcd3a12df8f425e8e3..af0495a57a1e078e68f6612af18b7d9de6dcbdb5 100644 (file)
@@ -1,5 +1,5 @@
 error[E0412]: cannot find type `Path` in this scope
-  --> $DIR/use_suggestion_placement.rs:17:16
+  --> $DIR/use_suggestion_placement.rs:15:16
    |
 LL |     type Bar = Path;
    |                ^^^^ not found in this scope
@@ -10,7 +10,7 @@ LL |     use std::path::Path;
    |
 
 error[E0425]: cannot find value `A` in this scope
-  --> $DIR/use_suggestion_placement.rs:22:13
+  --> $DIR/use_suggestion_placement.rs:20:13
    |
 LL |     let _ = A;
    |             ^ not found in this scope
@@ -21,7 +21,7 @@ LL | use m::A;
    |
 
 error[E0412]: cannot find type `HashMap` in this scope
-  --> $DIR/use_suggestion_placement.rs:27:23
+  --> $DIR/use_suggestion_placement.rs:25:23
    |
 LL |     type Dict<K, V> = HashMap<K, V>;
    |                       ^^^^^^^ not found in this scope
index 2b110c9a325156081c18b7edb19d8e78eaf79c1f..c60ff7dc93449f30e470e1b304c577fc2f85c398 100644 (file)
@@ -12,10 +12,4 @@ impl S {
     fn g() {}
 }
 
-extern "Rust" {
-    #[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
-    #[naked]
-    fn h();
-}
-
 fn main() {}
index 1249d1df07179cbc655ec28fd566acb6b3b1ba2a..211cd3f16ba1b48ad3d9ecf62e0881c8afc2cd78 100644 (file)
@@ -4,18 +4,12 @@ error[E0736]: cannot use `#[track_caller]` with `#[naked]`
 LL | #[track_caller]
    | ^^^^^^^^^^^^^^^
 
-error[E0736]: cannot use `#[track_caller]` with `#[naked]`
-  --> $DIR/error-with-naked.rs:16:5
-   |
-LL |     #[track_caller]
-   |     ^^^^^^^^^^^^^^^
-
 error[E0736]: cannot use `#[track_caller]` with `#[naked]`
   --> $DIR/error-with-naked.rs:10:5
    |
 LL |     #[track_caller]
    |     ^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0736`.
index bf09171c9a12afc7914a91341967e18357b2a18f..6403b3f55c40ccf714e927b592ae41bd44dfbe12 100644 (file)
@@ -3,7 +3,7 @@ fn ffi(
         /// Foo
         //~^ ERROR documentation comments cannot be applied to function
         #[test] a: i32,
-        //~^ ERROR expected an inert attribute, found an attribute macro
+        //~^ ERROR expected non-macro attribute, found attribute macro
         /// Bar
         //~^ ERROR documentation comments cannot be applied to function
         #[must_use]
@@ -19,7 +19,7 @@ fn ffi(
     /// Foo
     //~^ ERROR documentation comments cannot be applied to function
     #[test] a: u32,
-    //~^ ERROR expected an inert attribute, found an attribute macro
+    //~^ ERROR expected non-macro attribute, found attribute macro
     /// Bar
     //~^ ERROR documentation comments cannot be applied to function
     #[must_use]
@@ -34,7 +34,7 @@ pub fn foo(
     /// Foo
     //~^ ERROR documentation comments cannot be applied to function
     #[test] a: u32,
-    //~^ ERROR expected an inert attribute, found an attribute macro
+    //~^ ERROR expected non-macro attribute, found attribute macro
     /// Bar
     //~^ ERROR documentation comments cannot be applied to function
     #[must_use]
@@ -54,7 +54,7 @@ fn foo(
         /// Bar
         //~^ ERROR documentation comments cannot be applied to function
         #[test] a: i32,
-        //~^ ERROR expected an inert attribute, found an attribute macro
+        //~^ ERROR expected non-macro attribute, found attribute macro
         /// Baz
         //~^ ERROR documentation comments cannot be applied to function
         #[must_use]
@@ -69,7 +69,7 @@ fn issue_64682_associated_fn(
         /// Foo
         //~^ ERROR documentation comments cannot be applied to function
         #[test] a: i32,
-        //~^ ERROR expected an inert attribute, found an attribute macro
+        //~^ ERROR expected non-macro attribute, found attribute macro
         /// Baz
         //~^ ERROR documentation comments cannot be applied to function
         #[must_use]
@@ -90,7 +90,7 @@ fn foo(
         /// Bar
         //~^ ERROR documentation comments cannot be applied to function
         #[test] a: i32,
-        //~^ ERROR expected an inert attribute, found an attribute macro
+        //~^ ERROR expected non-macro attribute, found attribute macro
         /// Baz
         //~^ ERROR documentation comments cannot be applied to function
         #[must_use]
@@ -109,7 +109,7 @@ fn foo(
         /// Bar
         //~^ ERROR documentation comments cannot be applied to function
         #[test] a: i32,
-        //~^ ERROR expected an inert attribute, found an attribute macro
+        //~^ ERROR expected non-macro attribute, found attribute macro
         /// Baz
         //~^ ERROR documentation comments cannot be applied to function
         #[must_use]
@@ -124,7 +124,7 @@ fn issue_64682_associated_fn(
         /// Foo
         //~^ ERROR documentation comments cannot be applied to function
         #[test] a: i32,
-        //~^ ERROR expected an inert attribute, found an attribute macro
+        //~^ ERROR expected non-macro attribute, found attribute macro
         /// Baz
         //~^ ERROR documentation comments cannot be applied to function
         #[must_use]
@@ -144,7 +144,7 @@ fn foo(
         /// Bar
         //~^ ERROR documentation comments cannot be applied to function
         #[test] a: i32,
-        //~^ ERROR expected an inert attribute, found an attribute macro
+        //~^ ERROR expected non-macro attribute, found attribute macro
         /// Baz
         //~^ ERROR documentation comments cannot be applied to function
         #[must_use]
@@ -161,7 +161,7 @@ fn main() {
         /// Foo
         //~^ ERROR documentation comments cannot be applied to function
         #[test] a: u32,
-        //~^ ERROR expected an inert attribute, found an attribute macro
+        //~^ ERROR expected non-macro attribute, found attribute macro
         /// Bar
         //~^ ERROR documentation comments cannot be applied to function
         #[must_use]
index 4d0349e8765f0eca73372ae915c8d11e41ca3671..edca8cea68d72a9cc7c8d56d27a8d26b6f5891fe 100644 (file)
@@ -1,62 +1,62 @@
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/param-attrs-builtin-attrs.rs:5:9
+error: expected non-macro attribute, found attribute macro `test`
+  --> $DIR/param-attrs-builtin-attrs.rs:5:11
    |
 LL |         #[test] a: i32,
-   |         ^^^^^^^
+   |           ^^^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/param-attrs-builtin-attrs.rs:21:5
+error: expected non-macro attribute, found attribute macro `test`
+  --> $DIR/param-attrs-builtin-attrs.rs:21:7
    |
 LL |     #[test] a: u32,
-   |     ^^^^^^^
+   |       ^^^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/param-attrs-builtin-attrs.rs:36:5
+error: expected non-macro attribute, found attribute macro `test`
+  --> $DIR/param-attrs-builtin-attrs.rs:36:7
    |
 LL |     #[test] a: u32,
-   |     ^^^^^^^
+   |       ^^^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/param-attrs-builtin-attrs.rs:56:9
+error: expected non-macro attribute, found attribute macro `test`
+  --> $DIR/param-attrs-builtin-attrs.rs:56:11
    |
 LL |         #[test] a: i32,
-   |         ^^^^^^^
+   |           ^^^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/param-attrs-builtin-attrs.rs:71:9
+error: expected non-macro attribute, found attribute macro `test`
+  --> $DIR/param-attrs-builtin-attrs.rs:71:11
    |
 LL |         #[test] a: i32,
-   |         ^^^^^^^
+   |           ^^^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/param-attrs-builtin-attrs.rs:92:9
+error: expected non-macro attribute, found attribute macro `test`
+  --> $DIR/param-attrs-builtin-attrs.rs:92:11
    |
 LL |         #[test] a: i32,
-   |         ^^^^^^^
+   |           ^^^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/param-attrs-builtin-attrs.rs:111:9
+error: expected non-macro attribute, found attribute macro `test`
+  --> $DIR/param-attrs-builtin-attrs.rs:111:11
    |
 LL |         #[test] a: i32,
-   |         ^^^^^^^
+   |           ^^^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/param-attrs-builtin-attrs.rs:126:9
+error: expected non-macro attribute, found attribute macro `test`
+  --> $DIR/param-attrs-builtin-attrs.rs:126:11
    |
 LL |         #[test] a: i32,
-   |         ^^^^^^^
+   |           ^^^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/param-attrs-builtin-attrs.rs:146:9
+error: expected non-macro attribute, found attribute macro `test`
+  --> $DIR/param-attrs-builtin-attrs.rs:146:11
    |
 LL |         #[test] a: i32,
-   |         ^^^^^^^
+   |           ^^^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/param-attrs-builtin-attrs.rs:163:9
+error: expected non-macro attribute, found attribute macro `test`
+  --> $DIR/param-attrs-builtin-attrs.rs:163:11
    |
 LL |         #[test] a: u32,
-   |         ^^^^^^^
+   |           ^^^^ not a non-macro attribute
 
 error: documentation comments cannot be applied to function parameters
   --> $DIR/param-attrs-builtin-attrs.rs:3:9
index be9085d5878cb493d3860b98a00a5f972e680332..fcfa610ec8554e438e833c0589c15c810a08cc60 100644 (file)
@@ -8,58 +8,58 @@
 struct W(u8);
 
 extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); }
-//~^ ERROR expected an inert attribute, found an attribute macro
-//~| ERROR expected an inert attribute, found an attribute macro
+//~^ ERROR expected non-macro attribute, found attribute macro
+//~| ERROR expected non-macro attribute, found attribute macro
 
 unsafe extern "C" fn cvar(arg1: i32, #[id] mut args: ...) {}
-//~^ ERROR expected an inert attribute, found an attribute macro
+//~^ ERROR expected non-macro attribute, found attribute macro
 
 type Alias = extern "C" fn(#[id] u8, #[id] ...);
-    //~^ ERROR expected an inert attribute, found an attribute macro
-    //~| ERROR expected an inert attribute, found an attribute macro
+    //~^ ERROR expected non-macro attribute, found attribute macro
+    //~| ERROR expected non-macro attribute, found attribute macro
 
 fn free(#[id] arg1: u8) {
-    //~^ ERROR expected an inert attribute, found an attribute macro
+    //~^ ERROR expected non-macro attribute, found attribute macro
     let lam = |#[id] W(x), #[id] y: usize| ();
-    //~^ ERROR expected an inert attribute, found an attribute macro
-    //~| ERROR expected an inert attribute, found an attribute macro
+    //~^ ERROR expected non-macro attribute, found attribute macro
+    //~| ERROR expected non-macro attribute, found attribute macro
 }
 
 impl W {
     fn inherent1(#[id] self, #[id] arg1: u8) {}
-    //~^ ERROR expected an inert attribute, found an attribute macro
-    //~| ERROR expected an inert attribute, found an attribute macro
+    //~^ ERROR expected non-macro attribute, found attribute macro
+    //~| ERROR expected non-macro attribute, found attribute macro
     fn inherent2(#[id] &self, #[id] arg1: u8) {}
-    //~^ ERROR expected an inert attribute, found an attribute macro
-    //~| ERROR expected an inert attribute, found an attribute macro
+    //~^ ERROR expected non-macro attribute, found attribute macro
+    //~| ERROR expected non-macro attribute, found attribute macro
     fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {}
-    //~^ ERROR expected an inert attribute, found an attribute macro
-    //~| ERROR expected an inert attribute, found an attribute macro
+    //~^ ERROR expected non-macro attribute, found attribute macro
+    //~| ERROR expected non-macro attribute, found attribute macro
     fn inherent4<'a>(#[id] self: Box<Self>, #[id] arg1: u8) {}
-    //~^ ERROR expected an inert attribute, found an attribute macro
-    //~| ERROR expected an inert attribute, found an attribute macro
+    //~^ ERROR expected non-macro attribute, found attribute macro
+    //~| ERROR expected non-macro attribute, found attribute macro
     fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8) {}
-    //~^ ERROR expected an inert attribute, found an attribute macro
-    //~| ERROR expected an inert attribute, found an attribute macro
+    //~^ ERROR expected non-macro attribute, found attribute macro
+    //~| ERROR expected non-macro attribute, found attribute macro
 }
 
 trait A {
     fn trait1(#[id] self, #[id] arg1: u8);
-    //~^ ERROR expected an inert attribute, found an attribute macro
-    //~| ERROR expected an inert attribute, found an attribute macro
+    //~^ ERROR expected non-macro attribute, found attribute macro
+    //~| ERROR expected non-macro attribute, found attribute macro
     fn trait2(#[id] &self, #[id] arg1: u8);
-    //~^ ERROR expected an inert attribute, found an attribute macro
-    //~| ERROR expected an inert attribute, found an attribute macro
+    //~^ ERROR expected non-macro attribute, found attribute macro
+    //~| ERROR expected non-macro attribute, found attribute macro
     fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8);
-    //~^ ERROR expected an inert attribute, found an attribute macro
-    //~| ERROR expected an inert attribute, found an attribute macro
+    //~^ ERROR expected non-macro attribute, found attribute macro
+    //~| ERROR expected non-macro attribute, found attribute macro
     fn trait4<'a>(#[id] self: Box<Self>, #[id] arg1: u8, #[id] Vec<u8>);
-    //~^ ERROR expected an inert attribute, found an attribute macro
-    //~| ERROR expected an inert attribute, found an attribute macro
-    //~| ERROR expected an inert attribute, found an attribute macro
+    //~^ ERROR expected non-macro attribute, found attribute macro
+    //~| ERROR expected non-macro attribute, found attribute macro
+    //~| ERROR expected non-macro attribute, found attribute macro
     fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8);
-    //~^ ERROR expected an inert attribute, found an attribute macro
-    //~| ERROR expected an inert attribute, found an attribute macro
+    //~^ ERROR expected non-macro attribute, found attribute macro
+    //~| ERROR expected non-macro attribute, found attribute macro
 }
 
 fn main() {}
index 1cc3c3d82281bb1579c2442dd996f0de20ce5904..38c5050f3428dd932e2cd9e30bdf6b3c3573e121 100644 (file)
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:10:21
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:10:23
    |
 LL | extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); }
-   |                     ^^^^^
+   |                       ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:10:38
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:10:40
    |
 LL | extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); }
-   |                                      ^^^^^
+   |                                        ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:14:38
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:14:40
    |
 LL | unsafe extern "C" fn cvar(arg1: i32, #[id] mut args: ...) {}
-   |                                      ^^^^^
+   |                                        ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:17:28
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:17:30
    |
 LL | type Alias = extern "C" fn(#[id] u8, #[id] ...);
-   |                            ^^^^^
+   |                              ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:17:38
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:17:40
    |
 LL | type Alias = extern "C" fn(#[id] u8, #[id] ...);
-   |                                      ^^^^^
+   |                                        ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:21:9
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:21:11
    |
 LL | fn free(#[id] arg1: u8) {
-   |         ^^^^^
+   |           ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:23:16
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:23:18
    |
 LL |     let lam = |#[id] W(x), #[id] y: usize| ();
-   |                ^^^^^
+   |                  ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:23:28
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:23:30
    |
 LL |     let lam = |#[id] W(x), #[id] y: usize| ();
-   |                            ^^^^^
+   |                              ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:29:18
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:29:20
    |
 LL |     fn inherent1(#[id] self, #[id] arg1: u8) {}
-   |                  ^^^^^
+   |                    ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:29:30
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:29:32
    |
 LL |     fn inherent1(#[id] self, #[id] arg1: u8) {}
-   |                              ^^^^^
+   |                                ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:32:18
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:32:20
    |
 LL |     fn inherent2(#[id] &self, #[id] arg1: u8) {}
-   |                  ^^^^^
+   |                    ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:32:31
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:32:33
    |
 LL |     fn inherent2(#[id] &self, #[id] arg1: u8) {}
-   |                               ^^^^^
+   |                                 ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:35:22
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:35:24
    |
 LL |     fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {}
-   |                      ^^^^^
+   |                        ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:35:42
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:35:44
    |
 LL |     fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {}
-   |                                          ^^^^^
+   |                                            ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:38:22
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:38:24
    |
 LL |     fn inherent4<'a>(#[id] self: Box<Self>, #[id] arg1: u8) {}
-   |                      ^^^^^
+   |                        ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:38:45
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:38:47
    |
 LL |     fn inherent4<'a>(#[id] self: Box<Self>, #[id] arg1: u8) {}
-   |                                             ^^^^^
+   |                                               ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:41:38
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:41:40
    |
 LL |     fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8) {}
-   |                                      ^^^^^
+   |                                        ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:41:54
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:41:56
    |
 LL |     fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8) {}
-   |                                                      ^^^^^
+   |                                                        ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:47:15
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:47:17
    |
 LL |     fn trait1(#[id] self, #[id] arg1: u8);
-   |               ^^^^^
+   |                 ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:47:27
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:47:29
    |
 LL |     fn trait1(#[id] self, #[id] arg1: u8);
-   |                           ^^^^^
+   |                             ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:50:15
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:50:17
    |
 LL |     fn trait2(#[id] &self, #[id] arg1: u8);
-   |               ^^^^^
+   |                 ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:50:28
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:50:30
    |
 LL |     fn trait2(#[id] &self, #[id] arg1: u8);
-   |                            ^^^^^
+   |                              ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:53:19
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:53:21
    |
 LL |     fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8);
-   |                   ^^^^^
+   |                     ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:53:39
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:53:41
    |
 LL |     fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8);
-   |                                       ^^^^^
+   |                                         ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:56:19
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:56:21
    |
 LL |     fn trait4<'a>(#[id] self: Box<Self>, #[id] arg1: u8, #[id] Vec<u8>);
-   |                   ^^^^^
+   |                     ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:56:42
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:56:44
    |
 LL |     fn trait4<'a>(#[id] self: Box<Self>, #[id] arg1: u8, #[id] Vec<u8>);
-   |                                          ^^^^^
+   |                                            ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:56:58
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:56:60
    |
 LL |     fn trait4<'a>(#[id] self: Box<Self>, #[id] arg1: u8, #[id] Vec<u8>);
-   |                                                          ^^^^^
+   |                                                            ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:60:38
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:60:40
    |
 LL |     fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8);
-   |                                      ^^^^^
+   |                                        ^^ not a non-macro attribute
 
-error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:60:54
+error: expected non-macro attribute, found attribute macro `id`
+  --> $DIR/proc-macro-cannot-be-used.rs:60:56
    |
 LL |     fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8);
-   |                                                      ^^^^^
+   |                                                        ^^ not a non-macro attribute
 
 error: aborting due to 29 previous errors
 
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs
new file mode 100644 (file)
index 0000000..6a511f4
--- /dev/null
@@ -0,0 +1,27 @@
+//! Basic test for calling methods on generic type parameters in `const fn`.
+
+// check-pass
+
+#![feature(const_fn)]
+#![feature(const_trait_impl)]
+#![allow(incomplete_features)]
+
+struct S;
+
+impl const PartialEq for S {
+    fn eq(&self, _: &S) -> bool {
+        true
+    }
+}
+
+const fn equals_self<T: PartialEq>(t: &T) -> bool {
+    *t == *t
+}
+
+const fn equals_self_wrapper<T: PartialEq>(t: &T) -> bool {
+    equals_self(t)
+}
+
+pub const EQ: bool = equals_self_wrapper(&S);
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs
new file mode 100644 (file)
index 0000000..b39d277
--- /dev/null
@@ -0,0 +1,24 @@
+// check-pass
+
+#![feature(const_fn)]
+#![feature(const_trait_impl)]
+#![feature(const_trait_bound_opt_out)]
+#![allow(incomplete_features)]
+
+struct S;
+
+impl const PartialEq for S {
+    fn eq(&self, _: &S) -> bool {
+        true
+    }
+}
+
+// This duplicate bound should not result in ambiguities. It should be equivalent to a single const
+// bound.
+const fn equals_self<T: PartialEq + ?const PartialEq>(t: &T) -> bool {
+    *t == *t
+}
+
+pub const EQ: bool = equals_self(&S);
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs
new file mode 100644 (file)
index 0000000..6d4bfe7
--- /dev/null
@@ -0,0 +1,11 @@
+#![feature(const_fn)]
+#![feature(const_trait_impl)]
+#![feature(const_trait_bound_opt_out)]
+#![allow(incomplete_features)]
+
+pub const fn equals_self<T: ?const PartialEq>(t: &T) -> bool {
+    *t == *t
+    //~^ ERROR calls in constant functions are limited to constant functions
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr
new file mode 100644 (file)
index 0000000..4b2fc56
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/call-generic-method-fail.rs:7:5
+   |
+LL |     *t == *t
+   |     ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-opt-out.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-opt-out.rs
new file mode 100644 (file)
index 0000000..f0e3214
--- /dev/null
@@ -0,0 +1,24 @@
+// check-pass
+
+#![feature(const_fn)]
+#![feature(const_trait_impl)]
+#![feature(const_trait_bound_opt_out)]
+#![allow(incomplete_features)]
+
+struct S;
+
+impl PartialEq for S {
+    fn eq(&self, _: &S) -> bool {
+        true
+    }
+}
+
+const fn equals_self<T: ?const PartialEq>(t: &T) -> bool {
+    true
+}
+
+pub const EQ: bool = equals_self(&S);
+
+// Calling `equals_self` with a type that only has a non-const impl is fine, because we opted out.
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
new file mode 100644 (file)
index 0000000..2c8f635
--- /dev/null
@@ -0,0 +1,26 @@
+// FIXME(jschievink): this is not rejected correctly (only when the non-const impl is actually used)
+// ignore-test
+
+#![feature(const_fn)]
+#![feature(const_trait_impl)]
+#![allow(incomplete_features)]
+
+struct S;
+
+impl PartialEq for S {
+    fn eq(&self, _: &S) -> bool {
+        true
+    }
+}
+
+const fn equals_self<T: PartialEq>(t: &T) -> bool {
+    true
+}
+
+// Calling `equals_self` with something that has a non-const impl should throw an error, despite
+// it not using the impl.
+
+pub const EQ: bool = equals_self(&S);
+//~^ ERROR
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs
new file mode 100644 (file)
index 0000000..e968e6e
--- /dev/null
@@ -0,0 +1,23 @@
+//! Basic test for calling methods on generic type parameters in `const fn`.
+
+// check-pass
+
+#![feature(const_fn)]
+#![feature(const_trait_impl)]
+#![allow(incomplete_features)]
+
+struct S;
+
+impl const PartialEq for S {
+    fn eq(&self, _: &S) -> bool {
+        true
+    }
+}
+
+const fn equals_self<T: PartialEq>(t: &T) -> bool {
+    *t == *t
+}
+
+pub const EQ: bool = equals_self(&S);
+
+fn main() {}
index 53b8fddcf31e0b64001f1262efc953d621b252b0..c454dfa4eb93bf3074135711d3fb7abd4d234373 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 #![allow(dead_code)]
-// ignore-cloudabi stdout does not map to file descriptor 1 by default
 // ignore-wasm32-bare no libc
 // ignore-sgx no libc
 
index 3fc631be60ed900935eaca7a84e36106e536a669..c321e86dc18216a5217bc5180efa49c908197069 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi spawning processes is not supported
 // ignore-emscripten spawning processes is not supported
 // ignore-sgx no processes
 
index 8fef66eac8de208d568ce678af9b4af32831383e..15fcf78893ebb496a6aa8bb57e9b61de29259492 100644 (file)
@@ -3,7 +3,6 @@
 // main thread exit while still being in use by signal handlers. This test
 // triggers this situation by sending signal from atexit handler.
 //
-// ignore-cloudabi no signal handling support
 // ignore-wasm32-bare no libc
 // ignore-windows
 // ignore-sgx no libc
index bd34a2181603b1cf5143125ee31c7940b0522713..0963dcc80f6bfcea48452aeb2889cc324d0a7582 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 // ignore-windows
index f472029b820b8fbfdbb68537e51a62550e0549c2..144eeca23184b16743a4f5f706db4857321714b4 100644 (file)
@@ -4,7 +4,6 @@
 // Be sure that when a SIGPIPE would have been received that the entire process
 // doesn't die in a ball of fire, but rather it's gracefully handled.
 
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
index cef123d697bcd6f42a5ae483a944f77e54b596dd..5d927a5acc8d230f1be03d4c6d10595f4ff203fe 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-cloudabi no std::net support
-
 use std::net::TcpListener;
 use std::net::TcpStream;
 use std::io::{self, Read, Write};
index 46f36679b89fbe61233de1910e5a7378c9ccb217..473d36c2ab1e332afe6ad4f0e09e3033c7516064 100644 (file)
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-33884.rs:8:22
+  --> $DIR/issue-33884.rs:6:22
    |
 LL |     stream.write_fmt(format!("message received"))
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Arguments`, found struct `String`
index 4776740d8de9087e58e3af488837a11ba7a5c803..70e04bf7ee6e81216918bf504e5925ef0596fb1d 100644 (file)
@@ -6,7 +6,7 @@
 
 #[foo]
 mod foo {
-    #![foo] //~ ERROR non-builtin inner attributes are unstable
+    #![foo] //~ ERROR custom inner attributes are unstable
 }
 
 fn main() {}
index 79b12590fc53833edca03650fc51cfde97ee2f7d..a998d7217a13f563322a74698f5f29addd1c408c 100644 (file)
@@ -1,8 +1,8 @@
-error[E0658]: non-builtin inner attributes are unstable
-  --> $DIR/issue-36530.rs:9:5
+error[E0658]: custom inner attributes are unstable
+  --> $DIR/issue-36530.rs:9:8
    |
 LL |     #![foo]
-   |     ^^^^^^^
+   |        ^^^
    |
    = note: see issue #54726 <https://github.com/rust-lang/rust/issues/54726> for more information
    = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable
index 89b8eba1e95e77b8b5cb841ba53b38abb90ff6bb..8f1599a5abcb0fbf98e965e8cf84dcff70d9f108 100644 (file)
@@ -5,9 +5,6 @@
 //~| ERROR cannot determine resolution for the derive macro `Debug`
 //~| ERROR cannot determine resolution for the derive macro `PartialEq`
 //~| ERROR cannot determine resolution for the derive macro `Eq`
-//~| ERROR cannot determine resolution for the derive macro `Debug`
-//~| ERROR cannot determine resolution for the derive macro `PartialEq`
-//~| ERROR cannot determine resolution for the derive macro `Eq`
 struct DerivedOn;
 
 fn main() {}
index b160a4e5877d576fe2ef3e6cd2427de4c5b584b1..85beac535c965616031408ae8c2d8b1938fc992e 100644 (file)
@@ -28,30 +28,6 @@ LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
    |
    = note: import resolution is stuck, try simplifying macro imports
 
-error: cannot determine resolution for the derive macro `Eq`
-  --> $DIR/issue-43927-non-ADT-derive.rs:3:29
-   |
-LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
-   |                             ^^
-   |
-   = note: import resolution is stuck, try simplifying macro imports
-
-error: cannot determine resolution for the derive macro `PartialEq`
-  --> $DIR/issue-43927-non-ADT-derive.rs:3:18
-   |
-LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
-   |                  ^^^^^^^^^
-   |
-   = note: import resolution is stuck, try simplifying macro imports
-
-error: cannot determine resolution for the derive macro `Debug`
-  --> $DIR/issue-43927-non-ADT-derive.rs:3:11
-   |
-LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
-   |           ^^^^^
-   |
-   = note: import resolution is stuck, try simplifying macro imports
-
-error: aborting due to 7 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0774`.
index 17897d8b803d9a967ed33c674e93e7f9a172dd53..b3cd8255bb9b10f84473a5e716df2a15449b6035 100644 (file)
@@ -1,6 +1,6 @@
 // Make sure specialization cannot change impl polarity
 
-#![feature(optin_builtin_traits)]
+#![feature(auto_traits)]
 #![feature(negative_impls)]
 #![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
index 7726972b95b6465faee6206638f8ddd096eebe43..172f4079821a72d28065ad4096521f89517efea1 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no std::env
 
 #![allow(stable_features)]
 #![feature(cfg_target_feature)]
index 902a2b6f5a0e96aa330e51701c6387f33ee4a088..b5e76666af1f8eb65c6ad2c89c5bc6ce83c9c7ba 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 // ignore-android FIXME #17520
-// ignore-cloudabi spawning processes is not supported
 // ignore-emscripten spawning processes is not supported
 // ignore-openbsd no support for libbacktrace without filename
 // ignore-sgx no processes
index e96406e46b57b6bed640e3e7d2a4a4006cd198e0..4b67dbf79e007df73aab5712d71e4281e9354642 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
index dece3dcd54b2f629827ba89f78b7ca7489c16ce9..111b9ba94773fb2913dc100785a436d976226d16 100644 (file)
 pub struct Foo;
 impl Foo {
     pub fn foo() {
-        enum Panic { Common };
+        enum Panic { Common }
     }
     pub fn bar() {
-        enum Panic { Common };
+        enum Panic { Common }
     }
 }
 
index b06e204d31bf036627761b8235956bea9329b76a..69544b1c0603633c3a9b96b5085a7658c4d240ec 100644 (file)
@@ -32,7 +32,6 @@ struct Outer {
 
 
 #[cfg(any(target_os = "android",
-          target_os = "cloudabi",
           target_os = "dragonfly",
           target_os = "emscripten",
           target_os = "freebsd",
index 1ada54cc102ed022fe0e9b6de98fdbaf0eefc4e9..05bd98df0064ae45c3249c5150fff92f0ea5feaa 100644 (file)
@@ -6,7 +6,7 @@
 //[legacy]normalize-stderr-32bit: "hee444285569b39c2" -> "SYMBOL_HASH"
 //[legacy]normalize-stderr-64bit: "h310ea0259fc3d32d" -> "SYMBOL_HASH"
 
-#![feature(optin_builtin_traits, rustc_attrs)]
+#![feature(auto_traits, rustc_attrs)]
 #![allow(dead_code)]
 
 mod foo {
index 08b47dc531857c1ef493f5f94378f3f5d0eb6a29..175663643403bdf47194e8daabd24805f9f0ac38 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 // ignore-android needs extra network permissions
-// ignore-cloudabi no global network namespace access
 // ignore-emscripten no threads or sockets support
 // ignore-netbsd system ulimit (Too many open files)
 // ignore-openbsd system ulimit (Too many open files)
index 15e10dc250f19b87ac710c86aa023e19481ca9bb..b8ae214dc09b1a3caaf91c3b9c7acbddd9147e2c 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 
-// ignore-cloudabi networking not available
 // ignore-wasm32-bare networking not available
 // ignore-sgx ToSocketAddrs cannot be used for DNS Resolution
 
diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait-auto-trait.rs b/src/test/ui/traits/traits-inductive-overflow-supertrait-auto-trait.rs
new file mode 100644 (file)
index 0000000..5fea47a
--- /dev/null
@@ -0,0 +1,18 @@
+// Auto-trait-based version of #29859, supertrait version. Test that using
+// a simple auto trait `..` impl alone still doesn't allow arbitrary bounds
+// to be synthesized.
+
+#![feature(auto_traits)]
+#![feature(negative_impls)]
+
+auto trait Magic: Copy {} //~ ERROR E0568
+
+fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
+
+#[derive(Debug)]
+struct NoClone;
+
+fn main() {
+    let (a, b) = copy(NoClone); //~ ERROR
+    println!("{:?} {:?}", a, b);
+}
diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait-auto-trait.stderr b/src/test/ui/traits/traits-inductive-overflow-supertrait-auto-trait.stderr
new file mode 100644 (file)
index 0000000..140ffa4
--- /dev/null
@@ -0,0 +1,23 @@
+error[E0568]: auto traits cannot have super traits
+  --> $DIR/traits-inductive-overflow-supertrait-auto-trait.rs:8:19
+   |
+LL | auto trait Magic: Copy {}
+   |            -----  ^^^^ help: remove the super traits
+   |            |
+   |            auto trait cannot have super traits
+
+error[E0277]: the trait bound `NoClone: Copy` is not satisfied
+  --> $DIR/traits-inductive-overflow-supertrait-auto-trait.rs:16:23
+   |
+LL | fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
+   |            ----- required by this bound in `copy`
+...
+LL |     let (a, b) = copy(NoClone);
+   |                       ^^^^^^^ the trait `Copy` is not implemented for `NoClone`
+   |
+   = note: required because of the requirements on the impl of `Magic` for `NoClone`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0568.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.rs b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.rs
deleted file mode 100644 (file)
index 571f934..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// OIBIT-based version of #29859, supertrait version. Test that using
-// a simple OIBIT `..` impl alone still doesn't allow arbitrary bounds
-// to be synthesized.
-
-#![feature(optin_builtin_traits)]
-#![feature(negative_impls)]
-
-auto trait Magic: Copy {} //~ ERROR E0568
-
-fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
-
-#[derive(Debug)]
-struct NoClone;
-
-fn main() {
-    let (a, b) = copy(NoClone); //~ ERROR
-    println!("{:?} {:?}", a, b);
-}
diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr
deleted file mode 100644 (file)
index c11234e..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-error[E0568]: auto traits cannot have super traits
-  --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:8:19
-   |
-LL | auto trait Magic: Copy {}
-   |            -----  ^^^^ help: remove the super traits
-   |            |
-   |            auto trait cannot have super traits
-
-error[E0277]: the trait bound `NoClone: Copy` is not satisfied
-  --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:16:23
-   |
-LL | fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
-   |            ----- required by this bound in `copy`
-...
-LL |     let (a, b) = copy(NoClone);
-   |                       ^^^^^^^ the trait `Copy` is not implemented for `NoClone`
-   |
-   = note: required because of the requirements on the impl of `Magic` for `NoClone`
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0277, E0568.
-For more information about an error, try `rustc --explain E0277`.
index dfb05599be6bac67cb6197d51a94bffd9dd69aff..90f56d5fa71d164324e220f0647dda9216a189d0 100644 (file)
@@ -5,7 +5,7 @@
 
 fn main() {
     let try = 2;
-    struct try { try: u32 };
+    struct try { try: u32 }
     let try: try = try { try };
     assert_eq!(try.try, 2);
 }
index a8a99a150c1ae06a2954cca8c8d4ba5d380eacd5..e1b6cfbe5ae1b6741dcf6affad1a6fb81f6f6f61 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-cloudabi no std::fs support
-
 #![feature(try_trait)]
 
 use std::ops::Try;
index f2e17812aed8046ae5a36f202c23e77f68f0e3c4..be17de2fe7cc077028e92eaf908cd4e73e48e3f1 100644 (file)
@@ -1,5 +1,5 @@
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`)
-  --> $DIR/try-operator-on-main.rs:9:5
+  --> $DIR/try-operator-on-main.rs:7:5
    |
 LL | / fn main() {
 LL | |     // error for a `Try` type on a non-`Try` fn
@@ -15,7 +15,7 @@ LL | | }
    = note: required by `from_error`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/try-operator-on-main.rs:12:5
+  --> $DIR/try-operator-on-main.rs:10:5
    |
 LL |     ()?;
    |     ^^^ the `?` operator cannot be applied to type `()`
@@ -24,7 +24,7 @@ LL |     ()?;
    = note: required by `into_result`
 
 error[E0277]: the trait bound `(): Try` is not satisfied
-  --> $DIR/try-operator-on-main.rs:15:25
+  --> $DIR/try-operator-on-main.rs:13:25
    |
 LL |     try_trait_generic::<()>();
    |                         ^^ the trait `Try` is not implemented for `()`
@@ -33,7 +33,7 @@ LL | fn try_trait_generic<T: Try>() -> T {
    |                         --- required by this bound in `try_trait_generic`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/try-operator-on-main.rs:22:5
+  --> $DIR/try-operator-on-main.rs:20:5
    |
 LL |     ()?;
    |     ^^^ the `?` operator cannot be applied to type `()`
index 9118e8e7134593dc8402d73d845a5c3af2e25c4e..516ae4c4090dc55bf4ed07227191d2e2006a88b1 100644 (file)
@@ -1,7 +1,6 @@
 // run-pass
 
 #![allow(dead_code)]
-// ignore-cloudabi no std::fs
 
 use std::fs::File;
 use std::io::{Read, self};
index d8a07c55cf266d7f9afa48bee6d3df4ad54e1f13..692197210b15fdce27038d55aebbb15ee3b6691b 100644 (file)
@@ -1,7 +1,6 @@
 // run-pass
 
 #![allow(stable_features)]
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
index c0d39c59014eca7d094d19ad13c876f2e9a0abc0..3aad085f0897295c184ff97f76482fa63e0996c0 100644 (file)
@@ -7,7 +7,7 @@ pub fn new() -> Self {
         input_cells: Vec::new()
         //~^ ERROR cannot find value `input_cells` in this scope
         //~| ERROR parenthesized type parameters may only be used with a `Fn` trait
-        //~| ERROR wrong number of type arguments: expected 1, found 0
+        //~| ERROR wrong number of type arguments: expected at least 1, found 0
     }
 }
 
index 7895cf77fc0bf0cacf93bffd8f45746b7aa12145..402e54d2a95ddf9270bb5149dc26da80c316ff46 100644 (file)
@@ -10,11 +10,11 @@ error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
 LL |         input_cells: Vec::new()
    |                           ^^^^^ only `Fn` traits may use parentheses
 
-error[E0107]: wrong number of type arguments: expected 1, found 0
+error[E0107]: wrong number of type arguments: expected at least 1, found 0
   --> $DIR/issue-34255-1.rs:7:22
    |
 LL |         input_cells: Vec::new()
-   |                      ^^^^^^^^^^ expected 1 type argument
+   |                      ^^^^^^^^^^ expected at least 1 type argument
 
 error: aborting due to 3 previous errors
 
index d00025b770861b20307bdc8a4afe93df61c02b0f..ef2cd415fcaaa22d8bba45b83a9af1c53817a7fd 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(optin_builtin_traits, core)]
+#![feature(auto_traits, core)]
 #![crate_type = "rlib"]
 
 pub auto trait DefaultedTrait { }
index 08b16c0e9ca3e144fb766eb4978b60784910c20f..2683590775904c433bbf061d11df9c6eb5f78ad7 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
 // ignore-vxworks no 'ps'
index 32a4df87fbe1215ee588869aed38e3a04e869c3a..e1136807b3c43e0f57bb9aebe2718d495a362049 100644 (file)
@@ -24,7 +24,6 @@ pub fn main() {
 }
 
 #[cfg(any(target_os = "android",
-          target_os = "cloudabi",
           target_os = "dragonfly",
           target_os = "emscripten",
           target_os = "freebsd",
index 98b5a439c82de00e651f42908cb493a34084dc21..fb87d8ea0ba7f0a52df9e639785492a6205f2289 100644 (file)
@@ -10,7 +10,7 @@ impl Drop for Foo {
         fn drop(&mut self) {
           unsafe { destructions -= 1 };
         }
-    };
+    }
 
     let _x = [Foo, Foo, Foo];
 }
index 687354dc6aee23e6740d846264d2c294aec33e36..0462efaa9b001fe5946c134db9c33a6abe4e4846 100644 (file)
@@ -57,7 +57,6 @@
     "aarch64-fuchsia",
     "aarch64-linux-android",
     "aarch64-pc-windows-msvc",
-    "aarch64-unknown-cloudabi",
     "aarch64-unknown-hermit",
     "aarch64-unknown-linux-gnu",
     "aarch64-unknown-linux-musl",
     "x86_64-rumprun-netbsd",
     "x86_64-sun-solaris",
     "x86_64-pc-solaris",
-    "x86_64-unknown-cloudabi",
     "x86_64-unknown-freebsd",
     "x86_64-unknown-illumos",
     "x86_64-unknown-linux-gnu",
index 2af662e22177a839763ac8fb70d245a680b15214..bfca1cd22bf514d5f2b6c1089b0ded0ba7dfaa6e 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 2af662e22177a839763ac8fb70d245a680b15214
+Subproject commit bfca1cd22bf514d5f2b6c1089b0ded0ba7dfaa6e
index 6c92e10522c99feb0e7f07bf7d6e66a9e0ecde96..a3f114e0bb34f4e64c8eb233afa49b344d106f33 100644 (file)
@@ -1,8 +1,8 @@
 Thank you for making Clippy better!
 
 We're collecting our changelog from pull request descriptions.
-If your PR only updates to the latest nightly, you can leave the
-`changelog` entry as `none`. Otherwise, please write a short comment
+If your PR only includes internal changes, you can just write
+`changelognone`. Otherwise, please write a short comment
 explaining your change.
 
 If your PR fixes an issue, you can add "fixes #issue_number" into this
@@ -28,5 +28,5 @@ Delete this line and everything above before opening your PR.
 
 ---
 
-*Please keep the line below*
-changelog: none
+*Please write a short comment explaining your change (or "none" for internal only changes)*
+changelog:
index 1b9b33803de26c29bc093fb6bb18274127b439b7..b9e4b0e67040cc89a6b4c9d84b76c67e28737648 100644 (file)
@@ -6,11 +6,117 @@ document.
 
 ## Unreleased / In Rust Nightly
 
-[e636b88...master](https://github.com/rust-lang/rust-clippy/compare/e636b88...master)
+[b20d4c1...master](https://github.com/rust-lang/rust-clippy/compare/b20d4c1...master)
+
+## Rust 1.49
+
+Current beta, release 2020-12-31
+
+[e636b88...b20d4c1](https://github.com/rust-lang/rust-clippy/compare/e636b88...b20d4c1)
+
+### New Lints
+
+* [`field_reassign_with_default`] [#5911](https://github.com/rust-lang/rust-clippy/pull/5911)
+* [`await_holding_refcell_ref`] [#6029](https://github.com/rust-lang/rust-clippy/pull/6029)
+* [`disallowed_method`] [#6081](https://github.com/rust-lang/rust-clippy/pull/6081)
+* [`inline_asm_x86_att_syntax`] [#6092](https://github.com/rust-lang/rust-clippy/pull/6092)
+* [`inline_asm_x86_intel_syntax`] [#6092](https://github.com/rust-lang/rust-clippy/pull/6092)
+* [`from_iter_instead_of_collect`] [#6101](https://github.com/rust-lang/rust-clippy/pull/6101)
+* [`mut_mutex_lock`] [#6103](https://github.com/rust-lang/rust-clippy/pull/6103)
+* [`single_element_loop`] [#6109](https://github.com/rust-lang/rust-clippy/pull/6109)
+* [`manual_unwrap_or`] [#6123](https://github.com/rust-lang/rust-clippy/pull/6123)
+* [`large_types_passed_by_value`] [#6135](https://github.com/rust-lang/rust-clippy/pull/6135)
+* [`result_unit_err`] [#6157](https://github.com/rust-lang/rust-clippy/pull/6157)
+* [`ref_option_ref`] [#6165](https://github.com/rust-lang/rust-clippy/pull/6165)
+* [`manual_range_contains`] [#6177](https://github.com/rust-lang/rust-clippy/pull/6177)
+* [`unusual_byte_groupings`] [#6183](https://github.com/rust-lang/rust-clippy/pull/6183)
+* [`comparison_to_empty`] [#6226](https://github.com/rust-lang/rust-clippy/pull/6226)
+* [`map_collect_result_unit`] [#6227](https://github.com/rust-lang/rust-clippy/pull/6227)
+* [`manual_ok_or`] [#6233](https://github.com/rust-lang/rust-clippy/pull/6233)
+
+### Moves and Deprecations
+
+* Rename `single_char_push_str` to [`single_char_add_str`]
+  [#6037](https://github.com/rust-lang/rust-clippy/pull/6037)
+* Rename `zero_width_space` to [`invisible_characters`]
+  [#6105](https://github.com/rust-lang/rust-clippy/pull/6105)
+* Deprecate [`drop_bounds`] (uplifted)
+  [#6111](https://github.com/rust-lang/rust-clippy/pull/6111)
+* Move [`string_lit_as_bytes`] to `nursery`
+  [#6117](https://github.com/rust-lang/rust-clippy/pull/6117)
+* Move [`rc_buffer`] to `restriction`
+  [#6128](https://github.com/rust-lang/rust-clippy/pull/6128)
+
+### Enhancements
+
+* [`manual_memcpy`]: Also lint when there are loop counters (and produce a
+  reliable suggestion)
+  [#5727](https://github.com/rust-lang/rust-clippy/pull/5727)
+* [`single_char_add_str`]: Also lint on `String::insert_str`
+  [#6037](https://github.com/rust-lang/rust-clippy/pull/6037)
+* [`invisible_characters`]: Also lint the characters `\u{AD}` and `\u{2060}`
+  [#6105](https://github.com/rust-lang/rust-clippy/pull/6105)
+* [`eq_op`]: Also lint on the `assert_*!` macro family
+  [#6167](https://github.com/rust-lang/rust-clippy/pull/6167)
+* [`items_after_statements`]: Also lint in local macro expansions
+  [#6176](https://github.com/rust-lang/rust-clippy/pull/6176)
+* [`unnecessary_cast`]: Also lint casts on integer and float literals
+  [#6187](https://github.com/rust-lang/rust-clippy/pull/6187)
+* [`manual_unwrap_or`]: Also lint `Result::unwrap_or`
+  [#6190](https://github.com/rust-lang/rust-clippy/pull/6190)
+* [`match_like_matches_macro`]: Also lint when `match` has more than two arms
+  [#6216](https://github.com/rust-lang/rust-clippy/pull/6216)
+* [`integer_arithmetic`]: Better handle `/` an `%` operators
+  [#6229](https://github.com/rust-lang/rust-clippy/pull/6229)
+
+### False Positive Fixes
+
+* [`needless_lifetimes`]: Bail out if the function has a `where` clause with the
+  lifetime [#5978](https://github.com/rust-lang/rust-clippy/pull/5978)
+* [`explicit_counter_loop`]: No longer lints, when loop counter is used after it
+  is incremented [#6076](https://github.com/rust-lang/rust-clippy/pull/6076)
+* [`or_fun_call`]: Revert changes addressing the handling of `const fn`
+  [#6077](https://github.com/rust-lang/rust-clippy/pull/6077)
+* [`needless_range_loop`]: No longer lints, when the iterable is used in the
+  range [#6102](https://github.com/rust-lang/rust-clippy/pull/6102)
+* [`inconsistent_digit_grouping`]: Fix bug when using floating point exponent
+  [#6104](https://github.com/rust-lang/rust-clippy/pull/6104)
+* [`mistyped_literal_suffixes`]: No longer lints on the fractional part of a
+  float (e.g. `713.32_64`)
+  [#6114](https://github.com/rust-lang/rust-clippy/pull/6114)
+* [`invalid_regex`]: No longer lint on unicode characters within `bytes::Regex`
+  [#6132](https://github.com/rust-lang/rust-clippy/pull/6132)
+* [`boxed_local`]: No longer lints on `extern fn` arguments
+  [#6133](https://github.com/rust-lang/rust-clippy/pull/6133)
+* [`needless_lifetimes`]: Fix regression, where lifetime is used in `where`
+  clause [#6198](https://github.com/rust-lang/rust-clippy/pull/6198)
+
+### Suggestion Fixes/Improvements
+
+* [`unnecessary_sort_by`]: Avoid dereferencing the suggested closure parameter
+  [#6078](https://github.com/rust-lang/rust-clippy/pull/6078)
+* [`needless_arbitrary_self_type`]: Correctly handle expanded code
+  [#6093](https://github.com/rust-lang/rust-clippy/pull/6093)
+* [`useless_format`]: Preserve raw strings in suggestion
+  [#6151](https://github.com/rust-lang/rust-clippy/pull/6151)
+* [`empty_loop`]: Suggest alternatives
+  [#6162](https://github.com/rust-lang/rust-clippy/pull/6162)
+* [`borrowed_box`]: Correctly add parentheses in suggestion
+  [#6200](https://github.com/rust-lang/rust-clippy/pull/6200)
+* [`unused_unit`]: Improve suggestion formatting
+  [#6247](https://github.com/rust-lang/rust-clippy/pull/6247)
+
+### Documentation Improvements
+
+* Some doc improvements:
+    * [`rc_buffer`] [#6090](https://github.com/rust-lang/rust-clippy/pull/6090)
+    * [`empty_loop`] [#6162](https://github.com/rust-lang/rust-clippy/pull/6162)
+* [`doc_markdown`]: Document problematic link text style
+  [#6107](https://github.com/rust-lang/rust-clippy/pull/6107)
 
 ## Rust 1.48
 
-Current beta, release 2020-11-19
+Current stable, released 2020-11-19
 
 [09bd400...e636b88](https://github.com/rust-lang/rust-clippy/compare/09bd400...e636b88)
 
@@ -56,7 +162,7 @@ Current beta, release 2020-11-19
 
 * [`useless_attribute`]: permit allowing [`wildcard_imports`] and [`enum_glob_use`]
   [#5994](https://github.com/rust-lang/rust-clippy/pull/5994)
-* [`transmute_ptr_to_ptr`]: avoid suggesting dereferencing raw pointers in const contexts 
+* [`transmute_ptr_to_ptr`]: avoid suggesting dereferencing raw pointers in const contexts
   [#5999](https://github.com/rust-lang/rust-clippy/pull/5999)
 * [`redundant_closure_call`]: take into account usages of the closure in nested functions and closures
   [#5920](https://github.com/rust-lang/rust-clippy/pull/5920)
@@ -64,7 +170,7 @@ Current beta, release 2020-11-19
   [#5949](https://github.com/rust-lang/rust-clippy/pull/5949)
 * [`doc_markdown`]: allow using "GraphQL" without backticks
   [#5996](https://github.com/rust-lang/rust-clippy/pull/5996)
-* [`to_string_in_display`]: avoid linting when calling `to_string()` on anything that is not `self` 
+* [`to_string_in_display`]: avoid linting when calling `to_string()` on anything that is not `self`
   [#5971](https://github.com/rust-lang/rust-clippy/pull/5971)
 * [`indexing_slicing`] and [`out_of_bounds_indexing`] treat references to arrays as arrays
   [#6034](https://github.com/rust-lang/rust-clippy/pull/6034)
@@ -85,19 +191,19 @@ Current beta, release 2020-11-19
   [#5946](https://github.com/rust-lang/rust-clippy/pull/5946)
 * [`useless_conversion`]: show the type in the error message
   [#6035](https://github.com/rust-lang/rust-clippy/pull/6035)
-* [`unnecessary_mut_passed`]: discriminate between functions and methods in the error message 
+* [`unnecessary_mut_passed`]: discriminate between functions and methods in the error message
   [#5892](https://github.com/rust-lang/rust-clippy/pull/5892)
 * [`float_cmp`] and [`float_cmp_const`]: change wording to make margin of error less ambiguous
   [#6043](https://github.com/rust-lang/rust-clippy/pull/6043)
 * [`default_trait_access`]: do not use unnecessary type parameters in the suggestion
   [#5993](https://github.com/rust-lang/rust-clippy/pull/5993)
-* [`collapsible_if`]: don't use expanded code in the suggestion 
+* [`collapsible_if`]: don't use expanded code in the suggestion
   [#5992](https://github.com/rust-lang/rust-clippy/pull/5992)
 * Do not suggest empty format strings in [`print_with_newline`] and [`write_with_newline`]
   [#6042](https://github.com/rust-lang/rust-clippy/pull/6042)
 * [`unit_arg`]: improve the readability of the suggestion
   [#5931](https://github.com/rust-lang/rust-clippy/pull/5931)
-* [`stable_sort_primitive`]: print the type that is being sorted in the lint message 
+* [`stable_sort_primitive`]: print the type that is being sorted in the lint message
   [#5935](https://github.com/rust-lang/rust-clippy/pull/5935)
 * Show line count and max lines in [`too_many_lines`] lint message
   [#6009](https://github.com/rust-lang/rust-clippy/pull/6009)
@@ -105,7 +211,7 @@ Current beta, release 2020-11-19
   [#5900](https://github.com/rust-lang/rust-clippy/pull/5900)
 * [`option_map_unit_fn`] and [`result_map_unit_fn`]: print the unit type `()` explicitly
   [#6024](https://github.com/rust-lang/rust-clippy/pull/6024)
-* [`redundant_allocation`]: suggest replacing `Rc<Box<T>>` with `Rc<T>` 
+* [`redundant_allocation`]: suggest replacing `Rc<Box<T>>` with `Rc<T>`
   [#5899](https://github.com/rust-lang/rust-clippy/pull/5899)
 * Make lint messages adhere to rustc dev guide conventions
   [#5893](https://github.com/rust-lang/rust-clippy/pull/5893)
@@ -128,7 +234,7 @@ Current beta, release 2020-11-19
 
 ## Rust 1.47
 
-Current stable, released 2020-10-08
+Released 2020-10-08
 
 [c2c07fa...09bd400](https://github.com/rust-lang/rust-clippy/compare/c2c07fa...09bd400)
 
@@ -1787,6 +1893,7 @@ Released 2018-09-13
 [`len_without_is_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_without_is_empty
 [`len_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_zero
 [`let_and_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return
+[`let_underscore_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_drop
 [`let_underscore_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_lock
 [`let_underscore_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_must_use
 [`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value
@@ -1956,6 +2063,7 @@ Released 2018-09-13
 [`string_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add
 [`string_add_assign`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add_assign
 [`string_extend_chars`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_extend_chars
+[`string_from_utf8_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_from_utf8_as_bytes
 [`string_lit_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_lit_as_bytes
 [`string_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_to_string
 [`struct_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools
@@ -2006,6 +2114,7 @@ Released 2018-09-13
 [`unnecessary_operation`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_operation
 [`unnecessary_sort_by`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_sort_by
 [`unnecessary_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap
+[`unnecessary_wraps`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps
 [`unneeded_field_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#unneeded_field_pattern
 [`unneeded_wildcard_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#unneeded_wildcard_pattern
 [`unnested_or_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns
index 8a5975e1f9711b25878cc04d41d7215f3562b3be..1da626b505dfb9e1da2978c909a392acba24dcc7 100644 (file)
@@ -7,28 +7,22 @@ A collection of lints to catch common mistakes and improve your [Rust](https://g
 
 [There are over 400 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
 
-We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:
-
-* `clippy::all` (everything that is on by default: all the categories below except for `nursery`, `pedantic`, and `cargo`)
-* `clippy::correctness` (code that is just **outright wrong** or **very very useless**, causes hard errors by default)
-* `clippy::style` (code that should be written in a more idiomatic way)
-* `clippy::complexity` (code that does something simple but in a complex way)
-* `clippy::perf` (code that can be written in a faster way)
-* `clippy::pedantic` (lints which are rather strict, off by default)
-* `clippy::nursery` (new lints that aren't quite ready yet, off by default)
-* `clippy::cargo` (checks against the cargo manifest, off by default)
+Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html).
+You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the lint level by category.
+
+Category | Description | Default level
+-- | -- | --
+`clippy::all` | all lints that are on by default (correctness, style, complexity, perf) | **warn/deny**
+`clippy::correctness` | code that is outright wrong or very useless | **deny**
+`clippy::style` | code that should be written in a more idiomatic way | **warn**
+`clippy::complexity` | code that does something simple but in a complex way | **warn**
+`clippy::perf` | code that can be written to run faster | **warn**
+`clippy::pedantic` | lints which are rather strict or might have false positives | allow
+`clippy::nursery` | new lints that are still under development | allow
+`clippy::cargo` | lints for the cargo manifest | allow
 
 More to come, please [file an issue](https://github.com/rust-lang/rust-clippy/issues) if you have ideas!
 
-Only the following of those categories are enabled by default:
-
-* `clippy::style`
-* `clippy::correctness`
-* `clippy::complexity`
-* `clippy::perf`
-
-Other categories need to be enabled in order for their lints to be executed.
-
 The [lint list](https://rust-lang.github.io/rust-clippy/master/index.html) also contains "restriction lints", which are
 for things which are usually not considered "bad", but may be useful to turn on in specific cases. These should be used
 very selectively, if at all.
index 556b67e0b3742ec1eee0165cf5937b38d8167d9b..fcf093f8835d866f7a2059521999ab75dd58c065 100644 (file)
@@ -22,20 +22,7 @@ pub fn run(update_mode: UpdateMode) {
 
     let usable_lint_count = round_to_fifty(usable_lints.len());
 
-    let mut file_change = replace_region_in_file(
-        Path::new("src/lintlist/mod.rs"),
-        "begin lint list",
-        "end lint list",
-        false,
-        update_mode == UpdateMode::Change,
-        || {
-            format!("vec!{:#?}", sorted_usable_lints)
-                .lines()
-                .map(ToString::to_string)
-                .collect::<Vec<_>>()
-        },
-    )
-    .changed;
+    let mut file_change = false;
 
     file_change |= replace_region_in_file(
         Path::new("README.md"),
index a2ccb0369c4a42c8dd25edae486b868f0d90deff..62c73dbac48b4a28f622158d525361242913d2bb 100644 (file)
@@ -129,8 +129,11 @@ fn match_assert_with_message<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>)
         if let ExprKind::Block(ref block, _) = arms[0].body.kind;
         if block.stmts.is_empty();
         if let Some(block_expr) = &block.expr;
-        if let ExprKind::Block(ref inner_block, _) = block_expr.kind;
-        if let Some(begin_panic_call) = &inner_block.expr;
+        // inner block is optional. unwrap it if it exists, or use the expression as is otherwise.
+        if let Some(begin_panic_call) = match block_expr.kind {
+            ExprKind::Block(ref inner_block, _) => &inner_block.expr,
+            _ => &block.expr,
+        };
         // function call
         if let Some(args) = match_panic_call(cx, begin_panic_call);
         if args.len() == 1;
index 57702dafa6a0ce8a878102a15443db90afdea860..15505fd79f4a1f6ac0c338de623b478c6b0c1268 100644 (file)
@@ -5,7 +5,7 @@
     span_lint_and_sugg, span_lint_and_then, without_block_comments,
 };
 use if_chain::if_chain;
-use rustc_ast::util::lev_distance::find_best_match_for_name;
+use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
 use rustc_errors::Applicability;
 use rustc_hir::{
@@ -40,7 +40,7 @@
 ];
 
 // NOTE: windows is excluded from the list because it's also a valid target family.
-static NON_UNIX_SYSTEMS: &[&str] = &["cloudabi", "hermit", "none", "wasi"];
+static NON_UNIX_SYSTEMS: &[&str] = &["hermit", "none", "wasi"];
 
 declare_clippy_lint! {
     /// **What it does:** Checks for items annotated with `#[inline(always)]`,
@@ -427,7 +427,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_>, ident: &str, items: &[NestedMet
                             .map(|l| Symbol::intern(&l.name_lower()))
                             .collect::<Vec<_>>();
                         let sugg = find_best_match_for_name(
-                            symbols.iter(),
+                            &symbols,
                             Symbol::intern(&format!("clippy::{}", name_lower)),
                             None,
                         );
index fcebb54c6c217840d3b5a2b7faa8f1249dc72a29..58892024ce2439cebfde97b587939df93c8bf406 100644 (file)
@@ -45,7 +45,7 @@
     /// }
     /// ```
     pub AWAIT_HOLDING_LOCK,
-    correctness,
+    pedantic,
     "Inside an async function, holding a MutexGuard while calling await"
 }
 
@@ -65,8 +65,8 @@
     /// use std::cell::RefCell;
     ///
     /// async fn foo(x: &RefCell<u32>) {
-    ///   let b = x.borrow_mut()();
-    ///   *ref += 1;
+    ///   let mut y = x.borrow_mut();
+    ///   *y += 1;
     ///   bar.await;
     /// }
     /// ```
     ///
     /// async fn foo(x: &RefCell<u32>) {
     ///   {
-    ///     let b = x.borrow_mut();
-    ///     *ref += 1;
+    ///      let mut y = x.borrow_mut();
+    ///      *y += 1;
     ///   }
     ///   bar.await;
     /// }
     /// ```
     pub AWAIT_HOLDING_REFCELL_REF,
-    correctness,
+    pedantic,
     "Inside an async function, holding a RefCell ref while calling await"
 }
 
index 76a000157df03dce006669941382b1b2e7af8bfd..0d294761af5ab9a844b48e3495a01ef57b661ab7 100644 (file)
     /// [package]
     /// name = "clippy"
     /// version = "0.0.212"
+    /// description = "A bunch of helpful lints to avoid common pitfalls in Rust"
+    /// repository = "https://github.com/rust-lang/rust-clippy"
+    /// readme = "README.md"
+    /// license = "MIT OR Apache-2.0"
+    /// keywords = ["clippy", "lint", "plugin"]
+    /// categories = ["development-tools", "development-tools::cargo-plugins"]
+    /// ```
+    ///
+    /// Should include an authors field like:
+    ///
+    /// ```toml
+    /// # This `Cargo.toml` includes all common metadata
+    /// [package]
+    /// name = "clippy"
+    /// version = "0.0.212"
     /// authors = ["Someone <someone@rust-lang.org>"]
     /// description = "A bunch of helpful lints to avoid common pitfalls in Rust"
     /// repository = "https://github.com/rust-lang/rust-clippy"
index 461c6e31d3eb40b2ad099246f598caf7f69714b9..1c3285ed701db19683379058e45f6a2c2453bd46 100644 (file)
@@ -181,3 +181,8 @@ macro_rules! declare_deprecated_lint {
     pub TEMPORARY_CSTRING_AS_PTR,
     "this lint has been uplifted to rustc and is now called `temporary_cstring_as_ptr`"
 }
+
+declare_deprecated_lint! {
+    pub PANIC_PARAMS,
+    "this lint has been uplifted to rustc and is now called `panic_fmt`"
+}
index d2a322e1223c660c6ff0b5977769f0b71ee76750..f9697afe405257aaab6a1e9341bce83cce7a364d 100644 (file)
@@ -68,7 +68,7 @@ fn check_fn(
             for &(p, _span) in preds {
                 let p = p.subst(cx.tcx, subst);
                 if let Some(trait_ref) = p.to_opt_poly_trait_ref() {
-                    if Some(trait_ref.def_id()) == cx.tcx.lang_items().future_trait() {
+                    if Some(trait_ref.value.def_id()) == cx.tcx.lang_items().future_trait() {
                         is_future = true;
                         break;
                     }
index 8e2f03d6e4e91641cfd93e22e75f958d10413c03..8842901d90b83dac9b9b7e638fbb0a774733dd0e 100644 (file)
@@ -69,7 +69,7 @@
 }
 
 declare_clippy_lint! {
-    /// **What it does:** Checks for comparing to an empty slice such as "" or [],`
+    /// **What it does:** Checks for comparing to an empty slice such as `""` or `[]`,
     /// and suggests using `.is_empty()` where applicable.
     ///
     /// **Why is this bad?** Some structures can answer `.is_empty()` much faster
index ae2f6131b5b8fb0bdf653081ca3c0f905c9c9886..6a5a77f8690a9be9b17c526c23e884cd1be6fa77 100644 (file)
@@ -5,7 +5,7 @@
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
-use crate::utils::{is_must_use_func_call, is_must_use_ty, match_type, paths, span_lint_and_help};
+use crate::utils::{implements_trait, is_must_use_func_call, is_must_use_ty, match_type, paths, span_lint_and_help};
 
 declare_clippy_lint! {
     /// **What it does:** Checks for `let _ = <expr>`
     "non-binding let on a synchronization lock"
 }
 
-declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK]);
+declare_clippy_lint! {
+    /// **What it does:** Checks for `let _ = <expr>`
+    /// where expr has a type that implements `Drop`
+    ///
+    /// **Why is this bad?** This statement immediately drops the initializer
+    /// expression instead of extending its lifetime to the end of the scope, which
+    /// is often not intended. To extend the expression's lifetime to the end of the
+    /// scope, use an underscore-prefixed name instead (i.e. _var). If you want to
+    /// explicitly drop the expression, `std::mem::drop` conveys your intention
+    /// better and is less error-prone.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    ///
+    /// Bad:
+    /// ```rust,ignore
+    /// struct Droppable;
+    /// impl Drop for Droppable {
+    ///     fn drop(&mut self) {}
+    /// }
+    /// {
+    ///     let _ = Droppable;
+    ///     //               ^ dropped here
+    ///     /* more code */
+    /// }
+    /// ```
+    ///
+    /// Good:
+    /// ```rust,ignore
+    /// {
+    ///     let _droppable = Droppable;
+    ///     /* more code */
+    ///     // dropped at end of scope
+    /// }
+    /// ```
+    pub LET_UNDERSCORE_DROP,
+    pedantic,
+    "non-binding let on a type that implements `Drop`"
+}
+
+declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_DROP]);
 
 const SYNC_GUARD_PATHS: [&[&str]; 3] = [
     &paths::MUTEX_GUARD,
@@ -84,6 +125,15 @@ fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) {
 
                     GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
                 });
+                let implements_drop = cx.tcx.lang_items().drop_trait().map_or(false, |drop_trait|
+                    init_ty.walk().any(|inner| match inner.unpack() {
+                        GenericArgKind::Type(inner_ty) => {
+                            implements_trait(cx, inner_ty, drop_trait, &[])
+                        },
+
+                        GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
+                    })
+                );
                 if contains_sync_guard {
                     span_lint_and_help(
                         cx,
@@ -94,6 +144,16 @@ fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) {
                         "consider using an underscore-prefixed named \
                             binding or dropping explicitly with `std::mem::drop`"
                     )
+                } else if implements_drop {
+                    span_lint_and_help(
+                        cx,
+                        LET_UNDERSCORE_DROP,
+                        local.span,
+                        "non-binding `let` on a type that implements `Drop`",
+                        None,
+                        "consider using an underscore-prefixed named \
+                            binding or dropping explicitly with `std::mem::drop`"
+                    )
                 } else if is_must_use_ty(cx, cx.typeck_results().expr_ty(init)) {
                     span_lint_and_help(
                         cx,
index 126852df502eb38465750a851771675fedb648ee..7e8cbd00c22a146dadb04d454046ed3bb2ce1cfb 100644 (file)
@@ -323,6 +323,7 @@ macro_rules! declare_clippy_lint {
 mod unit_return_expecting_ord;
 mod unnamed_address;
 mod unnecessary_sort_by;
+mod unnecessary_wraps;
 mod unnested_or_patterns;
 mod unsafe_removed_from_name;
 mod unused_io_amount;
@@ -495,6 +496,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         "clippy::temporary_cstring_as_ptr",
         "this lint has been uplifted to rustc and is now called `temporary_cstring_as_ptr`",
     );
+    store.register_removed(
+        "clippy::panic_params",
+        "this lint has been uplifted to rustc and is now called `panic_fmt`",
+    );
     // end deprecated lints, do not remove this comment, it’s used in `update_lints`
 
     // begin register lints, do not remove this comment, it’s used in `update_lints`
@@ -622,6 +627,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         &len_zero::LEN_WITHOUT_IS_EMPTY,
         &len_zero::LEN_ZERO,
         &let_if_seq::USELESS_LET_IF_SEQ,
+        &let_underscore::LET_UNDERSCORE_DROP,
         &let_underscore::LET_UNDERSCORE_LOCK,
         &let_underscore::LET_UNDERSCORE_MUST_USE,
         &lifetimes::EXTRA_UNUSED_LIFETIMES,
@@ -788,7 +794,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         &overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL,
         &panic_in_result_fn::PANIC_IN_RESULT_FN,
         &panic_unimplemented::PANIC,
-        &panic_unimplemented::PANIC_PARAMS,
         &panic_unimplemented::TODO,
         &panic_unimplemented::UNIMPLEMENTED,
         &panic_unimplemented::UNREACHABLE,
@@ -832,6 +837,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         &stable_sort_primitive::STABLE_SORT_PRIMITIVE,
         &strings::STRING_ADD,
         &strings::STRING_ADD_ASSIGN,
+        &strings::STRING_FROM_UTF8_AS_BYTES,
         &strings::STRING_LIT_AS_BYTES,
         &suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL,
         &suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL,
@@ -890,6 +896,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         &unnamed_address::FN_ADDRESS_COMPARISONS,
         &unnamed_address::VTABLE_ADDRESS_COMPARISONS,
         &unnecessary_sort_by::UNNECESSARY_SORT_BY,
+        &unnecessary_wraps::UNNECESSARY_WRAPS,
         &unnested_or_patterns::UNNESTED_OR_PATTERNS,
         &unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME,
         &unused_io_amount::UNUSED_IO_AMOUNT,
@@ -1062,6 +1069,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| box redundant_clone::RedundantClone);
     store.register_late_pass(|| box slow_vector_initialization::SlowVectorInit);
     store.register_late_pass(|| box unnecessary_sort_by::UnnecessarySortBy);
+    store.register_late_pass(|| box unnecessary_wraps::UnnecessaryWraps);
     store.register_late_pass(|| box types::RefToMut);
     store.register_late_pass(|| box assertions_on_constants::AssertionsOnConstants);
     store.register_late_pass(|| box missing_const_for_fn::MissingConstForFn);
@@ -1216,6 +1224,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
 
     store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![
         LintId::of(&attrs::INLINE_ALWAYS),
+        LintId::of(&await_holding_invalid::AWAIT_HOLDING_LOCK),
+        LintId::of(&await_holding_invalid::AWAIT_HOLDING_REFCELL_REF),
         LintId::of(&bit_mask::VERBOSE_BIT_MASK),
         LintId::of(&checked_conversions::CHECKED_CONVERSIONS),
         LintId::of(&copies::SAME_FUNCTIONS_IN_IF_CONDITION),
@@ -1239,6 +1249,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&infinite_iter::MAYBE_INFINITE_ITER),
         LintId::of(&items_after_statements::ITEMS_AFTER_STATEMENTS),
         LintId::of(&large_stack_arrays::LARGE_STACK_ARRAYS),
+        LintId::of(&let_underscore::LET_UNDERSCORE_DROP),
         LintId::of(&literal_representation::LARGE_DIGIT_GROUPS),
         LintId::of(&literal_representation::UNREADABLE_LITERAL),
         LintId::of(&loops::EXPLICIT_INTO_ITER_LOOP),
@@ -1318,8 +1329,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&attrs::MISMATCHED_TARGET_OS),
         LintId::of(&attrs::UNKNOWN_CLIPPY_LINTS),
         LintId::of(&attrs::USELESS_ATTRIBUTE),
-        LintId::of(&await_holding_invalid::AWAIT_HOLDING_LOCK),
-        LintId::of(&await_holding_invalid::AWAIT_HOLDING_REFCELL_REF),
         LintId::of(&bit_mask::BAD_BIT_MASK),
         LintId::of(&bit_mask::INEFFECTIVE_BIT_MASK),
         LintId::of(&blacklisted_name::BLACKLISTED_NAME),
@@ -1499,7 +1508,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&open_options::NONSENSICAL_OPEN_OPTIONS),
         LintId::of(&option_env_unwrap::OPTION_ENV_UNWRAP),
         LintId::of(&overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
-        LintId::of(&panic_unimplemented::PANIC_PARAMS),
         LintId::of(&partialeq_ne_impl::PARTIALEQ_NE_IMPL),
         LintId::of(&precedence::PRECEDENCE),
         LintId::of(&ptr::CMP_NULL),
@@ -1527,6 +1535,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
         LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION),
         LintId::of(&stable_sort_primitive::STABLE_SORT_PRIMITIVE),
+        LintId::of(&strings::STRING_FROM_UTF8_AS_BYTES),
         LintId::of(&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
         LintId::of(&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
         LintId::of(&swap::ALMOST_SWAPPED),
@@ -1567,6 +1576,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS),
         LintId::of(&unnamed_address::VTABLE_ADDRESS_COMPARISONS),
         LintId::of(&unnecessary_sort_by::UNNECESSARY_SORT_BY),
+        LintId::of(&unnecessary_wraps::UNNECESSARY_WRAPS),
         LintId::of(&unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME),
         LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT),
         LintId::of(&unused_unit::UNUSED_UNIT),
@@ -1666,7 +1676,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST),
         LintId::of(&non_expressive_names::JUST_UNDERSCORES_AND_DIGITS),
         LintId::of(&non_expressive_names::MANY_SINGLE_CHAR_NAMES),
-        LintId::of(&panic_unimplemented::PANIC_PARAMS),
         LintId::of(&ptr::CMP_NULL),
         LintId::of(&ptr::PTR_ARG),
         LintId::of(&ptr_eq::PTR_EQ),
@@ -1752,6 +1761,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&reference::DEREF_ADDROF),
         LintId::of(&reference::REF_IN_DEREF),
         LintId::of(&repeat_once::REPEAT_ONCE),
+        LintId::of(&strings::STRING_FROM_UTF8_AS_BYTES),
         LintId::of(&swap::MANUAL_SWAP),
         LintId::of(&temporary_assignment::TEMPORARY_ASSIGNMENT),
         LintId::of(&transmute::CROSSPOINTER_TRANSMUTE),
@@ -1770,6 +1780,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&types::UNNECESSARY_CAST),
         LintId::of(&types::VEC_BOX),
         LintId::of(&unnecessary_sort_by::UNNECESSARY_SORT_BY),
+        LintId::of(&unnecessary_wraps::UNNECESSARY_WRAPS),
         LintId::of(&unwrap::UNNECESSARY_UNWRAP),
         LintId::of(&useless_conversion::USELESS_CONVERSION),
         LintId::of(&zero_div_zero::ZERO_DIVIDED_BY_ZERO),
@@ -1782,8 +1793,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&attrs::DEPRECATED_SEMVER),
         LintId::of(&attrs::MISMATCHED_TARGET_OS),
         LintId::of(&attrs::USELESS_ATTRIBUTE),
-        LintId::of(&await_holding_invalid::AWAIT_HOLDING_LOCK),
-        LintId::of(&await_holding_invalid::AWAIT_HOLDING_REFCELL_REF),
         LintId::of(&bit_mask::BAD_BIT_MASK),
         LintId::of(&bit_mask::INEFFECTIVE_BIT_MASK),
         LintId::of(&booleans::LOGIC_BUG),
index 5a4264f9b5c4ec4995f457b4856740ac64a7e009..0d31e9cfc3decb073691ca18766184563141b25f 100644 (file)
@@ -4,10 +4,10 @@
 use crate::utils::usage::{is_unused, mutated_variables};
 use crate::utils::{
     contains_name, get_enclosing_block, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait,
-    indent_of, is_integer_const, is_no_std_crate, is_refutable, is_type_diagnostic_item, last_path_segment,
-    match_trait_method, match_type, match_var, multispan_sugg, qpath_res, single_segment_path, snippet,
-    snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg,
-    span_lint_and_then, sugg, SpanlessEq,
+    indent_of, is_in_panic_handler, is_integer_const, is_no_std_crate, is_refutable, is_type_diagnostic_item,
+    last_path_segment, match_trait_method, match_type, match_var, multispan_sugg, qpath_res, single_segment_path,
+    snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_help,
+    span_lint_and_sugg, span_lint_and_then, sugg, SpanlessEq,
 };
 use if_chain::if_chain;
 use rustc_ast::ast;
@@ -543,17 +543,15 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         // (also matches an explicit "match" instead of "if let")
         // (even if the "match" or "if let" is used for declaration)
         if let ExprKind::Loop(ref block, _, LoopSource::Loop) = expr.kind {
-            // also check for empty `loop {}` statements
-            // TODO(issue #6161): Enable for no_std crates (outside of #[panic_handler])
-            if block.stmts.is_empty() && block.expr.is_none() && !is_no_std_crate(cx.tcx.hir().krate()) {
-                span_lint_and_help(
-                    cx,
-                    EMPTY_LOOP,
-                    expr.span,
-                    "empty `loop {}` wastes CPU cycles",
-                    None,
-                    "You should either use `panic!()` or add `std::thread::sleep(..);` to the loop body.",
-                );
+            // also check for empty `loop {}` statements, skipping those in #[panic_handler]
+            if block.stmts.is_empty() && block.expr.is_none() && !is_in_panic_handler(cx, expr) {
+                let msg = "empty `loop {}` wastes CPU cycles";
+                let help = if is_no_std_crate(cx.tcx.hir().krate()) {
+                    "you should either use `panic!()` or add a call pausing or sleeping the thread to the loop body"
+                } else {
+                    "you should either use `panic!()` or add `std::thread::sleep(..);` to the loop body"
+                };
+                span_lint_and_help(cx, EMPTY_LOOP, expr.span, msg, None, help);
             }
 
             // extract the expression from the first statement (if any) in a block
index 864d1ea87f57572d45fa9e8f7dfcc5063fd5b1d8..7b3b450ef93e943fad6882126463f32a42617ebd 100644 (file)
@@ -1,5 +1,5 @@
 use crate::utils::paths::FUTURE_FROM_GENERATOR;
-use crate::utils::{match_function_call, snippet_block, snippet_opt, span_lint_and_then};
+use crate::utils::{match_function_call, position_before_rarrow, snippet_block, snippet_opt, span_lint_and_then};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
@@ -69,7 +69,7 @@ fn check_fn(
                     |diag| {
                         if_chain! {
                             if let Some(header_snip) = snippet_opt(cx, header_span);
-                            if let Some(ret_pos) = header_snip.rfind("->");
+                            if let Some(ret_pos) = position_before_rarrow(header_snip.clone());
                             if let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output);
                             then {
                                 let help = format!("make the function `async` and {}", ret_sugg);
@@ -194,7 +194,7 @@ fn suggested_ret(cx: &LateContext<'_>, output: &Ty<'_>) -> Option<(&'static str,
         },
         _ => {
             let sugg = "return the output of the future directly";
-            snippet_opt(cx, output.span).map(|snip| (sugg, format!("-> {}", snip)))
+            snippet_opt(cx, output.span).map(|snip| (sugg, format!(" -> {}", snip)))
         },
     }
 }
index 034cd99a9be06b072ef7a1e8fdafa8e8a912cf42..220240acb7aa916368140b92e3cc1df1ef0bab35 100644 (file)
@@ -8,13 +8,15 @@
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::Mutability;
 use rustc_middle::ty;
+use rustc_middle::ty::adjustment::Adjust;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::symbol::Ident;
 use rustc_span::{sym, Span};
 
 declare_clippy_lint! {
-    /// **What it does:** Checks for usage of `iterator.map(|x| x.clone())` and suggests
-    /// `iterator.cloned()` instead
+    /// **What it does:** Checks for usage of `map(|x| x.clone())` or
+    /// dereferencing closures for `Copy` types, on `Iterator` or `Option`,
+    /// and suggests `cloned()` or `copied()` instead
     ///
     /// **Why is this bad?** Readability, this can be written more concisely
     ///
@@ -75,14 +77,19 @@ fn check_expr(&mut self, cx: &LateContext<'_>, e: &hir::Expr<'_>) {
                                     }
                                 }
                             },
-                            hir::ExprKind::MethodCall(ref method, _, ref obj, _) => {
-                                if ident_eq(name, &obj[0]) && method.ident.as_str() == "clone"
-                                    && match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) {
-
-                                    let obj_ty = cx.typeck_results().expr_ty(&obj[0]);
-                                    if let ty::Ref(_, ty, _) = obj_ty.kind() {
-                                        let copy = is_copy(cx, ty);
-                                        lint(cx, e.span, args[0].span, copy);
+                            hir::ExprKind::MethodCall(ref method, _, [obj], _) => if_chain! {
+                                if ident_eq(name, obj) && method.ident.name == sym::clone;
+                                if match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT);
+                                // no autoderefs
+                                if !cx.typeck_results().expr_adjustments(obj).iter()
+                                    .any(|a| matches!(a.kind, Adjust::Deref(Some(..))));
+                                then {
+                                    let obj_ty = cx.typeck_results().expr_ty(obj);
+                                    if let ty::Ref(_, ty, mutability) = obj_ty.kind() {
+                                        if matches!(mutability, Mutability::Not) {
+                                            let copy = is_copy(cx, ty);
+                                            lint(cx, e.span, args[0].span, copy);
+                                        }
                                     } else {
                                         lint_needless_cloning(cx, e.span, args[0].span);
                                     }
index ae37942e55a1bbf65cf77a47d1925cb4b141dc5e..540a1484a8558292a92ad7ea0222eabce8892d26 100644 (file)
@@ -1,14 +1,12 @@
 use super::{contains_return, BIND_INSTEAD_OF_MAP};
 use crate::utils::{
     in_macro, match_qpath, match_type, method_calls, multispan_sugg_with_applicability, paths, remove_blocks, snippet,
-    snippet_with_macro_callsite, span_lint_and_sugg, span_lint_and_then,
+    snippet_with_macro_callsite, span_lint_and_sugg, span_lint_and_then, visitors::find_all_ret_expressions,
 };
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_hir::intravisit::{self, Visitor};
 use rustc_lint::LateContext;
-use rustc_middle::hir::map::Map;
 use rustc_span::Span;
 
 pub(crate) struct OptionAndThenSome;
@@ -193,124 +191,3 @@ fn lint(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) -> b
         }
     }
 }
-
-/// returns `true` if expr contains match expr desugared from try
-fn contains_try(expr: &hir::Expr<'_>) -> bool {
-    struct TryFinder {
-        found: bool,
-    }
-
-    impl<'hir> intravisit::Visitor<'hir> for TryFinder {
-        type Map = Map<'hir>;
-
-        fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
-            intravisit::NestedVisitorMap::None
-        }
-
-        fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
-            if self.found {
-                return;
-            }
-            match expr.kind {
-                hir::ExprKind::Match(_, _, hir::MatchSource::TryDesugar) => self.found = true,
-                _ => intravisit::walk_expr(self, expr),
-            }
-        }
-    }
-
-    let mut visitor = TryFinder { found: false };
-    visitor.visit_expr(expr);
-    visitor.found
-}
-
-fn find_all_ret_expressions<'hir, F>(_cx: &LateContext<'_>, expr: &'hir hir::Expr<'hir>, callback: F) -> bool
-where
-    F: FnMut(&'hir hir::Expr<'hir>) -> bool,
-{
-    struct RetFinder<F> {
-        in_stmt: bool,
-        failed: bool,
-        cb: F,
-    }
-
-    struct WithStmtGuarg<'a, F> {
-        val: &'a mut RetFinder<F>,
-        prev_in_stmt: bool,
-    }
-
-    impl<F> RetFinder<F> {
-        fn inside_stmt(&mut self, in_stmt: bool) -> WithStmtGuarg<'_, F> {
-            let prev_in_stmt = std::mem::replace(&mut self.in_stmt, in_stmt);
-            WithStmtGuarg {
-                val: self,
-                prev_in_stmt,
-            }
-        }
-    }
-
-    impl<F> std::ops::Deref for WithStmtGuarg<'_, F> {
-        type Target = RetFinder<F>;
-
-        fn deref(&self) -> &Self::Target {
-            self.val
-        }
-    }
-
-    impl<F> std::ops::DerefMut for WithStmtGuarg<'_, F> {
-        fn deref_mut(&mut self) -> &mut Self::Target {
-            self.val
-        }
-    }
-
-    impl<F> Drop for WithStmtGuarg<'_, F> {
-        fn drop(&mut self) {
-            self.val.in_stmt = self.prev_in_stmt;
-        }
-    }
-
-    impl<'hir, F: FnMut(&'hir hir::Expr<'hir>) -> bool> intravisit::Visitor<'hir> for RetFinder<F> {
-        type Map = Map<'hir>;
-
-        fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
-            intravisit::NestedVisitorMap::None
-        }
-
-        fn visit_stmt(&mut self, stmt: &'hir hir::Stmt<'_>) {
-            intravisit::walk_stmt(&mut *self.inside_stmt(true), stmt)
-        }
-
-        fn visit_expr(&mut self, expr: &'hir hir::Expr<'_>) {
-            if self.failed {
-                return;
-            }
-            if self.in_stmt {
-                match expr.kind {
-                    hir::ExprKind::Ret(Some(expr)) => self.inside_stmt(false).visit_expr(expr),
-                    _ => intravisit::walk_expr(self, expr),
-                }
-            } else {
-                match expr.kind {
-                    hir::ExprKind::Match(cond, arms, _) => {
-                        self.inside_stmt(true).visit_expr(cond);
-                        for arm in arms {
-                            self.visit_expr(arm.body);
-                        }
-                    },
-                    hir::ExprKind::Block(..) => intravisit::walk_expr(self, expr),
-                    hir::ExprKind::Ret(Some(expr)) => self.visit_expr(expr),
-                    _ => self.failed |= !(self.cb)(expr),
-                }
-            }
-        }
-    }
-
-    !contains_try(expr) && {
-        let mut ret_finder = RetFinder {
-            in_stmt: false,
-            failed: false,
-            cb: callback,
-        };
-        ret_finder.visit_expr(expr);
-        !ret_finder.failed
-    }
-}
index 30f4c0c56d27b068c1b43b9833fdddd3f7a60a4d..fa1744043657a2eee08d978616af231d4f73c706 100644 (file)
 }
 
 declare_clippy_lint! {
-    /// **What it does:** Checks for an iterator search (such as `find()`,
+    /// **What it does:** Checks for an iterator or string search (such as `find()`,
     /// `position()`, or `rposition()`) followed by a call to `is_some()`.
     ///
     /// **Why is this bad?** Readability, this can be written more concisely as
-    /// `_.any(_)`.
+    /// `_.any(_)` or `_.contains(_)`.
     ///
     /// **Known problems:** None.
     ///
     /// ```
     pub SEARCH_IS_SOME,
     complexity,
-    "using an iterator search followed by `is_some()`, which is more succinctly expressed as a call to `any()`"
+    "using an iterator or string search followed by `is_some()`, which is more succinctly expressed as a call to `any()` or `contains()`"
 }
 
 declare_clippy_lint! {
 }
 
 declare_clippy_lint! {
-    /// **What it does:** Checks for usage of `_.map(_).collect::<Result<(),_>()`.
+    /// **What it does:** Checks for usage of `_.map(_).collect::<Result<(), _>()`.
     ///
     /// **Why is this bad?** Using `try_for_each` instead is more readable and idiomatic.
     ///
@@ -1797,12 +1797,20 @@ fn check_general_case<'tcx>(
         cx: &LateContext<'tcx>,
         name: &str,
         method_span: Span,
-        fun_span: Span,
         self_expr: &hir::Expr<'_>,
         arg: &'tcx hir::Expr<'_>,
-        or_has_args: bool,
         span: Span,
+        // None if lambda is required
+        fun_span: Option<Span>,
     ) {
+        // (path, fn_has_argument, methods, suffix)
+        static KNOW_TYPES: [(&[&str], bool, &[&str], &str); 4] = [
+            (&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"),
+            (&paths::HASHMAP_ENTRY, false, &["or_insert"], "with"),
+            (&paths::OPTION, false, &["map_or", "ok_or", "or", "unwrap_or"], "else"),
+            (&paths::RESULT, true, &["or", "unwrap_or"], "else"),
+        ];
+
         if let hir::ExprKind::MethodCall(ref path, _, ref args, _) = &arg.kind {
             if path.ident.as_str() == "len" {
                 let ty = cx.typeck_results().expr_ty(&args[0]).peel_refs();
@@ -1818,16 +1826,8 @@ fn check_general_case<'tcx>(
             }
         }
 
-        // (path, fn_has_argument, methods, suffix)
-        let know_types: &[(&[_], _, &[_], _)] = &[
-            (&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"),
-            (&paths::HASHMAP_ENTRY, false, &["or_insert"], "with"),
-            (&paths::OPTION, false, &["map_or", "ok_or", "or", "unwrap_or"], "else"),
-            (&paths::RESULT, true, &["or", "unwrap_or"], "else"),
-        ];
-
         if_chain! {
-            if know_types.iter().any(|k| k.2.contains(&name));
+            if KNOW_TYPES.iter().any(|k| k.2.contains(&name));
 
             if is_lazyness_candidate(cx, arg);
             if !contains_return(&arg);
@@ -1835,15 +1835,23 @@ fn check_general_case<'tcx>(
             let self_ty = cx.typeck_results().expr_ty(self_expr);
 
             if let Some(&(_, fn_has_arguments, poss, suffix)) =
-                know_types.iter().find(|&&i| match_type(cx, self_ty, i.0));
+                KNOW_TYPES.iter().find(|&&i| match_type(cx, self_ty, i.0));
 
             if poss.contains(&name);
 
             then {
-                let sugg: Cow<'_, _> = match (fn_has_arguments, !or_has_args) {
-                    (true, _) => format!("|_| {}", snippet_with_macro_callsite(cx, arg.span, "..")).into(),
-                    (false, false) => format!("|| {}", snippet_with_macro_callsite(cx, arg.span, "..")).into(),
-                    (false, true) => snippet_with_macro_callsite(cx, fun_span, ".."),
+                let sugg: Cow<'_, str> = {
+                    let (snippet_span, use_lambda) = match (fn_has_arguments, fun_span) {
+                        (false, Some(fun_span)) => (fun_span, false),
+                        _ => (arg.span, true),
+                    };
+                    let snippet = snippet_with_macro_callsite(cx, snippet_span, "..");
+                    if use_lambda {
+                        let l_arg = if fn_has_arguments { "_" } else { "" };
+                        format!("|{}| {}", l_arg, snippet).into()
+                    } else {
+                        snippet
+                    }
                 };
                 let span_replace_word = method_span.with_hi(span.hi());
                 span_lint_and_sugg(
@@ -1864,28 +1872,13 @@ fn check_general_case<'tcx>(
             hir::ExprKind::Call(ref fun, ref or_args) => {
                 let or_has_args = !or_args.is_empty();
                 if !check_unwrap_or_default(cx, name, fun, &args[0], &args[1], or_has_args, expr.span) {
-                    check_general_case(
-                        cx,
-                        name,
-                        method_span,
-                        fun.span,
-                        &args[0],
-                        &args[1],
-                        or_has_args,
-                        expr.span,
-                    );
+                    let fun_span = if or_has_args { None } else { Some(fun.span) };
+                    check_general_case(cx, name, method_span, &args[0], &args[1], expr.span, fun_span);
                 }
             },
-            hir::ExprKind::MethodCall(_, span, ref or_args, _) => check_general_case(
-                cx,
-                name,
-                method_span,
-                span,
-                &args[0],
-                &args[1],
-                !or_args.is_empty(),
-                expr.span,
-            ),
+            hir::ExprKind::Index(..) | hir::ExprKind::MethodCall(..) => {
+                check_general_case(cx, name, method_span, &args[0], &args[1], expr.span, None);
+            },
             _ => {},
         }
     }
@@ -3048,6 +3041,7 @@ fn lint_flat_map_identity<'tcx>(
 }
 
 /// lint searching an Iterator followed by `is_some()`
+/// or calling `find()` on a string followed by `is_some()`
 fn lint_search_is_some<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &'tcx hir::Expr<'_>,
@@ -3059,10 +3053,10 @@ fn lint_search_is_some<'tcx>(
     // lint if caller of search is an Iterator
     if match_trait_method(cx, &is_some_args[0], &paths::ITERATOR) {
         let msg = format!(
-            "called `is_some()` after searching an `Iterator` with {}. This is more succinctly \
-             expressed by calling `any()`.",
+            "called `is_some()` after searching an `Iterator` with `{}`",
             search_method
         );
+        let hint = "this is more succinctly expressed by calling `any()`";
         let search_snippet = snippet(cx, search_args[1].span, "..");
         if search_snippet.lines().count() <= 1 {
             // suggest `any(|x| ..)` instead of `any(|&x| ..)` for `find(|&x| ..).is_some()`
@@ -3090,7 +3084,7 @@ fn lint_search_is_some<'tcx>(
                 SEARCH_IS_SOME,
                 method_span.with_hi(expr.span.hi()),
                 &msg,
-                "try this",
+                "use `any()` instead",
                 format!(
                     "any({})",
                     any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
@@ -3098,7 +3092,36 @@ fn lint_search_is_some<'tcx>(
                 Applicability::MachineApplicable,
             );
         } else {
-            span_lint(cx, SEARCH_IS_SOME, expr.span, &msg);
+            span_lint_and_help(cx, SEARCH_IS_SOME, expr.span, &msg, None, hint);
+        }
+    }
+    // lint if `find()` is called by `String` or `&str`
+    else if search_method == "find" {
+        let is_string_or_str_slice = |e| {
+            let self_ty = cx.typeck_results().expr_ty(e).peel_refs();
+            if is_type_diagnostic_item(cx, self_ty, sym!(string_type)) {
+                true
+            } else {
+                *self_ty.kind() == ty::Str
+            }
+        };
+        if_chain! {
+            if is_string_or_str_slice(&search_args[0]);
+            if is_string_or_str_slice(&search_args[1]);
+            then {
+                let msg = "called `is_some()` after calling `find()` on a string";
+                let mut applicability = Applicability::MachineApplicable;
+                let find_arg = snippet_with_applicability(cx, search_args[1].span, "..", &mut applicability);
+                span_lint_and_sugg(
+                    cx,
+                    SEARCH_IS_SOME,
+                    method_span.with_hi(expr.span.hi()),
+                    msg,
+                    "use `contains()` instead",
+                    format!("contains({})", find_arg),
+                    applicability,
+                );
+            }
         }
     }
 }
@@ -3901,21 +3924,24 @@ fn lint_from_iter(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<
     let ty = cx.typeck_results().expr_ty(expr);
     let arg_ty = cx.typeck_results().expr_ty(&args[0]);
 
-    let from_iter_id = get_trait_def_id(cx, &paths::FROM_ITERATOR).unwrap();
-    let iter_id = get_trait_def_id(cx, &paths::ITERATOR).unwrap();
+    if_chain! {
+        if let Some(from_iter_id) = get_trait_def_id(cx, &paths::FROM_ITERATOR);
+        if let Some(iter_id) = get_trait_def_id(cx, &paths::ITERATOR);
 
-    if implements_trait(cx, ty, from_iter_id, &[]) && implements_trait(cx, arg_ty, iter_id, &[]) {
-        // `expr` implements `FromIterator` trait
-        let iter_expr = snippet(cx, args[0].span, "..");
-        span_lint_and_sugg(
-            cx,
-            FROM_ITER_INSTEAD_OF_COLLECT,
-            expr.span,
-            "usage of `FromIterator::from_iter`",
-            "use `.collect()` instead of `::from_iter()`",
-            format!("{}.collect()", iter_expr),
-            Applicability::MaybeIncorrect,
-        );
+        if implements_trait(cx, ty, from_iter_id, &[]) && implements_trait(cx, arg_ty, iter_id, &[]);
+        then {
+            // `expr` implements `FromIterator` trait
+            let iter_expr = snippet(cx, args[0].span, "..");
+            span_lint_and_sugg(
+                cx,
+                FROM_ITER_INSTEAD_OF_COLLECT,
+                expr.span,
+                "usage of `FromIterator::from_iter`",
+                "use `.collect()` instead of `::from_iter()`",
+                format!("{}.collect()", iter_expr),
+                Applicability::MaybeIncorrect,
+            );
+        }
     }
 }
 
index cde89983a2656aff2d0a50eb646b690699a79c6b..a867bdb326d722dfc0c089fda2fa6f8b6adc71d2 100644 (file)
@@ -33,6 +33,17 @@ pub(super) fn lint<'tcx>(
                 } else {
                     "unnecessary closure used to substitute value for `Result::Err`"
                 };
+                let applicability = if body
+                    .params
+                    .iter()
+                    // bindings are checked to be unused above
+                    .all(|param| matches!(param.pat.kind, hir::PatKind::Binding(..) | hir::PatKind::Wild))
+                {
+                    Applicability::MachineApplicable
+                } else {
+                    // replacing the lambda may break type inference
+                    Applicability::MaybeIncorrect
+                };
 
                 span_lint_and_sugg(
                     cx,
@@ -46,7 +57,7 @@ pub(super) fn lint<'tcx>(
                         simplify_using,
                         snippet(cx, body_expr.span, ".."),
                     ),
-                    Applicability::MachineApplicable,
+                    applicability,
                 );
             }
         }
index 009e3d8937e0233e2602ff03c37e7bc5f2311609..4678f6872f37ce64887bab2d16fbab1639946850 100644 (file)
@@ -147,7 +147,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) {
             hir::ItemKind::Union(..) => "a union",
             hir::ItemKind::OpaqueTy(..) => "an existential type",
             hir::ItemKind::ExternCrate(..)
-            | hir::ItemKind::ForeignMod(..)
+            | hir::ItemKind::ForeignMod { .. }
             | hir::ItemKind::GlobalAsm(..)
             | hir::ItemKind::Impl { .. }
             | hir::ItemKind::Use(..) => return,
index 53abe6086ea411ef5220b9b78e7e75088bf01acf..913d9daff46fd49a680f17ac9f2f207531660bba 100644 (file)
@@ -125,7 +125,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) {
             | hir::ItemKind::Union(..)
             | hir::ItemKind::OpaqueTy(..)
             | hir::ItemKind::ExternCrate(..)
-            | hir::ItemKind::ForeignMod(..)
+            | hir::ItemKind::ForeignMod { .. }
             | hir::ItemKind::Impl { .. }
             | hir::ItemKind::Use(..) => {},
         };
index 9cceecc785a28e6690aa3687dba3c9ec81762d80..11044e0c2fb487bab154c72fac101619445a9cea 100644 (file)
@@ -89,11 +89,7 @@ fn check_sig<'tcx>(cx: &LateContext<'tcx>, item_hir_id: hir::HirId, decl: &hir::
     for (hir_ty, ty) in decl.inputs.iter().zip(fn_sig.inputs().skip_binder().iter()) {
         check_ty(cx, hir_ty.span, ty);
     }
-    check_ty(
-        cx,
-        decl.output.span(),
-        cx.tcx.erase_late_bound_regions(fn_sig.output()),
-    );
+    check_ty(cx, decl.output.span(), cx.tcx.erase_late_bound_regions(fn_sig.output()));
 }
 
 // We want to lint 1. sets or maps with 2. not immutable key types and 3. no unerased
index 7b662eae7753eef1571c09880064486ec15f2cd5..6b0d198edcffa647112af10cceccea3a3304f2d2 100644 (file)
@@ -5,11 +5,15 @@
 use std::ptr;
 
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp};
+use rustc_hir::def_id::DefId;
+use rustc_hir::{
+    BodyId, Expr, ExprKind, HirId, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp,
+};
 use rustc_infer::traits::specialization_graph;
 use rustc_lint::{LateContext, LateLintPass, Lint};
+use rustc_middle::mir::interpret::{ConstValue, ErrorHandled};
 use rustc_middle::ty::adjustment::Adjust;
-use rustc_middle::ty::{AssocKind, Ty};
+use rustc_middle::ty::{self, AssocKind, Const, Ty};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{InnerSpan, Span, DUMMY_SP};
 use rustc_typeck::hir_ty_to_ty;
     /// `std::sync::ONCE_INIT` constant). In this case the use of `const` is legit,
     /// and this lint should be suppressed.
     ///
-    /// When an enum has variants with interior mutability, use of its non interior mutable
-    /// variants can generate false positives. See issue
-    /// [#3962](https://github.com/rust-lang/rust-clippy/issues/3962)
+    /// Even though the lint avoids triggering on a constant whose type has enums that have variants
+    /// with interior mutability, and its value uses non interior mutable variants (see
+    /// [#3962](https://github.com/rust-lang/rust-clippy/issues/3962) and
+    /// [#3825](https://github.com/rust-lang/rust-clippy/issues/3825) for examples);
+    /// it complains about associated constants without default values only based on its types;
+    /// which might not be preferable.
+    /// There're other enums plus associated constants cases that the lint cannot handle.
     ///
     /// Types that have underlying or potential interior mutability trigger the lint whether
     /// the interior mutable field is used or not. See issues
     /// [#5812](https://github.com/rust-lang/rust-clippy/issues/5812) and
-    /// [#3825](https://github.com/rust-lang/rust-clippy/issues/3825)
     ///
     /// **Example:**
     /// ```rust
     "referencing `const` with interior mutability"
 }
 
+fn is_unfrozen<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
+    // Ignore types whose layout is unknown since `is_freeze` reports every generic types as `!Freeze`,
+    // making it indistinguishable from `UnsafeCell`. i.e. it isn't a tool to prove a type is
+    // 'unfrozen'. However, this code causes a false negative in which
+    // a type contains a layout-unknown type, but also a unsafe cell like `const CELL: Cell<T>`.
+    // Yet, it's better than `ty.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_PROJECTION)`
+    // since it works when a pointer indirection involves (`Cell<*const T>`).
+    // Making up a `ParamEnv` where every generic params and assoc types are `Freeze`is another option;
+    // but I'm not sure whether it's a decent way, if possible.
+    cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() && !ty.is_freeze(cx.tcx.at(DUMMY_SP), cx.param_env)
+}
+
+fn is_value_unfrozen_raw<'tcx>(
+    cx: &LateContext<'tcx>,
+    result: Result<ConstValue<'tcx>, ErrorHandled>,
+    ty: Ty<'tcx>,
+) -> bool {
+    fn inner<'tcx>(cx: &LateContext<'tcx>, val: &'tcx Const<'tcx>) -> bool {
+        match val.ty.kind() {
+            // the fact that we have to dig into every structs to search enums
+            // leads us to the point checking `UnsafeCell` directly is the only option.
+            ty::Adt(ty_def, ..) if Some(ty_def.did) == cx.tcx.lang_items().unsafe_cell_type() => true,
+            ty::Array(..) | ty::Adt(..) | ty::Tuple(..) => {
+                let val = cx.tcx.destructure_const(cx.param_env.and(val));
+                val.fields.iter().any(|field| inner(cx, field))
+            },
+            _ => false,
+        }
+    }
+
+    result.map_or_else(
+        |err| {
+            // Consider `TooGeneric` cases as being unfrozen.
+            // This causes a false positive where an assoc const whose type is unfrozen
+            // have a value that is a frozen variant with a generic param (an example is
+            // `declare_interior_mutable_const::enums::BothOfCellAndGeneric::GENERIC_VARIANT`).
+            // However, it prevents a number of false negatives that is, I think, important:
+            // 1. assoc consts in trait defs referring to consts of themselves
+            //    (an example is `declare_interior_mutable_const::traits::ConcreteTypes::ANOTHER_ATOMIC`).
+            // 2. a path expr referring to assoc consts whose type is doesn't have
+            //    any frozen variants in trait defs (i.e. without substitute for `Self`).
+            //    (e.g. borrowing `borrow_interior_mutable_const::trait::ConcreteTypes::ATOMIC`)
+            // 3. similar to the false positive above;
+            //    but the value is an unfrozen variant, or the type has no enums. (An example is
+            //    `declare_interior_mutable_const::enums::BothOfCellAndGeneric::UNFROZEN_VARIANT`
+            //    and `declare_interior_mutable_const::enums::BothOfCellAndGeneric::NO_ENUM`).
+            // One might be able to prevent these FNs correctly, and replace this with `false`;
+            // e.g. implementing `has_frozen_variant` described above, and not running this function
+            // when the type doesn't have any frozen variants would be the 'correct' way for the 2nd
+            // case (that actually removes another suboptimal behavior (I won't say 'false positive') where,
+            // similar to 2., but with the a frozen variant) (e.g. borrowing
+            // `borrow_interior_mutable_const::enums::AssocConsts::TO_BE_FROZEN_VARIANT`).
+            // I chose this way because unfrozen enums as assoc consts are rare (or, hopefully, none).
+            err == ErrorHandled::TooGeneric
+        },
+        |val| inner(cx, Const::from_value(cx.tcx, val, ty)),
+    )
+}
+
+fn is_value_unfrozen_poly<'tcx>(cx: &LateContext<'tcx>, body_id: BodyId, ty: Ty<'tcx>) -> bool {
+    let result = cx.tcx.const_eval_poly(body_id.hir_id.owner.to_def_id());
+    is_value_unfrozen_raw(cx, result, ty)
+}
+
+fn is_value_unfrozen_expr<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool {
+    let substs = cx.typeck_results().node_substs(hir_id);
+
+    let result = cx
+        .tcx
+        .const_eval_resolve(cx.param_env, ty::WithOptConstParam::unknown(def_id), substs, None, None);
+    is_value_unfrozen_raw(cx, result, ty)
+}
+
 #[derive(Copy, Clone)]
 enum Source {
     Item { item: Span },
@@ -130,19 +210,7 @@ fn lint(&self) -> (&'static Lint, &'static str, Span) {
     }
 }
 
-fn verify_ty_bound<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, source: Source) {
-    // Ignore types whose layout is unknown since `is_freeze` reports every generic types as `!Freeze`,
-    // making it indistinguishable from `UnsafeCell`. i.e. it isn't a tool to prove a type is
-    // 'unfrozen'. However, this code causes a false negative in which
-    // a type contains a layout-unknown type, but also a unsafe cell like `const CELL: Cell<T>`.
-    // Yet, it's better than `ty.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_PROJECTION)`
-    // since it works when a pointer indirection involves (`Cell<*const T>`).
-    // Making up a `ParamEnv` where every generic params and assoc types are `Freeze`is another option;
-    // but I'm not sure whether it's a decent way, if possible.
-    if cx.tcx.layout_of(cx.param_env.and(ty)).is_err() || ty.is_freeze(cx.tcx.at(DUMMY_SP), cx.param_env) {
-        return;
-    }
-
+fn lint(cx: &LateContext<'_>, source: Source) {
     let (lint, msg, span) = source.lint();
     span_lint_and_then(cx, lint, span, msg, |diag| {
         if span.from_expansion() {
@@ -165,24 +233,44 @@ fn verify_ty_bound<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, source: Source) {
 
 impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
     fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx Item<'_>) {
-        if let ItemKind::Const(hir_ty, ..) = &it.kind {
+        if let ItemKind::Const(hir_ty, body_id) = it.kind {
             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
-            verify_ty_bound(cx, ty, Source::Item { item: it.span });
+
+            if is_unfrozen(cx, ty) && is_value_unfrozen_poly(cx, body_id, ty) {
+                lint(cx, Source::Item { item: it.span });
+            }
         }
     }
 
     fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx TraitItem<'_>) {
-        if let TraitItemKind::Const(hir_ty, ..) = &trait_item.kind {
+        if let TraitItemKind::Const(hir_ty, body_id_opt) = &trait_item.kind {
             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
+
             // Normalize assoc types because ones originated from generic params
             // bounded other traits could have their bound.
             let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
-            verify_ty_bound(cx, normalized, Source::Assoc { item: trait_item.span });
+            if is_unfrozen(cx, normalized)
+                // When there's no default value, lint it only according to its type;
+                // in other words, lint consts whose value *could* be unfrozen, not definitely is.
+                // This feels inconsistent with how the lint treats generic types,
+                // which avoids linting types which potentially become unfrozen.
+                // One could check whether a unfrozen type have a *frozen variant*
+                // (like `body_id_opt.map_or_else(|| !has_frozen_variant(...), ...)`),
+                // and do the same as the case of generic types at impl items.
+                // Note that it isn't sufficient to check if it has an enum
+                // since all of that enum's variants can be unfrozen:
+                // i.e. having an enum doesn't necessary mean a type has a frozen variant.
+                // And, implementing it isn't a trivial task; it'll probably end up
+                // re-implementing the trait predicate evaluation specific to `Freeze`.
+                && body_id_opt.map_or(true, |body_id| is_value_unfrozen_poly(cx, body_id, normalized))
+            {
+                lint(cx, Source::Assoc { item: trait_item.span });
+            }
         }
     }
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) {
-        if let ImplItemKind::Const(hir_ty, ..) = &impl_item.kind {
+        if let ImplItemKind::Const(hir_ty, body_id) = &impl_item.kind {
             let item_hir_id = cx.tcx.hir().get_parent_node(impl_item.hir_id);
             let item = cx.tcx.hir().expect_item(item_hir_id);
 
@@ -209,16 +297,23 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<
                                 ),
                             ))
                             .is_err();
+                            // If there were a function like `has_frozen_variant` described above,
+                            // we should use here as a frozen variant is a potential to be frozen
+                            // similar to unknown layouts.
+                            // e.g. `layout_of(...).is_err() || has_frozen_variant(...);`
                         then {
                             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
                             let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
-                            verify_ty_bound(
-                                cx,
-                                normalized,
-                                Source::Assoc {
-                                    item: impl_item.span,
-                                },
-                            );
+                            if is_unfrozen(cx, normalized)
+                                && is_value_unfrozen_poly(cx, *body_id, normalized)
+                            {
+                                lint(
+                                   cx,
+                                   Source::Assoc {
+                                       item: impl_item.span,
+                                    },
+                                );
+                            }
                         }
                     }
                 },
@@ -226,7 +321,10 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<
                     let ty = hir_ty_to_ty(cx.tcx, hir_ty);
                     // Normalize assoc types originated from generic params.
                     let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
-                    verify_ty_bound(cx, normalized, Source::Assoc { item: impl_item.span });
+
+                    if is_unfrozen(cx, ty) && is_value_unfrozen_poly(cx, *body_id, normalized) {
+                        lint(cx, Source::Assoc { item: impl_item.span });
+                    }
                 },
                 _ => (),
             }
@@ -241,8 +339,8 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
             }
 
             // Make sure it is a const item.
-            match qpath_res(cx, qpath, expr.hir_id) {
-                Res::Def(DefKind::Const | DefKind::AssocConst, _) => {},
+            let item_def_id = match qpath_res(cx, qpath, expr.hir_id) {
+                Res::Def(DefKind::Const | DefKind::AssocConst, did) => did,
                 _ => return,
             };
 
@@ -319,7 +417,9 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                 cx.typeck_results().expr_ty(dereferenced_expr)
             };
 
-            verify_ty_bound(cx, ty, Source::Expr { expr: expr.span });
+            if is_unfrozen(cx, ty) && is_value_unfrozen_expr(cx, expr.hir_id, item_def_id, ty) {
+                lint(cx, Source::Expr { expr: expr.span });
+            }
         }
     }
 }
index 6b175490cc8331f2d6cda2efe280079d0d957a9e..5b42b61fcde90ee21f2d84204de9436f6e1aa0d9 100644 (file)
@@ -1,7 +1,5 @@
 use crate::utils::{span_lint, span_lint_and_then};
-use rustc_ast::ast::{
-    Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, Item, ItemKind, Local, Pat, PatKind,
-};
+use rustc_ast::ast::{Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, Item, ItemKind, Local, Pat, PatKind};
 use rustc_ast::visit::{walk_block, walk_expr, walk_pat, Visitor};
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_middle::lint::in_external_macro;
index 3d888fe73257322453792f913648a410f0c51912..31b03ecd101c09daaab92d96f992521fc3cb5166 100644 (file)
@@ -1,30 +1,10 @@
-use crate::utils::{is_direct_expn_of, is_expn_of, match_panic_call, span_lint};
+use crate::utils::{is_expn_of, match_panic_call, span_lint};
 use if_chain::if_chain;
-use rustc_ast::ast::LitKind;
-use rustc_hir::{Expr, ExprKind};
+use rustc_hir::Expr;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::Span;
 
-declare_clippy_lint! {
-    /// **What it does:** Checks for missing parameters in `panic!`.
-    ///
-    /// **Why is this bad?** Contrary to the `format!` family of macros, there are
-    /// two forms of `panic!`: if there are no parameters given, the first argument
-    /// is not a format string and used literally. So while `format!("{}")` will
-    /// fail to compile, `panic!("{}")` will not.
-    ///
-    /// **Known problems:** None.
-    ///
-    /// **Example:**
-    /// ```no_run
-    /// panic!("This `panic!` is probably missing a parameter there: {}");
-    /// ```
-    pub PANIC_PARAMS,
-    style,
-    "missing parameters in `panic!` calls"
-}
-
 declare_clippy_lint! {
     /// **What it does:** Checks for usage of `panic!`.
     ///
     "`unreachable!` should not be present in production code"
 }
 
-declare_lint_pass!(PanicUnimplemented => [PANIC_PARAMS, UNIMPLEMENTED, UNREACHABLE, TODO, PANIC]);
+declare_lint_pass!(PanicUnimplemented => [UNIMPLEMENTED, UNREACHABLE, TODO, PANIC]);
 
 impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if let Some(params) = match_panic_call(cx, expr) {
+        if match_panic_call(cx, expr).is_some() {
             let span = get_outer_span(expr);
             if is_expn_of(expr.span, "unimplemented").is_some() {
                 span_lint(
@@ -113,7 +93,6 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                 );
             } else if is_expn_of(expr.span, "panic").is_some() {
                 span_lint(cx, PANIC, span, "`panic` should not be present in production code");
-                match_panic(params, expr, cx);
             }
         }
     }
@@ -132,20 +111,3 @@ fn get_outer_span(expr: &Expr<'_>) -> Span {
         }
     }
 }
-
-fn match_panic(params: &[Expr<'_>], expr: &Expr<'_>, cx: &LateContext<'_>) {
-    if_chain! {
-        if let ExprKind::Lit(ref lit) = params[0].kind;
-        if is_direct_expn_of(expr.span, "panic").is_some();
-        if let LitKind::Str(ref string, _) = lit.node;
-        let string = string.as_str().replace("{{", "").replace("}}", "");
-        if let Some(par) = string.find('{');
-        if string[par..].contains('}');
-        if params[0].span.source_callee().is_none();
-        if params[0].span.lo() != params[0].span.hi();
-        then {
-            span_lint(cx, PANIC_PARAMS, params[0].span,
-                      "you probably are missing some parameter in your format string");
-        }
-    }
-}
index 79e9a56af9a196c14a413e9e5094dfae620bd8e5..4b514bbd42ca7d0df4c0b5ebb5853974dec1f31a 100644 (file)
@@ -222,13 +222,14 @@ fn check_possible_range_contains(cx: &LateContext<'_>, op: BinOpKind, l: &Expr<'
             let name = snippet_with_applicability(cx, name_span, "_", &mut applicability);
             let lo = snippet_with_applicability(cx, l_span, "_", &mut applicability);
             let hi = snippet_with_applicability(cx, u_span, "_", &mut applicability);
+            let space = if lo.ends_with('.') { " " } else { "" };
             span_lint_and_sugg(
                 cx,
                 MANUAL_RANGE_CONTAINS,
                 span,
                 &format!("manual `{}::contains` implementation", range_type),
                 "use",
-                format!("({}{}{}).contains(&{})", lo, range_op, hi, name),
+                format!("({}{}{}{}).contains(&{})", lo, space, range_op, hi, name),
                 applicability,
             );
         } else if !combine_and && ord == Some(lord) {
@@ -251,13 +252,14 @@ fn check_possible_range_contains(cx: &LateContext<'_>, op: BinOpKind, l: &Expr<'
             let name = snippet_with_applicability(cx, name_span, "_", &mut applicability);
             let lo = snippet_with_applicability(cx, l_span, "_", &mut applicability);
             let hi = snippet_with_applicability(cx, u_span, "_", &mut applicability);
+            let space = if lo.ends_with('.') { " " } else { "" };
             span_lint_and_sugg(
                 cx,
                 MANUAL_RANGE_CONTAINS,
                 span,
                 &format!("manual `!{}::contains` implementation", range_type),
                 "use",
-                format!("!({}{}{}).contains(&{})", lo, range_op, hi, name),
+                format!("!({}{}{}{}).contains(&{})", lo, space, range_op, hi, name),
                 applicability,
             );
         }
index 602facbe062ac31ccfa4fa27d80def21317dd39a..f0e507105a6a0ef241ece96d66782c039b35cbd7 100644 (file)
@@ -320,11 +320,11 @@ fn find_stmt_assigns_to<'tcx>(
 
     match (by_ref, &*rvalue) {
         (true, mir::Rvalue::Ref(_, _, place)) | (false, mir::Rvalue::Use(mir::Operand::Copy(place))) => {
-            base_local_and_movability(cx, mir, *place)
+            Some(base_local_and_movability(cx, mir, *place))
         },
         (false, mir::Rvalue::Ref(_, _, place)) => {
             if let [mir::ProjectionElem::Deref] = place.as_ref().projection {
-                base_local_and_movability(cx, mir, *place)
+                Some(base_local_and_movability(cx, mir, *place))
             } else {
                 None
             }
@@ -341,7 +341,7 @@ fn base_local_and_movability<'tcx>(
     cx: &LateContext<'tcx>,
     mir: &mir::Body<'tcx>,
     place: mir::Place<'tcx>,
-) -> Option<(mir::Local, CannotMoveOut)> {
+) -> (mir::Local, CannotMoveOut) {
     use rustc_middle::mir::PlaceRef;
 
     // Dereference. You cannot move things out from a borrowed value.
@@ -362,7 +362,7 @@ fn base_local_and_movability<'tcx>(
             && !is_copy(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty);
     }
 
-    Some((local, deref || field || slice))
+    (local, deref || field || slice)
 }
 
 struct LocalUseVisitor {
index 3fda00403c611890e9053cb60bb7b9cfcdcba720..efe3237990d436a0f14c78cbac299d16fff5b240 100644 (file)
@@ -1,9 +1,10 @@
-use crate::utils::{in_macro, snippet_with_applicability, span_lint_and_sugg};
+use crate::utils::{in_macro, snippet_opt, snippet_with_applicability, span_lint_and_sugg};
 use if_chain::if_chain;
-use rustc_ast::ast::{Expr, ExprKind, UnOp};
+use rustc_ast::ast::{Expr, ExprKind, Mutability, UnOp};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::BytePos;
 
 declare_clippy_lint! {
     /// **What it does:** Checks for usage of `*&` and `*&mut` in expressions.
@@ -42,19 +43,55 @@ impl EarlyLintPass for DerefAddrOf {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) {
         if_chain! {
             if let ExprKind::Unary(UnOp::Deref, ref deref_target) = e.kind;
-            if let ExprKind::AddrOf(_, _, ref addrof_target) = without_parens(deref_target).kind;
+            if let ExprKind::AddrOf(_, ref mutability, ref addrof_target) = without_parens(deref_target).kind;
             if !in_macro(addrof_target.span);
             then {
                 let mut applicability = Applicability::MachineApplicable;
-                span_lint_and_sugg(
-                    cx,
-                    DEREF_ADDROF,
-                    e.span,
-                    "immediately dereferencing a reference",
-                    "try this",
-                    format!("{}", snippet_with_applicability(cx, addrof_target.span, "_", &mut applicability)),
-                    applicability,
-                );
+                let sugg = if e.span.from_expansion() {
+                    if let Ok(macro_source) = cx.sess.source_map().span_to_snippet(e.span) {
+                        // Remove leading whitespace from the given span
+                        // e.g: ` $visitor` turns into `$visitor`
+                        let trim_leading_whitespaces = |span| {
+                            snippet_opt(cx, span).and_then(|snip| {
+                                #[allow(clippy::cast_possible_truncation)]
+                                snip.find(|c: char| !c.is_whitespace()).map(|pos| {
+                                    span.lo() + BytePos(pos as u32)
+                                })
+                            }).map_or(span, |start_no_whitespace| e.span.with_lo(start_no_whitespace))
+                        };
+
+                        let mut generate_snippet = |pattern: &str| {
+                            #[allow(clippy::cast_possible_truncation)]
+                            macro_source.rfind(pattern).map(|pattern_pos| {
+                                let rpos = pattern_pos + pattern.len();
+                                let span_after_ref = e.span.with_lo(BytePos(e.span.lo().0 + rpos as u32));
+                                let span = trim_leading_whitespaces(span_after_ref);
+                                snippet_with_applicability(cx, span, "_", &mut applicability)
+                            })
+                        };
+
+                        if *mutability == Mutability::Mut {
+                            generate_snippet("mut")
+                        } else {
+                            generate_snippet("&")
+                        }
+                    } else {
+                        Some(snippet_with_applicability(cx, e.span, "_", &mut applicability))
+                    }
+                } else {
+                    Some(snippet_with_applicability(cx, addrof_target.span, "_", &mut applicability))
+                };
+                if let Some(sugg) = sugg {
+                    span_lint_and_sugg(
+                        cx,
+                        DEREF_ADDROF,
+                        e.span,
+                        "immediately dereferencing a reference",
+                        "try this",
+                        sugg.to_string(),
+                        applicability,
+                    );
+                }
             }
         }
     }
index 95594e38c9ec14a7ef7d13b15f3c78fa6ed1b8de..d06ab14348237630582a8e2b4fe663ab6725d972 100644 (file)
@@ -11,7 +11,7 @@
 
 declare_clippy_lint! {
     /// **What it does:** Checks [regex](https://crates.io/crates/regex) creation
-    /// (with `Regex::new`,`RegexBuilder::new` or `RegexSet::new`) for correct
+    /// (with `Regex::new`, `RegexBuilder::new`, or `RegexSet::new`) for correct
     /// regex syntax.
     ///
     /// **Why is this bad?** This will lead to a runtime panic.
@@ -29,7 +29,7 @@
 
 declare_clippy_lint! {
     /// **What it does:** Checks for trivial [regex](https://crates.io/crates/regex)
-    /// creation (with `Regex::new`, `RegexBuilder::new` or `RegexSet::new`).
+    /// creation (with `Regex::new`, `RegexBuilder::new`, or `RegexSet::new`).
     ///
     /// **Why is this bad?** Matching the regex can likely be replaced by `==` or
     /// `str::starts_with`, `str::ends_with` or `std::contains` or other `str`
index 0dd2da949c4c33e5d8105148abda3f98430465b0..ede37624f71a4f1e7364cf4ae70af461c74dacf3 100644 (file)
@@ -1,5 +1,5 @@
 use rustc_errors::Applicability;
-use rustc_hir::{BinOpKind, Expr, ExprKind};
+use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, QPath};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -9,7 +9,10 @@
 use if_chain::if_chain;
 
 use crate::utils::SpanlessEq;
-use crate::utils::{get_parent_expr, is_allowed, is_type_diagnostic_item, span_lint, span_lint_and_sugg};
+use crate::utils::{
+    get_parent_expr, is_allowed, is_type_diagnostic_item, match_function_call, method_calls, paths, span_lint,
+    span_lint_and_sugg,
+};
 
 declare_clippy_lint! {
     /// **What it does:** Checks for string appends of the form `x = x + y` (without
@@ -174,16 +177,75 @@ fn is_add(cx: &LateContext<'_>, src: &Expr<'_>, target: &Expr<'_>) -> bool {
     }
 }
 
+declare_clippy_lint! {
+    /// **What it does:** Check if the string is transformed to byte array and casted back to string.
+    ///
+    /// **Why is this bad?** It's unnecessary, the string can be used directly.
+    ///
+    /// **Known problems:** None
+    ///
+    /// **Example:**
+    /// ```rust
+    /// let _ = std::str::from_utf8(&"Hello World!".as_bytes()[6..11]).unwrap();
+    /// ```
+    /// could be written as
+    /// ```rust
+    /// let _ = &"Hello World!"[6..11];
+    /// ```
+    pub STRING_FROM_UTF8_AS_BYTES,
+    complexity,
+    "casting string slices to byte slices and back"
+}
+
 // Max length a b"foo" string can take
 const MAX_LENGTH_BYTE_STRING_LIT: usize = 32;
 
-declare_lint_pass!(StringLitAsBytes => [STRING_LIT_AS_BYTES]);
+declare_lint_pass!(StringLitAsBytes => [STRING_LIT_AS_BYTES, STRING_FROM_UTF8_AS_BYTES]);
 
 impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         use crate::utils::{snippet, snippet_with_applicability};
         use rustc_ast::LitKind;
 
+        if_chain! {
+            // Find std::str::converts::from_utf8
+            if let Some(args) = match_function_call(cx, e, &paths::STR_FROM_UTF8);
+
+            // Find string::as_bytes
+            if let ExprKind::AddrOf(BorrowKind::Ref, _, ref args) = args[0].kind;
+            if let ExprKind::Index(ref left, ref right) = args.kind;
+            let (method_names, expressions, _) = method_calls(left, 1);
+            if method_names.len() == 1;
+            if expressions.len() == 1;
+            if expressions[0].len() == 1;
+            if method_names[0] == sym!(as_bytes);
+
+            // Check for slicer
+            if let ExprKind::Struct(ref path, _, _) = right.kind;
+            if let QPath::LangItem(LangItem::Range, _) = path;
+
+            then {
+                let mut applicability = Applicability::MachineApplicable;
+                let string_expression = &expressions[0][0];
+
+                let snippet_app = snippet_with_applicability(
+                    cx,
+                    string_expression.span, "..",
+                    &mut applicability,
+                );
+
+                span_lint_and_sugg(
+                    cx,
+                    STRING_FROM_UTF8_AS_BYTES,
+                    e.span,
+                    "calling a slice of `as_bytes()` with `from_utf8` should be not necessary",
+                    "try",
+                    format!("Some(&{}[{}])", snippet_app, snippet(cx, right.span, "..")),
+                    applicability
+                )
+            }
+        }
+
         if_chain! {
             if let ExprKind::MethodCall(path, _, args, _) = &e.kind;
             if path.ident.name == sym!(as_bytes);
index 6f6b6999bf0a9cdbace8ae8e28789bae480fa778..73e3a04aec98798f93600e88ae791e3d7e6cc47c 100644 (file)
@@ -1,6 +1,6 @@
 use crate::utils::{
-    is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet, snippet_with_macro_callsite,
-    span_lint_and_sugg,
+    differing_macro_contexts, in_macro, is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet,
+    snippet_with_macro_callsite, span_lint_and_sugg,
 };
 use if_chain::if_chain;
 use rustc_errors::Applicability;
@@ -92,8 +92,11 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                 };
 
                 let expr_err_ty = cx.typeck_results().expr_ty(err_arg);
+                let differing_contexts = differing_macro_contexts(expr.span, err_arg.span);
 
-                let origin_snippet = if err_arg.span.from_expansion() {
+                let origin_snippet = if in_macro(expr.span) && in_macro(err_arg.span) && differing_contexts {
+                    snippet(cx, err_arg.span.ctxt().outer_expn_data().call_site, "_")
+                } else if err_arg.span.from_expansion() && !in_macro(expr.span) {
                     snippet_with_macro_callsite(cx, err_arg.span, "_")
                 } else {
                     snippet(cx, err_arg.span, "_")
index c7d82da3b8ba4c0f38b6fb76a15321487b5e2f1f..f0e10e374e1182bc472c3f54b0209371ccc4543d 100644 (file)
@@ -553,7 +553,7 @@ fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, is_local: boo
                                     hir_ty.span,
                                     "`Vec<T>` is already on the heap, the boxing is unnecessary.",
                                     "try",
-                                    format!("Vec<{}>", ty_ty),
+                                    format!("Vec<{}>", snippet(cx, boxed_ty.span, "..")),
                                     Applicability::MachineApplicable,
                                 );
                                 return; // don't recurse into the type
index ade5fff5ffc0606344a613d6f2e7191717fe4b41..2501635e7ef6636933448be0ff2ac50c959a88bc 100644 (file)
@@ -24,7 +24,7 @@
     /// **Example:**
     ///
     /// ```rust
-    /// let mut twins = vec!((1,1), (2,2));
+    /// let mut twins = vec!((1, 1), (2, 2));
     /// twins.sort_by_key(|x| { x.1; });
     /// ```
     pub UNIT_RETURN_EXPECTING_ORD,
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
new file mode 100644 (file)
index 0000000..25ecc7a
--- /dev/null
@@ -0,0 +1,143 @@
+use crate::utils::{
+    in_macro, is_type_diagnostic_item, match_qpath, paths, return_ty, snippet, span_lint_and_then,
+    visitors::find_all_ret_expressions,
+};
+use if_chain::if_chain;
+use rustc_errors::Applicability;
+use rustc_hir::intravisit::FnKind;
+use rustc_hir::{Body, ExprKind, FnDecl, HirId, ItemKind, Node};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::subst::GenericArgKind;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::Span;
+
+declare_clippy_lint! {
+    /// **What it does:** Checks for private functions that only return `Ok` or `Some`.
+    ///
+    /// **Why is this bad?** It is not meaningful to wrap values when no `None` or `Err` is returned.
+    ///
+    /// **Known problems:** Since this lint changes function type signature, you may need to
+    /// adjust some code at callee side.
+    ///
+    /// **Example:**
+    ///
+    /// ```rust
+    /// fn get_cool_number(a: bool, b: bool) -> Option<i32> {
+    ///     if a && b {
+    ///         return Some(50);
+    ///     }
+    ///     if a {
+    ///         Some(0)
+    ///     } else {
+    ///         Some(10)
+    ///     }
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// fn get_cool_number(a: bool, b: bool) -> i32 {
+    ///     if a && b {
+    ///         return 50;
+    ///     }
+    ///     if a {
+    ///         0
+    ///     } else {
+    ///         10
+    ///     }
+    /// }
+    /// ```
+    pub UNNECESSARY_WRAPS,
+    complexity,
+    "functions that only return `Ok` or `Some`"
+}
+
+declare_lint_pass!(UnnecessaryWraps => [UNNECESSARY_WRAPS]);
+
+impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
+    fn check_fn(
+        &mut self,
+        cx: &LateContext<'tcx>,
+        fn_kind: FnKind<'tcx>,
+        fn_decl: &FnDecl<'tcx>,
+        body: &Body<'tcx>,
+        span: Span,
+        hir_id: HirId,
+    ) {
+        match fn_kind {
+            FnKind::ItemFn(.., visibility, _) | FnKind::Method(.., Some(visibility), _) => {
+                if visibility.node.is_pub() {
+                    return;
+                }
+            },
+            FnKind::Closure(..) => return,
+            _ => (),
+        }
+
+        if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
+            if matches!(item.kind, ItemKind::Impl{ of_trait: Some(_), ..} | ItemKind::Trait(..)) {
+                return;
+            }
+        }
+
+        let (return_type, path) = if is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym!(option_type)) {
+            ("Option", &paths::OPTION_SOME)
+        } else if is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym!(result_type)) {
+            ("Result", &paths::RESULT_OK)
+        } else {
+            return;
+        };
+
+        let mut suggs = Vec::new();
+        let can_sugg = find_all_ret_expressions(cx, &body.value, |ret_expr| {
+            if_chain! {
+                if !in_macro(ret_expr.span);
+                if let ExprKind::Call(ref func, ref args) = ret_expr.kind;
+                if let ExprKind::Path(ref qpath) = func.kind;
+                if match_qpath(qpath, path);
+                if args.len() == 1;
+                then {
+                    suggs.push((ret_expr.span, snippet(cx, args[0].span.source_callsite(), "..").to_string()));
+                    true
+                } else {
+                    false
+                }
+            }
+        });
+
+        if can_sugg && !suggs.is_empty() {
+            span_lint_and_then(
+                cx,
+                UNNECESSARY_WRAPS,
+                span,
+                format!(
+                    "this function's return value is unnecessarily wrapped by `{}`",
+                    return_type
+                )
+                .as_str(),
+                |diag| {
+                    let inner_ty = return_ty(cx, hir_id)
+                        .walk()
+                        .skip(1) // skip `std::option::Option` or `std::result::Result`
+                        .take(1) // take the first outermost inner type
+                        .filter_map(|inner| match inner.unpack() {
+                            GenericArgKind::Type(inner_ty) => Some(inner_ty.to_string()),
+                            _ => None,
+                        });
+                    inner_ty.for_each(|inner_ty| {
+                        diag.span_suggestion(
+                            fn_decl.output.span(),
+                            format!("remove `{}` from the return type...", return_type).as_str(),
+                            inner_ty,
+                            Applicability::MaybeIncorrect,
+                        );
+                    });
+                    diag.multipart_suggestion(
+                        "...and change the returning expressions",
+                        suggs,
+                        Applicability::MachineApplicable,
+                    );
+                },
+            );
+        }
+    }
+}
index b1339c3d6395de31cb5c56573debb95fdca5806c..f61fd2ecd735d915964c5b3ce80bfaa6da56e29e 100644 (file)
@@ -7,7 +7,7 @@
 use rustc_span::source_map::Span;
 use rustc_span::BytePos;
 
-use crate::utils::span_lint_and_sugg;
+use crate::utils::{position_before_rarrow, span_lint_and_sugg};
 
 declare_clippy_lint! {
     /// **What it does:** Checks for unit (`()`) expressions that can be removed.
@@ -120,26 +120,13 @@ fn is_unit_expr(expr: &ast::Expr) -> bool {
 
 fn lint_unneeded_unit_return(cx: &EarlyContext<'_>, ty: &ast::Ty, span: Span) {
     let (ret_span, appl) = if let Ok(fn_source) = cx.sess().source_map().span_to_snippet(span.with_hi(ty.span.hi())) {
-        fn_source
-            .rfind("->")
-            .map_or((ty.span, Applicability::MaybeIncorrect), |rpos| {
-                let mut rpos = rpos;
-                let chars: Vec<char> = fn_source.chars().collect();
-                while rpos > 1 {
-                    if let Some(c) = chars.get(rpos - 1) {
-                        if c.is_whitespace() {
-                            rpos -= 1;
-                            continue;
-                        }
-                    }
-                    break;
-                }
-                (
-                    #[allow(clippy::cast_possible_truncation)]
-                    ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)),
-                    Applicability::MachineApplicable,
-                )
-            })
+        position_before_rarrow(fn_source).map_or((ty.span, Applicability::MaybeIncorrect), |rpos| {
+            (
+                #[allow(clippy::cast_possible_truncation)]
+                ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)),
+                Applicability::MachineApplicable,
+            )
+        })
     } else {
         (ty.span, Applicability::MaybeIncorrect)
     };
index c6194b0c6de3ea74fe4cdd49c76cff1a96e74784..efa9c3fab4ab83c20c95d607a1df7ab7d5e71862 100644 (file)
@@ -12,8 +12,8 @@
 use rustc_span::sym;
 
 declare_clippy_lint! {
-    /// **What it does:** Checks for `Into`, `TryInto`, `From`, `TryFrom`,`IntoIter` calls
-    /// that useless converts to the same type as caller.
+    /// **What it does:** Checks for `Into`, `TryInto`, `From`, `TryFrom`, or `IntoIter` calls
+    /// which uselessly convert to the same type.
     ///
     /// **Why is this bad?** Redundant code.
     ///
@@ -31,7 +31,7 @@
     /// ```
     pub USELESS_CONVERSION,
     complexity,
-    "calls to `Into`, `TryInto`, `From`, `TryFrom`, `IntoIter` that performs useless conversions to the same type"
+    "calls to `Into`, `TryInto`, `From`, `TryFrom`, or `IntoIter` which perform useless conversions to the same type"
 }
 
 #[derive(Default)]
index 9050b9b2d9ab820c04332248b383375048eb67a5..fcf7a4b1367e3c4086bf6edeabe3faa519e3f948 100644 (file)
@@ -110,8 +110,7 @@ pub fn eq_expr_opt(l: &Option<P<Expr>>, r: &Option<P<Expr>>) -> bool {
 pub fn eq_struct_rest(l: &StructRest, r: &StructRest) -> bool {
     match (l, r) {
         (StructRest::Base(lb), StructRest::Base(rb)) => eq_expr(lb, rb),
-        (StructRest::Rest(_), StructRest::Rest(_)) => true,
-        (StructRest::None, StructRest::None) => true,
+        (StructRest::Rest(_), StructRest::Rest(_)) | (StructRest::None, StructRest::None) => true,
         _ => false,
     }
 }
index 4ceea13df377dc94db255feeb5bb543a16a112ce..8fe5ddee1ca8d8cf11d4ad300904cae10cc82ddf 100644 (file)
@@ -9,7 +9,7 @@
 //!  - or-fun-call
 //!  - option-if-let-else
 
-use crate::utils::is_ctor_or_promotable_const_function;
+use crate::utils::{is_ctor_or_promotable_const_function, is_type_diagnostic_item, match_type, paths};
 use rustc_hir::def::{DefKind, Res};
 
 use rustc_hir::intravisit;
@@ -96,6 +96,11 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
             let call_found = match &expr.kind {
                 // ignore enum and struct constructors
                 ExprKind::Call(..) => !is_ctor_or_promotable_const_function(self.cx, expr),
+                ExprKind::Index(obj, _) => {
+                    let ty = self.cx.typeck_results().expr_ty(obj);
+                    is_type_diagnostic_item(self.cx, ty, sym!(hashmap_type))
+                        || match_type(self.cx, ty, &paths::BTREEMAP)
+                },
                 ExprKind::MethodCall(..) => true,
                 _ => false,
             };
index 4fbfb3be32cbff9e821171c9d3d9112a977fdd3b..8f0ef9150d4503824677526c68155c243d617b97 100644 (file)
@@ -395,7 +395,7 @@ fn print_item(cx: &LateContext<'_>, item: &hir::Item<'_>) {
             println!("function of type {:#?}", item_ty);
         },
         hir::ItemKind::Mod(..) => println!("module"),
-        hir::ItemKind::ForeignMod(ref fm) => println!("foreign module with abi: {}", fm.abi),
+        hir::ItemKind::ForeignMod { abi, .. } => println!("foreign module with abi: {}", abi),
         hir::ItemKind::GlobalAsm(ref asm) => println!("global asm: {:?}", asm),
         hir::ItemKind::TyAlias(..) => {
             println!("type alias for {:?}", cx.tcx.type_of(did));
index 270fdc9bf462f6750621c2d83929528d7e933f30..e9c71e23a670b2c2997dd4e6f2ebbd7760dd157a 100644 (file)
@@ -21,6 +21,7 @@
 pub mod qualify_min_const_fn;
 pub mod sugg;
 pub mod usage;
+pub mod visitors;
 
 pub use self::attrs::*;
 pub use self::diagnostics::*;
@@ -364,6 +365,9 @@ pub fn implements_trait<'tcx>(
         return false;
     }
     let ty = cx.tcx.erase_regions(ty);
+    if ty.has_escaping_bound_vars() {
+        return false;
+    }
     let ty_params = cx.tcx.mk_substs(ty_params.iter());
     cx.tcx.type_implements_trait((trait_id, ty, ty_params, cx.param_env))
 }
@@ -468,6 +472,13 @@ pub fn is_entrypoint_fn(cx: &LateContext<'_>, def_id: DefId) -> bool {
         .map_or(false, |(entry_fn_def_id, _)| def_id == entry_fn_def_id.to_def_id())
 }
 
+/// Returns `true` if the expression is in the program's `#[panic_handler]`.
+pub fn is_in_panic_handler(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
+    let parent = cx.tcx.hir().get_parent_item(e.hir_id);
+    let def_id = cx.tcx.hir().local_def_id(parent).to_def_id();
+    Some(def_id) == cx.tcx.lang_items().panic_impl()
+}
+
 /// Gets the name of the item the expression is in, if available.
 pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> {
     let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id);
@@ -659,6 +670,35 @@ pub fn indent_of<T: LintContext>(cx: &T, span: Span) -> Option<usize> {
     snippet_opt(cx, line_span(cx, span)).and_then(|snip| snip.find(|c: char| !c.is_whitespace()))
 }
 
+/// Returns the positon just before rarrow
+///
+/// ```rust,ignore
+/// fn into(self) -> () {}
+///              ^
+/// // in case of unformatted code
+/// fn into2(self)-> () {}
+///               ^
+/// fn into3(self)   -> () {}
+///               ^
+/// ```
+#[allow(clippy::needless_pass_by_value)]
+pub fn position_before_rarrow(s: String) -> Option<usize> {
+    s.rfind("->").map(|rpos| {
+        let mut rpos = rpos;
+        let chars: Vec<char> = s.chars().collect();
+        while rpos > 1 {
+            if let Some(c) = chars.get(rpos - 1) {
+                if c.is_whitespace() {
+                    rpos -= 1;
+                    continue;
+                }
+            }
+            break;
+        }
+        rpos
+    })
+}
+
 /// Extends the span to the beginning of the spans line, incl. whitespaces.
 ///
 /// ```rust,ignore
index 8f5fbfd9f846a5706a3a3e2cec2a5eb98c5854a3..137f5d18b6649d0ae26d8694b863e9e907e72b6d 100644 (file)
 pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_str"];
 pub const STRING_AS_STR: [&str; 4] = ["alloc", "string", "String", "as_str"];
 pub const STR_ENDS_WITH: [&str; 4] = ["core", "str", "<impl str>", "ends_with"];
+pub const STR_FROM_UTF8: [&str; 4] = ["core", "str", "converts", "from_utf8"];
 pub const STR_LEN: [&str; 4] = ["core", "str", "<impl str>", "len"];
 pub const STR_STARTS_WITH: [&str; 4] = ["core", "str", "<impl str>", "starts_with"];
 pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"];
diff --git a/src/tools/clippy/clippy_lints/src/utils/visitors.rs b/src/tools/clippy/clippy_lints/src/utils/visitors.rs
new file mode 100644 (file)
index 0000000..b0837b6
--- /dev/null
@@ -0,0 +1,125 @@
+use rustc_hir as hir;
+use rustc_hir::intravisit::{self, Visitor};
+use rustc_lint::LateContext;
+use rustc_middle::hir::map::Map;
+
+/// returns `true` if expr contains match expr desugared from try
+fn contains_try(expr: &hir::Expr<'_>) -> bool {
+    struct TryFinder {
+        found: bool,
+    }
+
+    impl<'hir> intravisit::Visitor<'hir> for TryFinder {
+        type Map = Map<'hir>;
+
+        fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+            intravisit::NestedVisitorMap::None
+        }
+
+        fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
+            if self.found {
+                return;
+            }
+            match expr.kind {
+                hir::ExprKind::Match(_, _, hir::MatchSource::TryDesugar) => self.found = true,
+                _ => intravisit::walk_expr(self, expr),
+            }
+        }
+    }
+
+    let mut visitor = TryFinder { found: false };
+    visitor.visit_expr(expr);
+    visitor.found
+}
+
+pub fn find_all_ret_expressions<'hir, F>(_cx: &LateContext<'_>, expr: &'hir hir::Expr<'hir>, callback: F) -> bool
+where
+    F: FnMut(&'hir hir::Expr<'hir>) -> bool,
+{
+    struct RetFinder<F> {
+        in_stmt: bool,
+        failed: bool,
+        cb: F,
+    }
+
+    struct WithStmtGuarg<'a, F> {
+        val: &'a mut RetFinder<F>,
+        prev_in_stmt: bool,
+    }
+
+    impl<F> RetFinder<F> {
+        fn inside_stmt(&mut self, in_stmt: bool) -> WithStmtGuarg<'_, F> {
+            let prev_in_stmt = std::mem::replace(&mut self.in_stmt, in_stmt);
+            WithStmtGuarg {
+                val: self,
+                prev_in_stmt,
+            }
+        }
+    }
+
+    impl<F> std::ops::Deref for WithStmtGuarg<'_, F> {
+        type Target = RetFinder<F>;
+
+        fn deref(&self) -> &Self::Target {
+            self.val
+        }
+    }
+
+    impl<F> std::ops::DerefMut for WithStmtGuarg<'_, F> {
+        fn deref_mut(&mut self) -> &mut Self::Target {
+            self.val
+        }
+    }
+
+    impl<F> Drop for WithStmtGuarg<'_, F> {
+        fn drop(&mut self) {
+            self.val.in_stmt = self.prev_in_stmt;
+        }
+    }
+
+    impl<'hir, F: FnMut(&'hir hir::Expr<'hir>) -> bool> intravisit::Visitor<'hir> for RetFinder<F> {
+        type Map = Map<'hir>;
+
+        fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+            intravisit::NestedVisitorMap::None
+        }
+
+        fn visit_stmt(&mut self, stmt: &'hir hir::Stmt<'_>) {
+            intravisit::walk_stmt(&mut *self.inside_stmt(true), stmt)
+        }
+
+        fn visit_expr(&mut self, expr: &'hir hir::Expr<'_>) {
+            if self.failed {
+                return;
+            }
+            if self.in_stmt {
+                match expr.kind {
+                    hir::ExprKind::Ret(Some(expr)) => self.inside_stmt(false).visit_expr(expr),
+                    _ => intravisit::walk_expr(self, expr),
+                }
+            } else {
+                match expr.kind {
+                    hir::ExprKind::Match(cond, arms, _) => {
+                        self.inside_stmt(true).visit_expr(cond);
+                        for arm in arms {
+                            self.visit_expr(arm.body);
+                        }
+                    },
+                    hir::ExprKind::Block(..) => intravisit::walk_expr(self, expr),
+                    hir::ExprKind::Ret(Some(expr)) => self.visit_expr(expr),
+                    _ => self.failed |= !(self.cb)(expr),
+                }
+            }
+        }
+    }
+
+    !contains_try(expr) && {
+        let mut ret_finder = RetFinder {
+            in_stmt: false,
+            failed: false,
+            cb: callback,
+        };
+        ret_finder.visit_expr(expr);
+        !ret_finder.failed
+    }
+}
index 497264649573018a92df83380ad4308709979fea..115848c48044ce19000414b2923ba5f1fc5f3e4e 100644 (file)
@@ -29,8 +29,11 @@ bullet points might be helpful:
 * When writing the release notes for the **upcoming beta release**, you need to check
   out the Clippy commit of the current Rust `master`. [Link][rust_master_tools]
 * When writing the (forgotten) release notes for a **past stable release**, you
-  need to select the Rust release tag from the dropdown and then check the
-  commit of the Clippy directory:
+  need to check out the Rust release tag of the stable release.
+  [Link][rust_stable_tools]
+
+Usually you want to wirte the changelog of the **upcoming stable release**. Make
+sure though, that `beta` was already branched in the Rust repository.
 
 To find the commit hash, issue the following command when in a `rust-lang/rust` checkout:
 ```
@@ -71,6 +74,19 @@ The order should roughly be:
 7. Documentation improvements
 8. Others
 
+As section headers, we use:
+
+```
+### New Lints
+### Moves and Deprecations
+### Enhancements
+### False Positive Fixes
+### Suggestion Fixes/Improvements
+### ICE Fixes
+### Documentation Improvements
+### Others
+```
+
 Please also be sure to update the Beta/Unreleased sections at the top with the
 relevant commit ranges.
 
@@ -78,3 +94,4 @@ relevant commit ranges.
 [forge]: https://forge.rust-lang.org/
 [rust_master_tools]: https://github.com/rust-lang/rust/tree/master/src/tools/clippy
 [rust_beta_tools]: https://github.com/rust-lang/rust/tree/beta/src/tools/clippy
+[rust_stable_tools]: https://github.com/rust-lang/rust/releases
index cc71cc66b925b1ebb876fa1793afa57bb570401b..ef31c72481a236793b026fac2c02ca820268ac2c 100644 (file)
@@ -8,7 +8,6 @@
 
 // FIXME: switch to something more ergonomic here, once available.
 // (Currently there is no way to opt into sysroot crates without `extern crate`.)
-extern crate rustc_data_structures;
 extern crate rustc_driver;
 extern crate rustc_errors;
 extern crate rustc_interface;
@@ -26,8 +25,6 @@
 use std::path::{Path, PathBuf};
 use std::process::{exit, Command};
 
-mod lintlist;
-
 /// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If
 /// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`.
 fn arg_value<'a, T: Deref<Target = str>>(
@@ -92,113 +89,6 @@ fn config(&mut self, config: &mut interface::Config) {
     }
 }
 
-#[allow(clippy::find_map, clippy::filter_map)]
-fn describe_lints() {
-    use lintlist::{Level, Lint, ALL_LINTS, LINT_LEVELS};
-    use rustc_data_structures::fx::FxHashSet;
-
-    println!(
-        "
-Available lint options:
-    -W <foo>           Warn about <foo>
-    -A <foo>           Allow <foo>
-    -D <foo>           Deny <foo>
-    -F <foo>           Forbid <foo> (deny <foo> and all attempts to override)
-
-"
-    );
-
-    let lint_level = |lint: &Lint| {
-        LINT_LEVELS
-            .iter()
-            .find(|level_mapping| level_mapping.0 == lint.group)
-            .map(|(_, level)| match level {
-                Level::Allow => "allow",
-                Level::Warn => "warn",
-                Level::Deny => "deny",
-            })
-            .unwrap()
-    };
-
-    let mut lints: Vec<_> = ALL_LINTS.iter().collect();
-    // The sort doesn't case-fold but it's doubtful we care.
-    lints.sort_by_cached_key(|x: &&Lint| (lint_level(x), x.name));
-
-    let max_lint_name_len = lints
-        .iter()
-        .map(|lint| lint.name.len())
-        .map(|len| len + "clippy::".len())
-        .max()
-        .unwrap_or(0);
-
-    let padded = |x: &str| {
-        let mut s = " ".repeat(max_lint_name_len - x.chars().count());
-        s.push_str(x);
-        s
-    };
-
-    let scoped = |x: &str| format!("clippy::{}", x);
-
-    let lint_groups: FxHashSet<_> = lints.iter().map(|lint| lint.group).collect();
-
-    println!("Lint checks provided by clippy:\n");
-    println!("    {}  {:7.7}  meaning", padded("name"), "default");
-    println!("    {}  {:7.7}  -------", padded("----"), "-------");
-
-    let print_lints = |lints: &[&Lint]| {
-        for lint in lints {
-            let name = lint.name.replace("_", "-");
-            println!(
-                "    {}  {:7.7}  {}",
-                padded(&scoped(&name)),
-                lint_level(lint),
-                lint.desc
-            );
-        }
-        println!("\n");
-    };
-
-    print_lints(&lints);
-
-    let max_group_name_len = std::cmp::max(
-        "clippy::all".len(),
-        lint_groups
-            .iter()
-            .map(|group| group.len())
-            .map(|len| len + "clippy::".len())
-            .max()
-            .unwrap_or(0),
-    );
-
-    let padded_group = |x: &str| {
-        let mut s = " ".repeat(max_group_name_len - x.chars().count());
-        s.push_str(x);
-        s
-    };
-
-    println!("Lint groups provided by clippy:\n");
-    println!("    {}  sub-lints", padded_group("name"));
-    println!("    {}  ---------", padded_group("----"));
-    println!("    {}  the set of all clippy lints", padded_group("clippy::all"));
-
-    let print_lint_groups = || {
-        for group in lint_groups {
-            let name = group.to_lowercase().replace("_", "-");
-            let desc = lints
-                .iter()
-                .filter(|&lint| lint.group == group)
-                .map(|lint| lint.name)
-                .map(|name| name.replace("_", "-"))
-                .collect::<Vec<String>>()
-                .join(", ");
-            println!("    {}  {}", padded_group(&scoped(&name)), desc);
-        }
-        println!("\n");
-    };
-
-    print_lint_groups();
-}
-
 fn display_help() {
     println!(
         "\
@@ -379,17 +269,6 @@ pub fn main() {
             exit(0);
         }
 
-        let should_describe_lints = || {
-            let args: Vec<_> = env::args().collect();
-            args.windows(2)
-                .any(|args| args[1] == "help" && matches!(args[0].as_str(), "-W" | "-A" | "-D" | "-F"))
-        };
-
-        if !wrapper_mode && should_describe_lints() {
-            describe_lints();
-            exit(0);
-        }
-
         // this conditional check for the --sysroot flag is there so users can call
         // `clippy_driver` directly
         // without having to pass --sysroot or anything
diff --git a/src/tools/clippy/src/lintlist/lint.rs b/src/tools/clippy/src/lintlist/lint.rs
deleted file mode 100644 (file)
index c817d83..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/// Lint data parsed from the Clippy source code.
-#[derive(Clone, PartialEq, Debug)]
-pub struct Lint {
-    pub name: &'static str,
-    pub group: &'static str,
-    pub desc: &'static str,
-    pub deprecation: Option<&'static str>,
-    pub module: &'static str,
-}
-
-#[derive(PartialOrd, PartialEq, Ord, Eq)]
-pub enum Level {
-    Allow,
-    Warn,
-    Deny,
-}
-
-pub const LINT_LEVELS: [(&str, Level); 8] = [
-    ("correctness", Level::Deny),
-    ("style", Level::Warn),
-    ("complexity", Level::Warn),
-    ("perf", Level::Warn),
-    ("restriction", Level::Allow),
-    ("pedantic", Level::Allow),
-    ("nursery", Level::Allow),
-    ("cargo", Level::Allow),
-];
diff --git a/src/tools/clippy/src/lintlist/mod.rs b/src/tools/clippy/src/lintlist/mod.rs
deleted file mode 100644 (file)
index 702f9d8..0000000
+++ /dev/null
@@ -1,2928 +0,0 @@
-//! This file is managed by `cargo dev update_lints`. Do not edit or format this file.
-
-use std::lazy::SyncLazy;
-
-pub mod lint;
-pub use lint::Level;
-pub use lint::Lint;
-pub use lint::LINT_LEVELS;
-
-#[rustfmt::skip]
-pub static ALL_LINTS: SyncLazy<Vec<Lint>> = SyncLazy::new(|| {
-// begin lint list, do not remove this comment, it’s used in `update_lints`
-vec![
-    Lint {
-        name: "absurd_extreme_comparisons",
-        group: "correctness",
-        desc: "a comparison with a maximum or minimum value that is always true or false",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "almost_swapped",
-        group: "correctness",
-        desc: "`foo = bar; bar = foo` sequence",
-        deprecation: None,
-        module: "swap",
-    },
-    Lint {
-        name: "approx_constant",
-        group: "correctness",
-        desc: "the approximate of a known float constant (in `std::fXX::consts`)",
-        deprecation: None,
-        module: "approx_const",
-    },
-    Lint {
-        name: "as_conversions",
-        group: "restriction",
-        desc: "using a potentially dangerous silent `as` conversion",
-        deprecation: None,
-        module: "as_conversions",
-    },
-    Lint {
-        name: "assertions_on_constants",
-        group: "style",
-        desc: "`assert!(true)` / `assert!(false)` will be optimized out by the compiler, and should probably be replaced by a `panic!()` or `unreachable!()`",
-        deprecation: None,
-        module: "assertions_on_constants",
-    },
-    Lint {
-        name: "assign_op_pattern",
-        group: "style",
-        desc: "assigning the result of an operation on a variable to that same variable",
-        deprecation: None,
-        module: "assign_ops",
-    },
-    Lint {
-        name: "async_yields_async",
-        group: "correctness",
-        desc: "async blocks that return a type that can be awaited",
-        deprecation: None,
-        module: "async_yields_async",
-    },
-    Lint {
-        name: "await_holding_lock",
-        group: "correctness",
-        desc: "Inside an async function, holding a MutexGuard while calling await",
-        deprecation: None,
-        module: "await_holding_invalid",
-    },
-    Lint {
-        name: "await_holding_refcell_ref",
-        group: "correctness",
-        desc: "Inside an async function, holding a RefCell ref while calling await",
-        deprecation: None,
-        module: "await_holding_invalid",
-    },
-    Lint {
-        name: "bad_bit_mask",
-        group: "correctness",
-        desc: "expressions of the form `_ & mask == select` that will only ever return `true` or `false`",
-        deprecation: None,
-        module: "bit_mask",
-    },
-    Lint {
-        name: "bind_instead_of_map",
-        group: "complexity",
-        desc: "using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)`",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "blacklisted_name",
-        group: "style",
-        desc: "usage of a blacklisted/placeholder name",
-        deprecation: None,
-        module: "blacklisted_name",
-    },
-    Lint {
-        name: "blanket_clippy_restriction_lints",
-        group: "style",
-        desc: "enabling the complete restriction group",
-        deprecation: None,
-        module: "attrs",
-    },
-    Lint {
-        name: "blocks_in_if_conditions",
-        group: "style",
-        desc: "useless or complex blocks that can be eliminated in conditions",
-        deprecation: None,
-        module: "blocks_in_if_conditions",
-    },
-    Lint {
-        name: "bool_comparison",
-        group: "complexity",
-        desc: "comparing a variable to a boolean, e.g., `if x == true` or `if x != true`",
-        deprecation: None,
-        module: "needless_bool",
-    },
-    Lint {
-        name: "borrow_interior_mutable_const",
-        group: "style",
-        desc: "referencing `const` with interior mutability",
-        deprecation: None,
-        module: "non_copy_const",
-    },
-    Lint {
-        name: "borrowed_box",
-        group: "complexity",
-        desc: "a borrow of a boxed type",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "box_vec",
-        group: "perf",
-        desc: "usage of `Box<Vec<T>>`, vector elements are already on the heap",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "boxed_local",
-        group: "perf",
-        desc: "using `Box<T>` where unnecessary",
-        deprecation: None,
-        module: "escape",
-    },
-    Lint {
-        name: "builtin_type_shadow",
-        group: "style",
-        desc: "shadowing a builtin type",
-        deprecation: None,
-        module: "misc_early",
-    },
-    Lint {
-        name: "cargo_common_metadata",
-        group: "cargo",
-        desc: "common metadata is defined in `Cargo.toml`",
-        deprecation: None,
-        module: "cargo_common_metadata",
-    },
-    Lint {
-        name: "cast_lossless",
-        group: "pedantic",
-        desc: "casts using `as` that are known to be lossless, e.g., `x as u64` where `x: u8`",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "cast_possible_truncation",
-        group: "pedantic",
-        desc: "casts that may cause truncation of the value, e.g., `x as u8` where `x: u32`, or `x as i32` where `x: f32`",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "cast_possible_wrap",
-        group: "pedantic",
-        desc: "casts that may cause wrapping around the value, e.g., `x as i32` where `x: u32` and `x > i32::MAX`",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "cast_precision_loss",
-        group: "pedantic",
-        desc: "casts that cause loss of precision, e.g., `x as f32` where `x: u64`",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "cast_ptr_alignment",
-        group: "pedantic",
-        desc: "cast from a pointer to a more-strictly-aligned pointer",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "cast_ref_to_mut",
-        group: "correctness",
-        desc: "a cast of reference to a mutable pointer",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "cast_sign_loss",
-        group: "pedantic",
-        desc: "casts from signed types to unsigned types, e.g., `x as u32` where `x: i32`",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "char_lit_as_u8",
-        group: "complexity",
-        desc: "casting a character literal to `u8` truncates",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "chars_last_cmp",
-        group: "style",
-        desc: "using `.chars().last()` or `.chars().next_back()` to check if a string ends with a char",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "chars_next_cmp",
-        group: "style",
-        desc: "using `.chars().next()` to check if a string starts with a char",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "checked_conversions",
-        group: "pedantic",
-        desc: "`try_from` could replace manual bounds checking when casting",
-        deprecation: None,
-        module: "checked_conversions",
-    },
-    Lint {
-        name: "clone_double_ref",
-        group: "correctness",
-        desc: "using `clone` on `&&T`",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "clone_on_copy",
-        group: "complexity",
-        desc: "using `clone` on a `Copy` type",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "clone_on_ref_ptr",
-        group: "restriction",
-        desc: "using \'clone\' on a ref-counted pointer",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "cmp_nan",
-        group: "correctness",
-        desc: "comparisons to `NAN`, which will always return false, probably not intended",
-        deprecation: None,
-        module: "misc",
-    },
-    Lint {
-        name: "cmp_null",
-        group: "style",
-        desc: "comparing a pointer to a null pointer, suggesting to use `.is_null()` instead.",
-        deprecation: None,
-        module: "ptr",
-    },
-    Lint {
-        name: "cmp_owned",
-        group: "perf",
-        desc: "creating owned instances for comparing with others, e.g., `x == \"foo\".to_string()`",
-        deprecation: None,
-        module: "misc",
-    },
-    Lint {
-        name: "cognitive_complexity",
-        group: "nursery",
-        desc: "functions that should be split up into multiple functions",
-        deprecation: None,
-        module: "cognitive_complexity",
-    },
-    Lint {
-        name: "collapsible_if",
-        group: "style",
-        desc: "`if`s that can be collapsed (e.g., `if x { if y { ... } }` and `else { if x { ... } }`)",
-        deprecation: None,
-        module: "collapsible_if",
-    },
-    Lint {
-        name: "comparison_chain",
-        group: "style",
-        desc: "`if`s that can be rewritten with `match` and `cmp`",
-        deprecation: None,
-        module: "comparison_chain",
-    },
-    Lint {
-        name: "comparison_to_empty",
-        group: "style",
-        desc: "checking `x == \"\"` or `x == []` (or similar) when `.is_empty()` could be used instead",
-        deprecation: None,
-        module: "len_zero",
-    },
-    Lint {
-        name: "copy_iterator",
-        group: "pedantic",
-        desc: "implementing `Iterator` on a `Copy` type",
-        deprecation: None,
-        module: "copy_iterator",
-    },
-    Lint {
-        name: "create_dir",
-        group: "restriction",
-        desc: "calling `std::fs::create_dir` instead of `std::fs::create_dir_all`",
-        deprecation: None,
-        module: "create_dir",
-    },
-    Lint {
-        name: "crosspointer_transmute",
-        group: "complexity",
-        desc: "transmutes that have to or from types that are a pointer to the other",
-        deprecation: None,
-        module: "transmute",
-    },
-    Lint {
-        name: "dbg_macro",
-        group: "restriction",
-        desc: "`dbg!` macro is intended as a debugging tool",
-        deprecation: None,
-        module: "dbg_macro",
-    },
-    Lint {
-        name: "debug_assert_with_mut_call",
-        group: "nursery",
-        desc: "mutable arguments in `debug_assert{,_ne,_eq}!`",
-        deprecation: None,
-        module: "mutable_debug_assertion",
-    },
-    Lint {
-        name: "decimal_literal_representation",
-        group: "restriction",
-        desc: "using decimal representation when hexadecimal would be better",
-        deprecation: None,
-        module: "literal_representation",
-    },
-    Lint {
-        name: "declare_interior_mutable_const",
-        group: "style",
-        desc: "declaring `const` with interior mutability",
-        deprecation: None,
-        module: "non_copy_const",
-    },
-    Lint {
-        name: "default_trait_access",
-        group: "pedantic",
-        desc: "checks for literal calls to `Default::default()`",
-        deprecation: None,
-        module: "default",
-    },
-    Lint {
-        name: "deprecated_cfg_attr",
-        group: "complexity",
-        desc: "usage of `cfg_attr(rustfmt)` instead of tool attributes",
-        deprecation: None,
-        module: "attrs",
-    },
-    Lint {
-        name: "deprecated_semver",
-        group: "correctness",
-        desc: "use of `#[deprecated(since = \"x\")]` where x is not semver",
-        deprecation: None,
-        module: "attrs",
-    },
-    Lint {
-        name: "deref_addrof",
-        group: "complexity",
-        desc: "use of `*&` or `*&mut` in an expression",
-        deprecation: None,
-        module: "reference",
-    },
-    Lint {
-        name: "derive_hash_xor_eq",
-        group: "correctness",
-        desc: "deriving `Hash` but implementing `PartialEq` explicitly",
-        deprecation: None,
-        module: "derive",
-    },
-    Lint {
-        name: "derive_ord_xor_partial_ord",
-        group: "correctness",
-        desc: "deriving `Ord` but implementing `PartialOrd` explicitly",
-        deprecation: None,
-        module: "derive",
-    },
-    Lint {
-        name: "disallowed_method",
-        group: "nursery",
-        desc: "use of a disallowed method call",
-        deprecation: None,
-        module: "disallowed_method",
-    },
-    Lint {
-        name: "diverging_sub_expression",
-        group: "complexity",
-        desc: "whether an expression contains a diverging sub expression",
-        deprecation: None,
-        module: "eval_order_dependence",
-    },
-    Lint {
-        name: "doc_markdown",
-        group: "pedantic",
-        desc: "presence of `_`, `::` or camel-case outside backticks in documentation",
-        deprecation: None,
-        module: "doc",
-    },
-    Lint {
-        name: "double_comparisons",
-        group: "complexity",
-        desc: "unnecessary double comparisons that can be simplified",
-        deprecation: None,
-        module: "double_comparison",
-    },
-    Lint {
-        name: "double_must_use",
-        group: "style",
-        desc: "`#[must_use]` attribute on a `#[must_use]`-returning function / method",
-        deprecation: None,
-        module: "functions",
-    },
-    Lint {
-        name: "double_neg",
-        group: "style",
-        desc: "`--x`, which is a double negation of `x` and not a pre-decrement as in C/C++",
-        deprecation: None,
-        module: "misc_early",
-    },
-    Lint {
-        name: "double_parens",
-        group: "complexity",
-        desc: "Warn on unnecessary double parentheses",
-        deprecation: None,
-        module: "double_parens",
-    },
-    Lint {
-        name: "drop_copy",
-        group: "correctness",
-        desc: "calls to `std::mem::drop` with a value that implements Copy",
-        deprecation: None,
-        module: "drop_forget_ref",
-    },
-    Lint {
-        name: "drop_ref",
-        group: "correctness",
-        desc: "calls to `std::mem::drop` with a reference instead of an owned value",
-        deprecation: None,
-        module: "drop_forget_ref",
-    },
-    Lint {
-        name: "duplicate_underscore_argument",
-        group: "style",
-        desc: "function arguments having names which only differ by an underscore",
-        deprecation: None,
-        module: "misc_early",
-    },
-    Lint {
-        name: "duration_subsec",
-        group: "complexity",
-        desc: "checks for calculation of subsecond microseconds or milliseconds",
-        deprecation: None,
-        module: "duration_subsec",
-    },
-    Lint {
-        name: "else_if_without_else",
-        group: "restriction",
-        desc: "`if` expression with an `else if`, but without a final `else` branch",
-        deprecation: None,
-        module: "else_if_without_else",
-    },
-    Lint {
-        name: "empty_enum",
-        group: "pedantic",
-        desc: "enum with no variants",
-        deprecation: None,
-        module: "empty_enum",
-    },
-    Lint {
-        name: "empty_line_after_outer_attr",
-        group: "nursery",
-        desc: "empty line after outer attribute",
-        deprecation: None,
-        module: "attrs",
-    },
-    Lint {
-        name: "empty_loop",
-        group: "style",
-        desc: "empty `loop {}`, which should block or sleep",
-        deprecation: None,
-        module: "loops",
-    },
-    Lint {
-        name: "enum_clike_unportable_variant",
-        group: "correctness",
-        desc: "C-like enums that are `repr(isize/usize)` and have values that don\'t fit into an `i32`",
-        deprecation: None,
-        module: "enum_clike",
-    },
-    Lint {
-        name: "enum_glob_use",
-        group: "pedantic",
-        desc: "use items that import all variants of an enum",
-        deprecation: None,
-        module: "wildcard_imports",
-    },
-    Lint {
-        name: "enum_variant_names",
-        group: "style",
-        desc: "enums where all variants share a prefix/postfix",
-        deprecation: None,
-        module: "enum_variants",
-    },
-    Lint {
-        name: "eq_op",
-        group: "correctness",
-        desc: "equal operands on both sides of a comparison or bitwise combination (e.g., `x == x`)",
-        deprecation: None,
-        module: "eq_op",
-    },
-    Lint {
-        name: "erasing_op",
-        group: "correctness",
-        desc: "using erasing operations, e.g., `x * 0` or `y & 0`",
-        deprecation: None,
-        module: "erasing_op",
-    },
-    Lint {
-        name: "eval_order_dependence",
-        group: "complexity",
-        desc: "whether a variable read occurs before a write depends on sub-expression evaluation order",
-        deprecation: None,
-        module: "eval_order_dependence",
-    },
-    Lint {
-        name: "excessive_precision",
-        group: "style",
-        desc: "excessive precision for float literal",
-        deprecation: None,
-        module: "float_literal",
-    },
-    Lint {
-        name: "exit",
-        group: "restriction",
-        desc: "`std::process::exit` is called, terminating the program",
-        deprecation: None,
-        module: "exit",
-    },
-    Lint {
-        name: "expect_fun_call",
-        group: "perf",
-        desc: "using any `expect` method with a function call",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "expect_used",
-        group: "restriction",
-        desc: "using `.expect()` on `Result` or `Option`, which might be better handled",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "expl_impl_clone_on_copy",
-        group: "pedantic",
-        desc: "implementing `Clone` explicitly on `Copy` types",
-        deprecation: None,
-        module: "derive",
-    },
-    Lint {
-        name: "explicit_counter_loop",
-        group: "complexity",
-        desc: "for-looping with an explicit counter when `_.enumerate()` would do",
-        deprecation: None,
-        module: "loops",
-    },
-    Lint {
-        name: "explicit_deref_methods",
-        group: "pedantic",
-        desc: "Explicit use of deref or deref_mut method while not in a method chain.",
-        deprecation: None,
-        module: "dereference",
-    },
-    Lint {
-        name: "explicit_into_iter_loop",
-        group: "pedantic",
-        desc: "for-looping over `_.into_iter()` when `_` would do",
-        deprecation: None,
-        module: "loops",
-    },
-    Lint {
-        name: "explicit_iter_loop",
-        group: "pedantic",
-        desc: "for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do",
-        deprecation: None,
-        module: "loops",
-    },
-    Lint {
-        name: "explicit_write",
-        group: "complexity",
-        desc: "using the `write!()` family of functions instead of the `print!()` family of functions, when using the latter would work",
-        deprecation: None,
-        module: "explicit_write",
-    },
-    Lint {
-        name: "extra_unused_lifetimes",
-        group: "complexity",
-        desc: "unused lifetimes in function definitions",
-        deprecation: None,
-        module: "lifetimes",
-    },
-    Lint {
-        name: "fallible_impl_from",
-        group: "nursery",
-        desc: "Warn on impls of `From<..>` that contain `panic!()` or `unwrap()`",
-        deprecation: None,
-        module: "fallible_impl_from",
-    },
-    Lint {
-        name: "field_reassign_with_default",
-        group: "style",
-        desc: "binding initialized with Default should have its fields set in the initializer",
-        deprecation: None,
-        module: "default",
-    },
-    Lint {
-        name: "filetype_is_file",
-        group: "restriction",
-        desc: "`FileType::is_file` is not recommended to test for readable file type",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "filter_map",
-        group: "pedantic",
-        desc: "using combinations of `filter`, `map`, `filter_map` and `flat_map` which can usually be written as a single method call",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "filter_map_next",
-        group: "pedantic",
-        desc: "using combination of `filter_map` and `next` which can usually be written as a single method call",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "filter_next",
-        group: "complexity",
-        desc: "using `filter(p).next()`, which is more succinctly expressed as `.find(p)`",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "find_map",
-        group: "pedantic",
-        desc: "using a combination of `find` and `map` can usually be written as a single method call",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "flat_map_identity",
-        group: "complexity",
-        desc: "call to `flat_map` where `flatten` is sufficient",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "float_arithmetic",
-        group: "restriction",
-        desc: "any floating-point arithmetic statement",
-        deprecation: None,
-        module: "arithmetic",
-    },
-    Lint {
-        name: "float_cmp",
-        group: "correctness",
-        desc: "using `==` or `!=` on float values instead of comparing difference with an epsilon",
-        deprecation: None,
-        module: "misc",
-    },
-    Lint {
-        name: "float_cmp_const",
-        group: "restriction",
-        desc: "using `==` or `!=` on float constants instead of comparing difference with an epsilon",
-        deprecation: None,
-        module: "misc",
-    },
-    Lint {
-        name: "float_equality_without_abs",
-        group: "correctness",
-        desc: "float equality check without `.abs()`",
-        deprecation: None,
-        module: "float_equality_without_abs",
-    },
-    Lint {
-        name: "fn_address_comparisons",
-        group: "correctness",
-        desc: "comparison with an address of a function item",
-        deprecation: None,
-        module: "unnamed_address",
-    },
-    Lint {
-        name: "fn_params_excessive_bools",
-        group: "pedantic",
-        desc: "using too many bools in function parameters",
-        deprecation: None,
-        module: "excessive_bools",
-    },
-    Lint {
-        name: "fn_to_numeric_cast",
-        group: "style",
-        desc: "casting a function pointer to a numeric type other than usize",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "fn_to_numeric_cast_with_truncation",
-        group: "style",
-        desc: "casting a function pointer to a numeric type not wide enough to store the address",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "for_kv_map",
-        group: "style",
-        desc: "looping on a map using `iter` when `keys` or `values` would do",
-        deprecation: None,
-        module: "loops",
-    },
-    Lint {
-        name: "for_loops_over_fallibles",
-        group: "correctness",
-        desc: "for-looping over an `Option` or a `Result`, which is more clearly expressed as an `if let`",
-        deprecation: None,
-        module: "loops",
-    },
-    Lint {
-        name: "forget_copy",
-        group: "correctness",
-        desc: "calls to `std::mem::forget` with a value that implements Copy",
-        deprecation: None,
-        module: "drop_forget_ref",
-    },
-    Lint {
-        name: "forget_ref",
-        group: "correctness",
-        desc: "calls to `std::mem::forget` with a reference instead of an owned value",
-        deprecation: None,
-        module: "drop_forget_ref",
-    },
-    Lint {
-        name: "from_iter_instead_of_collect",
-        group: "style",
-        desc: "use `.collect()` instead of `::from_iter()`",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "future_not_send",
-        group: "nursery",
-        desc: "public Futures must be Send",
-        deprecation: None,
-        module: "future_not_send",
-    },
-    Lint {
-        name: "get_last_with_len",
-        group: "complexity",
-        desc: "Using `x.get(x.len() - 1)` when `x.last()` is correct and simpler",
-        deprecation: None,
-        module: "get_last_with_len",
-    },
-    Lint {
-        name: "get_unwrap",
-        group: "restriction",
-        desc: "using `.get().unwrap()` or `.get_mut().unwrap()` when using `[]` would work instead",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "identity_op",
-        group: "complexity",
-        desc: "using identity operations, e.g., `x + 0` or `y / 1`",
-        deprecation: None,
-        module: "identity_op",
-    },
-    Lint {
-        name: "if_let_mutex",
-        group: "correctness",
-        desc: "locking a `Mutex` in an `if let` block can cause deadlocks",
-        deprecation: None,
-        module: "if_let_mutex",
-    },
-    Lint {
-        name: "if_let_some_result",
-        group: "style",
-        desc: "usage of `ok()` in `if let Some(pat)` statements is unnecessary, match on `Ok(pat)` instead",
-        deprecation: None,
-        module: "if_let_some_result",
-    },
-    Lint {
-        name: "if_not_else",
-        group: "pedantic",
-        desc: "`if` branches that could be swapped so no negation operation is necessary on the condition",
-        deprecation: None,
-        module: "if_not_else",
-    },
-    Lint {
-        name: "if_same_then_else",
-        group: "correctness",
-        desc: "`if` with the same `then` and `else` blocks",
-        deprecation: None,
-        module: "copies",
-    },
-    Lint {
-        name: "ifs_same_cond",
-        group: "correctness",
-        desc: "consecutive `if`s with the same condition",
-        deprecation: None,
-        module: "copies",
-    },
-    Lint {
-        name: "implicit_hasher",
-        group: "pedantic",
-        desc: "missing generalization over different hashers",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "implicit_return",
-        group: "restriction",
-        desc: "use a return statement like `return expr` instead of an expression",
-        deprecation: None,
-        module: "implicit_return",
-    },
-    Lint {
-        name: "implicit_saturating_sub",
-        group: "pedantic",
-        desc: "Perform saturating subtraction instead of implicitly checking lower bound of data type",
-        deprecation: None,
-        module: "implicit_saturating_sub",
-    },
-    Lint {
-        name: "imprecise_flops",
-        group: "nursery",
-        desc: "usage of imprecise floating point operations",
-        deprecation: None,
-        module: "floating_point_arithmetic",
-    },
-    Lint {
-        name: "inconsistent_digit_grouping",
-        group: "style",
-        desc: "integer literals with digits grouped inconsistently",
-        deprecation: None,
-        module: "literal_representation",
-    },
-    Lint {
-        name: "indexing_slicing",
-        group: "restriction",
-        desc: "indexing/slicing usage",
-        deprecation: None,
-        module: "indexing_slicing",
-    },
-    Lint {
-        name: "ineffective_bit_mask",
-        group: "correctness",
-        desc: "expressions where a bit mask will be rendered useless by a comparison, e.g., `(x | 1) > 2`",
-        deprecation: None,
-        module: "bit_mask",
-    },
-    Lint {
-        name: "inefficient_to_string",
-        group: "pedantic",
-        desc: "using `to_string` on `&&T` where `T: ToString`",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "infallible_destructuring_match",
-        group: "style",
-        desc: "a `match` statement with a single infallible arm instead of a `let`",
-        deprecation: None,
-        module: "matches",
-    },
-    Lint {
-        name: "infinite_iter",
-        group: "correctness",
-        desc: "infinite iteration",
-        deprecation: None,
-        module: "infinite_iter",
-    },
-    Lint {
-        name: "inherent_to_string",
-        group: "style",
-        desc: "type implements inherent method `to_string()`, but should instead implement the `Display` trait",
-        deprecation: None,
-        module: "inherent_to_string",
-    },
-    Lint {
-        name: "inherent_to_string_shadow_display",
-        group: "correctness",
-        desc: "type implements inherent method `to_string()`, which gets shadowed by the implementation of the `Display` trait",
-        deprecation: None,
-        module: "inherent_to_string",
-    },
-    Lint {
-        name: "inline_always",
-        group: "pedantic",
-        desc: "use of `#[inline(always)]`",
-        deprecation: None,
-        module: "attrs",
-    },
-    Lint {
-        name: "inline_asm_x86_att_syntax",
-        group: "restriction",
-        desc: "prefer Intel x86 assembly syntax",
-        deprecation: None,
-        module: "asm_syntax",
-    },
-    Lint {
-        name: "inline_asm_x86_intel_syntax",
-        group: "restriction",
-        desc: "prefer AT&T x86 assembly syntax",
-        deprecation: None,
-        module: "asm_syntax",
-    },
-    Lint {
-        name: "inline_fn_without_body",
-        group: "correctness",
-        desc: "use of `#[inline]` on trait methods without bodies",
-        deprecation: None,
-        module: "inline_fn_without_body",
-    },
-    Lint {
-        name: "int_plus_one",
-        group: "complexity",
-        desc: "instead of using `x >= y + 1`, use `x > y`",
-        deprecation: None,
-        module: "int_plus_one",
-    },
-    Lint {
-        name: "integer_arithmetic",
-        group: "restriction",
-        desc: "any integer arithmetic expression which could overflow or panic",
-        deprecation: None,
-        module: "arithmetic",
-    },
-    Lint {
-        name: "integer_division",
-        group: "restriction",
-        desc: "integer division may cause loss of precision",
-        deprecation: None,
-        module: "integer_division",
-    },
-    Lint {
-        name: "into_iter_on_ref",
-        group: "style",
-        desc: "using `.into_iter()` on a reference",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "invalid_atomic_ordering",
-        group: "correctness",
-        desc: "usage of invalid atomic ordering in atomic operations and memory fences",
-        deprecation: None,
-        module: "atomic_ordering",
-    },
-    Lint {
-        name: "invalid_regex",
-        group: "correctness",
-        desc: "invalid regular expressions",
-        deprecation: None,
-        module: "regex",
-    },
-    Lint {
-        name: "invalid_upcast_comparisons",
-        group: "pedantic",
-        desc: "a comparison involving an upcast which is always true or false",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "invisible_characters",
-        group: "correctness",
-        desc: "using an invisible character in a string literal, which is confusing",
-        deprecation: None,
-        module: "unicode",
-    },
-    Lint {
-        name: "items_after_statements",
-        group: "pedantic",
-        desc: "blocks where an item comes after a statement",
-        deprecation: None,
-        module: "items_after_statements",
-    },
-    Lint {
-        name: "iter_cloned_collect",
-        group: "style",
-        desc: "using `.cloned().collect()` on slice to create a `Vec`",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "iter_next_loop",
-        group: "correctness",
-        desc: "for-looping over `_.next()` which is probably not intended",
-        deprecation: None,
-        module: "loops",
-    },
-    Lint {
-        name: "iter_next_slice",
-        group: "style",
-        desc: "using `.iter().next()` on a sliced array, which can be shortened to just `.get()`",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "iter_nth",
-        group: "perf",
-        desc: "using `.iter().nth()` on a standard library type with O(1) element access",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "iter_nth_zero",
-        group: "style",
-        desc: "replace `iter.nth(0)` with `iter.next()`",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "iter_skip_next",
-        group: "style",
-        desc: "using `.skip(x).next()` on an iterator",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "iterator_step_by_zero",
-        group: "correctness",
-        desc: "using `Iterator::step_by(0)`, which will panic at runtime",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "just_underscores_and_digits",
-        group: "style",
-        desc: "unclear name",
-        deprecation: None,
-        module: "non_expressive_names",
-    },
-    Lint {
-        name: "large_const_arrays",
-        group: "perf",
-        desc: "large non-scalar const array may cause performance overhead",
-        deprecation: None,
-        module: "large_const_arrays",
-    },
-    Lint {
-        name: "large_digit_groups",
-        group: "pedantic",
-        desc: "grouping digits into groups that are too large",
-        deprecation: None,
-        module: "literal_representation",
-    },
-    Lint {
-        name: "large_enum_variant",
-        group: "perf",
-        desc: "large size difference between variants on an enum",
-        deprecation: None,
-        module: "large_enum_variant",
-    },
-    Lint {
-        name: "large_stack_arrays",
-        group: "pedantic",
-        desc: "allocating large arrays on stack may cause stack overflow",
-        deprecation: None,
-        module: "large_stack_arrays",
-    },
-    Lint {
-        name: "large_types_passed_by_value",
-        group: "pedantic",
-        desc: "functions taking large arguments by value",
-        deprecation: None,
-        module: "pass_by_ref_or_value",
-    },
-    Lint {
-        name: "len_without_is_empty",
-        group: "style",
-        desc: "traits or impls with a public `len` method but no corresponding `is_empty` method",
-        deprecation: None,
-        module: "len_zero",
-    },
-    Lint {
-        name: "len_zero",
-        group: "style",
-        desc: "checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead",
-        deprecation: None,
-        module: "len_zero",
-    },
-    Lint {
-        name: "let_and_return",
-        group: "style",
-        desc: "creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block",
-        deprecation: None,
-        module: "returns",
-    },
-    Lint {
-        name: "let_underscore_lock",
-        group: "correctness",
-        desc: "non-binding let on a synchronization lock",
-        deprecation: None,
-        module: "let_underscore",
-    },
-    Lint {
-        name: "let_underscore_must_use",
-        group: "restriction",
-        desc: "non-binding let on a `#[must_use]` expression",
-        deprecation: None,
-        module: "let_underscore",
-    },
-    Lint {
-        name: "let_unit_value",
-        group: "pedantic",
-        desc: "creating a `let` binding to a value of unit type, which usually can\'t be used afterwards",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "linkedlist",
-        group: "pedantic",
-        desc: "usage of LinkedList, usually a vector is faster, or a more specialized data structure like a `VecDeque`",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "logic_bug",
-        group: "correctness",
-        desc: "boolean expressions that contain terminals which can be eliminated",
-        deprecation: None,
-        module: "booleans",
-    },
-    Lint {
-        name: "lossy_float_literal",
-        group: "restriction",
-        desc: "lossy whole number float literals",
-        deprecation: None,
-        module: "float_literal",
-    },
-    Lint {
-        name: "macro_use_imports",
-        group: "pedantic",
-        desc: "#[macro_use] is no longer needed",
-        deprecation: None,
-        module: "macro_use",
-    },
-    Lint {
-        name: "main_recursion",
-        group: "style",
-        desc: "recursion using the entrypoint",
-        deprecation: None,
-        module: "main_recursion",
-    },
-    Lint {
-        name: "manual_async_fn",
-        group: "style",
-        desc: "manual implementations of `async` functions can be simplified using the dedicated syntax",
-        deprecation: None,
-        module: "manual_async_fn",
-    },
-    Lint {
-        name: "manual_memcpy",
-        group: "perf",
-        desc: "manually copying items between slices",
-        deprecation: None,
-        module: "loops",
-    },
-    Lint {
-        name: "manual_non_exhaustive",
-        group: "style",
-        desc: "manual implementations of the non-exhaustive pattern can be simplified using #[non_exhaustive]",
-        deprecation: None,
-        module: "manual_non_exhaustive",
-    },
-    Lint {
-        name: "manual_ok_or",
-        group: "pedantic",
-        desc: "finds patterns that can be encoded more concisely with `Option::ok_or`",
-        deprecation: None,
-        module: "manual_ok_or",
-    },
-    Lint {
-        name: "manual_range_contains",
-        group: "style",
-        desc: "manually reimplementing {`Range`, `RangeInclusive`}`::contains`",
-        deprecation: None,
-        module: "ranges",
-    },
-    Lint {
-        name: "manual_saturating_arithmetic",
-        group: "style",
-        desc: "`.chcked_add/sub(x).unwrap_or(MAX/MIN)`",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "manual_strip",
-        group: "complexity",
-        desc: "suggests using `strip_{prefix,suffix}` over `str::{starts,ends}_with` and slicing",
-        deprecation: None,
-        module: "manual_strip",
-    },
-    Lint {
-        name: "manual_swap",
-        group: "complexity",
-        desc: "manual swap of two variables",
-        deprecation: None,
-        module: "swap",
-    },
-    Lint {
-        name: "manual_unwrap_or",
-        group: "complexity",
-        desc: "finds patterns that can be encoded more concisely with `Option::unwrap_or` or `Result::unwrap_or`",
-        deprecation: None,
-        module: "manual_unwrap_or",
-    },
-    Lint {
-        name: "many_single_char_names",
-        group: "style",
-        desc: "too many single character bindings",
-        deprecation: None,
-        module: "non_expressive_names",
-    },
-    Lint {
-        name: "map_clone",
-        group: "style",
-        desc: "using `iterator.map(|x| x.clone())`, or dereferencing closures for `Copy` types",
-        deprecation: None,
-        module: "map_clone",
-    },
-    Lint {
-        name: "map_collect_result_unit",
-        group: "style",
-        desc: "using `.map(_).collect::<Result<(),_>()`, which can be replaced with `try_for_each`",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "map_entry",
-        group: "perf",
-        desc: "use of `contains_key` followed by `insert` on a `HashMap` or `BTreeMap`",
-        deprecation: None,
-        module: "entry",
-    },
-    Lint {
-        name: "map_err_ignore",
-        group: "pedantic",
-        desc: "`map_err` should not ignore the original error",
-        deprecation: None,
-        module: "map_err_ignore",
-    },
-    Lint {
-        name: "map_flatten",
-        group: "pedantic",
-        desc: "using combinations of `flatten` and `map` which can usually be written as a single method call",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "map_identity",
-        group: "complexity",
-        desc: "using iterator.map(|x| x)",
-        deprecation: None,
-        module: "map_identity",
-    },
-    Lint {
-        name: "map_unwrap_or",
-        group: "pedantic",
-        desc: "using `.map(f).unwrap_or(a)` or `.map(f).unwrap_or_else(func)`, which are more succinctly expressed as `map_or(a, f)` or `map_or_else(a, f)`",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "match_as_ref",
-        group: "complexity",
-        desc: "a `match` on an Option value instead of using `as_ref()` or `as_mut`",
-        deprecation: None,
-        module: "matches",
-    },
-    Lint {
-        name: "match_bool",
-        group: "pedantic",
-        desc: "a `match` on a boolean expression instead of an `if..else` block",
-        deprecation: None,
-        module: "matches",
-    },
-    Lint {
-        name: "match_like_matches_macro",
-        group: "style",
-        desc: "a match that could be written with the matches! macro",
-        deprecation: None,
-        module: "matches",
-    },
-    Lint {
-        name: "match_on_vec_items",
-        group: "pedantic",
-        desc: "matching on vector elements can panic",
-        deprecation: None,
-        module: "match_on_vec_items",
-    },
-    Lint {
-        name: "match_overlapping_arm",
-        group: "style",
-        desc: "a `match` with overlapping arms",
-        deprecation: None,
-        module: "matches",
-    },
-    Lint {
-        name: "match_ref_pats",
-        group: "style",
-        desc: "a `match` or `if let` with all arms prefixed with `&` instead of deref-ing the match expression",
-        deprecation: None,
-        module: "matches",
-    },
-    Lint {
-        name: "match_same_arms",
-        group: "pedantic",
-        desc: "`match` with identical arm bodies",
-        deprecation: None,
-        module: "matches",
-    },
-    Lint {
-        name: "match_single_binding",
-        group: "complexity",
-        desc: "a match with a single binding instead of using `let` statement",
-        deprecation: None,
-        module: "matches",
-    },
-    Lint {
-        name: "match_wild_err_arm",
-        group: "pedantic",
-        desc: "a `match` with `Err(_)` arm and take drastic actions",
-        deprecation: None,
-        module: "matches",
-    },
-    Lint {
-        name: "match_wildcard_for_single_variants",
-        group: "pedantic",
-        desc: "a wildcard enum match for a single variant",
-        deprecation: None,
-        module: "matches",
-    },
-    Lint {
-        name: "maybe_infinite_iter",
-        group: "pedantic",
-        desc: "possible infinite iteration",
-        deprecation: None,
-        module: "infinite_iter",
-    },
-    Lint {
-        name: "mem_discriminant_non_enum",
-        group: "correctness",
-        desc: "calling `mem::descriminant` on non-enum type",
-        deprecation: None,
-        module: "mem_discriminant",
-    },
-    Lint {
-        name: "mem_forget",
-        group: "restriction",
-        desc: "`mem::forget` usage on `Drop` types, likely to cause memory leaks",
-        deprecation: None,
-        module: "mem_forget",
-    },
-    Lint {
-        name: "mem_replace_option_with_none",
-        group: "style",
-        desc: "replacing an `Option` with `None` instead of `take()`",
-        deprecation: None,
-        module: "mem_replace",
-    },
-    Lint {
-        name: "mem_replace_with_default",
-        group: "style",
-        desc: "replacing a value of type `T` with `T::default()` instead of using `std::mem::take`",
-        deprecation: None,
-        module: "mem_replace",
-    },
-    Lint {
-        name: "mem_replace_with_uninit",
-        group: "correctness",
-        desc: "`mem::replace(&mut _, mem::uninitialized())` or `mem::replace(&mut _, mem::zeroed())`",
-        deprecation: None,
-        module: "mem_replace",
-    },
-    Lint {
-        name: "min_max",
-        group: "correctness",
-        desc: "`min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant",
-        deprecation: None,
-        module: "minmax",
-    },
-    Lint {
-        name: "mismatched_target_os",
-        group: "correctness",
-        desc: "usage of `cfg(operating_system)` instead of `cfg(target_os = \"operating_system\")`",
-        deprecation: None,
-        module: "attrs",
-    },
-    Lint {
-        name: "misrefactored_assign_op",
-        group: "complexity",
-        desc: "having a variable on both sides of an assign op",
-        deprecation: None,
-        module: "assign_ops",
-    },
-    Lint {
-        name: "missing_const_for_fn",
-        group: "nursery",
-        desc: "Lint functions definitions that could be made `const fn`",
-        deprecation: None,
-        module: "missing_const_for_fn",
-    },
-    Lint {
-        name: "missing_docs_in_private_items",
-        group: "restriction",
-        desc: "detects missing documentation for public and private members",
-        deprecation: None,
-        module: "missing_doc",
-    },
-    Lint {
-        name: "missing_errors_doc",
-        group: "pedantic",
-        desc: "`pub fn` returns `Result` without `# Errors` in doc comment",
-        deprecation: None,
-        module: "doc",
-    },
-    Lint {
-        name: "missing_inline_in_public_items",
-        group: "restriction",
-        desc: "detects missing `#[inline]` attribute for public callables (functions, trait methods, methods...)",
-        deprecation: None,
-        module: "missing_inline",
-    },
-    Lint {
-        name: "missing_safety_doc",
-        group: "style",
-        desc: "`pub unsafe fn` without `# Safety` docs",
-        deprecation: None,
-        module: "doc",
-    },
-    Lint {
-        name: "mistyped_literal_suffixes",
-        group: "correctness",
-        desc: "mistyped literal suffix",
-        deprecation: None,
-        module: "literal_representation",
-    },
-    Lint {
-        name: "mixed_case_hex_literals",
-        group: "style",
-        desc: "hex literals whose letter digits are not consistently upper- or lowercased",
-        deprecation: None,
-        module: "misc_early",
-    },
-    Lint {
-        name: "module_inception",
-        group: "style",
-        desc: "modules that have the same name as their parent module",
-        deprecation: None,
-        module: "enum_variants",
-    },
-    Lint {
-        name: "module_name_repetitions",
-        group: "pedantic",
-        desc: "type names prefixed/postfixed with their containing module\'s name",
-        deprecation: None,
-        module: "enum_variants",
-    },
-    Lint {
-        name: "modulo_arithmetic",
-        group: "restriction",
-        desc: "any modulo arithmetic statement",
-        deprecation: None,
-        module: "modulo_arithmetic",
-    },
-    Lint {
-        name: "modulo_one",
-        group: "correctness",
-        desc: "taking a number modulo 1, which always returns 0",
-        deprecation: None,
-        module: "misc",
-    },
-    Lint {
-        name: "multiple_crate_versions",
-        group: "cargo",
-        desc: "multiple versions of the same crate being used",
-        deprecation: None,
-        module: "multiple_crate_versions",
-    },
-    Lint {
-        name: "multiple_inherent_impl",
-        group: "restriction",
-        desc: "Multiple inherent impl that could be grouped",
-        deprecation: None,
-        module: "inherent_impl",
-    },
-    Lint {
-        name: "must_use_candidate",
-        group: "pedantic",
-        desc: "function or method that could take a `#[must_use]` attribute",
-        deprecation: None,
-        module: "functions",
-    },
-    Lint {
-        name: "must_use_unit",
-        group: "style",
-        desc: "`#[must_use]` attribute on a unit-returning function / method",
-        deprecation: None,
-        module: "functions",
-    },
-    Lint {
-        name: "mut_from_ref",
-        group: "correctness",
-        desc: "fns that create mutable refs from immutable ref args",
-        deprecation: None,
-        module: "ptr",
-    },
-    Lint {
-        name: "mut_mut",
-        group: "pedantic",
-        desc: "usage of double-mut refs, e.g., `&mut &mut ...`",
-        deprecation: None,
-        module: "mut_mut",
-    },
-    Lint {
-        name: "mut_mutex_lock",
-        group: "style",
-        desc: "`&mut Mutex::lock` does unnecessary locking",
-        deprecation: None,
-        module: "mut_mutex_lock",
-    },
-    Lint {
-        name: "mut_range_bound",
-        group: "complexity",
-        desc: "for loop over a range where one of the bounds is a mutable variable",
-        deprecation: None,
-        module: "loops",
-    },
-    Lint {
-        name: "mutable_key_type",
-        group: "correctness",
-        desc: "Check for mutable `Map`/`Set` key type",
-        deprecation: None,
-        module: "mut_key",
-    },
-    Lint {
-        name: "mutex_atomic",
-        group: "perf",
-        desc: "using a mutex where an atomic value could be used instead",
-        deprecation: None,
-        module: "mutex_atomic",
-    },
-    Lint {
-        name: "mutex_integer",
-        group: "nursery",
-        desc: "using a mutex for an integer type",
-        deprecation: None,
-        module: "mutex_atomic",
-    },
-    Lint {
-        name: "naive_bytecount",
-        group: "perf",
-        desc: "use of naive `<slice>.filter(|&x| x == y).count()` to count byte values",
-        deprecation: None,
-        module: "bytecount",
-    },
-    Lint {
-        name: "needless_arbitrary_self_type",
-        group: "complexity",
-        desc: "type of `self` parameter is already by default `Self`",
-        deprecation: None,
-        module: "needless_arbitrary_self_type",
-    },
-    Lint {
-        name: "needless_bool",
-        group: "complexity",
-        desc: "if-statements with plain booleans in the then- and else-clause, e.g., `if p { true } else { false }`",
-        deprecation: None,
-        module: "needless_bool",
-    },
-    Lint {
-        name: "needless_borrow",
-        group: "nursery",
-        desc: "taking a reference that is going to be automatically dereferenced",
-        deprecation: None,
-        module: "needless_borrow",
-    },
-    Lint {
-        name: "needless_borrowed_reference",
-        group: "complexity",
-        desc: "taking a needless borrowed reference",
-        deprecation: None,
-        module: "needless_borrowed_ref",
-    },
-    Lint {
-        name: "needless_collect",
-        group: "perf",
-        desc: "collecting an iterator when collect is not needed",
-        deprecation: None,
-        module: "loops",
-    },
-    Lint {
-        name: "needless_continue",
-        group: "pedantic",
-        desc: "`continue` statements that can be replaced by a rearrangement of code",
-        deprecation: None,
-        module: "needless_continue",
-    },
-    Lint {
-        name: "needless_doctest_main",
-        group: "style",
-        desc: "presence of `fn main() {` in code examples",
-        deprecation: None,
-        module: "doc",
-    },
-    Lint {
-        name: "needless_lifetimes",
-        group: "complexity",
-        desc: "using explicit lifetimes for references in function arguments when elision rules would allow omitting them",
-        deprecation: None,
-        module: "lifetimes",
-    },
-    Lint {
-        name: "needless_pass_by_value",
-        group: "pedantic",
-        desc: "functions taking arguments by value, but not consuming them in its body",
-        deprecation: None,
-        module: "needless_pass_by_value",
-    },
-    Lint {
-        name: "needless_range_loop",
-        group: "style",
-        desc: "for-looping over a range of indices where an iterator over items would do",
-        deprecation: None,
-        module: "loops",
-    },
-    Lint {
-        name: "needless_return",
-        group: "style",
-        desc: "using a return statement like `return expr;` where an expression would suffice",
-        deprecation: None,
-        module: "returns",
-    },
-    Lint {
-        name: "needless_update",
-        group: "complexity",
-        desc: "using `Foo { ..base }` when there are no missing fields",
-        deprecation: None,
-        module: "needless_update",
-    },
-    Lint {
-        name: "neg_cmp_op_on_partial_ord",
-        group: "complexity",
-        desc: "The use of negated comparison operators on partially ordered types may produce confusing code.",
-        deprecation: None,
-        module: "neg_cmp_op_on_partial_ord",
-    },
-    Lint {
-        name: "neg_multiply",
-        group: "style",
-        desc: "multiplying integers with `-1`",
-        deprecation: None,
-        module: "neg_multiply",
-    },
-    Lint {
-        name: "never_loop",
-        group: "correctness",
-        desc: "any loop that will always `break` or `return`",
-        deprecation: None,
-        module: "loops",
-    },
-    Lint {
-        name: "new_ret_no_self",
-        group: "style",
-        desc: "not returning type containing `Self` in a `new` method",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "new_without_default",
-        group: "style",
-        desc: "`fn new() -> Self` method without `Default` implementation",
-        deprecation: None,
-        module: "new_without_default",
-    },
-    Lint {
-        name: "no_effect",
-        group: "complexity",
-        desc: "statements with no effect",
-        deprecation: None,
-        module: "no_effect",
-    },
-    Lint {
-        name: "non_ascii_literal",
-        group: "pedantic",
-        desc: "using any literal non-ASCII chars in a string literal instead of using the `\\\\u` escape",
-        deprecation: None,
-        module: "unicode",
-    },
-    Lint {
-        name: "nonminimal_bool",
-        group: "complexity",
-        desc: "boolean expressions that can be written more concisely",
-        deprecation: None,
-        module: "booleans",
-    },
-    Lint {
-        name: "nonsensical_open_options",
-        group: "correctness",
-        desc: "nonsensical combination of options for opening a file",
-        deprecation: None,
-        module: "open_options",
-    },
-    Lint {
-        name: "not_unsafe_ptr_arg_deref",
-        group: "correctness",
-        desc: "public functions dereferencing raw pointer arguments but not marked `unsafe`",
-        deprecation: None,
-        module: "functions",
-    },
-    Lint {
-        name: "ok_expect",
-        group: "style",
-        desc: "using `ok().expect()`, which gives worse error messages than calling `expect` directly on the Result",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "op_ref",
-        group: "style",
-        desc: "taking a reference to satisfy the type constraints on `==`",
-        deprecation: None,
-        module: "eq_op",
-    },
-    Lint {
-        name: "option_as_ref_deref",
-        group: "complexity",
-        desc: "using `as_ref().map(Deref::deref)`, which is more succinctly expressed as `as_deref()`",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "option_env_unwrap",
-        group: "correctness",
-        desc: "using `option_env!(...).unwrap()` to get environment variable",
-        deprecation: None,
-        module: "option_env_unwrap",
-    },
-    Lint {
-        name: "option_if_let_else",
-        group: "pedantic",
-        desc: "reimplementation of Option::map_or",
-        deprecation: None,
-        module: "option_if_let_else",
-    },
-    Lint {
-        name: "option_map_or_none",
-        group: "style",
-        desc: "using `Option.map_or(None, f)`, which is more succinctly expressed as `and_then(f)`",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "option_map_unit_fn",
-        group: "complexity",
-        desc: "using `option.map(f)`, where `f` is a function or closure that returns `()`",
-        deprecation: None,
-        module: "map_unit_fn",
-    },
-    Lint {
-        name: "option_option",
-        group: "pedantic",
-        desc: "usage of `Option<Option<T>>`",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "or_fun_call",
-        group: "perf",
-        desc: "using any `*or` method with a function call, which suggests `*or_else`",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "out_of_bounds_indexing",
-        group: "correctness",
-        desc: "out of bounds constant indexing",
-        deprecation: None,
-        module: "indexing_slicing",
-    },
-    Lint {
-        name: "overflow_check_conditional",
-        group: "complexity",
-        desc: "overflow checks inspired by C which are likely to panic",
-        deprecation: None,
-        module: "overflow_check_conditional",
-    },
-    Lint {
-        name: "panic",
-        group: "restriction",
-        desc: "usage of the `panic!` macro",
-        deprecation: None,
-        module: "panic_unimplemented",
-    },
-    Lint {
-        name: "panic_in_result_fn",
-        group: "restriction",
-        desc: "functions of type `Result<..>` that contain `panic!()`, `todo!()` or `unreachable()` or `unimplemented()` ",
-        deprecation: None,
-        module: "panic_in_result_fn",
-    },
-    Lint {
-        name: "panic_params",
-        group: "style",
-        desc: "missing parameters in `panic!` calls",
-        deprecation: None,
-        module: "panic_unimplemented",
-    },
-    Lint {
-        name: "panicking_unwrap",
-        group: "correctness",
-        desc: "checks for calls of `unwrap[_err]()` that will always fail",
-        deprecation: None,
-        module: "unwrap",
-    },
-    Lint {
-        name: "partialeq_ne_impl",
-        group: "complexity",
-        desc: "re-implementing `PartialEq::ne`",
-        deprecation: None,
-        module: "partialeq_ne_impl",
-    },
-    Lint {
-        name: "path_buf_push_overwrite",
-        group: "nursery",
-        desc: "calling `push` with file system root on `PathBuf` can overwrite it",
-        deprecation: None,
-        module: "path_buf_push_overwrite",
-    },
-    Lint {
-        name: "pattern_type_mismatch",
-        group: "restriction",
-        desc: "type of pattern does not match the expression type",
-        deprecation: None,
-        module: "pattern_type_mismatch",
-    },
-    Lint {
-        name: "possible_missing_comma",
-        group: "correctness",
-        desc: "possible missing comma in array",
-        deprecation: None,
-        module: "formatting",
-    },
-    Lint {
-        name: "precedence",
-        group: "complexity",
-        desc: "operations where precedence may be unclear",
-        deprecation: None,
-        module: "precedence",
-    },
-    Lint {
-        name: "print_literal",
-        group: "style",
-        desc: "printing a literal with a format string",
-        deprecation: None,
-        module: "write",
-    },
-    Lint {
-        name: "print_stdout",
-        group: "restriction",
-        desc: "printing on stdout",
-        deprecation: None,
-        module: "write",
-    },
-    Lint {
-        name: "print_with_newline",
-        group: "style",
-        desc: "using `print!()` with a format string that ends in a single newline",
-        deprecation: None,
-        module: "write",
-    },
-    Lint {
-        name: "println_empty_string",
-        group: "style",
-        desc: "using `println!(\"\")` with an empty string",
-        deprecation: None,
-        module: "write",
-    },
-    Lint {
-        name: "ptr_arg",
-        group: "style",
-        desc: "fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively",
-        deprecation: None,
-        module: "ptr",
-    },
-    Lint {
-        name: "ptr_eq",
-        group: "style",
-        desc: "use `std::ptr::eq` when comparing raw pointers",
-        deprecation: None,
-        module: "ptr_eq",
-    },
-    Lint {
-        name: "ptr_offset_with_cast",
-        group: "complexity",
-        desc: "unneeded pointer offset cast",
-        deprecation: None,
-        module: "ptr_offset_with_cast",
-    },
-    Lint {
-        name: "pub_enum_variant_names",
-        group: "pedantic",
-        desc: "public enums where all variants share a prefix/postfix",
-        deprecation: None,
-        module: "enum_variants",
-    },
-    Lint {
-        name: "question_mark",
-        group: "style",
-        desc: "checks for expressions that could be replaced by the question mark operator",
-        deprecation: None,
-        module: "question_mark",
-    },
-    Lint {
-        name: "range_minus_one",
-        group: "pedantic",
-        desc: "`x..=(y-1)` reads better as `x..y`",
-        deprecation: None,
-        module: "ranges",
-    },
-    Lint {
-        name: "range_plus_one",
-        group: "pedantic",
-        desc: "`x..(y+1)` reads better as `x..=y`",
-        deprecation: None,
-        module: "ranges",
-    },
-    Lint {
-        name: "range_zip_with_len",
-        group: "complexity",
-        desc: "zipping iterator with a range when `enumerate()` would do",
-        deprecation: None,
-        module: "ranges",
-    },
-    Lint {
-        name: "rc_buffer",
-        group: "restriction",
-        desc: "shared ownership of a buffer type",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "redundant_allocation",
-        group: "perf",
-        desc: "redundant allocation",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "redundant_clone",
-        group: "perf",
-        desc: "`clone()` of an owned value that is going to be dropped immediately",
-        deprecation: None,
-        module: "redundant_clone",
-    },
-    Lint {
-        name: "redundant_closure",
-        group: "style",
-        desc: "redundant closures, i.e., `|a| foo(a)` (which can be written as just `foo`)",
-        deprecation: None,
-        module: "eta_reduction",
-    },
-    Lint {
-        name: "redundant_closure_call",
-        group: "complexity",
-        desc: "throwaway closures called in the expression they are defined",
-        deprecation: None,
-        module: "redundant_closure_call",
-    },
-    Lint {
-        name: "redundant_closure_for_method_calls",
-        group: "pedantic",
-        desc: "redundant closures for method calls",
-        deprecation: None,
-        module: "eta_reduction",
-    },
-    Lint {
-        name: "redundant_field_names",
-        group: "style",
-        desc: "checks for fields in struct literals where shorthands could be used",
-        deprecation: None,
-        module: "redundant_field_names",
-    },
-    Lint {
-        name: "redundant_pattern",
-        group: "style",
-        desc: "using `name @ _` in a pattern",
-        deprecation: None,
-        module: "misc_early",
-    },
-    Lint {
-        name: "redundant_pattern_matching",
-        group: "style",
-        desc: "use the proper utility function avoiding an `if let`",
-        deprecation: None,
-        module: "matches",
-    },
-    Lint {
-        name: "redundant_pub_crate",
-        group: "nursery",
-        desc: "Using `pub(crate)` visibility on items that are not crate visible due to the visibility of the module that contains them.",
-        deprecation: None,
-        module: "redundant_pub_crate",
-    },
-    Lint {
-        name: "redundant_static_lifetimes",
-        group: "style",
-        desc: "Using explicit `\'static` lifetime for constants or statics when elision rules would allow omitting them.",
-        deprecation: None,
-        module: "redundant_static_lifetimes",
-    },
-    Lint {
-        name: "ref_in_deref",
-        group: "complexity",
-        desc: "Use of reference in auto dereference expression.",
-        deprecation: None,
-        module: "reference",
-    },
-    Lint {
-        name: "ref_option_ref",
-        group: "pedantic",
-        desc: "use `Option<&T>` instead of `&Option<&T>`",
-        deprecation: None,
-        module: "ref_option_ref",
-    },
-    Lint {
-        name: "repeat_once",
-        group: "complexity",
-        desc: "using `.repeat(1)` instead of `String.clone()`, `str.to_string()` or `slice.to_vec()` ",
-        deprecation: None,
-        module: "repeat_once",
-    },
-    Lint {
-        name: "rest_pat_in_fully_bound_structs",
-        group: "restriction",
-        desc: "a match on a struct that binds all fields but still uses the wildcard pattern",
-        deprecation: None,
-        module: "matches",
-    },
-    Lint {
-        name: "result_map_or_into_option",
-        group: "style",
-        desc: "using `Result.map_or(None, Some)`, which is more succinctly expressed as `ok()`",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "result_map_unit_fn",
-        group: "complexity",
-        desc: "using `result.map(f)`, where `f` is a function or closure that returns `()`",
-        deprecation: None,
-        module: "map_unit_fn",
-    },
-    Lint {
-        name: "result_unit_err",
-        group: "style",
-        desc: "public function returning `Result` with an `Err` type of `()`",
-        deprecation: None,
-        module: "functions",
-    },
-    Lint {
-        name: "reversed_empty_ranges",
-        group: "correctness",
-        desc: "reversing the limits of range expressions, resulting in empty ranges",
-        deprecation: None,
-        module: "ranges",
-    },
-    Lint {
-        name: "same_functions_in_if_condition",
-        group: "pedantic",
-        desc: "consecutive `if`s with the same function call",
-        deprecation: None,
-        module: "copies",
-    },
-    Lint {
-        name: "same_item_push",
-        group: "style",
-        desc: "the same item is pushed inside of a for loop",
-        deprecation: None,
-        module: "loops",
-    },
-    Lint {
-        name: "search_is_some",
-        group: "complexity",
-        desc: "using an iterator search followed by `is_some()`, which is more succinctly expressed as a call to `any()`",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "self_assignment",
-        group: "correctness",
-        desc: "explicit self-assignment",
-        deprecation: None,
-        module: "self_assignment",
-    },
-    Lint {
-        name: "serde_api_misuse",
-        group: "correctness",
-        desc: "various things that will negatively affect your serde experience",
-        deprecation: None,
-        module: "serde_api",
-    },
-    Lint {
-        name: "shadow_reuse",
-        group: "restriction",
-        desc: "rebinding a name to an expression that re-uses the original value, e.g., `let x = x + 1`",
-        deprecation: None,
-        module: "shadow",
-    },
-    Lint {
-        name: "shadow_same",
-        group: "restriction",
-        desc: "rebinding a name to itself, e.g., `let mut x = &mut x`",
-        deprecation: None,
-        module: "shadow",
-    },
-    Lint {
-        name: "shadow_unrelated",
-        group: "pedantic",
-        desc: "rebinding a name without even using the original value",
-        deprecation: None,
-        module: "shadow",
-    },
-    Lint {
-        name: "short_circuit_statement",
-        group: "complexity",
-        desc: "using a short circuit boolean condition as a statement",
-        deprecation: None,
-        module: "misc",
-    },
-    Lint {
-        name: "should_implement_trait",
-        group: "style",
-        desc: "defining a method that should be implementing a std trait",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "similar_names",
-        group: "pedantic",
-        desc: "similarly named items and bindings",
-        deprecation: None,
-        module: "non_expressive_names",
-    },
-    Lint {
-        name: "single_char_add_str",
-        group: "style",
-        desc: "`push_str()` or `insert_str()` used with a single-character string literal as parameter",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "single_char_pattern",
-        group: "perf",
-        desc: "using a single-character str where a char could be used, e.g., `_.split(\"x\")`",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "single_component_path_imports",
-        group: "style",
-        desc: "imports with single component path are redundant",
-        deprecation: None,
-        module: "single_component_path_imports",
-    },
-    Lint {
-        name: "single_element_loop",
-        group: "complexity",
-        desc: "there is no reason to have a single element loop",
-        deprecation: None,
-        module: "loops",
-    },
-    Lint {
-        name: "single_match",
-        group: "style",
-        desc: "a `match` statement with a single nontrivial arm (i.e., where the other arm is `_ => {}`) instead of `if let`",
-        deprecation: None,
-        module: "matches",
-    },
-    Lint {
-        name: "single_match_else",
-        group: "pedantic",
-        desc: "a `match` statement with two arms where the second arm\'s pattern is a placeholder instead of a specific match pattern",
-        deprecation: None,
-        module: "matches",
-    },
-    Lint {
-        name: "skip_while_next",
-        group: "complexity",
-        desc: "using `skip_while(p).next()`, which is more succinctly expressed as `.find(!p)`",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "slow_vector_initialization",
-        group: "perf",
-        desc: "slow vector initialization",
-        deprecation: None,
-        module: "slow_vector_initialization",
-    },
-    Lint {
-        name: "stable_sort_primitive",
-        group: "perf",
-        desc: "use of sort() when sort_unstable() is equivalent",
-        deprecation: None,
-        module: "stable_sort_primitive",
-    },
-    Lint {
-        name: "string_add",
-        group: "restriction",
-        desc: "using `x + ..` where x is a `String` instead of `push_str()`",
-        deprecation: None,
-        module: "strings",
-    },
-    Lint {
-        name: "string_add_assign",
-        group: "pedantic",
-        desc: "using `x = x + ..` where x is a `String` instead of `push_str()`",
-        deprecation: None,
-        module: "strings",
-    },
-    Lint {
-        name: "string_extend_chars",
-        group: "style",
-        desc: "using `x.extend(s.chars())` where s is a `&str` or `String`",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "string_lit_as_bytes",
-        group: "nursery",
-        desc: "calling `as_bytes` on a string literal instead of using a byte string literal",
-        deprecation: None,
-        module: "strings",
-    },
-    Lint {
-        name: "struct_excessive_bools",
-        group: "pedantic",
-        desc: "using too many bools in a struct",
-        deprecation: None,
-        module: "excessive_bools",
-    },
-    Lint {
-        name: "suboptimal_flops",
-        group: "nursery",
-        desc: "usage of sub-optimal floating point operations",
-        deprecation: None,
-        module: "floating_point_arithmetic",
-    },
-    Lint {
-        name: "suspicious_arithmetic_impl",
-        group: "correctness",
-        desc: "suspicious use of operators in impl of arithmetic trait",
-        deprecation: None,
-        module: "suspicious_trait_impl",
-    },
-    Lint {
-        name: "suspicious_assignment_formatting",
-        group: "style",
-        desc: "suspicious formatting of `*=`, `-=` or `!=`",
-        deprecation: None,
-        module: "formatting",
-    },
-    Lint {
-        name: "suspicious_else_formatting",
-        group: "style",
-        desc: "suspicious formatting of `else`",
-        deprecation: None,
-        module: "formatting",
-    },
-    Lint {
-        name: "suspicious_map",
-        group: "complexity",
-        desc: "suspicious usage of map",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "suspicious_op_assign_impl",
-        group: "correctness",
-        desc: "suspicious use of operators in impl of OpAssign trait",
-        deprecation: None,
-        module: "suspicious_trait_impl",
-    },
-    Lint {
-        name: "suspicious_unary_op_formatting",
-        group: "style",
-        desc: "suspicious formatting of unary `-` or `!` on the RHS of a BinOp",
-        deprecation: None,
-        module: "formatting",
-    },
-    Lint {
-        name: "tabs_in_doc_comments",
-        group: "style",
-        desc: "using tabs in doc comments is not recommended",
-        deprecation: None,
-        module: "tabs_in_doc_comments",
-    },
-    Lint {
-        name: "temporary_assignment",
-        group: "complexity",
-        desc: "assignments to temporaries",
-        deprecation: None,
-        module: "temporary_assignment",
-    },
-    Lint {
-        name: "to_digit_is_some",
-        group: "style",
-        desc: "`char.is_digit()` is clearer",
-        deprecation: None,
-        module: "to_digit_is_some",
-    },
-    Lint {
-        name: "to_string_in_display",
-        group: "correctness",
-        desc: "`to_string` method used while implementing `Display` trait",
-        deprecation: None,
-        module: "to_string_in_display",
-    },
-    Lint {
-        name: "todo",
-        group: "restriction",
-        desc: "`todo!` should not be present in production code",
-        deprecation: None,
-        module: "panic_unimplemented",
-    },
-    Lint {
-        name: "too_many_arguments",
-        group: "complexity",
-        desc: "functions with too many arguments",
-        deprecation: None,
-        module: "functions",
-    },
-    Lint {
-        name: "too_many_lines",
-        group: "pedantic",
-        desc: "functions with too many lines",
-        deprecation: None,
-        module: "functions",
-    },
-    Lint {
-        name: "toplevel_ref_arg",
-        group: "style",
-        desc: "an entire binding declared as `ref`, in a function argument or a `let` statement",
-        deprecation: None,
-        module: "misc",
-    },
-    Lint {
-        name: "trait_duplication_in_bounds",
-        group: "pedantic",
-        desc: "Check if the same trait bounds are specified twice during a function declaration",
-        deprecation: None,
-        module: "trait_bounds",
-    },
-    Lint {
-        name: "transmute_bytes_to_str",
-        group: "complexity",
-        desc: "transmutes from a `&[u8]` to a `&str`",
-        deprecation: None,
-        module: "transmute",
-    },
-    Lint {
-        name: "transmute_float_to_int",
-        group: "complexity",
-        desc: "transmutes from a float to an integer",
-        deprecation: None,
-        module: "transmute",
-    },
-    Lint {
-        name: "transmute_int_to_bool",
-        group: "complexity",
-        desc: "transmutes from an integer to a `bool`",
-        deprecation: None,
-        module: "transmute",
-    },
-    Lint {
-        name: "transmute_int_to_char",
-        group: "complexity",
-        desc: "transmutes from an integer to a `char`",
-        deprecation: None,
-        module: "transmute",
-    },
-    Lint {
-        name: "transmute_int_to_float",
-        group: "complexity",
-        desc: "transmutes from an integer to a float",
-        deprecation: None,
-        module: "transmute",
-    },
-    Lint {
-        name: "transmute_ptr_to_ptr",
-        group: "complexity",
-        desc: "transmutes from a pointer to a pointer / a reference to a reference",
-        deprecation: None,
-        module: "transmute",
-    },
-    Lint {
-        name: "transmute_ptr_to_ref",
-        group: "complexity",
-        desc: "transmutes from a pointer to a reference type",
-        deprecation: None,
-        module: "transmute",
-    },
-    Lint {
-        name: "transmutes_expressible_as_ptr_casts",
-        group: "complexity",
-        desc: "transmutes that could be a pointer cast",
-        deprecation: None,
-        module: "transmute",
-    },
-    Lint {
-        name: "transmuting_null",
-        group: "correctness",
-        desc: "transmutes from a null pointer to a reference, which is undefined behavior",
-        deprecation: None,
-        module: "transmuting_null",
-    },
-    Lint {
-        name: "trivial_regex",
-        group: "style",
-        desc: "trivial regular expressions",
-        deprecation: None,
-        module: "regex",
-    },
-    Lint {
-        name: "trivially_copy_pass_by_ref",
-        group: "pedantic",
-        desc: "functions taking small copyable arguments by reference",
-        deprecation: None,
-        module: "pass_by_ref_or_value",
-    },
-    Lint {
-        name: "try_err",
-        group: "style",
-        desc: "return errors explicitly rather than hiding them behind a `?`",
-        deprecation: None,
-        module: "try_err",
-    },
-    Lint {
-        name: "type_complexity",
-        group: "complexity",
-        desc: "usage of very complex types that might be better factored into `type` definitions",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "type_repetition_in_bounds",
-        group: "pedantic",
-        desc: "Types are repeated unnecessary in trait bounds use `+` instead of using `T: _, T: _`",
-        deprecation: None,
-        module: "trait_bounds",
-    },
-    Lint {
-        name: "undropped_manually_drops",
-        group: "correctness",
-        desc: "use of safe `std::mem::drop` function to drop a std::mem::ManuallyDrop, which will not drop the inner value",
-        deprecation: None,
-        module: "undropped_manually_drops",
-    },
-    Lint {
-        name: "unicode_not_nfc",
-        group: "pedantic",
-        desc: "using a Unicode literal not in NFC normal form (see [Unicode tr15](http://www.unicode.org/reports/tr15/) for further information)",
-        deprecation: None,
-        module: "unicode",
-    },
-    Lint {
-        name: "unimplemented",
-        group: "restriction",
-        desc: "`unimplemented!` should not be present in production code",
-        deprecation: None,
-        module: "panic_unimplemented",
-    },
-    Lint {
-        name: "uninit_assumed_init",
-        group: "correctness",
-        desc: "`MaybeUninit::uninit().assume_init()`",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "unit_arg",
-        group: "complexity",
-        desc: "passing unit to a function",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "unit_cmp",
-        group: "correctness",
-        desc: "comparing unit values",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "unit_return_expecting_ord",
-        group: "correctness",
-        desc: "fn arguments of type Fn(...) -> Ord returning the unit type ().",
-        deprecation: None,
-        module: "unit_return_expecting_ord",
-    },
-    Lint {
-        name: "unknown_clippy_lints",
-        group: "style",
-        desc: "unknown_lints for scoped Clippy lints",
-        deprecation: None,
-        module: "attrs",
-    },
-    Lint {
-        name: "unnecessary_cast",
-        group: "complexity",
-        desc: "cast to the same type, e.g., `x as i32` where `x: i32`",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "unnecessary_filter_map",
-        group: "complexity",
-        desc: "using `filter_map` when a more succinct alternative exists",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "unnecessary_fold",
-        group: "style",
-        desc: "using `fold` when a more succinct alternative exists",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "unnecessary_lazy_evaluations",
-        group: "style",
-        desc: "using unnecessary lazy evaluation, which can be replaced with simpler eager evaluation",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "unnecessary_mut_passed",
-        group: "style",
-        desc: "an argument passed as a mutable reference although the callee only demands an immutable reference",
-        deprecation: None,
-        module: "mut_reference",
-    },
-    Lint {
-        name: "unnecessary_operation",
-        group: "complexity",
-        desc: "outer expressions with no effect",
-        deprecation: None,
-        module: "no_effect",
-    },
-    Lint {
-        name: "unnecessary_sort_by",
-        group: "complexity",
-        desc: "Use of `Vec::sort_by` when `Vec::sort_by_key` or `Vec::sort` would be clearer",
-        deprecation: None,
-        module: "unnecessary_sort_by",
-    },
-    Lint {
-        name: "unnecessary_unwrap",
-        group: "complexity",
-        desc: "checks for calls of `unwrap[_err]()` that cannot fail",
-        deprecation: None,
-        module: "unwrap",
-    },
-    Lint {
-        name: "unneeded_field_pattern",
-        group: "restriction",
-        desc: "struct fields bound to a wildcard instead of using `..`",
-        deprecation: None,
-        module: "misc_early",
-    },
-    Lint {
-        name: "unneeded_wildcard_pattern",
-        group: "complexity",
-        desc: "tuple patterns with a wildcard pattern (`_`) is next to a rest pattern (`..`)",
-        deprecation: None,
-        module: "misc_early",
-    },
-    Lint {
-        name: "unnested_or_patterns",
-        group: "pedantic",
-        desc: "unnested or-patterns, e.g., `Foo(Bar) | Foo(Baz) instead of `Foo(Bar | Baz)`",
-        deprecation: None,
-        module: "unnested_or_patterns",
-    },
-    Lint {
-        name: "unreachable",
-        group: "restriction",
-        desc: "`unreachable!` should not be present in production code",
-        deprecation: None,
-        module: "panic_unimplemented",
-    },
-    Lint {
-        name: "unreadable_literal",
-        group: "pedantic",
-        desc: "long integer literal without underscores",
-        deprecation: None,
-        module: "literal_representation",
-    },
-    Lint {
-        name: "unsafe_derive_deserialize",
-        group: "pedantic",
-        desc: "deriving `serde::Deserialize` on a type that has methods using `unsafe`",
-        deprecation: None,
-        module: "derive",
-    },
-    Lint {
-        name: "unsafe_removed_from_name",
-        group: "style",
-        desc: "`unsafe` removed from API names on import",
-        deprecation: None,
-        module: "unsafe_removed_from_name",
-    },
-    Lint {
-        name: "unseparated_literal_suffix",
-        group: "pedantic",
-        desc: "literals whose suffix is not separated by an underscore",
-        deprecation: None,
-        module: "misc_early",
-    },
-    Lint {
-        name: "unsound_collection_transmute",
-        group: "correctness",
-        desc: "transmute between collections of layout-incompatible types",
-        deprecation: None,
-        module: "transmute",
-    },
-    Lint {
-        name: "unused_io_amount",
-        group: "correctness",
-        desc: "unused written/read amount",
-        deprecation: None,
-        module: "unused_io_amount",
-    },
-    Lint {
-        name: "unused_self",
-        group: "pedantic",
-        desc: "methods that contain a `self` argument but don\'t use it",
-        deprecation: None,
-        module: "unused_self",
-    },
-    Lint {
-        name: "unused_unit",
-        group: "style",
-        desc: "needless unit expression",
-        deprecation: None,
-        module: "unused_unit",
-    },
-    Lint {
-        name: "unusual_byte_groupings",
-        group: "style",
-        desc: "binary or hex literals that aren\'t grouped by four",
-        deprecation: None,
-        module: "literal_representation",
-    },
-    Lint {
-        name: "unwrap_in_result",
-        group: "restriction",
-        desc: "functions of type `Result<..>` or `Option`<...> that contain `expect()` or `unwrap()`",
-        deprecation: None,
-        module: "unwrap_in_result",
-    },
-    Lint {
-        name: "unwrap_used",
-        group: "restriction",
-        desc: "using `.unwrap()` on `Result` or `Option`, which should at least get a better message using `expect()`",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "use_debug",
-        group: "restriction",
-        desc: "use of `Debug`-based formatting",
-        deprecation: None,
-        module: "write",
-    },
-    Lint {
-        name: "use_self",
-        group: "nursery",
-        desc: "unnecessary structure name repetition whereas `Self` is applicable",
-        deprecation: None,
-        module: "use_self",
-    },
-    Lint {
-        name: "used_underscore_binding",
-        group: "pedantic",
-        desc: "using a binding which is prefixed with an underscore",
-        deprecation: None,
-        module: "misc",
-    },
-    Lint {
-        name: "useless_asref",
-        group: "complexity",
-        desc: "using `as_ref` where the types before and after the call are the same",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "useless_attribute",
-        group: "correctness",
-        desc: "use of lint attributes on `extern crate` items",
-        deprecation: None,
-        module: "attrs",
-    },
-    Lint {
-        name: "useless_conversion",
-        group: "complexity",
-        desc: "calls to `Into`, `TryInto`, `From`, `TryFrom`, `IntoIter` that performs useless conversions to the same type",
-        deprecation: None,
-        module: "useless_conversion",
-    },
-    Lint {
-        name: "useless_format",
-        group: "complexity",
-        desc: "useless use of `format!`",
-        deprecation: None,
-        module: "format",
-    },
-    Lint {
-        name: "useless_let_if_seq",
-        group: "nursery",
-        desc: "unidiomatic `let mut` declaration followed by initialization in `if`",
-        deprecation: None,
-        module: "let_if_seq",
-    },
-    Lint {
-        name: "useless_transmute",
-        group: "nursery",
-        desc: "transmutes that have the same to and from types or could be a cast/coercion",
-        deprecation: None,
-        module: "transmute",
-    },
-    Lint {
-        name: "useless_vec",
-        group: "perf",
-        desc: "useless `vec!`",
-        deprecation: None,
-        module: "vec",
-    },
-    Lint {
-        name: "vec_box",
-        group: "complexity",
-        desc: "usage of `Vec<Box<T>>` where T: Sized, vector elements are already on the heap",
-        deprecation: None,
-        module: "types",
-    },
-    Lint {
-        name: "vec_resize_to_zero",
-        group: "correctness",
-        desc: "emptying a vector with `resize(0, an_int)` instead of `clear()` is probably an argument inversion mistake",
-        deprecation: None,
-        module: "vec_resize_to_zero",
-    },
-    Lint {
-        name: "verbose_bit_mask",
-        group: "pedantic",
-        desc: "expressions where a bit mask is less readable than the corresponding method call",
-        deprecation: None,
-        module: "bit_mask",
-    },
-    Lint {
-        name: "verbose_file_reads",
-        group: "restriction",
-        desc: "use of `File::read_to_end` or `File::read_to_string`",
-        deprecation: None,
-        module: "verbose_file_reads",
-    },
-    Lint {
-        name: "vtable_address_comparisons",
-        group: "correctness",
-        desc: "comparison with an address of a trait vtable",
-        deprecation: None,
-        module: "unnamed_address",
-    },
-    Lint {
-        name: "while_immutable_condition",
-        group: "correctness",
-        desc: "variables used within while expression are not mutated in the body",
-        deprecation: None,
-        module: "loops",
-    },
-    Lint {
-        name: "while_let_loop",
-        group: "complexity",
-        desc: "`loop { if let { ... } else break }`, which can be written as a `while let` loop",
-        deprecation: None,
-        module: "loops",
-    },
-    Lint {
-        name: "while_let_on_iterator",
-        group: "style",
-        desc: "using a while-let loop instead of a for loop on an iterator",
-        deprecation: None,
-        module: "loops",
-    },
-    Lint {
-        name: "wildcard_dependencies",
-        group: "cargo",
-        desc: "wildcard dependencies being used",
-        deprecation: None,
-        module: "wildcard_dependencies",
-    },
-    Lint {
-        name: "wildcard_enum_match_arm",
-        group: "restriction",
-        desc: "a wildcard enum match arm using `_`",
-        deprecation: None,
-        module: "matches",
-    },
-    Lint {
-        name: "wildcard_imports",
-        group: "pedantic",
-        desc: "lint `use _::*` statements",
-        deprecation: None,
-        module: "wildcard_imports",
-    },
-    Lint {
-        name: "wildcard_in_or_patterns",
-        group: "complexity",
-        desc: "a wildcard pattern used with others patterns in same match arm",
-        deprecation: None,
-        module: "matches",
-    },
-    Lint {
-        name: "write_literal",
-        group: "style",
-        desc: "writing a literal with a format string",
-        deprecation: None,
-        module: "write",
-    },
-    Lint {
-        name: "write_with_newline",
-        group: "style",
-        desc: "using `write!()` with a format string that ends in a single newline",
-        deprecation: None,
-        module: "write",
-    },
-    Lint {
-        name: "writeln_empty_string",
-        group: "style",
-        desc: "using `writeln!(buf, \"\")` with an empty string",
-        deprecation: None,
-        module: "write",
-    },
-    Lint {
-        name: "wrong_pub_self_convention",
-        group: "restriction",
-        desc: "defining a public method named with an established prefix (like \"into_\") that takes `self` with the wrong convention",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "wrong_self_convention",
-        group: "style",
-        desc: "defining a method named with an established prefix (like \"into_\") that takes `self` with the wrong convention",
-        deprecation: None,
-        module: "methods",
-    },
-    Lint {
-        name: "wrong_transmute",
-        group: "correctness",
-        desc: "transmutes that are confusing at best, undefined behaviour at worst and always useless",
-        deprecation: None,
-        module: "transmute",
-    },
-    Lint {
-        name: "zero_divided_by_zero",
-        group: "complexity",
-        desc: "usage of `0.0 / 0.0` to obtain NaN instead of `f32::NAN` or `f64::NAN`",
-        deprecation: None,
-        module: "zero_div_zero",
-    },
-    Lint {
-        name: "zero_prefixed_literal",
-        group: "complexity",
-        desc: "integer literals starting with `0`",
-        deprecation: None,
-        module: "misc_early",
-    },
-    Lint {
-        name: "zero_ptr",
-        group: "style",
-        desc: "using `0 as *{const, mut} T`",
-        deprecation: None,
-        module: "misc",
-    },
-    Lint {
-        name: "zst_offset",
-        group: "correctness",
-        desc: "Check for offset calculations on raw pointers to zero-sized types",
-        deprecation: None,
-        module: "methods",
-    },
-]
-// end lint list, do not remove this comment, it’s used in `update_lints`
-});
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const.rs b/src/tools/clippy/tests/ui/borrow_interior_mutable_const.rs
deleted file mode 100644 (file)
index 9fcc9ec..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-#![warn(clippy::borrow_interior_mutable_const)]
-#![allow(clippy::declare_interior_mutable_const, clippy::ref_in_deref)]
-#![allow(const_item_mutation)]
-
-use std::borrow::Cow;
-use std::cell::{Cell, UnsafeCell};
-use std::fmt::Display;
-use std::sync::atomic::{AtomicUsize, Ordering};
-use std::sync::Once;
-
-const ATOMIC: AtomicUsize = AtomicUsize::new(5);
-const CELL: Cell<usize> = Cell::new(6);
-const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec<AtomicUsize>, u8) = ([ATOMIC], Vec::new(), 7);
-const INTEGER: u8 = 8;
-const STRING: String = String::new();
-const STR: &str = "012345";
-const COW: Cow<str> = Cow::Borrowed("abcdef");
-const NO_ANN: &dyn Display = &70;
-static STATIC_TUPLE: (AtomicUsize, String) = (ATOMIC, STRING);
-const ONCE_INIT: Once = Once::new();
-
-trait Trait<T> {
-    type AssocType;
-
-    const ATOMIC: AtomicUsize;
-    const INPUT: T;
-    const ASSOC: Self::AssocType;
-
-    fn function() {
-        let _ = &Self::INPUT;
-        let _ = &Self::ASSOC;
-    }
-}
-
-impl Trait<u32> for u64 {
-    type AssocType = AtomicUsize;
-
-    const ATOMIC: AtomicUsize = AtomicUsize::new(9);
-    const INPUT: u32 = 10;
-    const ASSOC: Self::AssocType = AtomicUsize::new(11);
-
-    fn function() {
-        let _ = &Self::INPUT;
-        let _ = &Self::ASSOC; //~ ERROR interior mutability
-    }
-}
-
-// This is just a pointer that can be safely dereferended,
-// it's semantically the same as `&'static T`;
-// but it isn't allowed to make a static reference from an arbitrary integer value at the moment.
-// For more information, please see the issue #5918.
-pub struct StaticRef<T> {
-    ptr: *const T,
-}
-
-impl<T> StaticRef<T> {
-    /// Create a new `StaticRef` from a raw pointer
-    ///
-    /// ## Safety
-    ///
-    /// Callers must pass in a reference to statically allocated memory which
-    /// does not overlap with other values.
-    pub const unsafe fn new(ptr: *const T) -> StaticRef<T> {
-        StaticRef { ptr }
-    }
-}
-
-impl<T> std::ops::Deref for StaticRef<T> {
-    type Target = T;
-
-    fn deref(&self) -> &'static T {
-        unsafe { &*self.ptr }
-    }
-}
-
-// use a tuple to make sure referencing a field behind a pointer isn't linted.
-const CELL_REF: StaticRef<(UnsafeCell<u32>,)> = unsafe { StaticRef::new(std::ptr::null()) };
-
-fn main() {
-    ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability
-    assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability
-
-    let _once = ONCE_INIT;
-    let _once_ref = &ONCE_INIT; //~ ERROR interior mutability
-    let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability
-    let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability
-    let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability
-    let _atomic_into_inner = ATOMIC.into_inner();
-    // these should be all fine.
-    let _twice = (ONCE_INIT, ONCE_INIT);
-    let _ref_twice = &(ONCE_INIT, ONCE_INIT);
-    let _ref_once = &(ONCE_INIT, ONCE_INIT).0;
-    let _array_twice = [ONCE_INIT, ONCE_INIT];
-    let _ref_array_twice = &[ONCE_INIT, ONCE_INIT];
-    let _ref_array_once = &[ONCE_INIT, ONCE_INIT][0];
-
-    // referencing projection is still bad.
-    let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability
-    let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability
-    let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability
-    let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
-    let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability
-    let _ = &*ATOMIC_TUPLE.1; //~ ERROR interior mutability
-    let _ = &ATOMIC_TUPLE.2;
-    let _ = (&&&&ATOMIC_TUPLE).0;
-    let _ = (&&&&ATOMIC_TUPLE).2;
-    let _ = ATOMIC_TUPLE.0;
-    let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
-    let _ = ATOMIC_TUPLE.1.into_iter();
-    let _ = ATOMIC_TUPLE.2;
-    let _ = &{ ATOMIC_TUPLE };
-
-    CELL.set(2); //~ ERROR interior mutability
-    assert_eq!(CELL.get(), 6); //~ ERROR interior mutability
-
-    assert_eq!(INTEGER, 8);
-    assert!(STRING.is_empty());
-
-    let a = ATOMIC;
-    a.store(4, Ordering::SeqCst);
-    assert_eq!(a.load(Ordering::SeqCst), 4);
-
-    STATIC_TUPLE.0.store(3, Ordering::SeqCst);
-    assert_eq!(STATIC_TUPLE.0.load(Ordering::SeqCst), 3);
-    assert!(STATIC_TUPLE.1.is_empty());
-
-    u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability
-    assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability
-
-    assert_eq!(NO_ANN.to_string(), "70"); // should never lint this.
-
-    let _ = &CELL_REF.0;
-}
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const.stderr b/src/tools/clippy/tests/ui/borrow_interior_mutable_const.stderr
deleted file mode 100644 (file)
index ed726a6..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/borrow_interior_mutable_const.rs:44:18
-   |
-LL |         let _ = &Self::ASSOC; //~ ERROR interior mutability
-   |                  ^^^^^^^^^^^
-   |
-   = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings`
-   = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/borrow_interior_mutable_const.rs:80:5
-   |
-LL |     ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability
-   |     ^^^^^^
-   |
-   = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/borrow_interior_mutable_const.rs:81:16
-   |
-LL |     assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability
-   |                ^^^^^^
-   |
-   = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/borrow_interior_mutable_const.rs:84:22
-   |
-LL |     let _once_ref = &ONCE_INIT; //~ ERROR interior mutability
-   |                      ^^^^^^^^^
-   |
-   = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/borrow_interior_mutable_const.rs:85:25
-   |
-LL |     let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability
-   |                         ^^^^^^^^^
-   |
-   = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/borrow_interior_mutable_const.rs:86:27
-   |
-LL |     let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability
-   |                           ^^^^^^^^^
-   |
-   = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/borrow_interior_mutable_const.rs:87:26
-   |
-LL |     let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability
-   |                          ^^^^^^^^^
-   |
-   = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/borrow_interior_mutable_const.rs:98:14
-   |
-LL |     let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability
-   |              ^^^^^^^^^^^^
-   |
-   = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/borrow_interior_mutable_const.rs:99:14
-   |
-LL |     let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability
-   |              ^^^^^^^^^^^^
-   |
-   = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/borrow_interior_mutable_const.rs:100:19
-   |
-LL |     let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability
-   |                   ^^^^^^^^^^^^
-   |
-   = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/borrow_interior_mutable_const.rs:101:14
-   |
-LL |     let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
-   |              ^^^^^^^^^^^^
-   |
-   = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/borrow_interior_mutable_const.rs:102:13
-   |
-LL |     let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability
-   |             ^^^^^^^^^^^^
-   |
-   = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/borrow_interior_mutable_const.rs:108:13
-   |
-LL |     let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
-   |             ^^^^^^^^^^^^
-   |
-   = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/borrow_interior_mutable_const.rs:113:5
-   |
-LL |     CELL.set(2); //~ ERROR interior mutability
-   |     ^^^^
-   |
-   = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/borrow_interior_mutable_const.rs:114:16
-   |
-LL |     assert_eq!(CELL.get(), 6); //~ ERROR interior mutability
-   |                ^^^^
-   |
-   = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/borrow_interior_mutable_const.rs:127:5
-   |
-LL |     u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability
-   |     ^^^^^^^^^^^
-   |
-   = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/borrow_interior_mutable_const.rs:128:16
-   |
-LL |     assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability
-   |                ^^^^^^^^^^^
-   |
-   = help: assign this const to a local or static variable, and use the variable here
-
-error: aborting due to 17 previous errors
-
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/auxiliary/helper.rs b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/auxiliary/helper.rs
new file mode 100644 (file)
index 0000000..2289f78
--- /dev/null
@@ -0,0 +1,16 @@
+// this file solely exists to test constants defined in foreign crates.
+// As the most common case is the `http` crate, it replicates `http::HeadewrName`'s structure.
+
+#![allow(clippy::declare_interior_mutable_const)]
+
+use std::sync::atomic::AtomicUsize;
+
+enum Private<T> {
+    ToBeUnfrozen(T),
+    Frozen(usize),
+}
+
+pub struct Wrapper(Private<AtomicUsize>);
+
+pub const WRAPPED_PRIVATE_UNFROZEN_VARIANT: Wrapper = Wrapper(Private::ToBeUnfrozen(AtomicUsize::new(6)));
+pub const WRAPPED_PRIVATE_FROZEN_VARIANT: Wrapper = Wrapper(Private::Frozen(7));
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.rs b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.rs
new file mode 100644 (file)
index 0000000..5027db4
--- /dev/null
@@ -0,0 +1,101 @@
+// aux-build:helper.rs
+
+#![warn(clippy::borrow_interior_mutable_const)]
+#![allow(clippy::declare_interior_mutable_const)]
+
+// this file (mostly) replicates its `declare` counterpart. Please see it for more discussions.
+
+extern crate helper;
+
+use std::cell::Cell;
+use std::sync::atomic::AtomicUsize;
+
+enum OptionalCell {
+    Unfrozen(Cell<bool>),
+    Frozen,
+}
+
+const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true));
+const FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen;
+
+fn borrow_optional_cell() {
+    let _ = &UNFROZEN_VARIANT; //~ ERROR interior mutability
+    let _ = &FROZEN_VARIANT;
+}
+
+trait AssocConsts {
+    const TO_BE_UNFROZEN_VARIANT: OptionalCell;
+    const TO_BE_FROZEN_VARIANT: OptionalCell;
+
+    const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false));
+    const DEFAULTED_ON_FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen;
+
+    fn function() {
+        // This is the "suboptimal behavior" mentioned in `is_value_unfrozen`
+        // caused by a similar reason to unfrozen types without any default values
+        // get linted even if it has frozen variants'.
+        let _ = &Self::TO_BE_FROZEN_VARIANT; //~ ERROR interior mutable
+
+        // The lint ignores default values because an impl of this trait can set
+        // an unfrozen variant to `DEFAULTED_ON_FROZEN_VARIANT` and use the default impl for `function`.
+        let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT; //~ ERROR interior mutable
+    }
+}
+
+impl AssocConsts for u64 {
+    const TO_BE_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false));
+    const TO_BE_FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen;
+
+    fn function() {
+        let _ = &<Self as AssocConsts>::TO_BE_UNFROZEN_VARIANT; //~ ERROR interior mutable
+        let _ = &<Self as AssocConsts>::TO_BE_FROZEN_VARIANT;
+        let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT; //~ ERROR interior mutable
+        let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT;
+    }
+}
+
+trait AssocTypes {
+    type ToBeUnfrozen;
+
+    const TO_BE_UNFROZEN_VARIANT: Option<Self::ToBeUnfrozen>;
+    const TO_BE_FROZEN_VARIANT: Option<Self::ToBeUnfrozen>;
+
+    // there's no need to test here because it's the exactly same as `trait::AssocTypes`
+    fn function();
+}
+
+impl AssocTypes for u64 {
+    type ToBeUnfrozen = AtomicUsize;
+
+    const TO_BE_UNFROZEN_VARIANT: Option<Self::ToBeUnfrozen> = Some(Self::ToBeUnfrozen::new(4)); //~ ERROR interior mutable
+    const TO_BE_FROZEN_VARIANT: Option<Self::ToBeUnfrozen> = None;
+
+    fn function() {
+        let _ = &<Self as AssocTypes>::TO_BE_UNFROZEN_VARIANT; //~ ERROR interior mutable
+        let _ = &<Self as AssocTypes>::TO_BE_FROZEN_VARIANT;
+    }
+}
+
+enum BothOfCellAndGeneric<T> {
+    Unfrozen(Cell<*const T>),
+    Generic(*const T),
+    Frozen(usize),
+}
+
+impl<T> BothOfCellAndGeneric<T> {
+    const UNFROZEN_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR interior mutable
+    const GENERIC_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mutable
+    const FROZEN_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Frozen(5);
+
+    fn function() {
+        let _ = &Self::UNFROZEN_VARIANT; //~ ERROR interior mutability
+        let _ = &Self::GENERIC_VARIANT; //~ ERROR interior mutability
+        let _ = &Self::FROZEN_VARIANT;
+    }
+}
+
+fn main() {
+    // constants defined in foreign crates
+    let _ = &helper::WRAPPED_PRIVATE_UNFROZEN_VARIANT; //~ ERROR interior mutability
+    let _ = &helper::WRAPPED_PRIVATE_FROZEN_VARIANT;
+}
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.stderr b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.stderr
new file mode 100644 (file)
index 0000000..654a1ee
--- /dev/null
@@ -0,0 +1,75 @@
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/enums.rs:22:14
+   |
+LL |     let _ = &UNFROZEN_VARIANT; //~ ERROR interior mutability
+   |              ^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings`
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/enums.rs:37:18
+   |
+LL |         let _ = &Self::TO_BE_FROZEN_VARIANT; //~ ERROR interior mutable
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/enums.rs:41:18
+   |
+LL |         let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT; //~ ERROR interior mutable
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/enums.rs:50:18
+   |
+LL |         let _ = &<Self as AssocConsts>::TO_BE_UNFROZEN_VARIANT; //~ ERROR interior mutable
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/enums.rs:52:18
+   |
+LL |         let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT; //~ ERROR interior mutable
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/enums.rs:74:18
+   |
+LL |         let _ = &<Self as AssocTypes>::TO_BE_UNFROZEN_VARIANT; //~ ERROR interior mutable
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/enums.rs:91:18
+   |
+LL |         let _ = &Self::UNFROZEN_VARIANT; //~ ERROR interior mutability
+   |                  ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/enums.rs:92:18
+   |
+LL |         let _ = &Self::GENERIC_VARIANT; //~ ERROR interior mutability
+   |                  ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/enums.rs:99:14
+   |
+LL |     let _ = &helper::WRAPPED_PRIVATE_UNFROZEN_VARIANT; //~ ERROR interior mutability
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: aborting due to 9 previous errors
+
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs
new file mode 100644 (file)
index 0000000..ea25729
--- /dev/null
@@ -0,0 +1,104 @@
+#![warn(clippy::borrow_interior_mutable_const)]
+#![allow(clippy::declare_interior_mutable_const, clippy::ref_in_deref)]
+#![allow(const_item_mutation)]
+
+use std::borrow::Cow;
+use std::cell::{Cell, UnsafeCell};
+use std::fmt::Display;
+use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::Once;
+
+const ATOMIC: AtomicUsize = AtomicUsize::new(5);
+const CELL: Cell<usize> = Cell::new(6);
+const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec<AtomicUsize>, u8) = ([ATOMIC], Vec::new(), 7);
+const INTEGER: u8 = 8;
+const STRING: String = String::new();
+const STR: &str = "012345";
+const COW: Cow<str> = Cow::Borrowed("abcdef");
+const NO_ANN: &dyn Display = &70;
+static STATIC_TUPLE: (AtomicUsize, String) = (ATOMIC, STRING);
+const ONCE_INIT: Once = Once::new();
+
+// This is just a pointer that can be safely dereferenced,
+// it's semantically the same as `&'static T`;
+// but it isn't allowed to make a static reference from an arbitrary integer value at the moment.
+// For more information, please see the issue #5918.
+pub struct StaticRef<T> {
+    ptr: *const T,
+}
+
+impl<T> StaticRef<T> {
+    /// Create a new `StaticRef` from a raw pointer
+    ///
+    /// ## Safety
+    ///
+    /// Callers must pass in a reference to statically allocated memory which
+    /// does not overlap with other values.
+    pub const unsafe fn new(ptr: *const T) -> StaticRef<T> {
+        StaticRef { ptr }
+    }
+}
+
+impl<T> std::ops::Deref for StaticRef<T> {
+    type Target = T;
+
+    fn deref(&self) -> &'static T {
+        unsafe { &*self.ptr }
+    }
+}
+
+// use a tuple to make sure referencing a field behind a pointer isn't linted.
+const CELL_REF: StaticRef<(UnsafeCell<u32>,)> = unsafe { StaticRef::new(std::ptr::null()) };
+
+fn main() {
+    ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability
+    assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability
+
+    let _once = ONCE_INIT;
+    let _once_ref = &ONCE_INIT; //~ ERROR interior mutability
+    let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability
+    let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability
+    let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability
+    let _atomic_into_inner = ATOMIC.into_inner();
+    // these should be all fine.
+    let _twice = (ONCE_INIT, ONCE_INIT);
+    let _ref_twice = &(ONCE_INIT, ONCE_INIT);
+    let _ref_once = &(ONCE_INIT, ONCE_INIT).0;
+    let _array_twice = [ONCE_INIT, ONCE_INIT];
+    let _ref_array_twice = &[ONCE_INIT, ONCE_INIT];
+    let _ref_array_once = &[ONCE_INIT, ONCE_INIT][0];
+
+    // referencing projection is still bad.
+    let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability
+    let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability
+    let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability
+    let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
+    let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability
+    let _ = &*ATOMIC_TUPLE.1;
+    let _ = &ATOMIC_TUPLE.2;
+    let _ = (&&&&ATOMIC_TUPLE).0;
+    let _ = (&&&&ATOMIC_TUPLE).2;
+    let _ = ATOMIC_TUPLE.0;
+    let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
+    let _ = ATOMIC_TUPLE.1.into_iter();
+    let _ = ATOMIC_TUPLE.2;
+    let _ = &{ ATOMIC_TUPLE };
+
+    CELL.set(2); //~ ERROR interior mutability
+    assert_eq!(CELL.get(), 6); //~ ERROR interior mutability
+
+    assert_eq!(INTEGER, 8);
+    assert!(STRING.is_empty());
+
+    let a = ATOMIC;
+    a.store(4, Ordering::SeqCst);
+    assert_eq!(a.load(Ordering::SeqCst), 4);
+
+    STATIC_TUPLE.0.store(3, Ordering::SeqCst);
+    assert_eq!(STATIC_TUPLE.0.load(Ordering::SeqCst), 3);
+    assert!(STATIC_TUPLE.1.is_empty());
+
+    assert_eq!(NO_ANN.to_string(), "70"); // should never lint this.
+
+    let _ = &CELL_REF.0;
+}
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr
new file mode 100644 (file)
index 0000000..9a908cf
--- /dev/null
@@ -0,0 +1,115 @@
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/others.rs:54:5
+   |
+LL |     ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability
+   |     ^^^^^^
+   |
+   = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings`
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/others.rs:55:16
+   |
+LL |     assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability
+   |                ^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/others.rs:58:22
+   |
+LL |     let _once_ref = &ONCE_INIT; //~ ERROR interior mutability
+   |                      ^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/others.rs:59:25
+   |
+LL |     let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability
+   |                         ^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/others.rs:60:27
+   |
+LL |     let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability
+   |                           ^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/others.rs:61:26
+   |
+LL |     let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability
+   |                          ^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/others.rs:72:14
+   |
+LL |     let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability
+   |              ^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/others.rs:73:14
+   |
+LL |     let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability
+   |              ^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/others.rs:74:19
+   |
+LL |     let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability
+   |                   ^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/others.rs:75:14
+   |
+LL |     let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
+   |              ^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/others.rs:76:13
+   |
+LL |     let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability
+   |             ^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/others.rs:82:13
+   |
+LL |     let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
+   |             ^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/others.rs:87:5
+   |
+LL |     CELL.set(2); //~ ERROR interior mutability
+   |     ^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/others.rs:88:16
+   |
+LL |     assert_eq!(CELL.get(), 6); //~ ERROR interior mutability
+   |                ^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: aborting due to 14 previous errors
+
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.rs b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.rs
new file mode 100644 (file)
index 0000000..06b5d62
--- /dev/null
@@ -0,0 +1,202 @@
+#![warn(clippy::borrow_interior_mutable_const)]
+#![allow(clippy::declare_interior_mutable_const)]
+
+// this file replicates its `declare` counterpart. Please see it for more discussions.
+
+use std::borrow::Cow;
+use std::cell::Cell;
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+trait ConcreteTypes {
+    const ATOMIC: AtomicUsize;
+    const STRING: String;
+
+    fn function() {
+        let _ = &Self::ATOMIC; //~ ERROR interior mutable
+        let _ = &Self::STRING;
+    }
+}
+
+impl ConcreteTypes for u64 {
+    const ATOMIC: AtomicUsize = AtomicUsize::new(9);
+    const STRING: String = String::new();
+
+    fn function() {
+        // Lint this again since implementers can choose not to borrow it.
+        let _ = &Self::ATOMIC; //~ ERROR interior mutable
+        let _ = &Self::STRING;
+    }
+}
+
+// a helper trait used below
+trait ConstDefault {
+    const DEFAULT: Self;
+}
+
+trait GenericTypes<T, U> {
+    const TO_REMAIN_GENERIC: T;
+    const TO_BE_CONCRETE: U;
+
+    fn function() {
+        let _ = &Self::TO_REMAIN_GENERIC;
+    }
+}
+
+impl<T: ConstDefault> GenericTypes<T, AtomicUsize> for Vec<T> {
+    const TO_REMAIN_GENERIC: T = T::DEFAULT;
+    const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11);
+
+    fn function() {
+        let _ = &Self::TO_REMAIN_GENERIC;
+        let _ = &Self::TO_BE_CONCRETE; //~ ERROR interior mutable
+    }
+}
+
+// a helper type used below
+pub struct Wrapper<T>(T);
+
+trait AssocTypes {
+    type ToBeFrozen;
+    type ToBeUnfrozen;
+    type ToBeGenericParam;
+
+    const TO_BE_FROZEN: Self::ToBeFrozen;
+    const TO_BE_UNFROZEN: Self::ToBeUnfrozen;
+    const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen>;
+    const WRAPPED_TO_BE_GENERIC_PARAM: Wrapper<Self::ToBeGenericParam>;
+
+    fn function() {
+        let _ = &Self::TO_BE_FROZEN;
+        let _ = &Self::WRAPPED_TO_BE_UNFROZEN;
+    }
+}
+
+impl<T: ConstDefault> AssocTypes for Vec<T> {
+    type ToBeFrozen = u16;
+    type ToBeUnfrozen = AtomicUsize;
+    type ToBeGenericParam = T;
+
+    const TO_BE_FROZEN: Self::ToBeFrozen = 12;
+    const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13);
+    const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen> = Wrapper(AtomicUsize::new(14));
+    const WRAPPED_TO_BE_GENERIC_PARAM: Wrapper<Self::ToBeGenericParam> = Wrapper(T::DEFAULT);
+
+    fn function() {
+        let _ = &Self::TO_BE_FROZEN;
+        let _ = &Self::TO_BE_UNFROZEN; //~ ERROR interior mutable
+        let _ = &Self::WRAPPED_TO_BE_UNFROZEN; //~ ERROR interior mutable
+        let _ = &Self::WRAPPED_TO_BE_GENERIC_PARAM;
+    }
+}
+
+// a helper trait used below
+trait AssocTypesHelper {
+    type NotToBeBounded;
+    type ToBeBounded;
+
+    const NOT_TO_BE_BOUNDED: Self::NotToBeBounded;
+}
+
+trait AssocTypesFromGenericParam<T>
+where
+    T: AssocTypesHelper<ToBeBounded = AtomicUsize>,
+{
+    const NOT_BOUNDED: T::NotToBeBounded;
+    const BOUNDED: T::ToBeBounded;
+
+    fn function() {
+        let _ = &Self::NOT_BOUNDED;
+        let _ = &Self::BOUNDED; //~ ERROR interior mutable
+    }
+}
+
+impl<T> AssocTypesFromGenericParam<T> for Vec<T>
+where
+    T: AssocTypesHelper<ToBeBounded = AtomicUsize>,
+{
+    const NOT_BOUNDED: T::NotToBeBounded = T::NOT_TO_BE_BOUNDED;
+    const BOUNDED: T::ToBeBounded = AtomicUsize::new(15);
+
+    fn function() {
+        let _ = &Self::NOT_BOUNDED;
+        let _ = &Self::BOUNDED; //~ ERROR interior mutable
+    }
+}
+
+trait SelfType: Sized {
+    const SELF: Self;
+    const WRAPPED_SELF: Option<Self>;
+
+    fn function() {
+        let _ = &Self::SELF;
+        let _ = &Self::WRAPPED_SELF;
+    }
+}
+
+impl SelfType for u64 {
+    const SELF: Self = 16;
+    const WRAPPED_SELF: Option<Self> = Some(20);
+
+    fn function() {
+        let _ = &Self::SELF;
+        let _ = &Self::WRAPPED_SELF;
+    }
+}
+
+impl SelfType for AtomicUsize {
+    const SELF: Self = AtomicUsize::new(17);
+    const WRAPPED_SELF: Option<Self> = Some(AtomicUsize::new(21));
+
+    fn function() {
+        let _ = &Self::SELF; //~ ERROR interior mutable
+        let _ = &Self::WRAPPED_SELF; //~ ERROR interior mutable
+    }
+}
+
+trait BothOfCellAndGeneric<T> {
+    const DIRECT: Cell<T>;
+    const INDIRECT: Cell<*const T>;
+
+    fn function() {
+        let _ = &Self::DIRECT;
+        let _ = &Self::INDIRECT; //~ ERROR interior mutable
+    }
+}
+
+impl<T: ConstDefault> BothOfCellAndGeneric<T> for Vec<T> {
+    const DIRECT: Cell<T> = Cell::new(T::DEFAULT);
+    const INDIRECT: Cell<*const T> = Cell::new(std::ptr::null());
+
+    fn function() {
+        let _ = &Self::DIRECT;
+        let _ = &Self::INDIRECT; //~ ERROR interior mutable
+    }
+}
+
+struct Local<T>(T);
+
+impl<T> Local<T>
+where
+    T: ConstDefault + AssocTypesHelper<ToBeBounded = AtomicUsize>,
+{
+    const ATOMIC: AtomicUsize = AtomicUsize::new(18);
+    const COW: Cow<'static, str> = Cow::Borrowed("tuvwxy");
+
+    const GENERIC_TYPE: T = T::DEFAULT;
+
+    const ASSOC_TYPE: T::NotToBeBounded = T::NOT_TO_BE_BOUNDED;
+    const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19);
+
+    fn function() {
+        let _ = &Self::ATOMIC; //~ ERROR interior mutable
+        let _ = &Self::COW;
+        let _ = &Self::GENERIC_TYPE;
+        let _ = &Self::ASSOC_TYPE;
+        let _ = &Self::BOUNDED_ASSOC_TYPE; //~ ERROR interior mutable
+    }
+}
+
+fn main() {
+    u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability
+    assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability
+}
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.stderr b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.stderr
new file mode 100644 (file)
index 0000000..8f26403
--- /dev/null
@@ -0,0 +1,123 @@
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/traits.rs:15:18
+   |
+LL |         let _ = &Self::ATOMIC; //~ ERROR interior mutable
+   |                  ^^^^^^^^^^^^
+   |
+   = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings`
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/traits.rs:26:18
+   |
+LL |         let _ = &Self::ATOMIC; //~ ERROR interior mutable
+   |                  ^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/traits.rs:51:18
+   |
+LL |         let _ = &Self::TO_BE_CONCRETE; //~ ERROR interior mutable
+   |                  ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/traits.rs:86:18
+   |
+LL |         let _ = &Self::TO_BE_UNFROZEN; //~ ERROR interior mutable
+   |                  ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/traits.rs:87:18
+   |
+LL |         let _ = &Self::WRAPPED_TO_BE_UNFROZEN; //~ ERROR interior mutable
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/traits.rs:109:18
+   |
+LL |         let _ = &Self::BOUNDED; //~ ERROR interior mutable
+   |                  ^^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/traits.rs:122:18
+   |
+LL |         let _ = &Self::BOUNDED; //~ ERROR interior mutable
+   |                  ^^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/traits.rs:151:18
+   |
+LL |         let _ = &Self::SELF; //~ ERROR interior mutable
+   |                  ^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/traits.rs:152:18
+   |
+LL |         let _ = &Self::WRAPPED_SELF; //~ ERROR interior mutable
+   |                  ^^^^^^^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/traits.rs:162:18
+   |
+LL |         let _ = &Self::INDIRECT; //~ ERROR interior mutable
+   |                  ^^^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/traits.rs:172:18
+   |
+LL |         let _ = &Self::INDIRECT; //~ ERROR interior mutable
+   |                  ^^^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/traits.rs:191:18
+   |
+LL |         let _ = &Self::ATOMIC; //~ ERROR interior mutable
+   |                  ^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/traits.rs:195:18
+   |
+LL |         let _ = &Self::BOUNDED_ASSOC_TYPE; //~ ERROR interior mutable
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/traits.rs:200:5
+   |
+LL |     u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability
+   |     ^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+  --> $DIR/traits.rs:201:16
+   |
+LL |     assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability
+   |                ^^^^^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: aborting due to 15 previous errors
+
index bb03ce4035533a4b19a8bb0cb99e8cfb1b43fe47..0eb7bb12b3546e85ad492460d28736886f1bd02b 100644 (file)
@@ -19,7 +19,7 @@ LL |         loop {}
    |         ^^^^^^^
    |
    = note: `-D clippy::empty-loop` implied by `-D warnings`
-   = help: You should either use `panic!()` or add `std::thread::sleep(..);` to the loop body.
+   = help: you should either use `panic!()` or add `std::thread::sleep(..);` to the loop body
 
 error: aborting due to 2 previous errors
 
diff --git a/src/tools/clippy/tests/ui/crashes/ice-6332.rs b/src/tools/clippy/tests/ui/crashes/ice-6332.rs
new file mode 100644 (file)
index 0000000..9dc92aa
--- /dev/null
@@ -0,0 +1,11 @@
+fn cmark_check() {
+    let mut link_err = false;
+    macro_rules! cmark_error {
+        ($bad:expr) => {
+            *$bad = true;
+        };
+    }
+    cmark_error!(&mut link_err);
+}
+
+pub fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/implements-trait.rs b/src/tools/clippy/tests/ui/crashes/implements-trait.rs
new file mode 100644 (file)
index 0000000..4502b01
--- /dev/null
@@ -0,0 +1,5 @@
+#[allow(clippy::needless_borrowed_reference)]
+fn main() {
+    let mut v = Vec::<String>::new();
+    let _ = v.iter_mut().filter(|&ref a| a.is_empty());
+}
diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const.rs b/src/tools/clippy/tests/ui/declare_interior_mutable_const.rs
deleted file mode 100644 (file)
index 3afcdca..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-#![warn(clippy::declare_interior_mutable_const)]
-
-use std::borrow::Cow;
-use std::cell::Cell;
-use std::fmt::Display;
-use std::sync::atomic::AtomicUsize;
-use std::sync::Once;
-
-const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable
-const CELL: Cell<usize> = Cell::new(6); //~ ERROR interior mutable
-const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec<AtomicUsize>, u8) = ([ATOMIC], Vec::new(), 7);
-//~^ ERROR interior mutable
-
-macro_rules! declare_const {
-    ($name:ident: $ty:ty = $e:expr) => {
-        const $name: $ty = $e;
-    };
-}
-declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable
-
-// const ATOMIC_REF: &AtomicUsize = &AtomicUsize::new(7); // This will simply trigger E0492.
-
-const INTEGER: u8 = 8;
-const STRING: String = String::new();
-const STR: &str = "012345";
-const COW: Cow<str> = Cow::Borrowed("abcdef");
-//^ note: a const item of Cow is used in the `postgres` package.
-
-const NO_ANN: &dyn Display = &70;
-
-static STATIC_TUPLE: (AtomicUsize, String) = (ATOMIC, STRING);
-//^ there should be no lints on this line
-
-#[allow(clippy::declare_interior_mutable_const)]
-const ONCE_INIT: Once = Once::new();
-
-// a constant whose type is a concrete type should be linted at the definition site.
-trait ConcreteTypes {
-    const ATOMIC: AtomicUsize; //~ ERROR interior mutable
-    const INTEGER: u64;
-    const STRING: String;
-    declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); //~ ERROR interior mutable
-}
-
-impl ConcreteTypes for u64 {
-    const ATOMIC: AtomicUsize = AtomicUsize::new(9);
-    const INTEGER: u64 = 10;
-    const STRING: String = String::new();
-}
-
-// a helper trait used below
-trait ConstDefault {
-    const DEFAULT: Self;
-}
-
-// a constant whose type is a generic type should be linted at the implementation site.
-trait GenericTypes<T, U> {
-    const TO_REMAIN_GENERIC: T;
-    const TO_BE_CONCRETE: U;
-
-    const HAVING_DEFAULT: T = Self::TO_REMAIN_GENERIC;
-    declare_const!(IN_MACRO: T = Self::TO_REMAIN_GENERIC);
-}
-
-impl<T: ConstDefault> GenericTypes<T, AtomicUsize> for u64 {
-    const TO_REMAIN_GENERIC: T = T::DEFAULT;
-    const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11); //~ ERROR interior mutable
-}
-
-// a helper type used below
-struct Wrapper<T>(T);
-
-// a constant whose type is an associated type should be linted at the implementation site, too.
-trait AssocTypes {
-    type ToBeFrozen;
-    type ToBeUnfrozen;
-    type ToBeGenericParam;
-
-    const TO_BE_FROZEN: Self::ToBeFrozen;
-    const TO_BE_UNFROZEN: Self::ToBeUnfrozen;
-    const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen>;
-    // to ensure it can handle things when a generic type remains after normalization.
-    const WRAPPED_TO_BE_GENERIC_PARAM: Wrapper<Self::ToBeGenericParam>;
-}
-
-impl<T: ConstDefault> AssocTypes for Vec<T> {
-    type ToBeFrozen = u16;
-    type ToBeUnfrozen = AtomicUsize;
-    type ToBeGenericParam = T;
-
-    const TO_BE_FROZEN: Self::ToBeFrozen = 12;
-    const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13); //~ ERROR interior mutable
-    const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen> = Wrapper(AtomicUsize::new(14)); //~ ERROR interior mutable
-    const WRAPPED_TO_BE_GENERIC_PARAM: Wrapper<Self::ToBeGenericParam> = Wrapper(T::DEFAULT);
-}
-
-// a helper trait used below
-trait AssocTypesHelper {
-    type NotToBeBounded;
-    type ToBeBounded;
-
-    const NOT_TO_BE_BOUNDED: Self::NotToBeBounded;
-}
-
-// a constant whose type is an assoc type originated from a generic param bounded at the definition
-// site should be linted at there.
-trait AssocTypesFromGenericParam<T>
-where
-    T: AssocTypesHelper<ToBeBounded = AtomicUsize>,
-{
-    const NOT_BOUNDED: T::NotToBeBounded;
-    const BOUNDED: T::ToBeBounded; //~ ERROR interior mutable
-}
-
-impl<T> AssocTypesFromGenericParam<T> for u64
-where
-    T: AssocTypesHelper<ToBeBounded = AtomicUsize>,
-{
-    // an associated type could remain unknown in a trait impl.
-    const NOT_BOUNDED: T::NotToBeBounded = T::NOT_TO_BE_BOUNDED;
-    const BOUNDED: T::ToBeBounded = AtomicUsize::new(15);
-}
-
-// a constant whose type is `Self` should be linted at the implementation site as well.
-// (`Option` requires `Sized` bound.)
-trait SelfType: Sized {
-    const SELF: Self;
-    // this was the one in the original issue (#5050).
-    const WRAPPED_SELF: Option<Self>;
-}
-
-impl SelfType for u64 {
-    const SELF: Self = 16;
-    const WRAPPED_SELF: Option<Self> = Some(20);
-}
-
-impl SelfType for AtomicUsize {
-    // this (interior mutable `Self` const) exists in `parking_lot`.
-    // `const_trait_impl` will replace it in the future, hopefully.
-    const SELF: Self = AtomicUsize::new(17); //~ ERROR interior mutable
-    const WRAPPED_SELF: Option<Self> = Some(AtomicUsize::new(21)); //~ ERROR interior mutable
-}
-
-// Even though a constant contains a generic type, if it also have a interior mutable type,
-// it should be linted at the definition site.
-trait BothOfCellAndGeneric<T> {
-    // this is a false negative in the current implementation.
-    const DIRECT: Cell<T>;
-    const INDIRECT: Cell<*const T>; //~ ERROR interior mutable
-}
-
-impl<T: ConstDefault> BothOfCellAndGeneric<T> for u64 {
-    const DIRECT: Cell<T> = Cell::new(T::DEFAULT);
-    const INDIRECT: Cell<*const T> = Cell::new(std::ptr::null());
-}
-
-struct Local<T>(T);
-
-// a constant in an inherent impl are essentially the same as a normal const item
-// except there can be a generic or associated type.
-impl<T> Local<T>
-where
-    T: ConstDefault + AssocTypesHelper<ToBeBounded = AtomicUsize>,
-{
-    const ATOMIC: AtomicUsize = AtomicUsize::new(18); //~ ERROR interior mutable
-    const COW: Cow<'static, str> = Cow::Borrowed("tuvwxy");
-
-    const GENERIC_TYPE: T = T::DEFAULT;
-
-    const ASSOC_TYPE: T::NotToBeBounded = T::NOT_TO_BE_BOUNDED;
-    const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); //~ ERROR interior mutable
-}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const.stderr b/src/tools/clippy/tests/ui/declare_interior_mutable_const.stderr
deleted file mode 100644 (file)
index 5cb10be..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-error: a `const` item should never be interior mutable
-  --> $DIR/declare_interior_mutable_const.rs:9:1
-   |
-LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable
-   | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
-   | make this a static item (maybe with lazy_static)
-   |
-   = note: `-D clippy::declare-interior-mutable-const` implied by `-D warnings`
-
-error: a `const` item should never be interior mutable
-  --> $DIR/declare_interior_mutable_const.rs:10:1
-   |
-LL | const CELL: Cell<usize> = Cell::new(6); //~ ERROR interior mutable
-   | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
-   | make this a static item (maybe with lazy_static)
-
-error: a `const` item should never be interior mutable
-  --> $DIR/declare_interior_mutable_const.rs:11:1
-   |
-LL | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec<AtomicUsize>, u8) = ([ATOMIC], Vec::new(), 7);
-   | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
-   | make this a static item (maybe with lazy_static)
-
-error: a `const` item should never be interior mutable
-  --> $DIR/declare_interior_mutable_const.rs:16:9
-   |
-LL |         const $name: $ty = $e;
-   |         ^^^^^^^^^^^^^^^^^^^^^^
-...
-LL | declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable
-   | ------------------------------------------ in this macro invocation
-   |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: a `const` item should never be interior mutable
-  --> $DIR/declare_interior_mutable_const.rs:39:5
-   |
-LL |     const ATOMIC: AtomicUsize; //~ ERROR interior mutable
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: a `const` item should never be interior mutable
-  --> $DIR/declare_interior_mutable_const.rs:16:9
-   |
-LL |         const $name: $ty = $e;
-   |         ^^^^^^^^^^^^^^^^^^^^^^
-...
-LL |     declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); //~ ERROR interior mutable
-   |     ----------------------------------------------------------- in this macro invocation
-   |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: a `const` item should never be interior mutable
-  --> $DIR/declare_interior_mutable_const.rs:67:5
-   |
-LL |     const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11); //~ ERROR interior mutable
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: a `const` item should never be interior mutable
-  --> $DIR/declare_interior_mutable_const.rs:92:5
-   |
-LL |     const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13); //~ ERROR interior mutable
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: a `const` item should never be interior mutable
-  --> $DIR/declare_interior_mutable_const.rs:93:5
-   |
-LL |     const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen> = Wrapper(AtomicUsize::new(14)); //~ ERROR interior mutable
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: a `const` item should never be interior mutable
-  --> $DIR/declare_interior_mutable_const.rs:112:5
-   |
-LL |     const BOUNDED: T::ToBeBounded; //~ ERROR interior mutable
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: a `const` item should never be interior mutable
-  --> $DIR/declare_interior_mutable_const.rs:140:5
-   |
-LL |     const SELF: Self = AtomicUsize::new(17); //~ ERROR interior mutable
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: a `const` item should never be interior mutable
-  --> $DIR/declare_interior_mutable_const.rs:141:5
-   |
-LL |     const WRAPPED_SELF: Option<Self> = Some(AtomicUsize::new(21)); //~ ERROR interior mutable
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: a `const` item should never be interior mutable
-  --> $DIR/declare_interior_mutable_const.rs:149:5
-   |
-LL |     const INDIRECT: Cell<*const T>; //~ ERROR interior mutable
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: a `const` item should never be interior mutable
-  --> $DIR/declare_interior_mutable_const.rs:165:5
-   |
-LL |     const ATOMIC: AtomicUsize = AtomicUsize::new(18); //~ ERROR interior mutable
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: a `const` item should never be interior mutable
-  --> $DIR/declare_interior_mutable_const.rs:171:5
-   |
-LL |     const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); //~ ERROR interior mutable
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 15 previous errors
-
diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/enums.rs b/src/tools/clippy/tests/ui/declare_interior_mutable_const/enums.rs
new file mode 100644 (file)
index 0000000..f445186
--- /dev/null
@@ -0,0 +1,123 @@
+#![warn(clippy::declare_interior_mutable_const)]
+
+use std::cell::Cell;
+use std::sync::atomic::AtomicUsize;
+
+enum OptionalCell {
+    Unfrozen(Cell<bool>),
+    Frozen,
+}
+
+// a constant with enums should be linted only when the used variant is unfrozen (#3962).
+const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true)); //~ ERROR interior mutable
+const FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen;
+
+const fn unfrozen_variant() -> OptionalCell {
+    OptionalCell::Unfrozen(Cell::new(false))
+}
+
+const fn frozen_variant() -> OptionalCell {
+    OptionalCell::Frozen
+}
+
+const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant(); //~ ERROR interior mutable
+const FROZEN_VARIANT_FROM_FN: OptionalCell = frozen_variant();
+
+enum NestedInnermost {
+    Unfrozen(AtomicUsize),
+    Frozen,
+}
+
+struct NestedInner {
+    inner: NestedInnermost,
+}
+
+enum NestedOuter {
+    NestedInner(NestedInner),
+    NotNested(usize),
+}
+
+struct NestedOutermost {
+    outer: NestedOuter,
+}
+
+// a constant with enums should be linted according to its value, no matter how structs involve.
+const NESTED_UNFROZEN_VARIANT: NestedOutermost = NestedOutermost {
+    outer: NestedOuter::NestedInner(NestedInner {
+        inner: NestedInnermost::Unfrozen(AtomicUsize::new(2)),
+    }),
+}; //~ ERROR interior mutable
+const NESTED_FROZEN_VARIANT: NestedOutermost = NestedOutermost {
+    outer: NestedOuter::NestedInner(NestedInner {
+        inner: NestedInnermost::Frozen,
+    }),
+};
+
+trait AssocConsts {
+    // When there's no default value, lint it only according to its type.
+    // Further details are on the corresponding code (`NonCopyConst::check_trait_item`).
+    const TO_BE_UNFROZEN_VARIANT: OptionalCell; //~ ERROR interior mutable
+    const TO_BE_FROZEN_VARIANT: OptionalCell; //~ ERROR interior mutable
+
+    // Lint default values accordingly.
+    const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false)); //~ ERROR interior mutable
+    const DEFAULTED_ON_FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen;
+}
+
+// The lint doesn't trigger for an assoc constant in a trait impl with an unfrozen type even if it
+// has enums. Further details are on the corresponding code in 'NonCopyConst::check_impl_item'.
+impl AssocConsts for u64 {
+    const TO_BE_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false));
+    const TO_BE_FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen;
+
+    // even if this sets an unfrozen variant, the lint ignores it.
+    const DEFAULTED_ON_FROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false));
+}
+
+// At first, I thought I'd need to check every patterns in `trait.rs`; but, what matters
+// here are values; and I think substituted generics at definitions won't appear in MIR.
+trait AssocTypes {
+    type ToBeUnfrozen;
+
+    const TO_BE_UNFROZEN_VARIANT: Option<Self::ToBeUnfrozen>;
+    const TO_BE_FROZEN_VARIANT: Option<Self::ToBeUnfrozen>;
+}
+
+impl AssocTypes for u64 {
+    type ToBeUnfrozen = AtomicUsize;
+
+    const TO_BE_UNFROZEN_VARIANT: Option<Self::ToBeUnfrozen> = Some(Self::ToBeUnfrozen::new(4)); //~ ERROR interior mutable
+    const TO_BE_FROZEN_VARIANT: Option<Self::ToBeUnfrozen> = None;
+}
+
+// Use raw pointers since direct generics have a false negative at the type level.
+enum BothOfCellAndGeneric<T> {
+    Unfrozen(Cell<*const T>),
+    Generic(*const T),
+    Frozen(usize),
+}
+
+impl<T> BothOfCellAndGeneric<T> {
+    const UNFROZEN_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR interior mutable
+
+    // This is a false positive. The argument about this is on `is_value_unfrozen_raw`
+    const GENERIC_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mutable
+
+    const FROZEN_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Frozen(5);
+
+    // This is what is likely to be a false negative when one tries to fix
+    // the `GENERIC_VARIANT` false positive.
+    const NO_ENUM: Cell<*const T> = Cell::new(std::ptr::null()); //~ ERROR interior mutable
+}
+
+// associated types here is basically the same as the one above.
+trait BothOfCellAndGenericWithAssocType {
+    type AssocType;
+
+    const UNFROZEN_VARIANT: BothOfCellAndGeneric<Self::AssocType> =
+        BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR interior mutable
+    const GENERIC_VARIANT: BothOfCellAndGeneric<Self::AssocType> = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mutable
+    const FROZEN_VARIANT: BothOfCellAndGeneric<Self::AssocType> = BothOfCellAndGeneric::Frozen(5);
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/enums.stderr b/src/tools/clippy/tests/ui/declare_interior_mutable_const/enums.stderr
new file mode 100644 (file)
index 0000000..84198d5
--- /dev/null
@@ -0,0 +1,89 @@
+error: a `const` item should never be interior mutable
+  --> $DIR/enums.rs:12:1
+   |
+LL | const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true)); //~ ERROR interior mutable
+   | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | make this a static item (maybe with lazy_static)
+   |
+   = note: `-D clippy::declare-interior-mutable-const` implied by `-D warnings`
+
+error: a `const` item should never be interior mutable
+  --> $DIR/enums.rs:23:1
+   |
+LL | const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant(); //~ ERROR interior mutable
+   | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | make this a static item (maybe with lazy_static)
+
+error: a `const` item should never be interior mutable
+  --> $DIR/enums.rs:45:1
+   |
+LL |   const NESTED_UNFROZEN_VARIANT: NestedOutermost = NestedOutermost {
+   |   ^----
+   |   |
+   |  _make this a static item (maybe with lazy_static)
+   | |
+LL | |     outer: NestedOuter::NestedInner(NestedInner {
+LL | |         inner: NestedInnermost::Unfrozen(AtomicUsize::new(2)),
+LL | |     }),
+LL | | }; //~ ERROR interior mutable
+   | |__^
+
+error: a `const` item should never be interior mutable
+  --> $DIR/enums.rs:59:5
+   |
+LL |     const TO_BE_UNFROZEN_VARIANT: OptionalCell; //~ ERROR interior mutable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: a `const` item should never be interior mutable
+  --> $DIR/enums.rs:60:5
+   |
+LL |     const TO_BE_FROZEN_VARIANT: OptionalCell; //~ ERROR interior mutable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: a `const` item should never be interior mutable
+  --> $DIR/enums.rs:63:5
+   |
+LL |     const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false)); //~ ERROR interior mutable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: a `const` item should never be interior mutable
+  --> $DIR/enums.rs:89:5
+   |
+LL |     const TO_BE_UNFROZEN_VARIANT: Option<Self::ToBeUnfrozen> = Some(Self::ToBeUnfrozen::new(4)); //~ ERROR interior mutable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: a `const` item should never be interior mutable
+  --> $DIR/enums.rs:101:5
+   |
+LL |     const UNFROZEN_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR interior mut...
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: a `const` item should never be interior mutable
+  --> $DIR/enums.rs:104:5
+   |
+LL |     const GENERIC_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mutable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: a `const` item should never be interior mutable
+  --> $DIR/enums.rs:110:5
+   |
+LL |     const NO_ENUM: Cell<*const T> = Cell::new(std::ptr::null()); //~ ERROR interior mutable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: a `const` item should never be interior mutable
+  --> $DIR/enums.rs:117:5
+   |
+LL | /     const UNFROZEN_VARIANT: BothOfCellAndGeneric<Self::AssocType> =
+LL | |         BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR interior mutable
+   | |____________________________________________________________________^
+
+error: a `const` item should never be interior mutable
+  --> $DIR/enums.rs:119:5
+   |
+LL |     const GENERIC_VARIANT: BothOfCellAndGeneric<Self::AssocType> = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mu...
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
+
diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs b/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs
new file mode 100644 (file)
index 0000000..48c5e95
--- /dev/null
@@ -0,0 +1,34 @@
+#![warn(clippy::declare_interior_mutable_const)]
+
+use std::borrow::Cow;
+use std::cell::Cell;
+use std::fmt::Display;
+use std::sync::atomic::AtomicUsize;
+use std::sync::Once;
+
+const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable
+const CELL: Cell<usize> = Cell::new(6); //~ ERROR interior mutable
+const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec<AtomicUsize>, u8) = ([ATOMIC], Vec::new(), 7);
+//~^ ERROR interior mutable
+
+macro_rules! declare_const {
+    ($name:ident: $ty:ty = $e:expr) => {
+        const $name: $ty = $e;
+    };
+}
+declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable
+
+// const ATOMIC_REF: &AtomicUsize = &AtomicUsize::new(7); // This will simply trigger E0492.
+
+const INTEGER: u8 = 8;
+const STRING: String = String::new();
+const STR: &str = "012345";
+const COW: Cow<str> = Cow::Borrowed("abcdef");
+//^ note: a const item of Cow is used in the `postgres` package.
+
+const NO_ANN: &dyn Display = &70;
+
+static STATIC_TUPLE: (AtomicUsize, String) = (ATOMIC, STRING);
+//^ there should be no lints on this line
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.stderr b/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.stderr
new file mode 100644 (file)
index 0000000..6153c96
--- /dev/null
@@ -0,0 +1,39 @@
+error: a `const` item should never be interior mutable
+  --> $DIR/others.rs:9:1
+   |
+LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable
+   | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | make this a static item (maybe with lazy_static)
+   |
+   = note: `-D clippy::declare-interior-mutable-const` implied by `-D warnings`
+
+error: a `const` item should never be interior mutable
+  --> $DIR/others.rs:10:1
+   |
+LL | const CELL: Cell<usize> = Cell::new(6); //~ ERROR interior mutable
+   | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | make this a static item (maybe with lazy_static)
+
+error: a `const` item should never be interior mutable
+  --> $DIR/others.rs:11:1
+   |
+LL | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec<AtomicUsize>, u8) = ([ATOMIC], Vec::new(), 7);
+   | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | make this a static item (maybe with lazy_static)
+
+error: a `const` item should never be interior mutable
+  --> $DIR/others.rs:16:9
+   |
+LL |         const $name: $ty = $e;
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable
+   | ------------------------------------------ in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.rs b/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.rs
new file mode 100644 (file)
index 0000000..535147c
--- /dev/null
@@ -0,0 +1,150 @@
+#![warn(clippy::declare_interior_mutable_const)]
+
+use std::borrow::Cow;
+use std::cell::Cell;
+use std::sync::atomic::AtomicUsize;
+
+macro_rules! declare_const {
+    ($name:ident: $ty:ty = $e:expr) => {
+        const $name: $ty = $e;
+    };
+}
+
+// a constant whose type is a concrete type should be linted at the definition site.
+trait ConcreteTypes {
+    const ATOMIC: AtomicUsize; //~ ERROR interior mutable
+    const INTEGER: u64;
+    const STRING: String;
+    declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); //~ ERROR interior mutable
+}
+
+impl ConcreteTypes for u64 {
+    const ATOMIC: AtomicUsize = AtomicUsize::new(9);
+    const INTEGER: u64 = 10;
+    const STRING: String = String::new();
+}
+
+// a helper trait used below
+trait ConstDefault {
+    const DEFAULT: Self;
+}
+
+// a constant whose type is a generic type should be linted at the implementation site.
+trait GenericTypes<T, U> {
+    const TO_REMAIN_GENERIC: T;
+    const TO_BE_CONCRETE: U;
+
+    const HAVING_DEFAULT: T = Self::TO_REMAIN_GENERIC;
+    declare_const!(IN_MACRO: T = Self::TO_REMAIN_GENERIC);
+}
+
+impl<T: ConstDefault> GenericTypes<T, AtomicUsize> for u64 {
+    const TO_REMAIN_GENERIC: T = T::DEFAULT;
+    const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11); //~ ERROR interior mutable
+}
+
+// a helper type used below
+struct Wrapper<T>(T);
+
+// a constant whose type is an associated type should be linted at the implementation site, too.
+trait AssocTypes {
+    type ToBeFrozen;
+    type ToBeUnfrozen;
+    type ToBeGenericParam;
+
+    const TO_BE_FROZEN: Self::ToBeFrozen;
+    const TO_BE_UNFROZEN: Self::ToBeUnfrozen;
+    const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen>;
+    // to ensure it can handle things when a generic type remains after normalization.
+    const WRAPPED_TO_BE_GENERIC_PARAM: Wrapper<Self::ToBeGenericParam>;
+}
+
+impl<T: ConstDefault> AssocTypes for Vec<T> {
+    type ToBeFrozen = u16;
+    type ToBeUnfrozen = AtomicUsize;
+    type ToBeGenericParam = T;
+
+    const TO_BE_FROZEN: Self::ToBeFrozen = 12;
+    const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13); //~ ERROR interior mutable
+    const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen> = Wrapper(AtomicUsize::new(14)); //~ ERROR interior mutable
+    const WRAPPED_TO_BE_GENERIC_PARAM: Wrapper<Self::ToBeGenericParam> = Wrapper(T::DEFAULT);
+}
+
+// a helper trait used below
+trait AssocTypesHelper {
+    type NotToBeBounded;
+    type ToBeBounded;
+
+    const NOT_TO_BE_BOUNDED: Self::NotToBeBounded;
+}
+
+// a constant whose type is an assoc type originated from a generic param bounded at the definition
+// site should be linted at there.
+trait AssocTypesFromGenericParam<T>
+where
+    T: AssocTypesHelper<ToBeBounded = AtomicUsize>,
+{
+    const NOT_BOUNDED: T::NotToBeBounded;
+    const BOUNDED: T::ToBeBounded; //~ ERROR interior mutable
+}
+
+impl<T> AssocTypesFromGenericParam<T> for u64
+where
+    T: AssocTypesHelper<ToBeBounded = AtomicUsize>,
+{
+    // an associated type could remain unknown in a trait impl.
+    const NOT_BOUNDED: T::NotToBeBounded = T::NOT_TO_BE_BOUNDED;
+    const BOUNDED: T::ToBeBounded = AtomicUsize::new(15);
+}
+
+// a constant whose type is `Self` should be linted at the implementation site as well.
+// (`Option` requires `Sized` bound.)
+trait SelfType: Sized {
+    const SELF: Self;
+    // this was the one in the original issue (#5050).
+    const WRAPPED_SELF: Option<Self>;
+}
+
+impl SelfType for u64 {
+    const SELF: Self = 16;
+    const WRAPPED_SELF: Option<Self> = Some(20);
+}
+
+impl SelfType for AtomicUsize {
+    // this (interior mutable `Self` const) exists in `parking_lot`.
+    // `const_trait_impl` will replace it in the future, hopefully.
+    const SELF: Self = AtomicUsize::new(17); //~ ERROR interior mutable
+    const WRAPPED_SELF: Option<Self> = Some(AtomicUsize::new(21)); //~ ERROR interior mutable
+}
+
+// Even though a constant contains a generic type, if it also have a interior mutable type,
+// it should be linted at the definition site.
+trait BothOfCellAndGeneric<T> {
+    // this is a false negative in the current implementation.
+    const DIRECT: Cell<T>;
+    const INDIRECT: Cell<*const T>; //~ ERROR interior mutable
+}
+
+impl<T: ConstDefault> BothOfCellAndGeneric<T> for u64 {
+    const DIRECT: Cell<T> = Cell::new(T::DEFAULT);
+    const INDIRECT: Cell<*const T> = Cell::new(std::ptr::null());
+}
+
+struct Local<T>(T);
+
+// a constant in an inherent impl are essentially the same as a normal const item
+// except there can be a generic or associated type.
+impl<T> Local<T>
+where
+    T: ConstDefault + AssocTypesHelper<ToBeBounded = AtomicUsize>,
+{
+    const ATOMIC: AtomicUsize = AtomicUsize::new(18); //~ ERROR interior mutable
+    const COW: Cow<'static, str> = Cow::Borrowed("tuvwxy");
+
+    const GENERIC_TYPE: T = T::DEFAULT;
+
+    const ASSOC_TYPE: T::NotToBeBounded = T::NOT_TO_BE_BOUNDED;
+    const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); //~ ERROR interior mutable
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.stderr b/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.stderr
new file mode 100644 (file)
index 0000000..bb77f39
--- /dev/null
@@ -0,0 +1,75 @@
+error: a `const` item should never be interior mutable
+  --> $DIR/traits.rs:15:5
+   |
+LL |     const ATOMIC: AtomicUsize; //~ ERROR interior mutable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::declare-interior-mutable-const` implied by `-D warnings`
+
+error: a `const` item should never be interior mutable
+  --> $DIR/traits.rs:9:9
+   |
+LL |         const $name: $ty = $e;
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); //~ ERROR interior mutable
+   |     ----------------------------------------------------------- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: a `const` item should never be interior mutable
+  --> $DIR/traits.rs:43:5
+   |
+LL |     const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11); //~ ERROR interior mutable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: a `const` item should never be interior mutable
+  --> $DIR/traits.rs:68:5
+   |
+LL |     const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13); //~ ERROR interior mutable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: a `const` item should never be interior mutable
+  --> $DIR/traits.rs:69:5
+   |
+LL |     const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen> = Wrapper(AtomicUsize::new(14)); //~ ERROR interior mutable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: a `const` item should never be interior mutable
+  --> $DIR/traits.rs:88:5
+   |
+LL |     const BOUNDED: T::ToBeBounded; //~ ERROR interior mutable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: a `const` item should never be interior mutable
+  --> $DIR/traits.rs:116:5
+   |
+LL |     const SELF: Self = AtomicUsize::new(17); //~ ERROR interior mutable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: a `const` item should never be interior mutable
+  --> $DIR/traits.rs:117:5
+   |
+LL |     const WRAPPED_SELF: Option<Self> = Some(AtomicUsize::new(21)); //~ ERROR interior mutable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: a `const` item should never be interior mutable
+  --> $DIR/traits.rs:125:5
+   |
+LL |     const INDIRECT: Cell<*const T>; //~ ERROR interior mutable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: a `const` item should never be interior mutable
+  --> $DIR/traits.rs:141:5
+   |
+LL |     const ATOMIC: AtomicUsize = AtomicUsize::new(18); //~ ERROR interior mutable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: a `const` item should never be interior mutable
+  --> $DIR/traits.rs:147:5
+   |
+LL |     const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); //~ ERROR interior mutable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 11 previous errors
+
index 56755596c97fc646faee8d75531021c79660b22d..4cbc5630d759d76d6c5e631e31871a3cbfebb2ac 100644 (file)
@@ -10,5 +10,6 @@
 #[warn(clippy::regex_macro)]
 #[warn(clippy::drop_bounds)]
 #[warn(clippy::temporary_cstring_as_ptr)]
+#[warn(clippy::panic_params)]
 
 fn main() {}
index 37b726fc00f1c414e76421db7b6bb12f8918262d..a348d01d734fed006f29ecd2e7dba3b96e8f5f1d 100644 (file)
@@ -72,11 +72,17 @@ error: lint `clippy::temporary_cstring_as_ptr` has been removed: `this lint has
 LL | #[warn(clippy::temporary_cstring_as_ptr)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: lint `clippy::panic_params` has been removed: `this lint has been uplifted to rustc and is now called `panic_fmt``
+  --> $DIR/deprecated.rs:13:8
+   |
+LL | #[warn(clippy::panic_params)]
+   |        ^^^^^^^^^^^^^^^^^^^^
+
 error: lint `clippy::str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon`
   --> $DIR/deprecated.rs:1:8
    |
 LL | #[warn(clippy::str_to_string)]
    |        ^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 13 previous errors
+error: aborting due to 14 previous errors
 
index 9e5b51d6d5e6d5da7344e0bdc33bacb163882010..0795900558b695824bdead9959b7201313b13034 100644 (file)
@@ -1,4 +1,5 @@
 // run-rustfix
+#![warn(clippy::deref_addrof)]
 
 fn get_number() -> usize {
     10
@@ -10,7 +11,6 @@ fn get_reference(n: &usize) -> &usize {
 
 #[allow(clippy::many_single_char_names, clippy::double_parens)]
 #[allow(unused_variables, unused_parens)]
-#[warn(clippy::deref_addrof)]
 fn main() {
     let a = 10;
     let aref = &a;
@@ -37,3 +37,27 @@ fn main() {
 
     let b = *aref;
 }
+
+#[rustfmt::skip]
+macro_rules! m {
+    ($visitor: expr) => {
+        $visitor
+    };
+}
+
+#[rustfmt::skip]
+macro_rules! m_mut {
+    ($visitor: expr) => {
+        $visitor
+    };
+}
+
+pub struct S;
+impl S {
+    pub fn f(&self) -> &Self {
+        m!(self)
+    }
+    pub fn f_mut(&self) -> &Self {
+        m_mut!(self)
+    }
+}
index 5641a73cbc1cb1b73e766dbbfb8de1d515a12e6d..60c4318601bc881799a07d7e6e7ffdcbd3886957 100644 (file)
@@ -1,4 +1,5 @@
 // run-rustfix
+#![warn(clippy::deref_addrof)]
 
 fn get_number() -> usize {
     10
@@ -10,7 +11,6 @@ fn get_reference(n: &usize) -> &usize {
 
 #[allow(clippy::many_single_char_names, clippy::double_parens)]
 #[allow(unused_variables, unused_parens)]
-#[warn(clippy::deref_addrof)]
 fn main() {
     let a = 10;
     let aref = &a;
@@ -37,3 +37,27 @@ fn main() {
 
     let b = **&aref;
 }
+
+#[rustfmt::skip]
+macro_rules! m {
+    ($visitor: expr) => {
+        *& $visitor
+    };
+}
+
+#[rustfmt::skip]
+macro_rules! m_mut {
+    ($visitor: expr) => {
+        *& mut $visitor
+    };
+}
+
+pub struct S;
+impl S {
+    pub fn f(&self) -> &Self {
+        m!(self)
+    }
+    pub fn f_mut(&self) -> &Self {
+        m_mut!(self)
+    }
+}
index bc51719e8a7a0e6bb9dfd4a4c4137208b59e8891..e85b30fa56eb884ff719241f62e659a57b3cc7fd 100644 (file)
@@ -48,5 +48,27 @@ error: immediately dereferencing a reference
 LL |     let b = **&aref;
    |              ^^^^^^ help: try this: `aref`
 
-error: aborting due to 8 previous errors
+error: immediately dereferencing a reference
+  --> $DIR/deref_addrof.rs:44:9
+   |
+LL |         *& $visitor
+   |         ^^^^^^^^^^^ help: try this: `$visitor`
+...
+LL |         m!(self)
+   |         -------- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: immediately dereferencing a reference
+  --> $DIR/deref_addrof.rs:51:9
+   |
+LL |         *& mut $visitor
+   |         ^^^^^^^^^^^^^^^ help: try this: `$visitor`
+...
+LL |         m_mut!(self)
+   |         ------------ in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 10 previous errors
 
index b82dc518a3ba60520d21f016e2b213ddb430bed4..6f12d36d777dcbae0fbbae36f393e16f514528ef 100644 (file)
@@ -1,4 +1,5 @@
 #![warn(clippy::derive_ord_xor_partial_ord)]
+#![allow(clippy::unnecessary_wraps)]
 
 use std::cmp::Ordering;
 
index 66bc4d42ce8c3c85e80d571bcbb658884a92cbe3..97b46a4aa89828c3dda6d9ed82f65c8f288cf835 100644 (file)
@@ -1,12 +1,12 @@
 error: you are deriving `Ord` but have implemented `PartialOrd` explicitly
-  --> $DIR/derive_ord_xor_partial_ord.rs:20:10
+  --> $DIR/derive_ord_xor_partial_ord.rs:21:10
    |
 LL | #[derive(Ord, PartialEq, Eq)]
    |          ^^^
    |
    = note: `-D clippy::derive-ord-xor-partial-ord` implied by `-D warnings`
 note: `PartialOrd` implemented here
-  --> $DIR/derive_ord_xor_partial_ord.rs:23:1
+  --> $DIR/derive_ord_xor_partial_ord.rs:24:1
    |
 LL | / impl PartialOrd for DeriveOrd {
 LL | |     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
@@ -17,13 +17,13 @@ LL | | }
    = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: you are deriving `Ord` but have implemented `PartialOrd` explicitly
-  --> $DIR/derive_ord_xor_partial_ord.rs:29:10
+  --> $DIR/derive_ord_xor_partial_ord.rs:30:10
    |
 LL | #[derive(Ord, PartialEq, Eq)]
    |          ^^^
    |
 note: `PartialOrd` implemented here
-  --> $DIR/derive_ord_xor_partial_ord.rs:32:1
+  --> $DIR/derive_ord_xor_partial_ord.rs:33:1
    |
 LL | / impl PartialOrd<DeriveOrdWithExplicitTypeVariable> for DeriveOrdWithExplicitTypeVariable {
 LL | |     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
@@ -34,7 +34,7 @@ LL | | }
    = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: you are implementing `Ord` explicitly but have derived `PartialOrd`
-  --> $DIR/derive_ord_xor_partial_ord.rs:41:1
+  --> $DIR/derive_ord_xor_partial_ord.rs:42:1
    |
 LL | / impl std::cmp::Ord for DerivePartialOrd {
 LL | |     fn cmp(&self, other: &Self) -> Ordering {
@@ -44,14 +44,14 @@ LL | | }
    | |_^
    |
 note: `PartialOrd` implemented here
-  --> $DIR/derive_ord_xor_partial_ord.rs:38:10
+  --> $DIR/derive_ord_xor_partial_ord.rs:39:10
    |
 LL | #[derive(PartialOrd, PartialEq, Eq)]
    |          ^^^^^^^^^^
    = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: you are implementing `Ord` explicitly but have derived `PartialOrd`
-  --> $DIR/derive_ord_xor_partial_ord.rs:61:5
+  --> $DIR/derive_ord_xor_partial_ord.rs:62:5
    |
 LL | /     impl Ord for DerivePartialOrdInUseOrd {
 LL | |         fn cmp(&self, other: &Self) -> Ordering {
@@ -61,7 +61,7 @@ LL | |     }
    | |_____^
    |
 note: `PartialOrd` implemented here
-  --> $DIR/derive_ord_xor_partial_ord.rs:58:14
+  --> $DIR/derive_ord_xor_partial_ord.rs:59:14
    |
 LL |     #[derive(PartialOrd, PartialEq, Eq)]
    |              ^^^^^^^^^^
index f47b81a450ea937c2bd142e47bdb9b0f140620bf..c77a74a58f22c6072dcfb295ea22794afbe1309c 100644 (file)
@@ -1,6 +1,7 @@
 // edition:2018
 #![warn(clippy::missing_errors_doc)]
 #![allow(clippy::result_unit_err)]
+#![allow(clippy::unnecessary_wraps)]
 
 use std::io;
 
index c7b616e2897087c01ee59976e37fe287afb6dbbc..b5a81419daee35d295197158c9e20d5a17f21871 100644 (file)
@@ -1,5 +1,5 @@
 error: docs for function returning `Result` missing `# Errors` section
-  --> $DIR/doc_errors.rs:7:1
+  --> $DIR/doc_errors.rs:8:1
    |
 LL | / pub fn pub_fn_missing_errors_header() -> Result<(), ()> {
 LL | |     unimplemented!();
@@ -9,7 +9,7 @@ LL | | }
    = note: `-D clippy::missing-errors-doc` implied by `-D warnings`
 
 error: docs for function returning `Result` missing `# Errors` section
-  --> $DIR/doc_errors.rs:11:1
+  --> $DIR/doc_errors.rs:12:1
    |
 LL | / pub async fn async_pub_fn_missing_errors_header() -> Result<(), ()> {
 LL | |     unimplemented!();
@@ -17,7 +17,7 @@ LL | | }
    | |_^
 
 error: docs for function returning `Result` missing `# Errors` section
-  --> $DIR/doc_errors.rs:16:1
+  --> $DIR/doc_errors.rs:17:1
    |
 LL | / pub fn pub_fn_returning_io_result() -> io::Result<()> {
 LL | |     unimplemented!();
@@ -25,7 +25,7 @@ LL | | }
    | |_^
 
 error: docs for function returning `Result` missing `# Errors` section
-  --> $DIR/doc_errors.rs:21:1
+  --> $DIR/doc_errors.rs:22:1
    |
 LL | / pub async fn async_pub_fn_returning_io_result() -> io::Result<()> {
 LL | |     unimplemented!();
@@ -33,7 +33,7 @@ LL | | }
    | |_^
 
 error: docs for function returning `Result` missing `# Errors` section
-  --> $DIR/doc_errors.rs:51:5
+  --> $DIR/doc_errors.rs:52:5
    |
 LL | /     pub fn pub_method_missing_errors_header() -> Result<(), ()> {
 LL | |         unimplemented!();
@@ -41,7 +41,7 @@ LL | |     }
    | |_____^
 
 error: docs for function returning `Result` missing `# Errors` section
-  --> $DIR/doc_errors.rs:56:5
+  --> $DIR/doc_errors.rs:57:5
    |
 LL | /     pub async fn async_pub_method_missing_errors_header() -> Result<(), ()> {
 LL | |         unimplemented!();
@@ -49,7 +49,7 @@ LL | |     }
    | |_____^
 
 error: docs for function returning `Result` missing `# Errors` section
-  --> $DIR/doc_errors.rs:85:5
+  --> $DIR/doc_errors.rs:86:5
    |
 LL |     fn trait_method_missing_errors_header() -> Result<(), ()>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 6b5bcdaa78e2762cd82fc68130cdb4405d217e03..e1a15c609fd233d6adf784fb5294c7a3b191baed 100644 (file)
@@ -1,6 +1,7 @@
 #![warn(clippy::drop_ref)]
 #![allow(clippy::toplevel_ref_arg)]
 #![allow(clippy::map_err_ignore)]
+#![allow(clippy::unnecessary_wraps)]
 
 use std::mem::drop;
 
index 7974bf56d44cf582e1b80e98ecf4c31c4aeb226e..10087cb4820a7ce650ce5f52016d0c615767491e 100644 (file)
 error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing.
-  --> $DIR/drop_ref.rs:10:5
+  --> $DIR/drop_ref.rs:11:5
    |
 LL |     drop(&SomeStruct);
    |     ^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::drop-ref` implied by `-D warnings`
 note: argument has type `&SomeStruct`
-  --> $DIR/drop_ref.rs:10:10
+  --> $DIR/drop_ref.rs:11:10
    |
 LL |     drop(&SomeStruct);
    |          ^^^^^^^^^^^
 
 error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing.
-  --> $DIR/drop_ref.rs:13:5
+  --> $DIR/drop_ref.rs:14:5
    |
 LL |     drop(&owned1);
    |     ^^^^^^^^^^^^^
    |
 note: argument has type `&SomeStruct`
-  --> $DIR/drop_ref.rs:13:10
+  --> $DIR/drop_ref.rs:14:10
    |
 LL |     drop(&owned1);
    |          ^^^^^^^
 
 error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing.
-  --> $DIR/drop_ref.rs:14:5
+  --> $DIR/drop_ref.rs:15:5
    |
 LL |     drop(&&owned1);
    |     ^^^^^^^^^^^^^^
    |
 note: argument has type `&&SomeStruct`
-  --> $DIR/drop_ref.rs:14:10
+  --> $DIR/drop_ref.rs:15:10
    |
 LL |     drop(&&owned1);
    |          ^^^^^^^^
 
 error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing.
-  --> $DIR/drop_ref.rs:15:5
+  --> $DIR/drop_ref.rs:16:5
    |
 LL |     drop(&mut owned1);
    |     ^^^^^^^^^^^^^^^^^
    |
 note: argument has type `&mut SomeStruct`
-  --> $DIR/drop_ref.rs:15:10
+  --> $DIR/drop_ref.rs:16:10
    |
 LL |     drop(&mut owned1);
    |          ^^^^^^^^^^^
 
 error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing.
-  --> $DIR/drop_ref.rs:19:5
+  --> $DIR/drop_ref.rs:20:5
    |
 LL |     drop(reference1);
    |     ^^^^^^^^^^^^^^^^
    |
 note: argument has type `&SomeStruct`
-  --> $DIR/drop_ref.rs:19:10
+  --> $DIR/drop_ref.rs:20:10
    |
 LL |     drop(reference1);
    |          ^^^^^^^^^^
 
 error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing.
-  --> $DIR/drop_ref.rs:22:5
+  --> $DIR/drop_ref.rs:23:5
    |
 LL |     drop(reference2);
    |     ^^^^^^^^^^^^^^^^
    |
 note: argument has type `&mut SomeStruct`
-  --> $DIR/drop_ref.rs:22:10
+  --> $DIR/drop_ref.rs:23:10
    |
 LL |     drop(reference2);
    |          ^^^^^^^^^^
 
 error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing.
-  --> $DIR/drop_ref.rs:25:5
+  --> $DIR/drop_ref.rs:26:5
    |
 LL |     drop(reference3);
    |     ^^^^^^^^^^^^^^^^
    |
 note: argument has type `&SomeStruct`
-  --> $DIR/drop_ref.rs:25:10
+  --> $DIR/drop_ref.rs:26:10
    |
 LL |     drop(reference3);
    |          ^^^^^^^^^^
 
 error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing.
-  --> $DIR/drop_ref.rs:30:5
+  --> $DIR/drop_ref.rs:31:5
    |
 LL |     drop(&val);
    |     ^^^^^^^^^^
    |
 note: argument has type `&T`
-  --> $DIR/drop_ref.rs:30:10
+  --> $DIR/drop_ref.rs:31:10
    |
 LL |     drop(&val);
    |          ^^^^
 
 error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing.
-  --> $DIR/drop_ref.rs:38:5
+  --> $DIR/drop_ref.rs:39:5
    |
 LL |     std::mem::drop(&SomeStruct);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: argument has type `&SomeStruct`
-  --> $DIR/drop_ref.rs:38:20
+  --> $DIR/drop_ref.rs:39:20
    |
 LL |     std::mem::drop(&SomeStruct);
    |                    ^^^^^^^^^^^
index fd3979f259a145c6ea6a917fb2876a7119d7f3f8..555f3d3d884a9d6d6a5f4f7520d4b152a53cfd24 100644 (file)
@@ -5,7 +5,7 @@ LL |     loop {}
    |     ^^^^^^^
    |
    = note: `-D clippy::empty-loop` implied by `-D warnings`
-   = help: You should either use `panic!()` or add `std::thread::sleep(..);` to the loop body.
+   = help: you should either use `panic!()` or add `std::thread::sleep(..);` to the loop body
 
 error: empty `loop {}` wastes CPU cycles
   --> $DIR/empty_loop.rs:11:9
@@ -13,7 +13,7 @@ error: empty `loop {}` wastes CPU cycles
 LL |         loop {}
    |         ^^^^^^^
    |
-   = help: You should either use `panic!()` or add `std::thread::sleep(..);` to the loop body.
+   = help: you should either use `panic!()` or add `std::thread::sleep(..);` to the loop body
 
 error: empty `loop {}` wastes CPU cycles
   --> $DIR/empty_loop.rs:15:9
@@ -21,7 +21,7 @@ error: empty `loop {}` wastes CPU cycles
 LL |         'inner: loop {}
    |         ^^^^^^^^^^^^^^^
    |
-   = help: You should either use `panic!()` or add `std::thread::sleep(..);` to the loop body.
+   = help: you should either use `panic!()` or add `std::thread::sleep(..);` to the loop body
 
 error: aborting due to 3 previous errors
 
index 879d1d5d916e439bf219fef4e343ab0320c13d51..4553d3ec505a33846cce213690a5a6905ef3330c 100644 (file)
 
 #[start]
 fn main(argc: isize, argv: *const *const u8) -> isize {
+    // This should trigger the lint
     loop {}
 }
 
 #[panic_handler]
 fn panic(_info: &PanicInfo) -> ! {
+    // This should NOT trigger the lint
     loop {}
 }
 
 #[lang = "eh_personality"]
-extern "C" fn eh_personality() {}
+extern "C" fn eh_personality() {
+    // This should also trigger the lint
+    loop {}
+}
diff --git a/src/tools/clippy/tests/ui/empty_loop_no_std.stderr b/src/tools/clippy/tests/ui/empty_loop_no_std.stderr
new file mode 100644 (file)
index 0000000..520248f
--- /dev/null
@@ -0,0 +1,19 @@
+error: empty `loop {}` wastes CPU cycles
+  --> $DIR/empty_loop_no_std.rs:14:5
+   |
+LL |     loop {}
+   |     ^^^^^^^
+   |
+   = note: `-D clippy::empty-loop` implied by `-D warnings`
+   = help: you should either use `panic!()` or add a call pausing or sleeping the thread to the loop body
+
+error: empty `loop {}` wastes CPU cycles
+  --> $DIR/empty_loop_no_std.rs:26:5
+   |
+LL |     loop {}
+   |     ^^^^^^^
+   |
+   = help: you should either use `panic!()` or add a call pausing or sleeping the thread to the loop body
+
+error: aborting due to 2 previous errors
+
index ef434245fd70c6c6721e5f67d9875f2cd0169cb4..514502416192640890c0c436981abcdb800f4d5e 100644 (file)
@@ -1,4 +1,5 @@
 #![warn(clippy::all, clippy::pedantic)]
+#![allow(clippy::clippy::let_underscore_drop)]
 #![allow(clippy::missing_docs_in_private_items)]
 
 fn main() {
index 91718dd11755b75310056c4a60277da2b63e8329..119226813793c172aba83986b6f15830039a6e5f 100644 (file)
@@ -1,5 +1,5 @@
 error: called `filter(..).map(..)` on an `Iterator`
-  --> $DIR/filter_methods.rs:5:21
+  --> $DIR/filter_methods.rs:6:21
    |
 LL |     let _: Vec<_> = vec![5; 6].into_iter().filter(|&x| x == 0).map(|x| x * 2).collect();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL |     let _: Vec<_> = vec![5; 6].into_iter().filter(|&x| x == 0).map(|x| x *
    = help: this is more succinctly expressed by calling `.filter_map(..)` instead
 
 error: called `filter(..).flat_map(..)` on an `Iterator`
-  --> $DIR/filter_methods.rs:7:21
+  --> $DIR/filter_methods.rs:8:21
    |
 LL |       let _: Vec<_> = vec![5_i8; 6]
    |  _____________________^
@@ -20,7 +20,7 @@ LL | |         .flat_map(|x| x.checked_mul(2))
    = help: this is more succinctly expressed by calling `.flat_map(..)` and filtering by returning `iter::empty()`
 
 error: called `filter_map(..).flat_map(..)` on an `Iterator`
-  --> $DIR/filter_methods.rs:13:21
+  --> $DIR/filter_methods.rs:14:21
    |
 LL |       let _: Vec<_> = vec![5_i8; 6]
    |  _____________________^
@@ -32,7 +32,7 @@ LL | |         .flat_map(|x| x.checked_mul(2))
    = help: this is more succinctly expressed by calling `.flat_map(..)` and filtering by returning `iter::empty()`
 
 error: called `filter_map(..).map(..)` on an `Iterator`
-  --> $DIR/filter_methods.rs:19:21
+  --> $DIR/filter_methods.rs:20:21
    |
 LL |       let _: Vec<_> = vec![5_i8; 6]
    |  _____________________^
index 447fdbe1fac53ee1dbbb1217473b87237d41a467..c49e6756a6c5bed9db7e73e40ae7acbf5aebb260 100644 (file)
@@ -1,5 +1,6 @@
 #![warn(clippy::forget_ref)]
 #![allow(clippy::toplevel_ref_arg)]
+#![allow(clippy::unnecessary_wraps)]
 
 use std::mem::forget;
 
index f90bcc2762cee2a92dcf73e96540011b68c0b422..b2c7f2023bfbf47519d00125d17da0babb767022 100644 (file)
 error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing.
-  --> $DIR/forget_ref.rs:9:5
+  --> $DIR/forget_ref.rs:10:5
    |
 LL |     forget(&SomeStruct);
    |     ^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::forget-ref` implied by `-D warnings`
 note: argument has type `&SomeStruct`
-  --> $DIR/forget_ref.rs:9:12
+  --> $DIR/forget_ref.rs:10:12
    |
 LL |     forget(&SomeStruct);
    |            ^^^^^^^^^^^
 
 error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing.
-  --> $DIR/forget_ref.rs:12:5
+  --> $DIR/forget_ref.rs:13:5
    |
 LL |     forget(&owned);
    |     ^^^^^^^^^^^^^^
    |
 note: argument has type `&SomeStruct`
-  --> $DIR/forget_ref.rs:12:12
+  --> $DIR/forget_ref.rs:13:12
    |
 LL |     forget(&owned);
    |            ^^^^^^
 
 error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing.
-  --> $DIR/forget_ref.rs:13:5
+  --> $DIR/forget_ref.rs:14:5
    |
 LL |     forget(&&owned);
    |     ^^^^^^^^^^^^^^^
    |
 note: argument has type `&&SomeStruct`
-  --> $DIR/forget_ref.rs:13:12
+  --> $DIR/forget_ref.rs:14:12
    |
 LL |     forget(&&owned);
    |            ^^^^^^^
 
 error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing.
-  --> $DIR/forget_ref.rs:14:5
+  --> $DIR/forget_ref.rs:15:5
    |
 LL |     forget(&mut owned);
    |     ^^^^^^^^^^^^^^^^^^
    |
 note: argument has type `&mut SomeStruct`
-  --> $DIR/forget_ref.rs:14:12
+  --> $DIR/forget_ref.rs:15:12
    |
 LL |     forget(&mut owned);
    |            ^^^^^^^^^^
 
 error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing.
-  --> $DIR/forget_ref.rs:18:5
+  --> $DIR/forget_ref.rs:19:5
    |
 LL |     forget(&*reference1);
    |     ^^^^^^^^^^^^^^^^^^^^
    |
 note: argument has type `&SomeStruct`
-  --> $DIR/forget_ref.rs:18:12
+  --> $DIR/forget_ref.rs:19:12
    |
 LL |     forget(&*reference1);
    |            ^^^^^^^^^^^^
 
 error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing.
-  --> $DIR/forget_ref.rs:21:5
+  --> $DIR/forget_ref.rs:22:5
    |
 LL |     forget(reference2);
    |     ^^^^^^^^^^^^^^^^^^
    |
 note: argument has type `&mut SomeStruct`
-  --> $DIR/forget_ref.rs:21:12
+  --> $DIR/forget_ref.rs:22:12
    |
 LL |     forget(reference2);
    |            ^^^^^^^^^^
 
 error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing.
-  --> $DIR/forget_ref.rs:24:5
+  --> $DIR/forget_ref.rs:25:5
    |
 LL |     forget(reference3);
    |     ^^^^^^^^^^^^^^^^^^
    |
 note: argument has type `&SomeStruct`
-  --> $DIR/forget_ref.rs:24:12
+  --> $DIR/forget_ref.rs:25:12
    |
 LL |     forget(reference3);
    |            ^^^^^^^^^^
 
 error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing.
-  --> $DIR/forget_ref.rs:29:5
+  --> $DIR/forget_ref.rs:30:5
    |
 LL |     forget(&val);
    |     ^^^^^^^^^^^^
    |
 note: argument has type `&T`
-  --> $DIR/forget_ref.rs:29:12
+  --> $DIR/forget_ref.rs:30:12
    |
 LL |     forget(&val);
    |            ^^^^
 
 error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing.
-  --> $DIR/forget_ref.rs:37:5
+  --> $DIR/forget_ref.rs:38:5
    |
 LL |     std::mem::forget(&SomeStruct);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: argument has type `&SomeStruct`
-  --> $DIR/forget_ref.rs:37:22
+  --> $DIR/forget_ref.rs:38:22
    |
 LL |     std::mem::forget(&SomeStruct);
    |                      ^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/let_underscore_drop.rs b/src/tools/clippy/tests/ui/let_underscore_drop.rs
new file mode 100644 (file)
index 0000000..98593ed
--- /dev/null
@@ -0,0 +1,19 @@
+#![warn(clippy::let_underscore_drop)]
+
+struct Droppable;
+
+impl Drop for Droppable {
+    fn drop(&mut self) {}
+}
+
+fn main() {
+    let unit = ();
+    let boxed = Box::new(());
+    let droppable = Droppable;
+    let optional = Some(Droppable);
+
+    let _ = ();
+    let _ = Box::new(());
+    let _ = Droppable;
+    let _ = Some(Droppable);
+}
diff --git a/src/tools/clippy/tests/ui/let_underscore_drop.stderr b/src/tools/clippy/tests/ui/let_underscore_drop.stderr
new file mode 100644 (file)
index 0000000..66069e0
--- /dev/null
@@ -0,0 +1,27 @@
+error: non-binding `let` on a type that implements `Drop`
+  --> $DIR/let_underscore_drop.rs:16:5
+   |
+LL |     let _ = Box::new(());
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::let-underscore-drop` implied by `-D warnings`
+   = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
+
+error: non-binding `let` on a type that implements `Drop`
+  --> $DIR/let_underscore_drop.rs:17:5
+   |
+LL |     let _ = Droppable;
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
+
+error: non-binding `let` on a type that implements `Drop`
+  --> $DIR/let_underscore_drop.rs:18:5
+   |
+LL |     let _ = Some(Droppable);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
+
+error: aborting due to 3 previous errors
+
index 27dda606067aa7fa8760316cb468c33111d4254e..a842e872a37b1f0fefcb21dad35b630ef75deaeb 100644 (file)
@@ -1,4 +1,5 @@
 #![warn(clippy::let_underscore_must_use)]
+#![allow(clippy::unnecessary_wraps)]
 
 // Debug implementations can fire this lint,
 // so we shouldn't lint external macros
index 447f2419e3bdb50932203b3ca2af5d7a33a3b1a8..5b751ea56deffe96d0413506ba5ed67abd039e6b 100644 (file)
@@ -1,5 +1,5 @@
 error: non-binding let on a result of a `#[must_use]` function
-  --> $DIR/let_underscore_must_use.rs:66:5
+  --> $DIR/let_underscore_must_use.rs:67:5
    |
 LL |     let _ = f();
    |     ^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL |     let _ = f();
    = help: consider explicitly using function result
 
 error: non-binding let on an expression with `#[must_use]` type
-  --> $DIR/let_underscore_must_use.rs:67:5
+  --> $DIR/let_underscore_must_use.rs:68:5
    |
 LL |     let _ = g();
    |     ^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL |     let _ = g();
    = help: consider explicitly using expression value
 
 error: non-binding let on a result of a `#[must_use]` function
-  --> $DIR/let_underscore_must_use.rs:69:5
+  --> $DIR/let_underscore_must_use.rs:70:5
    |
 LL |     let _ = l(0_u32);
    |     ^^^^^^^^^^^^^^^^^
@@ -24,7 +24,7 @@ LL |     let _ = l(0_u32);
    = help: consider explicitly using function result
 
 error: non-binding let on a result of a `#[must_use]` function
-  --> $DIR/let_underscore_must_use.rs:73:5
+  --> $DIR/let_underscore_must_use.rs:74:5
    |
 LL |     let _ = s.f();
    |     ^^^^^^^^^^^^^^
@@ -32,7 +32,7 @@ LL |     let _ = s.f();
    = help: consider explicitly using function result
 
 error: non-binding let on an expression with `#[must_use]` type
-  --> $DIR/let_underscore_must_use.rs:74:5
+  --> $DIR/let_underscore_must_use.rs:75:5
    |
 LL |     let _ = s.g();
    |     ^^^^^^^^^^^^^^
@@ -40,7 +40,7 @@ LL |     let _ = s.g();
    = help: consider explicitly using expression value
 
 error: non-binding let on a result of a `#[must_use]` function
-  --> $DIR/let_underscore_must_use.rs:77:5
+  --> $DIR/let_underscore_must_use.rs:78:5
    |
 LL |     let _ = S::h();
    |     ^^^^^^^^^^^^^^^
@@ -48,7 +48,7 @@ LL |     let _ = S::h();
    = help: consider explicitly using function result
 
 error: non-binding let on an expression with `#[must_use]` type
-  --> $DIR/let_underscore_must_use.rs:78:5
+  --> $DIR/let_underscore_must_use.rs:79:5
    |
 LL |     let _ = S::p();
    |     ^^^^^^^^^^^^^^^
@@ -56,7 +56,7 @@ LL |     let _ = S::p();
    = help: consider explicitly using expression value
 
 error: non-binding let on a result of a `#[must_use]` function
-  --> $DIR/let_underscore_must_use.rs:80:5
+  --> $DIR/let_underscore_must_use.rs:81:5
    |
 LL |     let _ = S::a();
    |     ^^^^^^^^^^^^^^^
@@ -64,7 +64,7 @@ LL |     let _ = S::a();
    = help: consider explicitly using function result
 
 error: non-binding let on an expression with `#[must_use]` type
-  --> $DIR/let_underscore_must_use.rs:82:5
+  --> $DIR/let_underscore_must_use.rs:83:5
    |
 LL |     let _ = if true { Ok(()) } else { Err(()) };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -72,7 +72,7 @@ LL |     let _ = if true { Ok(()) } else { Err(()) };
    = help: consider explicitly using expression value
 
 error: non-binding let on a result of a `#[must_use]` function
-  --> $DIR/let_underscore_must_use.rs:86:5
+  --> $DIR/let_underscore_must_use.rs:87:5
    |
 LL |     let _ = a.is_ok();
    |     ^^^^^^^^^^^^^^^^^^
@@ -80,7 +80,7 @@ LL |     let _ = a.is_ok();
    = help: consider explicitly using function result
 
 error: non-binding let on an expression with `#[must_use]` type
-  --> $DIR/let_underscore_must_use.rs:88:5
+  --> $DIR/let_underscore_must_use.rs:89:5
    |
 LL |     let _ = a.map(|_| ());
    |     ^^^^^^^^^^^^^^^^^^^^^^
@@ -88,7 +88,7 @@ LL |     let _ = a.map(|_| ());
    = help: consider explicitly using expression value
 
 error: non-binding let on an expression with `#[must_use]` type
-  --> $DIR/let_underscore_must_use.rs:90:5
+  --> $DIR/let_underscore_must_use.rs:91:5
    |
 LL |     let _ = a;
    |     ^^^^^^^^^^
index b4163d776e73abf4da6f4c565b50d4386052a1c5..a01c6ef99db921386fb8ea8bdaac007cb804c08a 100644 (file)
@@ -1,4 +1,4 @@
-#![allow(unused, clippy::many_single_char_names)]
+#![allow(unused, clippy::many_single_char_names, clippy::diverging_sub_expression)]
 #![warn(clippy::logic_bug)]
 
 fn main() {
index 4f551690c4370ab3b7f2428237f3a0d5e3548180..5184f6fdb88b3991850aead57bf02ea0a75b46cf 100644 (file)
@@ -7,7 +7,19 @@ use std::future::Future;
 
 async fn fut() -> i32 { 42 }
 
-async fn empty_fut()  {}
+#[rustfmt::skip]
+async fn fut2() -> i32 { 42 }
+
+#[rustfmt::skip]
+async fn fut3() -> i32 { 42 }
+
+async fn empty_fut() {}
+
+#[rustfmt::skip]
+async fn empty_fut2() {}
+
+#[rustfmt::skip]
+async fn empty_fut3() {}
 
 async fn core_fut() -> i32 { 42 }
 
index 6ed60309947a81b27f5e2a2b7a559cdbbacf9b7e..68c0e591f0b6eed6b4ffd5eeb1b8bd0fde47bae1 100644 (file)
@@ -9,10 +9,30 @@ fn fut() -> impl Future<Output = i32> {
     async { 42 }
 }
 
+#[rustfmt::skip]
+fn fut2() ->impl Future<Output = i32> {
+    async { 42 }
+}
+
+#[rustfmt::skip]
+fn fut3()-> impl Future<Output = i32> {
+    async { 42 }
+}
+
 fn empty_fut() -> impl Future<Output = ()> {
     async {}
 }
 
+#[rustfmt::skip]
+fn empty_fut2() ->impl Future<Output = ()> {
+    async {}
+}
+
+#[rustfmt::skip]
+fn empty_fut3()-> impl Future<Output = ()> {
+    async {}
+}
+
 fn core_fut() -> impl core::future::Future<Output = i32> {
     async move { 42 }
 }
index ccd828674276ba48cf9c6ba2a0f357edaecc5331..fdd43db3255ee5991fe49597ded05698fbae3f64 100644 (file)
@@ -15,14 +15,44 @@ LL | fn fut() -> impl Future<Output = i32> { 42 }
    |                                       ^^^^^^
 
 error: this function can be simplified using the `async fn` syntax
-  --> $DIR/manual_async_fn.rs:12:1
+  --> $DIR/manual_async_fn.rs:13:1
+   |
+LL | fn fut2() ->impl Future<Output = i32> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: make the function `async` and return the output of the future directly
+   |
+LL | async fn fut2() -> i32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^
+help: move the body of the async block to the enclosing function
+   |
+LL | fn fut2() ->impl Future<Output = i32> { 42 }
+   |                                       ^^^^^^
+
+error: this function can be simplified using the `async fn` syntax
+  --> $DIR/manual_async_fn.rs:18:1
+   |
+LL | fn fut3()-> impl Future<Output = i32> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: make the function `async` and return the output of the future directly
+   |
+LL | async fn fut3() -> i32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^
+help: move the body of the async block to the enclosing function
+   |
+LL | fn fut3()-> impl Future<Output = i32> { 42 }
+   |                                       ^^^^^^
+
+error: this function can be simplified using the `async fn` syntax
+  --> $DIR/manual_async_fn.rs:22:1
    |
 LL | fn empty_fut() -> impl Future<Output = ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: make the function `async` and remove the return type
    |
-LL | async fn empty_fut()  {
+LL | async fn empty_fut() {
    | ^^^^^^^^^^^^^^^^^^^^
 help: move the body of the async block to the enclosing function
    |
@@ -30,7 +60,37 @@ LL | fn empty_fut() -> impl Future<Output = ()> {}
    |                                            ^^
 
 error: this function can be simplified using the `async fn` syntax
-  --> $DIR/manual_async_fn.rs:16:1
+  --> $DIR/manual_async_fn.rs:27:1
+   |
+LL | fn empty_fut2() ->impl Future<Output = ()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: make the function `async` and remove the return type
+   |
+LL | async fn empty_fut2() {
+   | ^^^^^^^^^^^^^^^^^^^^^
+help: move the body of the async block to the enclosing function
+   |
+LL | fn empty_fut2() ->impl Future<Output = ()> {}
+   |                                            ^^
+
+error: this function can be simplified using the `async fn` syntax
+  --> $DIR/manual_async_fn.rs:32:1
+   |
+LL | fn empty_fut3()-> impl Future<Output = ()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: make the function `async` and remove the return type
+   |
+LL | async fn empty_fut3() {
+   | ^^^^^^^^^^^^^^^^^^^^^
+help: move the body of the async block to the enclosing function
+   |
+LL | fn empty_fut3()-> impl Future<Output = ()> {}
+   |                                            ^^
+
+error: this function can be simplified using the `async fn` syntax
+  --> $DIR/manual_async_fn.rs:36:1
    |
 LL | fn core_fut() -> impl core::future::Future<Output = i32> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -45,7 +105,7 @@ LL | fn core_fut() -> impl core::future::Future<Output = i32> { 42 }
    |                                                          ^^^^^^
 
 error: this function can be simplified using the `async fn` syntax
-  --> $DIR/manual_async_fn.rs:38:5
+  --> $DIR/manual_async_fn.rs:58:5
    |
 LL |     fn inh_fut() -> impl Future<Output = i32> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -65,7 +125,7 @@ LL |             let c = 21;
  ...
 
 error: this function can be simplified using the `async fn` syntax
-  --> $DIR/manual_async_fn.rs:73:1
+  --> $DIR/manual_async_fn.rs:93:1
    |
 LL | fn elided(_: &i32) -> impl Future<Output = i32> + '_ {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -80,7 +140,7 @@ LL | fn elided(_: &i32) -> impl Future<Output = i32> + '_ { 42 }
    |                                                      ^^^^^^
 
 error: this function can be simplified using the `async fn` syntax
-  --> $DIR/manual_async_fn.rs:82:1
+  --> $DIR/manual_async_fn.rs:102:1
    |
 LL | fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> + 'a + 'b {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -94,5 +154,5 @@ help: move the body of the async block to the enclosing function
 LL | fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> + 'a + 'b { 42 }
    |                                                                                    ^^^^^^
 
-error: aborting due to 6 previous errors
+error: aborting due to 10 previous errors
 
index b42e94bd727de9fa998f54bdb83d099ebf4401a9..887a97d7a01734dafb5269bcac6c57b62a2978db 100644 (file)
@@ -28,7 +28,7 @@ fn main() {
     // not applicable, or side isn't `Result::Err`
     foo.map_or(Ok::<i32, &str>(1), |v| Ok(v));
 
-    // not applicatble, expr is not a `Result` value
+    // not applicable, expr is not a `Result` value
     foo.map_or(42, |v| v);
 
     // TODO patterns not covered yet
index e5a6056fbf5cc40ba9cb089d663e1ca81b3186db..3c99872f5022a32cb4a35394fe12e8ba46b0e362 100644 (file)
@@ -32,7 +32,7 @@ fn main() {
     // not applicable, or side isn't `Result::Err`
     foo.map_or(Ok::<i32, &str>(1), |v| Ok(v));
 
-    // not applicatble, expr is not a `Result` value
+    // not applicable, expr is not a `Result` value
     foo.map_or(42, |v| v);
 
     // TODO patterns not covered yet
index 5aa5a43cb92cf672da6888096fed8bd4ceb9db3b..81d903c15d32a29475cf338109586a22511ab306 100644 (file)
@@ -1,6 +1,6 @@
 // run-rustfix
 #![allow(dead_code)]
-#![allow(unused_variables)]
+#![allow(unused_variables, clippy::unnecessary_wraps)]
 
 fn option_unwrap_or() {
     // int case
index df534031f54c32c83991357f07cb3826f021323c..16105d379c3052ac8c709e0ea24925411d0fb237 100644 (file)
@@ -1,6 +1,6 @@
 // run-rustfix
 #![allow(dead_code)]
-#![allow(unused_variables)]
+#![allow(unused_variables, clippy::unnecessary_wraps)]
 
 fn option_unwrap_or() {
     // int case
index 81c7f659efb1fed41dbbd9433b9dd5a8c3d79ffe..178d8705c2f02cedf1a70ed5ef6604e802fd873d 100644 (file)
@@ -2,6 +2,7 @@
 #![warn(clippy::all, clippy::pedantic)]
 #![allow(clippy::iter_cloned_collect)]
 #![allow(clippy::clone_on_copy, clippy::redundant_clone)]
+#![allow(clippy::let_underscore_drop)]
 #![allow(clippy::missing_docs_in_private_items)]
 #![allow(clippy::redundant_closure_for_method_calls)]
 #![allow(clippy::many_single_char_names)]
@@ -44,4 +45,19 @@ fn main() {
         let v = vec![&mut d];
         let _: Vec<u32> = v.into_iter().map(|&mut x| x).collect();
     }
+
+    // Issue #6299
+    {
+        let mut aa = 5;
+        let mut bb = 3;
+        let items = vec![&mut aa, &mut bb];
+        let _: Vec<_> = items.into_iter().map(|x| x.clone()).collect();
+    }
+
+    // Issue #6239 deref coercion and clone deref
+    {
+        use std::cell::RefCell;
+
+        let _ = Some(RefCell::new(String::new()).borrow()).map(|s| s.clone());
+    }
 }
index 8ed164f0ed51dabcf0d6e449351e427f6a1576d5..c73d81713b8a3a762adf71fa13589f65640d9463 100644 (file)
@@ -2,6 +2,7 @@
 #![warn(clippy::all, clippy::pedantic)]
 #![allow(clippy::iter_cloned_collect)]
 #![allow(clippy::clone_on_copy, clippy::redundant_clone)]
+#![allow(clippy::let_underscore_drop)]
 #![allow(clippy::missing_docs_in_private_items)]
 #![allow(clippy::redundant_closure_for_method_calls)]
 #![allow(clippy::many_single_char_names)]
@@ -44,4 +45,19 @@ fn main() {
         let v = vec![&mut d];
         let _: Vec<u32> = v.into_iter().map(|&mut x| x).collect();
     }
+
+    // Issue #6299
+    {
+        let mut aa = 5;
+        let mut bb = 3;
+        let items = vec![&mut aa, &mut bb];
+        let _: Vec<_> = items.into_iter().map(|x| x.clone()).collect();
+    }
+
+    // Issue #6239 deref coercion and clone deref
+    {
+        use std::cell::RefCell;
+
+        let _ = Some(RefCell::new(String::new()).borrow()).map(|s| s.clone());
+    }
 }
index 4f43cff50244449b93b23b76db601285132eab85..d84a5bf8d4de6f3bc3543b4861543e19a92264f9 100644 (file)
@@ -1,5 +1,5 @@
 error: you are using an explicit closure for copying elements
-  --> $DIR/map_clone.rs:10:22
+  --> $DIR/map_clone.rs:11:22
    |
 LL |     let _: Vec<i8> = vec![5_i8; 6].iter().map(|x| *x).collect();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `vec![5_i8; 6].iter().copied()`
@@ -7,31 +7,31 @@ LL |     let _: Vec<i8> = vec![5_i8; 6].iter().map(|x| *x).collect();
    = note: `-D clippy::map-clone` implied by `-D warnings`
 
 error: you are using an explicit closure for cloning elements
-  --> $DIR/map_clone.rs:11:26
+  --> $DIR/map_clone.rs:12:26
    |
 LL |     let _: Vec<String> = vec![String::new()].iter().map(|x| x.clone()).collect();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `vec![String::new()].iter().cloned()`
 
 error: you are using an explicit closure for copying elements
-  --> $DIR/map_clone.rs:12:23
+  --> $DIR/map_clone.rs:13:23
    |
 LL |     let _: Vec<u32> = vec![42, 43].iter().map(|&x| x).collect();
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `vec![42, 43].iter().copied()`
 
 error: you are using an explicit closure for copying elements
-  --> $DIR/map_clone.rs:14:26
+  --> $DIR/map_clone.rs:15:26
    |
 LL |     let _: Option<u64> = Some(&16).map(|b| *b);
    |                          ^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `Some(&16).copied()`
 
 error: you are using an explicit closure for copying elements
-  --> $DIR/map_clone.rs:15:25
+  --> $DIR/map_clone.rs:16:25
    |
 LL |     let _: Option<u8> = Some(&1).map(|x| x.clone());
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `Some(&1).copied()`
 
 error: you are needlessly cloning iterator elements
-  --> $DIR/map_clone.rs:26:29
+  --> $DIR/map_clone.rs:27:29
    |
 LL |     let _ = std::env::args().map(|v| v.clone());
    |                             ^^^^^^^^^^^^^^^^^^^ help: remove the `map` call
index 617b6422872645362a68e406fdf92490f78b94b5..05b9949f10217e2cd9ef17c3fd8a2a51dfff61d5 100644 (file)
@@ -1,4 +1,5 @@
 #![warn(clippy::map_err_ignore)]
+#![allow(clippy::unnecessary_wraps)]
 use std::convert::TryFrom;
 use std::error::Error;
 use std::fmt;
index 7273f4603807865c42ff29e87d7878c12bceaaaa..390d7ce2e4e7b0fa5a6c956929a72d6983838173 100644 (file)
@@ -1,5 +1,5 @@
 error: `map_err(|_|...` ignores the original error
-  --> $DIR/map_err.rs:22:32
+  --> $DIR/map_err.rs:23:32
    |
 LL |     println!("{:?}", x.map_err(|_| Errors::Ignored));
    |                                ^^^
index a5fdf7df613d325d6b5bf80ed09647806581adb0..773b5914439d39f03ccc5cacd3666f68c0d67eb6 100644 (file)
@@ -1,8 +1,10 @@
 // run-rustfix
 
 #![warn(clippy::all, clippy::pedantic)]
+#![allow(clippy::let_underscore_drop)]
 #![allow(clippy::missing_docs_in_private_items)]
 #![allow(clippy::map_identity)]
+#![allow(clippy::unnecessary_wraps)]
 
 fn main() {
     // mapping to Option on Iterator
index abbc4e16e567951af8a952810e2a7bce9724d832..578bd877267952da8f126e277a63e9fdc94176ba 100644 (file)
@@ -1,8 +1,10 @@
 // run-rustfix
 
 #![warn(clippy::all, clippy::pedantic)]
+#![allow(clippy::let_underscore_drop)]
 #![allow(clippy::missing_docs_in_private_items)]
 #![allow(clippy::map_identity)]
+#![allow(clippy::unnecessary_wraps)]
 
 fn main() {
     // mapping to Option on Iterator
index b6479cd69eac4f49f6a0abf08c55dc3ba7f0224d..756e6e818ad4454ee42494add7f11610d078295d 100644 (file)
@@ -1,5 +1,5 @@
 error: called `map(..).flatten()` on an `Iterator`
-  --> $DIR/map_flatten.rs:14:46
+  --> $DIR/map_flatten.rs:16:46
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().collect();
    |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `filter_map` instead: `.filter_map(option_id)`
@@ -7,31 +7,31 @@ LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().coll
    = note: `-D clippy::map-flatten` implied by `-D warnings`
 
 error: called `map(..).flatten()` on an `Iterator`
-  --> $DIR/map_flatten.rs:15:46
+  --> $DIR/map_flatten.rs:17:46
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_ref).flatten().collect();
    |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `filter_map` instead: `.filter_map(option_id_ref)`
 
 error: called `map(..).flatten()` on an `Iterator`
-  --> $DIR/map_flatten.rs:16:46
+  --> $DIR/map_flatten.rs:18:46
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_closure).flatten().collect();
    |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `filter_map` instead: `.filter_map(option_id_closure)`
 
 error: called `map(..).flatten()` on an `Iterator`
-  --> $DIR/map_flatten.rs:17:46
+  --> $DIR/map_flatten.rs:19:46
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| x.checked_add(1)).flatten().collect();
    |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `filter_map` instead: `.filter_map(|x| x.checked_add(1))`
 
 error: called `map(..).flatten()` on an `Iterator`
-  --> $DIR/map_flatten.rs:20:46
+  --> $DIR/map_flatten.rs:22:46
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect();
    |                                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `flat_map` instead: `.flat_map(|x| 0..x)`
 
 error: called `map(..).flatten()` on an `Option`
-  --> $DIR/map_flatten.rs:23:39
+  --> $DIR/map_flatten.rs:25:39
    |
 LL |     let _: Option<_> = (Some(Some(1))).map(|x| x).flatten();
    |                                       ^^^^^^^^^^^^^^^^^^^^^ help: try using `and_then` instead: `.and_then(|x| x)`
index d93e5b114ecfa7a8933431848efc8a8543f442d8..513d930e0568758783426279201dfa1bbfe9d8b7 100644 (file)
@@ -133,50 +133,6 @@ fn filter_next() {
     let _ = foo.filter().next();
 }
 
-/// Checks implementation of `SEARCH_IS_SOME` lint.
-#[rustfmt::skip]
-fn search_is_some() {
-    let v = vec![3, 2, 1, 0, -1, -2, -3];
-    let y = &&42;
-
-    // Check `find().is_some()`, single-line case.
-    let _ = v.iter().find(|&x| *x < 0).is_some();
-    let _ = (0..1).find(|x| **y == *x).is_some(); // one dereference less
-    let _ = (0..1).find(|x| *x == 0).is_some();
-    let _ = v.iter().find(|x| **x == 0).is_some();
-
-    // Check `find().is_some()`, multi-line case.
-    let _ = v.iter().find(|&x| {
-                              *x < 0
-                          }
-                   ).is_some();
-
-    // Check `position().is_some()`, single-line case.
-    let _ = v.iter().position(|&x| x < 0).is_some();
-
-    // Check `position().is_some()`, multi-line case.
-    let _ = v.iter().position(|&x| {
-                                  x < 0
-                              }
-                   ).is_some();
-
-    // Check `rposition().is_some()`, single-line case.
-    let _ = v.iter().rposition(|&x| x < 0).is_some();
-
-    // Check `rposition().is_some()`, multi-line case.
-    let _ = v.iter().rposition(|&x| {
-                                   x < 0
-                               }
-                   ).is_some();
-
-    // Check that we don't lint if the caller is not an `Iterator`.
-    let foo = IteratorFalsePositives { foo: 0 };
-    let _ = foo.find().is_some();
-    let _ = foo.position().is_some();
-    let _ = foo.rposition().is_some();
-}
-
 fn main() {
     filter_next();
-    search_is_some();
 }
index 8a281c2dbd25c2ec3feee082f9735bf89dff00f4..33aba630a5304e22de80e7badd67c1b460c32653 100644 (file)
@@ -20,73 +20,5 @@ LL | |                    ).next();
    |
    = note: `-D clippy::filter-next` implied by `-D warnings`
 
-error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:143:22
-   |
-LL |     let _ = v.iter().find(|&x| *x < 0).is_some();
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x < 0)`
-   |
-   = note: `-D clippy::search-is-some` implied by `-D warnings`
-
-error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:144:20
-   |
-LL |     let _ = (0..1).find(|x| **y == *x).is_some(); // one dereference less
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| **y == x)`
-
-error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:145:20
-   |
-LL |     let _ = (0..1).find(|x| *x == 0).is_some();
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| x == 0)`
-
-error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:146:22
-   |
-LL |     let _ = v.iter().find(|x| **x == 0).is_some();
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x == 0)`
-
-error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:149:13
-   |
-LL |       let _ = v.iter().find(|&x| {
-   |  _____________^
-LL | |                               *x < 0
-LL | |                           }
-LL | |                    ).is_some();
-   | |______________________________^
-
-error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:155:22
-   |
-LL |     let _ = v.iter().position(|&x| x < 0).is_some();
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)`
-
-error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:158:13
-   |
-LL |       let _ = v.iter().position(|&x| {
-   |  _____________^
-LL | |                                   x < 0
-LL | |                               }
-LL | |                    ).is_some();
-   | |______________________________^
-
-error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:164:22
-   |
-LL |     let _ = v.iter().rposition(|&x| x < 0).is_some();
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)`
-
-error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:167:13
-   |
-LL |       let _ = v.iter().rposition(|&x| {
-   |  _____________^
-LL | |                                    x < 0
-LL | |                                }
-LL | |                    ).is_some();
-   | |______________________________^
-
-error: aborting due to 11 previous errors
+error: aborting due to 2 previous errors
 
index 3ee77dcac31a0d6b3658fb4104147ab0a41402ef..f219a570e7fccc06f3c4ea88c6c0c47615d11e5e 100644 (file)
@@ -3,9 +3,6 @@
 #![warn(clippy::mismatched_target_os)]
 #![allow(unused)]
 
-#[cfg(target_os = "cloudabi")]
-fn cloudabi() {}
-
 #[cfg(target_os = "hermit")]
 fn hermit() {}
 
@@ -16,7 +13,7 @@ fn wasi() {}
 fn none() {}
 
 // list with conditions
-#[cfg(all(not(any(windows, target_os = "cloudabi")), target_os = "wasi"))]
+#[cfg(all(not(windows), target_os = "wasi"))]
 fn list() {}
 
 // windows is a valid target family, should be ignored
index 9cc411418e4c4d979ca53f274aab55a803558226..8a8ae756a4fcfc4156df856ec1422d07cfbd73e4 100644 (file)
@@ -3,9 +3,6 @@
 #![warn(clippy::mismatched_target_os)]
 #![allow(unused)]
 
-#[cfg(cloudabi)]
-fn cloudabi() {}
-
 #[cfg(hermit)]
 fn hermit() {}
 
@@ -16,7 +13,7 @@ fn wasi() {}
 fn none() {}
 
 // list with conditions
-#[cfg(all(not(any(windows, cloudabi)), wasi))]
+#[cfg(all(not(windows), wasi))]
 fn list() {}
 
 // windows is a valid target family, should be ignored
index 78fc27752d239bcc9d57f2c54139b19503d9bc97..5f1b090830464162784eb324d77de99adf135953 100644 (file)
@@ -1,23 +1,15 @@
 error: operating system used in target family position
   --> $DIR/mismatched_target_os_non_unix.rs:6:1
    |
-LL | #[cfg(cloudabi)]
-   | ^^^^^^--------^^
-   |       |
-   |       help: try: `target_os = "cloudabi"`
-   |
-   = note: `-D clippy::mismatched-target-os` implied by `-D warnings`
-
-error: operating system used in target family position
-  --> $DIR/mismatched_target_os_non_unix.rs:9:1
-   |
 LL | #[cfg(hermit)]
    | ^^^^^^------^^
    |       |
    |       help: try: `target_os = "hermit"`
+   |
+   = note: `-D clippy::mismatched-target-os` implied by `-D warnings`
 
 error: operating system used in target family position
-  --> $DIR/mismatched_target_os_non_unix.rs:12:1
+  --> $DIR/mismatched_target_os_non_unix.rs:9:1
    |
 LL | #[cfg(wasi)]
    | ^^^^^^----^^
@@ -25,7 +17,7 @@ LL | #[cfg(wasi)]
    |       help: try: `target_os = "wasi"`
 
 error: operating system used in target family position
-  --> $DIR/mismatched_target_os_non_unix.rs:15:1
+  --> $DIR/mismatched_target_os_non_unix.rs:12:1
    |
 LL | #[cfg(none)]
    | ^^^^^^----^^
@@ -33,19 +25,12 @@ LL | #[cfg(none)]
    |       help: try: `target_os = "none"`
 
 error: operating system used in target family position
-  --> $DIR/mismatched_target_os_non_unix.rs:19:1
-   |
-LL | #[cfg(all(not(any(windows, cloudabi)), wasi))]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: try
-   |
-LL | #[cfg(all(not(any(windows, target_os = "cloudabi")), wasi))]
-   |                            ^^^^^^^^^^^^^^^^^^^^^^
-help: try
+  --> $DIR/mismatched_target_os_non_unix.rs:16:1
    |
-LL | #[cfg(all(not(any(windows, cloudabi)), target_os = "wasi"))]
-   |                                        ^^^^^^^^^^^^^^^^^^
+LL | #[cfg(all(not(windows), wasi))]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^----^^^
+   |                         |
+   |                         help: try: `target_os = "wasi"`
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
index 6001ef37eb781cbb497397e1cbbdb74fd0d7bcb6..44972c8c63964c71e9678d54a49256f34ef54cb4 100644 (file)
@@ -1,5 +1,5 @@
 #![warn(clippy::needless_lifetimes)]
-#![allow(dead_code, clippy::needless_pass_by_value)]
+#![allow(dead_code, clippy::needless_pass_by_value, clippy::unnecessary_wraps)]
 
 fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
 
index 7ea154cb9b0187346be5e41da300559a6050866d..971be26278f3c4276e2d8b0b1490cd62f4902d96 100644 (file)
@@ -1,4 +1,4 @@
-#![allow(unused, clippy::many_single_char_names)]
+#![allow(unused, clippy::many_single_char_names, clippy::diverging_sub_expression)]
 #![warn(clippy::nonminimal_bool)]
 
 fn main() {
index 4de48cd0879a1cda58502936a3533b149567d379..907587402908a7bf09ec65e1bead808c9426239b 100644 (file)
@@ -1,4 +1,4 @@
-#![allow(unused, clippy::many_single_char_names)]
+#![allow(unused, clippy::many_single_char_names, clippy::diverging_sub_expression)]
 #![warn(clippy::nonminimal_bool)]
 
 fn methods_with_negation() {
index 96d1c54946c0b40a7cee773d20f4bc6dfe0408ab..7d29445e66c8b97b8730f096f45db5eb3a321255 100644 (file)
@@ -2,6 +2,7 @@
 
 #![warn(clippy::option_map_unit_fn)]
 #![allow(unused)]
+#![allow(clippy::unnecessary_wraps)]
 
 fn do_nothing<T>(_: T) {}
 
index 931ffc18665938cd3af7a9b592ad71f67a4df96d..b6f834f686f9f34cf68ef9f27dc131a226664ee6 100644 (file)
@@ -2,6 +2,7 @@
 
 #![warn(clippy::option_map_unit_fn)]
 #![allow(unused)]
+#![allow(clippy::unnecessary_wraps)]
 
 fn do_nothing<T>(_: T) {}
 
index d7d45ef9b0b334dd92827e6b92ce32f0e1c864b6..8abdbcafb6e935ed9ae422fc893e801f27363723 100644 (file)
@@ -1,5 +1,5 @@
 error: called `map(f)` on an `Option` value where `f` is a function that returns the unit type `()`
-  --> $DIR/option_map_unit_fn_fixable.rs:38:5
+  --> $DIR/option_map_unit_fn_fixable.rs:39:5
    |
 LL |     x.field.map(do_nothing);
    |     ^^^^^^^^^^^^^^^^^^^^^^^-
@@ -9,7 +9,7 @@ LL |     x.field.map(do_nothing);
    = note: `-D clippy::option-map-unit-fn` implied by `-D warnings`
 
 error: called `map(f)` on an `Option` value where `f` is a function that returns the unit type `()`
-  --> $DIR/option_map_unit_fn_fixable.rs:40:5
+  --> $DIR/option_map_unit_fn_fixable.rs:41:5
    |
 LL |     x.field.map(do_nothing);
    |     ^^^^^^^^^^^^^^^^^^^^^^^-
@@ -17,7 +17,7 @@ LL |     x.field.map(do_nothing);
    |     help: try this: `if let Some(x_field) = x.field { do_nothing(x_field) }`
 
 error: called `map(f)` on an `Option` value where `f` is a function that returns the unit type `()`
-  --> $DIR/option_map_unit_fn_fixable.rs:42:5
+  --> $DIR/option_map_unit_fn_fixable.rs:43:5
    |
 LL |     x.field.map(diverge);
    |     ^^^^^^^^^^^^^^^^^^^^-
@@ -25,7 +25,7 @@ LL |     x.field.map(diverge);
    |     help: try this: `if let Some(x_field) = x.field { diverge(x_field) }`
 
 error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
-  --> $DIR/option_map_unit_fn_fixable.rs:48:5
+  --> $DIR/option_map_unit_fn_fixable.rs:49:5
    |
 LL |     x.field.map(|value| x.do_option_nothing(value + captured));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -33,7 +33,7 @@ LL |     x.field.map(|value| x.do_option_nothing(value + captured));
    |     help: try this: `if let Some(value) = x.field { x.do_option_nothing(value + captured) }`
 
 error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
-  --> $DIR/option_map_unit_fn_fixable.rs:50:5
+  --> $DIR/option_map_unit_fn_fixable.rs:51:5
    |
 LL |     x.field.map(|value| { x.do_option_plus_one(value + captured); });
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -41,7 +41,7 @@ LL |     x.field.map(|value| { x.do_option_plus_one(value + captured); });
    |     help: try this: `if let Some(value) = x.field { x.do_option_plus_one(value + captured); }`
 
 error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
-  --> $DIR/option_map_unit_fn_fixable.rs:53:5
+  --> $DIR/option_map_unit_fn_fixable.rs:54:5
    |
 LL |     x.field.map(|value| do_nothing(value + captured));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -49,7 +49,7 @@ LL |     x.field.map(|value| do_nothing(value + captured));
    |     help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }`
 
 error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
-  --> $DIR/option_map_unit_fn_fixable.rs:55:5
+  --> $DIR/option_map_unit_fn_fixable.rs:56:5
    |
 LL |     x.field.map(|value| { do_nothing(value + captured) });
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -57,7 +57,7 @@ LL |     x.field.map(|value| { do_nothing(value + captured) });
    |     help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }`
 
 error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
-  --> $DIR/option_map_unit_fn_fixable.rs:57:5
+  --> $DIR/option_map_unit_fn_fixable.rs:58:5
    |
 LL |     x.field.map(|value| { do_nothing(value + captured); });
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -65,7 +65,7 @@ LL |     x.field.map(|value| { do_nothing(value + captured); });
    |     help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }`
 
 error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
-  --> $DIR/option_map_unit_fn_fixable.rs:59:5
+  --> $DIR/option_map_unit_fn_fixable.rs:60:5
    |
 LL |     x.field.map(|value| { { do_nothing(value + captured); } });
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -73,7 +73,7 @@ LL |     x.field.map(|value| { { do_nothing(value + captured); } });
    |     help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }`
 
 error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
-  --> $DIR/option_map_unit_fn_fixable.rs:62:5
+  --> $DIR/option_map_unit_fn_fixable.rs:63:5
    |
 LL |     x.field.map(|value| diverge(value + captured));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -81,7 +81,7 @@ LL |     x.field.map(|value| diverge(value + captured));
    |     help: try this: `if let Some(value) = x.field { diverge(value + captured) }`
 
 error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
-  --> $DIR/option_map_unit_fn_fixable.rs:64:5
+  --> $DIR/option_map_unit_fn_fixable.rs:65:5
    |
 LL |     x.field.map(|value| { diverge(value + captured) });
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -89,7 +89,7 @@ LL |     x.field.map(|value| { diverge(value + captured) });
    |     help: try this: `if let Some(value) = x.field { diverge(value + captured) }`
 
 error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
-  --> $DIR/option_map_unit_fn_fixable.rs:66:5
+  --> $DIR/option_map_unit_fn_fixable.rs:67:5
    |
 LL |     x.field.map(|value| { diverge(value + captured); });
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -97,7 +97,7 @@ LL |     x.field.map(|value| { diverge(value + captured); });
    |     help: try this: `if let Some(value) = x.field { diverge(value + captured); }`
 
 error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
-  --> $DIR/option_map_unit_fn_fixable.rs:68:5
+  --> $DIR/option_map_unit_fn_fixable.rs:69:5
    |
 LL |     x.field.map(|value| { { diverge(value + captured); } });
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -105,7 +105,7 @@ LL |     x.field.map(|value| { { diverge(value + captured); } });
    |     help: try this: `if let Some(value) = x.field { diverge(value + captured); }`
 
 error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
-  --> $DIR/option_map_unit_fn_fixable.rs:73:5
+  --> $DIR/option_map_unit_fn_fixable.rs:74:5
    |
 LL |     x.field.map(|value| { let y = plus_one(value + captured); });
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -113,7 +113,7 @@ LL |     x.field.map(|value| { let y = plus_one(value + captured); });
    |     help: try this: `if let Some(value) = x.field { let y = plus_one(value + captured); }`
 
 error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
-  --> $DIR/option_map_unit_fn_fixable.rs:75:5
+  --> $DIR/option_map_unit_fn_fixable.rs:76:5
    |
 LL |     x.field.map(|value| { plus_one(value + captured); });
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -121,7 +121,7 @@ LL |     x.field.map(|value| { plus_one(value + captured); });
    |     help: try this: `if let Some(value) = x.field { plus_one(value + captured); }`
 
 error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
-  --> $DIR/option_map_unit_fn_fixable.rs:77:5
+  --> $DIR/option_map_unit_fn_fixable.rs:78:5
    |
 LL |     x.field.map(|value| { { plus_one(value + captured); } });
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -129,7 +129,7 @@ LL |     x.field.map(|value| { { plus_one(value + captured); } });
    |     help: try this: `if let Some(value) = x.field { plus_one(value + captured); }`
 
 error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
-  --> $DIR/option_map_unit_fn_fixable.rs:80:5
+  --> $DIR/option_map_unit_fn_fixable.rs:81:5
    |
 LL |     x.field.map(|ref value| { do_nothing(value + captured) });
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -137,7 +137,7 @@ LL |     x.field.map(|ref value| { do_nothing(value + captured) });
    |     help: try this: `if let Some(ref value) = x.field { do_nothing(value + captured) }`
 
 error: called `map(f)` on an `Option` value where `f` is a function that returns the unit type `()`
-  --> $DIR/option_map_unit_fn_fixable.rs:82:5
+  --> $DIR/option_map_unit_fn_fixable.rs:83:5
    |
 LL |     option().map(do_nothing);}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^-
index a2617a13ecace67dd0543b49da8e62996b5bdec7..6859ba8e5bb8f08abf23ef45101217cd6ee9ec23 100644 (file)
@@ -1,4 +1,5 @@
 #![deny(clippy::option_option)]
+#![allow(clippy::unnecessary_wraps)]
 
 fn input(_: Option<Option<u8>>) {}
 
@@ -72,8 +73,6 @@ struct Foo<'a> {
         #[serde(skip_serializing_if = "Option::is_none")]
         #[serde(default)]
         #[serde(borrow)]
-        // FIXME: should not lint here
-        #[allow(clippy::option_option)]
         foo: Option<Option<Cow<'a, str>>>,
     }
 
index 0cd4c96eb4f9a17988b9cc86bbd0c71c5ba42353..ad7f081c71392ff9157f80580d1f62a824319b7c 100644 (file)
@@ -1,5 +1,5 @@
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> $DIR/option_option.rs:3:13
+  --> $DIR/option_option.rs:4:13
    |
 LL | fn input(_: Option<Option<u8>>) {}
    |             ^^^^^^^^^^^^^^^^^^
@@ -11,55 +11,55 @@ LL | #![deny(clippy::option_option)]
    |         ^^^^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> $DIR/option_option.rs:5:16
+  --> $DIR/option_option.rs:6:16
    |
 LL | fn output() -> Option<Option<u8>> {
    |                ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> $DIR/option_option.rs:9:27
+  --> $DIR/option_option.rs:10:27
    |
 LL | fn output_nested() -> Vec<Option<Option<u8>>> {
    |                           ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> $DIR/option_option.rs:14:30
+  --> $DIR/option_option.rs:15:30
    |
 LL | fn output_nested_nested() -> Option<Option<Option<u8>>> {
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> $DIR/option_option.rs:19:8
+  --> $DIR/option_option.rs:20:8
    |
 LL |     x: Option<Option<u8>>,
    |        ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> $DIR/option_option.rs:23:23
+  --> $DIR/option_option.rs:24:23
    |
 LL |     fn struct_fn() -> Option<Option<u8>> {
    |                       ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> $DIR/option_option.rs:29:22
+  --> $DIR/option_option.rs:30:22
    |
 LL |     fn trait_fn() -> Option<Option<u8>>;
    |                      ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> $DIR/option_option.rs:33:11
+  --> $DIR/option_option.rs:34:11
    |
 LL |     Tuple(Option<Option<u8>>),
    |           ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> $DIR/option_option.rs:34:17
+  --> $DIR/option_option.rs:35:17
    |
 LL |     Struct { x: Option<Option<u8>> },
    |                 ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> $DIR/option_option.rs:77:14
+  --> $DIR/option_option.rs:76:14
    |
 LL |         foo: Option<Option<Cow<'a, str>>>,
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 2045ffdb5f09d38996c36d57ffc9c56967859d96..2a63318c8c7a8bc7c8f1aa4c34e2ec1cfc943cb5 100644 (file)
@@ -2,6 +2,7 @@
 
 #![warn(clippy::or_fun_call)]
 #![allow(dead_code)]
+#![allow(clippy::unnecessary_wraps)]
 
 use std::collections::BTreeMap;
 use std::collections::HashMap;
@@ -70,6 +71,15 @@ fn or_fun_call() {
     let opt = Some(1);
     let hello = "Hello";
     let _ = opt.ok_or(format!("{} world.", hello));
+
+    // index
+    let map = HashMap::<u64, u64>::new();
+    let _ = Some(1).unwrap_or_else(|| map[&1]);
+    let map = BTreeMap::<u64, u64>::new();
+    let _ = Some(1).unwrap_or_else(|| map[&1]);
+    // don't lint index vec
+    let vec = vec![1];
+    let _ = Some(1).unwrap_or(vec[1]);
 }
 
 struct Foo(u8);
index 522f31b72d01f4d94a590dd179a86c287d1c6db4..026ef437caa1ad29f74d8f2ee7931665a28adab5 100644 (file)
@@ -2,6 +2,7 @@
 
 #![warn(clippy::or_fun_call)]
 #![allow(dead_code)]
+#![allow(clippy::unnecessary_wraps)]
 
 use std::collections::BTreeMap;
 use std::collections::HashMap;
@@ -70,6 +71,15 @@ fn make<T>() -> T {
     let opt = Some(1);
     let hello = "Hello";
     let _ = opt.ok_or(format!("{} world.", hello));
+
+    // index
+    let map = HashMap::<u64, u64>::new();
+    let _ = Some(1).unwrap_or(map[&1]);
+    let map = BTreeMap::<u64, u64>::new();
+    let _ = Some(1).unwrap_or(map[&1]);
+    // don't lint index vec
+    let vec = vec![1];
+    let _ = Some(1).unwrap_or(vec[1]);
 }
 
 struct Foo(u8);
index bc5978b538f16f69901c7d59576e840a95f95e23..fb8bf339828f4ff4e87f4442e2fbf2de42f5be85 100644 (file)
@@ -1,5 +1,5 @@
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:32:19
+  --> $DIR/or_fun_call.rs:33:19
    |
 LL |     with_const_fn.unwrap_or(Duration::from_secs(5));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Duration::from_secs(5))`
@@ -7,88 +7,100 @@ LL |     with_const_fn.unwrap_or(Duration::from_secs(5));
    = note: `-D clippy::or-fun-call` implied by `-D warnings`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:35:22
+  --> $DIR/or_fun_call.rs:36:22
    |
 LL |     with_constructor.unwrap_or(make());
    |                      ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)`
 
 error: use of `unwrap_or` followed by a call to `new`
-  --> $DIR/or_fun_call.rs:38:5
+  --> $DIR/or_fun_call.rs:39:5
    |
 LL |     with_new.unwrap_or(Vec::new());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:41:21
+  --> $DIR/or_fun_call.rs:42:21
    |
 LL |     with_const_args.unwrap_or(Vec::with_capacity(12));
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:44:14
+  --> $DIR/or_fun_call.rs:45:14
    |
 LL |     with_err.unwrap_or(make());
    |              ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:47:19
+  --> $DIR/or_fun_call.rs:48:19
    |
 LL |     with_err_args.unwrap_or(Vec::with_capacity(12));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))`
 
 error: use of `unwrap_or` followed by a call to `default`
-  --> $DIR/or_fun_call.rs:50:5
+  --> $DIR/or_fun_call.rs:51:5
    |
 LL |     with_default_trait.unwrap_or(Default::default());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()`
 
 error: use of `unwrap_or` followed by a call to `default`
-  --> $DIR/or_fun_call.rs:53:5
+  --> $DIR/or_fun_call.rs:54:5
    |
 LL |     with_default_type.unwrap_or(u64::default());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()`
 
 error: use of `unwrap_or` followed by a call to `new`
-  --> $DIR/or_fun_call.rs:56:5
+  --> $DIR/or_fun_call.rs:57:5
    |
 LL |     with_vec.unwrap_or(vec![]);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_vec.unwrap_or_default()`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:59:21
+  --> $DIR/or_fun_call.rs:60:21
    |
 LL |     without_default.unwrap_or(Foo::new());
    |                     ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)`
 
 error: use of `or_insert` followed by a function call
-  --> $DIR/or_fun_call.rs:62:19
+  --> $DIR/or_fun_call.rs:63:19
    |
 LL |     map.entry(42).or_insert(String::new());
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)`
 
 error: use of `or_insert` followed by a function call
-  --> $DIR/or_fun_call.rs:65:21
+  --> $DIR/or_fun_call.rs:66:21
    |
 LL |     btree.entry(42).or_insert(String::new());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:68:21
+  --> $DIR/or_fun_call.rs:69:21
    |
 LL |     let _ = stringy.unwrap_or("".to_owned());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())`
 
+error: use of `unwrap_or` followed by a function call
+  --> $DIR/or_fun_call.rs:77:21
+   |
+LL |     let _ = Some(1).unwrap_or(map[&1]);
+   |                     ^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| map[&1])`
+
+error: use of `unwrap_or` followed by a function call
+  --> $DIR/or_fun_call.rs:79:21
+   |
+LL |     let _ = Some(1).unwrap_or(map[&1]);
+   |                     ^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| map[&1])`
+
 error: use of `or` followed by a function call
-  --> $DIR/or_fun_call.rs:93:35
+  --> $DIR/or_fun_call.rs:103:35
    |
 LL |     let _ = Some("a".to_string()).or(Some("b".to_string()));
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some("b".to_string()))`
 
 error: use of `or` followed by a function call
-  --> $DIR/or_fun_call.rs:97:10
+  --> $DIR/or_fun_call.rs:107:10
    |
 LL |         .or(Some(Bar(b, Duration::from_secs(2))));
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some(Bar(b, Duration::from_secs(2))))`
 
-error: aborting due to 15 previous errors
+error: aborting due to 17 previous errors
 
diff --git a/src/tools/clippy/tests/ui/panic.rs b/src/tools/clippy/tests/ui/panic.rs
deleted file mode 100644 (file)
index 6e004aa..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-#![warn(clippy::panic_params)]
-#![allow(clippy::assertions_on_constants)]
-fn missing() {
-    if true {
-        panic!("{}");
-    } else if false {
-        panic!("{:?}");
-    } else {
-        assert!(true, "here be missing values: {}");
-    }
-
-    panic!("{{{this}}}");
-}
-
-fn ok_single() {
-    panic!("foo bar");
-}
-
-fn ok_inner() {
-    // Test for #768
-    assert!("foo bar".contains(&format!("foo {}", "bar")));
-}
-
-fn ok_multiple() {
-    panic!("{}", "This is {ok}");
-}
-
-fn ok_bracket() {
-    match 42 {
-        1337 => panic!("{so is this"),
-        666 => panic!("so is this}"),
-        _ => panic!("}so is that{"),
-    }
-}
-
-const ONE: u32 = 1;
-
-fn ok_nomsg() {
-    assert!({ 1 == ONE });
-    assert!(if 1 == ONE { ONE == 1 } else { false });
-}
-
-fn ok_escaped() {
-    panic!("{{ why should this not be ok? }}");
-    panic!(" or {{ that ?");
-    panic!(" or }} this ?");
-    panic!(" {or {{ that ?");
-    panic!(" }or }} this ?");
-    panic!("{{ test }");
-    panic!("{case }}");
-}
-
-fn main() {
-    missing();
-    ok_single();
-    ok_multiple();
-    ok_bracket();
-    ok_inner();
-    ok_nomsg();
-    ok_escaped();
-}
diff --git a/src/tools/clippy/tests/ui/panic.stderr b/src/tools/clippy/tests/ui/panic.stderr
deleted file mode 100644 (file)
index 1f8ff8c..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-error: you probably are missing some parameter in your format string
-  --> $DIR/panic.rs:5:16
-   |
-LL |         panic!("{}");
-   |                ^^^^
-   |
-   = note: `-D clippy::panic-params` implied by `-D warnings`
-
-error: you probably are missing some parameter in your format string
-  --> $DIR/panic.rs:7:16
-   |
-LL |         panic!("{:?}");
-   |                ^^^^^^
-
-error: you probably are missing some parameter in your format string
-  --> $DIR/panic.rs:9:23
-   |
-LL |         assert!(true, "here be missing values: {}");
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you probably are missing some parameter in your format string
-  --> $DIR/panic.rs:12:12
-   |
-LL |     panic!("{{{this}}}");
-   |            ^^^^^^^^^^^^
-
-error: aborting due to 4 previous errors
-
index 287726f7a2d4e99e827784da54e9a805e47bba14..3d3c19a1be5199e70c2a08f6c439aaca2e8a9645 100644 (file)
@@ -1,4 +1,5 @@
 #![warn(clippy::panic_in_result_fn)]
+#![allow(clippy::unnecessary_wraps)]
 
 struct A;
 
index c6936fd86923cfab412f794ce9aea9e47a2a43b0..ca73ac5a4111405c946c7dc8f6a422917cae48da 100644 (file)
@@ -1,5 +1,5 @@
 error: used `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` in a function that returns `Result`
-  --> $DIR/panic_in_result_fn.rs:6:5
+  --> $DIR/panic_in_result_fn.rs:7:5
    |
 LL | /     fn result_with_panic() -> Result<bool, String> // should emit lint
 LL | |     {
@@ -10,14 +10,14 @@ LL | |     }
    = note: `-D clippy::panic-in-result-fn` implied by `-D warnings`
    = help: `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing
 note: return Err() instead of panicking
-  --> $DIR/panic_in_result_fn.rs:8:9
+  --> $DIR/panic_in_result_fn.rs:9:9
    |
 LL |         panic!("error");
    |         ^^^^^^^^^^^^^^^^
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: used `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` in a function that returns `Result`
-  --> $DIR/panic_in_result_fn.rs:11:5
+  --> $DIR/panic_in_result_fn.rs:12:5
    |
 LL | /     fn result_with_unimplemented() -> Result<bool, String> // should emit lint
 LL | |     {
@@ -27,14 +27,14 @@ LL | |     }
    |
    = help: `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing
 note: return Err() instead of panicking
-  --> $DIR/panic_in_result_fn.rs:13:9
+  --> $DIR/panic_in_result_fn.rs:14:9
    |
 LL |         unimplemented!();
    |         ^^^^^^^^^^^^^^^^^
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: used `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` in a function that returns `Result`
-  --> $DIR/panic_in_result_fn.rs:16:5
+  --> $DIR/panic_in_result_fn.rs:17:5
    |
 LL | /     fn result_with_unreachable() -> Result<bool, String> // should emit lint
 LL | |     {
@@ -44,14 +44,14 @@ LL | |     }
    |
    = help: `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing
 note: return Err() instead of panicking
-  --> $DIR/panic_in_result_fn.rs:18:9
+  --> $DIR/panic_in_result_fn.rs:19:9
    |
 LL |         unreachable!();
    |         ^^^^^^^^^^^^^^^
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: used `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` in a function that returns `Result`
-  --> $DIR/panic_in_result_fn.rs:21:5
+  --> $DIR/panic_in_result_fn.rs:22:5
    |
 LL | /     fn result_with_todo() -> Result<bool, String> // should emit lint
 LL | |     {
@@ -61,14 +61,14 @@ LL | |     }
    |
    = help: `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing
 note: return Err() instead of panicking
-  --> $DIR/panic_in_result_fn.rs:23:9
+  --> $DIR/panic_in_result_fn.rs:24:9
    |
 LL |         todo!("Finish this");
    |         ^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: used `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` in a function that returns `Result`
-  --> $DIR/panic_in_result_fn.rs:52:1
+  --> $DIR/panic_in_result_fn.rs:53:1
    |
 LL | / fn function_result_with_panic() -> Result<bool, String> // should emit lint
 LL | | {
@@ -78,14 +78,14 @@ LL | | }
    |
    = help: `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing
 note: return Err() instead of panicking
-  --> $DIR/panic_in_result_fn.rs:54:5
+  --> $DIR/panic_in_result_fn.rs:55:5
    |
 LL |     panic!("error");
    |     ^^^^^^^^^^^^^^^^
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: used `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` in a function that returns `Result`
-  --> $DIR/panic_in_result_fn.rs:67:1
+  --> $DIR/panic_in_result_fn.rs:68:1
    |
 LL | / fn main() -> Result<(), String> {
 LL | |     todo!("finish main method");
@@ -95,7 +95,7 @@ LL | | }
    |
    = help: `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing
 note: return Err() instead of panicking
-  --> $DIR/panic_in_result_fn.rs:68:5
+  --> $DIR/panic_in_result_fn.rs:69:5
    |
 LL |     todo!("finish main method");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 11dff94a288657d0c662f383616e2e9b5175509b..0b5746cb52270ed7e59d4126b7664151d1d39e95 100644 (file)
@@ -1,5 +1,6 @@
 // run-rustfix
 #![allow(unreachable_code)]
+#![allow(clippy::unnecessary_wraps)]
 
 fn some_func(a: Option<u32>) -> Option<u32> {
     a?;
index 1d0ee82b4f7787b5e56445c334b2115066804d67..0f0825c9334679d185e9bc711dc86f05df0466d8 100644 (file)
@@ -1,5 +1,6 @@
 // run-rustfix
 #![allow(unreachable_code)]
+#![allow(clippy::unnecessary_wraps)]
 
 fn some_func(a: Option<u32>) -> Option<u32> {
     if a.is_none() {
index 502615fb175a1857b088db3468bccc16d3917992..6f330cfa385dddeaab2c9473fb9c684f381aea27 100644 (file)
@@ -1,5 +1,5 @@
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:5:5
+  --> $DIR/question_mark.rs:6:5
    |
 LL | /     if a.is_none() {
 LL | |         return None;
@@ -9,7 +9,7 @@ LL | |     }
    = note: `-D clippy::question-mark` implied by `-D warnings`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:50:9
+  --> $DIR/question_mark.rs:51:9
    |
 LL | /         if (self.opt).is_none() {
 LL | |             return None;
@@ -17,7 +17,7 @@ LL | |         }
    | |_________^ help: replace it with: `(self.opt)?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:54:9
+  --> $DIR/question_mark.rs:55:9
    |
 LL | /         if self.opt.is_none() {
 LL | |             return None
@@ -25,7 +25,7 @@ LL | |         }
    | |_________^ help: replace it with: `self.opt?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:58:17
+  --> $DIR/question_mark.rs:59:17
    |
 LL |           let _ = if self.opt.is_none() {
    |  _________________^
@@ -36,7 +36,7 @@ LL | |         };
    | |_________^ help: replace it with: `Some(self.opt?)`
 
 error: this if-let-else may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:64:17
+  --> $DIR/question_mark.rs:65:17
    |
 LL |           let _ = if let Some(x) = self.opt {
    |  _________________^
@@ -47,7 +47,7 @@ LL | |         };
    | |_________^ help: replace it with: `self.opt?`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:81:9
+  --> $DIR/question_mark.rs:82:9
    |
 LL | /         if self.opt.is_none() {
 LL | |             return None;
@@ -55,7 +55,7 @@ LL | |         }
    | |_________^ help: replace it with: `self.opt.as_ref()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:89:9
+  --> $DIR/question_mark.rs:90:9
    |
 LL | /         if self.opt.is_none() {
 LL | |             return None;
@@ -63,7 +63,7 @@ LL | |         }
    | |_________^ help: replace it with: `self.opt.as_ref()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:97:9
+  --> $DIR/question_mark.rs:98:9
    |
 LL | /         if self.opt.is_none() {
 LL | |             return None;
@@ -71,7 +71,7 @@ LL | |         }
    | |_________^ help: replace it with: `self.opt.as_ref()?;`
 
 error: this if-let-else may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:104:26
+  --> $DIR/question_mark.rs:105:26
    |
 LL |           let v: &Vec<_> = if let Some(ref v) = self.opt {
    |  __________________________^
@@ -82,7 +82,7 @@ LL | |         };
    | |_________^ help: replace it with: `self.opt.as_ref()?`
 
 error: this if-let-else may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:114:17
+  --> $DIR/question_mark.rs:115:17
    |
 LL |           let v = if let Some(v) = self.opt {
    |  _________________^
@@ -93,7 +93,7 @@ LL | |         };
    | |_________^ help: replace it with: `self.opt?`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:129:5
+  --> $DIR/question_mark.rs:130:5
    |
 LL | /     if f().is_none() {
 LL | |         return None;
index 632a6592a28b84b6831c29dd4e65bb90143d0dbb..048874a7f8294a5d0af9c3365f29572dd38d07f6 100644 (file)
@@ -38,4 +38,9 @@ fn main() {
     x >= 8 || x >= 12;
     x < 12 || 12 < x;
     x >= 8 || x <= 12;
+
+    // Fix #6315
+    let y = 3.;
+    (0. ..1.).contains(&y);
+    !(0. ..=1.).contains(&y);
 }
index 6af0d034ef617b25576507cf407b79a59879ba70..60ad259f404d8201ad16c86923c76442f38696fa 100644 (file)
@@ -38,4 +38,9 @@ fn main() {
     x >= 8 || x >= 12;
     x < 12 || 12 < x;
     x >= 8 || x <= 12;
+
+    // Fix #6315
+    let y = 3.;
+    y >= 0. && y < 1.;
+    y < 0. || y > 1.;
 }
index 69b009eafc30ab589f603f5d9c166072e560d173..bc79f1bca846394bfbcfd50baa39b58cec0dbe53 100644 (file)
@@ -72,5 +72,17 @@ error: manual `!RangeInclusive::contains` implementation
 LL |     999 < x || 1 > x;
    |     ^^^^^^^^^^^^^^^^ help: use: `!(1..=999).contains(&x)`
 
-error: aborting due to 12 previous errors
+error: manual `Range::contains` implementation
+  --> $DIR/range_contains.rs:44:5
+   |
+LL |     y >= 0. && y < 1.;
+   |     ^^^^^^^^^^^^^^^^^ help: use: `(0. ..1.).contains(&y)`
+
+error: manual `!RangeInclusive::contains` implementation
+  --> $DIR/range_contains.rs:45:5
+   |
+LL |     y < 0. || y > 1.;
+   |     ^^^^^^^^^^^^^^^^ help: use: `!(0. ..=1.).contains(&y)`
+
+error: aborting due to 14 previous errors
 
index fe8f62503b76748685eb4df7ca893a038ac65e2f..aa20512296aa1e6c025996d56958ee8b6eff96de 100644 (file)
@@ -7,6 +7,7 @@
     unused_must_use,
     clippy::needless_bool,
     clippy::match_like_matches_macro,
+    clippy::unnecessary_wraps,
     deprecated
 )]
 
index 09426a6e59082275ac3c35124585476add74f551..d76f9c288ffdbfe5608caf10d98e87810ed99d10 100644 (file)
@@ -7,6 +7,7 @@
     unused_must_use,
     clippy::needless_bool,
     clippy::match_like_matches_macro,
+    clippy::unnecessary_wraps,
     deprecated
 )]
 
index 3473ceea00e22ecec0fbdc59fa6c42291a63d3b3..aeb309f5ba12a5f474951bd60577f51929f6e3bf 100644 (file)
@@ -1,5 +1,5 @@
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:15:12
+  --> $DIR/redundant_pattern_matching.rs:16:12
    |
 LL |     if let Ok(_) = &result {}
    |     -------^^^^^---------- help: try this: `if result.is_ok()`
@@ -7,31 +7,31 @@ LL |     if let Ok(_) = &result {}
    = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:17:12
+  --> $DIR/redundant_pattern_matching.rs:18:12
    |
 LL |     if let Ok(_) = Ok::<i32, i32>(42) {}
    |     -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching.rs:19:12
+  --> $DIR/redundant_pattern_matching.rs:20:12
    |
 LL |     if let Err(_) = Err::<i32, i32>(42) {}
    |     -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:21:15
+  --> $DIR/redundant_pattern_matching.rs:22:15
    |
 LL |     while let Ok(_) = Ok::<i32, i32>(10) {}
    |     ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching.rs:23:15
+  --> $DIR/redundant_pattern_matching.rs:24:15
    |
 LL |     while let Err(_) = Ok::<i32, i32>(10) {}
    |     ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:33:5
+  --> $DIR/redundant_pattern_matching.rs:34:5
    |
 LL | /     match Ok::<i32, i32>(42) {
 LL | |         Ok(_) => true,
@@ -40,7 +40,7 @@ LL | |     };
    | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching.rs:38:5
+  --> $DIR/redundant_pattern_matching.rs:39:5
    |
 LL | /     match Ok::<i32, i32>(42) {
 LL | |         Ok(_) => false,
@@ -49,7 +49,7 @@ LL | |     };
    | |_____^ help: try this: `Ok::<i32, i32>(42).is_err()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching.rs:43:5
+  --> $DIR/redundant_pattern_matching.rs:44:5
    |
 LL | /     match Err::<i32, i32>(42) {
 LL | |         Ok(_) => false,
@@ -58,7 +58,7 @@ LL | |     };
    | |_____^ help: try this: `Err::<i32, i32>(42).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:48:5
+  --> $DIR/redundant_pattern_matching.rs:49:5
    |
 LL | /     match Err::<i32, i32>(42) {
 LL | |         Ok(_) => true,
@@ -67,73 +67,73 @@ LL | |     };
    | |_____^ help: try this: `Err::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:53:20
+  --> $DIR/redundant_pattern_matching.rs:54:20
    |
 LL |     let _ = if let Ok(_) = Ok::<usize, ()>(4) { true } else { false };
    |             -------^^^^^--------------------- help: try this: `if Ok::<usize, ()>(4).is_ok()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:59:20
+  --> $DIR/redundant_pattern_matching.rs:60:20
    |
 LL |     let _ = if let Ok(_) = gen_res() {
    |             -------^^^^^------------ help: try this: `if gen_res().is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching.rs:61:19
+  --> $DIR/redundant_pattern_matching.rs:62:19
    |
 LL |     } else if let Err(_) = gen_res() {
    |            -------^^^^^^------------ help: try this: `if gen_res().is_err()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching.rs:84:19
+  --> $DIR/redundant_pattern_matching.rs:85:19
    |
 LL |         while let Some(_) = r#try!(result_opt()) {}
    |         ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching.rs:85:16
+  --> $DIR/redundant_pattern_matching.rs:86:16
    |
 LL |         if let Some(_) = r#try!(result_opt()) {}
    |         -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching.rs:91:12
+  --> $DIR/redundant_pattern_matching.rs:92:12
    |
 LL |     if let Some(_) = m!() {}
    |     -------^^^^^^^------- help: try this: `if m!().is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching.rs:92:15
+  --> $DIR/redundant_pattern_matching.rs:93:15
    |
 LL |     while let Some(_) = m!() {}
    |     ----------^^^^^^^------- help: try this: `while m!().is_some()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:110:12
+  --> $DIR/redundant_pattern_matching.rs:111:12
    |
 LL |     if let Ok(_) = Ok::<i32, i32>(42) {}
    |     -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching.rs:112:12
+  --> $DIR/redundant_pattern_matching.rs:113:12
    |
 LL |     if let Err(_) = Err::<i32, i32>(42) {}
    |     -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:114:15
+  --> $DIR/redundant_pattern_matching.rs:115:15
    |
 LL |     while let Ok(_) = Ok::<i32, i32>(10) {}
    |     ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching.rs:116:15
+  --> $DIR/redundant_pattern_matching.rs:117:15
    |
 LL |     while let Err(_) = Ok::<i32, i32>(10) {}
    |     ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:118:5
+  --> $DIR/redundant_pattern_matching.rs:119:5
    |
 LL | /     match Ok::<i32, i32>(42) {
 LL | |         Ok(_) => true,
@@ -142,7 +142,7 @@ LL | |     };
    | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching.rs:123:5
+  --> $DIR/redundant_pattern_matching.rs:124:5
    |
 LL | /     match Err::<i32, i32>(42) {
 LL | |         Ok(_) => false,
index a66f581b2159f02058a9e29e1f64f416f257feb7..5e57c752b5a034fbe5d2a80588938068a54b384e 100644 (file)
@@ -1,3 +1,4 @@
+#![allow(clippy::unnecessary_wraps)]
 #[warn(clippy::result_unit_err)]
 #[allow(unused)]
 
index b8230032491b65e1c1af8c44b6286f2f29a17978..12901b354f9169d76fdf184a1e27934b6a38d011 100644 (file)
@@ -1,5 +1,5 @@
 error: this returns a `Result<_, ()>
-  --> $DIR/result_unit_error.rs:4:1
+  --> $DIR/result_unit_error.rs:5:1
    |
 LL | pub fn returns_unit_error() -> Result<u32, ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL | pub fn returns_unit_error() -> Result<u32, ()> {
    = help: use a custom Error type instead
 
 error: this returns a `Result<_, ()>
-  --> $DIR/result_unit_error.rs:13:5
+  --> $DIR/result_unit_error.rs:14:5
    |
 LL |     fn get_that_error(&self) -> Result<bool, ()>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL |     fn get_that_error(&self) -> Result<bool, ()>;
    = help: use a custom Error type instead
 
 error: this returns a `Result<_, ()>
-  --> $DIR/result_unit_error.rs:15:5
+  --> $DIR/result_unit_error.rs:16:5
    |
 LL |     fn get_this_one_too(&self) -> Result<bool, ()> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,7 +24,7 @@ LL |     fn get_this_one_too(&self) -> Result<bool, ()> {
    = help: use a custom Error type instead
 
 error: this returns a `Result<_, ()>
-  --> $DIR/result_unit_error.rs:33:5
+  --> $DIR/result_unit_error.rs:34:5
    |
 LL |     pub fn unit_error(&self) -> Result<usize, ()> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/search_is_some.rs b/src/tools/clippy/tests/ui/search_is_some.rs
new file mode 100644 (file)
index 0000000..f0dc3b3
--- /dev/null
@@ -0,0 +1,38 @@
+// aux-build:option_helpers.rs
+extern crate option_helpers;
+use option_helpers::IteratorFalsePositives;
+
+#[warn(clippy::search_is_some)]
+#[rustfmt::skip]
+fn main() {
+    let v = vec![3, 2, 1, 0, -1, -2, -3];
+    let y = &&42;
+
+
+    // Check `find().is_some()`, multi-line case.
+    let _ = v.iter().find(|&x| {
+                              *x < 0
+                          }
+                   ).is_some();
+
+    // Check `position().is_some()`, multi-line case.
+    let _ = v.iter().position(|&x| {
+                                  x < 0
+                              }
+                   ).is_some();
+
+    // Check `rposition().is_some()`, multi-line case.
+    let _ = v.iter().rposition(|&x| {
+                                   x < 0
+                               }
+                   ).is_some();
+
+    // Check that we don't lint if the caller is not an `Iterator` or string
+    let falsepos = IteratorFalsePositives { foo: 0 };
+    let _ = falsepos.find().is_some();
+    let _ = falsepos.position().is_some();
+    let _ = falsepos.rposition().is_some();
+    // check that we don't lint if `find()` is called with
+    // `Pattern` that is not a string
+    let _ = "hello world".find(|c: char| c == 'o' || c == 'l').is_some();
+}
diff --git a/src/tools/clippy/tests/ui/search_is_some.stderr b/src/tools/clippy/tests/ui/search_is_some.stderr
new file mode 100644 (file)
index 0000000..c601f56
--- /dev/null
@@ -0,0 +1,39 @@
+error: called `is_some()` after searching an `Iterator` with `find`
+  --> $DIR/search_is_some.rs:13:13
+   |
+LL |       let _ = v.iter().find(|&x| {
+   |  _____________^
+LL | |                               *x < 0
+LL | |                           }
+LL | |                    ).is_some();
+   | |______________________________^
+   |
+   = note: `-D clippy::search-is-some` implied by `-D warnings`
+   = help: this is more succinctly expressed by calling `any()`
+
+error: called `is_some()` after searching an `Iterator` with `position`
+  --> $DIR/search_is_some.rs:19:13
+   |
+LL |       let _ = v.iter().position(|&x| {
+   |  _____________^
+LL | |                                   x < 0
+LL | |                               }
+LL | |                    ).is_some();
+   | |______________________________^
+   |
+   = help: this is more succinctly expressed by calling `any()`
+
+error: called `is_some()` after searching an `Iterator` with `rposition`
+  --> $DIR/search_is_some.rs:25:13
+   |
+LL |       let _ = v.iter().rposition(|&x| {
+   |  _____________^
+LL | |                                    x < 0
+LL | |                                }
+LL | |                    ).is_some();
+   | |______________________________^
+   |
+   = help: this is more succinctly expressed by calling `any()`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable.fixed b/src/tools/clippy/tests/ui/search_is_some_fixable.fixed
new file mode 100644 (file)
index 0000000..dc3f290
--- /dev/null
@@ -0,0 +1,35 @@
+// run-rustfix
+
+#![warn(clippy::search_is_some)]
+
+fn main() {
+    let v = vec![3, 2, 1, 0, -1, -2, -3];
+    let y = &&42;
+
+    // Check `find().is_some()`, single-line case.
+    let _ = v.iter().any(|x| *x < 0);
+    let _ = (0..1).any(|x| **y == x); // one dereference less
+    let _ = (0..1).any(|x| x == 0);
+    let _ = v.iter().any(|x| *x == 0);
+
+    // Check `position().is_some()`, single-line case.
+    let _ = v.iter().any(|&x| x < 0);
+
+    // Check `rposition().is_some()`, single-line case.
+    let _ = v.iter().any(|&x| x < 0);
+
+    let s1 = String::from("hello world");
+    let s2 = String::from("world");
+    // caller of `find()` is a `&`static str`
+    let _ = "hello world".contains("world");
+    let _ = "hello world".contains(&s2);
+    let _ = "hello world".contains(&s2[2..]);
+    // caller of `find()` is a `String`
+    let _ = s1.contains("world");
+    let _ = s1.contains(&s2);
+    let _ = s1.contains(&s2[2..]);
+    // caller of `find()` is slice of `String`
+    let _ = s1[2..].contains("world");
+    let _ = s1[2..].contains(&s2);
+    let _ = s1[2..].contains(&s2[2..]);
+}
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable.rs b/src/tools/clippy/tests/ui/search_is_some_fixable.rs
new file mode 100644 (file)
index 0000000..146cf5a
--- /dev/null
@@ -0,0 +1,35 @@
+// run-rustfix
+
+#![warn(clippy::search_is_some)]
+
+fn main() {
+    let v = vec![3, 2, 1, 0, -1, -2, -3];
+    let y = &&42;
+
+    // Check `find().is_some()`, single-line case.
+    let _ = v.iter().find(|&x| *x < 0).is_some();
+    let _ = (0..1).find(|x| **y == *x).is_some(); // one dereference less
+    let _ = (0..1).find(|x| *x == 0).is_some();
+    let _ = v.iter().find(|x| **x == 0).is_some();
+
+    // Check `position().is_some()`, single-line case.
+    let _ = v.iter().position(|&x| x < 0).is_some();
+
+    // Check `rposition().is_some()`, single-line case.
+    let _ = v.iter().rposition(|&x| x < 0).is_some();
+
+    let s1 = String::from("hello world");
+    let s2 = String::from("world");
+    // caller of `find()` is a `&`static str`
+    let _ = "hello world".find("world").is_some();
+    let _ = "hello world".find(&s2).is_some();
+    let _ = "hello world".find(&s2[2..]).is_some();
+    // caller of `find()` is a `String`
+    let _ = s1.find("world").is_some();
+    let _ = s1.find(&s2).is_some();
+    let _ = s1.find(&s2[2..]).is_some();
+    // caller of `find()` is slice of `String`
+    let _ = s1[2..].find("world").is_some();
+    let _ = s1[2..].find(&s2).is_some();
+    let _ = s1[2..].find(&s2[2..]).is_some();
+}
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable.stderr b/src/tools/clippy/tests/ui/search_is_some_fixable.stderr
new file mode 100644 (file)
index 0000000..23c1d9a
--- /dev/null
@@ -0,0 +1,94 @@
+error: called `is_some()` after searching an `Iterator` with `find`
+  --> $DIR/search_is_some_fixable.rs:10:22
+   |
+LL |     let _ = v.iter().find(|&x| *x < 0).is_some();
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x| *x < 0)`
+   |
+   = note: `-D clippy::search-is-some` implied by `-D warnings`
+
+error: called `is_some()` after searching an `Iterator` with `find`
+  --> $DIR/search_is_some_fixable.rs:11:20
+   |
+LL |     let _ = (0..1).find(|x| **y == *x).is_some(); // one dereference less
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x| **y == x)`
+
+error: called `is_some()` after searching an `Iterator` with `find`
+  --> $DIR/search_is_some_fixable.rs:12:20
+   |
+LL |     let _ = (0..1).find(|x| *x == 0).is_some();
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x| x == 0)`
+
+error: called `is_some()` after searching an `Iterator` with `find`
+  --> $DIR/search_is_some_fixable.rs:13:22
+   |
+LL |     let _ = v.iter().find(|x| **x == 0).is_some();
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x| *x == 0)`
+
+error: called `is_some()` after searching an `Iterator` with `position`
+  --> $DIR/search_is_some_fixable.rs:16:22
+   |
+LL |     let _ = v.iter().position(|&x| x < 0).is_some();
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|&x| x < 0)`
+
+error: called `is_some()` after searching an `Iterator` with `rposition`
+  --> $DIR/search_is_some_fixable.rs:19:22
+   |
+LL |     let _ = v.iter().rposition(|&x| x < 0).is_some();
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|&x| x < 0)`
+
+error: called `is_some()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable.rs:24:27
+   |
+LL |     let _ = "hello world".find("world").is_some();
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^ help: use `contains()` instead: `contains("world")`
+
+error: called `is_some()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable.rs:25:27
+   |
+LL |     let _ = "hello world".find(&s2).is_some();
+   |                           ^^^^^^^^^^^^^^^^^^^ help: use `contains()` instead: `contains(&s2)`
+
+error: called `is_some()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable.rs:26:27
+   |
+LL |     let _ = "hello world".find(&s2[2..]).is_some();
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `contains()` instead: `contains(&s2[2..])`
+
+error: called `is_some()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable.rs:28:16
+   |
+LL |     let _ = s1.find("world").is_some();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^ help: use `contains()` instead: `contains("world")`
+
+error: called `is_some()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable.rs:29:16
+   |
+LL |     let _ = s1.find(&s2).is_some();
+   |                ^^^^^^^^^^^^^^^^^^^ help: use `contains()` instead: `contains(&s2)`
+
+error: called `is_some()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable.rs:30:16
+   |
+LL |     let _ = s1.find(&s2[2..]).is_some();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `contains()` instead: `contains(&s2[2..])`
+
+error: called `is_some()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable.rs:32:21
+   |
+LL |     let _ = s1[2..].find("world").is_some();
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^ help: use `contains()` instead: `contains("world")`
+
+error: called `is_some()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable.rs:33:21
+   |
+LL |     let _ = s1[2..].find(&s2).is_some();
+   |                     ^^^^^^^^^^^^^^^^^^^ help: use `contains()` instead: `contains(&s2)`
+
+error: called `is_some()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable.rs:34:21
+   |
+LL |     let _ = s1[2..].find(&s2[2..]).is_some();
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `contains()` instead: `contains(&s2[2..])`
+
+error: aborting due to 15 previous errors
+
diff --git a/src/tools/clippy/tests/ui/string_from_utf8_as_bytes.fixed b/src/tools/clippy/tests/ui/string_from_utf8_as_bytes.fixed
new file mode 100644 (file)
index 0000000..6e665cd
--- /dev/null
@@ -0,0 +1,6 @@
+// run-rustfix
+#![warn(clippy::string_from_utf8_as_bytes)]
+
+fn main() {
+    let _ = Some(&"Hello World!"[6..11]);
+}
diff --git a/src/tools/clippy/tests/ui/string_from_utf8_as_bytes.rs b/src/tools/clippy/tests/ui/string_from_utf8_as_bytes.rs
new file mode 100644 (file)
index 0000000..670d206
--- /dev/null
@@ -0,0 +1,6 @@
+// run-rustfix
+#![warn(clippy::string_from_utf8_as_bytes)]
+
+fn main() {
+    let _ = std::str::from_utf8(&"Hello World!".as_bytes()[6..11]);
+}
diff --git a/src/tools/clippy/tests/ui/string_from_utf8_as_bytes.stderr b/src/tools/clippy/tests/ui/string_from_utf8_as_bytes.stderr
new file mode 100644 (file)
index 0000000..bf5e5d3
--- /dev/null
@@ -0,0 +1,10 @@
+error: calling a slice of `as_bytes()` with `from_utf8` should be not necessary
+  --> $DIR/string_from_utf8_as_bytes.rs:5:13
+   |
+LL |     let _ = std::str::from_utf8(&"Hello World!".as_bytes()[6..11]);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(&"Hello World!"[6..11])`
+   |
+   = note: `-D clippy::string-from-utf8-as-bytes` implied by `-D warnings`
+
+error: aborting due to previous error
+
index 9e77dcd8731642567072e5ff8ac0a8a12db38cd5..652b611208b7376140f062e1a9c93d2be54d89b2 100644 (file)
@@ -2,6 +2,7 @@
 // aux-build:macro_rules.rs
 
 #![deny(clippy::try_err)]
+#![allow(clippy::unnecessary_wraps)]
 
 #[macro_use]
 extern crate macro_rules;
@@ -78,12 +79,46 @@ fn nested_error() -> Result<i32, i32> {
     Ok(1)
 }
 
+// Bad suggestion when in macro (see #6242)
+macro_rules! try_validation {
+    ($e: expr) => {{
+        match $e {
+            Ok(_) => 0,
+            Err(_) => return Err(1),
+        }
+    }};
+}
+
+macro_rules! ret_one {
+    () => {
+        1
+    };
+}
+
+macro_rules! try_validation_in_macro {
+    ($e: expr) => {{
+        match $e {
+            Ok(_) => 0,
+            Err(_) => return Err(ret_one!()),
+        }
+    }};
+}
+
+fn calling_macro() -> Result<i32, i32> {
+    // macro
+    try_validation!(Ok::<_, i32>(5));
+    // `Err` arg is another macro
+    try_validation_in_macro!(Ok::<_, i32>(5));
+    Ok(5)
+}
+
 fn main() {
     basic_test().unwrap();
     into_test().unwrap();
     negative_test().unwrap();
     closure_matches_test().unwrap();
     closure_into_test().unwrap();
+    calling_macro().unwrap();
 
     // We don't want to lint in external macros
     try_err!();
index 41bcb0a189e76de98a567bcb3db02caf9bd82354..6bd479657b70bb1041a91663b9e8357bfbeb9b36 100644 (file)
@@ -2,6 +2,7 @@
 // aux-build:macro_rules.rs
 
 #![deny(clippy::try_err)]
+#![allow(clippy::unnecessary_wraps)]
 
 #[macro_use]
 extern crate macro_rules;
@@ -78,12 +79,46 @@ fn nested_error() -> Result<i32, i32> {
     Ok(1)
 }
 
+// Bad suggestion when in macro (see #6242)
+macro_rules! try_validation {
+    ($e: expr) => {{
+        match $e {
+            Ok(_) => 0,
+            Err(_) => Err(1)?,
+        }
+    }};
+}
+
+macro_rules! ret_one {
+    () => {
+        1
+    };
+}
+
+macro_rules! try_validation_in_macro {
+    ($e: expr) => {{
+        match $e {
+            Ok(_) => 0,
+            Err(_) => Err(ret_one!())?,
+        }
+    }};
+}
+
+fn calling_macro() -> Result<i32, i32> {
+    // macro
+    try_validation!(Ok::<_, i32>(5));
+    // `Err` arg is another macro
+    try_validation_in_macro!(Ok::<_, i32>(5));
+    Ok(5)
+}
+
 fn main() {
     basic_test().unwrap();
     into_test().unwrap();
     negative_test().unwrap();
     closure_matches_test().unwrap();
     closure_into_test().unwrap();
+    calling_macro().unwrap();
 
     // We don't want to lint in external macros
     try_err!();
index 3f1cbc17e72d08ff35e90bfc0e9333472d1473f8..2c01d37192e8e296439258134367a1c37a5c6c63 100644 (file)
@@ -1,5 +1,5 @@
 error: returning an `Err(_)` with the `?` operator
-  --> $DIR/try_err.rs:18:9
+  --> $DIR/try_err.rs:19:9
    |
 LL |         Err(err)?;
    |         ^^^^^^^^^ help: try this: `return Err(err)`
@@ -11,46 +11,68 @@ LL | #![deny(clippy::try_err)]
    |         ^^^^^^^^^^^^^^^
 
 error: returning an `Err(_)` with the `?` operator
-  --> $DIR/try_err.rs:28:9
+  --> $DIR/try_err.rs:29:9
    |
 LL |         Err(err)?;
    |         ^^^^^^^^^ help: try this: `return Err(err.into())`
 
 error: returning an `Err(_)` with the `?` operator
-  --> $DIR/try_err.rs:48:17
+  --> $DIR/try_err.rs:49:17
    |
 LL |                 Err(err)?;
    |                 ^^^^^^^^^ help: try this: `return Err(err)`
 
 error: returning an `Err(_)` with the `?` operator
-  --> $DIR/try_err.rs:67:17
+  --> $DIR/try_err.rs:68:17
    |
 LL |                 Err(err)?;
    |                 ^^^^^^^^^ help: try this: `return Err(err.into())`
 
 error: returning an `Err(_)` with the `?` operator
-  --> $DIR/try_err.rs:106:9
+  --> $DIR/try_err.rs:87:23
+   |
+LL |             Err(_) => Err(1)?,
+   |                       ^^^^^^^ help: try this: `return Err(1)`
+...
+LL |     try_validation!(Ok::<_, i32>(5));
+   |     --------------------------------- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: returning an `Err(_)` with the `?` operator
+  --> $DIR/try_err.rs:102:23
+   |
+LL |             Err(_) => Err(ret_one!())?,
+   |                       ^^^^^^^^^^^^^^^^ help: try this: `return Err(ret_one!())`
+...
+LL |     try_validation_in_macro!(Ok::<_, i32>(5));
+   |     ------------------------------------------ in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: returning an `Err(_)` with the `?` operator
+  --> $DIR/try_err.rs:141:9
    |
 LL |         Err(foo!())?;
    |         ^^^^^^^^^^^^ help: try this: `return Err(foo!())`
 
 error: returning an `Err(_)` with the `?` operator
-  --> $DIR/try_err.rs:113:9
+  --> $DIR/try_err.rs:148:9
    |
 LL |         Err(io::ErrorKind::WriteZero)?
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `return Poll::Ready(Err(io::ErrorKind::WriteZero.into()))`
 
 error: returning an `Err(_)` with the `?` operator
-  --> $DIR/try_err.rs:115:9
+  --> $DIR/try_err.rs:150:9
    |
 LL |         Err(io::Error::new(io::ErrorKind::InvalidInput, "error"))?
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `return Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, "error")))`
 
 error: returning an `Err(_)` with the `?` operator
-  --> $DIR/try_err.rs:123:9
+  --> $DIR/try_err.rs:158:9
    |
 LL |         Err(io::ErrorKind::NotFound)?
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `return Poll::Ready(Some(Err(io::ErrorKind::NotFound.into())))`
 
-error: aborting due to 8 previous errors
+error: aborting due to 10 previous errors
 
index fec115ff29d6699cd82adafbf5d34dbcc1e25d3a..9ad16d365094e73b165124cc68b35fe28c7172a1 100644 (file)
@@ -4,6 +4,7 @@
     unused_must_use,
     unused_variables,
     clippy::unused_unit,
+    clippy::unnecessary_wraps,
     clippy::or_fun_call
 )]
 
index 90fee3aab23b0c96cd3b8cff521f208ad8cff55d..c3a839a9bf8120fcefe07023da88df1948f89ff8 100644 (file)
@@ -1,5 +1,5 @@
 error: passing a unit value to a function
-  --> $DIR/unit_arg.rs:29:5
+  --> $DIR/unit_arg.rs:30:5
    |
 LL | /     foo({
 LL | |         1;
@@ -20,7 +20,7 @@ LL |     foo(());
    |
 
 error: passing a unit value to a function
-  --> $DIR/unit_arg.rs:32:5
+  --> $DIR/unit_arg.rs:33:5
    |
 LL |     foo(foo(1));
    |     ^^^^^^^^^^^
@@ -32,7 +32,7 @@ LL |     foo(());
    |
 
 error: passing a unit value to a function
-  --> $DIR/unit_arg.rs:33:5
+  --> $DIR/unit_arg.rs:34:5
    |
 LL | /     foo({
 LL | |         foo(1);
@@ -54,7 +54,7 @@ LL |     foo(());
    |
 
 error: passing a unit value to a function
-  --> $DIR/unit_arg.rs:38:5
+  --> $DIR/unit_arg.rs:39:5
    |
 LL | /     b.bar({
 LL | |         1;
@@ -74,7 +74,7 @@ LL |     b.bar(());
    |
 
 error: passing unit values to a function
-  --> $DIR/unit_arg.rs:41:5
+  --> $DIR/unit_arg.rs:42:5
    |
 LL |     taking_multiple_units(foo(0), foo(1));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -87,7 +87,7 @@ LL |     taking_multiple_units((), ());
    |
 
 error: passing unit values to a function
-  --> $DIR/unit_arg.rs:42:5
+  --> $DIR/unit_arg.rs:43:5
    |
 LL | /     taking_multiple_units(foo(0), {
 LL | |         foo(1);
@@ -110,7 +110,7 @@ LL |     taking_multiple_units((), ());
    |
 
 error: passing unit values to a function
-  --> $DIR/unit_arg.rs:46:5
+  --> $DIR/unit_arg.rs:47:5
    |
 LL | /     taking_multiple_units(
 LL | |         {
@@ -140,7 +140,7 @@ LL |         foo(2);
  ...
 
 error: passing a unit value to a function
-  --> $DIR/unit_arg.rs:57:13
+  --> $DIR/unit_arg.rs:58:13
    |
 LL |     None.or(Some(foo(2)));
    |             ^^^^^^^^^^^^
@@ -154,7 +154,7 @@ LL |     });
    |
 
 error: passing a unit value to a function
-  --> $DIR/unit_arg.rs:60:5
+  --> $DIR/unit_arg.rs:61:5
    |
 LL |     foo(foo(()))
    |     ^^^^^^^^^^^^
@@ -166,7 +166,7 @@ LL |     foo(())
    |
 
 error: passing a unit value to a function
-  --> $DIR/unit_arg.rs:93:5
+  --> $DIR/unit_arg.rs:94:5
    |
 LL |     Some(foo(1))
    |     ^^^^^^^^^^^^
index e785ac02feb320e4c4fb1c54e671a335a4a3d3fc..6770a7fac90fdc6343092d5e05a02e750d4a0019 100644 (file)
@@ -1,7 +1,7 @@
 // does not test any rustfixable lints
 
 #![warn(clippy::clone_on_ref_ptr)]
-#![allow(unused, clippy::redundant_clone)]
+#![allow(unused, clippy::redundant_clone, clippy::unnecessary_wraps)]
 
 use std::cell::RefCell;
 use std::rc::{self, Rc};
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.rs b/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.rs
new file mode 100644 (file)
index 0000000..2e923bc
--- /dev/null
@@ -0,0 +1,18 @@
+#![warn(clippy::unnecessary_lazy_evaluations)]
+
+struct Deep(Option<usize>);
+
+#[derive(Copy, Clone)]
+struct SomeStruct {
+    some_field: usize,
+}
+
+fn main() {
+    // fix will break type inference
+    let _ = Ok(1).unwrap_or_else(|()| 2);
+    mod e {
+        pub struct E;
+    }
+    let _ = Ok(1).unwrap_or_else(|e::E| 2);
+    let _ = Ok(1).unwrap_or_else(|SomeStruct { .. }| 2);
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.stderr b/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.stderr
new file mode 100644 (file)
index 0000000..581d641
--- /dev/null
@@ -0,0 +1,22 @@
+error: unnecessary closure used to substitute value for `Result::Err`
+  --> $DIR/unnecessary_lazy_eval_unfixable.rs:12:13
+   |
+LL |     let _ = Ok(1).unwrap_or_else(|()| 2);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `Ok(1).unwrap_or(2)`
+   |
+   = note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings`
+
+error: unnecessary closure used to substitute value for `Result::Err`
+  --> $DIR/unnecessary_lazy_eval_unfixable.rs:16:13
+   |
+LL |     let _ = Ok(1).unwrap_or_else(|e::E| 2);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `Ok(1).unwrap_or(2)`
+
+error: unnecessary closure used to substitute value for `Result::Err`
+  --> $DIR/unnecessary_lazy_eval_unfixable.rs:17:13
+   |
+LL |     let _ = Ok(1).unwrap_or_else(|SomeStruct { .. }| 2);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `Ok(1).unwrap_or(2)`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/unnecessary_wraps.rs b/src/tools/clippy/tests/ui/unnecessary_wraps.rs
new file mode 100644 (file)
index 0000000..a53dec8
--- /dev/null
@@ -0,0 +1,116 @@
+#![warn(clippy::unnecessary_wraps)]
+#![allow(clippy::no_effect)]
+#![allow(clippy::needless_return)]
+#![allow(clippy::if_same_then_else)]
+#![allow(dead_code)]
+
+// should be linted
+fn func1(a: bool, b: bool) -> Option<i32> {
+    if a && b {
+        return Some(42);
+    }
+    if a {
+        Some(-1);
+        Some(2)
+    } else {
+        return Some(1337);
+    }
+}
+
+// should be linted
+fn func2(a: bool, b: bool) -> Option<i32> {
+    if a && b {
+        return Some(10);
+    }
+    if a {
+        Some(20)
+    } else {
+        Some(30)
+    }
+}
+
+// public fns should not be linted
+pub fn func3(a: bool) -> Option<i32> {
+    if a {
+        Some(1)
+    } else {
+        Some(1)
+    }
+}
+
+// should not be linted
+fn func4(a: bool) -> Option<i32> {
+    if a {
+        Some(1)
+    } else {
+        None
+    }
+}
+
+// should be linted
+fn func5() -> Option<i32> {
+    Some(1)
+}
+
+// should not be linted
+fn func6() -> Option<i32> {
+    None
+}
+
+// should be linted
+fn func7() -> Result<i32, ()> {
+    Ok(1)
+}
+
+// should not be linted
+fn func8(a: bool) -> Result<i32, ()> {
+    if a {
+        Ok(1)
+    } else {
+        Err(())
+    }
+}
+
+// should not be linted
+fn func9(a: bool) -> Result<i32, ()> {
+    Err(())
+}
+
+// should not be linted
+fn func10() -> Option<()> {
+    unimplemented!()
+}
+
+struct A;
+
+impl A {
+    // should not be linted
+    pub fn func11() -> Option<i32> {
+        Some(1)
+    }
+
+    // should be linted
+    fn func12() -> Option<i32> {
+        Some(1)
+    }
+}
+
+trait B {
+    // trait impls are not linted
+    fn func13() -> Option<i32> {
+        Some(1)
+    }
+}
+
+impl B for A {
+    // trait impls are not linted
+    fn func13() -> Option<i32> {
+        Some(0)
+    }
+}
+
+fn main() {
+    // method calls are not linted
+    func1(true, true);
+    func2(true, true);
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_wraps.stderr b/src/tools/clippy/tests/ui/unnecessary_wraps.stderr
new file mode 100644 (file)
index 0000000..410f054
--- /dev/null
@@ -0,0 +1,106 @@
+error: this function's return value is unnecessarily wrapped by `Option`
+  --> $DIR/unnecessary_wraps.rs:8:1
+   |
+LL | / fn func1(a: bool, b: bool) -> Option<i32> {
+LL | |     if a && b {
+LL | |         return Some(42);
+LL | |     }
+...  |
+LL | |     }
+LL | | }
+   | |_^
+   |
+   = note: `-D clippy::unnecessary-wraps` implied by `-D warnings`
+help: remove `Option` from the return type...
+   |
+LL | fn func1(a: bool, b: bool) -> i32 {
+   |                               ^^^
+help: ...and change the returning expressions
+   |
+LL |         return 42;
+LL |     }
+LL |     if a {
+LL |         Some(-1);
+LL |         2
+LL |     } else {
+ ...
+
+error: this function's return value is unnecessarily wrapped by `Option`
+  --> $DIR/unnecessary_wraps.rs:21:1
+   |
+LL | / fn func2(a: bool, b: bool) -> Option<i32> {
+LL | |     if a && b {
+LL | |         return Some(10);
+LL | |     }
+...  |
+LL | |     }
+LL | | }
+   | |_^
+   |
+help: remove `Option` from the return type...
+   |
+LL | fn func2(a: bool, b: bool) -> i32 {
+   |                               ^^^
+help: ...and change the returning expressions
+   |
+LL |         return 10;
+LL |     }
+LL |     if a {
+LL |         20
+LL |     } else {
+LL |         30
+   |
+
+error: this function's return value is unnecessarily wrapped by `Option`
+  --> $DIR/unnecessary_wraps.rs:51:1
+   |
+LL | / fn func5() -> Option<i32> {
+LL | |     Some(1)
+LL | | }
+   | |_^
+   |
+help: remove `Option` from the return type...
+   |
+LL | fn func5() -> i32 {
+   |               ^^^
+help: ...and change the returning expressions
+   |
+LL |     1
+   |
+
+error: this function's return value is unnecessarily wrapped by `Result`
+  --> $DIR/unnecessary_wraps.rs:61:1
+   |
+LL | / fn func7() -> Result<i32, ()> {
+LL | |     Ok(1)
+LL | | }
+   | |_^
+   |
+help: remove `Result` from the return type...
+   |
+LL | fn func7() -> i32 {
+   |               ^^^
+help: ...and change the returning expressions
+   |
+LL |     1
+   |
+
+error: this function's return value is unnecessarily wrapped by `Option`
+  --> $DIR/unnecessary_wraps.rs:93:5
+   |
+LL | /     fn func12() -> Option<i32> {
+LL | |         Some(1)
+LL | |     }
+   | |_____^
+   |
+help: remove `Option` from the return type...
+   |
+LL |     fn func12() -> i32 {
+   |                    ^^^
+help: ...and change the returning expressions
+   |
+LL |         1
+   |
+
+error: aborting due to 5 previous errors
+
index 8a9b0cd3cf019466d3786f7be3eb08ceda2f0509..03977de9455ebb34a380a4b1b591a46c105576bb 100644 (file)
@@ -1,6 +1,7 @@
 // run-rustfix
 
 #![deny(clippy::useless_conversion)]
+#![allow(clippy::unnecessary_wraps)]
 
 fn test_generic<T: Copy>(val: T) -> T {
     let _ = val;
index 4faa1572973bc0ff5df24d3c2fe392e49d219c0d..f6e094c16616c438b98e13bb5f93427ff850038d 100644 (file)
@@ -1,6 +1,7 @@
 // run-rustfix
 
 #![deny(clippy::useless_conversion)]
+#![allow(clippy::unnecessary_wraps)]
 
 fn test_generic<T: Copy>(val: T) -> T {
     let _ = T::from(val);
index 11c6efb25cceace746742c0bf5677c2c21b5043d..26a33595031bd9455e54317395bf978e55ee7b1f 100644 (file)
@@ -1,5 +1,5 @@
 error: useless conversion to the same type: `T`
-  --> $DIR/useless_conversion.rs:6:13
+  --> $DIR/useless_conversion.rs:7:13
    |
 LL |     let _ = T::from(val);
    |             ^^^^^^^^^^^^ help: consider removing `T::from()`: `val`
@@ -11,61 +11,61 @@ LL | #![deny(clippy::useless_conversion)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: useless conversion to the same type: `T`
-  --> $DIR/useless_conversion.rs:7:5
+  --> $DIR/useless_conversion.rs:8:5
    |
 LL |     val.into()
    |     ^^^^^^^^^^ help: consider removing `.into()`: `val`
 
 error: useless conversion to the same type: `i32`
-  --> $DIR/useless_conversion.rs:19:22
+  --> $DIR/useless_conversion.rs:20:22
    |
 LL |         let _: i32 = 0i32.into();
    |                      ^^^^^^^^^^^ help: consider removing `.into()`: `0i32`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion.rs:60:21
+  --> $DIR/useless_conversion.rs:61:21
    |
 LL |     let _: String = "foo".to_string().into();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion.rs:61:21
+  --> $DIR/useless_conversion.rs:62:21
    |
 LL |     let _: String = From::from("foo".to_string());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion.rs:62:13
+  --> $DIR/useless_conversion.rs:63:13
    |
 LL |     let _ = String::from("foo".to_string());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion.rs:63:13
+  --> $DIR/useless_conversion.rs:64:13
    |
 LL |     let _ = String::from(format!("A: {:04}", 123));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)`
 
 error: useless conversion to the same type: `std::str::Lines`
-  --> $DIR/useless_conversion.rs:64:13
+  --> $DIR/useless_conversion.rs:65:13
    |
 LL |     let _ = "".lines().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()`
 
 error: useless conversion to the same type: `std::vec::IntoIter<i32>`
-  --> $DIR/useless_conversion.rs:65:13
+  --> $DIR/useless_conversion.rs:66:13
    |
 LL |     let _ = vec![1, 2, 3].into_iter().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion.rs:66:21
+  --> $DIR/useless_conversion.rs:67:21
    |
 LL |     let _: String = format!("Hello {}", "world").into();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")`
 
 error: useless conversion to the same type: `i32`
-  --> $DIR/useless_conversion.rs:71:13
+  --> $DIR/useless_conversion.rs:72:13
    |
 LL |     let _ = i32::from(a + b) * 3;
    |             ^^^^^^^^^^^^^^^^ help: consider removing `i32::from()`: `(a + b)`
index d0bee2460dd843993f9bd2d9035446f803638cb6..4fa28b525c3c29f93694c2c89b538bef630774cd 100644 (file)
@@ -35,4 +35,18 @@ mod should_not_trigger {
     }
 }
 
+mod inner_mod {
+    mod inner {
+        pub struct S;
+    }
+
+    mod inner2 {
+        use super::inner::S;
+
+        pub fn f() -> Vec<S> {
+            vec![]
+        }
+    }
+}
+
 fn main() {}
index 500a0ae263ea509a8be6ba1d205000908fe3f766..7dc735cd90be7d43f2343d8dfb605edca3e53c5d 100644 (file)
@@ -35,4 +35,18 @@ struct TraitVec<T: ?Sized> {
     }
 }
 
+mod inner_mod {
+    mod inner {
+        pub struct S;
+    }
+
+    mod inner2 {
+        use super::inner::S;
+
+        pub fn f() -> Vec<Box<S>> {
+            vec![]
+        }
+    }
+}
+
 fn main() {}
index 29bf7069e8adb84c68f55eefe214a2bae8381a6e..57e2f1fdf9a7449407850a5a25f48d01b97de3f8 100644 (file)
@@ -18,5 +18,11 @@ error: `Vec<T>` is already on the heap, the boxing is unnecessary.
 LL |     struct B(Vec<Vec<Box<(u32)>>>);
    |                  ^^^^^^^^^^^^^^^ help: try: `Vec<u32>`
 
-error: aborting due to 3 previous errors
+error: `Vec<T>` is already on the heap, the boxing is unnecessary.
+  --> $DIR/vec_box_sized.rs:46:23
+   |
+LL |         pub fn f() -> Vec<Box<S>> {
+   |                       ^^^^^^^^^^^ help: try: `Vec<S>`
+
+error: aborting due to 4 previous errors
 
index 4f8754a930120ecb55e1675788fa9b6d042d2369..b1e5742b78531870fafac354b30323eafbcf72eb 100644 (file)
@@ -7,7 +7,7 @@
     dead_code,
     clippy::single_match,
     clippy::wildcard_in_or_patterns,
-    clippy::unnested_or_patterns
+    clippy::unnested_or_patterns, clippy::diverging_sub_expression
 )]
 
 use std::io::ErrorKind;
index 5e66644ceca0ff202a14b221730e905e7bc8d1bb..cd3ec3ea8d2629a3e22a532dc10279a234c080d4 100644 (file)
@@ -7,7 +7,7 @@
     dead_code,
     clippy::single_match,
     clippy::wildcard_in_or_patterns,
-    clippy::unnested_or_patterns
+    clippy::unnested_or_patterns, clippy::diverging_sub_expression
 )]
 
 use std::io::ErrorKind;
index 287f8935327c561f0dd7b8543597fbfe5095b9ae..ee9c9045fff55940b42177b9eecef25bebe2b780 100644 (file)
@@ -4,6 +4,7 @@
 #![warn(clippy::wildcard_imports)]
 //#![allow(clippy::redundant_pub_crate)]
 #![allow(unused)]
+#![allow(clippy::unnecessary_wraps)]
 #![warn(unused_imports)]
 
 extern crate wildcard_imports_helper;
index 1f261159f4a94e2f32b2c44237e66e2ea62510d7..efaa8f9ef664186b0ba5e70a6d9cd4143bb31460 100644 (file)
@@ -4,6 +4,7 @@
 #![warn(clippy::wildcard_imports)]
 //#![allow(clippy::redundant_pub_crate)]
 #![allow(unused)]
+#![allow(clippy::unnecessary_wraps)]
 #![warn(unused_imports)]
 
 extern crate wildcard_imports_helper;
index 351988f31ead5b881c5086951cb42fc2e6af9b69..66267dd27b84fcf4da55e265ed164709a6e6647e 100644 (file)
@@ -1,5 +1,5 @@
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:11:5
+  --> $DIR/wildcard_imports.rs:12:5
    |
 LL | use crate::fn_mod::*;
    |     ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
@@ -7,85 +7,85 @@ LL | use crate::fn_mod::*;
    = note: `-D clippy::wildcard-imports` implied by `-D warnings`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:12:5
+  --> $DIR/wildcard_imports.rs:13:5
    |
 LL | use crate::mod_mod::*;
    |     ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:13:5
+  --> $DIR/wildcard_imports.rs:14:5
    |
 LL | use crate::multi_fn_mod::*;
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:15:5
+  --> $DIR/wildcard_imports.rs:16:5
    |
 LL | use crate::struct_mod::*;
    |     ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:19:5
+  --> $DIR/wildcard_imports.rs:20:5
    |
 LL | use wildcard_imports_helper::inner::inner_for_self_import::*;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:20:5
+  --> $DIR/wildcard_imports.rs:21:5
    |
 LL | use wildcard_imports_helper::*;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:91:13
+  --> $DIR/wildcard_imports.rs:92:13
    |
 LL |         use crate::fn_mod::*;
    |             ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:97:75
+  --> $DIR/wildcard_imports.rs:98:75
    |
 LL |         use wildcard_imports_helper::inner::inner_for_self_import::{self, *};
    |                                                                           ^ help: try: `inner_extern_foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:98:13
+  --> $DIR/wildcard_imports.rs:99:13
    |
 LL |         use wildcard_imports_helper::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:109:20
+  --> $DIR/wildcard_imports.rs:110:20
    |
 LL |         use self::{inner::*, inner2::*};
    |                    ^^^^^^^^ help: try: `inner::inner_foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:109:30
+  --> $DIR/wildcard_imports.rs:110:30
    |
 LL |         use self::{inner::*, inner2::*};
    |                              ^^^^^^^^^ help: try: `inner2::inner_bar`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:116:13
+  --> $DIR/wildcard_imports.rs:117:13
    |
 LL |         use wildcard_imports_helper::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:145:9
+  --> $DIR/wildcard_imports.rs:146:9
    |
 LL |     use crate::in_fn_test::*;
    |         ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:154:9
+  --> $DIR/wildcard_imports.rs:155:9
    |
 LL |     use crate:: in_fn_test::  * ;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:155:9
+  --> $DIR/wildcard_imports.rs:156:9
    |
 LL |       use crate:: fn_mod::
    |  _________^
@@ -93,31 +93,31 @@ LL | |         *;
    | |_________^ help: try: `crate:: fn_mod::foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:166:13
+  --> $DIR/wildcard_imports.rs:167:13
    |
 LL |         use super::*;
    |             ^^^^^^^^ help: try: `super::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:201:17
+  --> $DIR/wildcard_imports.rs:202:17
    |
 LL |             use super::*;
    |                 ^^^^^^^^ help: try: `super::insidefoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:209:13
+  --> $DIR/wildcard_imports.rs:210:13
    |
 LL |         use super_imports::*;
    |             ^^^^^^^^^^^^^^^^ help: try: `super_imports::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:218:17
+  --> $DIR/wildcard_imports.rs:219:17
    |
 LL |             use super::super::*;
    |                 ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:227:13
+  --> $DIR/wildcard_imports.rs:228:13
    |
 LL |         use super::super::super_imports::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo`
index 19aec0ea598f9eb6b658d2ecaae0b0f30b1bb3ff..8d23227fdb8b78dab6a6ac3556ac581e81f127de 100644 (file)
@@ -153,11 +153,14 @@ fn parse_line(file_name: &str, line: &str, output: &str, proc_res: &ProcRes) ->
                 if serde_json::from_str::<FutureIncompatReport>(line).is_ok() {
                     vec![]
                 } else {
-                    proc_res.fatal(Some(&format!(
-                        "failed to decode compiler output as json: \
+                    proc_res.fatal(
+                        Some(&format!(
+                            "failed to decode compiler output as json: \
                          `{}`\nline: {}\noutput: {}",
-                        error, line, output
-                    )));
+                            error, line, output
+                        )),
+                        || (),
+                    );
                 }
             }
         }
index 2b167ac8e9fb288c19b4293383a3de8f4e2a70d2..32347db5dbb1ceb1b35af940413223733f1bdf52 100644 (file)
@@ -379,7 +379,7 @@ pub fn run_tests(config: Config) {
         }
         Err(e) => {
             // We don't know if tests passed or not, but if there was an error
-            // during testing we don't want to just suceeed (we may not have
+            // during testing we don't want to just succeed (we may not have
             // tested something), so fail.
             //
             // This should realistically "never" happen, so don't try to make
index d46f905e6cc52e385cddb8e96b3b685b67961b01..1b9f0089dced05248ce4dbd28bd10a818326dc16 100644 (file)
@@ -287,6 +287,7 @@ pub fn compute_stamp_hash(config: &Config) -> String {
     format!("{:x}", hash.finish())
 }
 
+#[derive(Copy, Clone)]
 struct TestCx<'test> {
     config: &'test Config,
     props: &'test TestProps,
@@ -977,7 +978,8 @@ fn run_debuginfo_gdb_test_no_opt(&self) {
             script_str.push_str("set print pretty off\n");
 
             // Add the pretty printer directory to GDB's source-file search path
-            script_str.push_str(&format!("directory {}\n", rust_pp_module_abs_path));
+            script_str
+                .push_str(&format!("directory {}\n", rust_pp_module_abs_path.replace(r"\", r"\\")));
 
             // Load the target executable
             script_str
@@ -1728,7 +1730,7 @@ fn is_vxworks_pure_dynamic(&self) -> bool {
         self.config.target.contains("vxworks") && !self.is_vxworks_pure_static()
     }
 
-    fn compose_and_run_compiler(&self, mut rustc: Command, input: Option<String>) -> ProcRes {
+    fn build_all_auxiliary(&self, rustc: &mut Command) -> PathBuf {
         let aux_dir = self.aux_output_dir_name();
 
         if !self.props.aux_builds.is_empty() {
@@ -1747,6 +1749,11 @@ fn compose_and_run_compiler(&self, mut rustc: Command, input: Option<String>) ->
             rustc.arg("--extern").arg(format!("{}={}/{}", aux_name, aux_dir.display(), lib_name));
         }
 
+        aux_dir
+    }
+
+    fn compose_and_run_compiler(&self, mut rustc: Command, input: Option<String>) -> ProcRes {
+        let aux_dir = self.build_all_auxiliary(&mut rustc);
         self.props.unset_rustc_env.clone().iter().fold(&mut rustc, |rustc, v| rustc.env_remove(v));
         rustc.envs(self.props.rustc_env.clone());
         self.compose_and_run(
@@ -1783,8 +1790,7 @@ fn build_auxiliary(&self, source_path: &str, aux_dir: &Path) -> bool {
 
         let (dylib, crate_type) = if aux_props.no_prefer_dynamic {
             (true, None)
-        } else if self.config.target.contains("cloudabi")
-            || self.config.target.contains("emscripten")
+        } else if self.config.target.contains("emscripten")
             || (self.config.target.contains("musl")
                 && !aux_props.force_host
                 && !self.config.host.contains("musl"))
@@ -2208,7 +2214,17 @@ fn fatal(&self, err: &str) -> ! {
 
     fn fatal_proc_rec(&self, err: &str, proc_res: &ProcRes) -> ! {
         self.error(err);
-        proc_res.fatal(None);
+        proc_res.fatal(None, || ());
+    }
+
+    fn fatal_proc_rec_with_ctx(
+        &self,
+        err: &str,
+        proc_res: &ProcRes,
+        on_failure: impl FnOnce(Self),
+    ) -> ! {
+        self.error(err);
+        proc_res.fatal(None, || on_failure(*self));
     }
 
     // codegen tests (using FileCheck)
@@ -2325,15 +2341,131 @@ fn run_rustdoc_test(&self) {
             let res = self.cmd2procres(
                 Command::new(&self.config.docck_python)
                     .arg(root.join("src/etc/htmldocck.py"))
-                    .arg(out_dir)
+                    .arg(&out_dir)
                     .arg(&self.testpaths.file),
             );
             if !res.status.success() {
-                self.fatal_proc_rec("htmldocck failed!", &res);
+                self.fatal_proc_rec_with_ctx("htmldocck failed!", &res, |mut this| {
+                    this.compare_to_default_rustdoc(&out_dir)
+                });
             }
         }
     }
 
+    fn compare_to_default_rustdoc(&mut self, out_dir: &Path) {
+        println!("info: generating a diff against nightly rustdoc");
+
+        let suffix =
+            self.safe_revision().map_or("nightly".into(), |path| path.to_owned() + "-nightly");
+        let compare_dir = output_base_dir(self.config, self.testpaths, Some(&suffix));
+        // Don't give an error if the directory didn't already exist
+        let _ = fs::remove_dir_all(&compare_dir);
+        create_dir_all(&compare_dir).unwrap();
+
+        // We need to create a new struct for the lifetimes on `config` to work.
+        let new_rustdoc = TestCx {
+            config: &Config {
+                // FIXME: use beta or a user-specified rustdoc instead of
+                // hardcoding the default toolchain
+                rustdoc_path: Some("rustdoc".into()),
+                // Needed for building auxiliary docs below
+                rustc_path: "rustc".into(),
+                ..self.config.clone()
+            },
+            ..*self
+        };
+
+        let output_file = TargetLocation::ThisDirectory(new_rustdoc.aux_output_dir_name());
+        let mut rustc = new_rustdoc.make_compile_args(
+            &new_rustdoc.testpaths.file,
+            output_file,
+            EmitMetadata::No,
+            AllowUnused::Yes,
+        );
+        rustc.arg("-L").arg(&new_rustdoc.aux_output_dir_name());
+        new_rustdoc.build_all_auxiliary(&mut rustc);
+
+        let proc_res = new_rustdoc.document(&compare_dir);
+        if !proc_res.status.success() {
+            proc_res.fatal(Some("failed to run nightly rustdoc"), || ());
+        }
+
+        #[rustfmt::skip]
+        let tidy_args = [
+            "--indent", "yes",
+            "--indent-spaces", "2",
+            "--wrap", "0",
+            "--show-warnings", "no",
+            "--markup", "yes",
+            "--quiet", "yes",
+            "-modify",
+        ];
+        let tidy_dir = |dir| {
+            let tidy = |file: &_| {
+                Command::new("tidy")
+                    .args(&tidy_args)
+                    .arg(file)
+                    .spawn()
+                    .unwrap_or_else(|err| {
+                        self.fatal(&format!("failed to run tidy - is it installed? - {}", err))
+                    })
+                    .wait()
+                    .unwrap()
+            };
+            for entry in walkdir::WalkDir::new(dir) {
+                let entry = entry.expect("failed to read file");
+                if entry.file_type().is_file()
+                    && entry.path().extension().and_then(|p| p.to_str()) == Some("html".into())
+                {
+                    tidy(entry.path());
+                }
+            }
+        };
+        tidy_dir(out_dir);
+        tidy_dir(&compare_dir);
+
+        let pager = {
+            let output = Command::new("git").args(&["config", "--get", "core.pager"]).output().ok();
+            output.and_then(|out| {
+                if out.status.success() {
+                    Some(String::from_utf8(out.stdout).expect("invalid UTF8 in git pager"))
+                } else {
+                    None
+                }
+            })
+        };
+        let mut diff = Command::new("diff");
+        diff.args(&["-u", "-r"]).args(&[out_dir, &compare_dir]);
+
+        let output = if let Some(pager) = pager {
+            let diff_pid = diff.stdout(Stdio::piped()).spawn().expect("failed to run `diff`");
+            let pager = pager.trim();
+            if self.config.verbose {
+                eprintln!("using pager {}", pager);
+            }
+            let output = Command::new(pager)
+                // disable paging; we want this to be non-interactive
+                .env("PAGER", "")
+                .stdin(diff_pid.stdout.unwrap())
+                // Capture output and print it explicitly so it will in turn be
+                // captured by libtest.
+                .output()
+                .unwrap();
+            assert!(output.status.success());
+            output
+        } else {
+            eprintln!("warning: no pager configured, falling back to `diff --color`");
+            eprintln!(
+                "help: try configuring a git pager (e.g. `delta`) with `git config --global core.pager delta`"
+            );
+            let output = diff.arg("--color").output().unwrap();
+            assert!(output.status.success() || output.status.code() == Some(1));
+            output
+        };
+        println!("{}", String::from_utf8_lossy(&output.stdout));
+        eprintln!("{}", String::from_utf8_lossy(&output.stderr));
+    }
+
     fn get_lines<P: AsRef<Path>>(
         &self,
         path: &P,
@@ -3590,7 +3722,7 @@ pub struct ProcRes {
 }
 
 impl ProcRes {
-    pub fn fatal(&self, err: Option<&str>) -> ! {
+    pub fn fatal(&self, err: Option<&str>, on_failure: impl FnOnce()) -> ! {
         if let Some(e) = err {
             println!("\nerror: {}", e);
         }
@@ -3612,6 +3744,7 @@ pub fn fatal(&self, err: Option<&str>) -> ! {
             json::extract_rendered(&self.stdout),
             json::extract_rendered(&self.stderr),
         );
+        on_failure();
         // Use resume_unwind instead of panic!() to prevent a panic message + backtrace from
         // compiletest, which is unnecessary noise.
         std::panic::resume_unwind(Box::new(()));
index 1a727fc2b82ea6e6a1236cbebbae2b0b9f748709..4f77e719fba92e0a1aa4e572681c4d36e38b9de3 100644 (file)
@@ -12,7 +12,6 @@
 const OS_TABLE: &[(&str, &str)] = &[
     ("android", "android"),
     ("androideabi", "android"),
-    ("cloudabi", "cloudabi"),
     ("cuda", "cuda"),
     ("darwin", "macos"),
     ("dragonfly", "dragonfly"),
index df4109151b6870cdb6d170326d1c099746990ea8..746ea5b141baf1f86c2ad17753a37b135e0c1aa3 160000 (submodule)
@@ -1 +1 @@
-Subproject commit df4109151b6870cdb6d170326d1c099746990ea8
+Subproject commit 746ea5b141baf1f86c2ad17753a37b135e0c1aa3
index bce3cf06b0751ce72a5ca0abe3ca01d882655f98..6697fbd1be2def091d14a274d44628e6510d96d1 100644 (file)
@@ -173,7 +173,6 @@ pub fn check(path: &Path, bad: &mut bool) {
             // parser to tidy.
             !file.ancestors().any(|a| {
                 a.ends_with("src/test") ||
-                    a.ends_with("library/std/src/sys/cloudabi") ||
                     a.ends_with("src/doc/book")
             });
 
index 04f2bbaa0d955a1887010f46877ce83d3ba10fa9..f675b78651ef945c47dfddce3954663b5bc3ad02 100644 (file)
@@ -31,8 +31,6 @@ pub fn check(root_path: &Path, bad: &mut bool) {
                 // UI tests with different names
                 || path.ends_with("src/thread/local/dynamic_tests.rs")
                 || path.ends_with("src/sync/mpsc/sync_tests.rs")
-                // Has copyright banner
-                || path.ends_with("src/sys/cloudabi/abi/cloudabi.rs")
         }
     };