]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #90035 - SparrowLii:rfc2528, r=jackh726
authorMatthias Krüger <matthias.krueger@famsik.de>
Tue, 9 Nov 2021 18:00:41 +0000 (19:00 +0100)
committerGitHub <noreply@github.com>
Tue, 9 Nov 2021 18:00:41 +0000 (19:00 +0100)
implement rfc-2528 type_changing-struct-update

This PR implement rfc2528-type_changing-struct-update.
The main change process is as follows:
1. Move the processing part of `base_expr` into `check_expr_struct_fields` to avoid returning `remaining_fields` (a relatively complex hash table)
2. Before performing the type consistency check(`check_expr_has_type_or_error`), if the `type_changing_struct_update` feature is set, enter a different processing flow, otherwise keep the original flow
3. In the case of the same structure definition, check each field in `remaining_fields`. If the field in `base_expr` is not the suptype of the field in `adt_ty`, an error(`FeildMisMatch`) will be reported.

The MIR part does not need to be changed, because only the items contained in `remaining_fields` will be extracted from `base_expr` when MIR is generated. This means that fields with different types in `base_expr` will not be used
Updates #86618
cc `@nikomatsakis`

1717 files changed:
.github/workflows/ci.yml
.mailmap
Cargo.lock
RELEASES.md
compiler/rustc_ast/README.md
compiler/rustc_ast/src/ast.rs
compiler/rustc_ast/src/lib.rs
compiler/rustc_ast/src/mut_visit.rs
compiler/rustc_ast/src/tokenstream.rs
compiler/rustc_ast/src/util/comments.rs
compiler/rustc_ast/src/util/parser.rs
compiler/rustc_ast/src/util/unicode.rs [new file with mode: 0644]
compiler/rustc_ast/src/visit.rs
compiler/rustc_ast_lowering/src/asm.rs
compiler/rustc_ast_lowering/src/index.rs
compiler/rustc_ast_lowering/src/item.rs
compiler/rustc_ast_lowering/src/lib.rs
compiler/rustc_ast_passes/src/ast_validation.rs
compiler/rustc_ast_passes/src/feature_gate.rs
compiler/rustc_ast_passes/src/lib.rs
compiler/rustc_ast_pretty/src/pprust/state.rs
compiler/rustc_borrowck/src/borrow_set.rs
compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
compiler/rustc_borrowck/src/lib.rs
compiler/rustc_borrowck/src/nll.rs
compiler/rustc_borrowck/src/region_infer/mod.rs
compiler/rustc_borrowck/src/type_check/mod.rs
compiler/rustc_borrowck/src/universal_regions.rs
compiler/rustc_builtin_macros/src/asm.rs
compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
compiler/rustc_builtin_macros/src/deriving/mod.rs
compiler/rustc_builtin_macros/src/format.rs
compiler/rustc_builtin_macros/src/global_allocator.rs
compiler/rustc_builtin_macros/src/lib.rs
compiler/rustc_builtin_macros/src/test.rs
compiler/rustc_builtin_macros/src/test_harness.rs
compiler/rustc_codegen_gcc/src/asm.rs
compiler/rustc_codegen_gcc/src/builder.rs
compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
compiler/rustc_codegen_llvm/src/abi.rs
compiler/rustc_codegen_llvm/src/asm.rs
compiler/rustc_codegen_llvm/src/back/write.rs
compiler/rustc_codegen_llvm/src/builder.rs
compiler/rustc_codegen_llvm/src/context.rs
compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
compiler/rustc_codegen_llvm/src/intrinsic.rs
compiler/rustc_codegen_llvm/src/lib.rs
compiler/rustc_codegen_llvm/src/llvm/ffi.rs
compiler/rustc_codegen_llvm/src/llvm_util.rs
compiler/rustc_codegen_ssa/src/back/link.rs
compiler/rustc_codegen_ssa/src/back/symbol_export.rs
compiler/rustc_codegen_ssa/src/back/write.rs
compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
compiler/rustc_codegen_ssa/src/lib.rs
compiler/rustc_codegen_ssa/src/mir/block.rs
compiler/rustc_codegen_ssa/src/mir/mod.rs
compiler/rustc_codegen_ssa/src/mir/statement.rs
compiler/rustc_codegen_ssa/src/target_features.rs
compiler/rustc_codegen_ssa/src/traits/asm.rs
compiler/rustc_codegen_ssa/src/traits/backend.rs
compiler/rustc_codegen_ssa/src/traits/builder.rs
compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
compiler/rustc_const_eval/src/const_eval/error.rs
compiler/rustc_const_eval/src/const_eval/eval_queries.rs
compiler/rustc_const_eval/src/const_eval/fn_queries.rs
compiler/rustc_const_eval/src/const_eval/machine.rs
compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs
compiler/rustc_const_eval/src/interpret/terminator.rs
compiler/rustc_const_eval/src/lib.rs
compiler/rustc_const_eval/src/transform/check_consts/check.rs
compiler/rustc_const_eval/src/transform/check_consts/mod.rs
compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
compiler/rustc_const_eval/src/transform/check_consts/resolver.rs
compiler/rustc_const_eval/src/transform/promote_consts.rs
compiler/rustc_data_structures/src/lib.rs
compiler/rustc_data_structures/src/sorted_map.rs
compiler/rustc_data_structures/src/steal.rs
compiler/rustc_driver/src/lib.rs
compiler/rustc_error_codes/src/error_codes.rs
compiler/rustc_error_codes/src/error_codes/E0786.md [new file with mode: 0644]
compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
compiler/rustc_errors/src/diagnostic.rs
compiler/rustc_errors/src/emitter.rs
compiler/rustc_errors/src/lib.rs
compiler/rustc_expand/src/lib.rs
compiler/rustc_expand/src/proc_macro_server.rs
compiler/rustc_feature/src/accepted.rs
compiler/rustc_feature/src/active.rs
compiler/rustc_feature/src/builtin_attrs.rs
compiler/rustc_hir/Cargo.toml
compiler/rustc_hir/src/def.rs
compiler/rustc_hir/src/hir.rs
compiler/rustc_hir/src/hir_id.rs
compiler/rustc_hir/src/lang_items.rs
compiler/rustc_incremental/src/lib.rs
compiler/rustc_index/src/vec.rs
compiler/rustc_infer/src/infer/canonical/query_response.rs
compiler/rustc_infer/src/infer/combine.rs
compiler/rustc_infer/src/infer/error_reporting/mod.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
compiler/rustc_infer/src/infer/mod.rs
compiler/rustc_infer/src/infer/opaque_types.rs
compiler/rustc_infer/src/infer/outlives/env.rs
compiler/rustc_infer/src/lib.rs
compiler/rustc_infer/src/traits/engine.rs
compiler/rustc_interface/src/interface.rs
compiler/rustc_interface/src/lib.rs
compiler/rustc_interface/src/passes.rs
compiler/rustc_interface/src/tests.rs
compiler/rustc_interface/src/util.rs
compiler/rustc_lexer/src/unescape.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_lint/src/context.rs
compiler/rustc_lint/src/hidden_unicode_codepoints.rs [new file with mode: 0644]
compiler/rustc_lint/src/internal.rs
compiler/rustc_lint/src/lib.rs
compiler/rustc_lint_defs/src/builtin.rs
compiler/rustc_lint_defs/src/lib.rs
compiler/rustc_llvm/build.rs
compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
compiler/rustc_llvm/src/lib.rs
compiler/rustc_macros/src/hash_stable.rs
compiler/rustc_macros/src/query.rs
compiler/rustc_metadata/Cargo.toml
compiler/rustc_metadata/src/creader.rs
compiler/rustc_metadata/src/lib.rs
compiler/rustc_metadata/src/locator.rs
compiler/rustc_metadata/src/native_libs.rs
compiler/rustc_metadata/src/rmeta/decoder.rs
compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
compiler/rustc_metadata/src/rmeta/encoder.rs
compiler/rustc_metadata/src/rmeta/mod.rs
compiler/rustc_middle/src/hir/map/mod.rs
compiler/rustc_middle/src/lib.rs
compiler/rustc_middle/src/lint.rs
compiler/rustc_middle/src/mir/interpret/error.rs
compiler/rustc_middle/src/mir/mod.rs
compiler/rustc_middle/src/mir/pretty.rs
compiler/rustc_middle/src/mir/spanview.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/ty/consts.rs
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_middle/src/ty/print/pretty.rs
compiler/rustc_middle/src/ty/query.rs
compiler/rustc_middle/src/ty/relate.rs
compiler/rustc_middle/src/ty/sty.rs
compiler/rustc_middle/src/ty/subst.rs
compiler/rustc_middle/src/ty/util.rs
compiler/rustc_mir_build/src/lib.rs
compiler/rustc_mir_build/src/thir/cx/expr.rs
compiler/rustc_mir_build/src/thir/pattern/mod.rs
compiler/rustc_mir_dataflow/src/framework/cursor.rs
compiler/rustc_mir_dataflow/src/framework/tests.rs
compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
compiler/rustc_mir_dataflow/src/impls/mod.rs
compiler/rustc_mir_dataflow/src/lib.rs
compiler/rustc_mir_dataflow/src/rustc_peek.rs
compiler/rustc_mir_transform/src/coverage/mod.rs
compiler/rustc_mir_transform/src/coverage/spans.rs
compiler/rustc_mir_transform/src/lib.rs
compiler/rustc_mir_transform/src/reveal_all.rs
compiler/rustc_mir_transform/src/unreachable_prop.rs
compiler/rustc_monomorphize/src/collector.rs
compiler/rustc_monomorphize/src/lib.rs
compiler/rustc_monomorphize/src/polymorphize.rs
compiler/rustc_monomorphize/src/util.rs
compiler/rustc_parse/Cargo.toml
compiler/rustc_parse/src/lexer/mod.rs
compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
compiler/rustc_parse/src/parser/item.rs
compiler/rustc_passes/src/check_attr.rs
compiler/rustc_passes/src/check_const.rs
compiler/rustc_passes/src/lib.rs
compiler/rustc_passes/src/region.rs
compiler/rustc_privacy/src/lib.rs
compiler/rustc_query_impl/src/lib.rs
compiler/rustc_query_impl/src/on_disk_cache.rs
compiler/rustc_query_impl/src/plumbing.rs
compiler/rustc_query_system/src/ich/hcx.rs
compiler/rustc_query_system/src/ich/impls_hir.rs
compiler/rustc_query_system/src/lib.rs
compiler/rustc_query_system/src/query/config.rs
compiler/rustc_query_system/src/query/mod.rs
compiler/rustc_query_system/src/query/plumbing.rs
compiler/rustc_resolve/src/build_reduced_graph.rs
compiler/rustc_resolve/src/diagnostics.rs
compiler/rustc_resolve/src/late.rs
compiler/rustc_resolve/src/late/diagnostics.rs
compiler/rustc_resolve/src/late/lifetimes.rs
compiler/rustc_resolve/src/lib.rs
compiler/rustc_save_analysis/src/dump_visitor.rs
compiler/rustc_save_analysis/src/lib.rs
compiler/rustc_session/src/config.rs
compiler/rustc_session/src/lib.rs
compiler/rustc_session/src/options.rs
compiler/rustc_session/src/session.rs
compiler/rustc_span/src/hygiene.rs
compiler/rustc_span/src/lib.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_symbol_mangling/src/lib.rs
compiler/rustc_symbol_mangling/src/v0.rs
compiler/rustc_target/src/abi/call/mod.rs
compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs
compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs
compiler/rustc_target/src/spec/aarch64_fuchsia.rs
compiler/rustc_target/src/spec/aarch64_linux_android.rs
compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs
compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs
compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs
compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs
compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
compiler/rustc_target/src/spec/hermit_kernel_base.rs
compiler/rustc_target/src/spec/mod.rs
compiler/rustc_target/src/spec/x86_64_apple_darwin.rs
compiler/rustc_target/src/spec/x86_64_fuchsia.rs
compiler/rustc_target/src/spec/x86_64_pc_solaris.rs
compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs
compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs
compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs
compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs
compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs
compiler/rustc_target/src/spec/x86_64_unknown_none.rs [new file with mode: 0644]
compiler/rustc_trait_selection/src/autoderef.rs
compiler/rustc_trait_selection/src/lib.rs
compiler/rustc_trait_selection/src/opaque_types.rs
compiler/rustc_trait_selection/src/traits/auto_trait.rs
compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
compiler/rustc_trait_selection/src/traits/codegen.rs
compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
compiler/rustc_trait_selection/src/traits/fulfill.rs
compiler/rustc_trait_selection/src/traits/mod.rs
compiler/rustc_trait_selection/src/traits/project.rs
compiler/rustc_trait_selection/src/traits/query/type_op/custom.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/structural_match.rs
compiler/rustc_traits/src/implied_outlives_bounds.rs
compiler/rustc_ty_utils/src/needs_drop.rs
compiler/rustc_ty_utils/src/ty.rs
compiler/rustc_typeck/src/astconv/generics.rs
compiler/rustc_typeck/src/check/_match.rs
compiler/rustc_typeck/src/check/cast.rs
compiler/rustc_typeck/src/check/check.rs
compiler/rustc_typeck/src/check/closure.rs
compiler/rustc_typeck/src/check/coercion.rs
compiler/rustc_typeck/src/check/compare_method.rs
compiler/rustc_typeck/src/check/demand.rs
compiler/rustc_typeck/src/check/dropck.rs
compiler/rustc_typeck/src/check/expr.rs
compiler/rustc_typeck/src/check/fallback.rs
compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
compiler/rustc_typeck/src/check/method/suggest.rs
compiler/rustc_typeck/src/check/mod.rs
compiler/rustc_typeck/src/check/op.rs
compiler/rustc_typeck/src/check/pat.rs
compiler/rustc_typeck/src/check/regionck.rs
compiler/rustc_typeck/src/check/upvar.rs
compiler/rustc_typeck/src/check/wfcheck.rs
compiler/rustc_typeck/src/check/writeback.rs
compiler/rustc_typeck/src/coherence/builtin.rs
compiler/rustc_typeck/src/collect.rs
compiler/rustc_typeck/src/collect/type_of.rs
compiler/rustc_typeck/src/hir_wf_check.rs
compiler/rustc_typeck/src/lib.rs
compiler/rustc_typeck/src/outlives/outlives_bounds.rs
compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
library/alloc/benches/btree/map.rs
library/alloc/src/alloc.rs
library/alloc/src/collections/binary_heap.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/set.rs
library/alloc/src/collections/btree/set/tests.rs
library/alloc/src/collections/linked_list.rs
library/alloc/src/collections/mod.rs
library/alloc/src/fmt.rs
library/alloc/src/lib.rs
library/alloc/src/rc.rs
library/alloc/src/slice.rs
library/alloc/src/str.rs
library/alloc/src/string.rs
library/alloc/src/sync.rs
library/alloc/src/vec/drain.rs
library/alloc/tests/str.rs
library/backtrace
library/core/src/alloc/layout.rs
library/core/src/any.rs
library/core/src/ascii.rs
library/core/src/cell.rs
library/core/src/char/decode.rs
library/core/src/clone.rs
library/core/src/default.rs
library/core/src/fmt/mod.rs
library/core/src/future/mod.rs
library/core/src/internal_macros.rs
library/core/src/intrinsics.rs
library/core/src/iter/sources/empty.rs
library/core/src/lib.rs
library/core/src/marker.rs
library/core/src/mem/mod.rs
library/core/src/num/error.rs
library/core/src/num/f32.rs
library/core/src/num/f64.rs
library/core/src/num/int_macros.rs
library/core/src/num/mod.rs
library/core/src/num/nonzero.rs
library/core/src/num/uint_macros.rs
library/core/src/num/wrapping.rs
library/core/src/ops/arith.rs
library/core/src/ops/bit.rs
library/core/src/ops/control_flow.rs
library/core/src/ops/range.rs
library/core/src/option.rs
library/core/src/panic/location.rs
library/core/src/panic/panic_info.rs
library/core/src/panicking.rs
library/core/src/pin.rs
library/core/src/ptr/mod.rs
library/core/src/ptr/non_null.rs
library/core/src/ptr/unique.rs
library/core/src/result.rs
library/core/src/slice/ascii.rs
library/core/src/slice/iter.rs
library/core/src/slice/memchr.rs
library/core/src/slice/mod.rs
library/core/src/slice/raw.rs
library/core/src/str/error.rs
library/core/src/str/iter.rs
library/core/src/str/lossy.rs
library/core/src/str/mod.rs
library/core/src/str/pattern.rs
library/core/src/str/traits.rs
library/core/src/str/validations.rs
library/core/src/task/wake.rs
library/core/src/time.rs
library/core/tests/ascii.rs
library/core/tests/lib.rs
library/proc_macro/src/lib.rs
library/std/Cargo.toml
library/std/src/backtrace.rs
library/std/src/collections/hash/map.rs
library/std/src/collections/hash/set.rs
library/std/src/env.rs
library/std/src/f32.rs
library/std/src/f32/tests.rs
library/std/src/f64.rs
library/std/src/f64/tests.rs
library/std/src/ffi/c_str.rs
library/std/src/ffi/os_str.rs
library/std/src/fs.rs
library/std/src/fs/tests.rs
library/std/src/io/error.rs
library/std/src/io/mod.rs
library/std/src/io/stdio.rs
library/std/src/io/util.rs
library/std/src/lib.rs
library/std/src/net/addr.rs
library/std/src/net/ip.rs
library/std/src/net/tcp.rs
library/std/src/os/raw/mod.rs
library/std/src/os/unix/net/addr.rs
library/std/src/os/unix/net/ancillary.rs
library/std/src/os/unix/net/listener.rs
library/std/src/os/unix/process.rs
library/std/src/panicking.rs
library/std/src/path.rs
library/std/src/process.rs
library/std/src/rt.rs
library/std/src/sync/condvar.rs
library/std/src/sync/mpsc/cache_aligned.rs
library/std/src/sync/mpsc/mod.rs
library/std/src/sys/hermit/condvar.rs
library/std/src/sys/itron/thread.rs
library/std/src/sys/unix/stack_overflow.rs
library/std/src/sys/unix/thread.rs
library/std/src/sys/windows/c.rs
library/std/src/sys/windows/fs.rs
library/std/src/sys/windows/path.rs
library/std/src/sys/windows/path/tests.rs
library/std/src/sys/windows/thread_local_dtor.rs
library/std/src/sys/windows/thread_local_key.rs
library/std/src/sys_common/process.rs
library/std/src/sys_common/wtf8.rs
library/std/src/thread/mod.rs
library/std/src/thread/tests.rs
library/std/src/time.rs
library/std/src/time/tests.rs
library/test/src/formatters/junit.rs
library/unwind/src/lib.rs
src/bootstrap/bootstrap.py
src/bootstrap/builder.rs
src/bootstrap/compile.rs
src/bootstrap/doc.rs
src/bootstrap/lib.rs
src/bootstrap/metadata.rs
src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile
src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
src/ci/docker/host-x86_64/dist-x86_64-linux/build-curl.sh
src/ci/docker/host-x86_64/dist-x86_64-linux/build-openssl.sh
src/ci/docker/host-x86_64/dist-x86_64-linux/download-openssl-curl.sh [new file with mode: 0755]
src/ci/docker/host-x86_64/shared/ISRG_Root_X1.crt [deleted file]
src/ci/docker/run.sh
src/ci/docker/scripts/freebsd-toolchain.sh
src/ci/github-actions/ci.yml
src/doc/book
src/doc/embedded-book
src/doc/nomicon
src/doc/reference
src/doc/rust-by-example
src/doc/rustc-dev-guide
src/doc/rustc/src/SUMMARY.md
src/doc/rustc/src/exploit-mitigations.md
src/doc/rustc/src/platform-support.md
src/doc/rustc/src/platform-support/x86_64-unknown-none.md [new file with mode: 0644]
src/doc/rustdoc/src/SUMMARY.md
src/doc/rustdoc/src/how-to-read-rustdoc.md [new file with mode: 0644]
src/doc/rustdoc/src/the-doc-attribute.md
src/doc/rustdoc/src/unstable-features.md
src/doc/unstable-book/src/compiler-flags/no-unique-section-names.md [new file with mode: 0644]
src/doc/unstable-book/src/compiler-flags/sanitizer.md
src/doc/unstable-book/src/library-features/asm.md
src/doc/unstable-book/src/library-features/global-asm.md
src/librustdoc/Cargo.toml
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/blanket_impl.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/clean/utils.rs
src/librustdoc/config.rs
src/librustdoc/core.rs
src/librustdoc/docfs.rs
src/librustdoc/doctest.rs
src/librustdoc/fold.rs
src/librustdoc/formats/cache.rs
src/librustdoc/formats/item_type.rs
src/librustdoc/html/format.rs
src/librustdoc/html/highlight.rs
src/librustdoc/html/highlight/fixtures/sample.html
src/librustdoc/html/layout.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/render/cache.rs
src/librustdoc/html/render/context.rs
src/librustdoc/html/render/mod.rs
src/librustdoc/html/render/print_item.rs
src/librustdoc/html/render/span_map.rs
src/librustdoc/html/render/write_shared.rs
src/librustdoc/html/sources.rs
src/librustdoc/html/static/css/noscript.css
src/librustdoc/html/static/css/rustdoc.css
src/librustdoc/html/static/css/themes/ayu.css
src/librustdoc/html/static/css/themes/dark.css
src/librustdoc/html/static/css/themes/light.css
src/librustdoc/html/static/fonts/NanumBarunGothic-LICENSE.txt [new file with mode: 0644]
src/librustdoc/html/static/fonts/NanumBarunGothic.ttf.woff [new file with mode: 0644]
src/librustdoc/html/static/fonts/NanumBarunGothic.ttf.woff2 [new file with mode: 0644]
src/librustdoc/html/static/fonts/noto-sans-kr-LICENSE.txt [deleted file]
src/librustdoc/html/static/fonts/noto-sans-kr-regular.woff [deleted file]
src/librustdoc/html/static/fonts/noto-sans-kr-regular.woff2 [deleted file]
src/librustdoc/html/static/js/main.js
src/librustdoc/html/static/js/search.js
src/librustdoc/html/static_files.rs
src/librustdoc/html/templates/page.html
src/librustdoc/json/conversions.rs
src/librustdoc/lib.rs
src/librustdoc/passes/bare_urls.rs
src/librustdoc/passes/calculate_doc_coverage.rs
src/librustdoc/passes/check_code_block_syntax.rs
src/librustdoc/passes/check_doc_test_visibility.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/passes/collect_intra_doc_links/early.rs
src/librustdoc/passes/collect_trait_impls.rs
src/librustdoc/passes/html_tags.rs
src/librustdoc/passes/stripper.rs
src/librustdoc/scrape_examples.rs
src/librustdoc/visit.rs [new file with mode: 0644]
src/librustdoc/visit_ast.rs
src/stage0.json
src/test/assembly/asm/aarch64-types.rs
src/test/assembly/asm/arm-types.rs
src/test/assembly/asm/bpf-types.rs
src/test/assembly/asm/global_asm.rs
src/test/assembly/asm/hexagon-types.rs
src/test/assembly/asm/mips-types.rs
src/test/assembly/asm/nvptx-types.rs
src/test/assembly/asm/powerpc-types.rs
src/test/assembly/asm/riscv-types.rs
src/test/assembly/asm/s390x-types.rs
src/test/assembly/asm/wasm-types.rs
src/test/assembly/asm/x86-types.rs
src/test/codegen-units/item-collection/implicit-panic-call.rs [new file with mode: 0644]
src/test/codegen/asm-powerpc-clobbers.rs
src/test/codegen/sanitizer_cfi_add_canonical_jump_tables_flag.rs [new file with mode: 0644]
src/test/codegen/sanitizer_cfi_emit_type_checks.rs [new file with mode: 0644]
src/test/codegen/sanitizer_cfi_emit_type_metadata.rs [new file with mode: 0644]
src/test/mir-opt/issue-78192.rs
src/test/pretty/dollar-crate.pp
src/test/pretty/issue-4264.pp
src/test/run-make-fulldeps/foreign-exceptions/foo.rs
src/test/run-make-fulldeps/invalid-library/Makefile
src/test/run-make-fulldeps/obtain-borrowck/driver.rs
src/test/run-make-fulldeps/print-cfg/Makefile
src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/Makefile [new file with mode: 0644]
src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/examples/ex.rs [new file with mode: 0644]
src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs [new file with mode: 0644]
src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/proc.rs [new file with mode: 0644]
src/test/run-make-fulldeps/tools.mk
src/test/run-make/invalid-so/Makefile [new file with mode: 0644]
src/test/run-make/invalid-so/bar.rs [new file with mode: 0644]
src/test/run-make/issue-36710/foo.rs
src/test/run-make/rustdoc-scrape-examples-invalid-expr/Makefile [new file with mode: 0644]
src/test/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs [new file with mode: 0644]
src/test/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs [new file with mode: 0644]
src/test/run-make/rustdoc-scrape-examples-multiple/src/lib.rs
src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex1.rs
src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex2.rs
src/test/run-make/rustdoc-scrape-examples-ordering/src/lib.rs
src/test/rustdoc-gui/headings.goml [new file with mode: 0644]
src/test/rustdoc-gui/javascript-disabled.goml [new file with mode: 0644]
src/test/rustdoc-gui/module-items-font.goml
src/test/rustdoc-gui/overflow-tooltip-information.goml [new file with mode: 0644]
src/test/rustdoc-gui/sidebar.goml
src/test/rustdoc-gui/src/test_docs/lib.rs
src/test/rustdoc-js/generics.js
src/test/rustdoc-js/generics.rs
src/test/rustdoc-ui/invalid-doc-attr.stderr
src/test/rustdoc-ui/recursive-deref-ice.rs [new file with mode: 0644]
src/test/rustdoc/deref-recursive-pathbuf.rs [new file with mode: 0644]
src/test/rustdoc/deref-recursive.rs [new file with mode: 0644]
src/test/rustdoc/deref-typedef.rs
src/test/rustdoc/doc-auto-cfg.rs [new file with mode: 0644]
src/test/rustdoc/doc-cfg-hide.rs
src/test/rustdoc/doc-cfg-implicit.rs
src/test/rustdoc/feature-gate-doc_auto_cfg.rs [new file with mode: 0644]
src/test/rustdoc/include_str_cut.rs [new file with mode: 0644]
src/test/rustdoc/recursive-deref-sidebar.rs
src/test/rustdoc/recursive-deref.rs
src/test/rustdoc/short-line.md [new file with mode: 0644]
src/test/ui-fulldeps/internal-lints/query_stability.rs [deleted file]
src/test/ui-fulldeps/internal-lints/query_stability.stderr [deleted file]
src/test/ui-fulldeps/internal-lints/query_stability_incorrect.rs [deleted file]
src/test/ui-fulldeps/internal-lints/query_stability_incorrect.stderr [deleted file]
src/test/ui-fulldeps/lint-tool-test.rs
src/test/ui-fulldeps/lint-tool-test.stderr
src/test/ui/abi/unsupported.aarch64.stderr
src/test/ui/abi/unsupported.arm.stderr
src/test/ui/abi/unsupported.rs
src/test/ui/abi/unsupported.x64.stderr
src/test/ui/argument-passing.rs [deleted file]
src/test/ui/array-slice-vec/mut-vstore-expr.rs [new file with mode: 0644]
src/test/ui/asm/aarch64/bad-reg.rs
src/test/ui/asm/aarch64/const.rs
src/test/ui/asm/aarch64/parse-error.rs
src/test/ui/asm/aarch64/sym.rs
src/test/ui/asm/aarch64/type-check-2.rs
src/test/ui/asm/aarch64/type-check-3.rs
src/test/ui/asm/aarch64/type-check-3.stderr
src/test/ui/asm/bad-template.rs
src/test/ui/asm/issue-89305.rs
src/test/ui/asm/issue-89305.stderr
src/test/ui/asm/naked-functions.rs
src/test/ui/asm/naked-functions.stderr
src/test/ui/asm/named-asm-labels.rs
src/test/ui/asm/type-check-1.rs
src/test/ui/asm/x86_64/bad-reg.rs
src/test/ui/asm/x86_64/const.rs
src/test/ui/asm/x86_64/issue-89875.rs [new file with mode: 0644]
src/test/ui/asm/x86_64/parse-error.rs
src/test/ui/asm/x86_64/sym.rs
src/test/ui/asm/x86_64/type-check-2.rs
src/test/ui/asm/x86_64/type-check-3.rs
src/test/ui/associated-types/associated-types-path-2.rs
src/test/ui/associated-types/associated-types-path-2.stderr
src/test/ui/associated-types/issue-22066.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-22828.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-28871.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-47139-1.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-54467.rs [new file with mode: 0644]
src/test/ui/async-await/async-fn-nonsend.stderr
src/test/ui/async-await/issue-64130-1-sync.stderr
src/test/ui/async-await/issue-64130-2-send.stderr
src/test/ui/async-await/issue-64130-3-other.stderr
src/test/ui/async-await/issue-64130-non-send-future-diags.rs
src/test/ui/async-await/issue-64130-non-send-future-diags.stderr
src/test/ui/async-await/issue-71137.rs
src/test/ui/async-await/issue-71137.stderr
src/test/ui/async-await/issue-73541-1.rs [new file with mode: 0644]
src/test/ui/async-await/issue-73541-1.stderr [new file with mode: 0644]
src/test/ui/async-await/issues/issue-67893.rs
src/test/ui/async-await/issues/issue-67893.stderr
src/test/ui/async-await/pin-needed-to-poll-2.stderr
src/test/ui/attributes/invalid-doc-attr.stderr
src/test/ui/attributes/issue-40962.rs [new file with mode: 0644]
src/test/ui/attributes/key-value-expansion.stderr
src/test/ui/attributes/unrestricted-attribute-tokens.rs [new file with mode: 0644]
src/test/ui/auxiliary/changing-crates-a1.rs [deleted file]
src/test/ui/auxiliary/changing-crates-a2.rs [deleted file]
src/test/ui/auxiliary/changing-crates-b.rs [deleted file]
src/test/ui/auxiliary/legacy-const-generics.rs [deleted file]
src/test/ui/auxiliary/lto-duplicate-symbols1.rs [deleted file]
src/test/ui/auxiliary/lto-duplicate-symbols2.rs [deleted file]
src/test/ui/auxiliary/lto-rustc-loads-linker-plugin.rs [deleted file]
src/test/ui/auxiliary/nested_item.rs [deleted file]
src/test/ui/bastion-of-the-turbofish.rs [deleted file]
src/test/ui/binding/ambiguity-item.stderr
src/test/ui/binop/structured-compare.rs [new file with mode: 0644]
src/test/ui/borrowck/issue-46095.rs [new file with mode: 0644]
src/test/ui/box/new-box.rs [new file with mode: 0644]
src/test/ui/c-variadic/issue-32201.rs [new file with mode: 0644]
src/test/ui/c-variadic/issue-32201.stderr [new file with mode: 0644]
src/test/ui/cast/supported-cast.rs [new file with mode: 0644]
src/test/ui/changing-crates.rs [deleted file]
src/test/ui/changing-crates.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/issue-90465.fixed [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/issue-90465.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/issue-90465.stderr [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed
src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs
src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr
src/test/ui/closures/2229_closure_analysis/migrations/issue-90024-adt-correct-subst.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed
src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs
src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr
src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed
src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs
src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr
src/test/ui/closures/issue-10398.rs [new file with mode: 0644]
src/test/ui/closures/issue-10398.stderr [new file with mode: 0644]
src/test/ui/closures/issue-42463.rs [new file with mode: 0644]
src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr
src/test/ui/closures/print/closure-print-generic-verbose-2.stderr
src/test/ui/closures/print/closure-print-verbose.stderr
src/test/ui/coercion/auxiliary/issue-39823.rs [new file with mode: 0644]
src/test/ui/coercion/issue-14589.rs [new file with mode: 0644]
src/test/ui/coercion/issue-39823.rs [new file with mode: 0644]
src/test/ui/coercion/issue-73886.rs [new file with mode: 0644]
src/test/ui/coercion/issue-73886.stderr [new file with mode: 0644]
src/test/ui/compare-method/issue-90444.rs [new file with mode: 0644]
src/test/ui/compare-method/issue-90444.stderr [new file with mode: 0644]
src/test/ui/conditional-compilation/issue-34028.rs [new file with mode: 0644]
src/test/ui/const-generics/auxiliary/legacy-const-generics.rs [new file with mode: 0644]
src/test/ui/const-generics/expose-default-substs-param-env.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr
src/test/ui/const-generics/impl-trait-with-const-arguments.stderr
src/test/ui/const-generics/issues/issue-88997.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-88997.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-89304.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-89334.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-90364.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-90364.stderr [new file with mode: 0644]
src/test/ui/const-generics/legacy-const-generics-bad.rs [new file with mode: 0644]
src/test/ui/const-generics/legacy-const-generics-bad.stderr [new file with mode: 0644]
src/test/ui/const-generics/legacy-const-generics.rs [new file with mode: 0644]
src/test/ui/consts/inline_asm.rs
src/test/ui/consts/inline_asm.stderr
src/test/ui/consts/issue-13902.rs [new file with mode: 0644]
src/test/ui/consts/issue-17074.rs [new file with mode: 0644]
src/test/ui/consts/issue-18294.rs [new file with mode: 0644]
src/test/ui/consts/issue-18294.stderr [new file with mode: 0644]
src/test/ui/consts/issue-23968-const-not-overflow.rs [new file with mode: 0644]
src/test/ui/consts/issue-37550-1.rs [new file with mode: 0644]
src/test/ui/consts/issue-37550-1.stderr [new file with mode: 0644]
src/test/ui/consts/issue-37991.rs [new file with mode: 0644]
src/test/ui/consts/promote-not.rs
src/test/ui/consts/promote-not.stderr
src/test/ui/consts/qualif-indirect-mutation-fail.rs [new file with mode: 0644]
src/test/ui/consts/qualif-indirect-mutation-fail.stderr [new file with mode: 0644]
src/test/ui/consts/qualif-indirect-mutation-pass.rs [new file with mode: 0644]
src/test/ui/consts/qualif-union.rs [new file with mode: 0644]
src/test/ui/consts/qualif-union.stderr [new file with mode: 0644]
src/test/ui/crate-loading/auxiliary/libfoo.rlib [new file with mode: 0644]
src/test/ui/crate-loading/invalid-rlib.rs [new file with mode: 0644]
src/test/ui/crate-loading/invalid-rlib.stderr [new file with mode: 0644]
src/test/ui/deprecation/deprecation-lint.rs
src/test/ui/deprecation/deprecation-lint.stderr
src/test/ui/deprecation/try-macro-suggestion.rs [new file with mode: 0644]
src/test/ui/deprecation/try-macro-suggestion.stderr [new file with mode: 0644]
src/test/ui/deriving/issue-19358.rs [new file with mode: 0644]
src/test/ui/deriving/issue-58319.rs [new file with mode: 0644]
src/test/ui/diverging-tuple-parts-39485.rs [deleted file]
src/test/ui/diverging-tuple-parts-39485.stderr [deleted file]
src/test/ui/drop/issue-35546.rs [new file with mode: 0644]
src/test/ui/drop/terminate-in-initializer.rs [new file with mode: 0644]
src/test/ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs [new file with mode: 0644]
src/test/ui/editions-crate-root-2015.rs [deleted file]
src/test/ui/editions-crate-root-2015.stderr [deleted file]
src/test/ui/editions/epoch-gate-feature.rs [new file with mode: 0644]
src/test/ui/entry-point/imported_main_conflict.rs
src/test/ui/entry-point/imported_main_conflict.stderr
src/test/ui/enum-discriminant/issue-51582.rs [new file with mode: 0644]
src/test/ui/enum/issue-42747.rs [new file with mode: 0644]
src/test/ui/epoch-gate-feature.rs [deleted file]
src/test/ui/error-codes/E0659.stderr
src/test/ui/extern/extern-methods.rs
src/test/ui/extern/extern-thiscall.rs
src/test/ui/extern/extern-vectorcall.rs
src/test/ui/extern/issue-28324.mir.stderr [new file with mode: 0644]
src/test/ui/extern/issue-28324.rs [new file with mode: 0644]
src/test/ui/extern/issue-28324.thir.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-asm_const.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-asm_const.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-asm_experimental_arch.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-asm_experimental_arch.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-asm_sym.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-asm_sym.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.rs [deleted file]
src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr [deleted file]
src/test/ui/for-loop-while/issue-51345.rs [new file with mode: 0644]
src/test/ui/for-loop-while/long-while.rs [new file with mode: 0644]
src/test/ui/foreign/nil-decl-in-foreign.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/collections-project-default.rs
src/test/ui/generic-associated-types/collections.rs
src/test/ui/generic-associated-types/generic-associated-type-bounds.rs
src/test/ui/generic-associated-types/issue-70303.rs
src/test/ui/generic-associated-types/issue-76535.rs
src/test/ui/generic-associated-types/issue-76535.stderr
src/test/ui/generic-associated-types/issue-79422.rs
src/test/ui/generic-associated-types/issue-79422.stderr
src/test/ui/generic-associated-types/issue-86787.rs
src/test/ui/generic-associated-types/issue-86787.stderr
src/test/ui/generic-associated-types/issue-87258_a.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-87258_a.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-87258_b.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-87258_b.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-88287.rs
src/test/ui/generic-associated-types/issue-88360.rs
src/test/ui/generic-associated-types/issue-88360.stderr
src/test/ui/generic-associated-types/issue-88459.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-88595.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-88595.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-90014.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-90014.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.rs
src/test/ui/generic-associated-types/self-outlives-lint.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/self-outlives-lint.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/streaming_iterator.rs
src/test/ui/generic-associated-types/variance_constraints.rs
src/test/ui/generics/issue-1112.rs [new file with mode: 0644]
src/test/ui/generics/issue-333.rs [new file with mode: 0644]
src/test/ui/generics/issue-59508-1.rs [new file with mode: 0644]
src/test/ui/generics/issue-59508-1.stderr [new file with mode: 0644]
src/test/ui/generics/issue-59508.fixed [new file with mode: 0644]
src/test/ui/generics/issue-59508.rs [new file with mode: 0644]
src/test/ui/generics/issue-59508.stderr [new file with mode: 0644]
src/test/ui/hello2021.rs
src/test/ui/higher-rank-trait-bounds/issue-60283.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/issue-60283.stderr [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr [deleted file]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.nll.stderr [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-76956.rs [new file with mode: 0644]
src/test/ui/hrtb/issue-62203-hrtb-ice.rs
src/test/ui/hrtb/issue-62203-hrtb-ice.stderr
src/test/ui/hrtb/issue-90177.rs [new file with mode: 0644]
src/test/ui/hygiene/auxiliary/fields.rs [new file with mode: 0644]
src/test/ui/hygiene/auxiliary/methods.rs [new file with mode: 0644]
src/test/ui/hygiene/auxiliary/pub_hygiene.rs [new file with mode: 0644]
src/test/ui/hygiene/auxiliary/use_by_macro.rs [new file with mode: 0644]
src/test/ui/hygiene/auxiliary/variants.rs [new file with mode: 0644]
src/test/ui/hygiene/cross-crate-define-and-use.rs [new file with mode: 0644]
src/test/ui/hygiene/cross-crate-fields.rs [new file with mode: 0644]
src/test/ui/hygiene/cross-crate-glob-hygiene.rs [new file with mode: 0644]
src/test/ui/hygiene/cross-crate-glob-hygiene.stderr [new file with mode: 0644]
src/test/ui/hygiene/cross-crate-methods.rs [new file with mode: 0644]
src/test/ui/hygiene/cross-crate-name-collision.rs [new file with mode: 0644]
src/test/ui/hygiene/cross-crate-name-hiding-2.rs [new file with mode: 0644]
src/test/ui/hygiene/cross-crate-name-hiding-2.stderr [new file with mode: 0644]
src/test/ui/hygiene/cross-crate-name-hiding.rs [new file with mode: 0644]
src/test/ui/hygiene/cross-crate-name-hiding.stderr [new file with mode: 0644]
src/test/ui/hygiene/cross-crate-redefine.rs [new file with mode: 0644]
src/test/ui/hygiene/cross-crate-redefine.stderr [new file with mode: 0644]
src/test/ui/hygiene/cross-crate-variants.rs [new file with mode: 0644]
src/test/ui/hygiene/cross_crate_hygiene.rs [deleted file]
src/test/ui/hygiene/lambda-var-hygiene.rs [new file with mode: 0644]
src/test/ui/impl-trait/auto-trait-leak2.stderr
src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/feature-gate.stderr
src/test/ui/impl-trait/issue-49579.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-49685.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-51185.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/universal-issue-48703.stderr
src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr
src/test/ui/impl-trait/where-allowed.rs
src/test/ui/impl-trait/where-allowed.stderr
src/test/ui/imports/duplicate.stderr
src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr
src/test/ui/imports/glob-shadowing.stderr
src/test/ui/imports/issue-53269.stderr
src/test/ui/imports/issue-55884-1.stderr
src/test/ui/imports/issue-56125.stderr
src/test/ui/imports/issue-57539.stderr
src/test/ui/imports/local-modularized-tricky-fail-1.stderr
src/test/ui/imports/macro-paths.stderr
src/test/ui/imports/macros.stderr
src/test/ui/imports/rfc-1560-warning-cycle.stderr
src/test/ui/imports/shadow_builtin_macros.stderr
src/test/ui/in-band-lifetimes.rs [deleted file]
src/test/ui/in-band-lifetimes/in-band-lifetimes.rs [new file with mode: 0644]
src/test/ui/inference/lub-glb-with-unbound-infer-var.rs [new file with mode: 0644]
src/test/ui/inline-const/const-expr-inference.rs [new file with mode: 0644]
src/test/ui/inline-const/const-expr-lifetime-err.rs [new file with mode: 0644]
src/test/ui/inline-const/const-expr-lifetime-err.stderr [new file with mode: 0644]
src/test/ui/inline-const/const-expr-lifetime.rs [new file with mode: 0644]
src/test/ui/inline-const/const-match-pat-inference.rs [new file with mode: 0644]
src/test/ui/inline-const/const-match-pat-lifetime-err.rs [new file with mode: 0644]
src/test/ui/inline-const/const-match-pat-lifetime.rs [new file with mode: 0644]
src/test/ui/intrinsics/const-eval-select-bad.rs
src/test/ui/intrinsics/const-eval-select-bad.stderr
src/test/ui/intrinsics/intrinsic-alignment.rs
src/test/ui/issues/auxiliary/issue-19163.rs [deleted file]
src/test/ui/issues/auxiliary/issue-39823.rs [deleted file]
src/test/ui/issues/auxiliary/xcrate-issue-43189-a.rs [deleted file]
src/test/ui/issues/auxiliary/xcrate-issue-43189-b.rs [deleted file]
src/test/ui/issues/auxiliary/xcrate-issue-46112-rexport-core.rs [deleted file]
src/test/ui/issues/auxiliary/xcrate-issue-61711-b.rs [deleted file]
src/test/ui/issues/issue-10398.rs [deleted file]
src/test/ui/issues/issue-10398.stderr [deleted file]
src/test/ui/issues/issue-1112.rs [deleted file]
src/test/ui/issues/issue-11577.rs [deleted file]
src/test/ui/issues/issue-11940.rs [deleted file]
src/test/ui/issues/issue-12796.rs [deleted file]
src/test/ui/issues/issue-12796.stderr [deleted file]
src/test/ui/issues/issue-13483.rs [deleted file]
src/test/ui/issues/issue-13483.stderr [deleted file]
src/test/ui/issues/issue-13902.rs [deleted file]
src/test/ui/issues/issue-14227.mir.stderr [deleted file]
src/test/ui/issues/issue-14227.rs [deleted file]
src/test/ui/issues/issue-14227.thir.stderr [deleted file]
src/test/ui/issues/issue-14456.rs [deleted file]
src/test/ui/issues/issue-14589.rs [deleted file]
src/test/ui/issues/issue-14837.rs [deleted file]
src/test/ui/issues/issue-15080.rs [deleted file]
src/test/ui/issues/issue-16098.rs [deleted file]
src/test/ui/issues/issue-16098.stderr [deleted file]
src/test/ui/issues/issue-16272.rs [deleted file]
src/test/ui/issues/issue-17074.rs [deleted file]
src/test/ui/issues/issue-18060.rs [deleted file]
src/test/ui/issues/issue-18294.rs [deleted file]
src/test/ui/issues/issue-18294.stderr [deleted file]
src/test/ui/issues/issue-18652.rs [deleted file]
src/test/ui/issues/issue-19163.rs [deleted file]
src/test/ui/issues/issue-19163.stderr [deleted file]
src/test/ui/issues/issue-19358.rs [deleted file]
src/test/ui/issues/issue-19660.rs [deleted file]
src/test/ui/issues/issue-19660.stderr [deleted file]
src/test/ui/issues/issue-20091.rs [deleted file]
src/test/ui/issues/issue-20616-4.rs [deleted file]
src/test/ui/issues/issue-20616-4.stderr [deleted file]
src/test/ui/issues/issue-20616-5.rs [deleted file]
src/test/ui/issues/issue-20616-5.stderr [deleted file]
src/test/ui/issues/issue-20616-6.rs [deleted file]
src/test/ui/issues/issue-20616-6.stderr [deleted file]
src/test/ui/issues/issue-20616-7.rs [deleted file]
src/test/ui/issues/issue-20616-7.stderr [deleted file]
src/test/ui/issues/issue-20823.rs [deleted file]
src/test/ui/issues/issue-21356.rs [deleted file]
src/test/ui/issues/issue-21356.stderr [deleted file]
src/test/ui/issues/issue-21475.rs [deleted file]
src/test/ui/issues/issue-21520.rs [deleted file]
src/test/ui/issues/issue-22066.rs [deleted file]
src/test/ui/issues/issue-22463.rs [deleted file]
src/test/ui/issues/issue-22828.rs [deleted file]
src/test/ui/issues/issue-23458.rs [deleted file]
src/test/ui/issues/issue-23458.stderr [deleted file]
src/test/ui/issues/issue-23716.rs [deleted file]
src/test/ui/issues/issue-23716.stderr [deleted file]
src/test/ui/issues/issue-23968-const-not-overflow.rs [deleted file]
src/test/ui/issues/issue-24010.rs [deleted file]
src/test/ui/issues/issue-24313.rs [deleted file]
src/test/ui/issues/issue-2444.rs [deleted file]
src/test/ui/issues/issue-26251.rs [deleted file]
src/test/ui/issues/issue-26448-1.rs [deleted file]
src/test/ui/issues/issue-26448-2.rs [deleted file]
src/test/ui/issues/issue-26448-3.rs [deleted file]
src/test/ui/issues/issue-26638.rs [deleted file]
src/test/ui/issues/issue-26638.stderr [deleted file]
src/test/ui/issues/issue-26996.rs [deleted file]
src/test/ui/issues/issue-2748-b.rs [deleted file]
src/test/ui/issues/issue-28324.mir.stderr [deleted file]
src/test/ui/issues/issue-28324.rs [deleted file]
src/test/ui/issues/issue-28324.thir.stderr [deleted file]
src/test/ui/issues/issue-28498-ugeh-with-passed-to-fn.rs [deleted file]
src/test/ui/issues/issue-28871.rs [deleted file]
src/test/ui/issues/issue-29084.rs [deleted file]
src/test/ui/issues/issue-29084.stderr [deleted file]
src/test/ui/issues/issue-3021-c.rs [deleted file]
src/test/ui/issues/issue-3021-c.stderr [deleted file]
src/test/ui/issues/issue-3021.rs [deleted file]
src/test/ui/issues/issue-3021.stderr [deleted file]
src/test/ui/issues/issue-30225.rs [deleted file]
src/test/ui/issues/issue-30225.stderr [deleted file]
src/test/ui/issues/issue-30355.rs [deleted file]
src/test/ui/issues/issue-30355.stderr [deleted file]
src/test/ui/issues/issue-31076.rs [deleted file]
src/test/ui/issues/issue-31076.stderr [deleted file]
src/test/ui/issues/issue-31299.rs
src/test/ui/issues/issue-31804.rs [deleted file]
src/test/ui/issues/issue-31804.stderr [deleted file]
src/test/ui/issues/issue-31845.rs [deleted file]
src/test/ui/issues/issue-31845.stderr [deleted file]
src/test/ui/issues/issue-3211.rs [deleted file]
src/test/ui/issues/issue-32201.rs [deleted file]
src/test/ui/issues/issue-32201.stderr [deleted file]
src/test/ui/issues/issue-333.rs [deleted file]
src/test/ui/issues/issue-34028.rs [deleted file]
src/test/ui/issues/issue-34171.rs [deleted file]
src/test/ui/issues/issue-34255-1.rs [deleted file]
src/test/ui/issues/issue-34255-1.stderr [deleted file]
src/test/ui/issues/issue-35546.rs [deleted file]
src/test/ui/issues/issue-37175.rs [deleted file]
src/test/ui/issues/issue-37366.rs [deleted file]
src/test/ui/issues/issue-37550.rs [deleted file]
src/test/ui/issues/issue-37550.stderr [deleted file]
src/test/ui/issues/issue-37991.rs [deleted file]
src/test/ui/issues/issue-38604.rs [deleted file]
src/test/ui/issues/issue-38604.stderr [deleted file]
src/test/ui/issues/issue-39388.rs [deleted file]
src/test/ui/issues/issue-39388.stderr [deleted file]
src/test/ui/issues/issue-3973.rs [deleted file]
src/test/ui/issues/issue-3973.stderr [deleted file]
src/test/ui/issues/issue-39823.rs [deleted file]
src/test/ui/issues/issue-40770.rs [deleted file]
src/test/ui/issues/issue-40827.stderr
src/test/ui/issues/issue-40962.rs [deleted file]
src/test/ui/issues/issue-42463.rs [deleted file]
src/test/ui/issues/issue-42679.rs [deleted file]
src/test/ui/issues/issue-42747.rs [deleted file]
src/test/ui/issues/issue-43189.rs [deleted file]
src/test/ui/issues/issue-43189.stderr [deleted file]
src/test/ui/issues/issue-44005.rs [deleted file]
src/test/ui/issues/issue-44005.stderr [deleted file]
src/test/ui/issues/issue-4401.rs [deleted file]
src/test/ui/issues/issue-4448.rs [deleted file]
src/test/ui/issues/issue-45124.rs [deleted file]
src/test/ui/issues/issue-45152.rs [deleted file]
src/test/ui/issues/issue-46095.rs [deleted file]
src/test/ui/issues/issue-46112.rs [deleted file]
src/test/ui/issues/issue-46112.stderr [deleted file]
src/test/ui/issues/issue-47139-1.rs [deleted file]
src/test/ui/issues/issue-49040.rs [deleted file]
src/test/ui/issues/issue-49040.stderr [deleted file]
src/test/ui/issues/issue-49579.rs [deleted file]
src/test/ui/issues/issue-49685.rs [deleted file]
src/test/ui/issues/issue-50731.rs [deleted file]
src/test/ui/issues/issue-5099.rs [deleted file]
src/test/ui/issues/issue-5099.stderr [deleted file]
src/test/ui/issues/issue-50993.rs [deleted file]
src/test/ui/issues/issue-50993.stderr [deleted file]
src/test/ui/issues/issue-51185.rs [deleted file]
src/test/ui/issues/issue-51345.rs [deleted file]
src/test/ui/issues/issue-51582.rs [deleted file]
src/test/ui/issues/issue-53787-inline-assembler-macro.rs [deleted file]
src/test/ui/issues/issue-53787-inline-assembler-macro.stderr [deleted file]
src/test/ui/issues/issue-54467.rs [deleted file]
src/test/ui/issues/issue-56031.rs [deleted file]
src/test/ui/issues/issue-56031.stderr [deleted file]
src/test/ui/issues/issue-57410-1.rs [deleted file]
src/test/ui/issues/issue-57597.rs [deleted file]
src/test/ui/issues/issue-57597.stderr [deleted file]
src/test/ui/issues/issue-58319.rs [deleted file]
src/test/ui/issues/issue-59029-1.rs [deleted file]
src/test/ui/issues/issue-59029-1.stderr [deleted file]
src/test/ui/issues/issue-59508-1.rs [deleted file]
src/test/ui/issues/issue-59508-1.stderr [deleted file]
src/test/ui/issues/issue-59508.fixed [deleted file]
src/test/ui/issues/issue-59508.rs [deleted file]
src/test/ui/issues/issue-59508.stderr [deleted file]
src/test/ui/issues/issue-60283.rs [deleted file]
src/test/ui/issues/issue-60283.stderr [deleted file]
src/test/ui/issues/issue-60662.rs [deleted file]
src/test/ui/issues/issue-60662.stdout [deleted file]
src/test/ui/issues/issue-61711-once-caused-rustc-inf-loop.rs [deleted file]
src/test/ui/issues/issue-61882-2.rs [deleted file]
src/test/ui/issues/issue-61882-2.stderr [deleted file]
src/test/ui/issues/issue-61882.rs [deleted file]
src/test/ui/issues/issue-61882.stderr [deleted file]
src/test/ui/issues/issue-63364.rs [deleted file]
src/test/ui/issues/issue-63364.stderr [deleted file]
src/test/ui/issues/issue-6596-1.rs [deleted file]
src/test/ui/issues/issue-6596-1.stderr [deleted file]
src/test/ui/issues/issue-6804.rs [deleted file]
src/test/ui/issues/issue-6804.stderr [deleted file]
src/test/ui/issues/issue-72455.rs [deleted file]
src/test/ui/issues/issue-7246.rs
src/test/ui/issues/issue-7246.stderr
src/test/ui/issues/issue-72574-2.rs [deleted file]
src/test/ui/issues/issue-72574-2.stderr [deleted file]
src/test/ui/issues/issue-73541-1.rs [deleted file]
src/test/ui/issues/issue-73541-1.stderr [deleted file]
src/test/ui/issues/issue-73886.rs [deleted file]
src/test/ui/issues/issue-73886.stderr [deleted file]
src/test/ui/issues/issue-74739.rs [deleted file]
src/test/ui/issues/issue-811.rs [deleted file]
src/test/ui/issues/issue-8351-1.rs [deleted file]
src/test/ui/issues/issue-8351-2.rs [deleted file]
src/test/ui/issues/issue-86865.rs [deleted file]
src/test/ui/issues/issue-86865.stderr [deleted file]
src/test/ui/issues/issue-8827.rs [deleted file]
src/test/ui/issues/issue-9396.rs [deleted file]
src/test/ui/iterators/into-iter-on-arrays-2021.rs
src/test/ui/lambda-var-hygiene.rs [deleted file]
src/test/ui/lang-items/issue-19660.rs [new file with mode: 0644]
src/test/ui/lang-items/issue-19660.stderr [new file with mode: 0644]
src/test/ui/lang-items/issue-31076.rs [new file with mode: 0644]
src/test/ui/lang-items/issue-31076.stderr [new file with mode: 0644]
src/test/ui/lang-items/required-lang-item.rs [new file with mode: 0644]
src/test/ui/lang-items/required-lang-item.stderr [new file with mode: 0644]
src/test/ui/legacy-const-generics-bad.rs [deleted file]
src/test/ui/legacy-const-generics-bad.stderr [deleted file]
src/test/ui/legacy-const-generics.rs [deleted file]
src/test/ui/lifetimes/issue-26638.rs [new file with mode: 0644]
src/test/ui/lifetimes/issue-26638.stderr [new file with mode: 0644]
src/test/ui/lifetimes/issue-90170-elision-mismatch.fixed [new file with mode: 0644]
src/test/ui/lifetimes/issue-90170-elision-mismatch.nll.stderr [new file with mode: 0644]
src/test/ui/lifetimes/issue-90170-elision-mismatch.rs [new file with mode: 0644]
src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr [new file with mode: 0644]
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr
src/test/ui/lint/crate_level_only_lint.rs
src/test/ui/lint/crate_level_only_lint.stderr
src/test/ui/lint/forbid-group-group-2.rs
src/test/ui/lint/forbid-group-group-2.stderr
src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs
src/test/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs
src/test/ui/lint/force-warn/warn-by-default-lint-two-modules.rs
src/test/ui/lint/force-warn/warnings-lint-group.rs
src/test/ui/lint/force-warn/warnings-lint-group.stderr
src/test/ui/lint/issue-14837.rs [new file with mode: 0644]
src/test/ui/lint/issue-57410-1.rs [new file with mode: 0644]
src/test/ui/lint/issue-63364.rs [new file with mode: 0644]
src/test/ui/lint/issue-63364.stderr [new file with mode: 0644]
src/test/ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs [new file with mode: 0644]
src/test/ui/lint/lint-forbid-internal-unsafe.rs
src/test/ui/lint/lint-forbid-internal-unsafe.stderr
src/test/ui/lint/must_not_suspend/gated.rs [new file with mode: 0644]
src/test/ui/lint/must_not_suspend/gated.stderr [new file with mode: 0644]
src/test/ui/lint/must_not_suspend/issue-89562.rs [new file with mode: 0644]
src/test/ui/lint/must_not_suspend/mutex.rs
src/test/ui/lint/must_not_suspend/mutex.stderr
src/test/ui/lint/must_not_suspend/warn.rs
src/test/ui/lint/must_not_suspend/warn.stderr
src/test/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.rs
src/test/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.stderr
src/test/ui/lint/unnecessary-extern-crate.rs [new file with mode: 0644]
src/test/ui/lint/unnecessary-extern-crate.stderr [new file with mode: 0644]
src/test/ui/lint/unused_parens_json_suggestion.fixed
src/test/ui/lint/unused_parens_json_suggestion.rs
src/test/ui/lint/unused_parens_json_suggestion.stderr
src/test/ui/lint/unused_parens_remove_json_suggestion.fixed
src/test/ui/lint/unused_parens_remove_json_suggestion.rs
src/test/ui/lint/unused_parens_remove_json_suggestion.stderr
src/test/ui/lint/warn-ctypes-inhibit.rs [new file with mode: 0644]
src/test/ui/llvm-asm/issue-23458.rs [new file with mode: 0644]
src/test/ui/llvm-asm/issue-23458.stderr [new file with mode: 0644]
src/test/ui/llvm-asm/issue-37366.rs [new file with mode: 0644]
src/test/ui/llvm-asm/issue-53787-inline-assembler-macro.rs [new file with mode: 0644]
src/test/ui/llvm-asm/issue-53787-inline-assembler-macro.stderr [new file with mode: 0644]
src/test/ui/long-while.rs [deleted file]
src/test/ui/lto-and-no-bitcode-in-rlib.rs [deleted file]
src/test/ui/lto-and-no-bitcode-in-rlib.stderr [deleted file]
src/test/ui/lto-duplicate-symbols.rs [deleted file]
src/test/ui/lto-duplicate-symbols.stderr [deleted file]
src/test/ui/lto-many-codegen-units.rs [deleted file]
src/test/ui/lto-opt-level-s.rs [deleted file]
src/test/ui/lto-opt-level-z.rs [deleted file]
src/test/ui/lto-rustc-loads-linker-plugin.rs [deleted file]
src/test/ui/lto-still-runs-thread-dtors.rs [deleted file]
src/test/ui/lto-thin-rustc-loads-linker-plugin.rs [deleted file]
src/test/ui/lto/all-crates.rs [new file with mode: 0644]
src/test/ui/lto/auxiliary/dylib.rs [new file with mode: 0644]
src/test/ui/lto/auxiliary/lto-duplicate-symbols1.rs [new file with mode: 0644]
src/test/ui/lto/auxiliary/lto-duplicate-symbols2.rs [new file with mode: 0644]
src/test/ui/lto/auxiliary/lto-rustc-loads-linker-plugin.rs [new file with mode: 0644]
src/test/ui/lto/auxiliary/msvc-imp-present.rs [new file with mode: 0644]
src/test/ui/lto/auxiliary/thin-lto-inlines-aux.rs [new file with mode: 0644]
src/test/ui/lto/dylib-works.rs [new file with mode: 0644]
src/test/ui/lto/lto-and-no-bitcode-in-rlib.rs [new file with mode: 0644]
src/test/ui/lto/lto-and-no-bitcode-in-rlib.stderr [new file with mode: 0644]
src/test/ui/lto/lto-duplicate-symbols.rs [new file with mode: 0644]
src/test/ui/lto/lto-duplicate-symbols.stderr [new file with mode: 0644]
src/test/ui/lto/lto-many-codegen-units.rs [new file with mode: 0644]
src/test/ui/lto/lto-opt-level-s.rs [new file with mode: 0644]
src/test/ui/lto/lto-opt-level-z.rs [new file with mode: 0644]
src/test/ui/lto/lto-rustc-loads-linker-plugin.rs [new file with mode: 0644]
src/test/ui/lto/lto-still-runs-thread-dtors.rs [new file with mode: 0644]
src/test/ui/lto/lto-thin-rustc-loads-linker-plugin.rs [new file with mode: 0644]
src/test/ui/lto/msvc-imp-present.rs [new file with mode: 0644]
src/test/ui/lto/thin-lto-global-allocator.rs [new file with mode: 0644]
src/test/ui/lto/thin-lto-inlines.rs [new file with mode: 0644]
src/test/ui/lto/thin-lto-inlines2.rs [new file with mode: 0644]
src/test/ui/lto/weak-works.rs [new file with mode: 0644]
src/test/ui/lub-glb-with-unbound-infer-var.rs [deleted file]
src/test/ui/macros/ambiguity-legacy-vs-modern.stderr
src/test/ui/macros/auxiliary/issue-19163.rs [new file with mode: 0644]
src/test/ui/macros/issue-16098.rs [new file with mode: 0644]
src/test/ui/macros/issue-16098.stderr [new file with mode: 0644]
src/test/ui/macros/issue-19163.rs [new file with mode: 0644]
src/test/ui/macros/issue-19163.stderr [new file with mode: 0644]
src/test/ui/macros/issue-21356.rs [new file with mode: 0644]
src/test/ui/macros/issue-21356.stderr [new file with mode: 0644]
src/test/ui/macros/issue-22463.rs [new file with mode: 0644]
src/test/ui/macros/issue-29084.rs [new file with mode: 0644]
src/test/ui/macros/issue-29084.stderr [new file with mode: 0644]
src/test/ui/macros/issue-34171.rs [new file with mode: 0644]
src/test/ui/macros/issue-37175.rs [new file with mode: 0644]
src/test/ui/macros/issue-39388.rs [new file with mode: 0644]
src/test/ui/macros/issue-39388.stderr [new file with mode: 0644]
src/test/ui/macros/issue-40770.rs [new file with mode: 0644]
src/test/ui/macros/issue-57597.rs [new file with mode: 0644]
src/test/ui/macros/issue-57597.stderr [new file with mode: 0644]
src/test/ui/macros/issue-6596-1.rs [new file with mode: 0644]
src/test/ui/macros/issue-6596-1.stderr [new file with mode: 0644]
src/test/ui/macros/issue-86865.rs [new file with mode: 0644]
src/test/ui/macros/issue-86865.stderr [new file with mode: 0644]
src/test/ui/macros/macro-path-prelude-shadowing.stderr
src/test/ui/macros/macro-shadowing.stderr
src/test/ui/macros/out-of-order-shadowing.stderr
src/test/ui/macros/restricted-shadowing-legacy.stderr
src/test/ui/macros/restricted-shadowing-modern.stderr
src/test/ui/macros/trace_macros-format.rs [new file with mode: 0644]
src/test/ui/macros/trace_macros-format.stderr [new file with mode: 0644]
src/test/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.rs [new file with mode: 0644]
src/test/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.stderr [new file with mode: 0644]
src/test/ui/marker_trait_attr/overlap-permitted-for-annotated-marker-traits.rs [new file with mode: 0644]
src/test/ui/match/issue-11940.rs [new file with mode: 0644]
src/test/ui/match/issue-18060.rs [new file with mode: 0644]
src/test/ui/match/issue-26251.rs [new file with mode: 0644]
src/test/ui/match/issue-26996.rs [new file with mode: 0644]
src/test/ui/match/issue-42679.rs [new file with mode: 0644]
src/test/ui/matches2021.rs
src/test/ui/mir-dataflow/indirect-mutation-offset.rs [deleted file]
src/test/ui/mir-dataflow/indirect-mutation-offset.stderr [deleted file]
src/test/ui/mir/issue-74739.rs [new file with mode: 0644]
src/test/ui/mut-vstore-expr.rs [deleted file]
src/test/ui/mut/mutable-enum-indirect.stderr
src/test/ui/negative.rs [deleted file]
src/test/ui/nested_item_main.rs [deleted file]
src/test/ui/never_type/diverging-tuple-parts-39485.rs [new file with mode: 0644]
src/test/ui/never_type/diverging-tuple-parts-39485.stderr [new file with mode: 0644]
src/test/ui/new-box.rs [deleted file]
src/test/ui/nil-decl-in-foreign.rs [deleted file]
src/test/ui/no_send-enum.stderr
src/test/ui/no_share-enum.stderr
src/test/ui/numbers-arithmetic/unary-minus-suffix-inference.rs [new file with mode: 0644]
src/test/ui/object-does-not-impl-trait.rs [deleted file]
src/test/ui/object-does-not-impl-trait.stderr [deleted file]
src/test/ui/overlap-doesnt-conflict-with-specialization.rs [deleted file]
src/test/ui/overlap-doesnt-conflict-with-specialization.stderr [deleted file]
src/test/ui/overlap-permitted-for-annotated-marker-traits.rs [deleted file]
src/test/ui/packed/issue-46152.rs [new file with mode: 0644]
src/test/ui/parser/auxiliary/issue-89971-outer-attr-following-inner-attr-ice.rs [new file with mode: 0644]
src/test/ui/parser/bastion-of-the-turbofish.rs [new file with mode: 0644]
src/test/ui/parser/issue-13483.rs [new file with mode: 0644]
src/test/ui/parser/issue-13483.stderr [new file with mode: 0644]
src/test/ui/parser/issue-20616-4.rs [new file with mode: 0644]
src/test/ui/parser/issue-20616-4.stderr [new file with mode: 0644]
src/test/ui/parser/issue-20616-5.rs [new file with mode: 0644]
src/test/ui/parser/issue-20616-5.stderr [new file with mode: 0644]
src/test/ui/parser/issue-20616-6.rs [new file with mode: 0644]
src/test/ui/parser/issue-20616-6.stderr [new file with mode: 0644]
src/test/ui/parser/issue-20616-7.rs [new file with mode: 0644]
src/test/ui/parser/issue-20616-7.stderr [new file with mode: 0644]
src/test/ui/parser/issue-21475.rs [new file with mode: 0644]
src/test/ui/parser/issue-31804.rs [new file with mode: 0644]
src/test/ui/parser/issue-31804.stderr [new file with mode: 0644]
src/test/ui/parser/issue-34255-1.rs [new file with mode: 0644]
src/test/ui/parser/issue-34255-1.stderr [new file with mode: 0644]
src/test/ui/parser/issue-49040.rs [new file with mode: 0644]
src/test/ui/parser/issue-49040.stderr [new file with mode: 0644]
src/test/ui/parser/issue-56031.rs [new file with mode: 0644]
src/test/ui/parser/issue-56031.stderr [new file with mode: 0644]
src/test/ui/parser/issue-89971-outer-attr-following-inner-attr-ice.rs [new file with mode: 0644]
src/test/ui/parser/issue-89971-outer-attr-following-inner-attr-ice.stderr [new file with mode: 0644]
src/test/ui/parser/unicode-control-codepoints.rs [new file with mode: 0644]
src/test/ui/parser/unicode-control-codepoints.stderr [new file with mode: 0644]
src/test/ui/pattern/issue-11577.rs [new file with mode: 0644]
src/test/ui/pattern/issue-15080.rs [new file with mode: 0644]
src/test/ui/pattern/issue-72574-2.rs [new file with mode: 0644]
src/test/ui/pattern/issue-72574-2.stderr [new file with mode: 0644]
src/test/ui/pattern/issue-8351-1.rs [new file with mode: 0644]
src/test/ui/pattern/issue-8351-2.rs [new file with mode: 0644]
src/test/ui/privacy/pub-priv-dep/pub-priv1.rs
src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr
src/test/ui/proc-macro/ambiguous-builtin-attrs.rs
src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr
src/test/ui/proc-macro/auxiliary/api/parse.rs
src/test/ui/proc-macro/derive-helper-shadowing.stderr
src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr
src/test/ui/proc-macro/issue-41211.stderr
src/test/ui/proc-macro/meta-macro-hygiene.stdout
src/test/ui/proc-macro/nonterminal-token-hygiene.stdout
src/test/ui/proc-macro/proc-macro-attributes.stderr
src/test/ui/process/issue-14456.rs [new file with mode: 0644]
src/test/ui/process/issue-16272.rs [new file with mode: 0644]
src/test/ui/process/issue-20091.rs [new file with mode: 0644]
src/test/ui/process/signal-exit-status.rs [new file with mode: 0644]
src/test/ui/reachable/expr_cast.rs
src/test/ui/reachable/expr_cast.stderr
src/test/ui/regions/issue-21520.rs [new file with mode: 0644]
src/test/ui/regions/issue-26448-1.rs [new file with mode: 0644]
src/test/ui/regions/issue-26448-2.rs [new file with mode: 0644]
src/test/ui/regions/issue-26448-3.rs [new file with mode: 0644]
src/test/ui/required-lang-item.rs [deleted file]
src/test/ui/required-lang-item.stderr [deleted file]
src/test/ui/resolve/editions-crate-root-2015.rs [new file with mode: 0644]
src/test/ui/resolve/editions-crate-root-2015.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-12796.rs [new file with mode: 0644]
src/test/ui/resolve/issue-12796.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-23716.rs [new file with mode: 0644]
src/test/ui/resolve/issue-23716.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-3021-c.rs [new file with mode: 0644]
src/test/ui/resolve/issue-3021-c.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-3021.rs [new file with mode: 0644]
src/test/ui/resolve/issue-3021.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-31845.rs [new file with mode: 0644]
src/test/ui/resolve/issue-31845.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-5099.rs [new file with mode: 0644]
src/test/ui/resolve/issue-5099.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-90113.rs [new file with mode: 0644]
src/test/ui/resolve/issue-90113.stderr [new file with mode: 0644]
src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.rs [new file with mode: 0644]
src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
src/test/ui/rt-explody-panic-payloads.rs
src/test/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr
src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr
src/test/ui/rust-2018/uniform-paths/ambiguity-nested.stderr
src/test/ui/rust-2018/uniform-paths/ambiguity.stderr
src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr
src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr
src/test/ui/rust-2018/uniform-paths/issue-56596.stderr
src/test/ui/rust-2018/uniform-paths/macro-rules.stderr
src/test/ui/rust-2018/uniform-paths/redundant.rs
src/test/ui/rust-2021/future-prelude-collision-shadow.stderr
src/test/ui/rust-2021/prelude2021.rs
src/test/ui/rust-2021/reserved-prefixes-migration.fixed
src/test/ui/rust-2021/reserved-prefixes-migration.rs
src/test/ui/self/issue-61882-2.rs [new file with mode: 0644]
src/test/ui/self/issue-61882-2.stderr [new file with mode: 0644]
src/test/ui/self/issue-61882.rs [new file with mode: 0644]
src/test/ui/self/issue-61882.stderr [new file with mode: 0644]
src/test/ui/signal-exit-status.rs [deleted file]
src/test/ui/specialization/transmute-specialization.rs [new file with mode: 0644]
src/test/ui/specialization/transmute-specialization.stderr [new file with mode: 0644]
src/test/ui/stability-attribute/stability-attribute-trait-impl.rs
src/test/ui/stability-attribute/stability-attribute-trait-impl.stderr
src/test/ui/static/auxiliary/nested_item.rs [new file with mode: 0644]
src/test/ui/static/nested_item_main.rs [new file with mode: 0644]
src/test/ui/statics/issue-14227.mir.stderr [new file with mode: 0644]
src/test/ui/statics/issue-14227.rs [new file with mode: 0644]
src/test/ui/statics/issue-14227.thir.stderr [new file with mode: 0644]
src/test/ui/statics/uninhabited-static.rs
src/test/ui/statics/uninhabited-static.stderr
src/test/ui/structs-enums/issue-50731.rs [new file with mode: 0644]
src/test/ui/structs-enums/rec-align-u64.rs
src/test/ui/structured-compare.rs [deleted file]
src/test/ui/suggestions/boxed-variant-field.rs [new file with mode: 0644]
src/test/ui/suggestions/boxed-variant-field.stderr [new file with mode: 0644]
src/test/ui/suggestions/into-str.stderr
src/test/ui/suggestions/suggest-tryinto-edition-change.rs [new file with mode: 0644]
src/test/ui/suggestions/suggest-tryinto-edition-change.stderr [new file with mode: 0644]
src/test/ui/suggestions/undeclared-module-alloc.rs [new file with mode: 0644]
src/test/ui/suggestions/undeclared-module-alloc.stderr [new file with mode: 0644]
src/test/ui/supported-cast.rs [deleted file]
src/test/ui/svh/auxiliary/changing-crates-a1.rs [new file with mode: 0644]
src/test/ui/svh/auxiliary/changing-crates-a2.rs [new file with mode: 0644]
src/test/ui/svh/auxiliary/changing-crates-b.rs [new file with mode: 0644]
src/test/ui/svh/changing-crates.rs [new file with mode: 0644]
src/test/ui/svh/changing-crates.stderr [new file with mode: 0644]
src/test/ui/syntax-trait-polarity.rs [deleted file]
src/test/ui/syntax-trait-polarity.stderr [deleted file]
src/test/ui/synthetic-param.stderr
src/test/ui/terminate-in-initializer.rs [deleted file]
src/test/ui/terr-sorts.stderr
src/test/ui/test-attrs/issue-20823.rs [new file with mode: 0644]
src/test/ui/thin-lto-global-allocator.rs [deleted file]
src/test/ui/thinlto/all-crates.rs [deleted file]
src/test/ui/thinlto/auxiliary/dylib.rs [deleted file]
src/test/ui/thinlto/auxiliary/msvc-imp-present.rs [deleted file]
src/test/ui/thinlto/auxiliary/thin-lto-inlines-aux.rs [deleted file]
src/test/ui/thinlto/dylib-works.rs [deleted file]
src/test/ui/thinlto/msvc-imp-present.rs [deleted file]
src/test/ui/thinlto/thin-lto-inlines.rs [deleted file]
src/test/ui/thinlto/thin-lto-inlines2.rs [deleted file]
src/test/ui/thinlto/weak-works.rs [deleted file]
src/test/ui/threads-sendsync/issue-24313.rs [new file with mode: 0644]
src/test/ui/threads-sendsync/issue-4448.rs [new file with mode: 0644]
src/test/ui/threads-sendsync/issue-8827.rs [new file with mode: 0644]
src/test/ui/threads-sendsync/issue-9396.rs [new file with mode: 0644]
src/test/ui/threads-sendsync/trivial-message.rs [new file with mode: 0644]
src/test/ui/threads-sendsync/yield2.rs [new file with mode: 0644]
src/test/ui/trace_macros-format.rs [deleted file]
src/test/ui/trace_macros-format.stderr [deleted file]
src/test/ui/trait-bounds/issue-75961.rs [new file with mode: 0644]
src/test/ui/traits/issue-24010.rs [new file with mode: 0644]
src/test/ui/traits/issue-38604.rs [new file with mode: 0644]
src/test/ui/traits/issue-38604.stderr [new file with mode: 0644]
src/test/ui/traits/issue-3973.rs [new file with mode: 0644]
src/test/ui/traits/issue-3973.stderr [new file with mode: 0644]
src/test/ui/traits/issue-59029-1.rs [new file with mode: 0644]
src/test/ui/traits/issue-59029-1.stderr [new file with mode: 0644]
src/test/ui/traits/issue-71136.stderr
src/test/ui/traits/issue-72455.rs [new file with mode: 0644]
src/test/ui/traits/issue-90195-2.rs [new file with mode: 0644]
src/test/ui/traits/issue-90195.rs [new file with mode: 0644]
src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr
src/test/ui/traits/object-does-not-impl-trait.rs [new file with mode: 0644]
src/test/ui/traits/object-does-not-impl-trait.stderr [new file with mode: 0644]
src/test/ui/traits/syntax-trait-polarity.rs [new file with mode: 0644]
src/test/ui/traits/syntax-trait-polarity.stderr [new file with mode: 0644]
src/test/ui/transmute-specialization.rs [deleted file]
src/test/ui/transmute-specialization.stderr [deleted file]
src/test/ui/trivial-message.rs [deleted file]
src/test/ui/try-block/issue-45124.rs [new file with mode: 0644]
src/test/ui/try-macro-suggestion.rs [deleted file]
src/test/ui/try-macro-suggestion.stderr [deleted file]
src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs
src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr
src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr
src/test/ui/type-alias-impl-trait/issue-60662.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-60662.stdout [new file with mode: 0644]
src/test/ui/type-inference/issue-30225.rs [new file with mode: 0644]
src/test/ui/type-inference/issue-30225.stderr [new file with mode: 0644]
src/test/ui/typeck/auxiliary/xcrate-issue-43189-a.rs [new file with mode: 0644]
src/test/ui/typeck/auxiliary/xcrate-issue-43189-b.rs [new file with mode: 0644]
src/test/ui/typeck/auxiliary/xcrate-issue-46112-rexport-core.rs [new file with mode: 0644]
src/test/ui/typeck/auxiliary/xcrate-issue-61711-b.rs [new file with mode: 0644]
src/test/ui/typeck/issue-43189.rs [new file with mode: 0644]
src/test/ui/typeck/issue-43189.stderr [new file with mode: 0644]
src/test/ui/typeck/issue-46112.rs [new file with mode: 0644]
src/test/ui/typeck/issue-46112.stderr [new file with mode: 0644]
src/test/ui/typeck/issue-61711-once-caused-rustc-inf-loop.rs [new file with mode: 0644]
src/test/ui/typeck/issue-89806.rs [new file with mode: 0644]
src/test/ui/typeck/issue-89806.stderr [new file with mode: 0644]
src/test/ui/typeck/issue-90101.rs [new file with mode: 0644]
src/test/ui/typeck/issue-90101.stderr [new file with mode: 0644]
src/test/ui/typeck/issue-90164.rs [new file with mode: 0644]
src/test/ui/typeck/issue-90164.stderr [new file with mode: 0644]
src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.rs [new file with mode: 0644]
src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr [new file with mode: 0644]
src/test/ui/typeck/typeck-unsafe-always-share.stderr
src/test/ui/unary-minus-suffix-inference.rs [deleted file]
src/test/ui/unboxed-closures/issue-18652.rs [new file with mode: 0644]
src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr
src/test/ui/uniform-paths/basic-nested.rs
src/test/ui/uniform-paths/basic.rs
src/test/ui/uniform-paths/macros-nested.rs
src/test/ui/uniform-paths/macros.rs
src/test/ui/unnecessary-extern-crate.rs [deleted file]
src/test/ui/unnecessary-extern-crate.stderr [deleted file]
src/test/ui/unrestricted-attribute-tokens.rs [deleted file]
src/test/ui/unsized-locals/unsized-exprs.stderr
src/test/ui/unsized/issue-30355.rs [new file with mode: 0644]
src/test/ui/unsized/issue-30355.stderr [new file with mode: 0644]
src/test/ui/unsized/unchanged-param.rs
src/test/ui/unused-crate-deps/extern-loc-missing-loc.rs
src/test/ui/use/use-nested-groups-unused-imports.rs
src/test/ui/use/use-nested-groups-unused-imports.stderr
src/test/ui/warn-ctypes-inhibit.rs [deleted file]
src/test/ui/x86stdcall.rs
src/test/ui/yield2.rs [deleted file]
src/tools/bump-stage0/src/main.rs
src/tools/cargo
src/tools/clippy/.cargo/config [deleted file]
src/tools/clippy/.cargo/config.toml [new file with mode: 0644]
src/tools/clippy/.github/deploy.sh
src/tools/clippy/CHANGELOG.md
src/tools/clippy/CONTRIBUTING.md
src/tools/clippy/Cargo.toml
src/tools/clippy/clippy_dev/src/new_lint.rs
src/tools/clippy/clippy_lints/Cargo.toml
src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
src/tools/clippy/clippy_lints/src/casts/mod.rs
src/tools/clippy/clippy_lints/src/deprecated_lints.rs
src/tools/clippy/clippy_lints/src/dereference.rs
src/tools/clippy/clippy_lints/src/doc.rs
src/tools/clippy/clippy_lints/src/entry.rs
src/tools/clippy/clippy_lints/src/enum_variants.rs
src/tools/clippy/clippy_lints/src/eta_reduction.rs
src/tools/clippy/clippy_lints/src/excessive_bools.rs
src/tools/clippy/clippy_lints/src/format.rs
src/tools/clippy/clippy_lints/src/future_not_send.rs
src/tools/clippy/clippy_lints/src/if_not_else.rs
src/tools/clippy/clippy_lints/src/if_then_panic.rs [deleted file]
src/tools/clippy/clippy_lints/src/int_plus_one.rs
src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs
src/tools/clippy/clippy_lints/src/lib.register_all.rs
src/tools/clippy/clippy_lints/src/lib.register_correctness.rs
src/tools/clippy/clippy_lints/src/lib.register_lints.rs
src/tools/clippy/clippy_lints/src/lib.register_nursery.rs
src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs
src/tools/clippy/clippy_lints/src/lib.register_restriction.rs
src/tools/clippy/clippy_lints/src/lib.register_style.rs
src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs
src/tools/clippy/clippy_lints/src/lib.rs
src/tools/clippy/clippy_lints/src/lifetimes.rs
src/tools/clippy/clippy_lints/src/loops/utils.rs
src/tools/clippy/clippy_lints/src/manual_assert.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/match_str_case_mismatch.rs
src/tools/clippy/clippy_lints/src/matches.rs
src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
src/tools/clippy/clippy_lints/src/misc_early/double_neg.rs
src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/misc_early/mod.rs
src/tools/clippy/clippy_lints/src/misc_early/unseparated_literal_suffix.rs [deleted file]
src/tools/clippy/clippy_lints/src/module_style.rs
src/tools/clippy/clippy_lints/src/needless_borrow.rs
src/tools/clippy/clippy_lints/src/non_expressive_names.rs
src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
src/tools/clippy/clippy_lints/src/option_if_let_else.rs
src/tools/clippy/clippy_lints/src/ptr.rs
src/tools/clippy/clippy_lints/src/question_mark.rs
src/tools/clippy/clippy_lints/src/strings.rs
src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
src/tools/clippy/clippy_lints/src/unicode.rs
src/tools/clippy/clippy_lints/src/unit_hash.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/unwrap_in_result.rs
src/tools/clippy/clippy_lints/src/utils/conf.rs
src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
src/tools/clippy/clippy_lints/src/write.rs
src/tools/clippy/clippy_utils/src/ast_utils.rs
src/tools/clippy/clippy_utils/src/camel_case.rs [deleted file]
src/tools/clippy/clippy_utils/src/consts.rs
src/tools/clippy/clippy_utils/src/diagnostics.rs
src/tools/clippy/clippy_utils/src/higher.rs
src/tools/clippy/clippy_utils/src/lib.rs
src/tools/clippy/clippy_utils/src/str_utils.rs [new file with mode: 0644]
src/tools/clippy/doc/adding_lints.md
src/tools/clippy/rust-toolchain
src/tools/clippy/tests/compile-test.rs
src/tools/clippy/tests/missing-test-files.rs
src/tools/clippy/tests/ui-toml/functions_maxlines/test.rs
src/tools/clippy/tests/ui-toml/functions_maxlines/test.stderr
src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.rs
src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.stderr
src/tools/clippy/tests/ui/assertions_on_constants.rs
src/tools/clippy/tests/ui/assertions_on_constants.stderr
src/tools/clippy/tests/ui/async_yields_async.fixed
src/tools/clippy/tests/ui/async_yields_async.rs
src/tools/clippy/tests/ui/async_yields_async.stderr
src/tools/clippy/tests/ui/await_holding_lock.rs
src/tools/clippy/tests/ui/await_holding_lock.stderr
src/tools/clippy/tests/ui/await_holding_refcell_ref.rs
src/tools/clippy/tests/ui/await_holding_refcell_ref.stderr
src/tools/clippy/tests/ui/cast.rs
src/tools/clippy/tests/ui/cast.stderr
src/tools/clippy/tests/ui/crashes/auxiliary/ice-7868-aux.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/crashes/ice-3969.rs
src/tools/clippy/tests/ui/crashes/ice-3969.stderr
src/tools/clippy/tests/ui/crashes/ice-5207.rs
src/tools/clippy/tests/ui/crashes/ice-6252.rs
src/tools/clippy/tests/ui/crashes/ice-6252.stderr
src/tools/clippy/tests/ui/crashes/ice-7231.rs
src/tools/clippy/tests/ui/crashes/ice-7868.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/crashes/ice-7868.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/crashes/ice-7869.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/crashes/ice-7869.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/crashes/used_underscore_binding_macro.rs
src/tools/clippy/tests/ui/debug_assert_with_mut_call.rs
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/diverging_sub_expression.rs
src/tools/clippy/tests/ui/diverging_sub_expression.stderr
src/tools/clippy/tests/ui/doc/doc-fixable.fixed [new file with mode: 0644]
src/tools/clippy/tests/ui/doc/doc-fixable.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/doc/doc-fixable.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/doc/doc.rs [deleted file]
src/tools/clippy/tests/ui/doc/doc.stderr [deleted file]
src/tools/clippy/tests/ui/doc/issue_1832.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/doc/issue_902.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr
src/tools/clippy/tests/ui/doc_errors.rs
src/tools/clippy/tests/ui/doc_errors.stderr
src/tools/clippy/tests/ui/doc_unsafe.rs
src/tools/clippy/tests/ui/double_neg.rs
src/tools/clippy/tests/ui/double_neg.stderr
src/tools/clippy/tests/ui/enum_variants.stderr
src/tools/clippy/tests/ui/eval_order_dependence.rs
src/tools/clippy/tests/ui/eval_order_dependence.stderr
src/tools/clippy/tests/ui/fallible_impl_from.rs
src/tools/clippy/tests/ui/fallible_impl_from.stderr
src/tools/clippy/tests/ui/fn_params_excessive_bools.rs
src/tools/clippy/tests/ui/fn_params_excessive_bools.stderr
src/tools/clippy/tests/ui/format.fixed
src/tools/clippy/tests/ui/format.rs
src/tools/clippy/tests/ui/format.stderr
src/tools/clippy/tests/ui/format_args.fixed
src/tools/clippy/tests/ui/format_args.rs
src/tools/clippy/tests/ui/format_args.stderr
src/tools/clippy/tests/ui/format_args_unfixable.rs
src/tools/clippy/tests/ui/formatting.rs
src/tools/clippy/tests/ui/formatting.stderr
src/tools/clippy/tests/ui/future_not_send.rs
src/tools/clippy/tests/ui/future_not_send.stderr
src/tools/clippy/tests/ui/if_not_else.rs
src/tools/clippy/tests/ui/if_not_else.stderr
src/tools/clippy/tests/ui/if_then_panic.fixed [deleted file]
src/tools/clippy/tests/ui/if_then_panic.rs [deleted file]
src/tools/clippy/tests/ui/if_then_panic.stderr [deleted file]
src/tools/clippy/tests/ui/implicit_hasher.rs
src/tools/clippy/tests/ui/implicit_hasher.stderr
src/tools/clippy/tests/ui/implicit_return.fixed
src/tools/clippy/tests/ui/implicit_return.rs
src/tools/clippy/tests/ui/implicit_return.stderr
src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed
src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs
src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr
src/tools/clippy/tests/ui/issue-7447.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/issue_4266.rs
src/tools/clippy/tests/ui/issue_4266.stderr
src/tools/clippy/tests/ui/iter_count.fixed
src/tools/clippy/tests/ui/iter_count.rs
src/tools/clippy/tests/ui/iter_count.stderr
src/tools/clippy/tests/ui/len_without_is_empty.rs
src/tools/clippy/tests/ui/len_without_is_empty.stderr
src/tools/clippy/tests/ui/literals.rs
src/tools/clippy/tests/ui/literals.stderr
src/tools/clippy/tests/ui/macro_use_imports.fixed
src/tools/clippy/tests/ui/macro_use_imports.rs
src/tools/clippy/tests/ui/macro_use_imports.stderr
src/tools/clippy/tests/ui/manual_assert.edition2018.fixed [new file with mode: 0644]
src/tools/clippy/tests/ui/manual_assert.edition2018.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/manual_assert.edition2021.fixed [new file with mode: 0644]
src/tools/clippy/tests/ui/manual_assert.edition2021.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/manual_assert.fixed [new file with mode: 0644]
src/tools/clippy/tests/ui/manual_assert.rs [new file with mode: 0644]
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_map_option.fixed
src/tools/clippy/tests/ui/manual_map_option.rs
src/tools/clippy/tests/ui/manual_map_option.stderr
src/tools/clippy/tests/ui/many_single_char_names.rs
src/tools/clippy/tests/ui/many_single_char_names.stderr
src/tools/clippy/tests/ui/match_overlapping_arm.rs
src/tools/clippy/tests/ui/match_ref_pats.rs
src/tools/clippy/tests/ui/match_str_case_mismatch.rs
src/tools/clippy/tests/ui/match_str_case_mismatch.stderr
src/tools/clippy/tests/ui/match_wild_err_arm.edition2018.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/match_wild_err_arm.edition2021.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/match_wild_err_arm.rs
src/tools/clippy/tests/ui/match_wild_err_arm.stderr [deleted file]
src/tools/clippy/tests/ui/methods.rs
src/tools/clippy/tests/ui/methods.stderr
src/tools/clippy/tests/ui/missing-doc.rs
src/tools/clippy/tests/ui/missing-doc.stderr
src/tools/clippy/tests/ui/missing_panics_doc.rs
src/tools/clippy/tests/ui/missing_panics_doc.stderr
src/tools/clippy/tests/ui/mistyped_literal_suffix.fixed
src/tools/clippy/tests/ui/mistyped_literal_suffix.rs
src/tools/clippy/tests/ui/mistyped_literal_suffix.stderr
src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs
src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.stderr
src/tools/clippy/tests/ui/needless_borrow_pat.rs
src/tools/clippy/tests/ui/needless_borrow_pat.stderr
src/tools/clippy/tests/ui/needless_continue.rs
src/tools/clippy/tests/ui/needless_continue.stderr
src/tools/clippy/tests/ui/needless_lifetimes.rs
src/tools/clippy/tests/ui/needless_lifetimes.stderr
src/tools/clippy/tests/ui/needless_return.fixed
src/tools/clippy/tests/ui/needless_return.rs
src/tools/clippy/tests/ui/needless_return.stderr
src/tools/clippy/tests/ui/non_expressive_names.rs
src/tools/clippy/tests/ui/non_expressive_names.stderr
src/tools/clippy/tests/ui/option_if_let_else.fixed
src/tools/clippy/tests/ui/option_if_let_else.rs
src/tools/clippy/tests/ui/option_if_let_else.stderr
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/ptr_arg.rs
src/tools/clippy/tests/ui/ptr_arg.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/redundant_clone.fixed
src/tools/clippy/tests/ui/redundant_clone.stderr
src/tools/clippy/tests/ui/redundant_closure_call_early.rs
src/tools/clippy/tests/ui/redundant_else.rs
src/tools/clippy/tests/ui/ref_binding_to_reference.rs
src/tools/clippy/tests/ui/ref_binding_to_reference.stderr
src/tools/clippy/tests/ui/rename.fixed
src/tools/clippy/tests/ui/rename.rs
src/tools/clippy/tests/ui/rename.stderr
src/tools/clippy/tests/ui/should_impl_trait/corner_cases.rs
src/tools/clippy/tests/ui/should_impl_trait/method_list_1.rs
src/tools/clippy/tests/ui/should_impl_trait/method_list_1.stderr
src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs
src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr
src/tools/clippy/tests/ui/similar_names.rs
src/tools/clippy/tests/ui/similar_names.stderr
src/tools/clippy/tests/ui/single_component_path_imports.fixed
src/tools/clippy/tests/ui/single_component_path_imports.rs
src/tools/clippy/tests/ui/single_component_path_imports.stderr
src/tools/clippy/tests/ui/single_component_path_imports_macro.fixed
src/tools/clippy/tests/ui/single_component_path_imports_macro.rs
src/tools/clippy/tests/ui/single_component_path_imports_macro.stderr
src/tools/clippy/tests/ui/single_component_path_imports_nested_first.rs
src/tools/clippy/tests/ui/single_component_path_imports_nested_first.stderr
src/tools/clippy/tests/ui/single_component_path_imports_self_after.rs
src/tools/clippy/tests/ui/single_component_path_imports_self_before.rs
src/tools/clippy/tests/ui/string_slice.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/string_slice.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/suspicious_else_formatting.rs
src/tools/clippy/tests/ui/suspicious_else_formatting.stderr
src/tools/clippy/tests/ui/suspicious_operation_groupings.rs
src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr
src/tools/clippy/tests/ui/unit_hash.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/unit_hash.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/unused_async.rs
src/tools/clippy/tests/ui/unused_async.stderr
src/tools/clippy/tests/ui/use_self.fixed
src/tools/clippy/tests/ui/use_self.rs
src/tools/clippy/tests/ui/use_self.stderr
src/tools/clippy/tests/ui/used_underscore_binding.rs
src/tools/clippy/tests/ui/used_underscore_binding.stderr
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/clippy/tests/ui/wrong_self_convention.rs
src/tools/clippy/tests/ui/wrong_self_convention.stderr
src/tools/clippy/tests/ui/wrong_self_convention2.rs
src/tools/clippy/tests/ui/wrong_self_convention2.stderr
src/tools/clippy/tests/ui/wrong_self_conventions_mut.rs
src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr
src/tools/compiletest/src/header.rs
src/tools/compiletest/src/header/tests.rs
src/tools/compiletest/src/runtest.rs
src/tools/compiletest/src/util.rs
src/tools/linkchecker/main.rs
src/tools/miri
src/tools/rust-analyzer
src/tools/rustdoc-js/tester.js
src/tools/rustfmt/.github/workflows/rustdoc_check.yml [new file with mode: 0644]
src/tools/rustfmt/Configurations.md
src/tools/rustfmt/Contributing.md
src/tools/rustfmt/README.md
src/tools/rustfmt/appveyor.yml [deleted file]
src/tools/rustfmt/intellij.md
src/tools/rustfmt/legacy-rustfmt.toml [deleted file]
src/tools/rustfmt/rust-toolchain
src/tools/rustfmt/src/attr.rs
src/tools/rustfmt/src/attr/doc_comment.rs
src/tools/rustfmt/src/bin/main.rs
src/tools/rustfmt/src/cargo-fmt/main.rs
src/tools/rustfmt/src/chains.rs
src/tools/rustfmt/src/comment.rs
src/tools/rustfmt/src/config/options.rs
src/tools/rustfmt/src/emitter/checkstyle.rs
src/tools/rustfmt/src/emitter/diff.rs
src/tools/rustfmt/src/expr.rs
src/tools/rustfmt/src/format-diff/main.rs
src/tools/rustfmt/src/formatting.rs
src/tools/rustfmt/src/git-rustfmt/main.rs
src/tools/rustfmt/src/imports.rs
src/tools/rustfmt/src/items.rs
src/tools/rustfmt/src/lib.rs
src/tools/rustfmt/src/lists.rs
src/tools/rustfmt/src/macros.rs
src/tools/rustfmt/src/matches.rs
src/tools/rustfmt/src/modules.rs
src/tools/rustfmt/src/overflow.rs
src/tools/rustfmt/src/pairs.rs
src/tools/rustfmt/src/patterns.rs
src/tools/rustfmt/src/reorder.rs
src/tools/rustfmt/src/syntux/parser.rs
src/tools/rustfmt/src/syntux/session.rs
src/tools/rustfmt/src/test/mod.rs
src/tools/rustfmt/src/test/mod_resolver.rs
src/tools/rustfmt/src/types.rs
src/tools/rustfmt/src/utils.rs
src/tools/rustfmt/src/visitor.rs
src/tools/rustfmt/tests/mod-resolver/issue-5063/foo.rs [new file with mode: 0644]
src/tools/rustfmt/tests/mod-resolver/issue-5063/foo/bar/baz.rs [new file with mode: 0644]
src/tools/rustfmt/tests/mod-resolver/issue-5063/main.rs [new file with mode: 0644]
src/tools/rustfmt/tests/source/configs/group_imports/One-merge_imports.rs [new file with mode: 0644]
src/tools/rustfmt/tests/source/configs/group_imports/One-nested.rs [new file with mode: 0644]
src/tools/rustfmt/tests/source/configs/group_imports/One-no_reorder.rs [new file with mode: 0644]
src/tools/rustfmt/tests/source/configs/group_imports/One.rs [new file with mode: 0644]
src/tools/rustfmt/tests/source/empty-item-single-line-false.rs [new file with mode: 0644]
src/tools/rustfmt/tests/source/item-brace-style-always-next-line.rs
src/tools/rustfmt/tests/target/configs/group_imports/One-merge_imports.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/configs/group_imports/One-nested.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/configs/group_imports/One-no_reorder.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/configs/group_imports/One.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/empty-item-single-line-false.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5012/trailing_comma_always.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5012/trailing_comma_never.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5033/minimum_example.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5033/nested_modules.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue_4850.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/item-brace-style-always-next-line.rs
src/tools/tidy/src/edition.rs
src/tools/tidy/src/features.rs
src/tools/tidy/src/ui_tests.rs
triagebot.toml

index 580120b25a251584df6bc22ebbb2075dddcc8c9a..407db519d51dc0631442037d06819c0df6937fac 100644 (file)
@@ -532,16 +532,9 @@ jobs:
     strategy:
       matrix:
         include:
-          - name: dist-x86_64-apple
-            env:
-              SCRIPT: "./x.py dist --exclude src/doc --exclude extended && ./x.py dist --target=x86_64-apple-darwin src/doc && ./x.py dist extended"
-              RUST_CONFIGURE_ARGS: "--host=x86_64-apple-darwin --target=x86_64-apple-darwin,aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.7
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              DIST_REQUIRE_ALL_TOOLS: 1
-            os: macos-latest
+          - name: dist-x86_64-linux
+            os: ubuntu-latest-xl
+            env: {}
     timeout-minutes: 600
     runs-on: "${{ matrix.os }}"
     steps:
index 3b3e7334b759879790c962f2f977f4f3d5633db1..a160f2f4fbfecc2d97e69bc408987dacbb9a2157 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -111,6 +111,7 @@ Graydon Hoare <graydon@pobox.com> Graydon Hoare <graydon@mozilla.com>
 Guillaume Gomez <guillaume1.gomez@gmail.com>
 Guillaume Gomez <guillaume1.gomez@gmail.com> ggomez <ggomez@ggo.ifr.lan>
 Guillaume Gomez <guillaume1.gomez@gmail.com> Guillaume Gomez <ggomez@ggo.ifr.lan>
+Guillaume Gomez <guillaume1.gomez@gmail.com> Guillaume Gomez <guillaume.gomez@huawei.com>
 Hanna Kruppe <hanna.kruppe@gmail.com> <robin.kruppe@gmail.com>
 Heather <heather@cynede.net> <Cynede@Gentoo.org>
 Heather <heather@cynede.net> <Heather@cynede.net>
index 41275accbe9625ef764e089e548eb4bf02a1276a..7cd07e3847282b9d9405a5244414c2f49283adc8 100644 (file)
@@ -276,7 +276,7 @@ dependencies = [
 
 [[package]]
 name = "cargo"
-version = "0.58.0"
+version = "0.59.0"
 dependencies = [
  "anyhow",
  "atty",
@@ -576,7 +576,7 @@ dependencies = [
 name = "clippy"
 version = "0.1.58"
 dependencies = [
- "cargo_metadata 0.12.0",
+ "cargo_metadata 0.14.0",
  "clippy_lints",
  "clippy_utils",
  "compiletest_rs",
@@ -588,7 +588,7 @@ dependencies = [
  "regex",
  "rustc-workspace-hack",
  "rustc_tools_util 0.2.0",
- "semver 0.11.0",
+ "semver 1.0.3",
  "serde",
  "syn",
  "tempfile",
@@ -613,7 +613,7 @@ dependencies = [
 name = "clippy_lints"
 version = "0.1.58"
 dependencies = [
- "cargo_metadata 0.12.0",
+ "cargo_metadata 0.14.0",
  "clippy_utils",
  "if_chain",
  "itertools 0.10.1",
@@ -621,7 +621,7 @@ dependencies = [
  "quine-mc_cluskey",
  "regex-syntax",
  "rustc-semver",
- "semver 0.11.0",
+ "semver 1.0.3",
  "serde",
  "serde_json",
  "toml",
@@ -710,9 +710,9 @@ dependencies = [
 
 [[package]]
 name = "compiletest_rs"
-version = "0.7.0"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64698e5e2435db061a85e6320af12c30c5fd88eb84b35d2c1e03ce4f143255ca"
+checksum = "29843cb8d351febf86557681d049d1e1652b81a086a190fa1173c07fd17fbf83"
 dependencies = [
  "diff",
  "filetime",
@@ -888,9 +888,9 @@ dependencies = [
 
 [[package]]
 name = "curl"
-version = "0.4.39"
+version = "0.4.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aaa3b8db7f3341ddef15786d250106334d4a6c4b0ae4a46cd77082777d9849b9"
+checksum = "877cc2f9b8367e32b6dabb9d581557e651cb3aa693a37f8679091bbf42687d5d"
 dependencies = [
  "curl-sys",
  "libc",
@@ -903,9 +903,9 @@ dependencies = [
 
 [[package]]
 name = "curl-sys"
-version = "0.4.49+curl-7.79.1"
+version = "0.4.50+curl-7.79.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0f44960aea24a786a46907b8824ebc0e66ca06bf4e4978408c7499620343483"
+checksum = "4856b76919dd599f31236bb18db5f5bd36e2ce131e64f857ca5c259665b76171"
 dependencies = [
  "cc",
  "libc",
@@ -1900,9 +1900,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
 
 [[package]]
 name = "libc"
-version = "0.2.103"
+version = "0.2.106"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
+checksum = "a60553f9a9e039a333b4e9b20573b9e9b9c0bb3a11e201ccc48ef4283456d673"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -2349,9 +2349,9 @@ dependencies = [
 
 [[package]]
 name = "odht"
-version = "0.3.0"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2504d29fda40b3f2f9ef525392435ab660e407c188196cb664b116ebcca0142"
+checksum = "5a518809ac14b25b569624d0268eba1e88498f71615893dca57982bed7621abb"
 dependencies = [
  "cfg-if 1.0.0",
 ]
@@ -4259,6 +4259,7 @@ dependencies = [
  "rustc_span",
  "tracing",
  "unicode-normalization",
+ "unicode-width",
 ]
 
 [[package]]
@@ -4615,8 +4616,8 @@ dependencies = [
  "itertools 0.9.0",
  "minifier",
  "pulldown-cmark 0.8.0",
+ "rayon",
  "regex",
- "rustc-rayon",
  "rustdoc-json-types",
  "serde",
  "serde_json",
index f1584224656ae0f29e95184455ab424d32dd0ed6..a38ab7cabf468c39aace386fb49321579be2dc22 100644 (file)
@@ -1,3 +1,11 @@
+Version 1.56.1 (2021-11-01)
+===========================
+
+- New lints to detect the presence of bidirectional-override Unicode
+  codepoints in the compiled source code ([CVE-2021-42574])
+
+[CVE-2021-42574]: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-42574
+
 Version 1.56.0 (2021-10-21)
 ========================
 
index dd407dba1f4cca03b3e19bce687b40e49a3ead68..b2b90fed033b3f1192fc3e75f065a957d14b72e6 100644 (file)
@@ -1,6 +1,5 @@
 The `rustc_ast` crate contains those things concerned purely with syntax
-– that is, the AST ("abstract syntax tree"), parser, pretty-printer,
-lexer, macro expander, and utilities for traversing ASTs.
+– that is, the AST ("abstract syntax tree"), along with some definitions for tokens and token streams, data structures/traits for mutating ASTs, and shared definitions for other AST-related parts of the compiler (like the lexer and macro-expansion).
 
 For more information about how these things work in rustc, see the
 rustc dev guide:
index e2424e7d7ad9064f38563795d6ce59f54cba963f..f9e19d30fcc7e5456ca3ab086d145ed1ab6d3fe0 100644 (file)
@@ -2645,34 +2645,42 @@ fn default() -> FnHeader {
 }
 
 #[derive(Clone, Encodable, Decodable, Debug)]
-pub struct TraitKind(
-    pub IsAuto,
-    pub Unsafe,
-    pub Generics,
-    pub GenericBounds,
-    pub Vec<P<AssocItem>>,
-);
+pub struct Trait {
+    pub unsafety: Unsafe,
+    pub is_auto: IsAuto,
+    pub generics: Generics,
+    pub bounds: GenericBounds,
+    pub items: Vec<P<AssocItem>>,
+}
 
 #[derive(Clone, Encodable, Decodable, Debug)]
-pub struct TyAliasKind(pub Defaultness, pub Generics, pub GenericBounds, pub Option<P<Ty>>);
+pub struct TyAlias {
+    pub defaultness: Defaultness,
+    pub generics: Generics,
+    pub bounds: GenericBounds,
+    pub ty: Option<P<Ty>>,
+}
 
 #[derive(Clone, Encodable, Decodable, Debug)]
-pub struct ImplKind {
-    pub unsafety: Unsafe,
-    pub polarity: ImplPolarity,
+pub struct Impl {
     pub defaultness: Defaultness,
-    pub constness: Const,
+    pub unsafety: Unsafe,
     pub generics: Generics,
-
+    pub constness: Const,
+    pub polarity: ImplPolarity,
     /// The trait being implemented, if any.
     pub of_trait: Option<TraitRef>,
-
     pub self_ty: P<Ty>,
     pub items: Vec<P<AssocItem>>,
 }
 
 #[derive(Clone, Encodable, Decodable, Debug)]
-pub struct FnKind(pub Defaultness, pub FnSig, pub Generics, pub Option<P<Block>>);
+pub struct Fn {
+    pub defaultness: Defaultness,
+    pub generics: Generics,
+    pub sig: FnSig,
+    pub body: Option<P<Block>>,
+}
 
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub enum ItemKind {
@@ -2695,7 +2703,7 @@ pub enum ItemKind {
     /// A function declaration (`fn`).
     ///
     /// E.g., `fn foo(bar: usize) -> usize { .. }`.
-    Fn(Box<FnKind>),
+    Fn(Box<Fn>),
     /// A module declaration (`mod`).
     ///
     /// E.g., `mod foo;` or `mod foo { .. }`.
@@ -2711,7 +2719,7 @@ pub enum ItemKind {
     /// A type alias (`type`).
     ///
     /// E.g., `type Foo = Bar<u8>;`.
-    TyAlias(Box<TyAliasKind>),
+    TyAlias(Box<TyAlias>),
     /// An enum definition (`enum`).
     ///
     /// E.g., `enum Foo<A, B> { C<A>, D<B> }`.
@@ -2727,7 +2735,7 @@ pub enum ItemKind {
     /// A trait declaration (`trait`).
     ///
     /// E.g., `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}`.
-    Trait(Box<TraitKind>),
+    Trait(Box<Trait>),
     /// Trait alias
     ///
     /// E.g., `trait Foo = Bar + Quux;`.
@@ -2735,7 +2743,7 @@ pub enum ItemKind {
     /// An implementation.
     ///
     /// E.g., `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`.
-    Impl(Box<ImplKind>),
+    Impl(Box<Impl>),
     /// A macro invocation.
     ///
     /// E.g., `foo!(..)`.
@@ -2782,14 +2790,14 @@ pub fn descr(&self) -> &str {
 
     pub fn generics(&self) -> Option<&Generics> {
         match self {
-            Self::Fn(box FnKind(_, _, generics, _))
-            | Self::TyAlias(box TyAliasKind(_, generics, ..))
+            Self::Fn(box Fn { generics, .. })
+            | Self::TyAlias(box TyAlias { generics, .. })
             | Self::Enum(_, generics)
             | Self::Struct(_, generics)
             | Self::Union(_, generics)
-            | Self::Trait(box TraitKind(_, _, generics, ..))
+            | Self::Trait(box Trait { generics, .. })
             | Self::TraitAlias(generics, _)
-            | Self::Impl(box ImplKind { generics, .. }) => Some(generics),
+            | Self::Impl(box Impl { generics, .. }) => Some(generics),
             _ => None,
         }
     }
@@ -2812,9 +2820,9 @@ pub enum AssocItemKind {
     /// If `def` is parsed, then the constant is provided, and otherwise required.
     Const(Defaultness, P<Ty>, Option<P<Expr>>),
     /// An associated function.
-    Fn(Box<FnKind>),
+    Fn(Box<Fn>),
     /// An associated type.
-    TyAlias(Box<TyAliasKind>),
+    TyAlias(Box<TyAlias>),
     /// A macro expanding to associated items.
     MacCall(MacCall),
 }
@@ -2825,9 +2833,9 @@ pub enum AssocItemKind {
 impl AssocItemKind {
     pub fn defaultness(&self) -> Defaultness {
         match *self {
-            Self::Const(def, ..)
-            | Self::Fn(box FnKind(def, ..))
-            | Self::TyAlias(box TyAliasKind(def, ..)) => def,
+            Self::Const(defaultness, ..)
+            | Self::Fn(box Fn { defaultness, .. })
+            | Self::TyAlias(box TyAlias { defaultness, .. }) => defaultness,
             Self::MacCall(..) => Defaultness::Final,
         }
     }
@@ -2864,9 +2872,9 @@ pub enum ForeignItemKind {
     /// A foreign static item (`static FOO: u8`).
     Static(P<Ty>, Mutability, Option<P<Expr>>),
     /// An foreign function.
-    Fn(Box<FnKind>),
+    Fn(Box<Fn>),
     /// An foreign type.
-    TyAlias(Box<TyAliasKind>),
+    TyAlias(Box<TyAlias>),
     /// A macro expanding to foreign items.
     MacCall(MacCall),
 }
index e3c610585d978e32c8ef8071aa0ffda993431310..b9db2a7e089de1416d8667ffce0eb08322b50969 100644 (file)
@@ -1,4 +1,4 @@
-//! The Rust parser and macro expander.
+//! The Rust Abstract Syntax Tree (AST).
 //!
 //! # Note
 //!
@@ -16,6 +16,7 @@
 #![feature(nll)]
 #![feature(min_specialization)]
 #![recursion_limit = "256"]
+#![feature(slice_internals)]
 
 #[macro_use]
 extern crate rustc_macros;
@@ -25,6 +26,7 @@ pub mod util {
     pub mod comments;
     pub mod literal;
     pub mod parser;
+    pub mod unicode;
 }
 
 pub mod ast;
index 74def2bab1bfa2a58319e728f6765a2c9dc0f081..fc5cc963992579b76514eeddb92d9fb0a851b3b3 100644 (file)
@@ -459,7 +459,8 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
             vis.visit_mt(mt);
         }
         TyKind::BareFn(bft) => {
-            let BareFnTy { unsafety: _, ext: _, generic_params, decl } = bft.deref_mut();
+            let BareFnTy { unsafety, ext: _, generic_params, decl } = bft.deref_mut();
+            visit_unsafety(unsafety, vis);
             generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
             vis.visit_fn_decl(decl);
         }
@@ -488,7 +489,8 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
 }
 
 pub fn noop_visit_foreign_mod<T: MutVisitor>(foreign_mod: &mut ForeignMod, vis: &mut T) {
-    let ForeignMod { unsafety: _, abi: _, items } = foreign_mod;
+    let ForeignMod { unsafety, abi: _, items } = foreign_mod;
+    visit_unsafety(unsafety, vis);
     items.flat_map_in_place(|item| vis.flat_map_foreign_item(item));
 }
 
@@ -788,6 +790,38 @@ pub fn visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut
     }
 }
 
+// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
+pub fn visit_defaultness<T: MutVisitor>(defaultness: &mut Defaultness, vis: &mut T) {
+    match defaultness {
+        Defaultness::Default(span) => vis.visit_span(span),
+        Defaultness::Final => {}
+    }
+}
+
+// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
+pub fn visit_unsafety<T: MutVisitor>(unsafety: &mut Unsafe, vis: &mut T) {
+    match unsafety {
+        Unsafe::Yes(span) => vis.visit_span(span),
+        Unsafe::No => {}
+    }
+}
+
+// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
+pub fn visit_polarity<T: MutVisitor>(polarity: &mut ImplPolarity, vis: &mut T) {
+    match polarity {
+        ImplPolarity::Positive => {}
+        ImplPolarity::Negative(span) => vis.visit_span(span),
+    }
+}
+
+// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
+pub fn visit_constness<T: MutVisitor>(constness: &mut Const, vis: &mut T) {
+    match constness {
+        Const::Yes(span) => vis.visit_span(span),
+        Const::No => {}
+    }
+}
+
 pub fn noop_visit_asyncness<T: MutVisitor>(asyncness: &mut Async, vis: &mut T) {
     match asyncness {
         Async::Yes { span: _, closure_id, return_impl_trait_id } => {
@@ -955,25 +989,35 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
     match kind {
         ItemKind::ExternCrate(_orig_name) => {}
         ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
-        ItemKind::Static(ty, _, expr) | ItemKind::Const(_, ty, expr) => {
+        ItemKind::Static(ty, _, expr) => {
             vis.visit_ty(ty);
             visit_opt(expr, |expr| vis.visit_expr(expr));
         }
-        ItemKind::Fn(box FnKind(_, sig, generics, body)) => {
+        ItemKind::Const(defaultness, ty, expr) => {
+            visit_defaultness(defaultness, vis);
+            vis.visit_ty(ty);
+            visit_opt(expr, |expr| vis.visit_expr(expr));
+        }
+        ItemKind::Fn(box Fn { defaultness, generics, sig, body }) => {
+            visit_defaultness(defaultness, vis);
             visit_fn_sig(sig, vis);
             vis.visit_generics(generics);
             visit_opt(body, |body| vis.visit_block(body));
         }
-        ItemKind::Mod(_unsafety, mod_kind) => match mod_kind {
-            ModKind::Loaded(items, _inline, inner_span) => {
-                vis.visit_span(inner_span);
-                items.flat_map_in_place(|item| vis.flat_map_item(item));
+        ItemKind::Mod(unsafety, mod_kind) => {
+            visit_unsafety(unsafety, vis);
+            match mod_kind {
+                ModKind::Loaded(items, _inline, inner_span) => {
+                    vis.visit_span(inner_span);
+                    items.flat_map_in_place(|item| vis.flat_map_item(item));
+                }
+                ModKind::Unloaded => {}
             }
-            ModKind::Unloaded => {}
-        },
+        }
         ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
         ItemKind::GlobalAsm(asm) => noop_visit_inline_asm(asm, vis),
-        ItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
+        ItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty }) => {
+            visit_defaultness(defaultness, vis);
             vis.visit_generics(generics);
             visit_bounds(bounds, vis);
             visit_opt(ty, |ty| vis.visit_ty(ty));
@@ -986,22 +1030,27 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
             vis.visit_variant_data(variant_data);
             vis.visit_generics(generics);
         }
-        ItemKind::Impl(box ImplKind {
-            unsafety: _,
-            polarity: _,
-            defaultness: _,
-            constness: _,
+        ItemKind::Impl(box Impl {
+            defaultness,
+            unsafety,
             generics,
+            constness,
+            polarity,
             of_trait,
             self_ty,
             items,
         }) => {
+            visit_defaultness(defaultness, vis);
+            visit_unsafety(unsafety, vis);
             vis.visit_generics(generics);
+            visit_constness(constness, vis);
+            visit_polarity(polarity, vis);
             visit_opt(of_trait, |trait_ref| vis.visit_trait_ref(trait_ref));
             vis.visit_ty(self_ty);
             items.flat_map_in_place(|item| vis.flat_map_impl_item(item));
         }
-        ItemKind::Trait(box TraitKind(.., generics, bounds, items)) => {
+        ItemKind::Trait(box Trait { unsafety, is_auto: _, generics, bounds, items }) => {
+            visit_unsafety(unsafety, vis);
             vis.visit_generics(generics);
             visit_bounds(bounds, vis);
             items.flat_map_in_place(|item| vis.flat_map_trait_item(item));
@@ -1025,16 +1074,19 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
     visitor.visit_vis(vis);
     visit_attrs(attrs, visitor);
     match kind {
-        AssocItemKind::Const(_, ty, expr) => {
+        AssocItemKind::Const(defaultness, ty, expr) => {
+            visit_defaultness(defaultness, visitor);
             visitor.visit_ty(ty);
             visit_opt(expr, |expr| visitor.visit_expr(expr));
         }
-        AssocItemKind::Fn(box FnKind(_, sig, generics, body)) => {
+        AssocItemKind::Fn(box Fn { defaultness, generics, sig, body }) => {
+            visit_defaultness(defaultness, visitor);
             visitor.visit_generics(generics);
             visit_fn_sig(sig, visitor);
             visit_opt(body, |body| visitor.visit_block(body));
         }
-        AssocItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
+        AssocItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty }) => {
+            visit_defaultness(defaultness, visitor);
             visitor.visit_generics(generics);
             visit_bounds(bounds, visitor);
             visit_opt(ty, |ty| visitor.visit_ty(ty));
@@ -1047,8 +1099,10 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
 }
 
 pub fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
-    let FnHeader { unsafety: _, asyncness, constness: _, ext: _ } = header;
+    let FnHeader { unsafety, asyncness, constness, ext: _ } = header;
+    visit_constness(constness, vis);
     vis.visit_asyncness(asyncness);
+    visit_unsafety(unsafety, vis);
 }
 
 // FIXME: Avoid visiting the crate as a `Mod` item, flat map only the inner items if possible,
@@ -1114,12 +1168,14 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>(
             visitor.visit_ty(ty);
             visit_opt(expr, |expr| visitor.visit_expr(expr));
         }
-        ForeignItemKind::Fn(box FnKind(_, sig, generics, body)) => {
+        ForeignItemKind::Fn(box Fn { defaultness, generics, sig, body }) => {
+            visit_defaultness(defaultness, visitor);
             visitor.visit_generics(generics);
             visit_fn_sig(sig, visitor);
             visit_opt(body, |body| visitor.visit_block(body));
         }
-        ForeignItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
+        ForeignItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty }) => {
+            visit_defaultness(defaultness, visitor);
             visitor.visit_generics(generics);
             visit_bounds(bounds, visitor);
             visit_opt(ty, |ty| visitor.visit_ty(ty));
index 5d994dbad4d1fcf128851668679a54ced7f92e41..51cabb50cd3de7280a1ddfd8cff2caaeabb1e3c6 100644 (file)
@@ -221,12 +221,6 @@ pub fn to_tokenstream(&self) -> TokenStream {
                     for attr in &data.attrs {
                         match attr.style {
                             crate::AttrStyle::Outer => {
-                                assert!(
-                                    inner_attrs.len() == 0,
-                                    "Found outer attribute {:?} after inner attrs {:?}",
-                                    attr,
-                                    inner_attrs
-                                );
                                 outer_attrs.push(attr);
                             }
                             crate::AttrStyle::Inner => {
index 542a330a031414f469f52a256793b93c311f1fc7..c40aec4b671dd4ec0db312e12249802a822f0038 100644 (file)
@@ -38,7 +38,7 @@ fn get_vertical_trim(lines: &[&str]) -> Option<(usize, usize)> {
             i += 1;
         }
         // like the first, a last line of all stars should be omitted
-        if j > i && lines[j - 1].chars().skip(1).all(|c| c == '*') {
+        if j > i && !lines[j - 1].is_empty() && lines[j - 1].chars().all(|c| c == '*') {
             j -= 1;
         }
 
index 500c97e65ef9cc868611037369912944f783430a..742a7d1d2df70907fa087b4221fffbf816b835bf 100644 (file)
@@ -212,7 +212,8 @@ pub fn to_ast_binop(&self) -> Option<BinOpKind> {
     /// parentheses while having a high degree of confidence on the correctness of the suggestion.
     pub fn can_continue_expr_unambiguously(&self) -> bool {
         use AssocOp::*;
-        match self {
+        matches!(
+            self,
             BitXor | // `{ 42 } ^ 3`
             Assign | // `{ 42 } = { 42 }`
             Divide | // `{ 42 } / 42`
@@ -225,9 +226,8 @@ pub fn can_continue_expr_unambiguously(&self) -> bool {
             As | // `{ 42 } as usize`
             // Equal | // `{ 42 } == { 42 }`    Accepting these here would regress incorrect
             // NotEqual | // `{ 42 } != { 42 }  struct literals parser recovery.
-            Colon => true, // `{ 42 }: usize`
-            _ => false,
-        }
+            Colon, // `{ 42 }: usize`
+        )
     }
 }
 
diff --git a/compiler/rustc_ast/src/util/unicode.rs b/compiler/rustc_ast/src/util/unicode.rs
new file mode 100644 (file)
index 0000000..f009f7b
--- /dev/null
@@ -0,0 +1,35 @@
+pub const TEXT_FLOW_CONTROL_CHARS: &[char] = &[
+    '\u{202A}', '\u{202B}', '\u{202D}', '\u{202E}', '\u{2066}', '\u{2067}', '\u{2068}', '\u{202C}',
+    '\u{2069}',
+];
+
+#[inline]
+pub fn contains_text_flow_control_chars(s: &str) -> bool {
+    // Char   - UTF-8
+    // U+202A - E2 80 AA
+    // U+202B - E2 80 AB
+    // U+202C - E2 80 AC
+    // U+202D - E2 80 AD
+    // U+202E - E2 80 AE
+    // U+2066 - E2 81 A6
+    // U+2067 - E2 81 A7
+    // U+2068 - E2 81 A8
+    // U+2069 - E2 81 A9
+    let mut bytes = s.as_bytes();
+    loop {
+        match core::slice::memchr::memchr(0xE2, &bytes) {
+            Some(idx) => {
+                // bytes are valid UTF-8 -> E2 must be followed by two bytes
+                let ch = &bytes[idx..idx + 3];
+                match ch {
+                    [_, 0x80, 0xAA..=0xAE] | [_, 0x81, 0xA6..=0xA9] => break true,
+                    _ => {}
+                }
+                bytes = &bytes[idx + 3..];
+            }
+            None => {
+                break false;
+            }
+        }
+    }
+}
index b38031042e0f09ed1265acf60725eca661dc84f5..be794ed221ae702331d0940d0df935545d255b61 100644 (file)
@@ -285,7 +285,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             visitor.visit_ty(typ);
             walk_list!(visitor, visit_expr, expr);
         }
-        ItemKind::Fn(box FnKind(_, ref sig, ref generics, ref body)) => {
+        ItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => {
             visitor.visit_generics(generics);
             let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref());
             visitor.visit_fn(kind, item.span, item.id)
@@ -300,7 +300,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             walk_list!(visitor, visit_foreign_item, &foreign_module.items);
         }
         ItemKind::GlobalAsm(ref asm) => walk_inline_asm(visitor, asm),
-        ItemKind::TyAlias(box TyAliasKind(_, ref generics, ref bounds, ref ty)) => {
+        ItemKind::TyAlias(box TyAlias { defaultness: _, ref generics, ref bounds, ref ty }) => {
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_ty, ty);
@@ -309,12 +309,12 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             visitor.visit_generics(generics);
             visitor.visit_enum_def(enum_definition, generics, item.id, item.span)
         }
-        ItemKind::Impl(box ImplKind {
-            unsafety: _,
-            polarity: _,
+        ItemKind::Impl(box Impl {
             defaultness: _,
-            constness: _,
+            unsafety: _,
             ref generics,
+            constness: _,
+            polarity: _,
             ref of_trait,
             ref self_ty,
             ref items,
@@ -329,7 +329,13 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             visitor.visit_generics(generics);
             visitor.visit_variant_data(struct_definition);
         }
-        ItemKind::Trait(box TraitKind(.., ref generics, ref bounds, ref items)) => {
+        ItemKind::Trait(box Trait {
+            unsafety: _,
+            is_auto: _,
+            ref generics,
+            ref bounds,
+            ref items,
+        }) => {
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait);
@@ -547,12 +553,12 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI
             visitor.visit_ty(ty);
             walk_list!(visitor, visit_expr, expr);
         }
-        ForeignItemKind::Fn(box FnKind(_, sig, generics, body)) => {
+        ForeignItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => {
             visitor.visit_generics(generics);
             let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, body.as_deref());
             visitor.visit_fn(kind, span, id);
         }
-        ForeignItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
+        ForeignItemKind::TyAlias(box TyAlias { defaultness: _, generics, bounds, ty }) => {
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_ty, ty);
@@ -653,12 +659,12 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
             visitor.visit_ty(ty);
             walk_list!(visitor, visit_expr, expr);
         }
-        AssocItemKind::Fn(box FnKind(_, sig, generics, body)) => {
+        AssocItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => {
             visitor.visit_generics(generics);
             let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, body.as_deref());
             visitor.visit_fn(kind, span, id);
         }
-        AssocItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
+        AssocItemKind::TyAlias(box TyAlias { defaultness: _, generics, bounds, ty }) => {
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_ty, ty);
index 957b14f34872962eef8455fcbf1bc5ffa712993d..95997a37d845b97e18a86b779992aae0b8e6b7b5 100644 (file)
@@ -4,20 +4,42 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
-use rustc_span::{Span, Symbol};
+use rustc_session::parse::feature_err;
+use rustc_span::{sym, Span, Symbol};
 use rustc_target::asm;
 use std::collections::hash_map::Entry;
 use std::fmt::Write;
 
 impl<'a, 'hir> LoweringContext<'a, 'hir> {
     crate fn lower_inline_asm(&mut self, sp: Span, asm: &InlineAsm) -> &'hir hir::InlineAsm<'hir> {
-        // Rustdoc needs to support asm! from foriegn architectures: don't try
-        // lowering the register contraints in this case.
+        // Rustdoc needs to support asm! from foreign architectures: don't try
+        // lowering the register constraints in this case.
         let asm_arch = if self.sess.opts.actually_rustdoc { None } else { self.sess.asm_arch };
         if asm_arch.is_none() && !self.sess.opts.actually_rustdoc {
             struct_span_err!(self.sess, sp, E0472, "inline assembly is unsupported on this target")
                 .emit();
         }
+        if let Some(asm_arch) = asm_arch {
+            // Inline assembly is currently only stable for these architectures.
+            let is_stable = matches!(
+                asm_arch,
+                asm::InlineAsmArch::X86
+                    | asm::InlineAsmArch::X86_64
+                    | asm::InlineAsmArch::Arm
+                    | asm::InlineAsmArch::AArch64
+                    | asm::InlineAsmArch::RiscV32
+                    | asm::InlineAsmArch::RiscV64
+            );
+            if !is_stable && !self.sess.features_untracked().asm_experimental_arch {
+                feature_err(
+                    &self.sess.parse_sess,
+                    sym::asm_experimental_arch,
+                    sp,
+                    "inline assembly is not stable yet on this architecture",
+                )
+                .emit();
+            }
+        }
         if asm.options.contains(InlineAsmOptions::ATT_SYNTAX)
             && !matches!(asm_arch, Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64))
             && !self.sess.opts.actually_rustdoc
@@ -121,10 +143,30 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             out_expr: out_expr.as_ref().map(|expr| self.lower_expr_mut(expr)),
                         }
                     }
-                    InlineAsmOperand::Const { ref anon_const } => hir::InlineAsmOperand::Const {
-                        anon_const: self.lower_anon_const(anon_const),
-                    },
+                    InlineAsmOperand::Const { ref anon_const } => {
+                        if !self.sess.features_untracked().asm_const {
+                            feature_err(
+                                &self.sess.parse_sess,
+                                sym::asm_const,
+                                *op_sp,
+                                "const operands for inline assembly are unstable",
+                            )
+                            .emit();
+                        }
+                        hir::InlineAsmOperand::Const {
+                            anon_const: self.lower_anon_const(anon_const),
+                        }
+                    }
                     InlineAsmOperand::Sym { ref expr } => {
+                        if !self.sess.features_untracked().asm_sym {
+                            feature_err(
+                                &self.sess.parse_sess,
+                                sym::asm_sym,
+                                *op_sp,
+                                "sym operands for inline assembly are unstable",
+                            )
+                            .emit();
+                        }
                         hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) }
                     }
                 };
@@ -214,9 +256,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 // means that we disallow passing a value in/out of the asm and
                 // require that the operand name an explicit register, not a
                 // register class.
-                if reg_class.is_clobber_only(asm_arch.unwrap())
-                    && !(op.is_clobber() && matches!(reg, asm::InlineAsmRegOrRegClass::Reg(_)))
-                {
+                if reg_class.is_clobber_only(asm_arch.unwrap()) && !op.is_clobber() {
                     let msg = format!(
                         "register class `{}` can only be used as a clobber, \
                              not as an input or output",
index dc2b1a730fbd6bc2625fbb1296fabd0ad468fb07..8a9dad2cdd7d86635425ed9853b012abe1003f37 100644 (file)
@@ -1,4 +1,5 @@
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sorted_map::SortedMap;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::definitions;
 use rustc_span::source_map::SourceMap;
 use rustc_span::{Span, DUMMY_SP};
 
-use std::iter::repeat;
 use tracing::debug;
 
 /// A visitor that walks over the HIR and collects `Node`s into a HIR map.
 pub(super) struct NodeCollector<'a, 'hir> {
     /// Source map
     source_map: &'a SourceMap,
-    bodies: &'a IndexVec<ItemLocalId, Option<&'hir Body<'hir>>>,
+    bodies: &'a SortedMap<ItemLocalId, &'hir Body<'hir>>,
 
     /// Outputs
     nodes: IndexVec<ItemLocalId, Option<ParentedNode<'hir>>>,
@@ -30,21 +30,11 @@ pub(super) struct NodeCollector<'a, 'hir> {
     definitions: &'a definitions::Definitions,
 }
 
-fn insert_vec_map<K: Idx, V: Clone>(map: &mut IndexVec<K, Option<V>>, k: K, v: V) {
-    let i = k.index();
-    let len = map.len();
-    if i >= len {
-        map.extend(repeat(None).take(i - len + 1));
-    }
-    debug_assert!(map[k].is_none());
-    map[k] = Some(v);
-}
-
 pub(super) fn index_hir<'hir>(
     sess: &Session,
     definitions: &definitions::Definitions,
     item: hir::OwnerNode<'hir>,
-    bodies: &IndexVec<ItemLocalId, Option<&'hir Body<'hir>>>,
+    bodies: &SortedMap<ItemLocalId, &'hir Body<'hir>>,
 ) -> (IndexVec<ItemLocalId, Option<ParentedNode<'hir>>>, FxHashMap<LocalDefId, ItemLocalId>) {
     let mut nodes = IndexVec::new();
     // This node's parent should never be accessed: the owner's parent is computed by the
@@ -94,11 +84,7 @@ fn insert(&mut self, span: Span, hir_id: HirId, node: Node<'hir>) {
             }
         }
 
-        insert_vec_map(
-            &mut self.nodes,
-            hir_id.local_id,
-            ParentedNode { parent: self.parent_node, node: node },
-        );
+        self.nodes.insert(hir_id.local_id, ParentedNode { parent: self.parent_node, node: node });
     }
 
     fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_node_id: HirId, f: F) {
@@ -144,7 +130,7 @@ fn visit_nested_foreign_item(&mut self, foreign_id: ForeignItemId) {
 
     fn visit_nested_body(&mut self, id: BodyId) {
         debug_assert_eq!(id.hir_id.owner, self.owner);
-        let body = self.bodies[id.hir_id.local_id].unwrap();
+        let body = self.bodies[&id.hir_id.local_id];
         self.visit_body(body);
     }
 
index e8747f2c5f8f9d06bd03a49ca35c587254b1287d..6a4571cf6d278928ab4bd8ae10ceda56613f7e56 100644 (file)
@@ -49,7 +49,7 @@ fn visit_item(&mut self, item: &'a Item) {
         self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
             let this = &mut ItemLowerer { lctx: this };
             match item.kind {
-                ItemKind::Impl(box ImplKind { ref of_trait, .. }) => {
+                ItemKind::Impl(box Impl { ref of_trait, .. }) => {
                     this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item));
                 }
                 _ => visit::walk_item(this, item),
@@ -218,12 +218,12 @@ fn lower_item_kind(
                 let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
                 hir::ItemKind::Const(ty, body_id)
             }
-            ItemKind::Fn(box FnKind(
-                _,
-                FnSig { ref decl, header, span: fn_sig_span },
+            ItemKind::Fn(box Fn {
+                sig: FnSig { ref decl, header, span: fn_sig_span },
                 ref generics,
                 ref body,
-            )) => {
+                ..
+            }) => {
                 let fn_def_id = self.resolver.local_def_id(id);
                 self.with_new_scopes(|this| {
                     this.current_item = Some(ident.span);
@@ -273,7 +273,7 @@ fn lower_item_kind(
             ItemKind::GlobalAsm(ref asm) => {
                 hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm))
             }
-            ItemKind::TyAlias(box TyAliasKind(_, ref gen, _, Some(ref ty))) => {
+            ItemKind::TyAlias(box TyAlias { ref generics, ty: Some(ref ty), .. }) => {
                 // We lower
                 //
                 // type Foo = impl Trait
@@ -288,10 +288,10 @@ fn lower_item_kind(
                         capturable_lifetimes: &mut FxHashSet::default(),
                     },
                 );
-                let generics = self.lower_generics(gen, ImplTraitContext::disallowed());
+                let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
                 hir::ItemKind::TyAlias(ty, generics)
             }
-            ItemKind::TyAlias(box TyAliasKind(_, ref generics, _, None)) => {
+            ItemKind::TyAlias(box TyAlias { ref generics, ty: None, .. }) => {
                 let ty = self.arena.alloc(self.ty(span, hir::TyKind::Err));
                 let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
                 hir::ItemKind::TyAlias(ty, generics)
@@ -318,7 +318,7 @@ fn lower_item_kind(
                     self.lower_generics(generics, ImplTraitContext::disallowed()),
                 )
             }
-            ItemKind::Impl(box ImplKind {
+            ItemKind::Impl(box Impl {
                 unsafety,
                 polarity,
                 defaultness,
@@ -384,13 +384,13 @@ fn lower_item_kind(
                     items: new_impl_items,
                 })
             }
-            ItemKind::Trait(box TraitKind(
+            ItemKind::Trait(box Trait {
                 is_auto,
                 unsafety,
                 ref generics,
                 ref bounds,
                 ref items,
-            )) => {
+            }) => {
                 let bounds = self.lower_param_bounds(bounds, ImplTraitContext::disallowed());
                 let items = self
                     .arena
@@ -655,7 +655,7 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir
             def_id,
             ident: self.lower_ident(i.ident),
             kind: match i.kind {
-                ForeignItemKind::Fn(box FnKind(_, ref sig, ref generics, _)) => {
+                ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => {
                     let fdec = &sig.decl;
                     let (generics, (fn_dec, fn_args)) = self.add_in_band_defs(
                         generics,
@@ -772,13 +772,13 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
                 let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x)));
                 (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body))
             }
-            AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, None)) => {
+            AssocItemKind::Fn(box Fn { ref sig, ref generics, body: None, .. }) => {
                 let names = self.lower_fn_params_to_names(&sig.decl);
                 let (generics, sig) =
                     self.lower_method_sig(generics, sig, trait_item_def_id, false, None);
                 (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)))
             }
-            AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, Some(ref body))) => {
+            AssocItemKind::Fn(box Fn { ref sig, ref generics, body: Some(ref body), .. }) => {
                 let asyncness = sig.header.asyncness;
                 let body_id =
                     self.lower_maybe_async_body(i.span, &sig.decl, asyncness, Some(&body));
@@ -791,8 +791,8 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
                 );
                 (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)))
             }
-            AssocItemKind::TyAlias(box TyAliasKind(_, ref generics, ref bounds, ref default)) => {
-                let ty = default.as_ref().map(|x| self.lower_ty(x, ImplTraitContext::disallowed()));
+            AssocItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. }) => {
+                let ty = ty.as_ref().map(|x| self.lower_ty(x, ImplTraitContext::disallowed()));
                 let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
                 let kind = hir::TraitItemKind::Type(
                     self.lower_param_bounds(bounds, ImplTraitContext::disallowed()),
@@ -818,11 +818,11 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
     fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
         let (kind, has_default) = match &i.kind {
             AssocItemKind::Const(_, _, default) => (hir::AssocItemKind::Const, default.is_some()),
-            AssocItemKind::TyAlias(box TyAliasKind(_, _, _, default)) => {
-                (hir::AssocItemKind::Type, default.is_some())
+            AssocItemKind::TyAlias(box TyAlias { ty, .. }) => {
+                (hir::AssocItemKind::Type, ty.is_some())
             }
-            AssocItemKind::Fn(box FnKind(_, sig, _, default)) => {
-                (hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }, default.is_some())
+            AssocItemKind::Fn(box Fn { sig, body, .. }) => {
+                (hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }, body.is_some())
             }
             AssocItemKind::MacCall(..) => unimplemented!(),
         };
@@ -853,7 +853,7 @@ fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
                     hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())),
                 )
             }
-            AssocItemKind::Fn(box FnKind(_, sig, generics, body)) => {
+            AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
                 self.current_item = Some(i.span);
                 let asyncness = sig.header.asyncness;
                 let body_id =
@@ -869,7 +869,7 @@ fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
 
                 (generics, hir::ImplItemKind::Fn(sig, body_id))
             }
-            AssocItemKind::TyAlias(box TyAliasKind(_, generics, _, ty)) => {
+            AssocItemKind::TyAlias(box TyAlias { generics, ty, .. }) => {
                 let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
                 let kind = match ty {
                     None => {
@@ -920,7 +920,7 @@ fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
             kind: match &i.kind {
                 AssocItemKind::Const(..) => hir::AssocItemKind::Const,
                 AssocItemKind::TyAlias(..) => hir::AssocItemKind::Type,
-                AssocItemKind::Fn(box FnKind(_, sig, ..)) => {
+                AssocItemKind::Fn(box Fn { sig, .. }) => {
                     hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
                 }
                 AssocItemKind::MacCall(..) => unimplemented!(),
@@ -974,8 +974,7 @@ fn record_body(
         let body = hir::Body { generator_kind: self.generator_kind, params, value };
         let id = body.id();
         debug_assert_eq!(id.hir_id.owner, self.current_hir_id_owner);
-        self.bodies.ensure_contains_elem(id.hir_id.local_id, || None);
-        self.bodies[id.hir_id.local_id] = Some(self.arena.alloc(body));
+        self.bodies.push((id.hir_id.local_id, self.arena.alloc(body)));
         id
     }
 
index 63ba5b45f4c4741dd950cb5cbed99693fc44c2d0..79464a751721751ddfcce69776513184901395dd 100644 (file)
@@ -35,7 +35,6 @@
 #![feature(iter_zip)]
 #![feature(never_type)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 use rustc_ast::token::{self, Token};
 use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, TokenStream, TokenTree};
@@ -45,6 +44,7 @@
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::sorted_map::SortedMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{struct_span_err, Applicability};
@@ -67,7 +67,6 @@
 use rustc_span::{Span, DUMMY_SP};
 
 use smallvec::SmallVec;
-use std::collections::BTreeMap;
 use tracing::{debug, trace};
 
 macro_rules! arena_vec {
@@ -104,9 +103,9 @@ struct LoweringContext<'a, 'hir: 'a> {
     /// The items being lowered are collected here.
     owners: IndexVec<LocalDefId, Option<hir::OwnerInfo<'hir>>>,
     /// Bodies inside the owner being lowered.
-    bodies: IndexVec<hir::ItemLocalId, Option<&'hir hir::Body<'hir>>>,
+    bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>,
     /// Attributes inside the owner being lowered.
-    attrs: BTreeMap<hir::ItemLocalId, &'hir [Attribute]>,
+    attrs: SortedMap<hir::ItemLocalId, &'hir [Attribute]>,
 
     generator_kind: Option<hir::GeneratorKind>,
 
@@ -301,8 +300,8 @@ pub fn lower_crate<'a, 'hir>(
         nt_to_tokenstream,
         arena,
         owners,
-        bodies: IndexVec::new(),
-        attrs: BTreeMap::default(),
+        bodies: Vec::new(),
+        attrs: SortedMap::new(),
         catch_scope: None,
         loop_scope: None,
         is_in_loop_condition: false,
@@ -479,7 +478,7 @@ fn with_hir_id_owner(
 
     fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> hir::OwnerInfo<'hir> {
         let attrs = std::mem::take(&mut self.attrs);
-        let bodies = std::mem::take(&mut self.bodies);
+        let mut bodies = std::mem::take(&mut self.bodies);
         let local_node_ids = std::mem::take(&mut self.local_node_ids);
         let trait_map = local_node_ids
             .into_iter()
@@ -491,13 +490,15 @@ fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> hir::OwnerInfo<'hir
             .collect();
 
         #[cfg(debug_assertions)]
-        for (&id, attrs) in attrs.iter() {
+        for (id, attrs) in attrs.iter() {
             // Verify that we do not store empty slices in the map.
             if attrs.is_empty() {
                 panic!("Stored empty attributes for {:?}", id);
             }
         }
 
+        bodies.sort_by_key(|(k, _)| *k);
+        let bodies = SortedMap::from_presorted_elements(bodies);
         let (hash_including_bodies, hash_without_bodies) = self.hash_owner(node, &bodies);
         let (nodes, parenting) =
             index::index_hir(self.sess, self.resolver.definitions(), node, &bodies);
@@ -518,7 +519,7 @@ fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> hir::OwnerInfo<'hir
     fn hash_owner(
         &mut self,
         node: hir::OwnerNode<'hir>,
-        bodies: &IndexVec<hir::ItemLocalId, Option<&'hir hir::Body<'hir>>>,
+        bodies: &SortedMap<hir::ItemLocalId, &'hir hir::Body<'hir>>,
     ) -> (Fingerprint, Fingerprint) {
         let mut hcx = self.resolver.create_stable_hashing_context();
         let mut stable_hasher = StableHasher::new();
index 793f6504be6f79f030ea168db247a9a4793f1d80..1822ba6ec996493d952d217a25fa39253c5c383a 100644 (file)
@@ -1064,7 +1064,7 @@ fn visit_item(&mut self, item: &'a Item) {
         }
 
         match item.kind {
-            ItemKind::Impl(box ImplKind {
+            ItemKind::Impl(box Impl {
                 unsafety,
                 polarity,
                 defaultness: _,
@@ -1111,7 +1111,7 @@ fn visit_item(&mut self, item: &'a Item) {
                 });
                 return; // Avoid visiting again.
             }
-            ItemKind::Impl(box ImplKind {
+            ItemKind::Impl(box Impl {
                 unsafety,
                 polarity,
                 defaultness,
@@ -1152,8 +1152,8 @@ fn visit_item(&mut self, item: &'a Item) {
                         .emit();
                 }
             }
-            ItemKind::Fn(box FnKind(def, ref sig, ref generics, ref body)) => {
-                self.check_defaultness(item.span, def);
+            ItemKind::Fn(box Fn { defaultness, ref sig, ref generics, ref body }) => {
+                self.check_defaultness(item.span, defaultness);
 
                 if body.is_none() {
                     let msg = "free function without a body";
@@ -1195,19 +1195,13 @@ fn visit_item(&mut self, item: &'a Item) {
                     }
                 }
             }
-            ItemKind::Trait(box TraitKind(
-                is_auto,
-                _,
-                ref generics,
-                ref bounds,
-                ref trait_items,
-            )) => {
+            ItemKind::Trait(box Trait { is_auto, ref generics, ref bounds, ref items, .. }) => {
                 if is_auto == IsAuto::Yes {
                     // Auto traits cannot have generics, super traits nor contain items.
                     self.deny_generic_params(generics, item.ident.span);
                     self.deny_super_traits(bounds, item.ident.span);
                     self.deny_where_clause(&generics.where_clause, item.ident.span);
-                    self.deny_items(trait_items, item.ident.span);
+                    self.deny_items(items, item.ident.span);
                 }
                 self.no_questions_in_bounds(bounds, "supertraits", true);
 
@@ -1217,7 +1211,7 @@ fn visit_item(&mut self, item: &'a Item) {
                 self.visit_ident(item.ident);
                 self.visit_generics(generics);
                 self.with_banned_tilde_const(|this| walk_list!(this, visit_param_bound, bounds));
-                walk_list!(self, visit_assoc_item, trait_items, AssocCtxt::Trait);
+                walk_list!(self, visit_assoc_item, items, AssocCtxt::Trait);
                 walk_list!(self, visit_attribute, &item.attrs);
                 return;
             }
@@ -1278,9 +1272,9 @@ fn visit_item(&mut self, item: &'a Item) {
                 let msg = "free static item without body";
                 self.error_item_without_body(item.span, "static", msg, " = <expr>;");
             }
-            ItemKind::TyAlias(box TyAliasKind(def, _, ref bounds, ref body)) => {
-                self.check_defaultness(item.span, def);
-                if body.is_none() {
+            ItemKind::TyAlias(box TyAlias { defaultness, ref bounds, ref ty, .. }) => {
+                self.check_defaultness(item.span, defaultness);
+                if ty.is_none() {
                     let msg = "free type alias without body";
                     self.error_item_without_body(item.span, "type", msg, " = <type>;");
                 }
@@ -1294,15 +1288,15 @@ fn visit_item(&mut self, item: &'a Item) {
 
     fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
         match &fi.kind {
-            ForeignItemKind::Fn(box FnKind(def, sig, _, body)) => {
-                self.check_defaultness(fi.span, *def);
+            ForeignItemKind::Fn(box Fn { defaultness, sig, body, .. }) => {
+                self.check_defaultness(fi.span, *defaultness);
                 self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
                 self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
                 self.check_foreign_item_ascii_only(fi.ident);
             }
-            ForeignItemKind::TyAlias(box TyAliasKind(def, generics, bounds, body)) => {
-                self.check_defaultness(fi.span, *def);
-                self.check_foreign_kind_bodyless(fi.ident, "type", body.as_ref().map(|b| b.span));
+            ForeignItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty, .. }) => {
+                self.check_defaultness(fi.span, *defaultness);
+                self.check_foreign_kind_bodyless(fi.ident, "type", ty.as_ref().map(|b| b.span));
                 self.check_type_no_bounds(bounds, "`extern` blocks");
                 self.check_foreign_ty_genericless(generics);
                 self.check_foreign_item_ascii_only(fi.ident);
@@ -1587,11 +1581,11 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
                 AssocItemKind::Const(_, _, body) => {
                     self.check_impl_item_provided(item.span, body, "constant", " = <expr>;");
                 }
-                AssocItemKind::Fn(box FnKind(_, _, _, body)) => {
+                AssocItemKind::Fn(box Fn { body, .. }) => {
                     self.check_impl_item_provided(item.span, body, "function", " { <body> }");
                 }
-                AssocItemKind::TyAlias(box TyAliasKind(_, _, bounds, body)) => {
-                    self.check_impl_item_provided(item.span, body, "type", " = <type>;");
+                AssocItemKind::TyAlias(box TyAlias { bounds, ty, .. }) => {
+                    self.check_impl_item_provided(item.span, ty, "type", " = <type>;");
                     self.check_type_no_bounds(bounds, "`impl`s");
                 }
                 _ => {}
@@ -1600,7 +1594,7 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
 
         if ctxt == AssocCtxt::Trait || self.in_trait_impl {
             self.invalid_visibility(&item.vis, None);
-            if let AssocItemKind::Fn(box FnKind(_, sig, _, _)) = &item.kind {
+            if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
                 self.check_trait_fn_not_const(sig.header.constness);
                 self.check_trait_fn_not_async(item.span, sig.header.asyncness);
             }
@@ -1611,7 +1605,7 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
         }
 
         match item.kind {
-            AssocItemKind::TyAlias(box TyAliasKind(_, ref generics, ref bounds, ref ty))
+            AssocItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. })
                 if ctxt == AssocCtxt::Trait =>
             {
                 self.visit_vis(&item.vis);
@@ -1623,7 +1617,7 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
                 });
                 walk_list!(self, visit_ty, ty);
             }
-            AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, ref body))
+            AssocItemKind::Fn(box Fn { ref sig, ref generics, ref body, .. })
                 if self.in_const_trait_impl
                     || ctxt == AssocCtxt::Trait
                     || matches!(sig.header.constness, Const::Yes(_)) =>
index 91b4597a9bb1f021357f9bfff3aada7bcee74ff0..f45a79f026fb53521ab83117144b2c91a9003a2f 100644 (file)
@@ -423,9 +423,7 @@ fn visit_item(&mut self, i: &'a ast::Item) {
                 }
             }
 
-            ast::ItemKind::Impl(box ast::ImplKind {
-                polarity, defaultness, ref of_trait, ..
-            }) => {
+            ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, ref of_trait, .. }) => {
                 if let ast::ImplPolarity::Negative(span) = polarity {
                     gate_feature_post!(
                         &self,
@@ -441,7 +439,7 @@ fn visit_item(&mut self, i: &'a ast::Item) {
                 }
             }
 
-            ast::ItemKind::Trait(box ast::TraitKind(ast::IsAuto::Yes, ..)) => {
+            ast::ItemKind::Trait(box ast::Trait { is_auto: ast::IsAuto::Yes, .. }) => {
                 gate_feature_post!(
                     &self,
                     auto_traits,
@@ -459,7 +457,7 @@ fn visit_item(&mut self, i: &'a ast::Item) {
                 gate_feature_post!(&self, decl_macro, i.span, msg);
             }
 
-            ast::ItemKind::TyAlias(box ast::TyAliasKind(_, _, _, Some(ref ty))) => {
+            ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ref ty), .. }) => {
                 self.check_impl_trait(&ty)
             }
 
@@ -541,15 +539,13 @@ fn visit_expr(&mut self, e: &'a ast::Expr) {
             ast::ExprKind::TryBlock(_) => {
                 gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental");
             }
-            ast::ExprKind::Block(_, opt_label) => {
-                if let Some(label) = opt_label {
-                    gate_feature_post!(
-                        &self,
-                        label_break_value,
-                        label.ident.span,
-                        "labels on blocks are unstable"
-                    );
-                }
+            ast::ExprKind::Block(_, Some(label)) => {
+                gate_feature_post!(
+                    &self,
+                    label_break_value,
+                    label.ident.span,
+                    "labels on blocks are unstable"
+                );
             }
             _ => {}
         }
@@ -634,7 +630,7 @@ fn visit_assoc_ty_constraint(&mut self, constraint: &'a AssocTyConstraint) {
     fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
         let is_fn = match i.kind {
             ast::AssocItemKind::Fn(_) => true,
-            ast::AssocItemKind::TyAlias(box ast::TyAliasKind(_, ref generics, _, ref ty)) => {
+            ast::AssocItemKind::TyAlias(box ast::TyAlias { ref generics, ref ty, .. }) => {
                 if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
                     gate_feature_post!(
                         &self,
index 6da128a037499db3cc9802b5113b27ae0d88f0dc..47666670b2b63dbb2f2fbbe714e278011e1da4d7 100644 (file)
@@ -7,7 +7,6 @@
 #![feature(iter_is_partitioned)]
 #![feature(box_patterns)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 pub mod ast_validation;
 pub mod feature_gate;
index 6d0589b7ba1af7a5ae205dc8a45df5f09ae9257e..b59e49926add91d9d2a1c6fdb13c17e00c8ddcb1 100644 (file)
@@ -1044,15 +1044,27 @@ pub fn print_type(&mut self, ty: &ast::Ty) {
         self.maybe_print_comment(span.lo());
         self.print_outer_attributes(attrs);
         match kind {
-            ast::ForeignItemKind::Fn(box ast::FnKind(def, sig, gen, body)) => {
-                self.print_fn_full(sig, ident, gen, vis, *def, body.as_deref(), attrs);
+            ast::ForeignItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
+                self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
             }
             ast::ForeignItemKind::Static(ty, mutbl, body) => {
                 let def = ast::Defaultness::Final;
                 self.print_item_const(ident, Some(*mutbl), ty, body.as_deref(), vis, def);
             }
-            ast::ForeignItemKind::TyAlias(box ast::TyAliasKind(def, generics, bounds, ty)) => {
-                self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, *def);
+            ast::ForeignItemKind::TyAlias(box ast::TyAlias {
+                defaultness,
+                generics,
+                bounds,
+                ty,
+            }) => {
+                self.print_associated_type(
+                    ident,
+                    generics,
+                    bounds,
+                    ty.as_deref(),
+                    vis,
+                    *defaultness,
+                );
             }
             ast::ForeignItemKind::MacCall(m) => {
                 self.print_mac(m);
@@ -1156,9 +1168,17 @@ fn print_associated_type(
             ast::ItemKind::Const(def, ref ty, ref body) => {
                 self.print_item_const(item.ident, None, ty, body.as_deref(), &item.vis, def);
             }
-            ast::ItemKind::Fn(box ast::FnKind(def, ref sig, ref gen, ref body)) => {
+            ast::ItemKind::Fn(box ast::Fn { defaultness, ref sig, ref generics, ref body }) => {
                 let body = body.as_deref();
-                self.print_fn_full(sig, item.ident, gen, &item.vis, def, body, &item.attrs);
+                self.print_fn_full(
+                    sig,
+                    item.ident,
+                    generics,
+                    &item.vis,
+                    defaultness,
+                    body,
+                    &item.attrs,
+                );
             }
             ast::ItemKind::Mod(unsafety, ref mod_kind) => {
                 self.head(self.to_string(|s| {
@@ -1203,9 +1223,21 @@ fn print_associated_type(
                 self.print_inline_asm(asm);
                 self.end();
             }
-            ast::ItemKind::TyAlias(box ast::TyAliasKind(def, ref generics, ref bounds, ref ty)) => {
+            ast::ItemKind::TyAlias(box ast::TyAlias {
+                defaultness,
+                ref generics,
+                ref bounds,
+                ref ty,
+            }) => {
                 let ty = ty.as_deref();
-                self.print_associated_type(item.ident, generics, bounds, ty, &item.vis, def);
+                self.print_associated_type(
+                    item.ident,
+                    generics,
+                    bounds,
+                    ty,
+                    &item.vis,
+                    defaultness,
+                );
             }
             ast::ItemKind::Enum(ref enum_definition, ref params) => {
                 self.print_enum_def(enum_definition, params, item.ident, item.span, &item.vis);
@@ -1218,7 +1250,7 @@ fn print_associated_type(
                 self.head(visibility_qualified(&item.vis, "union"));
                 self.print_struct(struct_def, generics, item.ident, item.span, true);
             }
-            ast::ItemKind::Impl(box ast::ImplKind {
+            ast::ItemKind::Impl(box ast::Impl {
                 unsafety,
                 polarity,
                 defaultness,
@@ -1261,13 +1293,14 @@ fn print_associated_type(
                 }
                 self.bclose(item.span);
             }
-            ast::ItemKind::Trait(box ast::TraitKind(
+            ast::ItemKind::Trait(box ast::Trait {
                 is_auto,
                 unsafety,
                 ref generics,
                 ref bounds,
-                ref trait_items,
-            )) => {
+                ref items,
+                ..
+            }) => {
                 self.head("");
                 self.print_visibility(&item.vis);
                 self.print_unsafety(unsafety);
@@ -1290,7 +1323,7 @@ fn print_associated_type(
                 self.s.word(" ");
                 self.bopen();
                 self.print_inner_attributes(&item.attrs);
-                for trait_item in trait_items {
+                for trait_item in items {
                     self.print_assoc_item(trait_item);
                 }
                 self.bclose(item.span);
@@ -1405,11 +1438,7 @@ fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) {
         }
     }
 
-    crate fn print_record_struct_body(
-        &mut self,
-        fields: &Vec<ast::FieldDef>,
-        span: rustc_span::Span,
-    ) {
+    crate fn print_record_struct_body(&mut self, fields: &[ast::FieldDef], span: rustc_span::Span) {
         self.nbsp();
         self.bopen();
         self.hardbreak_if_not_bol();
@@ -1483,14 +1512,21 @@ fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) {
         self.maybe_print_comment(span.lo());
         self.print_outer_attributes(attrs);
         match kind {
-            ast::AssocItemKind::Fn(box ast::FnKind(def, sig, gen, body)) => {
-                self.print_fn_full(sig, ident, gen, vis, *def, body.as_deref(), attrs);
+            ast::AssocItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
+                self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
             }
             ast::AssocItemKind::Const(def, ty, body) => {
                 self.print_item_const(ident, None, ty, body.as_deref(), vis, *def);
             }
-            ast::AssocItemKind::TyAlias(box ast::TyAliasKind(def, generics, bounds, ty)) => {
-                self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, *def);
+            ast::AssocItemKind::TyAlias(box ast::TyAlias { defaultness, generics, bounds, ty }) => {
+                self.print_associated_type(
+                    ident,
+                    generics,
+                    bounds,
+                    ty.as_deref(),
+                    vis,
+                    *defaultness,
+                );
             }
             ast::AssocItemKind::MacCall(m) => {
                 self.print_mac(m);
index e30d6c7fca73191a66468303cacbbf94d9396d70..952e18c1e570db6463ce2bf8b9e349bfc0a629f0 100644 (file)
 use std::fmt;
 use std::ops::Index;
 
-crate struct BorrowSet<'tcx> {
+pub struct BorrowSet<'tcx> {
     /// The fundamental map relating bitvector indexes to the borrows
     /// in the MIR. Each borrow is also uniquely identified in the MIR
     /// by the `Location` of the assignment statement in which it
     /// appears on the right hand side. Thus the location is the map
     /// key, and its position in the map corresponds to `BorrowIndex`.
-    crate location_map: FxIndexMap<Location, BorrowData<'tcx>>,
+    pub location_map: FxIndexMap<Location, BorrowData<'tcx>>,
 
     /// Locations which activate borrows.
     /// NOTE: a given location may activate more than one borrow in the future
     /// when more general two-phase borrow support is introduced, but for now we
     /// only need to store one borrow index.
-    crate activation_map: FxHashMap<Location, Vec<BorrowIndex>>,
+    pub activation_map: FxHashMap<Location, Vec<BorrowIndex>>,
 
     /// Map from local to all the borrows on that local.
-    crate local_map: FxHashMap<mir::Local, FxHashSet<BorrowIndex>>,
+    pub local_map: FxHashMap<mir::Local, FxHashSet<BorrowIndex>>,
 
     crate locals_state_at_exit: LocalsStateAtExit,
 }
@@ -43,27 +43,27 @@ fn index(&self, index: BorrowIndex) -> &BorrowData<'tcx> {
 /// Location where a two-phase borrow is activated, if a borrow
 /// is in fact a two-phase borrow.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
-crate enum TwoPhaseActivation {
+pub enum TwoPhaseActivation {
     NotTwoPhase,
     NotActivated,
     ActivatedAt(Location),
 }
 
 #[derive(Debug, Clone)]
-crate struct BorrowData<'tcx> {
+pub struct BorrowData<'tcx> {
     /// Location where the borrow reservation starts.
     /// In many cases, this will be equal to the activation location but not always.
-    crate reserve_location: Location,
+    pub reserve_location: Location,
     /// Location where the borrow is activated.
-    crate activation_location: TwoPhaseActivation,
+    pub activation_location: TwoPhaseActivation,
     /// What kind of borrow this is
-    crate kind: mir::BorrowKind,
+    pub kind: mir::BorrowKind,
     /// The region for which this borrow is live
-    crate region: RegionVid,
+    pub region: RegionVid,
     /// Place from which we are borrowing
-    crate borrowed_place: mir::Place<'tcx>,
+    pub borrowed_place: mir::Place<'tcx>,
     /// Place to which the borrow was stored
-    crate assigned_place: mir::Place<'tcx>,
+    pub assigned_place: mir::Place<'tcx>,
 }
 
 impl<'tcx> fmt::Display for BorrowData<'tcx> {
@@ -78,7 +78,7 @@ fn fmt(&self, w: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-crate enum LocalsStateAtExit {
+pub enum LocalsStateAtExit {
     AllAreInvalidated,
     SomeAreInvalidated { has_storage_dead_or_moved: BitSet<Local> },
 }
index 15309ccd8df278ef157210533c15436bd75780ad..1bc9f8cf3ccc8660d83d41b83cfdee1ec85e4e04 100644 (file)
@@ -339,7 +339,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
     // We generally shouldn't have errors here because the query was
     // already run, but there's no point using `delay_span_bug`
     // when we're going to emit an error here anyway.
-    let _errors = fulfill_cx.select_all_or_error(infcx).err().unwrap_or_else(Vec::new);
+    let _errors = fulfill_cx.select_all_or_error(infcx);
 
     let (sub_region, cause) = infcx.with_region_constraints(|region_constraints| {
         debug!("{:#?}", region_constraints);
index 439c728798d3a42b1b8c1717fd61a4a873103820..46a3c0fa1015248cfcc806148757693432b26c00 100644 (file)
@@ -408,7 +408,7 @@ pub(crate) fn report_use_of_moved_or_uninitialized(
                     let param = generics.type_param(&param_ty, tcx);
                     if let Some(generics) = tcx
                         .hir()
-                        .get_generics(tcx.closure_base_def_id(self.mir_def_id().to_def_id()))
+                        .get_generics(tcx.typeck_root_def_id(self.mir_def_id().to_def_id()))
                     {
                         suggest_constraining_type_param(
                             tcx,
index d5de0801ac4431ccfcaab25872a16923501b8925..79973ab170cad8e362dd85199181b79b2e4c24ff 100644 (file)
@@ -53,10 +53,7 @@ pub(crate) enum LaterUseKind {
 
 impl BorrowExplanation {
     pub(crate) fn is_explained(&self) -> bool {
-        match self {
-            BorrowExplanation::Unexplained => false,
-            _ => true,
-        }
+        !matches!(self, BorrowExplanation::Unexplained)
     }
     pub(crate) fn add_explanation_to_diagnostic<'tcx>(
         &self,
index b1056900ad058f9ef3c1086a82d625e1ee850f23..aca7d3174f6cd567080aafd61b38949ba1154439 100644 (file)
@@ -2,7 +2,6 @@
 
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
-#![cfg_attr(bootstrap, feature(const_panic))]
 #![feature(crate_visibility_modifier)]
 #![feature(format_args_capture)]
 #![feature(in_band_lifetimes)]
@@ -13,7 +12,6 @@
 #![feature(trusted_step)]
 #![feature(try_blocks)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate rustc_middle;
@@ -65,7 +63,7 @@
 
 use self::path_utils::*;
 
-mod borrow_set;
+pub mod borrow_set;
 mod borrowck_errors;
 mod constraint_generation;
 mod constraints;
index e5924f9d08478ff484bcf5feef030bb7a48419cc..6ffab16577908fcbc747a0a4ff2d5b72620628fb 100644 (file)
@@ -376,7 +376,7 @@ pub(super) fn dump_annotation<'a, 'tcx>(
     errors_buffer: &mut Vec<Diagnostic>,
 ) {
     let tcx = infcx.tcx;
-    let base_def_id = tcx.closure_base_def_id(body.source.def_id());
+    let base_def_id = tcx.typeck_root_def_id(body.source.def_id());
     if !tcx.has_attr(base_def_id, sym::rustc_regions) {
         return;
     }
index 22bb3a29425ee1b49d5b44a3bc228030af3d0ac7..b39a28f79aaddc3f2eda6882bf5bd7b934fb2f9b 100644 (file)
@@ -569,7 +569,7 @@ pub(super) fn solve(
         // to store those. Otherwise, we'll pass in `None` to the
         // functions below, which will trigger them to report errors
         // eagerly.
-        let mut outlives_requirements = infcx.tcx.is_closure(mir_def_id).then(Vec::new);
+        let mut outlives_requirements = infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new);
 
         self.check_type_tests(infcx, body, outlives_requirements.as_mut(), &mut errors_buffer);
 
@@ -2110,14 +2110,14 @@ fn check_member_constraints(
                     _ => constraint_sup_scc != target_scc,
                 }
             } else {
-                match categorized_path[*i].category {
+                !matches!(
+                    categorized_path[*i].category,
                     ConstraintCategory::OpaqueType
-                    | ConstraintCategory::Boring
-                    | ConstraintCategory::BoringNoLocation
-                    | ConstraintCategory::Internal
-                    | ConstraintCategory::Predicate(_) => false,
-                    _ => true,
-                }
+                        | ConstraintCategory::Boring
+                        | ConstraintCategory::BoringNoLocation
+                        | ConstraintCategory::Internal
+                        | ConstraintCategory::Predicate(_)
+                )
             }
         };
 
@@ -2229,7 +2229,7 @@ fn apply_requirements(
             tcx,
             closure_substs,
             self.num_external_vids,
-            tcx.closure_base_def_id(closure_def_id),
+            tcx.typeck_root_def_id(closure_def_id),
         );
         debug!("apply_requirements: closure_mapping={:?}", closure_mapping);
 
index 7e69e710d68681ffed9ff5265bf22527661a1fdc..ddd077c22faf86662dfb93c482f2374dc249cd07 100644 (file)
@@ -10,6 +10,7 @@
 use rustc_data_structures::vec_map::VecMap;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_index::vec::{Idx, IndexVec};
@@ -36,7 +37,6 @@
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::VariantIdx;
 use rustc_trait_selection::infer::InferCtxtExt as _;
-use rustc_trait_selection::opaque_types::InferCtxtExt;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::type_op;
 use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
@@ -656,7 +656,7 @@ fn sanitize_promoted(&mut self, promoted_body: &'b Body<'tcx>, location: Locatio
             // If the region is live at at least one location in the promoted MIR,
             // then add a liveness constraint to the main MIR for this region
             // at the location provided as an argument to this method
-            if let Some(_) = liveness_constraints.get_elements(region).next() {
+            if liveness_constraints.get_elements(region).next().is_some() {
                 self.cx
                     .borrowck_context
                     .constraints
@@ -1344,13 +1344,9 @@ fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Lo
                 // though.
                 let category = match place.as_local() {
                     Some(RETURN_PLACE) => {
-                        if let BorrowCheckContext {
-                            universal_regions:
-                                UniversalRegions { defining_ty: DefiningTy::Const(def_id, _), .. },
-                            ..
-                        } = self.borrowck_context
-                        {
-                            if tcx.is_static(*def_id) {
+                        let defining_ty = &self.borrowck_context.universal_regions.defining_ty;
+                        if defining_ty.is_const() {
+                            if tcx.is_static(defining_ty.def_id()) {
                                 ConstraintCategory::UseAsStatic
                             } else {
                                 ConstraintCategory::UseAsConst
@@ -1528,6 +1524,8 @@ fn check_terminator(
                 }
             }
             TerminatorKind::SwitchInt { ref discr, switch_ty, .. } => {
+                self.check_operand(discr, term_location);
+
                 let discr_ty = discr.ty(body, tcx);
                 if let Err(terr) = self.sub_types(
                     discr_ty,
@@ -1550,6 +1548,11 @@ fn check_terminator(
                 // FIXME: check the values
             }
             TerminatorKind::Call { ref func, ref args, ref destination, from_hir_call, .. } => {
+                self.check_operand(func, term_location);
+                for arg in args {
+                    self.check_operand(arg, term_location);
+                }
+
                 let func_ty = func.ty(body, tcx);
                 debug!("check_terminator: call, func_ty={:?}", func_ty);
                 let sig = match func_ty.kind() {
@@ -1594,6 +1597,8 @@ fn check_terminator(
                 self.check_call_inputs(body, term, &sig, args, term_location, from_hir_call);
             }
             TerminatorKind::Assert { ref cond, ref msg, .. } => {
+                self.check_operand(cond, term_location);
+
                 let cond_ty = cond.ty(body, tcx);
                 if cond_ty != tcx.types.bool {
                     span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
@@ -1609,6 +1614,8 @@ fn check_terminator(
                 }
             }
             TerminatorKind::Yield { ref value, .. } => {
+                self.check_operand(value, term_location);
+
                 let value_ty = value.ty(body, tcx);
                 match body.yield_ty() {
                     None => span_mirbug!(self, term, "yield in non-generator"),
@@ -1651,7 +1658,12 @@ fn check_call_dest(
                     Some(RETURN_PLACE) => {
                         if let BorrowCheckContext {
                             universal_regions:
-                                UniversalRegions { defining_ty: DefiningTy::Const(def_id, _), .. },
+                                UniversalRegions {
+                                    defining_ty:
+                                        DefiningTy::Const(def_id, _)
+                                        | DefiningTy::InlineConst(def_id, _),
+                                    ..
+                                },
                             ..
                         } = self.borrowck_context
                         {
@@ -1932,15 +1944,51 @@ fn aggregate_field_ty(
         }
     }
 
+    fn check_operand(&mut self, op: &Operand<'tcx>, location: Location) {
+        if let Operand::Constant(constant) = op {
+            let maybe_uneval = match constant.literal {
+                ConstantKind::Ty(ct) => match ct.val {
+                    ty::ConstKind::Unevaluated(uv) => Some(uv),
+                    _ => None,
+                },
+                _ => None,
+            };
+            if let Some(uv) = maybe_uneval {
+                if uv.promoted.is_none() {
+                    let tcx = self.tcx();
+                    let def_id = uv.def.def_id_for_type_of();
+                    if tcx.def_kind(def_id) == DefKind::InlineConst {
+                        let predicates = self.prove_closure_bounds(
+                            tcx,
+                            def_id.expect_local(),
+                            uv.substs(tcx),
+                            location,
+                        );
+                        self.normalize_and_prove_instantiated_predicates(
+                            def_id,
+                            predicates,
+                            location.to_locations(),
+                        );
+                    }
+                }
+            }
+        }
+    }
+
     fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
         let tcx = self.tcx();
 
         match rvalue {
             Rvalue::Aggregate(ak, ops) => {
+                for op in ops {
+                    self.check_operand(op, location);
+                }
                 self.check_aggregate_rvalue(&body, rvalue, ak, ops, location)
             }
 
             Rvalue::Repeat(operand, len) => {
+                self.check_operand(operand, location);
+
                 // If the length cannot be evaluated we must assume that the length can be larger
                 // than 1.
                 // If the length is larger than 1, the repeat expression will need to copy the
@@ -1991,7 +2039,22 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
                 }
             }
 
-            Rvalue::NullaryOp(_, ty) | Rvalue::ShallowInitBox(_, ty) => {
+            Rvalue::NullaryOp(_, ty) => {
+                let trait_ref = ty::TraitRef {
+                    def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
+                    substs: tcx.mk_substs_trait(ty, &[]),
+                };
+
+                self.prove_trait_ref(
+                    trait_ref,
+                    location.to_locations(),
+                    ConstraintCategory::SizedBound,
+                );
+            }
+
+            Rvalue::ShallowInitBox(operand, ty) => {
+                self.check_operand(operand, location);
+
                 let trait_ref = ty::TraitRef {
                     def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
                     substs: tcx.mk_substs_trait(ty, &[]),
@@ -2005,6 +2068,8 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
             }
 
             Rvalue::Cast(cast_kind, op, ty) => {
+                self.check_operand(op, location);
+
                 match cast_kind {
                     CastKind::Pointer(PointerCast::ReifyFnPointer) => {
                         let fn_sig = op.ty(body, tcx).fn_sig(tcx);
@@ -2251,6 +2316,9 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
                 BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge,
                 box (left, right),
             ) => {
+                self.check_operand(left, location);
+                self.check_operand(right, location);
+
                 let ty_left = left.ty(body, tcx);
                 match ty_left.kind() {
                     // Types with regions are comparable if they have a common super-type.
@@ -2301,13 +2369,19 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
                 }
             }
 
+            Rvalue::Use(operand) | Rvalue::UnaryOp(_, operand) => {
+                self.check_operand(operand, location);
+            }
+
+            Rvalue::BinaryOp(_, box (left, right))
+            | Rvalue::CheckedBinaryOp(_, box (left, right)) => {
+                self.check_operand(left, location);
+                self.check_operand(right, location);
+            }
+
             Rvalue::AddressOf(..)
             | Rvalue::ThreadLocalRef(..)
-            | Rvalue::Use(..)
             | Rvalue::Len(..)
-            | Rvalue::BinaryOp(..)
-            | Rvalue::CheckedBinaryOp(..)
-            | Rvalue::UnaryOp(..)
             | Rvalue::Discriminant(..) => {}
         }
     }
index bebd19370299d00cdf360796c578638612f80312..b986df403f9f3f2c97789bad02c2b9720708bd71 100644 (file)
@@ -23,7 +23,7 @@
 use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
-use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt};
+use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt};
 use std::iter;
 
 use crate::nll::ToRegionVid;
@@ -108,6 +108,10 @@ pub enum DefiningTy<'tcx> {
     /// is that it has no inputs and a single return value, which is
     /// the value of the constant.
     Const(DefId, SubstsRef<'tcx>),
+
+    /// The MIR represents an inline const. The signature has no inputs and a
+    /// single return value found via `InlineConstSubsts::ty`.
+    InlineConst(DefId, SubstsRef<'tcx>),
 }
 
 impl<'tcx> DefiningTy<'tcx> {
@@ -121,7 +125,7 @@ pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
             DefiningTy::Generator(_, substs, _) => {
                 Either::Right(Either::Left(substs.as_generator().upvar_tys()))
             }
-            DefiningTy::FnDef(..) | DefiningTy::Const(..) => {
+            DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => {
                 Either::Right(Either::Right(iter::empty()))
             }
         }
@@ -133,22 +137,16 @@ pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
     pub fn implicit_inputs(self) -> usize {
         match self {
             DefiningTy::Closure(..) | DefiningTy::Generator(..) => 1,
-            DefiningTy::FnDef(..) | DefiningTy::Const(..) => 0,
+            DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => 0,
         }
     }
 
     pub fn is_fn_def(&self) -> bool {
-        match *self {
-            DefiningTy::FnDef(..) => true,
-            _ => false,
-        }
+        matches!(*self, DefiningTy::FnDef(..))
     }
 
     pub fn is_const(&self) -> bool {
-        match *self {
-            DefiningTy::Const(..) => true,
-            _ => false,
-        }
+        matches!(*self, DefiningTy::Const(..) | DefiningTy::InlineConst(..))
     }
 
     pub fn def_id(&self) -> DefId {
@@ -156,7 +154,8 @@ pub fn def_id(&self) -> DefId {
             DefiningTy::Closure(def_id, ..)
             | DefiningTy::Generator(def_id, ..)
             | DefiningTy::FnDef(def_id, ..)
-            | DefiningTy::Const(def_id, ..) => def_id,
+            | DefiningTy::Const(def_id, ..)
+            | DefiningTy::InlineConst(def_id, ..) => def_id,
         }
     }
 }
@@ -248,7 +247,7 @@ pub fn closure_mapping(
         tcx: TyCtxt<'tcx>,
         closure_substs: SubstsRef<'tcx>,
         expected_num_vars: usize,
-        closure_base_def_id: DefId,
+        typeck_root_def_id: DefId,
     ) -> IndexVec<RegionVid, ty::Region<'tcx>> {
         let mut region_mapping = IndexVec::with_capacity(expected_num_vars);
         region_mapping.push(tcx.lifetimes.re_static);
@@ -256,7 +255,7 @@ pub fn closure_mapping(
             region_mapping.push(fr);
         });
 
-        for_each_late_bound_region_defined_on(tcx, closure_base_def_id, |r| {
+        for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| {
             region_mapping.push(r);
         });
 
@@ -350,8 +349,8 @@ pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
                 // tests, and the resulting print-outs include def-ids
                 // and other things that are not stable across tests!
                 // So we just include the region-vid. Annoying.
-                let closure_base_def_id = tcx.closure_base_def_id(def_id);
-                for_each_late_bound_region_defined_on(tcx, closure_base_def_id, |r| {
+                let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
+                for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| {
                     err.note(&format!("late-bound region is {:?}", self.to_region_vid(r),));
                 });
             }
@@ -365,8 +364,8 @@ pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
                 // FIXME: As above, we'd like to print out the region
                 // `r` but doing so is not stable across architectures
                 // and so forth.
-                let closure_base_def_id = tcx.closure_base_def_id(def_id);
-                for_each_late_bound_region_defined_on(tcx, closure_base_def_id, |r| {
+                let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
+                for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| {
                     err.note(&format!("late-bound region is {:?}", self.to_region_vid(r),));
                 });
             }
@@ -382,6 +381,12 @@ pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
                     tcx.def_path_str_with_substs(def_id, substs),
                 ));
             }
+            DefiningTy::InlineConst(def_id, substs) => {
+                err.note(&format!(
+                    "defining inline constant type: {}",
+                    tcx.def_path_str_with_substs(def_id, substs),
+                ));
+            }
         }
     }
 }
@@ -417,7 +422,7 @@ fn build(self) -> UniversalRegions<'tcx> {
         let mut indices = self.compute_indices(fr_static, defining_ty);
         debug!("build: indices={:?}", indices);
 
-        let closure_base_def_id = self.infcx.tcx.closure_base_def_id(self.mir_def.did.to_def_id());
+        let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
 
         // If this is a closure or generator, then the late-bound regions from the enclosing
         // function are actually external regions to us. For example, here, 'a is not local
@@ -425,7 +430,7 @@ fn build(self) -> UniversalRegions<'tcx> {
         // fn foo<'a>() {
         //     let c = || { let x: &'a u32 = ...; }
         // }
-        if self.mir_def.did.to_def_id() != closure_base_def_id {
+        if self.mir_def.did.to_def_id() != typeck_root_def_id {
             self.infcx
                 .replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices)
         }
@@ -443,7 +448,7 @@ fn build(self) -> UniversalRegions<'tcx> {
         );
         // Converse of above, if this is a function then the late-bound regions declared on its
         // signature are local to the fn.
-        if self.mir_def.did.to_def_id() == closure_base_def_id {
+        if self.mir_def.did.to_def_id() == typeck_root_def_id {
             self.infcx
                 .replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices);
         }
@@ -508,12 +513,12 @@ fn build(self) -> UniversalRegions<'tcx> {
     /// see `DefiningTy` for details.
     fn defining_ty(&self) -> DefiningTy<'tcx> {
         let tcx = self.infcx.tcx;
-        let closure_base_def_id = tcx.closure_base_def_id(self.mir_def.did.to_def_id());
+        let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
 
         match tcx.hir().body_owner_kind(self.mir_hir_id) {
             BodyOwnerKind::Closure | BodyOwnerKind::Fn => {
-                let defining_ty = if self.mir_def.did.to_def_id() == closure_base_def_id {
-                    tcx.type_of(closure_base_def_id)
+                let defining_ty = if self.mir_def.did.to_def_id() == typeck_root_def_id {
+                    tcx.type_of(typeck_root_def_id)
                 } else {
                     let tables = tcx.typeck(self.mir_def.did);
                     tables.node_type(self.mir_hir_id)
@@ -540,11 +545,21 @@ fn defining_ty(&self) -> DefiningTy<'tcx> {
             }
 
             BodyOwnerKind::Const | BodyOwnerKind::Static(..) => {
-                assert_eq!(self.mir_def.did.to_def_id(), closure_base_def_id);
-                let identity_substs = InternalSubsts::identity_for_item(tcx, closure_base_def_id);
-                let substs =
-                    self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_substs);
-                DefiningTy::Const(self.mir_def.did.to_def_id(), substs)
+                let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
+                if self.mir_def.did.to_def_id() == typeck_root_def_id {
+                    let substs =
+                        self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_substs);
+                    DefiningTy::Const(self.mir_def.did.to_def_id(), substs)
+                } else {
+                    let ty = tcx.typeck(self.mir_def.did).node_type(self.mir_hir_id);
+                    let substs = InlineConstSubsts::new(
+                        tcx,
+                        InlineConstSubstsParts { parent_substs: identity_substs, ty },
+                    )
+                    .substs;
+                    let substs = self.infcx.replace_free_regions_with_nll_infer_vars(FR, substs);
+                    DefiningTy::InlineConst(self.mir_def.did.to_def_id(), substs)
+                }
             }
         }
     }
@@ -559,17 +574,19 @@ fn compute_indices(
         defining_ty: DefiningTy<'tcx>,
     ) -> UniversalRegionIndices<'tcx> {
         let tcx = self.infcx.tcx;
-        let closure_base_def_id = tcx.closure_base_def_id(self.mir_def.did.to_def_id());
-        let identity_substs = InternalSubsts::identity_for_item(tcx, closure_base_def_id);
+        let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
+        let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
         let fr_substs = match defining_ty {
-            DefiningTy::Closure(_, ref substs) | DefiningTy::Generator(_, ref substs, _) => {
+            DefiningTy::Closure(_, ref substs)
+            | DefiningTy::Generator(_, ref substs, _)
+            | DefiningTy::InlineConst(_, ref substs) => {
                 // In the case of closures, we rely on the fact that
                 // the first N elements in the ClosureSubsts are
-                // inherited from the `closure_base_def_id`.
+                // inherited from the `typeck_root_def_id`.
                 // Therefore, when we zip together (below) with
                 // `identity_substs`, we will get only those regions
                 // that correspond to early-bound regions declared on
-                // the `closure_base_def_id`.
+                // the `typeck_root_def_id`.
                 assert!(substs.len() >= identity_substs.len());
                 assert_eq!(substs.regions().count(), identity_substs.regions().count());
                 substs
@@ -654,6 +671,12 @@ fn compute_inputs_and_output(
                 let ty = indices.fold_to_region_vids(tcx, ty);
                 ty::Binder::dummy(tcx.intern_type_list(&[ty]))
             }
+
+            DefiningTy::InlineConst(def_id, substs) => {
+                assert_eq!(self.mir_def.did.to_def_id(), def_id);
+                let ty = substs.as_inline_const().ty();
+                ty::Binder::dummy(tcx.intern_type_list(&[ty]))
+            }
         }
     }
 }
@@ -742,8 +765,8 @@ fn replace_late_bound_regions_with_nll_infer_vars(
         indices: &mut UniversalRegionIndices<'tcx>,
     ) {
         debug!("replace_late_bound_regions_with_nll_infer_vars(mir_def_id={:?})", mir_def_id);
-        let closure_base_def_id = self.tcx.closure_base_def_id(mir_def_id.to_def_id());
-        for_each_late_bound_region_defined_on(self.tcx, closure_base_def_id, |r| {
+        let typeck_root_def_id = self.tcx.typeck_root_def_id(mir_def_id.to_def_id());
+        for_each_late_bound_region_defined_on(self.tcx, typeck_root_def_id, |r| {
             debug!("replace_late_bound_regions_with_nll_infer_vars: r={:?}", r);
             if !indices.indices.contains_key(&r) {
                 let region_vid = self.next_nll_region_var(FR);
index 198287f608e3973d318d9d4e6e869be0dbd48c26..50127b5b15ce8fc6a87b1f38995b59a69beef96f 100644 (file)
@@ -547,7 +547,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
                 if let Some(snippet) = &template_snippet {
                     if let Some(pos) = snippet.find(needle) {
                         let end = pos
-                            + &snippet[pos..]
+                            + snippet[pos..]
                                 .find(|c| matches!(c, '\n' | ';' | '\\' | '"'))
                                 .unwrap_or(snippet[pos..].len() - 1);
                         let inner = InnerSpan::new(pos, end);
index a225b328ab6a4fc205c260e5bce01e440866384c..994a74a5a9b9f939190f50b3bcfa5184b3f9f4bb 100644 (file)
@@ -557,12 +557,12 @@ fn create_derived_impl(
                     tokens: None,
                 },
                 attrs: Vec::new(),
-                kind: ast::AssocItemKind::TyAlias(Box::new(ast::TyAliasKind(
-                    ast::Defaultness::Final,
-                    Generics::default(),
-                    Vec::new(),
-                    Some(type_def.to_ty(cx, self.span, type_ident, generics)),
-                ))),
+                kind: ast::AssocItemKind::TyAlias(Box::new(ast::TyAlias {
+                    defaultness: ast::Defaultness::Final,
+                    generics: Generics::default(),
+                    bounds: Vec::new(),
+                    ty: Some(type_def.to_ty(cx, self.span, type_ident, generics)),
+                })),
                 tokens: None,
             })
         });
@@ -726,7 +726,7 @@ fn create_derived_impl(
             self.span,
             Ident::empty(),
             a,
-            ast::ItemKind::Impl(Box::new(ast::ImplKind {
+            ast::ItemKind::Impl(Box::new(ast::Impl {
                 unsafety,
                 polarity: ast::ImplPolarity::Positive,
                 defaultness: ast::Defaultness::Final,
@@ -955,7 +955,7 @@ fn create_method(
             decl: fn_decl,
             span: trait_.span,
         };
-        let def = ast::Defaultness::Final;
+        let defaultness = ast::Defaultness::Final;
 
         // Create the method.
         P(ast::AssocItem {
@@ -968,12 +968,12 @@ fn create_method(
                 tokens: None,
             },
             ident: method_ident,
-            kind: ast::AssocItemKind::Fn(Box::new(ast::FnKind(
-                def,
+            kind: ast::AssocItemKind::Fn(Box::new(ast::Fn {
+                defaultness,
                 sig,
-                fn_generics,
-                Some(body_block),
-            ))),
+                generics: fn_generics,
+                body: Some(body_block),
+            })),
             tokens: None,
         })
     }
index fa389a51115782696ef49c9d7a7c860aaab1e624..367a5aa732370a0dff03491b22f151322989206e 100644 (file)
@@ -2,7 +2,7 @@
 
 use rustc_ast as ast;
 use rustc_ast::ptr::P;
-use rustc_ast::{ImplKind, ItemKind, MetaItem};
+use rustc_ast::{Impl, ItemKind, MetaItem};
 use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::Span;
@@ -180,7 +180,7 @@ fn inject_impl_of_structural_trait(
         span,
         Ident::empty(),
         attrs,
-        ItemKind::Impl(Box::new(ImplKind {
+        ItemKind::Impl(Box::new(Impl {
             unsafety: ast::Unsafe::No,
             polarity: ast::ImplPolarity::Positive,
             defaultness: ast::Defaultness::Final,
index f0056cb79766a49f4db2f34a68a81b93c5176063..52b00a2bc74746d9d0fddbe3ff592ebd4f690774 100644 (file)
@@ -760,16 +760,11 @@ fn build_piece(
     /// Actually builds the expression which the format_args! block will be
     /// expanded to.
     fn into_expr(self) -> P<ast::Expr> {
-        let mut locals =
-            Vec::with_capacity((0..self.args.len()).map(|i| self.arg_unique_types[i].len()).sum());
-        let mut counts = Vec::with_capacity(self.count_args.len());
-        let mut pats = Vec::with_capacity(self.args.len());
+        let mut args = Vec::with_capacity(
+            self.arg_unique_types.iter().map(|v| v.len()).sum::<usize>() + self.count_args.len(),
+        );
         let mut heads = Vec::with_capacity(self.args.len());
 
-        let names_pos: Vec<_> = (0..self.args.len())
-            .map(|i| Ident::from_str_and_span(&format!("arg{}", i), self.macsp))
-            .collect();
-
         // First, build up the static array which will become our precompiled
         // format "string"
         let pieces = self.ecx.expr_vec_slice(self.fmtsp, self.str_pieces);
@@ -787,11 +782,8 @@ fn into_expr(self) -> P<ast::Expr> {
         // of each variable because we don't want to move out of the arguments
         // passed to this function.
         for (i, e) in self.args.into_iter().enumerate() {
-            let name = names_pos[i];
-            let span = self.ecx.with_def_site_ctxt(e.span);
-            pats.push(self.ecx.pat_ident(span, name));
             for arg_ty in self.arg_unique_types[i].iter() {
-                locals.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, name));
+                args.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, i));
             }
             heads.push(self.ecx.expr_addr_of(e.span, e));
         }
@@ -800,15 +792,11 @@ fn into_expr(self) -> P<ast::Expr> {
                 Exact(i) => i,
                 _ => panic!("should never happen"),
             };
-            let name = names_pos[index];
             let span = spans_pos[index];
-            counts.push(Context::format_arg(self.ecx, self.macsp, span, &Count, name));
+            args.push(Context::format_arg(self.ecx, self.macsp, span, &Count, index));
         }
 
-        // Now create a vector containing all the arguments
-        let args = locals.into_iter().chain(counts.into_iter());
-
-        let args_array = self.ecx.expr_vec(self.macsp, args.collect());
+        let args_array = self.ecx.expr_vec(self.macsp, args);
 
         // Constructs an AST equivalent to:
         //
@@ -838,7 +826,7 @@ fn into_expr(self) -> P<ast::Expr> {
         // But the nested match expression is proved to perform not as well
         // as series of let's; the first approach does.
         let args_match = {
-            let pat = self.ecx.pat_tuple(self.macsp, pats);
+            let pat = self.ecx.pat_ident(self.macsp, Ident::new(sym::_args, self.macsp));
             let arm = self.ecx.arm(self.macsp, pat, args_array);
             let head = self.ecx.expr(self.macsp, ast::ExprKind::Tup(heads));
             self.ecx.expr_match(self.macsp, head, vec![arm])
@@ -877,10 +865,11 @@ fn format_arg(
         macsp: Span,
         mut sp: Span,
         ty: &ArgumentType,
-        arg: Ident,
+        arg_index: usize,
     ) -> P<ast::Expr> {
         sp = ecx.with_def_site_ctxt(sp);
-        let arg = ecx.expr_ident(sp, arg);
+        let arg = ecx.expr_ident(sp, Ident::new(sym::_args, sp));
+        let arg = ecx.expr(sp, ast::ExprKind::Field(arg, Ident::new(sym::integer(arg_index), sp)));
         let trait_ = match *ty {
             Placeholder(trait_) if trait_ == "<invalid>" => return DummyResult::raw_expr(sp, true),
             Placeholder(trait_) => trait_,
index 3f71ee6f489a08fbbdd1d413f92905f9fe769417..a433876147f8d903edbc8568485649f5eef0cf92 100644 (file)
@@ -5,7 +5,7 @@
 };
 use rustc_ast::ptr::P;
 use rustc_ast::{self as ast, Attribute, Expr, FnHeader, FnSig, Generics, Param, StmtKind};
-use rustc_ast::{FnKind, ItemKind, Mutability, Stmt, Ty, TyKind, Unsafe};
+use rustc_ast::{Fn, ItemKind, Mutability, Stmt, Ty, TyKind, Unsafe};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
@@ -84,13 +84,13 @@ fn allocator_fn(&self, method: &AllocatorMethod) -> Stmt {
         let decl = self.cx.fn_decl(abi_args, ast::FnRetTy::Ty(output_ty));
         let header = FnHeader { unsafety: Unsafe::Yes(self.span), ..FnHeader::default() };
         let sig = FnSig { decl, header, span: self.span };
-        let block = Some(self.cx.block_expr(output_expr));
-        let kind = ItemKind::Fn(Box::new(FnKind(
-            ast::Defaultness::Final,
+        let body = Some(self.cx.block_expr(output_expr));
+        let kind = ItemKind::Fn(Box::new(Fn {
+            defaultness: ast::Defaultness::Final,
             sig,
-            Generics::default(),
-            block,
-        )));
+            generics: Generics::default(),
+            body,
+        }));
         let item = self.cx.item(
             self.span,
             Ident::from_str_and_span(&self.kind.fn_name(method.name), self.span),
index d3e2ed02c32ea2de4e4596372aa5548a808053b2..d1d276930b90aa1c45912cede65d38c9821e72e7 100644 (file)
@@ -11,7 +11,6 @@
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_quote)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 extern crate proc_macro;
 
index bbca07085ea3615043d6b0db868459dc68c39de9..d2629926b51da705f3ae4e1dfbb28b9c1f54911d 100644 (file)
@@ -429,7 +429,7 @@ fn test_type(cx: &ExtCtxt<'_>) -> TestType {
 fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
     let has_should_panic_attr = cx.sess.contains_name(&i.attrs, sym::should_panic);
     let sd = &cx.sess.parse_sess.span_diagnostic;
-    if let ast::ItemKind::Fn(box ast::FnKind(_, ref sig, ref generics, _)) = i.kind {
+    if let ast::ItemKind::Fn(box ast::Fn { ref sig, ref generics, .. }) = i.kind {
         if let ast::Unsafe::Yes(span) = sig.header.unsafety {
             sd.struct_span_err(i.span, "unsafe functions cannot be used for tests")
                 .span_label(span, "`unsafe` because of this")
@@ -478,7 +478,7 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
 }
 
 fn has_bench_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
-    let has_sig = if let ast::ItemKind::Fn(box ast::FnKind(_, ref sig, _, _)) = i.kind {
+    let has_sig = if let ast::ItemKind::Fn(box ast::Fn { ref sig, .. }) = i.kind {
         // N.B., inadequate check, but we're running
         // well before resolve, can't get too deep.
         sig.decl.inputs.len() == 1
index d791677cb8ee1adbd64cd24f9df8aa3fe5aa1c2c..64ccd4331e58a7c3492840e3bba07e8d88452e4b 100644 (file)
@@ -313,13 +313,13 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
 
     let decl = ecx.fn_decl(vec![], ast::FnRetTy::Ty(main_ret_ty));
     let sig = ast::FnSig { decl, header: ast::FnHeader::default(), span: sp };
-    let def = ast::Defaultness::Final;
-    let main = ast::ItemKind::Fn(Box::new(ast::FnKind(
-        def,
+    let defaultness = ast::Defaultness::Final;
+    let main = ast::ItemKind::Fn(Box::new(ast::Fn {
+        defaultness,
         sig,
-        ast::Generics::default(),
-        Some(main_body),
-    )));
+        generics: ast::Generics::default(),
+        body: Some(main_body),
+    }));
 
     // Honor the reexport_test_harness_main attribute
     let main_id = match cx.reexport_test_harness_main {
index 3b77097e9ad00230b058ab0ef63762cb9eabbc96..7c3ed3c5ee9db8d68b0aea669111bd1e9216ad8f 100644 (file)
@@ -118,7 +118,7 @@ fn codegen_llvm_inline_asm(&mut self, _ia: &LlvmInlineAsmInner, _outputs: Vec<Pl
         true
     }
 
-    fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, _span: &[Span]) {
+    fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, _span: &[Span], _instance: Instance<'_>) {
         let asm_arch = self.tcx.sess.asm_arch.unwrap();
         let is_x86 = matches!(asm_arch, InlineAsmArch::X86 | InlineAsmArch::X86_64);
         let att_dialect = is_x86 && options.contains(InlineAsmOptions::ATT_SYNTAX);
index ac908418ee4bf6fcf160a070090705e157c5793c..fff2aa6df7c725ab53bcd2a2c9ba5008c15b72e2 100644 (file)
@@ -915,6 +915,16 @@ fn nonnull_metadata(&mut self, _load: RValue<'gcc>) {
         // TODO(antoyo)
     }
 
+    fn type_metadata(&mut self, _function: RValue<'gcc>, _typeid: String) {
+        // Unsupported.
+    }
+
+    fn typeid_metadata(&mut self, _typeid: String) -> RValue<'gcc> {
+        // Unsupported.
+        self.context.new_rvalue_from_int(self.int_type, 0)
+    }
+
+
     fn store(&mut self, val: RValue<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
         self.store_with_flags(val, ptr, align, MemFlags::empty())
     }
index 375d422cb25c40608565b752f0b555caf54425a4..64bd586662d385a863a45b0bd555d340cda24721 100644 (file)
@@ -367,6 +367,11 @@ fn sideeffect(&mut self) {
         // TODO(antoyo)
     }
 
+    fn type_test(&mut self, _pointer: Self::Value, _typeid: Self::Value) -> Self::Value {
+        // Unsupported.
+        self.context.new_rvalue_from_int(self.int_type, 0)
+    }
+
     fn va_start(&mut self, _va_list: RValue<'gcc>) -> RValue<'gcc> {
         unimplemented!();
     }
index dca9c1f04d3c0fd40672c6babd21295aeb89473b..bedd3523d899e89f0f8205c28b72ad7e03307c17 100644 (file)
@@ -1,7 +1,6 @@
 use crate::builder::Builder;
 use crate::context::CodegenCx;
 use crate::llvm::{self, AttributePlace};
-use crate::llvm_util;
 use crate::type_::Type;
 use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
@@ -53,15 +52,10 @@ fn apply_attrs_to_callsite(
 }
 
 fn should_use_mutable_noalias(cx: &CodegenCx<'_, '_>) -> bool {
-    // LLVM prior to version 12 has known miscompiles in the presence of
-    // noalias attributes (see #54878). Only enable mutable noalias by
-    // default for versions we believe to be safe.
-    cx.tcx
-        .sess
-        .opts
-        .debugging_opts
-        .mutable_noalias
-        .unwrap_or_else(|| llvm_util::get_version() >= (12, 0, 0))
+    // LLVM prior to version 12 had known miscompiles in the presence of
+    // noalias attributes (see #54878), but we don't support earlier
+    // versions at all anymore. We now enable mutable noalias by default.
+    cx.tcx.sess.opts.debugging_opts.mutable_noalias.unwrap_or(true)
 }
 
 impl ArgAttributesExt for ArgAttributes {
index 341a88824169847f23948d40631592e7f992cf27..f128f76958092214e70afad072253c0aff55054e 100644 (file)
@@ -13,7 +13,7 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
 use rustc_middle::ty::layout::TyAndLayout;
-use rustc_middle::{bug, span_bug};
+use rustc_middle::{bug, span_bug, ty::Instance};
 use rustc_span::{Pos, Span, Symbol};
 use rustc_target::abi::*;
 use rustc_target::asm::*;
@@ -120,6 +120,7 @@ fn codegen_inline_asm(
         operands: &[InlineAsmOperandRef<'tcx, Self>],
         options: InlineAsmOptions,
         line_spans: &[Span],
+        instance: Instance<'_>,
     ) {
         let asm_arch = self.tcx.sess.asm_arch.unwrap();
 
@@ -135,7 +136,10 @@ fn codegen_inline_asm(
                     let is_target_supported = |reg_class: InlineAsmRegClass| {
                         for &(_, feature) in reg_class.supported_types(asm_arch) {
                             if let Some(feature) = feature {
-                                if self.tcx.sess.target_features.contains(&Symbol::intern(feature))
+                                let codegen_fn_attrs = self.tcx.codegen_fn_attrs(instance.def_id());
+                                let feature_name = Symbol::intern(feature);
+                                if self.tcx.sess.target_features.contains(&feature_name)
+                                    || codegen_fn_attrs.target_features.contains(&feature_name)
                                 {
                                     return true;
                                 }
index 380dfd387235d1b6037c193db8aefdf8a7d7aa22..6187dbf4d1b5599428e3d7f4a3100a057afe49fb 100644 (file)
@@ -161,6 +161,7 @@ pub fn target_machine_factory(
     let ffunction_sections =
         sess.opts.debugging_opts.function_sections.unwrap_or(sess.target.function_sections);
     let fdata_sections = ffunction_sections;
+    let funique_section_names = !sess.opts.debugging_opts.no_unique_section_names;
 
     let code_model = to_llvm_code_model(sess.code_model());
 
@@ -205,6 +206,7 @@ pub fn target_machine_factory(
                 use_softfp,
                 ffunction_sections,
                 fdata_sections,
+                funique_section_names,
                 trap_unreachable,
                 singlethread,
                 asm_comments,
@@ -284,7 +286,7 @@ fn report_inline_asm(
         cookie = 0;
     }
     let level = match level {
-        llvm::DiagnosticLevel::Error => Level::Error,
+        llvm::DiagnosticLevel::Error => Level::Error { lint: false },
         llvm::DiagnosticLevel::Warning => Level::Warning,
         llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note,
     };
index d5deacf3811304c972fb0cc5919b833c23ac0f97..6c74163fb496c18bf33923b9c2fc0c5f949a2e30 100644 (file)
@@ -604,6 +604,32 @@ fn nonnull_metadata(&mut self, load: &'ll Value) {
         }
     }
 
+    fn type_metadata(&mut self, function: &'ll Value, typeid: String) {
+        let typeid_metadata = self.typeid_metadata(typeid);
+        let v = [self.const_usize(0), typeid_metadata];
+        unsafe {
+            llvm::LLVMGlobalSetMetadata(
+                function,
+                llvm::MD_type as c_uint,
+                llvm::LLVMValueAsMetadata(llvm::LLVMMDNodeInContext(
+                    self.cx.llcx,
+                    v.as_ptr(),
+                    v.len() as c_uint,
+                )),
+            )
+        }
+    }
+
+    fn typeid_metadata(&mut self, typeid: String) -> Self::Value {
+        unsafe {
+            llvm::LLVMMDStringInContext(
+                self.cx.llcx,
+                typeid.as_ptr() as *const c_char,
+                typeid.as_bytes().len() as c_uint,
+            )
+        }
+    }
+
     fn store(&mut self, val: &'ll Value, ptr: &'ll Value, align: Align) -> &'ll Value {
         self.store_with_flags(val, ptr, align, MemFlags::empty())
     }
@@ -705,7 +731,7 @@ fn sext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
     }
 
     fn fptoui_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> {
-        if llvm_util::get_version() >= (12, 0, 0) && !self.fptoint_sat_broken_in_llvm() {
+        if !self.fptoint_sat_broken_in_llvm() {
             let src_ty = self.cx.val_ty(val);
             let float_width = self.cx.float_width(src_ty);
             let int_width = self.cx.int_width(dest_ty);
@@ -717,7 +743,7 @@ fn fptoui_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Val
     }
 
     fn fptosi_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> {
-        if llvm_util::get_version() >= (12, 0, 0) && !self.fptoint_sat_broken_in_llvm() {
+        if !self.fptoint_sat_broken_in_llvm() {
             let src_ty = self.cx.val_ty(val);
             let float_width = self.cx.float_width(src_ty);
             let int_width = self.cx.int_width(dest_ty);
index 257a0ac89d86ffff881fd814b631841fba8d26dc..1dba264a9614a32a5ae9fa62dce679a1d3fc5318 100644 (file)
@@ -134,9 +134,6 @@ pub unsafe fn create_module(
     let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
 
     let mut target_data_layout = sess.target.data_layout.clone();
-    if llvm_util::get_version() < (12, 0, 0) && sess.target.arch == "powerpc64" {
-        target_data_layout = target_data_layout.replace("-v256:256:256-v512:512:512", "");
-    }
     if llvm_util::get_version() < (13, 0, 0) {
         if sess.target.arch == "powerpc64" {
             target_data_layout = target_data_layout.replace("-S128", "");
@@ -221,6 +218,15 @@ pub unsafe fn create_module(
         llvm::LLVMRustAddModuleFlag(llmod, avoid_plt, 1);
     }
 
+    if sess.is_sanitizer_cfi_enabled() {
+        // FIXME(rcvalle): Add support for non canonical jump tables.
+        let canonical_jump_tables = "CFI Canonical Jump Tables\0".as_ptr().cast();
+        // FIXME(rcvalle): Add it with Override behavior flag--LLVMRustAddModuleFlag adds it with
+        // Warning behavior flag. Add support for specifying the behavior flag to
+        // LLVMRustAddModuleFlag.
+        llvm::LLVMRustAddModuleFlag(llmod, canonical_jump_tables, 1);
+    }
+
     // Control Flow Guard is currently only supported by the MSVC linker on Windows.
     if sess.target.is_like_msvc {
         match sess.opts.cg.control_flow_guard {
@@ -779,6 +785,8 @@ macro_rules! mk_struct {
             ifn!("llvm.instrprof.increment", fn(i8p, t_i64, t_i32, t_i32) -> void);
         }
 
+        ifn!("llvm.type.test", fn(i8p, self.type_metadata()) -> i1);
+
         if self.sess().opts.debuginfo != DebugInfo::None {
             ifn!("llvm.dbg.declare", fn(self.type_metadata(), self.type_metadata()) -> void);
             ifn!("llvm.dbg.value", fn(self.type_metadata(), t_i64, self.type_metadata()) -> void);
index 1f1bd73c7d035d51ae736dae5bfde264980b1d0a..2a6bf7d9b1a4ddac535843a25a4c2e052bd79ac1 100644 (file)
@@ -322,7 +322,7 @@ fn dbg_scope_fn(
         type_names::push_item_name(self.tcx(), def_id, false, &mut name);
 
         // Find the enclosing function, in case this is a closure.
-        let enclosing_fn_def_id = self.tcx().closure_base_def_id(def_id);
+        let enclosing_fn_def_id = self.tcx().typeck_root_def_id(def_id);
 
         // Get_template_parameters() will append a `<...>` clause to the function
         // name if necessary.
index c43141c769519c790311e3b456f57463598030c1..e63fb22829a3f5b9789f3ab4f95a54ec1e97a404 100644 (file)
@@ -401,6 +401,14 @@ fn sideeffect(&mut self) {
         }
     }
 
+    fn type_test(&mut self, pointer: Self::Value, typeid: Self::Value) -> Self::Value {
+        // Test the called operand using llvm.type.test intrinsic. The LowerTypeTests link-time
+        // optimization pass replaces calls to this intrinsic with code to test type membership.
+        let i8p_ty = self.type_i8p();
+        let bitcast = self.bitcast(pointer, i8p_ty);
+        self.call_intrinsic("llvm.type.test", &[bitcast, typeid])
+    }
+
     fn va_start(&mut self, va_list: &'ll Value) -> &'ll Value {
         self.call_intrinsic("llvm.va_start", &[va_list])
     }
index f1dacc393d53b6c9a49813ba4c9d8e252dfc399a..64fedb7bc1a5cbb7b20559e67dd126d563a9e403 100644 (file)
@@ -13,7 +13,6 @@
 #![feature(iter_zip)]
 #![feature(nll)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 use back::write::{create_informational_target_machine, create_target_machine};
 
@@ -77,6 +76,27 @@ pub mod llvm {
 #[derive(Clone)]
 pub struct LlvmCodegenBackend(());
 
+struct TimeTraceProfiler {
+    enabled: bool,
+}
+
+impl TimeTraceProfiler {
+    fn new(enabled: bool) -> Self {
+        if enabled {
+            unsafe { llvm::LLVMTimeTraceProfilerInitialize() }
+        }
+        TimeTraceProfiler { enabled }
+    }
+}
+
+impl Drop for TimeTraceProfiler {
+    fn drop(&mut self) {
+        if self.enabled {
+            unsafe { llvm::LLVMTimeTraceProfilerFinishThread() }
+        }
+    }
+}
+
 impl ExtraBackendMethods for LlvmCodegenBackend {
     fn new_metadata(&self, tcx: TyCtxt<'_>, mod_name: &str) -> ModuleLlvm {
         ModuleLlvm::new_metadata(tcx, mod_name)
@@ -120,6 +140,34 @@ fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str {
     fn tune_cpu<'b>(&self, sess: &'b Session) -> Option<&'b str> {
         llvm_util::tune_cpu(sess)
     }
+
+    fn spawn_thread<F, T>(time_trace: bool, f: F) -> std::thread::JoinHandle<T>
+    where
+        F: FnOnce() -> T,
+        F: Send + 'static,
+        T: Send + 'static,
+    {
+        std::thread::spawn(move || {
+            let _profiler = TimeTraceProfiler::new(time_trace);
+            f()
+        })
+    }
+
+    fn spawn_named_thread<F, T>(
+        time_trace: bool,
+        name: String,
+        f: F,
+    ) -> std::io::Result<std::thread::JoinHandle<T>>
+    where
+        F: FnOnce() -> T,
+        F: Send + 'static,
+        T: Send + 'static,
+    {
+        std::thread::Builder::new().name(name).spawn(move || {
+            let _profiler = TimeTraceProfiler::new(time_trace);
+            f()
+        })
+    }
 }
 
 impl WriteBackendMethods for LlvmCodegenBackend {
index 4c9ae4faf7233f4a1e88ed043eecb73d630b901a..749eec459aca1334be2f17da146280b6cb3fcc5c 100644 (file)
@@ -416,6 +416,7 @@ pub enum MetadataType {
     MD_nontemporal = 9,
     MD_mem_parallel_loop_access = 10,
     MD_nonnull = 11,
+    MD_type = 19,
 }
 
 /// LLVMRustAsmDialect
@@ -1002,6 +1003,8 @@ pub fn LLVMStructTypeInContext(
     pub fn LLVMSetValueName2(Val: &Value, Name: *const c_char, NameLen: size_t);
     pub fn LLVMReplaceAllUsesWith(OldVal: &'a Value, NewVal: &'a Value);
     pub fn LLVMSetMetadata(Val: &'a Value, KindID: c_uint, Node: &'a Value);
+    pub fn LLVMGlobalSetMetadata(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata);
+    pub fn LLVMValueAsMetadata(Node: &'a Value) -> &Metadata;
 
     // Operations on constants of any type
     pub fn LLVMConstNull(Ty: &Type) -> &Value;
@@ -1734,6 +1737,8 @@ pub fn LLVMRustBuildAtomicFence(
 
     pub fn LLVMTimeTraceProfilerInitialize();
 
+    pub fn LLVMTimeTraceProfilerFinishThread();
+
     pub fn LLVMTimeTraceProfilerFinish(FileName: *const c_char);
 
     pub fn LLVMAddAnalysisPasses(T: &'a TargetMachine, PM: &PassManager<'a>);
@@ -1770,7 +1775,7 @@ pub fn LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
 
     pub fn LLVMDisposeMessage(message: *mut c_char);
 
-    pub fn LLVMStartMultithreaded() -> Bool;
+    pub fn LLVMIsMultithreaded() -> Bool;
 
     /// Returns a string describing the last error caused by an LLVMRust* call.
     pub fn LLVMRustGetLastError() -> *const c_char;
@@ -2187,6 +2192,7 @@ pub fn LLVMRustCreateTargetMachine(
         UseSoftFP: bool,
         FunctionSections: bool,
         DataSections: bool,
+        UniqueSectionNames: bool,
         TrapUnreachable: bool,
         Singlethread: bool,
         AsmComments: bool,
index 4e4487ad88cebd2eb6eb5c17144348bb19a3654d..c3e7e7169a92c913934c223b7dfc60a522753a25 100644 (file)
 use std::ptr;
 use std::slice;
 use std::str;
-use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::Once;
 
-static POISONED: AtomicBool = AtomicBool::new(false);
 static INIT: Once = Once::new();
 
 pub(crate) fn init(sess: &Session) {
     unsafe {
         // Before we touch LLVM, make sure that multithreading is enabled.
+        if llvm::LLVMIsMultithreaded() != 1 {
+            bug!("LLVM compiled without support for threads");
+        }
         INIT.call_once(|| {
-            if llvm::LLVMStartMultithreaded() != 1 {
-                // use an extra bool to make sure that all future usage of LLVM
-                // cannot proceed despite the Once not running more than once.
-                POISONED.store(true, Ordering::SeqCst);
-            }
-
             configure_llvm(sess);
         });
-
-        if POISONED.load(Ordering::SeqCst) {
-            bug!("couldn't enable multi-threaded LLVM");
-        }
     }
 }
 
 fn require_inited() {
-    INIT.call_once(|| bug!("llvm is not initialized"));
-    if POISONED.load(Ordering::SeqCst) {
-        bug!("couldn't enable multi-threaded LLVM");
+    if !INIT.is_completed() {
+        bug!("LLVM is not initialized");
     }
 }
 
@@ -123,11 +113,6 @@ fn llvm_arg_to_arg_name(full_arg: &str) -> &str {
     }
 
     if sess.opts.debugging_opts.llvm_time_trace {
-        // time-trace is not thread safe and running it in parallel will cause seg faults.
-        if !sess.opts.debugging_opts.no_parallel_llvm {
-            bug!("`-Z llvm-time-trace` requires `-Z no-parallel-llvm")
-        }
-
         llvm::LLVMTimeTraceProfilerInitialize();
     }
 
@@ -190,6 +175,7 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> Vec<&'a str> {
         ("aarch64", "dpb2") => vec!["ccdp"],
         ("aarch64", "frintts") => vec!["fptoint"],
         ("aarch64", "fcma") => vec!["complxnum"],
+        ("aarch64", "pmuv3") => vec!["perfmon"],
         (_, s) => vec![s],
     }
 }
@@ -415,11 +401,6 @@ pub fn llvm_global_features(sess: &Session) -> Vec<String> {
     // -Ctarget-features
     features.extend(sess.opts.cg.target_feature.split(',').flat_map(&filter));
 
-    // FIXME: Move outline-atomics to target definition when earliest supported LLVM is 12.
-    if get_version() >= (12, 0, 0) && sess.target.llvm_target.contains("aarch64-unknown-linux") {
-        features.push("+outline-atomics".to_string());
-    }
-
     features
 }
 
index be50911f4e143a8b5cb91fc4e0c8d344c9600982..6c02543bd7cc4fc49c04e6b83c638bcff386546a 100644 (file)
@@ -1095,10 +1095,10 @@ fn add_sanitizer_libraries(sess: &Session, crate_type: CrateType, linker: &mut d
 }
 
 fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) {
-    fn find_sanitizer_runtime(sess: &Session, filename: &String) -> PathBuf {
+    fn find_sanitizer_runtime(sess: &Session, filename: &str) -> PathBuf {
         let session_tlib =
             filesearch::make_target_lib_path(&sess.sysroot, sess.opts.target_triple.triple());
-        let path = session_tlib.join(&filename);
+        let path = session_tlib.join(filename);
         if path.exists() {
             return session_tlib;
         } else {
index 4a7090b31b4a9d8bc99247d24866a229563de40a..f80f9965f4d8acd0c651fb0a74dbf867abafa8ad 100644 (file)
@@ -11,7 +11,7 @@
 use rustc_middle::middle::exported_symbols::{
     metadata_symbol_name, ExportedSymbol, SymbolExportLevel,
 };
-use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::query::{ExternProviders, Providers};
 use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
 use rustc_middle::ty::Instance;
 use rustc_middle::ty::{SymbolName, TyCtxt};
@@ -363,7 +363,7 @@ pub fn provide(providers: &mut Providers) {
     providers.wasm_import_module_map = wasm_import_module_map;
 }
 
-pub fn provide_extern(providers: &mut Providers) {
+pub fn provide_extern(providers: &mut ExternProviders) {
     providers.is_reachable_non_generic = is_reachable_non_generic_provider_extern;
     providers.upstream_monomorphizations_for = upstream_monomorphizations_for_provider;
 }
index da34612ce76acb274b996feb2538efb03e49eb92..85d51ea9a207b1cfebe505d9203ee53e55dc9a35 100644 (file)
@@ -310,6 +310,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
     pub no_landing_pads: bool,
     pub save_temps: bool,
     pub fewer_names: bool,
+    pub time_trace: bool,
     pub exported_symbols: Option<Arc<ExportedSymbols>>,
     pub opts: Arc<config::Options>,
     pub crate_types: Vec<CrateType>,
@@ -1039,6 +1040,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
         no_landing_pads: sess.panic_strategy() == PanicStrategy::Abort,
         fewer_names: sess.fewer_names(),
         save_temps: sess.opts.cg.save_temps,
+        time_trace: sess.opts.debugging_opts.llvm_time_trace,
         opts: Arc::new(sess.opts.clone()),
         prof: sess.prof.clone(),
         exported_symbols,
@@ -1198,7 +1200,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
     // Each LLVM module is automatically sent back to the coordinator for LTO if
     // necessary. There's already optimizations in place to avoid sending work
     // back to the coordinator if LTO isn't requested.
-    return thread::spawn(move || {
+    return B::spawn_thread(cgcx.time_trace, move || {
         let mut worker_id_counter = 0;
         let mut free_worker_ids = Vec::new();
         let mut get_worker_id = |free_worker_ids: &mut Vec<usize>| {
@@ -1615,59 +1617,57 @@ fn maybe_start_llvm_timer<'a>(
 pub struct WorkerFatalError;
 
 fn spawn_work<B: ExtraBackendMethods>(cgcx: CodegenContext<B>, work: WorkItem<B>) {
-    let builder = thread::Builder::new().name(work.short_description());
-    builder
-        .spawn(move || {
-            // Set up a destructor which will fire off a message that we're done as
-            // we exit.
-            struct Bomb<B: ExtraBackendMethods> {
-                coordinator_send: Sender<Box<dyn Any + Send>>,
-                result: Option<Result<WorkItemResult<B>, FatalError>>,
-                worker_id: usize,
-            }
-            impl<B: ExtraBackendMethods> Drop for Bomb<B> {
-                fn drop(&mut self) {
-                    let worker_id = self.worker_id;
-                    let msg = match self.result.take() {
-                        Some(Ok(WorkItemResult::Compiled(m))) => {
-                            Message::Done::<B> { result: Ok(m), worker_id }
-                        }
-                        Some(Ok(WorkItemResult::NeedsLink(m))) => {
-                            Message::NeedsLink::<B> { module: m, worker_id }
-                        }
-                        Some(Ok(WorkItemResult::NeedsFatLTO(m))) => {
-                            Message::NeedsFatLTO::<B> { result: m, worker_id }
-                        }
-                        Some(Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer))) => {
-                            Message::NeedsThinLTO::<B> { name, thin_buffer, worker_id }
-                        }
-                        Some(Err(FatalError)) => {
-                            Message::Done::<B> { result: Err(Some(WorkerFatalError)), worker_id }
-                        }
-                        None => Message::Done::<B> { result: Err(None), worker_id },
-                    };
-                    drop(self.coordinator_send.send(Box::new(msg)));
-                }
+    B::spawn_named_thread(cgcx.time_trace, work.short_description(), move || {
+        // Set up a destructor which will fire off a message that we're done as
+        // we exit.
+        struct Bomb<B: ExtraBackendMethods> {
+            coordinator_send: Sender<Box<dyn Any + Send>>,
+            result: Option<Result<WorkItemResult<B>, FatalError>>,
+            worker_id: usize,
+        }
+        impl<B: ExtraBackendMethods> Drop for Bomb<B> {
+            fn drop(&mut self) {
+                let worker_id = self.worker_id;
+                let msg = match self.result.take() {
+                    Some(Ok(WorkItemResult::Compiled(m))) => {
+                        Message::Done::<B> { result: Ok(m), worker_id }
+                    }
+                    Some(Ok(WorkItemResult::NeedsLink(m))) => {
+                        Message::NeedsLink::<B> { module: m, worker_id }
+                    }
+                    Some(Ok(WorkItemResult::NeedsFatLTO(m))) => {
+                        Message::NeedsFatLTO::<B> { result: m, worker_id }
+                    }
+                    Some(Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer))) => {
+                        Message::NeedsThinLTO::<B> { name, thin_buffer, worker_id }
+                    }
+                    Some(Err(FatalError)) => {
+                        Message::Done::<B> { result: Err(Some(WorkerFatalError)), worker_id }
+                    }
+                    None => Message::Done::<B> { result: Err(None), worker_id },
+                };
+                drop(self.coordinator_send.send(Box::new(msg)));
             }
+        }
 
-            let mut bomb = Bomb::<B> {
-                coordinator_send: cgcx.coordinator_send.clone(),
-                result: None,
-                worker_id: cgcx.worker,
-            };
+        let mut bomb = Bomb::<B> {
+            coordinator_send: cgcx.coordinator_send.clone(),
+            result: None,
+            worker_id: cgcx.worker,
+        };
 
-            // Execute the work itself, and if it finishes successfully then flag
-            // ourselves as a success as well.
-            //
-            // Note that we ignore any `FatalError` coming out of `execute_work_item`,
-            // as a diagnostic was already sent off to the main thread - just
-            // surface that there was an error in this worker.
-            bomb.result = {
-                let _prof_timer = work.start_profiling(&cgcx);
-                Some(execute_work_item(&cgcx, work))
-            };
-        })
-        .expect("failed to spawn thread");
+        // Execute the work itself, and if it finishes successfully then flag
+        // ourselves as a success as well.
+        //
+        // Note that we ignore any `FatalError` coming out of `execute_work_item`,
+        // as a diagnostic was already sent off to the main thread - just
+        // surface that there was an error in this worker.
+        bomb.result = {
+            let _prof_timer = work.start_profiling(&cgcx);
+            Some(execute_work_item(&cgcx, work))
+        };
+    })
+    .expect("failed to spawn thread");
 }
 
 enum SharedEmitterMessage {
@@ -1757,7 +1757,7 @@ pub fn check(&self, sess: &Session, blocking: bool) {
                     let msg = msg.strip_prefix("error: ").unwrap_or(&msg);
 
                     let mut err = match level {
-                        Level::Error => sess.struct_err(&msg),
+                        Level::Error { lint: false } => sess.struct_err(&msg),
                         Level::Warning => sess.struct_warn(&msg),
                         Level::Note => sess.struct_note_without_error(&msg),
                         _ => bug!("Invalid inline asm diagnostic level"),
index accb54e464553292fcd567093f4743a4fa453122..ab119ae25f5e89d496b69388ce65ab9058b4131b 100644 (file)
@@ -124,10 +124,7 @@ fn push_debuginfo_type_name<'tcx>(
             // info for MSVC debugger. However, wrapping these types' names in a synthetic type
             // causes the .natvis engine for WinDbg to fail to display their data, so we opt these
             // types out to aid debugging in MSVC.
-            let is_slice_or_str = match *inner_type.kind() {
-                ty::Slice(_) | ty::Str => true,
-                _ => false,
-            };
+            let is_slice_or_str = matches!(*inner_type.kind(), ty::Slice(_) | ty::Str);
 
             if !cpp_like_names {
                 output.push('&');
index 9f3c2f0c7ce30d803e8e501c06b22e637d3a971a..4c87d4d896e2ec8129362eb05464504d68108a26 100644 (file)
@@ -8,7 +8,6 @@
 #![feature(nll)]
 #![feature(associated_type_bounds)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 //! This crate contains codegen code that is used by all codegen backends (LLVM and others).
 //! The backend-agnostic functions of this crate use functions defined in various traits that
@@ -28,7 +27,7 @@
 use rustc_hir::LangItem;
 use rustc_middle::dep_graph::WorkProduct;
 use rustc_middle::middle::dependency_format::Dependencies;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::query::{ExternProviders, Providers};
 use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
 use rustc_session::cstore::{self, CrateSource};
 use rustc_session::utils::NativeLibKind;
@@ -170,7 +169,7 @@ pub fn provide(providers: &mut Providers) {
     crate::target_features::provide(providers);
 }
 
-pub fn provide_extern(providers: &mut Providers) {
+pub fn provide_extern(providers: &mut ExternProviders) {
     crate::back::symbol_export::provide_extern(providers);
 }
 
index b0a5631549df85af3bd872d04f00fd6bac9a84b7..a9471f7b7716052c60f0228c13bfd793c1c52361 100644 (file)
@@ -19,6 +19,7 @@
 use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
 use rustc_span::source_map::Span;
 use rustc_span::{sym, Symbol};
+use rustc_symbol_mangling::typeid_for_fnabi;
 use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode};
 use rustc_target::abi::{self, HasDataLayout, WrappingRange};
 use rustc_target::spec::abi::Abi;
@@ -818,12 +819,43 @@ fn codegen_call_terminator(
             self.codegen_argument(&mut bx, location, &mut llargs, last_arg);
         }
 
-        let fn_ptr = match (llfn, instance) {
-            (Some(llfn), _) => llfn,
-            (None, Some(instance)) => bx.get_fn_addr(instance),
+        let (is_indirect_call, fn_ptr) = match (llfn, instance) {
+            (Some(llfn), _) => (true, llfn),
+            (None, Some(instance)) => (false, bx.get_fn_addr(instance)),
             _ => span_bug!(span, "no llfn for call"),
         };
 
+        // For backends that support CFI using type membership (i.e., testing whether a given
+        // pointer is associated with a type identifier).
+        if bx.tcx().sess.is_sanitizer_cfi_enabled() && is_indirect_call {
+            // Emit type metadata and checks.
+            // FIXME(rcvalle): Add support for generalized identifiers.
+            // FIXME(rcvalle): Create distinct unnamed MDNodes for internal identifiers.
+            let typeid = typeid_for_fnabi(bx.tcx(), fn_abi);
+            let typeid_metadata = bx.typeid_metadata(typeid);
+
+            // Test whether the function pointer is associated with the type identifier.
+            let cond = bx.type_test(fn_ptr, typeid_metadata);
+            let mut bx_pass = bx.build_sibling_block("type_test.pass");
+            let mut bx_fail = bx.build_sibling_block("type_test.fail");
+            bx.cond_br(cond, bx_pass.llbb(), bx_fail.llbb());
+
+            helper.do_call(
+                self,
+                &mut bx_pass,
+                fn_abi,
+                fn_ptr,
+                &llargs,
+                destination.as_ref().map(|&(_, target)| (ret_dest, target)),
+                cleanup,
+            );
+
+            bx_fail.abort();
+            bx_fail.unreachable();
+
+            return;
+        }
+
         helper.do_call(
             self,
             &mut bx,
@@ -845,6 +877,7 @@ fn codegen_asm_terminator(
         options: ast::InlineAsmOptions,
         line_spans: &[Span],
         destination: Option<mir::BasicBlock>,
+        instance: Instance<'_>,
     ) {
         let span = terminator.source_info.span;
 
@@ -898,7 +931,7 @@ fn codegen_asm_terminator(
             })
             .collect();
 
-        bx.codegen_inline_asm(template, &operands, options, line_spans);
+        bx.codegen_inline_asm(template, &operands, options, line_spans, instance);
 
         if let Some(target) = destination {
             helper.funclet_br(self, &mut bx, target);
@@ -1029,6 +1062,7 @@ fn codegen_terminator(
                     options,
                     line_spans,
                     destination,
+                    self.instance,
                 );
             }
         }
index 476ddbd93980ca76565fd2d9579fa0c3fc80bc5b..1ef863e84af7fe757b691c6fb0167bcda350f489 100644 (file)
@@ -4,6 +4,7 @@
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout};
 use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
+use rustc_symbol_mangling::typeid_for_fnabi;
 use rustc_target::abi::call::{FnAbi, PassMode};
 
 use std::iter;
@@ -244,6 +245,13 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     for (bb, _) in traversal::reverse_postorder(&mir) {
         fx.codegen_block(bb);
     }
+
+    // For backends that support CFI using type membership (i.e., testing whether a given  pointer
+    // is associated with a type identifier).
+    if cx.tcx().sess.is_sanitizer_cfi_enabled() {
+        let typeid = typeid_for_fnabi(cx.tcx(), fn_abi);
+        bx.type_metadata(llfn, typeid);
+    }
 }
 
 /// Produces, for each argument, a `Value` pointing at the
index fe7f6288adb273913a8545f0ee4160d54395a244..2c96987d3399eb63f25d0a32ca0db16f3d5c4492 100644 (file)
@@ -125,7 +125,7 @@ pub fn codegen_statement(&mut self, mut bx: Bx, statement: &mir::Statement<'tcx>
                 let count = self.codegen_operand(&mut bx, count).immediate();
                 let pointee_layout = dst_val
                     .layout
-                    .pointee_info_at(&mut bx, rustc_target::abi::Size::ZERO)
+                    .pointee_info_at(&bx, rustc_target::abi::Size::ZERO)
                     .expect("Expected pointer");
                 let bytes = bx.mul(count, bx.const_usize(pointee_layout.size.bytes()));
 
index 8d7e9612f4749d63c0fbb9e6388520627ac85374..b4420df5df417a67196e3b4c70c7013449ea2cff 100644 (file)
@@ -19,6 +19,8 @@
     ("crypto", Some(sym::arm_target_feature)),
     ("aes", Some(sym::arm_target_feature)),
     ("sha2", Some(sym::arm_target_feature)),
+    ("i8mm", Some(sym::arm_target_feature)),
+    ("dotprod", Some(sym::arm_target_feature)),
     ("v5te", Some(sym::arm_target_feature)),
     ("v6", Some(sym::arm_target_feature)),
     ("v6k", Some(sym::arm_target_feature)),
@@ -35,7 +37,6 @@
     ("thumb-mode", Some(sym::arm_target_feature)),
 ];
 
-// Commented features are not available in LLVM 10.0, or have since been renamed
 const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     // FEAT_AdvSimd
     ("neon", Some(sym::aarch64_target_feature)),
     // FEAT_DIT
     ("dit", Some(sym::aarch64_target_feature)),
     // FEAT_FLAGM
-    // ("flagm", Some(sym::aarch64_target_feature)),
+    ("flagm", Some(sym::aarch64_target_feature)),
     // FEAT_SSBS
     ("ssbs", Some(sym::aarch64_target_feature)),
     // FEAT_SB
     ("sb", Some(sym::aarch64_target_feature)),
     // FEAT_PAUTH
-    // ("pauth", Some(sym::aarch64_target_feature)),
+    ("pauth", Some(sym::aarch64_target_feature)),
     // FEAT_DPB
     ("dpb", Some(sym::aarch64_target_feature)),
     // FEAT_DPB2
     // FEAT_FRINTTS
     ("frintts", Some(sym::aarch64_target_feature)),
     // FEAT_I8MM
-    // ("i8mm", Some(sym::aarch64_target_feature)),
+    ("i8mm", Some(sym::aarch64_target_feature)),
     // FEAT_F32MM
-    // ("f32mm", Some(sym::aarch64_target_feature)),
+    ("f32mm", Some(sym::aarch64_target_feature)),
     // FEAT_F64MM
-    // ("f64mm", Some(sym::aarch64_target_feature)),
+    ("f64mm", Some(sym::aarch64_target_feature)),
     // FEAT_BF16
-    // ("bf16", Some(sym::aarch64_target_feature)),
+    ("bf16", Some(sym::aarch64_target_feature)),
     // FEAT_RAND
     ("rand", Some(sym::aarch64_target_feature)),
     // FEAT_BTI
     ("sha3", Some(sym::aarch64_target_feature)),
     // FEAT_SM3 & FEAT_SM4
     ("sm4", Some(sym::aarch64_target_feature)),
+    // FEAT_PAN
+    ("pan", Some(sym::aarch64_target_feature)),
+    // FEAT_LOR
+    ("lor", Some(sym::aarch64_target_feature)),
+    // FEAT_VHE
+    ("vh", Some(sym::aarch64_target_feature)),
+    // FEAT_PMUv3
+    ("pmuv3", Some(sym::aarch64_target_feature)),
+    // FEAT_SPE
+    ("spe", Some(sym::aarch64_target_feature)),
     ("v8.1a", Some(sym::aarch64_target_feature)),
     ("v8.2a", Some(sym::aarch64_target_feature)),
     ("v8.3a", Some(sym::aarch64_target_feature)),
     ("v8.4a", Some(sym::aarch64_target_feature)),
     ("v8.5a", Some(sym::aarch64_target_feature)),
-    // ("v8.6a", Some(sym::aarch64_target_feature)),
-    // ("v8.7a", Some(sym::aarch64_target_feature)),
+    ("v8.6a", Some(sym::aarch64_target_feature)),
+    ("v8.7a", Some(sym::aarch64_target_feature)),
 ];
 
 const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
index 86f2781a7663b6a605c06764e75a4c0e26aa055b..31f539e1b03dba8f3cdeb548e3f91ca2dff0c477 100644 (file)
@@ -58,6 +58,7 @@ fn codegen_inline_asm(
         operands: &[InlineAsmOperandRef<'tcx, Self>],
         options: InlineAsmOptions,
         line_spans: &[Span],
+        instance: Instance<'_>,
     );
 }
 
index 8129a14fcfdc965b844074c9c9220fb1c3d99225..9c8bc3b2109881be537bd36682c4cc80cab8adb5 100644 (file)
@@ -9,7 +9,7 @@
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
 use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf, TyAndLayout};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::query::{ExternProviders, Providers};
 use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_session::{
     config::{self, OutputFilenames, PrintRequest},
@@ -80,7 +80,7 @@ fn metadata_loader(&self) -> Box<MetadataLoaderDyn> {
     }
 
     fn provide(&self, _providers: &mut Providers) {}
-    fn provide_extern(&self, _providers: &mut Providers) {}
+    fn provide_extern(&self, _providers: &mut ExternProviders) {}
     fn codegen_crate<'tcx>(
         &self,
         tcx: TyCtxt<'tcx>,
@@ -142,4 +142,26 @@ fn target_machine_factory(
     ) -> TargetMachineFactoryFn<Self>;
     fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str;
     fn tune_cpu<'b>(&self, sess: &'b Session) -> Option<&'b str>;
+
+    fn spawn_thread<F, T>(_time_trace: bool, f: F) -> std::thread::JoinHandle<T>
+    where
+        F: FnOnce() -> T,
+        F: Send + 'static,
+        T: Send + 'static,
+    {
+        std::thread::spawn(f)
+    }
+
+    fn spawn_named_thread<F, T>(
+        _time_trace: bool,
+        name: String,
+        f: F,
+    ) -> std::io::Result<std::thread::JoinHandle<T>>
+    where
+        F: FnOnce() -> T,
+        F: Send + 'static,
+        T: Send + 'static,
+    {
+        std::thread::Builder::new().name(name).spawn(f)
+    }
 }
index e7da96f0adafdaf53b510f3084c7f4ad684b59c3..158e658301eed725410dba017970a4b1d7e18fae 100644 (file)
@@ -158,6 +158,8 @@ fn write_operand_repeatedly(
 
     fn range_metadata(&mut self, load: Self::Value, range: WrappingRange);
     fn nonnull_metadata(&mut self, load: Self::Value);
+    fn type_metadata(&mut self, function: Self::Function, typeid: String);
+    fn typeid_metadata(&mut self, typeid: String) -> Self::Value;
 
     fn store(&mut self, val: Self::Value, ptr: Self::Value, align: Align) -> Self::Value;
     fn store_with_flags(
index 777436ad2ae8fd9290405e131d2c15361958a25d..78bf22ef9f2e2066c5ee3d9202c857d80e04b719 100644 (file)
@@ -24,6 +24,8 @@ fn codegen_intrinsic_call(
     ///
     /// Currently has any effect only when LLVM versions prior to 12.0 are used as the backend.
     fn sideeffect(&mut self);
+    /// Trait method used to test whether a given pointer is associated with a type identifier.
+    fn type_test(&mut self, pointer: Self::Value, typeid: Self::Value) -> Self::Value;
     /// Trait method used to inject `va_start` on the "spoofed" `VaListImpl` in
     /// Rust defined C-variadic functions.
     fn va_start(&mut self, val: Self::Value) -> Self::Value;
index 5da1681662577648009f96b1da5b0aabfe02229d..87298023980ed8c2ff2ccde238122e1a7556fb53 100644 (file)
@@ -25,10 +25,7 @@ pub enum ConstEvalErrKind {
 
 impl MachineStopType for ConstEvalErrKind {
     fn is_hard_err(&self) -> bool {
-        match self {
-            Self::Panic { .. } => true,
-            _ => false,
-        }
+        matches!(self, Self::Panic { .. })
     }
 }
 
index 57af0ff07143373cacfd7f11d2423e7e0bc8cd7c..6d3a89c0a8a5ba3927510556463c1b55d4397baa 100644 (file)
@@ -42,6 +42,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
                     | DefKind::Static
                     | DefKind::ConstParam
                     | DefKind::AnonConst
+                    | DefKind::InlineConst
                     | DefKind::AssocConst
             ),
         "Unexpected DefKind: {:?}",
index 80551518d3c5d8bdbe10341d2fd5d98e8ec1dafb..821b048eb9bcfc80331ce6f46616bcd3b42babc1 100644 (file)
@@ -51,10 +51,8 @@ fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
         // If the function itself is not annotated with `const`, it may still be a `const fn`
         // if it resides in a const trait impl.
         is_parent_const_impl_raw(tcx, hir_id)
-    } else if let hir::Node::Ctor(_) = node {
-        true
     } else {
-        false
+        matches!(node, hir::Node::Ctor(_))
     }
 }
 
index 8efe3eb868b941d48318863742aaeadec93964e8..dacd8f7c12cfd50204f00037a4e3eec8049d5a29 100644 (file)
@@ -30,34 +30,25 @@ fn hook_special_const_fn(
         &mut self,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx>],
-        is_const_fn: bool,
     ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
-        // The list of functions we handle here must be in sync with
-        // `is_lang_special_const_fn` in `transform/check_consts/mod.rs`.
+        // All `#[rustc_do_not_const_check]` functions should be hooked here.
         let def_id = instance.def_id();
 
-        if is_const_fn {
-            if Some(def_id) == self.tcx.lang_items().const_eval_select() {
-                // redirect to const_eval_select_ct
-                if let Some(const_eval_select) = self.tcx.lang_items().const_eval_select_ct() {
-                    return Ok(Some(
-                        ty::Instance::resolve(
-                            *self.tcx,
-                            ty::ParamEnv::reveal_all(),
-                            const_eval_select,
-                            instance.substs,
-                        )
-                        .unwrap()
-                        .unwrap(),
-                    ));
-                }
+        if Some(def_id) == self.tcx.lang_items().const_eval_select() {
+            // redirect to const_eval_select_ct
+            if let Some(const_eval_select) = self.tcx.lang_items().const_eval_select_ct() {
+                return Ok(Some(
+                    ty::Instance::resolve(
+                        *self.tcx,
+                        ty::ParamEnv::reveal_all(),
+                        const_eval_select,
+                        instance.substs,
+                    )
+                    .unwrap()
+                    .unwrap(),
+                ));
             }
-            return Ok(None);
-        }
-
-        if Some(def_id) == self.tcx.lang_items().panic_fn()
-            || Some(def_id) == self.tcx.lang_items().panic_str()
-            || Some(def_id) == self.tcx.lang_items().panic_display()
+        } else if Some(def_id) == self.tcx.lang_items().panic_display()
             || Some(def_id) == self.tcx.lang_items().begin_panic_fn()
         {
             // &str or &&str
@@ -274,31 +265,22 @@ fn find_mir_or_eval_fn(
 
         // Only check non-glue functions
         if let ty::InstanceDef::Item(def) = instance.def {
-            let mut is_const_fn = true;
-
             // Execution might have wandered off into other crates, so we cannot do a stability-
             // sensitive check here.  But we can at least rule out functions that are not const
             // at all.
             if !ecx.tcx.is_const_fn_raw(def.did) {
                 // allow calling functions marked with #[default_method_body_is_const].
                 if !ecx.tcx.has_attr(def.did, sym::default_method_body_is_const) {
-                    is_const_fn = false;
+                    // We certainly do *not* want to actually call the fn
+                    // though, so be sure we return here.
+                    throw_unsup_format!("calling non-const function `{}`", instance)
                 }
             }
 
-            // Some functions we support even if they are non-const -- but avoid testing
-            // that for const fn!
-            // `const_eval_select` is a const fn because it must use const trait bounds.
-            if let Some(new_instance) = ecx.hook_special_const_fn(instance, args, is_const_fn)? {
+            if let Some(new_instance) = ecx.hook_special_const_fn(instance, args)? {
                 // We call another const fn instead.
                 return Self::find_mir_or_eval_fn(ecx, new_instance, _abi, args, _ret, _unwind);
             }
-
-            if !is_const_fn {
-                // We certainly do *not* want to actually call the fn
-                // though, so be sure we return here.
-                throw_unsup_format!("calling non-const function `{}`", instance)
-            }
         }
         // This is a const fn. Call it.
         Ok(Some(ecx.load_mir(instance.def, None)?))
index a7012cd63f313059b270808ebea4cc8fe6d16c8d..5b4a5ac3577224722763b872f6ede27acbac6b2d 100644 (file)
@@ -138,10 +138,8 @@ fn path_generic_args(
         args: &[GenericArg<'tcx>],
     ) -> Result<Self::Path, Self::Error> {
         self = print_prefix(self)?;
-        let args = args.iter().cloned().filter(|arg| match arg.unpack() {
-            GenericArgKind::Lifetime(_) => false,
-            _ => true,
-        });
+        let args =
+            args.iter().cloned().filter(|arg| !matches!(arg.unpack(), GenericArgKind::Lifetime(_)));
         if args.clone().next().is_some() {
             self.generic_delimiters(|cx| cx.comma_sep(args))
         } else {
index 8d3544d434acf8560f81ab6b544ae1fe121e271d..00208574c555e9b77207dbb063a7041b2fba3427 100644 (file)
@@ -345,10 +345,8 @@ pub(crate) fn eval_fn_call(
 
                     // Figure out how to pass which arguments.
                     // The Rust ABI is special: ZST get skipped.
-                    let rust_abi = match caller_abi {
-                        Abi::Rust | Abi::RustCall => true,
-                        _ => false,
-                    };
+                    let rust_abi = matches!(caller_abi, Abi::Rust | Abi::RustCall);
+
                     // We have two iterators: Where the arguments come from,
                     // and where they go to.
 
index 17a5313d73a5f11a3de00b0e9470854f4e2e21e5..f308e764e861d0422e76464c39014aea20b59d09 100644 (file)
@@ -24,7 +24,6 @@
 #![feature(trusted_step)]
 #![feature(try_blocks)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate tracing;
index 85f37c813d85d1b2bbe3242b4c8159b90197ffc7..61fd828a430020d9c096a7a559135de424924a77 100644 (file)
@@ -12,7 +12,6 @@
 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
 use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt};
 use rustc_middle::ty::{Binder, TraitPredicate, TraitRef};
-use rustc_mir_dataflow::impls::MaybeMutBorrowedLocals;
 use rustc_mir_dataflow::{self, Analysis};
 use rustc_span::{sym, Span, Symbol};
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
 use super::ops::{self, NonConstOp, Status};
 use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop, NeedsNonConstDrop};
 use super::resolver::FlowSensitiveAnalysis;
-use super::{is_lang_panic_fn, is_lang_special_const_fn, ConstCx, Qualif};
+use super::{ConstCx, Qualif};
 use crate::const_eval::is_unstable_const_fn;
 
-// We are using `MaybeMutBorrowedLocals` as a proxy for whether an item may have been mutated
-// through a pointer prior to the given point. This is okay even though `MaybeMutBorrowedLocals`
-// kills locals upon `StorageDead` because a local will never be used after a `StorageDead`.
-type IndirectlyMutableResults<'mir, 'tcx> =
-    rustc_mir_dataflow::ResultsCursor<'mir, 'tcx, MaybeMutBorrowedLocals<'mir, 'tcx>>;
-
 type QualifResults<'mir, 'tcx, Q> =
     rustc_mir_dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>;
 
@@ -41,36 +34,9 @@ pub struct Qualifs<'mir, 'tcx> {
     has_mut_interior: Option<QualifResults<'mir, 'tcx, HasMutInterior>>,
     needs_drop: Option<QualifResults<'mir, 'tcx, NeedsDrop>>,
     needs_non_const_drop: Option<QualifResults<'mir, 'tcx, NeedsNonConstDrop>>,
-    indirectly_mutable: Option<IndirectlyMutableResults<'mir, 'tcx>>,
 }
 
 impl Qualifs<'mir, 'tcx> {
-    pub fn indirectly_mutable(
-        &mut self,
-        ccx: &'mir ConstCx<'mir, 'tcx>,
-        local: Local,
-        location: Location,
-    ) -> bool {
-        let indirectly_mutable = self.indirectly_mutable.get_or_insert_with(|| {
-            let ConstCx { tcx, body, param_env, .. } = *ccx;
-
-            // We can use `unsound_ignore_borrow_on_drop` here because custom drop impls are not
-            // allowed in a const.
-            //
-            // FIXME(ecstaticmorse): Someday we want to allow custom drop impls. How do we do this
-            // without breaking stable code?
-            MaybeMutBorrowedLocals::mut_borrows_only(tcx, &body, param_env)
-                .unsound_ignore_borrow_on_drop()
-                .into_engine(tcx, &body)
-                .pass_name("const_qualification")
-                .iterate_to_fixpoint()
-                .into_results_cursor(&body)
-        });
-
-        indirectly_mutable.seek_before_primary_effect(location);
-        indirectly_mutable.get().contains(local)
-    }
-
     /// Returns `true` if `local` is `NeedsDrop` at the given `Location`.
     ///
     /// Only updates the cursor if absolutely necessary
@@ -95,7 +61,7 @@ pub fn needs_drop(
         });
 
         needs_drop.seek_before_primary_effect(location);
-        needs_drop.get().contains(local) || self.indirectly_mutable(ccx, local, location)
+        needs_drop.get().contains(local)
     }
 
     /// Returns `true` if `local` is `NeedsNonConstDrop` at the given `Location`.
@@ -122,7 +88,7 @@ pub fn needs_non_const_drop(
         });
 
         needs_non_const_drop.seek_before_primary_effect(location);
-        needs_non_const_drop.get().contains(local) || self.indirectly_mutable(ccx, local, location)
+        needs_non_const_drop.get().contains(local)
     }
 
     /// Returns `true` if `local` is `HasMutInterior` at the given `Location`.
@@ -149,7 +115,7 @@ pub fn has_mut_interior(
         });
 
         has_mut_interior.seek_before_primary_effect(location);
-        has_mut_interior.get().contains(local) || self.indirectly_mutable(ccx, local, location)
+        has_mut_interior.get().contains(local)
     }
 
     fn in_return_place(
@@ -165,10 +131,7 @@ fn in_return_place(
             .body
             .basic_blocks()
             .iter_enumerated()
-            .find(|(_, block)| match block.terminator().kind {
-                TerminatorKind::Return => true,
-                _ => false,
-            })
+            .find(|(_, block)| matches!(block.terminator().kind, TerminatorKind::Return))
             .map(|(bb, _)| bb);
 
         let return_block = match return_block {
@@ -195,7 +158,7 @@ fn in_return_place(
                     .into_results_cursor(&ccx.body);
 
                 cursor.seek_after_primary_effect(return_loc);
-                cursor.contains(RETURN_PLACE)
+                cursor.get().contains(RETURN_PLACE)
             }
         };
 
@@ -918,31 +881,27 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
                 }
 
                 // At this point, we are calling a function, `callee`, whose `DefId` is known...
-                if is_lang_special_const_fn(tcx, callee) {
-                    // `begin_panic` and `panic_display` are generic functions that accept
-                    // types other than str. Check to enforce that only str can be used in
-                    // const-eval.
-
-                    // const-eval of the `begin_panic` fn assumes the argument is `&str`
-                    if Some(callee) == tcx.lang_items().begin_panic_fn() {
-                        match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
-                            ty::Ref(_, ty, _) if ty.is_str() => (),
-                            _ => self.check_op(ops::PanicNonStr),
-                        }
-                    }
 
-                    // const-eval of the `panic_display` fn assumes the argument is `&&str`
-                    if Some(callee) == tcx.lang_items().panic_display() {
-                        match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
-                            ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) =>
-                                {}
-                            _ => self.check_op(ops::PanicNonStr),
-                        }
+                // `begin_panic` and `panic_display` are generic functions that accept
+                // types other than str. Check to enforce that only str can be used in
+                // const-eval.
+
+                // const-eval of the `begin_panic` fn assumes the argument is `&str`
+                if Some(callee) == tcx.lang_items().begin_panic_fn() {
+                    match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
+                        ty::Ref(_, ty, _) if ty.is_str() => return,
+                        _ => self.check_op(ops::PanicNonStr),
                     }
+                }
 
-                    if is_lang_panic_fn(tcx, callee) {
-                        // run stability check on non-panic special const fns.
-                        return;
+                // const-eval of the `panic_display` fn assumes the argument is `&&str`
+                if Some(callee) == tcx.lang_items().panic_display() {
+                    match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
+                        ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) =>
+                        {
+                            return;
+                        }
+                        _ => self.check_op(ops::PanicNonStr),
                     }
                 }
 
@@ -1095,8 +1054,9 @@ fn check_return_ty_is_sync(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, hir_id: HirId)
         let mut fulfillment_cx = traits::FulfillmentContext::new();
         let sync_def_id = tcx.require_lang_item(LangItem::Sync, Some(body.span));
         fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), ty, sync_def_id, cause);
-        if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(&err, None, false);
+        let errors = fulfillment_cx.select_all_or_error(&infcx);
+        if !errors.is_empty() {
+            infcx.report_fulfillment_errors(&errors, None, false);
         }
     });
 }
index 58d0f1a3ad88ebaf13eaae87686acb9ce5fc21da..dc44409d500a04384f3910b24200f34d34895151 100644 (file)
@@ -72,24 +72,6 @@ pub fn fn_sig(&self) -> Option<&'tcx hir::FnSig<'tcx>> {
     }
 }
 
-/// Returns `true` if this `DefId` points to one of the official `panic` lang items.
-pub fn is_lang_panic_fn(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
-    Some(def_id) == tcx.lang_items().panic_fn()
-        || Some(def_id) == tcx.lang_items().panic_str()
-        || Some(def_id) == tcx.lang_items().panic_display()
-        || Some(def_id) == tcx.lang_items().begin_panic_fn()
-        || Some(def_id) == tcx.lang_items().panic_fmt()
-}
-
-/// Returns `true` if this `DefId` points to one of the lang items that will be handled differently
-/// in const_eval.
-pub fn is_lang_special_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
-    // We can allow calls to these functions because `hook_special_const_fn` in
-    // `const_eval/machine.rs` ensures the calls are handled specially.
-    // Keep in sync with what that function handles!
-    is_lang_panic_fn(tcx, def_id) || Some(def_id) == tcx.lang_items().const_eval_select()
-}
-
 pub fn rustc_allow_const_fn_unstable(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
index aa42f8936f32c26da5bf10824b97d38f9f0c4ee1..abc5a3c6a5206b352fe017a1f5dbef97b286d265 100644 (file)
@@ -170,11 +170,12 @@ fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, mut ty: Ty<'tcx>) -> bool {
             let mut selcx = SelectionContext::with_constness(&infcx, hir::Constness::Const);
             selcx.select(&obligation)
         });
-        match implsrc {
-            Ok(Some(ImplSource::ConstDrop(_)))
-            | Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => false,
-            _ => true,
-        }
+        !matches!(
+            implsrc,
+            Ok(Some(
+                ImplSource::ConstDrop(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst)
+            ))
+        )
     }
 
     fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, _: SubstsRef<'tcx>) -> bool {
@@ -258,6 +259,9 @@ pub fn in_rvalue<Q, F>(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, rvalue: &Rvalue
                 if Q::in_adt_inherently(cx, def, substs) {
                     return true;
                 }
+                if def.is_union() && Q::in_any_value_of_ty(cx, rvalue.ty(cx.body, cx.tcx)) {
+                    return true;
+                }
             }
 
             // Otherwise, proceed structurally...
index e20b86dd4523cd2c946ae55bed60bdf287e67a3d..fcce829eba4121a23c0f0336cd0023ec2310b6dd 100644 (file)
@@ -5,7 +5,11 @@
 use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::{self, BasicBlock, Local, Location, Statement, StatementKind};
+use rustc_mir_dataflow::fmt::DebugWithContext;
+use rustc_mir_dataflow::JoinSemiLattice;
+use rustc_span::DUMMY_SP;
 
+use std::fmt;
 use std::marker::PhantomData;
 
 use super::{qualifs, ConstCx, Qualif};
 /// A `Visitor` that propagates qualifs between locals. This defines the transfer function of
 /// `FlowSensitiveAnalysis`.
 ///
-/// This transfer does nothing when encountering an indirect assignment. Consumers should rely on
-/// the `MaybeMutBorrowedLocals` dataflow pass to see if a `Local` may have become qualified via
-/// an indirect assignment or function call.
+/// To account for indirect assignments, data flow conservatively assumes that local becomes
+/// qualified immediately after it is borrowed or its address escapes. The borrow must allow for
+/// mutation, which includes shared borrows of places with interior mutability. The type of
+/// borrowed place must contain the qualif.
 struct TransferFunction<'a, 'mir, 'tcx, Q> {
     ccx: &'a ConstCx<'mir, 'tcx>,
-    qualifs_per_local: &'a mut BitSet<Local>,
-
+    state: &'a mut State,
     _qualif: PhantomData<Q>,
 }
 
@@ -27,27 +31,38 @@ impl<Q> TransferFunction<'a, 'mir, 'tcx, Q>
 where
     Q: Qualif,
 {
-    fn new(ccx: &'a ConstCx<'mir, 'tcx>, qualifs_per_local: &'a mut BitSet<Local>) -> Self {
-        TransferFunction { ccx, qualifs_per_local, _qualif: PhantomData }
+    fn new(ccx: &'a ConstCx<'mir, 'tcx>, state: &'a mut State) -> Self {
+        TransferFunction { ccx, state, _qualif: PhantomData }
     }
 
     fn initialize_state(&mut self) {
-        self.qualifs_per_local.clear();
+        self.state.qualif.clear();
+        self.state.borrow.clear();
 
         for arg in self.ccx.body.args_iter() {
             let arg_ty = self.ccx.body.local_decls[arg].ty;
             if Q::in_any_value_of_ty(self.ccx, arg_ty) {
-                self.qualifs_per_local.insert(arg);
+                self.state.qualif.insert(arg);
             }
         }
     }
 
-    fn assign_qualif_direct(&mut self, place: &mir::Place<'tcx>, value: bool) {
+    fn assign_qualif_direct(&mut self, place: &mir::Place<'tcx>, mut value: bool) {
         debug_assert!(!place.is_indirect());
 
+        if !value {
+            for (base, _elem) in place.iter_projections() {
+                let base_ty = base.ty(self.ccx.body, self.ccx.tcx);
+                if base_ty.ty.is_union() && Q::in_any_value_of_ty(self.ccx, base_ty.ty) {
+                    value = true;
+                    break;
+                }
+            }
+        }
+
         match (value, place.as_ref()) {
             (true, mir::PlaceRef { local, .. }) => {
-                self.qualifs_per_local.insert(local);
+                self.state.qualif.insert(local);
             }
 
             // For now, we do not clear the qualif if a local is overwritten in full by
@@ -55,7 +70,7 @@ fn assign_qualif_direct(&mut self, place: &mir::Place<'tcx>, value: bool) {
             // with aggregates where we overwrite all fields with assignments, which would not
             // get this feature.
             (false, mir::PlaceRef { local: _, projection: &[] }) => {
-                // self.qualifs_per_local.remove(*local);
+                // self.state.qualif.remove(*local);
             }
 
             _ => {}
@@ -78,6 +93,37 @@ fn apply_call_return_effect(
             self.assign_qualif_direct(&return_place, qualif);
         }
     }
+
+    fn address_of_allows_mutation(&self, _mt: mir::Mutability, _place: mir::Place<'tcx>) -> bool {
+        // Exact set of permissions granted by AddressOf is undecided. Conservatively assume that
+        // it might allow mutation until resolution of #56604.
+        true
+    }
+
+    fn ref_allows_mutation(&self, kind: mir::BorrowKind, place: mir::Place<'tcx>) -> bool {
+        match kind {
+            mir::BorrowKind::Mut { .. } => true,
+            mir::BorrowKind::Shared | mir::BorrowKind::Shallow | mir::BorrowKind::Unique => {
+                self.shared_borrow_allows_mutation(place)
+            }
+        }
+    }
+
+    /// `&` only allow mutation if the borrowed place is `!Freeze`.
+    ///
+    /// This assumes that it is UB to take the address of a struct field whose type is
+    /// `Freeze`, then use pointer arithmetic to derive a pointer to a *different* field of
+    /// that same struct whose type is `!Freeze`. If we decide that this is not UB, we will
+    /// have to check the type of the borrowed **local** instead of the borrowed **place**
+    /// below. See [rust-lang/unsafe-code-guidelines#134].
+    ///
+    /// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134
+    fn shared_borrow_allows_mutation(&self, place: mir::Place<'tcx>) -> bool {
+        !place
+            .ty(self.ccx.body, self.ccx.tcx)
+            .ty
+            .is_freeze(self.ccx.tcx.at(DUMMY_SP), self.ccx.param_env)
+    }
 }
 
 impl<Q> Visitor<'tcx> for TransferFunction<'_, '_, 'tcx, Q>
@@ -95,7 +141,12 @@ fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) {
         // it no longer needs to be dropped.
         if let mir::Operand::Move(place) = operand {
             if let Some(local) = place.as_local() {
-                self.qualifs_per_local.remove(local);
+                // For backward compatibility with the MaybeMutBorrowedLocals used in an earlier
+                // implementation we retain qualif if a local had been borrowed before. This might
+                // not be strictly necessary since the local is no longer initialized.
+                if !self.state.borrow.contains(local) {
+                    self.state.qualif.remove(local);
+                }
             }
         }
     }
@@ -106,11 +157,8 @@ fn visit_assign(
         rvalue: &mir::Rvalue<'tcx>,
         location: Location,
     ) {
-        let qualif = qualifs::in_rvalue::<Q, _>(
-            self.ccx,
-            &mut |l| self.qualifs_per_local.contains(l),
-            rvalue,
-        );
+        let qualif =
+            qualifs::in_rvalue::<Q, _>(self.ccx, &mut |l| self.state.qualif.contains(l), rvalue);
         if !place.is_indirect() {
             self.assign_qualif_direct(place, qualif);
         }
@@ -120,10 +168,53 @@ fn visit_assign(
         self.super_assign(place, rvalue, location);
     }
 
+    fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
+        self.super_rvalue(rvalue, location);
+
+        match rvalue {
+            mir::Rvalue::AddressOf(mt, borrowed_place) => {
+                if !borrowed_place.is_indirect()
+                    && self.address_of_allows_mutation(*mt, *borrowed_place)
+                {
+                    let place_ty = borrowed_place.ty(self.ccx.body, self.ccx.tcx).ty;
+                    if Q::in_any_value_of_ty(self.ccx, place_ty) {
+                        self.state.qualif.insert(borrowed_place.local);
+                        self.state.borrow.insert(borrowed_place.local);
+                    }
+                }
+            }
+
+            mir::Rvalue::Ref(_, kind, borrowed_place) => {
+                if !borrowed_place.is_indirect() && self.ref_allows_mutation(*kind, *borrowed_place)
+                {
+                    let place_ty = borrowed_place.ty(self.ccx.body, self.ccx.tcx).ty;
+                    if Q::in_any_value_of_ty(self.ccx, place_ty) {
+                        self.state.qualif.insert(borrowed_place.local);
+                        self.state.borrow.insert(borrowed_place.local);
+                    }
+                }
+            }
+
+            mir::Rvalue::Cast(..)
+            | mir::Rvalue::ShallowInitBox(..)
+            | mir::Rvalue::Use(..)
+            | mir::Rvalue::ThreadLocalRef(..)
+            | mir::Rvalue::Repeat(..)
+            | mir::Rvalue::Len(..)
+            | mir::Rvalue::BinaryOp(..)
+            | mir::Rvalue::CheckedBinaryOp(..)
+            | mir::Rvalue::NullaryOp(..)
+            | mir::Rvalue::UnaryOp(..)
+            | mir::Rvalue::Discriminant(..)
+            | mir::Rvalue::Aggregate(..) => {}
+        }
+    }
+
     fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
         match statement.kind {
             StatementKind::StorageDead(local) => {
-                self.qualifs_per_local.remove(local);
+                self.state.qualif.remove(local);
+                self.state.borrow.remove(local);
             }
             _ => self.super_statement(statement, location),
         }
@@ -136,7 +227,7 @@ fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Loc
         if let mir::TerminatorKind::DropAndReplace { value, place, .. } = &terminator.kind {
             let qualif = qualifs::in_operand::<Q, _>(
                 self.ccx,
-                &mut |l| self.qualifs_per_local.contains(l),
+                &mut |l| self.state.qualif.contains(l),
                 value,
             );
 
@@ -145,6 +236,9 @@ fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Loc
             }
         }
 
+        // We ignore borrow on drop because custom drop impls are not allowed in consts.
+        // FIXME: Reconsider if accounting for borrows in drops is necessary for const drop.
+
         // We need to assign qualifs to the dropped location before visiting the operand that
         // replaces it since qualifs can be cleared on move.
         self.super_terminator(terminator, location);
@@ -165,24 +259,76 @@ pub(super) fn new(_: Q, ccx: &'a ConstCx<'mir, 'tcx>) -> Self {
         FlowSensitiveAnalysis { ccx, _qualif: PhantomData }
     }
 
-    fn transfer_function(
-        &self,
-        state: &'a mut BitSet<Local>,
-    ) -> TransferFunction<'a, 'mir, 'tcx, Q> {
+    fn transfer_function(&self, state: &'a mut State) -> TransferFunction<'a, 'mir, 'tcx, Q> {
         TransferFunction::<Q>::new(self.ccx, state)
     }
 }
 
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub(super) struct State {
+    /// Describes whether a local contains qualif.
+    pub qualif: BitSet<Local>,
+    /// Describes whether a local's address escaped and it might become qualified as a result an
+    /// indirect mutation.
+    pub borrow: BitSet<Local>,
+}
+
+impl State {
+    #[inline]
+    pub(super) fn contains(&self, local: Local) -> bool {
+        self.qualif.contains(local)
+    }
+}
+
+impl<C> DebugWithContext<C> for State {
+    fn fmt_with(&self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str("qualif: ")?;
+        self.qualif.fmt_with(ctxt, f)?;
+        f.write_str(" borrow: ")?;
+        self.borrow.fmt_with(ctxt, f)?;
+        Ok(())
+    }
+
+    fn fmt_diff_with(&self, old: &Self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        if self == old {
+            return Ok(());
+        }
+
+        if self.qualif != old.qualif {
+            f.write_str("qualif: ")?;
+            self.qualif.fmt_diff_with(&old.qualif, ctxt, f)?;
+            f.write_str("\n")?;
+        }
+
+        if self.borrow != old.borrow {
+            f.write_str("borrow: ")?;
+            self.qualif.fmt_diff_with(&old.borrow, ctxt, f)?;
+            f.write_str("\n")?;
+        }
+
+        Ok(())
+    }
+}
+
+impl JoinSemiLattice for State {
+    fn join(&mut self, other: &Self) -> bool {
+        self.qualif.join(&other.qualif) || self.borrow.join(&other.borrow)
+    }
+}
+
 impl<Q> rustc_mir_dataflow::AnalysisDomain<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q>
 where
     Q: Qualif,
 {
-    type Domain = BitSet<Local>;
+    type Domain = State;
 
     const NAME: &'static str = Q::ANALYSIS_NAME;
 
     fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
-        BitSet::new_empty(body.local_decls.len())
+        State {
+            qualif: BitSet::new_empty(body.local_decls.len()),
+            borrow: BitSet::new_empty(body.local_decls.len()),
+        }
     }
 
     fn initialize_start_block(&self, _body: &mir::Body<'tcx>, state: &mut Self::Domain) {
index ebcc8213c604b889187c00e17d13d5f1e6b3c658..7bf378601e053317963dcdc036129b94c05be7e3 100644 (file)
@@ -26,7 +26,7 @@
 use std::cell::Cell;
 use std::{cmp, iter, mem};
 
-use crate::transform::check_consts::{is_lang_special_const_fn, qualifs, ConstCx};
+use crate::transform::check_consts::{qualifs, ConstCx};
 use crate::transform::MirPass;
 
 /// A `MirPass` for promotion.
@@ -656,9 +656,7 @@ fn validate_call(
         }
 
         let is_const_fn = match *fn_ty.kind() {
-            ty::FnDef(def_id, _) => {
-                self.tcx.is_const_fn_raw(def_id) || is_lang_special_const_fn(self.tcx, def_id)
-            }
+            ty::FnDef(def_id, _) => self.tcx.is_const_fn_raw(def_id),
             _ => false,
         };
         if !is_const_fn {
@@ -837,11 +835,7 @@ fn promote_temp(&mut self, temp: Local) -> Local {
         new_temp
     }
 
-    fn promote_candidate(
-        mut self,
-        candidate: Candidate,
-        next_promoted_id: usize,
-    ) -> Option<Body<'tcx>> {
+    fn promote_candidate(mut self, candidate: Candidate, next_promoted_id: usize) -> Body<'tcx> {
         let def = self.source.source.with_opt_param();
         let mut rvalue = {
             let promoted = &mut self.promoted;
@@ -940,7 +934,7 @@ fn promote_candidate(
 
         let span = self.promoted.span;
         self.assign(RETURN_PLACE, rvalue, span);
-        Some(self.promoted)
+        self.promoted
     }
 }
 
@@ -1013,11 +1007,9 @@ pub fn promote_candidates<'tcx>(
             keep_original: false,
         };
 
-        //FIXME(oli-obk): having a `maybe_push()` method on `IndexVec` might be nice
-        if let Some(mut promoted) = promoter.promote_candidate(candidate, promotions.len()) {
-            promoted.source.promoted = Some(promotions.next_index());
-            promotions.push(promoted);
-        }
+        let mut promoted = promoter.promote_candidate(candidate, promotions.len());
+        promoted.source.promoted = Some(promotions.next_index());
+        promotions.push(promoted);
     }
 
     // Insert each of `extra_statements` before its indicated location, which
index 0fbcd22c5e09876a27e46c7a29cc75ff591adeee..77784bf1705234d0018ef5aca044267902dd6735 100644 (file)
@@ -11,7 +11,6 @@
 #![feature(associated_type_bounds)]
 #![feature(auto_traits)]
 #![feature(bool_to_option)]
-#![cfg_attr(bootstrap, feature(const_panic))]
 #![feature(control_flow_enum)]
 #![feature(core_intrinsics)]
 #![feature(extend_one)]
@@ -28,7 +27,6 @@
 #![feature(thread_id_value)]
 #![allow(rustc::default_hash_types)]
 #![deny(unaligned_references)]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate tracing;
index 20e2a3b9696e8560cb80d71d50cd9d8d6a0c281d..9efea1228ab29e8ad42783aee9adc7165ef2f5a8 100644 (file)
@@ -1,3 +1,4 @@
+use crate::stable_hasher::{HashStable, StableHasher};
 use std::borrow::Borrow;
 use std::cmp::Ordering;
 use std::iter::FromIterator;
 /// stores data in a more compact way. It also supports accessing contiguous
 /// ranges of elements as a slice, and slices of already sorted elements can be
 /// inserted efficiently.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encodable, Decodable)]
-pub struct SortedMap<K: Ord, V> {
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)]
+pub struct SortedMap<K, V> {
     data: Vec<(K, V)>,
 }
 
-impl<K: Ord, V> SortedMap<K, V> {
+impl<K, V> Default for SortedMap<K, V> {
+    #[inline]
+    fn default() -> SortedMap<K, V> {
+        SortedMap { data: Vec::new() }
+    }
+}
+
+impl<K, V> SortedMap<K, V> {
     #[inline]
-    pub fn new() -> SortedMap<K, V> {
-        SortedMap { data: vec![] }
+    pub const fn new() -> SortedMap<K, V> {
+        SortedMap { data: Vec::new() }
     }
+}
 
+impl<K: Ord, V> SortedMap<K, V> {
     /// Construct a `SortedMap` from a presorted set of elements. This is faster
     /// than creating an empty map and then inserting the elements individually.
     ///
@@ -281,5 +291,12 @@ fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
     }
 }
 
+impl<K: HashStable<CTX>, V: HashStable<CTX>, CTX> HashStable<CTX> for SortedMap<K, V> {
+    #[inline]
+    fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
+        self.data.hash_stable(ctx, hasher);
+    }
+}
+
 #[cfg(test)]
 mod tests;
index a1ffbae8b15f6dd7d3c02264ade7a1c2faf2d24d..a3ece6550473cce4ce080bbdc5e28f15b69e1cc2 100644 (file)
@@ -34,7 +34,7 @@ pub fn new(value: T) -> Self {
     #[track_caller]
     pub fn borrow(&self) -> MappedReadGuard<'_, T> {
         let borrow = self.value.borrow();
-        if let None = &*borrow {
+        if borrow.is_none() {
             panic!("attempted to read from stolen value: {}", std::any::type_name::<T>());
         }
         ReadGuard::map(borrow, |opt| opt.as_ref().unwrap())
index 1a9f8961bd74167dff07f4b30a103cb21b596c17..9a57ec991444ac8e160ae835d213b6513afad26e 100644 (file)
@@ -8,7 +8,6 @@
 #![feature(nll)]
 #![feature(once_cell)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate tracing;
@@ -847,7 +846,7 @@ fn sort_lint_groups(
     let builtin = sort_lints(sess, builtin);
 
     let (plugin_groups, builtin_groups): (Vec<_>, _) =
-        lint_store.get_lint_groups().partition(|&(.., p)| p);
+        lint_store.get_lint_groups().iter().cloned().partition(|&(.., p)| p);
     let plugin_groups = sort_lint_groups(plugin_groups);
     let builtin_groups = sort_lint_groups(builtin_groups);
 
index 724e3f7fed3996e1aeb2638a71681fda46a5a2ca..ce26ff62235f466103df17ccdf0b1e07287460d6 100644 (file)
 E0783: include_str!("./error_codes/E0783.md"),
 E0784: include_str!("./error_codes/E0784.md"),
 E0785: include_str!("./error_codes/E0785.md"),
+E0786: include_str!("./error_codes/E0786.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
-//  E0019, merged into E0015
-//  E0035, merged into E0087/E0089
-//  E0036, merged into E0087/E0089
+//  E0019, // merged into E0015
+//  E0035, // merged into E0087/E0089
+//  E0036, // merged into E0087/E0089
 //  E0068,
 //  E0085,
 //  E0086,
 //  E0134,
 //  E0135,
 //  E0141,
-//  E0153, unused error code
-//  E0157, unused error code
+//  E0153, // unused error code
+//  E0157, // unused error code
 //  E0159, // use of trait `{}` as struct constructor
 //  E0163, // merged into E0071
 //  E0167,
            // between structures with the same definition
 //  E0385, // {} in an aliasable location
 //  E0402, // cannot use an outer type parameter in this context
-//  E0406, merged into 420
-//  E0410, merged into 408
-//  E0413, merged into 530
-//  E0414, merged into 530
-//  E0417, merged into 532
-//  E0418, merged into 532
-//  E0419, merged into 531
-//  E0420, merged into 532
-//  E0421, merged into 531
-//  E0427, merged into 530
+//  E0406, // merged into 420
+//  E0410, // merged into 408
+//  E0413, // merged into 530
+//  E0414, // merged into 530
+//  E0417, // merged into 532
+//  E0418, // merged into 532
+//  E0419, // merged into 531
+//  E0420, // merged into 532
+//  E0421, // merged into 531
+//  E0427, // merged into 530
 //  E0456, // plugin `..` is not available for triple `..`
     E0457, // plugin `..` only found in rlib format, but must be available...
     E0460, // found possibly newer version of crate `..`
     E0461, // couldn't find crate `..` with expected target triple ..
     E0462, // found staticlib `..` instead of rlib or dylib
     E0465, // multiple .. candidates for `..` found
-//  E0467, removed
-//  E0470, removed
+//  E0467, // removed
+//  E0470, // removed
 //  E0471, // constant evaluation error (in pattern)
     E0472, // llvm_asm! is unsupported on this target
 //  E0473, // dereference of reference outside its lifetime
     E0490, // a value of type `..` is borrowed for too long
     E0514, // metadata version mismatch
     E0519, // local crate and dependency have same (crate-name, disambiguator)
-    // two dependencies have same (crate-name, disambiguator) but different SVH
-    E0523,
+    E0523, // two dependencies have same (crate-name, disambiguator) but different SVH
 //  E0526, // shuffle indices are not constant
 //  E0540, // multiple rustc_deprecated attributes
 //  E0548, // replaced with a generic attribute input check
     E0711, // a feature has been declared with conflicting stability attributes
     E0717, // rustc_promotable without stability attribute
 //  E0721, // `await` keyword
-//  E0723, unstable feature in `const` context
+//  E0723, // unstable feature in `const` context
     E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
 //  E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
     E0772, // `'static' obligation coming from `impl dyn Trait {}` or `impl Foo for dyn Bar {}`.
diff --git a/compiler/rustc_error_codes/src/error_codes/E0786.md b/compiler/rustc_error_codes/src/error_codes/E0786.md
new file mode 100644 (file)
index 0000000..4a9635b
--- /dev/null
@@ -0,0 +1,14 @@
+A metadata file was invalid.
+
+Erroneous code example:
+
+```ignore (needs extern files)
+use ::foo; // error: found invalid metadata files for crate `foo`
+```
+
+When loading crates, each crate must have a valid metadata file.
+Invalid files could be caused by filesystem corruption,
+an IO error while reading the file, or (rarely) a bug in the compiler itself.
+
+Consider deleting the file and recreating it,
+or reporting a bug against the compiler.
index 1eb497460e63c053ceec0ea015227513c0dfa79a..9db8f751390c110d3993b4468585211540e1c68d 100644 (file)
@@ -66,7 +66,7 @@ fn source_string(file: Lrc<SourceFile>, line: &Line) -> String {
 /// Maps `Diagnostic::Level` to `snippet::AnnotationType`
 fn annotation_type_for_level(level: Level) -> AnnotationType {
     match level {
-        Level::Bug | Level::Fatal | Level::Error => AnnotationType::Error,
+        Level::Bug | Level::Fatal | Level::Error { .. } => AnnotationType::Error,
         Level::Warning => AnnotationType::Warning,
         Level::Note => AnnotationType::Note,
         Level::Help => AnnotationType::Help,
index f2381d75c565fd6d365edf242f363b44c0836722..e5116cd8dfed2c1b7ff840ec2a218900935fa620 100644 (file)
@@ -114,7 +114,7 @@ pub fn new_with_code(level: Level, code: Option<DiagnosticId>, message: &str) ->
 
     pub fn is_error(&self) -> bool {
         match self.level {
-            Level::Bug | Level::Fatal | Level::Error | Level::FailureNote => true,
+            Level::Bug | Level::Fatal | Level::Error { .. } | Level::FailureNote => true,
 
             Level::Warning | Level::Note | Level::Help | Level::Cancelled | Level::Allow => false,
         }
index e17604740f0319eedad22501bae4622fc1f2bedc..e16ff9741229148c75827914ede58af494849180 100644 (file)
@@ -2063,8 +2063,26 @@ fn num_decimal_digits(num: usize) -> usize {
     MAX_DIGITS
 }
 
+// We replace some characters so the CLI output is always consistent and underlines aligned.
+const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[
+    ('\t', "    "),   // We do our own tab replacement
+    ('\u{202A}', ""), // The following unicode text flow control characters are inconsistently
+    ('\u{202B}', ""), // supported accross CLIs and can cause confusion due to the bytes on disk
+    ('\u{202D}', ""), // not corresponding to the visible source code, so we replace them always.
+    ('\u{202E}', ""),
+    ('\u{2066}', ""),
+    ('\u{2067}', ""),
+    ('\u{2068}', ""),
+    ('\u{202C}', ""),
+    ('\u{2069}', ""),
+];
+
 fn replace_tabs(str: &str) -> String {
-    str.replace('\t', "    ")
+    let mut s = str.to_string();
+    for (c, replacement) in OUTPUT_REPLACEMENTS {
+        s = s.replace(*c, replacement);
+    }
+    s
 }
 
 fn draw_col_separator(buffer: &mut StyledBuffer, line: usize, col: usize) {
index 45b24d728860709d7b43bdb9e9532a61b3ddbef9..21a2eb771c8e2b7c282c5f0445bc38c9a4c0b632 100644 (file)
@@ -10,7 +10,6 @@
 #![feature(iter_zip)]
 #![feature(let_else)]
 #![feature(nll)]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate rustc_macros;
@@ -412,6 +411,8 @@ pub struct Handler {
 /// as well as inconsistent state observation.
 struct HandlerInner {
     flags: HandlerFlags,
+    /// The number of lint errors that have been emitted.
+    lint_err_count: usize,
     /// The number of errors that have been emitted, including duplicates.
     ///
     /// This is not necessarily the count that's reported to the user once
@@ -551,6 +552,7 @@ pub fn with_emitter_and_flags(
             flags,
             inner: Lock::new(HandlerInner {
                 flags,
+                lint_err_count: 0,
                 err_count: 0,
                 warn_count: 0,
                 deduplicated_err_count: 0,
@@ -727,7 +729,13 @@ pub fn struct_span_err_with_code(
     /// Construct a builder at the `Error` level with the `msg`.
     // FIXME: This method should be removed (every error should have an associated error code).
     pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_> {
-        DiagnosticBuilder::new(self, Level::Error, msg)
+        DiagnosticBuilder::new(self, Level::Error { lint: false }, msg)
+    }
+
+    /// This should only be used by `rustc_middle::lint::struct_lint_level`. Do not use it for hard errors.
+    #[doc(hidden)]
+    pub fn struct_err_lint(&self, msg: &str) -> DiagnosticBuilder<'_> {
+        DiagnosticBuilder::new(self, Level::Error { lint: true }, msg)
     }
 
     /// Construct a builder at the `Error` level with the `msg` and the `code`.
@@ -791,11 +799,14 @@ pub fn span_fatal_with_code(
     }
 
     pub fn span_err(&self, span: impl Into<MultiSpan>, msg: &str) {
-        self.emit_diag_at_span(Diagnostic::new(Error, msg), span);
+        self.emit_diag_at_span(Diagnostic::new(Error { lint: false }, msg), span);
     }
 
     pub fn span_err_with_code(&self, span: impl Into<MultiSpan>, msg: &str, code: DiagnosticId) {
-        self.emit_diag_at_span(Diagnostic::new_with_code(Error, Some(code), msg), span);
+        self.emit_diag_at_span(
+            Diagnostic::new_with_code(Error { lint: false }, Some(code), msg),
+            span,
+        );
     }
 
     pub fn span_warn(&self, span: impl Into<MultiSpan>, msg: &str) {
@@ -863,6 +874,9 @@ pub fn err_count(&self) -> usize {
     pub fn has_errors(&self) -> bool {
         self.inner.borrow().has_errors()
     }
+    pub fn has_errors_or_lint_errors(&self) -> bool {
+        self.inner.borrow().has_errors_or_lint_errors()
+    }
     pub fn has_errors_or_delayed_span_bugs(&self) -> bool {
         self.inner.borrow().has_errors_or_delayed_span_bugs()
     }
@@ -980,7 +994,11 @@ fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) {
             }
         }
         if diagnostic.is_error() {
-            self.bump_err_count();
+            if matches!(diagnostic.level, Level::Error { lint: true }) {
+                self.bump_lint_err_count();
+            } else {
+                self.bump_err_count();
+            }
         } else {
             self.bump_warn_count();
         }
@@ -1074,11 +1092,14 @@ fn err_count(&self) -> usize {
     fn has_errors(&self) -> bool {
         self.err_count() > 0
     }
+    fn has_errors_or_lint_errors(&self) -> bool {
+        self.has_errors() || self.lint_err_count > 0
+    }
     fn has_errors_or_delayed_span_bugs(&self) -> bool {
         self.has_errors() || !self.delayed_span_bugs.is_empty()
     }
     fn has_any_message(&self) -> bool {
-        self.err_count() > 0 || self.warn_count > 0
+        self.err_count() > 0 || self.lint_err_count > 0 || self.warn_count > 0
     }
 
     fn abort_if_errors(&mut self) {
@@ -1132,7 +1153,7 @@ fn fatal(&mut self, msg: &str) -> FatalError {
     }
 
     fn err(&mut self, msg: &str) {
-        self.emit_error(Error, msg);
+        self.emit_error(Error { lint: false }, msg);
     }
 
     /// Emit an error; level should be `Error` or `Fatal`.
@@ -1168,6 +1189,11 @@ fn flush_delayed(&mut self, bugs: Vec<Diagnostic>, explanation: &str) {
         }
     }
 
+    fn bump_lint_err_count(&mut self) {
+        self.lint_err_count += 1;
+        self.panic_if_treat_err_as_bug();
+    }
+
     fn bump_err_count(&mut self) {
         self.err_count += 1;
         self.panic_if_treat_err_as_bug();
@@ -1211,7 +1237,10 @@ fn decorate(mut self) -> Diagnostic {
 pub enum Level {
     Bug,
     Fatal,
-    Error,
+    Error {
+        /// If this error comes from a lint, don't abort compilation even when abort_if_errors() is called.
+        lint: bool,
+    },
     Warning,
     Note,
     Help,
@@ -1230,7 +1259,7 @@ impl Level {
     fn color(self) -> ColorSpec {
         let mut spec = ColorSpec::new();
         match self {
-            Bug | Fatal | Error => {
+            Bug | Fatal | Error { .. } => {
                 spec.set_fg(Some(Color::Red)).set_intense(true);
             }
             Warning => {
@@ -1251,7 +1280,7 @@ fn color(self) -> ColorSpec {
     pub fn to_str(self) -> &'static str {
         match self {
             Bug => "error: internal compiler error",
-            Fatal | Error => "error",
+            Fatal | Error { .. } => "error",
             Warning => "warning",
             Note => "note",
             Help => "help",
index 49b0bb55d87c94c8205f6bc2fbb6d25d3290d395..521ca2135c6f217ad573c1ffbf437ade2652c08b 100644 (file)
@@ -10,7 +10,6 @@
 #![feature(proc_macro_span)]
 #![feature(try_blocks)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate rustc_macros;
index 5cb97198765fe4411a8e691f1990e7e9e2a850c6..66f6c008259005da2fc79fabf458e9271b893631 100644 (file)
@@ -273,7 +273,7 @@ fn to_internal(self) -> TokenStream {
 impl ToInternal<rustc_errors::Level> for Level {
     fn to_internal(self) -> rustc_errors::Level {
         match self {
-            Level::Error => rustc_errors::Level::Error,
+            Level::Error => rustc_errors::Level::Error { lint: false },
             Level::Warning => rustc_errors::Level::Warning,
             Level::Note => rustc_errors::Level::Note,
             Level::Help => rustc_errors::Level::Help,
index 0d7a2afb6367d6b92d6dfd26d7ae3f01097342cb..941d957103c0cef98dd5e474ee99fd13caa5ba72 100644 (file)
@@ -297,6 +297,8 @@ macro_rules! declare_features {
     (accepted, macro_attributes_in_derive_output, "1.57.0", Some(81119), None),
     /// Allows panicking during const eval (producing compile-time errors).
     (accepted, const_panic, "1.57.0", Some(51999), None),
+    /// Lessens the requirements for structs to implement `Unsize`.
+    (accepted, relaxed_struct_unsize, "1.58.0", Some(81793), None),
 
     // -------------------------------------------------------------------------
     // feature-group-end: accepted features
index 2bbfb561ba59461a6ea310f6417673d5c497ffc0..0266b7844ba7fce5181ef9bfef21631e058be0af 100644 (file)
@@ -101,9 +101,13 @@ pub fn set(&self, features: &mut Features, span: Span) {
     }
 }
 
+// See https://rustc-dev-guide.rust-lang.org/feature-gates.html#feature-gates for more
+// documentation about handling feature gates.
+//
 // If you change this, please modify `src/doc/unstable-book` as well.
 //
-// Don't ever remove anything from this list; move them to `removed.rs`.
+// Don't ever remove anything from this list; move them to `accepted.rs` if
+// accepted or `removed.rs` if removed.
 //
 // The version numbers here correspond to the version in which the current status
 // was set. This is most important for knowing when a particular feature became
@@ -589,9 +593,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Allows `extern "C-cmse-nonsecure-call" fn()`.
     (active, abi_c_cmse_nonsecure_call, "1.51.0", Some(81391), None),
 
-    /// Lessens the requirements for structs to implement `Unsize`.
-    (active, relaxed_struct_unsize, "1.51.0", Some(81793), None),
-
     /// Allows associated types in inherent impls.
     (incomplete, inherent_associated_types, "1.52.0", Some(8995), None),
 
@@ -688,6 +689,18 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// not changed from prior instances of the same struct (RFC #2528)
     (incomplete, type_changing_struct_update, "1.58.0", Some(86555), None),
 
+    /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.
+    (active, doc_auto_cfg, "1.58.0", Some(43781), None),
+
+    /// Allows using `const` operands in inline assembly.
+    (active, asm_const, "1.58.0", Some(72016), None),
+
+    /// Allows using `sym` operands in inline assembly.
+    (active, asm_sym, "1.58.0", Some(72016), None),
+
+    /// Enables experimental inline assembly support for additional architectures.
+    (active, asm_experimental_arch, "1.58.0", Some(72016), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
index ee43dc985a043d87413e7deebe9cc0e623e64821..33188d375f5d5e2f333ff8605a5414cf58b796ac 100644 (file)
@@ -460,9 +460,6 @@ macro_rules! experimental {
     // Prevents field reads in the marked trait or method to be considered
     // during dead code analysis.
     rustc_attr!(rustc_trivial_field_reads, Normal, template!(Word), INTERNAL_UNSTABLE),
-    // Used by the `rustc::potential_query_instability` lint to warn methods which
-    // might not be stable during incremental compilation.
-    rustc_attr!(rustc_lint_query_instability, Normal, template!(Word), INTERNAL_UNSTABLE),
 
     // ==========================================================================
     // Internal attributes, Const related:
index 3b6e6db72d1f7128e42a099c2c2fef6001e9c5f1..41c63440ba3cd86f72d5e055dd5bcd73c6fbcf00 100644 (file)
@@ -17,4 +17,4 @@ rustc_serialize = { path = "../rustc_serialize" }
 rustc_ast = { path = "../rustc_ast" }
 tracing = "0.1"
 smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
-odht = { version = "0.3.0", features = ["nightly"] }
+odht = { version = "0.3.1", features = ["nightly"] }
index cb668eb35e093da9b2194eef756f4208e436c677..60761a05de8270180810ca2d6995fab17eb59dac 100644 (file)
@@ -104,8 +104,10 @@ pub enum DefKind {
     Use,
     /// An `extern` block.
     ForeignMod,
-    /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]`, or `const { 1 + 2}`
+    /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]`
     AnonConst,
+    /// An inline constant, e.g. `const { 1 + 2 }`
+    InlineConst,
     /// Opaque type, aka `impl Trait`.
     OpaqueTy,
     Field,
@@ -155,6 +157,7 @@ pub fn descr(self, def_id: DefId) -> &'static str {
             DefKind::Use => "import",
             DefKind::ForeignMod => "foreign module",
             DefKind::AnonConst => "constant expression",
+            DefKind::InlineConst => "inline constant",
             DefKind::Field => "field",
             DefKind::Impl => "implementation",
             DefKind::Closure => "closure",
@@ -174,6 +177,7 @@ pub fn article(&self) -> &'static str {
             | DefKind::OpaqueTy
             | DefKind::Impl
             | DefKind::Use
+            | DefKind::InlineConst
             | DefKind::ExternCrate => "an",
             DefKind::Macro(macro_kind) => macro_kind.article(),
             _ => "a",
@@ -207,6 +211,7 @@ pub fn ns(&self) -> Option<Namespace> {
 
             // Not namespaced.
             DefKind::AnonConst
+            | DefKind::InlineConst
             | DefKind::Field
             | DefKind::LifetimeParam
             | DefKind::ExternCrate
index 6f25715fbecc47b4829c0b660f07b878361d5246..a441a635c1eb37ce6b0e3474eeefd97eba449243 100644 (file)
@@ -12,6 +12,7 @@
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sorted_map::SortedMap;
 use rustc_index::vec::IndexVec;
 use rustc_macros::HashStable_Generic;
 use rustc_span::source_map::Spanned;
@@ -22,7 +23,6 @@
 use rustc_target::spec::abi::Abi;
 
 use smallvec::SmallVec;
-use std::collections::BTreeMap;
 use std::fmt;
 
 #[derive(Copy, Clone, Encodable, HashStable_Generic)]
@@ -676,13 +676,13 @@ pub struct ParentedNode<'tcx> {
 /// Attributes owned by a HIR owner.
 #[derive(Debug)]
 pub struct AttributeMap<'tcx> {
-    pub map: BTreeMap<ItemLocalId, &'tcx [Attribute]>,
+    pub map: SortedMap<ItemLocalId, &'tcx [Attribute]>,
     pub hash: Fingerprint,
 }
 
 impl<'tcx> AttributeMap<'tcx> {
     pub const EMPTY: &'static AttributeMap<'static> =
-        &AttributeMap { map: BTreeMap::new(), hash: Fingerprint::ZERO };
+        &AttributeMap { map: SortedMap::new(), hash: Fingerprint::ZERO };
 
     #[inline]
     pub fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] {
@@ -705,7 +705,7 @@ pub struct OwnerNodes<'tcx> {
     // used.
     pub nodes: IndexVec<ItemLocalId, Option<ParentedNode<'tcx>>>,
     /// Content of local bodies.
-    pub bodies: IndexVec<ItemLocalId, Option<&'tcx Body<'tcx>>>,
+    pub bodies: SortedMap<ItemLocalId, &'tcx Body<'tcx>>,
 }
 
 /// Full information resulting from lowering an AST node.
index 877871f7c3d80b69655319fe65775e97a7c79f20..39552eb9f3102afa193135fcad0722cfd7a5dfe9 100644 (file)
@@ -1,5 +1,4 @@
 use crate::def_id::{LocalDefId, CRATE_DEF_INDEX};
-use rustc_index::vec::IndexVec;
 use std::fmt;
 
 /// Uniquely identifies a node in the HIR of the current crate. It is
@@ -66,70 +65,3 @@ impl ItemLocalId {
     owner: LocalDefId { local_def_index: CRATE_DEF_INDEX },
     local_id: ItemLocalId::from_u32(0),
 };
-
-/// N.B. This collection is currently unused, but will be used by #72015 and future PRs.
-#[derive(Clone, Default, Debug, Encodable, Decodable)]
-pub struct HirIdVec<T> {
-    map: IndexVec<LocalDefId, IndexVec<ItemLocalId, T>>,
-}
-
-impl<T> HirIdVec<T> {
-    pub fn push_owner(&mut self, id: LocalDefId) {
-        self.map.ensure_contains_elem(id, IndexVec::new);
-    }
-
-    pub fn push(&mut self, id: HirId, value: T) {
-        if id.local_id == ItemLocalId::from_u32(0) {
-            self.push_owner(id.owner);
-        }
-        let submap = &mut self.map[id.owner];
-        let _ret_id = submap.push(value);
-        debug_assert_eq!(_ret_id, id.local_id);
-    }
-
-    pub fn push_sparse(&mut self, id: HirId, value: T)
-    where
-        T: Default,
-    {
-        self.map.ensure_contains_elem(id.owner, IndexVec::new);
-        let submap = &mut self.map[id.owner];
-        let i = id.local_id.index();
-        let len = submap.len();
-        if i >= len {
-            submap.extend(std::iter::repeat_with(T::default).take(i - len + 1));
-        }
-        submap[id.local_id] = value;
-    }
-
-    pub fn get(&self, id: HirId) -> Option<&T> {
-        self.map.get(id.owner)?.get(id.local_id)
-    }
-
-    pub fn get_owner(&self, id: LocalDefId) -> &IndexVec<ItemLocalId, T> {
-        &self.map[id]
-    }
-
-    pub fn iter(&self) -> impl Iterator<Item = &T> {
-        self.map.iter().flat_map(|la| la.iter())
-    }
-
-    pub fn iter_enumerated(&self) -> impl Iterator<Item = (HirId, &T)> {
-        self.map.iter_enumerated().flat_map(|(owner, la)| {
-            la.iter_enumerated().map(move |(local_id, attr)| (HirId { owner, local_id }, attr))
-        })
-    }
-}
-
-impl<T> std::ops::Index<HirId> for HirIdVec<T> {
-    type Output = T;
-
-    fn index(&self, id: HirId) -> &T {
-        &self.map[id.owner][id.local_id]
-    }
-}
-
-impl<T> std::ops::IndexMut<HirId> for HirIdVec<T> {
-    fn index_mut(&mut self, id: HirId) -> &mut T {
-        &mut self.map[id.owner][id.local_id]
-    }
-}
index 97d4123138e8fa846e6255feec3545b3bcfd3da0..3037996d48bc03bb8e1a0ca1cc4847b53c7d082f 100644 (file)
@@ -281,12 +281,12 @@ pub fn extract<'a, F>(check_name: F, attrs: &'a [ast::Attribute]) -> Option<(Sym
     // in the sense that a crate is not required to have it defined to use it, but a final product
     // is required to define it somewhere. Additionally, there are restrictions on crates that use
     // a weak lang item, but do not have it defined.
-    Panic,                   sym::panic,               panic_fn,                   Target::Fn,             GenericRequirement::None;
+    Panic,                   sym::panic,               panic_fn,                   Target::Fn,             GenericRequirement::Exact(0);
     PanicFmt,                sym::panic_fmt,           panic_fmt,                  Target::Fn,             GenericRequirement::None;
     PanicDisplay,            sym::panic_display,       panic_display,              Target::Fn,             GenericRequirement::None;
     PanicStr,                sym::panic_str,           panic_str,                  Target::Fn,             GenericRequirement::None;
     ConstPanicFmt,           sym::const_panic_fmt,     const_panic_fmt,            Target::Fn,             GenericRequirement::None;
-    PanicBoundsCheck,        sym::panic_bounds_check,  panic_bounds_check_fn,      Target::Fn,             GenericRequirement::None;
+    PanicBoundsCheck,        sym::panic_bounds_check,  panic_bounds_check_fn,      Target::Fn,             GenericRequirement::Exact(0);
     PanicInfo,               sym::panic_info,          panic_info,                 Target::Struct,         GenericRequirement::None;
     PanicLocation,           sym::panic_location,      panic_location,             Target::Struct,         GenericRequirement::None;
     PanicImpl,               sym::panic_impl,          panic_impl,                 Target::Fn,             GenericRequirement::None;
index 0478fb2baa00f6d8b23a32e50f3d8ef4c5570939..dd3f8c937f81abd400017a7885e74a02990ada60 100644 (file)
@@ -5,7 +5,6 @@
 #![feature(let_else)]
 #![feature(nll)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate rustc_middle;
index 66399d2999848d1b6380362853bb61f19aec1016..45639bad24313164070e1ce4ae9162b3e71aa8b7 100644 (file)
@@ -124,10 +124,7 @@ impl $type {
 
             #[inline]
             $v const fn from_usize(value: usize) -> Self {
-                #[cfg(not(bootstrap))]
                 assert!(value <= ($max as usize));
-                #[cfg(bootstrap)]
-                [()][(value > ($max as usize)) as usize];
                 unsafe {
                     Self::from_u32_unchecked(value as u32)
                 }
@@ -135,10 +132,7 @@ impl $type {
 
             #[inline]
             $v const fn from_u32(value: u32) -> Self {
-                #[cfg(not(bootstrap))]
                 assert!(value <= $max);
-                #[cfg(bootstrap)]
-                [()][(value > $max) as usize];
                 unsafe {
                     Self::from_u32_unchecked(value)
                 }
index 2296cc6129ae8594a70f579b546d307a844418ad..5b4a9d9dfad456e43b201933ffe15107eb2f73d9 100644 (file)
@@ -108,7 +108,7 @@ fn make_query_response<T>(
         let tcx = self.tcx;
 
         // Select everything, returning errors.
-        let true_errors = fulfill_cx.select_where_possible(self).err().unwrap_or_else(Vec::new);
+        let true_errors = fulfill_cx.select_where_possible(self);
         debug!("true_errors = {:#?}", true_errors);
 
         if !true_errors.is_empty() {
@@ -118,7 +118,7 @@ fn make_query_response<T>(
         }
 
         // Anything left unselected *now* must be an ambiguity.
-        let ambig_errors = fulfill_cx.select_all_or_error(self).err().unwrap_or_else(Vec::new);
+        let ambig_errors = fulfill_cx.select_all_or_error(self);
         debug!("ambig_errors = {:#?}", ambig_errors);
 
         let region_obligations = self.take_registered_region_obligations();
index 3f54247ecef211bcd48e6e621b05d39037193e15..09bfb3290f4ca7d8f4956d6cb379bf2cde3fec34 100644 (file)
@@ -866,6 +866,7 @@ fn binders<T>(
         Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
     }
 
+    #[tracing::instrument(level = "debug", skip(self))]
     fn tys(&mut self, t: Ty<'tcx>, _t: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
         debug_assert_eq!(t, _t);
         debug!("ConstInferUnifier: t={:?}", t);
@@ -941,6 +942,7 @@ fn regions(
         }
     }
 
+    #[tracing::instrument(level = "debug", skip(self))]
     fn consts(
         &mut self,
         c: &'tcx ty::Const<'tcx>,
@@ -951,29 +953,38 @@ fn consts(
 
         match c.val {
             ty::ConstKind::Infer(InferConst::Var(vid)) => {
-                let mut inner = self.infcx.inner.borrow_mut();
-                let variable_table = &mut inner.const_unification_table();
-
                 // Check if the current unification would end up
                 // unifying `target_vid` with a const which contains
                 // an inference variable which is unioned with `target_vid`.
                 //
                 // Not doing so can easily result in stack overflows.
-                if variable_table.unioned(self.target_vid, vid) {
+                if self
+                    .infcx
+                    .inner
+                    .borrow_mut()
+                    .const_unification_table()
+                    .unioned(self.target_vid, vid)
+                {
                     return Err(TypeError::CyclicConst(c));
                 }
 
-                let var_value = variable_table.probe_value(vid);
+                let var_value =
+                    self.infcx.inner.borrow_mut().const_unification_table().probe_value(vid);
                 match var_value.val {
                     ConstVariableValue::Known { value: u } => self.consts(u, u),
                     ConstVariableValue::Unknown { universe } => {
                         if self.for_universe.can_name(universe) {
                             Ok(c)
                         } else {
-                            let new_var_id = variable_table.new_key(ConstVarValue {
-                                origin: var_value.origin,
-                                val: ConstVariableValue::Unknown { universe: self.for_universe },
-                            });
+                            let new_var_id =
+                                self.infcx.inner.borrow_mut().const_unification_table().new_key(
+                                    ConstVarValue {
+                                        origin: var_value.origin,
+                                        val: ConstVariableValue::Unknown {
+                                            universe: self.for_universe,
+                                        },
+                                    },
+                                );
                             Ok(self.tcx().mk_const_var(new_var_id, c.ty))
                         }
                     }
index 2173ff1f9ab035823c013e08abc3d757ea9602d3..8849d623b2dad2b7273e2d2525fc4f4973f14e5c 100644 (file)
@@ -1466,7 +1466,7 @@ fn add_labels_for_types(
                     let mut returned_async_output_error = false;
                     for &sp in values {
                         if sp.is_desugaring(DesugaringKind::Async) && !returned_async_output_error {
-                            if &[sp] != err.span.primary_spans() {
+                            if [sp] != err.span.primary_spans() {
                                 let mut span: MultiSpan = sp.into();
                                 span.push_span_label(
                                     sp,
index 1b35c4032f44c5d14e3fe30e935deb79a7dc4a64..ac57796763fb3cf30082f085707e5428cdd6785e 100644 (file)
@@ -7,7 +7,10 @@
 use crate::infer::lexical_region_resolve::RegionResolutionError;
 use crate::infer::SubregionOrigin;
 
-use rustc_errors::{struct_span_err, ErrorReported};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
+use rustc_hir as hir;
+use rustc_hir::{GenericParamKind, Ty};
+use rustc_middle::ty::Region;
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// Print the error message for lifetime errors when both the concerned regions are anonymous.
@@ -160,11 +163,13 @@ pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorReported> {
                 }
             };
 
-        let mut e = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch");
+        let mut err = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch");
 
-        e.span_label(span_1, main_label);
-        e.span_label(span_2, String::new());
-        e.span_label(span, span_label);
+        err.span_label(span_1, main_label);
+        err.span_label(span_2, String::new());
+        err.span_label(span, span_label);
+
+        self.suggest_adding_lifetime_params(sub, ty_sup, ty_sub, &mut err);
 
         if let Some(t) = future_return_type {
             let snip = self
@@ -178,14 +183,87 @@ pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorReported> {
                     (_, "") => None,
                     _ => Some(s),
                 })
-                .unwrap_or("{unnamed_type}".to_string());
+                .unwrap_or_else(|| "{unnamed_type}".to_string());
 
-            e.span_label(
+            err.span_label(
                 t.span,
                 &format!("this `async fn` implicitly returns an `impl Future<Output = {}>`", snip),
             );
         }
-        e.emit();
+        err.emit();
         Some(ErrorReported)
     }
+
+    fn suggest_adding_lifetime_params(
+        &self,
+        sub: Region<'tcx>,
+        ty_sup: &Ty<'_>,
+        ty_sub: &Ty<'_>,
+        err: &mut DiagnosticBuilder<'_>,
+    ) {
+        if let (
+            hir::Ty { kind: hir::TyKind::Rptr(lifetime_sub, _), .. },
+            hir::Ty { kind: hir::TyKind::Rptr(lifetime_sup, _), .. },
+        ) = (ty_sub, ty_sup)
+        {
+            if lifetime_sub.name.is_elided() && lifetime_sup.name.is_elided() {
+                if let Some(anon_reg) = self.tcx().is_suitable_region(sub) {
+                    let hir_id = self.tcx().hir().local_def_id_to_hir_id(anon_reg.def_id);
+                    if let hir::Node::Item(&hir::Item {
+                        kind: hir::ItemKind::Fn(_, ref generics, ..),
+                        ..
+                    }) = self.tcx().hir().get(hir_id)
+                    {
+                        let (suggestion_param_name, introduce_new) = generics
+                            .params
+                            .iter()
+                            .find(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
+                            .and_then(|p| self.tcx().sess.source_map().span_to_snippet(p.span).ok())
+                            .map(|name| (name, false))
+                            .unwrap_or_else(|| ("'a".to_string(), true));
+
+                        let mut suggestions = vec![
+                            if let hir::LifetimeName::Underscore = lifetime_sub.name {
+                                (lifetime_sub.span, suggestion_param_name.clone())
+                            } else {
+                                (
+                                    lifetime_sub.span.shrink_to_hi(),
+                                    suggestion_param_name.clone() + " ",
+                                )
+                            },
+                            if let hir::LifetimeName::Underscore = lifetime_sup.name {
+                                (lifetime_sup.span, suggestion_param_name.clone())
+                            } else {
+                                (
+                                    lifetime_sup.span.shrink_to_hi(),
+                                    suggestion_param_name.clone() + " ",
+                                )
+                            },
+                        ];
+
+                        if introduce_new {
+                            let new_param_suggestion = match &generics.params {
+                                [] => (generics.span, format!("<{}>", suggestion_param_name)),
+                                [first, ..] => (
+                                    first.span.shrink_to_lo(),
+                                    format!("{}, ", suggestion_param_name),
+                                ),
+                            };
+
+                            suggestions.push(new_param_suggestion);
+                        }
+
+                        err.multipart_suggestion(
+                            "consider introducing a named lifetime parameter",
+                            suggestions,
+                            Applicability::MaybeIncorrect,
+                        );
+                        err.note(
+                            "each elided lifetime in input position becomes a distinct lifetime",
+                        );
+                    }
+                }
+            }
+        }
+    }
 }
index 6b905f67e683f900b53ed0e9ca99dba49342161a..9dae978dcde7d9b79dd59c74335b6d2529a0684c 100644 (file)
@@ -1252,16 +1252,16 @@ pub fn set_tainted_by_errors(&self) {
         self.tainted_by_errors_flag.set(true)
     }
 
-    /// Process the region constraints and report any errors that
+    /// Process the region constraints and return any any errors that
     /// result. After this, no more unification operations should be
     /// done -- or the compiler will panic -- but it is legal to use
     /// `resolve_vars_if_possible` as well as `fully_resolve`.
-    pub fn resolve_regions_and_report_errors(
+    pub fn resolve_regions(
         &self,
         region_context: DefId,
         outlives_env: &OutlivesEnvironment<'tcx>,
         mode: RegionckMode,
-    ) {
+    ) -> Vec<RegionResolutionError<'tcx>> {
         let (var_infos, data) = {
             let mut inner = self.inner.borrow_mut();
             let inner = &mut *inner;
@@ -1287,6 +1287,21 @@ pub fn resolve_regions_and_report_errors(
         let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
         assert!(old_value.is_none());
 
+        errors
+    }
+
+    /// Process the region constraints and report any errors that
+    /// result. After this, no more unification operations should be
+    /// done -- or the compiler will panic -- but it is legal to use
+    /// `resolve_vars_if_possible` as well as `fully_resolve`.
+    pub fn resolve_regions_and_report_errors(
+        &self,
+        region_context: DefId,
+        outlives_env: &OutlivesEnvironment<'tcx>,
+        mode: RegionckMode,
+    ) {
+        let errors = self.resolve_regions(region_context, outlives_env, mode);
+
         if !self.is_tainted_by_errors() {
             // As a heuristic, just skip reporting region errors
             // altogether if other errors have been reported while
index d0883f23a4e6bb9237a7c8b83aa17f0dca6beb2c..e2e07f2072e498ea907e7fb176ed0ff9e9d811f2 100644 (file)
@@ -1,8 +1,17 @@
+use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use crate::infer::{InferCtxt, InferOk};
+use crate::traits;
+use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::vec_map::VecMap;
 use rustc_hir as hir;
-use rustc_middle::ty::{OpaqueTypeKey, Ty};
+use rustc_hir::def_id::LocalDefId;
+use rustc_middle::ty::fold::BottomUpFolder;
+use rustc_middle::ty::subst::{GenericArgKind, Subst};
+use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitor};
 use rustc_span::Span;
 
+use std::ops::ControlFlow;
+
 pub type OpaqueTypeMap<'tcx> = VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>;
 
 /// Information about the opaque types whose values we
@@ -45,3 +54,584 @@ pub struct OpaqueTypeDecl<'tcx> {
     /// The origin of the opaque type.
     pub origin: hir::OpaqueTyOrigin,
 }
+
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+    /// Replaces all opaque types in `value` with fresh inference variables
+    /// and creates appropriate obligations. For example, given the input:
+    ///
+    ///     impl Iterator<Item = impl Debug>
+    ///
+    /// this method would create two type variables, `?0` and `?1`. It would
+    /// return the type `?0` but also the obligations:
+    ///
+    ///     ?0: Iterator<Item = ?1>
+    ///     ?1: Debug
+    ///
+    /// Moreover, it returns an `OpaqueTypeMap` that would map `?0` to
+    /// info about the `impl Iterator<..>` type and `?1` to info about
+    /// the `impl Debug` type.
+    ///
+    /// # Parameters
+    ///
+    /// - `parent_def_id` -- the `DefId` of the function in which the opaque type
+    ///   is defined
+    /// - `body_id` -- the body-id with which the resulting obligations should
+    ///   be associated
+    /// - `param_env` -- the in-scope parameter environment to be used for
+    ///   obligations
+    /// - `value` -- the value within which we are instantiating opaque types
+    /// - `value_span` -- the span where the value came from, used in error reporting
+    pub fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
+        &self,
+        body_id: hir::HirId,
+        param_env: ty::ParamEnv<'tcx>,
+        value: T,
+        value_span: Span,
+    ) -> InferOk<'tcx, T> {
+        debug!(
+            "instantiate_opaque_types(value={:?}, body_id={:?}, \
+             param_env={:?}, value_span={:?})",
+            value, body_id, param_env, value_span,
+        );
+        let mut instantiator =
+            Instantiator { infcx: self, body_id, param_env, value_span, obligations: vec![] };
+        let value = instantiator.instantiate_opaque_types_in_map(value);
+        InferOk { value, obligations: instantiator.obligations }
+    }
+
+    /// Given the map `opaque_types` containing the opaque
+    /// `impl Trait` types whose underlying, hidden types are being
+    /// inferred, this method adds constraints to the regions
+    /// appearing in those underlying hidden types to ensure that they
+    /// at least do not refer to random scopes within the current
+    /// function. These constraints are not (quite) sufficient to
+    /// guarantee that the regions are actually legal values; that
+    /// final condition is imposed after region inference is done.
+    ///
+    /// # The Problem
+    ///
+    /// Let's work through an example to explain how it works. Assume
+    /// the current function is as follows:
+    ///
+    /// ```text
+    /// fn foo<'a, 'b>(..) -> (impl Bar<'a>, impl Bar<'b>)
+    /// ```
+    ///
+    /// Here, we have two `impl Trait` types whose values are being
+    /// inferred (the `impl Bar<'a>` and the `impl
+    /// Bar<'b>`). Conceptually, this is sugar for a setup where we
+    /// define underlying opaque types (`Foo1`, `Foo2`) and then, in
+    /// the return type of `foo`, we *reference* those definitions:
+    ///
+    /// ```text
+    /// type Foo1<'x> = impl Bar<'x>;
+    /// type Foo2<'x> = impl Bar<'x>;
+    /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
+    ///                    //  ^^^^ ^^
+    ///                    //  |    |
+    ///                    //  |    substs
+    ///                    //  def_id
+    /// ```
+    ///
+    /// As indicating in the comments above, each of those references
+    /// is (in the compiler) basically a substitution (`substs`)
+    /// applied to the type of a suitable `def_id` (which identifies
+    /// `Foo1` or `Foo2`).
+    ///
+    /// Now, at this point in compilation, what we have done is to
+    /// replace each of the references (`Foo1<'a>`, `Foo2<'b>`) with
+    /// fresh inference variables C1 and C2. We wish to use the values
+    /// of these variables to infer the underlying types of `Foo1` and
+    /// `Foo2`. That is, this gives rise to higher-order (pattern) unification
+    /// constraints like:
+    ///
+    /// ```text
+    /// for<'a> (Foo1<'a> = C1)
+    /// for<'b> (Foo1<'b> = C2)
+    /// ```
+    ///
+    /// For these equation to be satisfiable, the types `C1` and `C2`
+    /// can only refer to a limited set of regions. For example, `C1`
+    /// can only refer to `'static` and `'a`, and `C2` can only refer
+    /// to `'static` and `'b`. The job of this function is to impose that
+    /// constraint.
+    ///
+    /// Up to this point, C1 and C2 are basically just random type
+    /// inference variables, and hence they may contain arbitrary
+    /// regions. In fact, it is fairly likely that they do! Consider
+    /// this possible definition of `foo`:
+    ///
+    /// ```text
+    /// fn foo<'a, 'b>(x: &'a i32, y: &'b i32) -> (impl Bar<'a>, impl Bar<'b>) {
+    ///         (&*x, &*y)
+    ///     }
+    /// ```
+    ///
+    /// Here, the values for the concrete types of the two impl
+    /// traits will include inference variables:
+    ///
+    /// ```text
+    /// &'0 i32
+    /// &'1 i32
+    /// ```
+    ///
+    /// Ordinarily, the subtyping rules would ensure that these are
+    /// sufficiently large. But since `impl Bar<'a>` isn't a specific
+    /// type per se, we don't get such constraints by default. This
+    /// is where this function comes into play. It adds extra
+    /// constraints to ensure that all the regions which appear in the
+    /// inferred type are regions that could validly appear.
+    ///
+    /// This is actually a bit of a tricky constraint in general. We
+    /// want to say that each variable (e.g., `'0`) can only take on
+    /// values that were supplied as arguments to the opaque type
+    /// (e.g., `'a` for `Foo1<'a>`) or `'static`, which is always in
+    /// scope. We don't have a constraint quite of this kind in the current
+    /// region checker.
+    ///
+    /// # The Solution
+    ///
+    /// We generally prefer to make `<=` constraints, since they
+    /// integrate best into the region solver. To do that, we find the
+    /// "minimum" of all the arguments that appear in the substs: that
+    /// is, some region which is less than all the others. In the case
+    /// of `Foo1<'a>`, that would be `'a` (it's the only choice, after
+    /// all). Then we apply that as a least bound to the variables
+    /// (e.g., `'a <= '0`).
+    ///
+    /// In some cases, there is no minimum. Consider this example:
+    ///
+    /// ```text
+    /// fn baz<'a, 'b>() -> impl Trait<'a, 'b> { ... }
+    /// ```
+    ///
+    /// Here we would report a more complex "in constraint", like `'r
+    /// in ['a, 'b, 'static]` (where `'r` is some region appearing in
+    /// the hidden type).
+    ///
+    /// # Constrain regions, not the hidden concrete type
+    ///
+    /// Note that generating constraints on each region `Rc` is *not*
+    /// the same as generating an outlives constraint on `Tc` iself.
+    /// For example, if we had a function like this:
+    ///
+    /// ```rust
+    /// fn foo<'a, T>(x: &'a u32, y: T) -> impl Foo<'a> {
+    ///   (x, y)
+    /// }
+    ///
+    /// // Equivalent to:
+    /// type FooReturn<'a, T> = impl Foo<'a>;
+    /// fn foo<'a, T>(..) -> FooReturn<'a, T> { .. }
+    /// ```
+    ///
+    /// then the hidden type `Tc` would be `(&'0 u32, T)` (where `'0`
+    /// is an inference variable). If we generated a constraint that
+    /// `Tc: 'a`, then this would incorrectly require that `T: 'a` --
+    /// but this is not necessary, because the opaque type we
+    /// create will be allowed to reference `T`. So we only generate a
+    /// constraint that `'0: 'a`.
+    ///
+    /// # The `free_region_relations` parameter
+    ///
+    /// The `free_region_relations` argument is used to find the
+    /// "minimum" of the regions supplied to a given opaque type.
+    /// It must be a relation that can answer whether `'a <= 'b`,
+    /// where `'a` and `'b` are regions that appear in the "substs"
+    /// for the opaque type references (the `<'a>` in `Foo1<'a>`).
+    ///
+    /// Note that we do not impose the constraints based on the
+    /// generic regions from the `Foo1` definition (e.g., `'x`). This
+    /// is because the constraints we are imposing here is basically
+    /// the concern of the one generating the constraining type C1,
+    /// which is the current function. It also means that we can
+    /// take "implied bounds" into account in some cases:
+    ///
+    /// ```text
+    /// trait SomeTrait<'a, 'b> { }
+    /// fn foo<'a, 'b>(_: &'a &'b u32) -> impl SomeTrait<'a, 'b> { .. }
+    /// ```
+    ///
+    /// Here, the fact that `'b: 'a` is known only because of the
+    /// implied bounds from the `&'a &'b u32` parameter, and is not
+    /// "inherent" to the opaque type definition.
+    ///
+    /// # Parameters
+    ///
+    /// - `opaque_types` -- the map produced by `instantiate_opaque_types`
+    /// - `free_region_relations` -- something that can be used to relate
+    ///   the free regions (`'a`) that appear in the impl trait.
+    #[instrument(level = "debug", skip(self))]
+    pub fn constrain_opaque_type(
+        &self,
+        opaque_type_key: OpaqueTypeKey<'tcx>,
+        opaque_defn: &OpaqueTypeDecl<'tcx>,
+    ) {
+        let def_id = opaque_type_key.def_id;
+
+        let tcx = self.tcx;
+
+        let concrete_ty = self.resolve_vars_if_possible(opaque_defn.concrete_ty);
+
+        debug!(?concrete_ty);
+
+        let first_own_region = match opaque_defn.origin {
+            hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => {
+                // We lower
+                //
+                // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
+                //
+                // into
+                //
+                // type foo::<'p0..'pn>::Foo<'q0..'qm>
+                // fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
+                //
+                // For these types we only iterate over `'l0..lm` below.
+                tcx.generics_of(def_id).parent_count
+            }
+            // These opaque type inherit all lifetime parameters from their
+            // parent, so we have to check them all.
+            hir::OpaqueTyOrigin::TyAlias => 0,
+        };
+
+        // For a case like `impl Foo<'a, 'b>`, we would generate a constraint
+        // `'r in ['a, 'b, 'static]` for each region `'r` that appears in the
+        // hidden type (i.e., it must be equal to `'a`, `'b`, or `'static`).
+        //
+        // `conflict1` and `conflict2` are the two region bounds that we
+        // detected which were unrelated. They are used for diagnostics.
+
+        // Create the set of choice regions: each region in the hidden
+        // type can be equal to any of the region parameters of the
+        // opaque type definition.
+        let choice_regions: Lrc<Vec<ty::Region<'tcx>>> = Lrc::new(
+            opaque_type_key.substs[first_own_region..]
+                .iter()
+                .filter_map(|arg| match arg.unpack() {
+                    GenericArgKind::Lifetime(r) => Some(r),
+                    GenericArgKind::Type(_) | GenericArgKind::Const(_) => None,
+                })
+                .chain(std::iter::once(self.tcx.lifetimes.re_static))
+                .collect(),
+        );
+
+        concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
+            tcx: self.tcx,
+            op: |r| {
+                self.member_constraint(
+                    opaque_type_key.def_id,
+                    opaque_defn.definition_span,
+                    concrete_ty,
+                    r,
+                    &choice_regions,
+                )
+            },
+        });
+    }
+}
+
+// Visitor that requires that (almost) all regions in the type visited outlive
+// `least_region`. We cannot use `push_outlives_components` because regions in
+// closure signatures are not included in their outlives components. We need to
+// ensure all regions outlive the given bound so that we don't end up with,
+// say, `ReVar` appearing in a return type and causing ICEs when other
+// functions end up with region constraints involving regions from other
+// functions.
+//
+// We also cannot use `for_each_free_region` because for closures it includes
+// the regions parameters from the enclosing item.
+//
+// We ignore any type parameters because impl trait values are assumed to
+// capture all the in-scope type parameters.
+struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP> {
+    tcx: TyCtxt<'tcx>,
+    op: OP,
+}
+
+impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP>
+where
+    OP: FnMut(ty::Region<'tcx>),
+{
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        Some(self.tcx)
+    }
+
+    fn visit_binder<T: TypeFoldable<'tcx>>(
+        &mut self,
+        t: &ty::Binder<'tcx, T>,
+    ) -> ControlFlow<Self::BreakTy> {
+        t.as_ref().skip_binder().visit_with(self);
+        ControlFlow::CONTINUE
+    }
+
+    fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+        match *r {
+            // ignore bound regions, keep visiting
+            ty::ReLateBound(_, _) => ControlFlow::CONTINUE,
+            _ => {
+                (self.op)(r);
+                ControlFlow::CONTINUE
+            }
+        }
+    }
+
+    fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+        // We're only interested in types involving regions
+        if !ty.flags().intersects(ty::TypeFlags::HAS_POTENTIAL_FREE_REGIONS) {
+            return ControlFlow::CONTINUE;
+        }
+
+        match ty.kind() {
+            ty::Closure(_, ref substs) => {
+                // Skip lifetime parameters of the enclosing item(s)
+
+                substs.as_closure().tupled_upvars_ty().visit_with(self);
+                substs.as_closure().sig_as_fn_ptr_ty().visit_with(self);
+            }
+
+            ty::Generator(_, ref substs, _) => {
+                // Skip lifetime parameters of the enclosing item(s)
+                // Also skip the witness type, because that has no free regions.
+
+                substs.as_generator().tupled_upvars_ty().visit_with(self);
+                substs.as_generator().return_ty().visit_with(self);
+                substs.as_generator().yield_ty().visit_with(self);
+                substs.as_generator().resume_ty().visit_with(self);
+            }
+            _ => {
+                ty.super_visit_with(self);
+            }
+        }
+
+        ControlFlow::CONTINUE
+    }
+}
+
+struct Instantiator<'a, 'tcx> {
+    infcx: &'a InferCtxt<'a, 'tcx>,
+    body_id: hir::HirId,
+    param_env: ty::ParamEnv<'tcx>,
+    value_span: Span,
+    obligations: Vec<traits::PredicateObligation<'tcx>>,
+}
+
+impl<'a, 'tcx> Instantiator<'a, 'tcx> {
+    fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
+        let tcx = self.infcx.tcx;
+        value.fold_with(&mut BottomUpFolder {
+            tcx,
+            ty_op: |ty| {
+                if ty.references_error() {
+                    return tcx.ty_error();
+                } else if let ty::Opaque(def_id, substs) = ty.kind() {
+                    // Check that this is `impl Trait` type is
+                    // declared by `parent_def_id` -- i.e., one whose
+                    // value we are inferring.  At present, this is
+                    // always true during the first phase of
+                    // type-check, but not always true later on during
+                    // NLL. Once we support named opaque types more fully,
+                    // this same scenario will be able to arise during all phases.
+                    //
+                    // Here is an example using type alias `impl Trait`
+                    // that indicates the distinction we are checking for:
+                    //
+                    // ```rust
+                    // mod a {
+                    //   pub type Foo = impl Iterator;
+                    //   pub fn make_foo() -> Foo { .. }
+                    // }
+                    //
+                    // mod b {
+                    //   fn foo() -> a::Foo { a::make_foo() }
+                    // }
+                    // ```
+                    //
+                    // Here, the return type of `foo` references an
+                    // `Opaque` indeed, but not one whose value is
+                    // presently being inferred. You can get into a
+                    // similar situation with closure return types
+                    // today:
+                    //
+                    // ```rust
+                    // fn foo() -> impl Iterator { .. }
+                    // fn bar() {
+                    //     let x = || foo(); // returns the Opaque assoc with `foo`
+                    // }
+                    // ```
+                    if let Some(def_id) = def_id.as_local() {
+                        let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+                        let parent_def_id = self.infcx.defining_use_anchor;
+                        let def_scope_default = || {
+                            let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
+                            parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id)
+                        };
+                        let (in_definition_scope, origin) =
+                            match tcx.hir().expect_item(opaque_hir_id).kind {
+                                // Anonymous `impl Trait`
+                                hir::ItemKind::OpaqueTy(hir::OpaqueTy {
+                                    impl_trait_fn: Some(parent),
+                                    origin,
+                                    ..
+                                }) => (parent == parent_def_id.to_def_id(), origin),
+                                // Named `type Foo = impl Bar;`
+                                hir::ItemKind::OpaqueTy(hir::OpaqueTy {
+                                    impl_trait_fn: None,
+                                    origin,
+                                    ..
+                                }) => (
+                                    may_define_opaque_type(tcx, parent_def_id, opaque_hir_id),
+                                    origin,
+                                ),
+                                _ => (def_scope_default(), hir::OpaqueTyOrigin::TyAlias),
+                            };
+                        if in_definition_scope {
+                            let opaque_type_key =
+                                OpaqueTypeKey { def_id: def_id.to_def_id(), substs };
+                            return self.fold_opaque_ty(ty, opaque_type_key, origin);
+                        }
+
+                        debug!(
+                            "instantiate_opaque_types_in_map: \
+                             encountered opaque outside its definition scope \
+                             def_id={:?}",
+                            def_id,
+                        );
+                    }
+                }
+
+                ty
+            },
+            lt_op: |lt| lt,
+            ct_op: |ct| ct,
+        })
+    }
+
+    #[instrument(skip(self), level = "debug")]
+    fn fold_opaque_ty(
+        &mut self,
+        ty: Ty<'tcx>,
+        opaque_type_key: OpaqueTypeKey<'tcx>,
+        origin: hir::OpaqueTyOrigin,
+    ) -> Ty<'tcx> {
+        let infcx = self.infcx;
+        let tcx = infcx.tcx;
+        let OpaqueTypeKey { def_id, substs } = opaque_type_key;
+
+        // Use the same type variable if the exact same opaque type appears more
+        // than once in the return type (e.g., if it's passed to a type alias).
+        if let Some(opaque_defn) = infcx.inner.borrow().opaque_types.get(&opaque_type_key) {
+            debug!("re-using cached concrete type {:?}", opaque_defn.concrete_ty.kind());
+            return opaque_defn.concrete_ty;
+        }
+
+        let ty_var = infcx.next_ty_var(TypeVariableOrigin {
+            kind: TypeVariableOriginKind::TypeInference,
+            span: self.value_span,
+        });
+
+        // Ideally, we'd get the span where *this specific `ty` came
+        // from*, but right now we just use the span from the overall
+        // value being folded. In simple cases like `-> impl Foo`,
+        // these are the same span, but not in cases like `-> (impl
+        // Foo, impl Bar)`.
+        let definition_span = self.value_span;
+
+        {
+            let mut infcx = self.infcx.inner.borrow_mut();
+            infcx.opaque_types.insert(
+                OpaqueTypeKey { def_id, substs },
+                OpaqueTypeDecl { opaque_type: ty, definition_span, concrete_ty: ty_var, origin },
+            );
+            infcx.opaque_types_vars.insert(ty_var, ty);
+        }
+
+        debug!("generated new type inference var {:?}", ty_var.kind());
+
+        let item_bounds = tcx.explicit_item_bounds(def_id);
+
+        self.obligations.reserve(item_bounds.len());
+        for (predicate, _) in item_bounds {
+            debug!(?predicate);
+            let predicate = predicate.subst(tcx, substs);
+            debug!(?predicate);
+
+            // We can't normalize associated types from `rustc_infer`, but we can eagerly register inference variables for them.
+            let predicate = predicate.fold_with(&mut BottomUpFolder {
+                tcx,
+                ty_op: |ty| match ty.kind() {
+                    ty::Projection(projection_ty) => infcx.infer_projection(
+                        self.param_env,
+                        *projection_ty,
+                        traits::ObligationCause::misc(self.value_span, self.body_id),
+                        0,
+                        &mut self.obligations,
+                    ),
+                    _ => ty,
+                },
+                lt_op: |lt| lt,
+                ct_op: |ct| ct,
+            });
+            debug!(?predicate);
+
+            if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() {
+                if projection.ty.references_error() {
+                    // No point on adding these obligations since there's a type error involved.
+                    return tcx.ty_error();
+                }
+            }
+            // Change the predicate to refer to the type variable,
+            // which will be the concrete type instead of the opaque type.
+            // This also instantiates nested instances of `impl Trait`.
+            let predicate = self.instantiate_opaque_types_in_map(predicate);
+
+            let cause =
+                traits::ObligationCause::new(self.value_span, self.body_id, traits::OpaqueType);
+
+            // Require that the predicate holds for the concrete type.
+            debug!(?predicate);
+            self.obligations.push(traits::Obligation::new(cause, self.param_env, predicate));
+        }
+
+        ty_var
+    }
+}
+
+/// Returns `true` if `opaque_hir_id` is a sibling or a child of a sibling of `def_id`.
+///
+/// Example:
+/// ```rust
+/// pub mod foo {
+///     pub mod bar {
+///         pub trait Bar { .. }
+///
+///         pub type Baz = impl Bar;
+///
+///         fn f1() -> Baz { .. }
+///     }
+///
+///     fn f2() -> bar::Baz { .. }
+/// }
+/// ```
+///
+/// Here, `def_id` is the `LocalDefId` of the defining use of the opaque type (e.g., `f1` or `f2`),
+/// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`.
+/// For the above example, this function returns `true` for `f1` and `false` for `f2`.
+fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hir::HirId) -> bool {
+    let mut hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+
+    // Named opaque types can be defined by any siblings or children of siblings.
+    let scope = tcx.hir().get_defining_scope(opaque_hir_id);
+    // We walk up the node tree until we hit the root or the scope of the opaque type.
+    while hir_id != scope && hir_id != hir::CRATE_HIR_ID {
+        hir_id = tcx.hir().get_parent_item(hir_id);
+    }
+    // Syntactically, we are allowed to define the concrete type if:
+    let res = hir_id == scope;
+    trace!(
+        "may_define_opaque_type(def={:?}, opaque_node={:?}) = {}",
+        tcx.hir().find(hir_id),
+        tcx.hir().get(opaque_hir_id),
+        res
+    );
+    res
+}
index 9e04773c5fa2056c9bb4865d9051e938b5a0f86b..3947282aa6217f4dba820c79d75c6596e4294262 100644 (file)
@@ -99,7 +99,7 @@ pub fn region_bound_pairs_map(&self) -> &FxHashMap<hir::HirId, RegionBoundPairs<
     /// function. We can then add implied bounds and the like from the
     /// closure arguments into the environment -- these should only
     /// apply in the closure body, so once we exit, we invoke
-    /// `pop_snapshot_post_closure` to remove them.
+    /// `pop_snapshot_post_typeck_child` to remove them.
     ///
     /// Example:
     ///
@@ -129,12 +129,12 @@ pub fn region_bound_pairs_map(&self) -> &FxHashMap<hir::HirId, RegionBoundPairs<
     /// seems like it'd be readily fixed if we wanted. There are
     /// similar leaks around givens that seem equally suspicious, to
     /// be honest. --nmatsakis
-    pub fn push_snapshot_pre_closure(&self) -> usize {
+    pub fn push_snapshot_pre_typeck_child(&self) -> usize {
         self.region_bound_pairs_accum.len()
     }
 
-    /// See `push_snapshot_pre_closure`.
-    pub fn pop_snapshot_post_closure(&mut self, len: usize) {
+    /// See `push_snapshot_pre_typeck_child`.
+    pub fn pop_snapshot_post_typeck_child(&mut self, len: usize) {
         self.region_bound_pairs_accum.truncate(len);
     }
 
index 128a9428facbd6599fab4d11095a0e0fe65e274b..d0f1ff649d058a0558f80ef9258234fac1fd165a 100644 (file)
@@ -24,7 +24,6 @@
 #![feature(min_specialization)]
 #![feature(label_break_value)]
 #![recursion_limit = "512"] // For rustdoc
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate rustc_macros;
index dce4a87b041189a49910765f763ef7798d781a77..152a395c871be44a6008ba8cb46bd81c9094548a 100644 (file)
@@ -46,30 +46,25 @@ fn register_predicate_obligation(
         obligation: PredicateObligation<'tcx>,
     );
 
-    fn select_all_or_error(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>>;
+    fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec<FulfillmentError<'tcx>>;
 
     fn select_all_with_constness_or_error(
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
         _constness: hir::Constness,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+    ) -> Vec<FulfillmentError<'tcx>> {
         self.select_all_or_error(infcx)
     }
 
-    fn select_where_possible(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>>;
+    fn select_where_possible(&mut self, infcx: &InferCtxt<'_, 'tcx>)
+    -> Vec<FulfillmentError<'tcx>>;
 
     // FIXME(fee1-dead) this should not provide a default body for chalk as chalk should be updated
     fn select_with_constness_where_possible(
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
         _constness: hir::Constness,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+    ) -> Vec<FulfillmentError<'tcx>> {
         self.select_where_possible(infcx)
     }
 
index 81585f8f4e49c492e802ca855a645a40a4f7e6ea..7a6a643e3d0bb27ed53eb4e764da2f8989dae487 100644 (file)
@@ -38,7 +38,7 @@ pub struct Compiler {
     pub(crate) output_file: Option<PathBuf>,
     pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>>,
     pub(crate) override_queries:
-        Option<fn(&Session, &mut ty::query::Providers, &mut ty::query::Providers)>,
+        Option<fn(&Session, &mut ty::query::Providers, &mut ty::query::ExternProviders)>,
 }
 
 impl Compiler {
@@ -155,7 +155,7 @@ pub struct Config {
     ///
     /// The second parameter is local providers and the third parameter is external providers.
     pub override_queries:
-        Option<fn(&Session, &mut ty::query::Providers, &mut ty::query::Providers)>,
+        Option<fn(&Session, &mut ty::query::Providers, &mut ty::query::ExternProviders)>,
 
     /// This is a callback from the driver that is called to create a codegen backend.
     pub make_codegen_backend:
index 969df0fbf24d9127939ad751238e8cdd039b617b..2fc3759968fd3531d8c63857a98cbda411de3a00 100644 (file)
@@ -5,7 +5,6 @@
 #![feature(nll)]
 #![feature(once_cell)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 mod callbacks;
 pub mod interface;
index eea320835685cd5066039057601fd3a6f7b4fb08..3f6e879e6e44b778ef2576debe9424308d4be975 100644 (file)
@@ -19,7 +19,7 @@
 use rustc_metadata::{encode_metadata, EncodedMetadata};
 use rustc_middle::arena::Arena;
 use rustc_middle::dep_graph::DepGraph;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::query::{ExternProviders, Providers};
 use rustc_middle::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt};
 use rustc_mir_build as mir_build;
 use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr};
@@ -47,7 +47,7 @@
 use std::io::{self, BufWriter, Write};
 use std::lazy::SyncLazy;
 use std::marker::PhantomPinned;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 use std::pin::Pin;
 use std::rc::Rc;
 use std::{env, fs, iter};
@@ -536,7 +536,7 @@ fn check_output<F, T>(output_paths: &[PathBuf], f: F) -> Option<T>
     None
 }
 
-fn output_contains_path(output_paths: &[PathBuf], input_path: &PathBuf) -> bool {
+fn output_contains_path(output_paths: &[PathBuf], input_path: &Path) -> bool {
     let input_path = input_path.canonicalize().ok();
     if input_path.is_none() {
         return false;
@@ -552,7 +552,7 @@ fn output_conflicts_with_dir(output_paths: &[PathBuf]) -> Option<PathBuf> {
     check_output(output_paths, check)
 }
 
-fn escape_dep_filename(filename: &String) -> String {
+fn escape_dep_filename(filename: &str) -> String {
     // Apparently clang and gcc *only* escape spaces:
     // https://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4
     filename.replace(" ", "\\ ")
@@ -764,8 +764,8 @@ pub fn prepare_outputs(
     *providers
 });
 
-pub static DEFAULT_EXTERN_QUERY_PROVIDERS: SyncLazy<Providers> = SyncLazy::new(|| {
-    let mut extern_providers = *DEFAULT_QUERY_PROVIDERS;
+pub static DEFAULT_EXTERN_QUERY_PROVIDERS: SyncLazy<ExternProviders> = SyncLazy::new(|| {
+    let mut extern_providers = ExternProviders::default();
     rustc_metadata::provide_extern(&mut extern_providers);
     rustc_codegen_ssa::provide_extern(&mut extern_providers);
     extern_providers
@@ -816,7 +816,6 @@ pub fn create_global_ctxt<'tcx>(
     codegen_backend.provide(&mut local_providers);
 
     let mut extern_providers = *DEFAULT_EXTERN_QUERY_PROVIDERS;
-    codegen_backend.provide(&mut extern_providers);
     codegen_backend.provide_extern(&mut extern_providers);
 
     if let Some(callback) = compiler.override_queries {
index dab4d485e2d0b22d2c20c8e1e31a1dfd35e7ce26..2d3cb52f5fd478fc6718f715765ce8375479f73d 100644 (file)
@@ -744,6 +744,7 @@ macro_rules! tracked {
     tracked!(new_llvm_pass_manager, Some(true));
     tracked!(no_generate_arange_section, true);
     tracked!(no_link, true);
+    tracked!(no_unique_section_names, true);
     tracked!(no_profiler_runtime, true);
     tracked!(osx_rpath_install_name, true);
     tracked!(panic_abort_tests, true);
index cffb087af187f9be0d080b798b90b08dd8e93bba..946502378732a55dc2b373ae1cbcc06a715b41e9 100644 (file)
@@ -776,7 +776,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
     fn visit_item_kind(&mut self, i: &mut ast::ItemKind) {
         let is_const = match i {
             ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => true,
-            ast::ItemKind::Fn(box ast::FnKind(_, ref sig, _, _)) => Self::is_sig_const(sig),
+            ast::ItemKind::Fn(box ast::Fn { ref sig, .. }) => Self::is_sig_const(sig),
             _ => false,
         };
         self.run(is_const, |s| noop_visit_item_kind(i, s))
@@ -785,7 +785,7 @@ fn visit_item_kind(&mut self, i: &mut ast::ItemKind) {
     fn flat_map_trait_item(&mut self, i: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
         let is_const = match i.kind {
             ast::AssocItemKind::Const(..) => true,
-            ast::AssocItemKind::Fn(box ast::FnKind(_, ref sig, _, _)) => Self::is_sig_const(sig),
+            ast::AssocItemKind::Fn(box ast::Fn { ref sig, .. }) => Self::is_sig_const(sig),
             _ => false,
         };
         self.run(is_const, |s| noop_flat_map_assoc_item(i, s))
index b970c9e4911fafb36ff0612c0e30fb417d46437f..d789237e692d2beea5f514ee6f41b89080674be4 100644 (file)
@@ -68,11 +68,10 @@ pub enum EscapeError {
 impl EscapeError {
     /// Returns true for actual errors, as opposed to warnings.
     pub fn is_fatal(&self) -> bool {
-        match self {
-            EscapeError::UnskippedWhitespaceWarning => false,
-            EscapeError::MultipleSkippedLinesWarning => false,
-            _ => true,
-        }
+        !matches!(
+            self,
+            EscapeError::UnskippedWhitespaceWarning | EscapeError::MultipleSkippedLinesWarning
+        )
     }
 }
 
index c228ecb03fdec25f1d475fd9d9a2ef63ce0c6f0e..6548cdc0fdc52686e510fdd6b773371ab3377677 100644 (file)
@@ -369,12 +369,12 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
 
     fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
         match it.kind {
-            ast::ItemKind::Trait(box ast::TraitKind(_, ast::Unsafe::Yes(_), ..)) => self
+            ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => self
                 .report_unsafe(cx, it.span, |lint| {
                     lint.build("declaration of an `unsafe` trait").emit()
                 }),
 
-            ast::ItemKind::Impl(box ast::ImplKind { unsafety: ast::Unsafe::Yes(_), .. }) => self
+            ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => self
                 .report_unsafe(cx, it.span, |lint| {
                     lint.build("implementation of an `unsafe` trait").emit()
                 }),
@@ -921,7 +921,7 @@ fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) {
             // This is a hard error in future editions; avoid linting and erroring
             return;
         }
-        if let ast::AssocItemKind::Fn(box FnKind(_, ref sig, _, _)) = it.kind {
+        if let ast::AssocItemKind::Fn(box Fn { ref sig, .. }) = it.kind {
             for arg in sig.decl.inputs.iter() {
                 if let ast::PatKind::Ident(_, ident, None) = arg.pat.kind {
                     if ident.name == kw::Empty {
@@ -3130,18 +3130,13 @@ fn is_zero(expr: &hir::Expr<'_>) -> bool {
             false
         }
 
-        if let rustc_hir::ExprKind::Unary(ref un_op, ref expr_deref) = expr.kind {
-            if let rustc_hir::UnOp::Deref = un_op {
-                if is_null_ptr(cx, expr_deref) {
-                    cx.struct_span_lint(DEREF_NULLPTR, expr.span, |lint| {
-                        let mut err = lint.build("dereferencing a null pointer");
-                        err.span_label(
-                            expr.span,
-                            "this code causes undefined behavior when executed",
-                        );
-                        err.emit();
-                    });
-                }
+        if let rustc_hir::ExprKind::Unary(rustc_hir::UnOp::Deref, expr_deref) = expr.kind {
+            if is_null_ptr(cx, expr_deref) {
+                cx.struct_span_lint(DEREF_NULLPTR, expr.span, |lint| {
+                    let mut err = lint.build("dereferencing a null pointer");
+                    err.span_label(expr.span, "this code causes undefined behavior when executed");
+                    err.emit();
+                });
             }
         }
     }
@@ -3196,7 +3191,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
                         let snippet = template_snippet.as_str();
                         if let Some(pos) = snippet.find(needle) {
                             let end = pos
-                                + &snippet[pos..]
+                                + snippet[pos..]
                                     .find(|c| c == ':')
                                     .unwrap_or(snippet[pos..].len() - 1);
                             let inner = InnerSpan::new(pos, end);
index e34a92aba25f653c6e376438f4b85a7ea83b5aa1..4c936dec6f2cd3a72af9c3ca199a98708768009b 100644 (file)
@@ -18,6 +18,7 @@
 
 use crate::levels::{is_known_lint_tool, LintLevelsBuilder};
 use crate::passes::{EarlyLintPassObject, LateLintPassObject};
+use ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync;
@@ -39,7 +40,7 @@
 use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
 use rustc_session::Session;
 use rustc_span::lev_distance::find_best_match_for_name;
-use rustc_span::{symbol::Symbol, MultiSpan, Span, DUMMY_SP};
+use rustc_span::{symbol::Symbol, BytePos, MultiSpan, Span, DUMMY_SP};
 use rustc_target::abi;
 use tracing::debug;
 
@@ -144,11 +145,7 @@ pub fn get_lints<'t>(&'t self) -> &'t [&'static Lint] {
         &self.lints
     }
 
-    pub fn get_lint_groups<'t>(
-        &'t self,
-    ) -> impl Iterator<Item = (&'static str, Vec<LintId>, bool)> + 't {
-        // This function is not used in a way which observes the order of lints.
-        #[cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
+    pub fn get_lint_groups<'t>(&'t self) -> Vec<(&'static str, Vec<LintId>, bool)> {
         self.lint_groups
             .iter()
             .filter(|(_, LintGroup { depr, .. })| {
@@ -158,6 +155,7 @@ pub fn get_lint_groups<'t>(
             .map(|(k, LintGroup { lint_ids, from_plugin, .. })| {
                 (*k, lint_ids.clone(), *from_plugin)
             })
+            .collect()
     }
 
     pub fn register_early_pass(
@@ -600,6 +598,42 @@ fn lookup_with_diagnostics(
             // Now, set up surrounding context.
             let sess = self.sess();
             match diagnostic {
+                BuiltinLintDiagnostics::UnicodeTextFlow(span, content) => {
+                    let spans: Vec<_> = content
+                        .char_indices()
+                        .filter_map(|(i, c)| {
+                            TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| {
+                                let lo = span.lo() + BytePos(2 + i as u32);
+                                (c, span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32)))
+                            })
+                        })
+                        .collect();
+                    let (an, s) = match spans.len() {
+                        1 => ("an ", ""),
+                        _ => ("", "s"),
+                    };
+                    db.span_label(span, &format!(
+                        "this comment contains {}invisible unicode text flow control codepoint{}",
+                        an,
+                        s,
+                    ));
+                    for (c, span) in &spans {
+                        db.span_label(*span, format!("{:?}", c));
+                    }
+                    db.note(
+                        "these kind of unicode codepoints change the way text flows on \
+                         applications that support them, but can cause confusion because they \
+                         change the order of characters on the screen",
+                    );
+                    if !spans.is_empty() {
+                        db.multipart_suggestion_with_style(
+                            "if their presence wasn't intentional, you can remove them",
+                            spans.into_iter().map(|(_, span)| (span, "".to_string())).collect(),
+                            Applicability::MachineApplicable,
+                            SuggestionStyle::HideCodeAlways,
+                        );
+                    }
+                },
                 BuiltinLintDiagnostics::Normal => (),
                 BuiltinLintDiagnostics::BareTraitObject(span, is_global) => {
                     let (sugg, app) = match sess.source_map().span_to_snippet(span) {
diff --git a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
new file mode 100644 (file)
index 0000000..fde84be
--- /dev/null
@@ -0,0 +1,157 @@
+use crate::{EarlyContext, EarlyLintPass, LintContext};
+use ast::util::unicode::{contains_text_flow_control_chars, TEXT_FLOW_CONTROL_CHARS};
+use rustc_ast as ast;
+use rustc_errors::{Applicability, SuggestionStyle};
+use rustc_span::{BytePos, Span, Symbol};
+
+declare_lint! {
+    /// The `text_direction_codepoint_in_literal` lint detects Unicode codepoints that change the
+    /// visual representation of text on screen in a way that does not correspond to their on
+    /// memory representation.
+    ///
+    /// ### Explanation
+    ///
+    /// The unicode characters `\u{202A}`, `\u{202B}`, `\u{202D}`, `\u{202E}`, `\u{2066}`,
+    /// `\u{2067}`, `\u{2068}`, `\u{202C}` and `\u{2069}` make the flow of text on screen change
+    /// its direction on software that supports these codepoints. This makes the text "abc" display
+    /// as "cba" on screen. By leveraging software that supports these, people can write specially
+    /// crafted literals that make the surrounding code seem like it's performing one action, when
+    /// in reality it is performing another. Because of this, we proactively lint against their
+    /// presence to avoid surprises.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// #![deny(text_direction_codepoint_in_literal)]
+    /// fn main() {
+    ///     println!("{:?}", '‮');
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    pub TEXT_DIRECTION_CODEPOINT_IN_LITERAL,
+    Deny,
+    "detect special Unicode codepoints that affect the visual representation of text on screen, \
+     changing the direction in which text flows",
+}
+
+declare_lint_pass!(HiddenUnicodeCodepoints => [TEXT_DIRECTION_CODEPOINT_IN_LITERAL]);
+
+impl HiddenUnicodeCodepoints {
+    fn lint_text_direction_codepoint(
+        &self,
+        cx: &EarlyContext<'_>,
+        text: Symbol,
+        span: Span,
+        padding: u32,
+        point_at_inner_spans: bool,
+        label: &str,
+    ) {
+        // Obtain the `Span`s for each of the forbidden chars.
+        let spans: Vec<_> = text
+            .as_str()
+            .char_indices()
+            .filter_map(|(i, c)| {
+                TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| {
+                    let lo = span.lo() + BytePos(i as u32 + padding);
+                    (c, span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32)))
+                })
+            })
+            .collect();
+
+        cx.struct_span_lint(TEXT_DIRECTION_CODEPOINT_IN_LITERAL, span, |lint| {
+            let mut err = lint.build(&format!(
+                "unicode codepoint changing visible direction of text present in {}",
+                label
+            ));
+            let (an, s) = match spans.len() {
+                1 => ("an ", ""),
+                _ => ("", "s"),
+            };
+            err.span_label(
+                span,
+                &format!(
+                    "this {} contains {}invisible unicode text flow control codepoint{}",
+                    label, an, s,
+                ),
+            );
+            if point_at_inner_spans {
+                for (c, span) in &spans {
+                    err.span_label(*span, format!("{:?}", c));
+                }
+            }
+            err.note(
+                "these kind of unicode codepoints change the way text flows on applications that \
+                 support them, but can cause confusion because they change the order of \
+                 characters on the screen",
+            );
+            if point_at_inner_spans && !spans.is_empty() {
+                err.multipart_suggestion_with_style(
+                    "if their presence wasn't intentional, you can remove them",
+                    spans.iter().map(|(_, span)| (*span, "".to_string())).collect(),
+                    Applicability::MachineApplicable,
+                    SuggestionStyle::HideCodeAlways,
+                );
+                err.multipart_suggestion(
+                    "if you want to keep them but make them visible in your source code, you can \
+                    escape them",
+                    spans
+                        .into_iter()
+                        .map(|(c, span)| {
+                            let c = format!("{:?}", c);
+                            (span, c[1..c.len() - 1].to_string())
+                        })
+                        .collect(),
+                    Applicability::MachineApplicable,
+                );
+            } else {
+                // FIXME: in other suggestions we've reversed the inner spans of doc comments. We
+                // should do the same here to provide the same good suggestions as we do for
+                // literals above.
+                err.note("if their presence wasn't intentional, you can remove them");
+                err.note(&format!(
+                    "if you want to keep them but make them visible in your source code, you can \
+                     escape them: {}",
+                    spans
+                        .into_iter()
+                        .map(|(c, _)| { format!("{:?}", c) })
+                        .collect::<Vec<String>>()
+                        .join(", "),
+                ));
+            }
+            err.emit();
+        });
+    }
+}
+impl EarlyLintPass for HiddenUnicodeCodepoints {
+    fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
+        if let ast::AttrKind::DocComment(_, comment) = attr.kind {
+            if contains_text_flow_control_chars(&comment.as_str()) {
+                self.lint_text_direction_codepoint(cx, comment, attr.span, 0, false, "doc comment");
+            }
+        }
+    }
+
+    fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
+        // byte strings are already handled well enough by `EscapeError::NonAsciiCharInByteString`
+        let (text, span, padding) = match &expr.kind {
+            ast::ExprKind::Lit(ast::Lit { token, kind, span }) => {
+                let text = token.symbol;
+                if !contains_text_flow_control_chars(&text.as_str()) {
+                    return;
+                }
+                let padding = match kind {
+                    // account for `"` or `'`
+                    ast::LitKind::Str(_, ast::StrStyle::Cooked) | ast::LitKind::Char(_) => 1,
+                    // account for `r###"`
+                    ast::LitKind::Str(_, ast::StrStyle::Raw(val)) => *val as u32 + 2,
+                    _ => return,
+                };
+                (text, span, padding)
+            }
+            _ => return,
+        };
+        self.lint_text_direction_codepoint(cx, text, *span, padding, true, "literal");
+    }
+}
index e9dcc120200d0436e5b27c3f094b335860c5d461..c64a67b6b9f1b5c38dbc774948c62c0078930ed7 100644 (file)
@@ -5,7 +5,10 @@
 use rustc_ast as ast;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
-use rustc_hir::*;
+use rustc_hir::{
+    GenericArg, HirId, Item, ItemKind, MutTy, Mutability, Node, Path, PathSegment, QPath, Ty,
+    TyKind,
+};
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::hygiene::{ExpnKind, MacroKind};
@@ -48,60 +51,6 @@ fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, hir_id: HirId) {
     }
 }
 
-declare_tool_lint! {
-    pub rustc::POTENTIAL_QUERY_INSTABILITY,
-    Allow,
-    "require explicit opt-in when using potentially unstable methods or functions",
-    report_in_external_macro: true
-}
-
-declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY]);
-
-impl LateLintPass<'_> for QueryStability {
-    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
-        // FIXME(rustdoc): This lint uses typecheck results, causing rustdoc to
-        // error if there are resolution failures.
-        //
-        // As internal lints are currently always run if there are `unstable_options`,
-        // they are added to the lint store of rustdoc. Internal lints are also
-        // not used via the `lint_mod` query. Crate lints run outside of a query
-        // so rustdoc currently doesn't disable them.
-        //
-        // Instead of relying on this, either change crate lints to a query disabled by
-        // rustdoc, only run internal lints if the user is explicitly opting in
-        // or figure out a different way to avoid running lints for rustdoc.
-        if cx.tcx.sess.opts.actually_rustdoc {
-            return;
-        }
-
-        let (def_id, span) = match expr.kind {
-            ExprKind::Path(ref path) if let Some(def_id) = cx.qpath_res(path, expr.hir_id).opt_def_id() => {
-                (def_id, expr.span)
-            }
-            ExprKind::MethodCall(_, span, _, _) if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) => {
-                (def_id, span)
-            },
-            _ => return,
-        };
-
-        let substs = cx.typeck_results().node_substs(expr.hir_id);
-        if let Ok(Some(instance)) = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs) {
-            let def_id = instance.def_id();
-            if cx.tcx.has_attr(def_id, sym::rustc_lint_query_instability) {
-                cx.struct_span_lint(POTENTIAL_QUERY_INSTABILITY, span, |lint| {
-                    let msg = format!(
-                        "using `{}` can result in unstable query results",
-                        cx.tcx.item_name(def_id)
-                    );
-                    lint.build(&msg)
-                        .note("if you believe this case to be fine, allow this lint and add a comment explaining your rationale")
-                        .emit();
-                })
-            }
-        }
-    }
-}
-
 declare_tool_lint! {
     pub rustc::USAGE_OF_TY_TYKIND,
     Allow,
@@ -152,33 +101,31 @@ fn check_path(&mut self, cx: &LateContext<'_>, path: &'tcx Path<'tcx>, _: HirId)
 
     fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx Ty<'tcx>) {
         match &ty.kind {
-            TyKind::Path(qpath) => {
-                if let QPath::Resolved(_, path) = qpath {
-                    if let Some(last) = path.segments.iter().last() {
-                        if lint_ty_kind_usage(cx, last) {
-                            cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, |lint| {
-                                lint.build("usage of `ty::TyKind`")
-                                    .help("try using `Ty` instead")
-                                    .emit();
-                            })
-                        } else {
-                            if ty.span.from_expansion() {
-                                return;
-                            }
-                            if let Some(t) = is_ty_or_ty_ctxt(cx, ty) {
-                                if path.segments.len() > 1 {
-                                    cx.struct_span_lint(USAGE_OF_QUALIFIED_TY, path.span, |lint| {
-                                        lint.build(&format!("usage of qualified `ty::{}`", t))
-                                            .span_suggestion(
-                                                path.span,
-                                                "try using it unqualified",
-                                                t,
-                                                // The import probably needs to be changed
-                                                Applicability::MaybeIncorrect,
-                                            )
-                                            .emit();
-                                    })
-                                }
+            TyKind::Path(QPath::Resolved(_, path)) => {
+                if let Some(last) = path.segments.iter().last() {
+                    if lint_ty_kind_usage(cx, last) {
+                        cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, |lint| {
+                            lint.build("usage of `ty::TyKind`")
+                                .help("try using `Ty` instead")
+                                .emit();
+                        })
+                    } else {
+                        if ty.span.from_expansion() {
+                            return;
+                        }
+                        if let Some(t) = is_ty_or_ty_ctxt(cx, ty) {
+                            if path.segments.len() > 1 {
+                                cx.struct_span_lint(USAGE_OF_QUALIFIED_TY, path.span, |lint| {
+                                    lint.build(&format!("usage of qualified `ty::{}`", t))
+                                        .span_suggestion(
+                                            path.span,
+                                            "try using it unqualified",
+                                            t,
+                                            // The import probably needs to be changed
+                                            Applicability::MaybeIncorrect,
+                                        )
+                                        .emit();
+                                })
                             }
                         }
                     }
@@ -220,37 +167,30 @@ fn lint_ty_kind_usage(cx: &LateContext<'_>, segment: &PathSegment<'_>) -> bool {
 }
 
 fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, ty: &Ty<'_>) -> Option<String> {
-    if let TyKind::Path(qpath) = &ty.kind {
-        if let QPath::Resolved(_, path) = qpath {
-            match path.res {
-                Res::Def(_, def_id) => {
-                    if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(def_id)
-                    {
-                        return Some(format!(
-                            "{}{}",
-                            name,
-                            gen_args(path.segments.last().unwrap())
-                        ));
-                    }
+    if let TyKind::Path(QPath::Resolved(_, path)) = &ty.kind {
+        match path.res {
+            Res::Def(_, def_id) => {
+                if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(def_id) {
+                    return Some(format!("{}{}", name, gen_args(path.segments.last().unwrap())));
                 }
-                // Only lint on `&Ty` and `&TyCtxt` if it is used outside of a trait.
-                Res::SelfTy(None, Some((did, _))) => {
-                    if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
-                        if let Some(name @ (sym::Ty | sym::TyCtxt)) =
-                            cx.tcx.get_diagnostic_name(adt.did)
-                        {
-                            // NOTE: This path is currently unreachable as `Ty<'tcx>` is
-                            // defined as a type alias meaning that `impl<'tcx> Ty<'tcx>`
-                            // is not actually allowed.
-                            //
-                            // I(@lcnr) still kept this branch in so we don't miss this
-                            // if we ever change it in the future.
-                            return Some(format!("{}<{}>", name, substs[0]));
-                        }
+            }
+            // Only lint on `&Ty` and `&TyCtxt` if it is used outside of a trait.
+            Res::SelfTy(None, Some((did, _))) => {
+                if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
+                    if let Some(name @ (sym::Ty | sym::TyCtxt)) =
+                        cx.tcx.get_diagnostic_name(adt.did)
+                    {
+                        // NOTE: This path is currently unreachable as `Ty<'tcx>` is
+                        // defined as a type alias meaning that `impl<'tcx> Ty<'tcx>`
+                        // is not actually allowed.
+                        //
+                        // I(@lcnr) still kept this branch in so we don't miss this
+                        // if we ever change it in the future.
+                        return Some(format!("{}<{}>", name, substs[0]));
                     }
                 }
-                _ => (),
             }
+            _ => (),
         }
     }
 
@@ -289,8 +229,7 @@ fn gen_args(segment: &PathSegment<'_>) -> String {
 
 impl EarlyLintPass for LintPassImpl {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
-        if let ast::ItemKind::Impl(box ast::ImplKind { of_trait: Some(lint_pass), .. }) = &item.kind
-        {
+        if let ast::ItemKind::Impl(box ast::Impl { of_trait: Some(lint_pass), .. }) = &item.kind {
             if let Some(last) = lint_pass.path.segments.last() {
                 if last.ident.name == sym::LintPass {
                     let expn_data = lint_pass.path.span.ctxt().outer_expn_data();
index f83eaabdfefcde5de2705a50a964d65a0f35009a..f6514ddca9f57c26bf54647f7e1485520c5c237c 100644 (file)
 #![feature(box_patterns)]
 #![feature(crate_visibility_modifier)]
 #![feature(format_args_capture)]
-#![feature(if_let_guard)]
 #![feature(iter_order_by)]
 #![feature(iter_zip)]
 #![feature(never_type)]
 #![feature(nll)]
 #![feature(control_flow_enum)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate rustc_middle;
@@ -50,6 +48,7 @@
 mod context;
 mod early;
 mod enum_intrinsics_non_enums;
+pub mod hidden_unicode_codepoints;
 mod internal;
 mod late;
 mod levels;
@@ -80,6 +79,7 @@
 use array_into_iter::ArrayIntoIter;
 use builtin::*;
 use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
+use hidden_unicode_codepoints::*;
 use internal::*;
 use methods::*;
 use non_ascii_idents::*;
@@ -131,6 +131,7 @@ macro_rules! early_lint_passes {
                 DeprecatedAttr: DeprecatedAttr::new(),
                 WhileTrue: WhileTrue,
                 NonAsciiIdents: NonAsciiIdents,
+                HiddenUnicodeCodepoints: HiddenUnicodeCodepoints,
                 IncompleteFeatures: IncompleteFeatures,
                 RedundantSemicolons: RedundantSemicolons,
                 UnusedDocComment: UnusedDocComment,
@@ -302,7 +303,6 @@ macro_rules! register_passes {
         UNUSED_LABELS,
         UNUSED_PARENS,
         UNUSED_BRACES,
-        MUST_NOT_SUSPEND,
         REDUNDANT_SEMICOLONS
     );
 
@@ -486,8 +486,6 @@ fn register_internals(store: &mut LintStore) {
     store.register_early_pass(|| Box::new(LintPassImpl));
     store.register_lints(&DefaultHashTypes::get_lints());
     store.register_late_pass(|| Box::new(DefaultHashTypes));
-    store.register_lints(&QueryStability::get_lints());
-    store.register_late_pass(|| Box::new(QueryStability));
     store.register_lints(&ExistingDocKeyword::get_lints());
     store.register_late_pass(|| Box::new(ExistingDocKeyword));
     store.register_lints(&TyTyKind::get_lints());
@@ -498,7 +496,6 @@ fn register_internals(store: &mut LintStore) {
         None,
         vec![
             LintId::of(DEFAULT_HASH_TYPES),
-            LintId::of(POTENTIAL_QUERY_INSTABILITY),
             LintId::of(USAGE_OF_TY_TYKIND),
             LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
             LintId::of(TY_PASS_BY_REFERENCE),
index f35ca2659fd65661eae69ac75c8aa58e4f886729..c1a53c34b7a244d27cfbcdb8bc8289108b5debf4 100644 (file)
     ///
     /// ```rust
     /// #![feature(must_not_suspend)]
+    /// #![warn(must_not_suspend)]
     ///
     /// #[must_not_suspend]
     /// struct SyncThing {}
     /// `MutexGuard`'s)
     ///
     pub MUST_NOT_SUSPEND,
-    Warn,
+    Allow,
     "use of a `#[must_not_suspend]` value across a yield point",
+    @feature_gate = rustc_span::symbol::sym::must_not_suspend;
 }
 
 declare_lint! {
         BREAK_WITH_LABEL_AND_LOOP,
         UNUSED_ATTRIBUTES,
         NON_EXHAUSTIVE_OMITTED_PATTERNS,
+        TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
         DEREF_INTO_DYN_SUPERTRAIT,
     ]
 }
     @feature_gate = sym::non_exhaustive_omitted_patterns_lint;
 }
 
+declare_lint! {
+    /// The `text_direction_codepoint_in_comment` lint detects Unicode codepoints in comments that
+    /// change the visual representation of text on screen in a way that does not correspond to
+    /// their on memory representation.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// #![deny(text_direction_codepoint_in_comment)]
+    /// fn main() {
+    ///     println!("{:?}"); // '‮');
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Unicode allows changing the visual flow of text on screen in order to support scripts that
+    /// are written right-to-left, but a specially crafted comment can make code that will be
+    /// compiled appear to be part of a comment, depending on the software used to read the code.
+    /// To avoid potential problems or confusion, such as in CVE-2021-42574, by default we deny
+    /// their use.
+    pub TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
+    Deny,
+    "invisible directionality-changing codepoints in comment"
+}
+
 declare_lint! {
     /// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the
     /// `Deref` implementation with a `dyn SuperTrait` type as `Output`.
index f89d531b5ef5ceb8e403004c874d0c469d681cb8..feac2a7cfa48a77a8b0c88c296f5f584023478ab 100644 (file)
@@ -306,6 +306,7 @@ pub enum BuiltinLintDiagnostics {
     TrailingMacro(bool, Ident),
     BreakWithLabelAndLoop(Span),
     NamedAsmLabel(String),
+    UnicodeTextFlow(Span, String),
 }
 
 /// Lints that are buffered up early on in the `Session` before the
index 36a6d2cc33a99936b53df8c3566798683c9c71fb..943ce589c4f36ea41a19888cbe61af07159d0c40 100644 (file)
@@ -288,7 +288,7 @@ fn main() {
             let path = PathBuf::from(s);
             println!("cargo:rustc-link-search=native={}", path.parent().unwrap().display());
             if target.contains("windows") {
-                println!("cargo:rustc-link-lib=static-nobundle={}", stdcppname);
+                println!("cargo:rustc-link-lib=static:-bundle={}", stdcppname);
             } else {
                 println!("cargo:rustc-link-lib=static={}", stdcppname);
             }
@@ -302,6 +302,6 @@ fn main() {
     // Libstdc++ depends on pthread which Rust doesn't link on MinGW
     // since nothing else requires it.
     if target.contains("windows-gnu") {
-        println!("cargo:rustc-link-lib=static-nobundle=pthread");
+        println!("cargo:rustc-link-lib=static:-bundle=pthread");
     }
 }
index d6dc54c8d0ad6991ab2bbc86fa6a332d8642ecbc..ddbc3c5912836f1f8a9b3525c6045d9715fbca41 100644 (file)
@@ -75,6 +75,10 @@ extern "C" void LLVMTimeTraceProfilerInitialize() {
       /* ProcName */ "rustc");
 }
 
+extern "C" void LLVMTimeTraceProfilerFinishThread() {
+  timeTraceProfilerFinishThread();
+}
+
 extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) {
   StringRef FN(FileName);
   std::error_code EC;
@@ -462,6 +466,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
     LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat,
     bool FunctionSections,
     bool DataSections,
+    bool UniqueSectionNames,
     bool TrapUnreachable,
     bool Singlethread,
     bool AsmComments,
@@ -491,6 +496,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
   }
   Options.DataSections = DataSections;
   Options.FunctionSections = FunctionSections;
+  Options.UniqueSectionNames = UniqueSectionNames;
   Options.MCOptions.AsmVerbose = AsmComments;
   Options.MCOptions.PreserveAsmComments = AsmComments;
   Options.MCOptions.ABIName = ABIStr;
index 6493bd91ca27a836c54cb21bd80914b654474e6f..8476c2bfcc431ca7c8fe0a2e26323b4b6a9e918b 100644 (file)
@@ -1,5 +1,5 @@
 #![feature(nll)]
-#![feature(static_nobundle)]
+#![feature(native_link_modifiers)]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 
 // NOTE: This crate only exists to allow linking on mingw targets.
index dba885a27fe229f3c73176568cb4891135acf097..63bdcea87f8170a97df6b45df4f8bc8d8032e910 100644 (file)
@@ -24,11 +24,9 @@ fn parse_attributes(field: &syn::Field) -> Attributes {
                         }
                         if meta.path().is_ident("project") {
                             if let Meta::List(list) = meta {
-                                if let Some(nested) = list.nested.iter().next() {
-                                    if let NestedMeta::Meta(meta) = nested {
-                                        attrs.project = meta.path().get_ident().cloned();
-                                        any_attr = true;
-                                    }
+                                if let Some(NestedMeta::Meta(meta)) = list.nested.iter().next() {
+                                    attrs.project = meta.path().get_ident().cloned();
+                                    any_attr = true;
                                 }
                             }
                         }
index 443af50c5ff2c27b405ab6de9ebebc677a630cef..6dbba274360231a05c18e716b4a3d128bd1a3e75 100644 (file)
@@ -55,6 +55,9 @@ enum QueryModifier {
 
     /// Always evaluate the query, ignoring its dependencies
     EvalAlways(Ident),
+
+    /// Use a separate query provider for local and extern crates
+    SeparateProvideExtern(Ident),
 }
 
 impl Parse for QueryModifier {
@@ -118,6 +121,8 @@ fn parse(input: ParseStream<'_>) -> Result<Self> {
             Ok(QueryModifier::Anon(modifier))
         } else if modifier == "eval_always" {
             Ok(QueryModifier::EvalAlways(modifier))
+        } else if modifier == "separate_provide_extern" {
+            Ok(QueryModifier::SeparateProvideExtern(modifier))
         } else {
             Err(Error::new(modifier.span(), "unknown query modifier"))
         }
@@ -214,6 +219,9 @@ struct QueryModifiers {
 
     // Always evaluate the query, ignoring its dependencies
     eval_always: Option<Ident>,
+
+    /// Use a separate query provider for local and extern crates
+    separate_provide_extern: Option<Ident>,
 }
 
 /// Process query modifiers into a struct, erroring on duplicates
@@ -227,6 +235,7 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
     let mut no_hash = None;
     let mut anon = None;
     let mut eval_always = None;
+    let mut separate_provide_extern = None;
     for modifier in query.modifiers.0.drain(..) {
         match modifier {
             QueryModifier::LoadCached(tcx, id, block) => {
@@ -317,6 +326,15 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
                 }
                 eval_always = Some(ident);
             }
+            QueryModifier::SeparateProvideExtern(ident) => {
+                if separate_provide_extern.is_some() {
+                    panic!(
+                        "duplicate modifier `separate_provide_extern` for query `{}`",
+                        query.name
+                    );
+                }
+                separate_provide_extern = Some(ident);
+            }
         }
     }
     let desc = desc.unwrap_or_else(|| {
@@ -332,6 +350,7 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
         no_hash,
         anon,
         eval_always,
+        separate_provide_extern,
     }
 }
 
@@ -349,24 +368,14 @@ fn add_query_description_impl(
         let try_load_from_disk = if let Some((tcx, id, block)) = modifiers.load_cached.as_ref() {
             // Use custom code to load the query from disk
             quote! {
-                #[inline]
-                fn try_load_from_disk(
-                    #tcx: QueryCtxt<'tcx>,
-                    #id: SerializedDepNodeIndex
-                ) -> Option<Self::Value> {
-                    #block
-                }
+                const TRY_LOAD_FROM_DISK: Option<fn(QueryCtxt<$tcx>, SerializedDepNodeIndex) -> Option<Self::Value>>
+                    = Some(|#tcx, #id| { #block });
             }
         } else {
             // Use the default code to load the query from disk
             quote! {
-                #[inline]
-                fn try_load_from_disk(
-                    tcx: QueryCtxt<'tcx>,
-                    id: SerializedDepNodeIndex
-                ) -> Option<Self::Value> {
-                    tcx.on_disk_cache().as_ref()?.try_load_query_result(*tcx, id)
-                }
+                const TRY_LOAD_FROM_DISK: Option<fn(QueryCtxt<$tcx>, SerializedDepNodeIndex) -> Option<Self::Value>>
+                    = Some(|tcx, id| tcx.on_disk_cache().as_ref()?.try_load_query_result(*tcx, id));
             }
         };
 
@@ -380,12 +389,9 @@ fn try_load_from_disk(
         // expr is a `Block`, meaning that `{ #expr }` gets expanded
         // to `{ { stmts... } }`, which triggers the `unused_braces` lint.
         quote! {
-            #[inline]
             #[allow(unused_variables, unused_braces)]
-            fn cache_on_disk(
-                #tcx: QueryCtxt<'tcx>,
-                #key: &Self::Key,
-            ) -> bool {
+            #[inline]
+            fn cache_on_disk(#tcx: TyCtxt<'tcx>, #key: &Self::Key) -> bool {
                 #expr
             }
 
@@ -395,7 +401,14 @@ fn cache_on_disk(
         if modifiers.load_cached.is_some() {
             panic!("load_cached modifier on query `{}` without a cache modifier", name);
         }
-        quote! {}
+        quote! {
+            #[inline]
+            fn cache_on_disk(_: TyCtxt<'tcx>, _: &Self::Key) -> bool {
+                false
+            }
+
+            const TRY_LOAD_FROM_DISK: Option<fn(QueryCtxt<$tcx>, SerializedDepNodeIndex) -> Option<Self::Value>> = None;
+        }
     };
 
     let (tcx, desc) = modifiers.desc;
@@ -403,17 +416,17 @@ fn cache_on_disk(
 
     let desc = quote! {
         #[allow(unused_variables)]
-        fn describe(tcx: QueryCtxt<'tcx>, key: Self::Key) -> String {
+        fn describe(tcx: QueryCtxt<$tcx>, key: Self::Key) -> String {
             let (#tcx, #key) = (*tcx, key);
             ::rustc_middle::ty::print::with_no_trimmed_paths(|| format!(#desc).into())
         }
     };
 
     impls.extend(quote! {
-        impl<'tcx> QueryDescription<QueryCtxt<'tcx>> for queries::#name<'tcx> {
+        (#name<$tcx:tt>) => {
             #desc
             #cache
-        }
+        };
     });
 }
 
@@ -468,6 +481,10 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
         if let Some(eval_always) = &modifiers.eval_always {
             attributes.push(quote! { (#eval_always) });
         };
+        // Pass on the separate_provide_extern modifier
+        if let Some(separate_provide_extern) = &modifiers.separate_provide_extern {
+            attributes.push(quote! { (#separate_provide_extern) });
+        }
 
         // This uses the span of the query definition for the commas,
         // which can be important if we later encounter any ambiguity
@@ -521,7 +538,7 @@ macro_rules! rustc_cached_queries {
         }
         #[macro_export]
         macro_rules! rustc_query_description {
-            () => { #query_description_stream }
+            #query_description_stream
         }
     })
 }
index f71fefd17992083d4bd026199d7c3ca4e10e07fb..dec77d996f3f24cf040bf2694cc009a34f2578a4 100644 (file)
@@ -8,7 +8,7 @@ doctest = false
 
 [dependencies]
 libc = "0.2"
-odht = { version = "0.3.0", features = ["nightly"] }
+odht = { version = "0.3.1", features = ["nightly"] }
 snap = "1"
 tracing = "0.1"
 smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
index 95b74fd5306e54c75117f8508669406ca8488873..eb0a693226c480d51c91311cd63ddcc5bd1cfd76 100644 (file)
@@ -29,6 +29,7 @@
 
 use proc_macro::bridge::client::ProcMacro;
 use std::collections::BTreeMap;
+use std::ops::Fn;
 use std::path::Path;
 use std::{cmp, env};
 use tracing::{debug, info};
index f64f6cbeb594e100724da429a7fd87cb3d9fc2a0..6cf0dd8b1addbee40c76b377e7c05bb52c39455e 100644 (file)
@@ -10,7 +10,6 @@
 #![feature(try_blocks)]
 #![feature(never_type)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 extern crate proc_macro;
 
index bbd30c9327a6c3d501b5cf0720dc28e62cda7d91..7cba16e0a9ae38d9333afc16d1dc1b0b65699dfc 100644 (file)
 use std::io::{Read, Result as IoResult, Write};
 use std::path::{Path, PathBuf};
 use std::{cmp, fmt, fs};
-use tracing::{debug, info, warn};
+use tracing::{debug, info};
 
 #[derive(Clone)]
 crate struct CrateLocator<'a> {
@@ -350,6 +350,7 @@ impl<'a> CrateLocator<'a> {
         self.crate_rejections.via_kind.clear();
         self.crate_rejections.via_version.clear();
         self.crate_rejections.via_filename.clear();
+        self.crate_rejections.via_invalid.clear();
     }
 
     crate fn maybe_load_library_crate(&mut self) -> Result<Option<Library>, CrateError> {
@@ -548,8 +549,18 @@ fn extract_one(
                             continue;
                         }
                     }
-                    Err(err) => {
-                        warn!("no metadata found: {}", err);
+                    Err(MetadataError::LoadFailure(err)) => {
+                        info!("no metadata found: {}", err);
+                        // The file was present and created by the same compiler version, but we
+                        // couldn't load it for some reason.  Give a hard error instead of silently
+                        // ignoring it, but only if we would have given an error anyway.
+                        self.crate_rejections
+                            .via_invalid
+                            .push(CrateMismatch { path: lib, got: err });
+                        continue;
+                    }
+                    Err(err @ MetadataError::NotPresent(_)) => {
+                        info!("no metadata found: {}", err);
                         continue;
                     }
                 };
@@ -726,25 +737,28 @@ fn find_commandline_library(&mut self) -> Result<Option<Library>, CrateError> {
 fn get_metadata_section(
     target: &Target,
     flavor: CrateFlavor,
-    filename: &Path,
+    filename: &'p Path,
     loader: &dyn MetadataLoader,
-) -> Result<MetadataBlob, String> {
+) -> Result<MetadataBlob, MetadataError<'p>> {
     if !filename.exists() {
-        return Err(format!("no such file: '{}'", filename.display()));
+        return Err(MetadataError::NotPresent(filename));
     }
     let raw_bytes: MetadataRef = match flavor {
-        CrateFlavor::Rlib => loader.get_rlib_metadata(target, filename)?,
+        CrateFlavor::Rlib => {
+            loader.get_rlib_metadata(target, filename).map_err(MetadataError::LoadFailure)?
+        }
         CrateFlavor::Dylib => {
-            let buf = loader.get_dylib_metadata(target, filename)?;
+            let buf =
+                loader.get_dylib_metadata(target, filename).map_err(MetadataError::LoadFailure)?;
             // The header is uncompressed
             let header_len = METADATA_HEADER.len();
             debug!("checking {} bytes of metadata-version stamp", header_len);
             let header = &buf[..cmp::min(header_len, buf.len())];
             if header != METADATA_HEADER {
-                return Err(format!(
-                    "incompatible metadata version found: '{}'",
+                return Err(MetadataError::LoadFailure(format!(
+                    "invalid metadata version found: {}",
                     filename.display()
-                ));
+                )));
             }
 
             // Header is okay -> inflate the actual metadata
@@ -756,17 +770,28 @@ fn get_metadata_section(
             match FrameDecoder::new(compressed_bytes).read_to_end(&mut inflated) {
                 Ok(_) => rustc_erase_owner!(OwningRef::new(inflated).map_owner_box()),
                 Err(_) => {
-                    return Err(format!("failed to decompress metadata: {}", filename.display()));
+                    return Err(MetadataError::LoadFailure(format!(
+                        "failed to decompress metadata: {}",
+                        filename.display()
+                    )));
                 }
             }
         }
         CrateFlavor::Rmeta => {
             // mmap the file, because only a small fraction of it is read.
-            let file = std::fs::File::open(filename)
-                .map_err(|_| format!("failed to open rmeta metadata: '{}'", filename.display()))?;
+            let file = std::fs::File::open(filename).map_err(|_| {
+                MetadataError::LoadFailure(format!(
+                    "failed to open rmeta metadata: '{}'",
+                    filename.display()
+                ))
+            })?;
             let mmap = unsafe { Mmap::map(file) };
-            let mmap = mmap
-                .map_err(|_| format!("failed to mmap rmeta metadata: '{}'", filename.display()))?;
+            let mmap = mmap.map_err(|_| {
+                MetadataError::LoadFailure(format!(
+                    "failed to mmap rmeta metadata: '{}'",
+                    filename.display()
+                ))
+            })?;
 
             rustc_erase_owner!(OwningRef::new(mmap).map_owner_box())
         }
@@ -775,7 +800,10 @@ fn get_metadata_section(
     if blob.is_compatible() {
         Ok(blob)
     } else {
-        Err(format!("incompatible metadata version found: '{}'", filename.display()))
+        Err(MetadataError::LoadFailure(format!(
+            "invalid metadata version found: {}",
+            filename.display()
+        )))
     }
 }
 
@@ -854,6 +882,7 @@ struct CrateRejections {
     via_kind: Vec<CrateMismatch>,
     via_version: Vec<CrateMismatch>,
     via_filename: Vec<CrateMismatch>,
+    via_invalid: Vec<CrateMismatch>,
 }
 
 /// Candidate rejection reasons collected during crate search.
@@ -883,6 +912,24 @@ struct CrateRejections {
     NonDylibPlugin(Symbol),
 }
 
+enum MetadataError<'a> {
+    /// The file was missing.
+    NotPresent(&'a Path),
+    /// The file was present and invalid.
+    LoadFailure(String),
+}
+
+impl fmt::Display for MetadataError<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            MetadataError::NotPresent(filename) => {
+                f.write_str(&format!("no such file: '{}'", filename.display()))
+            }
+            MetadataError::LoadFailure(msg) => f.write_str(msg),
+        }
+    }
+}
+
 impl CrateError {
     crate fn report(self, sess: &Session, span: Span, missing_core: bool) -> ! {
         let mut err = match self {
@@ -1064,6 +1111,19 @@ impl CrateError {
                     }
                     err.note(&msg);
                     err
+                } else if !locator.crate_rejections.via_invalid.is_empty() {
+                    let mut err = struct_span_err!(
+                        sess,
+                        span,
+                        E0786,
+                        "found invalid metadata files for crate `{}`{}",
+                        crate_name,
+                        add,
+                    );
+                    for CrateMismatch { path: _, got } in locator.crate_rejections.via_invalid {
+                        err.note(&got);
+                    }
+                    err
                 } else {
                     let mut err = struct_span_err!(
                         sess,
index 2431b819a3f30e25d3507cd84c735703a2205771..bd5cda15b91abcfc18b6a6cc8ac089d25e7c5389 100644 (file)
@@ -309,7 +309,7 @@ fn process_command_line(&mut self) {
                     .libs
                     .iter()
                     .filter_map(|lib| lib.name.as_ref())
-                    .any(|n| &n.as_str() == &lib.name);
+                    .any(|n| n.as_str() == lib.name);
                 if new_name.is_empty() {
                     self.tcx.sess.err(&format!(
                         "an empty renaming target was specified for library `{}`",
index ca9daa49aa2d2115d4e522d23ef38996af7f7a80..5e90aec003e9b1a20e381b1069059a87b1125bc6 100644 (file)
@@ -1198,8 +1198,8 @@ fn each_child_of_item(&self, id: DefIndex, mut callback: impl FnMut(Export), ses
             }
         }
 
-        if let EntryKind::Mod(data) = kind {
-            for exp in data.decode((self, sess)).reexports.decode((self, sess)) {
+        if let EntryKind::Mod(exports) = kind {
+            for exp in exports.decode((self, sess)) {
                 match exp.res {
                     Res::Def(DefKind::Macro(..), _) => {}
                     _ if macros_only => continue,
@@ -1219,10 +1219,11 @@ fn is_item_mir_available(&self, id: DefIndex) -> bool {
     }
 
     fn module_expansion(&self, id: DefIndex, sess: &Session) -> ExpnId {
-        if let EntryKind::Mod(m) = self.kind(id) {
-            m.decode((self, sess)).expansion
-        } else {
-            panic!("Expected module, found {:?}", self.local_def_id(id))
+        match self.kind(id) {
+            EntryKind::Mod(_) | EntryKind::Enum(_) | EntryKind::Trait(_) => {
+                self.get_expn_that_defined(id, sess)
+            }
+            _ => panic!("Expected module, found {:?}", self.local_def_id(id)),
         }
     }
 
index e12f049a90bdf54cee9d9e2cc62470fc7490bc60..7ea004b16f23bc3546f4db41827ca4ef927a22a0 100644 (file)
@@ -10,7 +10,7 @@
 use rustc_middle::hir::exports::Export;
 use rustc_middle::middle::exported_symbols::ExportedSymbol;
 use rustc_middle::middle::stability::DeprecationEntry;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::query::{ExternProviders, Providers};
 use rustc_middle::ty::{self, TyCtxt, Visibility};
 use rustc_session::cstore::{CrateSource, CrateStore, ForeignModule};
 use rustc_session::utils::NativeLibKind;
@@ -26,7 +26,7 @@
 macro_rules! provide {
     (<$lt:tt> $tcx:ident, $def_id:ident, $other:ident, $cdata:ident,
       $($name:ident => $compute:block)*) => {
-        pub fn provide_extern(providers: &mut Providers) {
+        pub fn provide_extern(providers: &mut ExternProviders) {
             $(fn $name<$lt>(
                 $tcx: TyCtxt<$lt>,
                 def_id_arg: ty::query::query_keys::$name<$lt>,
@@ -51,7 +51,7 @@ pub fn provide_extern(providers: &mut Providers) {
                 $compute
             })*
 
-            *providers = Providers {
+            *providers = ExternProviders {
                 $($name,)*
                 ..*providers
             };
index 20f7b059b56008c77c22a456a188efebdb8c7cf4..aff5e02d0c655dc5b27909eba4a84b26d7759a51 100644 (file)
@@ -797,6 +797,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool {
         | DefKind::ConstParam
         | DefKind::LifetimeParam
         | DefKind::AnonConst
+        | DefKind::InlineConst
         | DefKind::GlobalAsm
         | DefKind::Closure
         | DefKind::Generator
@@ -832,6 +833,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool {
         DefKind::Use
         | DefKind::LifetimeParam
         | DefKind::AnonConst
+        | DefKind::InlineConst
         | DefKind::GlobalAsm
         | DefKind::Closure
         | DefKind::Generator
@@ -856,9 +858,11 @@ fn should_encode_mir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> (bool, bool) {
             (true, mir_opt_base)
         }
         // Constants
-        DefKind::AnonConst | DefKind::AssocConst | DefKind::Static | DefKind::Const => {
-            (true, false)
-        }
+        DefKind::AnonConst
+        | DefKind::InlineConst
+        | DefKind::AssocConst
+        | DefKind::Static
+        | DefKind::Const => (true, false),
         // Full-fledged functions
         DefKind::AssocFn | DefKind::Fn => {
             let generics = tcx.generics_of(def_id);
@@ -914,6 +918,7 @@ fn should_encode_variances(def_kind: DefKind) -> bool {
         | DefKind::Use
         | DefKind::LifetimeParam
         | DefKind::AnonConst
+        | DefKind::InlineConst
         | DefKind::GlobalAsm
         | DefKind::Closure
         | DefKind::Generator
@@ -939,6 +944,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool {
         | DefKind::AssocFn
         | DefKind::AssocConst
         | DefKind::AnonConst
+        | DefKind::InlineConst
         | DefKind::OpaqueTy
         | DefKind::Impl
         | DefKind::Field
@@ -1086,11 +1092,11 @@ fn encode_info_for_mod(&mut self, local_def_id: LocalDefId, md: &hir::Mod<'_>) {
             Lazy::empty()
         };
 
-        let data = ModData { reexports, expansion: tcx.expn_that_defined(local_def_id) };
-
-        record!(self.tables.kind[def_id] <- EntryKind::Mod(self.lazy(data)));
+        record!(self.tables.kind[def_id] <- EntryKind::Mod(reexports));
         if self.is_proc_macro {
             record!(self.tables.children[def_id] <- &[]);
+            // Encode this here because we don't do it in encode_def_ids.
+            record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id));
         } else {
             record!(self.tables.children[def_id] <- md.item_ids.iter().map(|item_id| {
                 item_id.def_id.local_def_index
index 42855e9d9d12f2fc25fda08857d48f3b8b0b908c..4e09d23169aca3c771b86ad12d68c6ec713c32b2 100644 (file)
@@ -346,7 +346,7 @@ enum EntryKind {
     Union(Lazy<VariantData>, ReprOptions),
     Fn(Lazy<FnData>),
     ForeignFn(Lazy<FnData>),
-    Mod(Lazy<ModData>),
+    Mod(Lazy<[Export]>),
     MacroDef(Lazy<MacroDef>),
     ProcMacro(MacroKind),
     Closure,
@@ -364,12 +364,6 @@ enum EntryKind {
 #[derive(Encodable, Decodable)]
 struct RenderedConst(String);
 
-#[derive(MetadataEncodable, MetadataDecodable)]
-struct ModData {
-    reexports: Lazy<[Export]>,
-    expansion: ExpnId,
-}
-
 #[derive(MetadataEncodable, MetadataDecodable)]
 struct FnData {
     asyncness: hir::IsAsync,
index fad7e875fa1c025ac4a6434aab0c109d76aece10..d9d0781b37aacefe4afab97366de2b6448907d6e 100644 (file)
@@ -266,7 +266,15 @@ pub fn opt_def_kind(&self, local_def_id: LocalDefId) -> Option<DefKind> {
                 };
                 DefKind::Ctor(ctor_of, def::CtorKind::from_hir(variant_data))
             }
-            Node::AnonConst(_) => DefKind::AnonConst,
+            Node::AnonConst(_) => {
+                let inline = match self.find(self.get_parent_node(hir_id)) {
+                    Some(Node::Expr(&Expr {
+                        kind: ExprKind::ConstBlock(ref anon_const), ..
+                    })) if anon_const.hir_id == hir_id => true,
+                    _ => false,
+                };
+                if inline { DefKind::InlineConst } else { DefKind::AnonConst }
+            }
             Node::Field(_) => DefKind::Field,
             Node::Expr(expr) => match expr.kind {
                 ExprKind::Closure(.., None) => DefKind::Closure,
@@ -376,7 +384,7 @@ pub fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
     }
 
     pub fn body(&self, id: BodyId) -> &'hir Body<'hir> {
-        self.tcx.hir_owner_nodes(id.hir_id.owner).unwrap().bodies[id.hir_id.local_id].unwrap()
+        self.tcx.hir_owner_nodes(id.hir_id.owner).unwrap().bodies[&id.hir_id.local_id]
     }
 
     pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> {
@@ -495,13 +503,10 @@ pub fn body_owners(self) -> impl Iterator<Item = LocalDefId> + 'hir {
             .iter_enumerated()
             .flat_map(move |(owner, owner_info)| {
                 let bodies = &owner_info.as_ref()?.nodes.bodies;
-                Some(bodies.iter_enumerated().filter_map(move |(local_id, body)| {
-                    if body.is_none() {
-                        return None;
-                    }
+                Some(bodies.iter().map(move |&(local_id, _)| {
                     let hir_id = HirId { owner, local_id };
                     let body_id = BodyId { hir_id };
-                    Some(self.body_owner_def_id(body_id))
+                    self.body_owner_def_id(body_id)
                 }))
             })
             .flatten()
@@ -515,13 +520,10 @@ pub fn par_body_owners<F: Fn(LocalDefId) + Sync + Send>(self, f: F) {
         par_iter(&self.krate().owners.raw).enumerate().for_each(|(owner, owner_info)| {
             let owner = LocalDefId::new(owner);
             if let Some(owner_info) = owner_info {
-                par_iter(&owner_info.nodes.bodies.raw).enumerate().for_each(|(local_id, body)| {
-                    if body.is_some() {
-                        let local_id = ItemLocalId::new(local_id);
-                        let hir_id = HirId { owner, local_id };
-                        let body_id = BodyId { hir_id };
-                        f(self.body_owner_def_id(body_id))
-                    }
+                par_iter(owner_info.nodes.bodies.range(..)).for_each(|(local_id, _)| {
+                    let hir_id = HirId { owner, local_id: *local_id };
+                    let body_id = BodyId { hir_id };
+                    f(self.body_owner_def_id(body_id))
                 })
             }
         });
@@ -578,8 +580,8 @@ pub fn walk_attributes(self, visitor: &mut impl Visitor<'hir>) {
         let krate = self.krate();
         for (owner, info) in krate.owners.iter_enumerated() {
             if let Some(info) = info {
-                for (&local_id, attrs) in info.attrs.map.iter() {
-                    let id = HirId { owner, local_id };
+                for (local_id, attrs) in info.attrs.map.iter() {
+                    let id = HirId { owner, local_id: *local_id };
                     for a in *attrs {
                         visitor.visit_attribute(id, a)
                     }
index d90eb839cf6014f78f963fb6bf43699d20859bd7..0894b80507581458cb006426ed59e7b33158347e 100644 (file)
@@ -56,7 +56,6 @@
 #![feature(try_reserve_kind)]
 #![feature(nonzero_ops)]
 #![recursion_limit = "512"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate bitflags;
index 1eba2994ed36e89af4038a3193094648d59e5500..0e70d49ef49d25faa9f12189bb36f4b394d4b220 100644 (file)
@@ -248,8 +248,12 @@ fn struct_lint_level_impl(
             (Level::Warn, None) => sess.struct_warn(""),
             (Level::ForceWarn, Some(span)) => sess.struct_span_force_warn(span, ""),
             (Level::ForceWarn, None) => sess.struct_force_warn(""),
-            (Level::Deny | Level::Forbid, Some(span)) => sess.struct_span_err(span, ""),
-            (Level::Deny | Level::Forbid, None) => sess.struct_err(""),
+            (Level::Deny | Level::Forbid, Some(span)) => {
+                let mut builder = sess.diagnostic().struct_err_lint("");
+                builder.set_span(span);
+                builder
+            }
+            (Level::Deny | Level::Forbid, None) => sess.diagnostic().struct_err_lint(""),
         };
 
         // If this code originates in a foreign macro, aka something that this crate
index 9472a287e5a41907c5f434729376484048582a1e..7a51bb4a1f32ae828f9de259450a815ba37981c1 100644 (file)
@@ -538,12 +538,12 @@ impl InterpError<'_> {
     /// To avoid performance issues, there are places where we want to be sure to never raise these formatting errors,
     /// so this method lets us detect them and `bug!` on unexpected errors.
     pub fn formatted_string(&self) -> bool {
-        match self {
+        matches!(
+            self,
             InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
-            | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure { .. })
-            | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) => true,
-            _ => false,
-        }
+                | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure { .. })
+                | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
+        )
     }
 
     /// Should this error be reported as a hard error, preventing compilation, or a soft error,
index 971556d4463004328c08c94838ebf1b73b3528e5..253ac266bedaa246cc1039b9a6e5191447cb152b 100644 (file)
@@ -2665,7 +2665,7 @@ fn map_projections(
         mut self,
         mut f: impl FnMut(UserTypeProjection) -> UserTypeProjection,
     ) -> Self {
-        self.contents = self.contents.drain(..).map(|(proj, span)| (f(proj), span)).collect();
+        self.contents = self.contents.into_iter().map(|(proj, span)| (f(proj), span)).collect();
         self
     }
 
index 8e363cfbff562d594d9850dfa52c0a6ed2ed553e..8e1b887f87da75695eb5c41a6156250db02171e8 100644 (file)
@@ -958,7 +958,7 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn Write) -> io::Res
             write!(w, "static {}", if tcx.is_mutable_static(def_id) { "mut " } else { "" })?
         }
         (_, _) if is_function => write!(w, "fn ")?,
-        (DefKind::AnonConst, _) => {} // things like anon const, not an item
+        (DefKind::AnonConst | DefKind::InlineConst, _) => {} // things like anon const, not an item
         _ => bug!("Unexpected def kind {:?}", kind),
     }
 
index 42683dac426e3b1fdd5271658149c50ca42bd014..1260c691e7844cfb1fc1447c51d938114233f280 100644 (file)
@@ -632,11 +632,11 @@ fn tooltip<'tcx>(
     for statement in statements {
         let source_range = source_range_no_file(tcx, &statement.source_info.span);
         text.push(format!(
-            "\n{}{}: {}: {}",
+            "\n{}{}: {}: {:?}",
             TOOLTIP_INDENT,
             source_range,
             statement_kind_name(&statement),
-            format!("{:?}", statement)
+            statement
         ));
     }
     if let Some(term) = terminator {
index c6c0fdc8851269d64339e2bdf955d0e7d1d3522f..a9f94b74c5efb2ade9d3fb13dbefe222f31f8386 100644 (file)
     /// parameter. e.g. `fn example<const N: usize=3>` called on `N` would return `3`.
     query const_param_default(param: DefId) -> &'tcx ty::Const<'tcx> {
         desc { |tcx| "compute const default for a given parameter `{}`", tcx.def_path_str(param)  }
+        separate_provide_extern
     }
 
     query default_anon_const_substs(key: DefId) -> SubstsRef<'tcx> {
             path = tcx.def_path_str(key),
         }
         cache_on_disk_if { key.is_local() }
+        separate_provide_extern
     }
 
     query analysis(key: ()) -> Result<(), ErrorReported> {
         desc { |tcx| "computing generics of `{}`", tcx.def_path_str(key) }
         storage(ArenaCacheSelector<'tcx>)
         cache_on_disk_if { key.is_local() }
+        separate_provide_extern
     }
 
     /// Maps from the `DefId` of an item (trait/struct/enum/fn) to the
     /// Bounds from the parent (e.g. with nested impl trait) are not included.
     query explicit_item_bounds(key: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
         desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     /// Elaborated version of the predicates from `explicit_item_bounds`.
 
     query native_libraries(_: CrateNum) -> Lrc<Vec<NativeLib>> {
         desc { "looking up the native libraries of a linked crate" }
+        separate_provide_extern
     }
 
     query lint_levels(_: ()) -> LintLevelMap {
         // This query reads from untracked data in definitions.
         eval_always
         desc { |tcx| "expansion that defined `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     query is_panic_runtime(_: CrateNum) -> bool {
         fatal_cycle
         desc { "checking if the crate is_panic_runtime" }
+        separate_provide_extern
     }
 
     /// Fetch the THIR for a given body. If typeck for that body failed, returns an empty `Thir`.
     query mir_const_qualif(key: DefId) -> mir::ConstQualifs {
         desc { |tcx| "const checking `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
+        separate_provide_extern
     }
     query mir_const_qualif_const_arg(
         key: (LocalDefId, DefId)
         desc {
             |tcx| "building an abstract representation for {}", tcx.def_path_str(key),
         }
+        separate_provide_extern
     }
     /// Try to build an abstract representation of the given constant.
     query thir_abstract_const_of_const_arg(
     ) -> &'tcx mir::Body<'tcx> {
         desc { |tcx| "caching mir of `{}` for CTFE", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
+        separate_provide_extern
     }
 
     query mir_for_ctfe_of_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::Body<'tcx> {
     query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> {
         desc { |tcx| "optimizing MIR for `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
+        separate_provide_extern
     }
 
     /// Returns coverage summary info for a function, after executing the `InstrumentCoverage`
     query promoted_mir(key: DefId) -> &'tcx IndexVec<mir::Promoted, mir::Body<'tcx>> {
         desc { |tcx| "optimizing promoted MIR for `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
+        separate_provide_extern
     }
     query promoted_mir_of_const_arg(
         key: (LocalDefId, DefId)
     /// Returns the predicates written explicitly by the user.
     query explicit_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> {
         desc { |tcx| "computing explicit predicates of `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     /// Returns the inferred outlives predicates (e.g., for `struct
     /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`).
     query inferred_outlives_of(key: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
         desc { |tcx| "computing inferred outlives predicates of `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     /// Maps from the `DefId` of a trait to the list of
     /// additional acyclicity requirements).
     query super_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> {
         desc { |tcx| "computing the super predicates of `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     /// The `Option<Ident>` is the name of an associated type. If it is `None`, then this query
     query trait_def(key: DefId) -> ty::TraitDef {
         desc { |tcx| "computing trait definition for `{}`", tcx.def_path_str(key) }
         storage(ArenaCacheSelector<'tcx>)
+        separate_provide_extern
     }
     query adt_def(key: DefId) -> &'tcx ty::AdtDef {
         desc { |tcx| "computing ADT definition for `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
     query adt_destructor(key: DefId) -> Option<ty::Destructor> {
         desc { |tcx| "computing `Drop` impl for `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     // The cycle error here should be reported as an error by `check_representable`.
     /// `is_const_fn` function.
     query is_const_fn_raw(key: DefId) -> bool {
         desc { |tcx| "checking if item is const fn: `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     query asyncness(key: DefId) -> hir::IsAsync {
         desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     /// Returns `true` if calls to the function may be promoted.
     /// Returns `true` if this is a foreign item (i.e., linked via `extern { ... }`).
     query is_foreign_item(key: DefId) -> bool {
         desc { |tcx| "checking if `{}` is a foreign item", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     /// Returns `Some(mutability)` if the node pointed to by `def_id` is a static item.
     query static_mutability(def_id: DefId) -> Option<hir::Mutability> {
         desc { |tcx| "looking up static mutability of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     /// Returns `Some(generator_kind)` if the node pointed to by `def_id` is a generator.
     query generator_kind(def_id: DefId) -> Option<hir::GeneratorKind> {
         desc { |tcx| "looking up generator kind of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     /// Gets a map with the variance of every item; use `item_variance` instead.
     /// Maps from the `DefId` of a type or region parameter to its (inferred) variance.
     query variances_of(def_id: DefId) -> &'tcx [ty::Variance] {
         desc { |tcx| "computing the variances of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     /// Maps from thee `DefId` of a type to its (inferred) outlives.
     /// Maps from an impl/trait `DefId` to a list of the `DefId`s of its items.
     query associated_item_def_ids(key: DefId) -> &'tcx [DefId] {
         desc { |tcx| "collecting associated items of `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     /// Maps from a trait item to the trait item "descriptor".
     query associated_item(key: DefId) -> ty::AssocItem {
         desc { |tcx| "computing associated item data for `{}`", tcx.def_path_str(key) }
         storage(ArenaCacheSelector<'tcx>)
+        separate_provide_extern
     }
 
     /// Collects the associated items defined on a trait or impl.
     /// Return `None` if this is an inherent impl.
     query impl_trait_ref(impl_id: DefId) -> Option<ty::TraitRef<'tcx>> {
         desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) }
+        separate_provide_extern
     }
     query impl_polarity(impl_id: DefId) -> ty::ImplPolarity {
         desc { |tcx| "computing implementation polarity of `{}`", tcx.def_path_str(impl_id) }
+        separate_provide_extern
     }
 
     query issue33140_self_ty(key: DefId) -> Option<ty::Ty<'tcx>> {
     query inherent_impls(key: DefId) -> &'tcx [DefId] {
         desc { |tcx| "collecting inherent impls for `{}`", tcx.def_path_str(key) }
         eval_always
+        separate_provide_extern
     }
 
     /// The result of unsafety-checking this `LocalDefId`.
         desc { |tcx| "processing `{}`", tcx.def_path_str(key.to_def_id()) }
     }
 
-    /// The signature of functions.
+    /// Computes the signature of the function.
     query fn_sig(key: DefId) -> ty::PolyFnSig<'tcx> {
         desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
+    /// Performs lint checking for the module.
     query lint_mod(key: LocalDefId) -> () {
         desc { |tcx| "linting {}", describe_as_module(key, tcx) }
     }
         desc { |tcx| "checking attributes in {}", describe_as_module(key, tcx) }
     }
 
+    /// Checks for uses of unstable APIs in the module.
     query check_mod_unstable_api_usage(key: LocalDefId) -> () {
         desc { |tcx| "checking for unstable API usage in {}", describe_as_module(key, tcx) }
     }
     }
 
     /// Caches `CoerceUnsized` kinds for impls on custom types.
-    query coerce_unsized_info(key: DefId)
-        -> ty::adjustment::CoerceUnsizedInfo {
-            desc { |tcx| "computing CoerceUnsized info for `{}`", tcx.def_path_str(key) }
-        }
+    query coerce_unsized_info(key: DefId) -> ty::adjustment::CoerceUnsizedInfo {
+        desc { |tcx| "computing CoerceUnsized info for `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
+    }
 
     query typeck_item_bodies(_: ()) -> () {
         desc { "type-checking all item bodies" }
     /// additional requirements that the closure's creator must verify.
     query mir_borrowck(key: LocalDefId) -> &'tcx mir::BorrowCheckResult<'tcx> {
         desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key.to_def_id()) }
-        cache_on_disk_if(tcx) { tcx.is_closure(key.to_def_id()) }
+        cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) }
     }
     query mir_borrowck_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::BorrowCheckResult<'tcx> {
         desc {
         desc { |tcx| "computing drop scopes for `{}`", tcx.def_path_str(def_id) }
     }
 
+    /// Generates a MIR body for the shim.
     query mir_shims(key: ty::InstanceDef<'tcx>) -> mir::Body<'tcx> {
         storage(ArenaCacheSelector<'tcx>)
         desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) }
 
     query opt_def_kind(def_id: DefId) -> Option<DefKind> {
         desc { |tcx| "looking up definition kind of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
+    /// Gets the span for the definition.
     query def_span(def_id: DefId) -> Span {
         desc { |tcx| "looking up span for `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
+    /// Gets the span for the identifier of the definition.
     query def_ident_span(def_id: DefId) -> Option<Span> {
         desc { |tcx| "looking up span for `{}`'s identifier", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     query lookup_stability(def_id: DefId) -> Option<&'tcx attr::Stability> {
         desc { |tcx| "looking up stability of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     query lookup_const_stability(def_id: DefId) -> Option<&'tcx attr::ConstStability> {
         desc { |tcx| "looking up const stability of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     query should_inherit_track_caller(def_id: DefId) -> bool {
 
     query lookup_deprecation_entry(def_id: DefId) -> Option<DeprecationEntry> {
         desc { |tcx| "checking whether `{}` is deprecated", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     query item_attrs(def_id: DefId) -> &'tcx [ast::Attribute] {
         desc { |tcx| "collecting attributes of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     query codegen_fn_attrs(def_id: DefId) -> CodegenFnAttrs {
 
     query fn_arg_names(def_id: DefId) -> &'tcx [rustc_span::symbol::Ident] {
         desc { |tcx| "looking up function parameter names for `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
     /// Gets the rendered value of the specified constant or associated constant.
     /// Used by rustdoc.
     query rendered_const(def_id: DefId) -> String {
         desc { |tcx| "rendering constant intializer of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
     query impl_parent(def_id: DefId) -> Option<DefId> {
         desc { |tcx| "computing specialization parent impl of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     /// Given an `associated_item`, find the trait it belongs to.
     /// Return `None` if the `DefId` is not an associated item.
     query trait_of_item(associated_item: DefId) -> Option<DefId> {
         desc { |tcx| "finding trait defining `{}`", tcx.def_path_str(associated_item) }
+        separate_provide_extern
     }
 
     query is_ctfe_mir_available(key: DefId) -> bool {
         desc { |tcx| "checking if item has ctfe mir available: `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
     query is_mir_available(key: DefId) -> bool {
         desc { |tcx| "checking if item has mir available: `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     query own_existential_vtable_entries(
     query dylib_dependency_formats(_: CrateNum)
                                     -> &'tcx [(CrateNum, LinkagePreference)] {
         desc { "dylib dependency formats of crate" }
+        separate_provide_extern
     }
 
     query dependency_formats(_: ()) -> Lrc<crate::middle::dependency_format::Dependencies> {
     query is_compiler_builtins(_: CrateNum) -> bool {
         fatal_cycle
         desc { "checking if the crate is_compiler_builtins" }
+        separate_provide_extern
     }
     query has_global_allocator(_: CrateNum) -> bool {
         // This query depends on untracked global state in CStore
         eval_always
         fatal_cycle
         desc { "checking if the crate has_global_allocator" }
+        separate_provide_extern
     }
     query has_panic_handler(_: CrateNum) -> bool {
         fatal_cycle
         desc { "checking if the crate has_panic_handler" }
+        separate_provide_extern
     }
     query is_profiler_runtime(_: CrateNum) -> bool {
         fatal_cycle
         desc { "query a crate is `#![profiler_runtime]`" }
+        separate_provide_extern
     }
     query panic_strategy(_: CrateNum) -> PanicStrategy {
         fatal_cycle
         desc { "query a crate's configured panic strategy" }
+        separate_provide_extern
     }
     query panic_in_drop_strategy(_: CrateNum) -> PanicStrategy {
         fatal_cycle
         desc { "query a crate's configured panic-in-drop strategy" }
+        separate_provide_extern
     }
     query is_no_builtins(_: CrateNum) -> bool {
         fatal_cycle
         desc { "test whether a crate has `#![no_builtins]`" }
+        separate_provide_extern
     }
     query symbol_mangling_version(_: CrateNum) -> SymbolManglingVersion {
         fatal_cycle
         desc { "query a crate's symbol mangling version" }
+        separate_provide_extern
     }
 
     query extern_crate(def_id: DefId) -> Option<&'tcx ExternCrate> {
         eval_always
         desc { "getting crate's ExternCrateData" }
+        separate_provide_extern
     }
 
     query specializes(_: (DefId, DefId)) -> bool {
 
     query impl_defaultness(def_id: DefId) -> hir::Defaultness {
         desc { |tcx| "looking up whether `{}` is a default impl", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     query impl_constness(def_id: DefId) -> hir::Constness {
         desc { |tcx| "looking up whether `{}` is a const impl", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     query check_item_well_formed(key: LocalDefId) -> () {
         -> DefIdMap<SymbolExportLevel> {
         storage(ArenaCacheSelector<'tcx>)
         desc { "looking up the exported symbols of a crate" }
+        separate_provide_extern
     }
     query is_reachable_non_generic(def_id: DefId) -> bool {
         desc { |tcx| "checking whether `{}` is an exported symbol", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
     query is_unreachable_local_definition(def_id: LocalDefId) -> bool {
         desc { |tcx|
                 "collecting available upstream monomorphizations for `{}`",
                 tcx.def_path_str(def_id),
             }
+            separate_provide_extern
         }
 
     /// Returns the upstream crate that exports drop-glue for the given
 
     query foreign_modules(_: CrateNum) -> Lrc<FxHashMap<DefId, ForeignModule>> {
         desc { "looking up the foreign modules of a linked crate" }
+        separate_provide_extern
     }
 
     /// Identifies the entry-point (e.g., the `main` function) for a given
     query crate_hash(_: CrateNum) -> Svh {
         eval_always
         desc { "looking up the hash a crate" }
+        separate_provide_extern
     }
     query crate_host_hash(_: CrateNum) -> Option<Svh> {
         eval_always
         desc { "looking up the hash of a host version of a crate" }
+        separate_provide_extern
     }
     query extra_filename(_: CrateNum) -> String {
         eval_always
         desc { "looking up the extra filename for a crate" }
+        separate_provide_extern
     }
     query crate_extern_paths(_: CrateNum) -> Vec<PathBuf> {
         eval_always
         desc { "looking up the paths for extern crates" }
+        separate_provide_extern
     }
 
     /// Given a crate and a trait, look up all impls of that trait in the crate.
     query implementations_of_trait(_: (CrateNum, DefId))
         -> &'tcx [(DefId, Option<ty::fast_reject::SimplifiedType>)] {
         desc { "looking up implementations of a trait in a crate" }
+        separate_provide_extern
     }
 
     /// Given a crate, look up all trait impls in that crate.
     query all_trait_implementations(_: CrateNum)
         -> &'tcx [(DefId, Option<ty::fast_reject::SimplifiedType>)] {
         desc { "looking up all (?) trait implementations" }
+        separate_provide_extern
     }
 
     query is_dllimport_foreign_item(def_id: DefId) -> bool {
 
     query visibility(def_id: DefId) -> ty::Visibility {
         desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     /// Computes the set of modules from which this type is visibly uninhabited.
     query dep_kind(_: CrateNum) -> CrateDepKind {
         eval_always
         desc { "fetching what a dependency looks like" }
+        separate_provide_extern
     }
+
+    /// Gets the name of the crate.
     query crate_name(_: CrateNum) -> Symbol {
         eval_always
         desc { "fetching what a crate is named" }
+        separate_provide_extern
     }
     query item_children(def_id: DefId) -> &'tcx [Export] {
         desc { |tcx| "collecting child items of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
     query extern_mod_stmt_cnum(def_id: LocalDefId) -> Option<CrateNum> {
         desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id.to_def_id()) }
     query defined_lib_features(_: CrateNum)
         -> &'tcx [(Symbol, Option<Symbol>)] {
         desc { "calculating the lib features defined in a crate" }
+        separate_provide_extern
     }
     /// Returns the lang items defined in another crate by loading it from metadata.
     query get_lang_items(_: ()) -> LanguageItems {
     /// Returns the lang items defined in another crate by loading it from metadata.
     query defined_lang_items(_: CrateNum) -> &'tcx [(DefId, usize)] {
         desc { "calculating the lang items defined in a crate" }
+        separate_provide_extern
     }
 
     /// Returns the diagnostic items defined in a crate.
     query diagnostic_items(_: CrateNum) -> rustc_hir::diagnostic_items::DiagnosticItems {
         storage(ArenaCacheSelector<'tcx>)
         desc { "calculating the diagnostic items map in a crate" }
+        separate_provide_extern
     }
 
     query missing_lang_items(_: CrateNum) -> &'tcx [LangItem] {
         desc { "calculating the missing lang items in a crate" }
+        separate_provide_extern
     }
     query visible_parent_map(_: ()) -> DefIdMap<DefId> {
         storage(ArenaCacheSelector<'tcx>)
     query missing_extern_crate_item(_: CrateNum) -> bool {
         eval_always
         desc { "seeing if we're missing an `extern crate` item for this crate" }
+        separate_provide_extern
     }
     query used_crate_source(_: CrateNum) -> Lrc<CrateSource> {
         eval_always
         desc { "looking at the source for a crate" }
+        separate_provide_extern
     }
     query postorder_cnums(_: ()) -> &'tcx [CrateNum] {
         eval_always
     query is_private_dep(c: CrateNum) -> bool {
         eval_always
         desc { "check whether crate {} is a private dependency", c }
+        separate_provide_extern
     }
     query allocator_kind(_: ()) -> Option<AllocatorKind> {
         eval_always
     query exported_symbols(_: CrateNum)
         -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportLevel)] {
         desc { "exported_symbols" }
+        separate_provide_extern
     }
 
     query collect_and_partition_mono_items(_: ()) -> (&'tcx DefIdSet, &'tcx [CodegenUnit<'tcx>]) {
             |tcx| "determining which generic parameters are unused by `{}`",
                 tcx.def_path_str(key.def_id())
         }
+        separate_provide_extern
     }
     query backend_optimization_level(_: ()) -> OptLevel {
         desc { "optimization level used by backend" }
index 869b2ab9dbcbc5a02495d8b515f6963ad1f10e6c..27e22ccac02a7fb7c771700ada2318eeace3a841 100644 (file)
@@ -1,7 +1,9 @@
 use crate::mir::interpret::ConstValue;
 use crate::mir::interpret::{LitToConstInput, Scalar};
-use crate::ty::{self, Ty, TyCtxt};
-use crate::ty::{ParamEnv, ParamEnvAnd};
+use crate::ty::{
+    self, InlineConstSubsts, InlineConstSubstsParts, InternalSubsts, ParamEnv, ParamEnvAnd, Ty,
+    TyCtxt, TypeFoldable,
+};
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -54,6 +56,24 @@ pub fn from_opt_const_arg_anon_const(
 
         let ty = tcx.type_of(def.def_id_for_type_of());
 
+        match Self::try_eval_lit_or_param(tcx, ty, expr) {
+            Some(v) => v,
+            None => tcx.mk_const(ty::Const {
+                val: ty::ConstKind::Unevaluated(ty::Unevaluated {
+                    def: def.to_global(),
+                    substs_: None,
+                    promoted: None,
+                }),
+                ty,
+            }),
+        }
+    }
+
+    fn try_eval_lit_or_param(
+        tcx: TyCtxt<'tcx>,
+        ty: Ty<'tcx>,
+        expr: &'tcx hir::Expr<'tcx>,
+    ) -> Option<&'tcx Self> {
         let lit_input = match expr.kind {
             hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
             hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind {
@@ -69,7 +89,7 @@ pub fn from_opt_const_arg_anon_const(
             // If an error occurred, ignore that it's a literal and leave reporting the error up to
             // mir.
             if let Ok(c) = tcx.at(expr.span).lit_to_const(lit_input) {
-                return c;
+                return Some(c);
             } else {
                 tcx.sess.delay_span_bug(expr.span, "Const::from_anon_const: couldn't lit_to_const");
             }
@@ -85,7 +105,7 @@ pub fn from_opt_const_arg_anon_const(
         };
 
         use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath};
-        let val = match expr.kind {
+        match expr.kind {
             ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => {
                 // Find the name and index of the const parameter by indexing the generics of
                 // the parent item and construct a `ParamConst`.
@@ -95,16 +115,53 @@ pub fn from_opt_const_arg_anon_const(
                 let generics = tcx.generics_of(item_def_id.to_def_id());
                 let index = generics.param_def_id_to_index[&def_id];
                 let name = tcx.hir().name(hir_id);
-                ty::ConstKind::Param(ty::ParamConst::new(index, name))
+                Some(tcx.mk_const(ty::Const {
+                    val: ty::ConstKind::Param(ty::ParamConst::new(index, name)),
+                    ty,
+                }))
             }
-            _ => ty::ConstKind::Unevaluated(ty::Unevaluated {
-                def: def.to_global(),
-                substs_: None,
-                promoted: None,
-            }),
+            _ => None,
+        }
+    }
+
+    pub fn from_inline_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx Self {
+        debug!("Const::from_inline_const(def_id={:?})", def_id);
+
+        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+
+        let body_id = match tcx.hir().get(hir_id) {
+            hir::Node::AnonConst(ac) => ac.body,
+            _ => span_bug!(
+                tcx.def_span(def_id.to_def_id()),
+                "from_inline_const can only process anonymous constants"
+            ),
         };
 
-        tcx.mk_const(ty::Const { val, ty })
+        let expr = &tcx.hir().body(body_id).value;
+
+        let ty = tcx.typeck(def_id).node_type(hir_id);
+
+        let ret = match Self::try_eval_lit_or_param(tcx, ty, expr) {
+            Some(v) => v,
+            None => {
+                let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id());
+                let parent_substs =
+                    tcx.erase_regions(InternalSubsts::identity_for_item(tcx, typeck_root_def_id));
+                let substs =
+                    InlineConstSubsts::new(tcx, InlineConstSubstsParts { parent_substs, ty })
+                        .substs;
+                tcx.mk_const(ty::Const {
+                    val: ty::ConstKind::Unevaluated(ty::Unevaluated {
+                        def: ty::WithOptConstParam::unknown(def_id).to_global(),
+                        substs_: Some(substs),
+                        promoted: None,
+                    }),
+                    ty,
+                })
+            }
+        };
+        debug_assert!(!ret.has_free_regions(tcx));
+        ret
     }
 
     /// Interns the given value as a constant.
index 8ec5f4c79781f34902df49db679edbcfc574a8a6..b87e23af72b702076ea2ea84f8d5b48bf87b6f43 100644 (file)
@@ -3060,9 +3060,10 @@ fn fn_abi_new_uncached(
                     // LLVM's definition of `noalias` is based solely on memory
                     // dependencies rather than pointer equality
                     //
-                    // Due to miscompiles in LLVM < 12, we apply a separate NoAliasMutRef attribute
-                    // for UniqueBorrowed arguments, so that the codegen backend can decide
-                    // whether or not to actually emit the attribute.
+                    // Due to past miscompiles in LLVM, we apply a separate NoAliasMutRef attribute
+                    // for UniqueBorrowed arguments, so that the codegen backend can decide whether
+                    // or not to actually emit the attribute. It can also be controlled with the
+                    // `-Zmutable-noalias` debugging option.
                     let no_alias = match kind {
                         PointerKind::Shared | PointerKind::UniqueBorrowed => false,
                         PointerKind::UniqueOwned => true,
index cf47da157d19f7c969eb8e0e9724d06056f052f0..40670f1fdcaefb03ac7b4ec18774be070bfec613 100644 (file)
     Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, BoundVariableKind,
     CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid, EarlyBoundRegion,
     ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig,
-    GeneratorSubsts, GeneratorSubstsParts, ParamConst, ParamTy, PolyExistentialProjection,
-    PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind,
-    RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo, VarianceDiagMutKind,
+    GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts, InlineConstSubstsParts, ParamConst,
+    ParamTy, PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig,
+    PolyTraitRef, ProjectionTy, Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut,
+    UpvarSubsts, VarianceDiagInfo, VarianceDiagMutKind,
 };
 pub use self::trait_def::TraitDef;
 
@@ -1927,7 +1928,8 @@ pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> {
                 | DefKind::Static
                 | DefKind::AssocConst
                 | DefKind::Ctor(..)
-                | DefKind::AnonConst => self.mir_for_ctfe_opt_const_arg(def),
+                | DefKind::AnonConst
+                | DefKind::InlineConst => self.mir_for_ctfe_opt_const_arg(def),
                 // If the caller wants `mir_for_ctfe` of a function they should not be using
                 // `instance_mir`, so we'll assume const fn also wants the optimized version.
                 _ => {
index b11a54d5dcb11e5558437eaf22043cc991b3209e..742005e245f9d160ed91387e209975e1f1ddf0da 100644 (file)
@@ -744,6 +744,7 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
                     p!(print_def_path(did, substs));
                     if !substs.as_closure().is_valid() {
                         p!(" closure_substs=(unavailable)");
+                        p!(write(" substs={:?}", substs));
                     } else {
                         p!(" closure_kind_ty=", print(substs.as_closure().kind_ty()));
                         p!(
index 6c1175ebdb4ee8b60115d25d15a2114eff8652e9..34f806271979af7ec3bef7af3d4e99438fc6862b 100644 (file)
@@ -123,6 +123,39 @@ macro_rules! query_storage {
     };
 }
 
+macro_rules! separate_provide_extern_decl {
+    ([][$name:ident]) => {
+        ()
+    };
+    ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => {
+        for<'tcx> fn(
+            TyCtxt<'tcx>,
+            query_keys::$name<'tcx>,
+        ) -> query_values::$name<'tcx>
+    };
+    ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
+        separate_provide_extern_decl!([$($modifiers)*][$($args)*])
+    };
+}
+
+macro_rules! separate_provide_extern_default {
+    ([][$name:ident]) => {
+        ()
+    };
+    ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => {
+        |_, key| bug!(
+            "`tcx.{}({:?})` unsupported by its crate; \
+             perhaps the `{}` query was never assigned a provider function",
+            stringify!($name),
+            key,
+            stringify!($name),
+        )
+    };
+    ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
+        separate_provide_extern_default!([$($modifiers)*][$($args)*])
+    };
+}
+
 macro_rules! define_callbacks {
     (<$tcx:tt>
      $($(#[$attr:meta])*
@@ -214,6 +247,10 @@ pub struct Providers {
             ) -> query_values::$name<'tcx>,)*
         }
 
+        pub struct ExternProviders {
+            $(pub $name: separate_provide_extern_decl!([$($modifiers)*][$name]),)*
+        }
+
         impl Default for Providers {
             fn default() -> Self {
                 Providers {
@@ -228,11 +265,24 @@ fn default() -> Self {
             }
         }
 
+        impl Default for ExternProviders {
+            fn default() -> Self {
+                ExternProviders {
+                    $($name: separate_provide_extern_default!([$($modifiers)*][$name]),)*
+                }
+            }
+        }
+
         impl Copy for Providers {}
         impl Clone for Providers {
             fn clone(&self) -> Self { *self }
         }
 
+        impl Copy for ExternProviders {}
+        impl Clone for ExternProviders {
+            fn clone(&self) -> Self { *self }
+        }
+
         pub trait QueryEngine<'tcx>: rustc_data_structures::sync::Sync {
             fn as_any(&'tcx self) -> &'tcx dyn std::any::Any;
 
index 8b20e1eec9a86e03ba2d3992530b195e385f4a59..c7d8bec506f6b80af01ed5e80d120ea8879ac7bb 100644 (file)
@@ -187,8 +187,12 @@ fn relate<R: TypeRelation<'tcx>>(
             })
             .enumerate()
             .map(|(i, r)| match r {
-                Err(TypeError::Sorts(exp_found)) => Err(TypeError::ArgumentSorts(exp_found, i)),
-                Err(TypeError::Mutability) => Err(TypeError::ArgumentMutability(i)),
+                Err(TypeError::Sorts(exp_found) | TypeError::ArgumentSorts(exp_found, _)) => {
+                    Err(TypeError::ArgumentSorts(exp_found, i))
+                }
+                Err(TypeError::Mutability | TypeError::ArgumentMutability(_)) => {
+                    Err(TypeError::ArgumentMutability(i))
+                }
                 r => r,
             });
         Ok(ty::FnSig {
index 874de3366d79213ee7499075d518f5a41f3eb58d..e57075ed33811d59589d3f340ef2f5c0ae272a1a 100644 (file)
@@ -704,6 +704,66 @@ pub fn tupled_upvars_ty(self) -> Ty<'tcx> {
     }
 }
 
+/// An inline const is modeled like
+///
+///     const InlineConst<'l0...'li, T0...Tj, R>: R;
+///
+/// where:
+///
+/// - 'l0...'li and T0...Tj are the generic parameters
+///   inherited from the item that defined the inline const,
+/// - R represents the type of the constant.
+///
+/// When the inline const is instantiated, `R` is substituted as the actual inferred
+/// type of the constant. The reason that `R` is represented as an extra type parameter
+/// is the same reason that [`ClosureSubsts`] have `CS` and `U` as type parameters:
+/// inline const can reference lifetimes that are internal to the creating function.
+#[derive(Copy, Clone, Debug, TypeFoldable)]
+pub struct InlineConstSubsts<'tcx> {
+    /// Generic parameters from the enclosing item,
+    /// concatenated with the inferred type of the constant.
+    pub substs: SubstsRef<'tcx>,
+}
+
+/// Struct returned by `split()`.
+pub struct InlineConstSubstsParts<'tcx, T> {
+    pub parent_substs: &'tcx [GenericArg<'tcx>],
+    pub ty: T,
+}
+
+impl<'tcx> InlineConstSubsts<'tcx> {
+    /// Construct `InlineConstSubsts` from `InlineConstSubstsParts`.
+    pub fn new(
+        tcx: TyCtxt<'tcx>,
+        parts: InlineConstSubstsParts<'tcx, Ty<'tcx>>,
+    ) -> InlineConstSubsts<'tcx> {
+        InlineConstSubsts {
+            substs: tcx.mk_substs(
+                parts.parent_substs.iter().copied().chain(std::iter::once(parts.ty.into())),
+            ),
+        }
+    }
+
+    /// Divides the inline const substs into their respective components.
+    /// The ordering assumed here must match that used by `InlineConstSubsts::new` above.
+    fn split(self) -> InlineConstSubstsParts<'tcx, GenericArg<'tcx>> {
+        match self.substs[..] {
+            [ref parent_substs @ .., ty] => InlineConstSubstsParts { parent_substs, ty },
+            _ => bug!("inline const substs missing synthetics"),
+        }
+    }
+
+    /// Returns the substitutions of the inline const's parent.
+    pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] {
+        self.split().parent_substs
+    }
+
+    /// Returns the type of this inline const.
+    pub fn ty(self) -> Ty<'tcx> {
+        self.split().ty.expect_ty()
+    }
+}
+
 #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable)]
 pub enum ExistentialPredicate<'tcx> {
index 2438d1a16021b50aa4f318d5946842e6bc6d4281..73a8e18949de06ad6a4d8d5b3dc0c8329b5c22bf 100644 (file)
@@ -3,7 +3,7 @@
 use crate::mir;
 use crate::ty::codec::{TyDecoder, TyEncoder};
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
-use crate::ty::sty::{ClosureSubsts, GeneratorSubsts};
+use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts};
 use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
 
 use rustc_hir::def_id::DefId;
@@ -204,6 +204,14 @@ pub fn as_generator(&'tcx self) -> GeneratorSubsts<'tcx> {
         GeneratorSubsts { substs: self }
     }
 
+    /// Interpret these substitutions as the substitutions of an inline const.
+    /// Inline const substitutions have a particular structure controlled by the
+    /// compiler that encodes information like the inferred type;
+    /// see `ty::InlineConstSubsts` struct for more comments.
+    pub fn as_inline_const(&'tcx self) -> InlineConstSubsts<'tcx> {
+        InlineConstSubsts { substs: self }
+    }
+
     /// Creates an `InternalSubsts` that maps each generic parameter to itself.
     pub fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> {
         Self::for_item(tcx, def_id, |param, _| tcx.mk_param_from_def(param))
index 2c884813d23187eea6f275f54c9cffb979085a36..6b287445ff032dade94803d5ba345326d7d7ac98 100644 (file)
@@ -423,6 +423,15 @@ pub fn is_closure(self, def_id: DefId) -> bool {
         matches!(self.def_kind(def_id), DefKind::Closure | DefKind::Generator)
     }
 
+    /// Returns `true` if `def_id` refers to a definition that does not have its own
+    /// type-checking context, i.e. closure, generator or inline const.
+    pub fn is_typeck_child(self, def_id: DefId) -> bool {
+        matches!(
+            self.def_kind(def_id),
+            DefKind::Closure | DefKind::Generator | DefKind::InlineConst
+        )
+    }
+
     /// Returns `true` if `def_id` refers to a trait (i.e., `trait Foo { ... }`).
     pub fn is_trait(self, def_id: DefId) -> bool {
         self.def_kind(def_id) == DefKind::Trait
@@ -440,16 +449,19 @@ pub fn is_constructor(self, def_id: DefId) -> bool {
         matches!(self.def_kind(def_id), DefKind::Ctor(..))
     }
 
-    /// Given the def-ID of a fn or closure, returns the def-ID of
-    /// the innermost fn item that the closure is contained within.
-    /// This is a significant `DefId` because, when we do
-    /// type-checking, we type-check this fn item and all of its
-    /// (transitive) closures together. Therefore, when we fetch the
+    /// Given the `DefId`, returns the `DefId` of the innermost item that
+    /// has its own type-checking context or "inference enviornment".
+    ///
+    /// For example, a closure has its own `DefId`, but it is type-checked
+    /// with the containing item. Similarly, an inline const block has its
+    /// own `DefId` but it is type-checked together with the containing item.
+    ///
+    /// Therefore, when we fetch the
     /// `typeck` the closure, for example, we really wind up
     /// fetching the `typeck` the enclosing fn item.
-    pub fn closure_base_def_id(self, def_id: DefId) -> DefId {
+    pub fn typeck_root_def_id(self, def_id: DefId) -> DefId {
         let mut def_id = def_id;
-        while self.is_closure(def_id) {
+        while self.is_typeck_child(def_id) {
             def_id = self.parent(def_id).unwrap_or_else(|| {
                 bug!("closure {:?} has no parent", def_id);
             });
index 6cf7c405473c92c737ac0446dc6a7a639a884178..b0f1e08562c1609b4d91ef91d0b9333478f2d59c 100644 (file)
@@ -10,7 +10,6 @@
 #![feature(once_cell)]
 #![feature(min_specialization)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate tracing;
index 17296a95bc17e26e2c6560ea91001e977c8841e7..b4005ccd1cc42205db0909d37699f2b802fbf561 100644 (file)
@@ -578,7 +578,7 @@ fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx>
 
             hir::ExprKind::ConstBlock(ref anon_const) => {
                 let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
-                let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id);
+                let value = ty::Const::from_inline_const(self.tcx, anon_const_def_id);
 
                 ExprKind::ConstBlock { value }
             }
index cb74ae4df2ef86ac4084583730a0d4343f20307e..ce80214c875fc5e46f329f65fc438f031759bed7 100644 (file)
@@ -544,7 +544,7 @@ fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> {
             let (lit, neg) = match expr.kind {
                 hir::ExprKind::ConstBlock(ref anon_const) => {
                     let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
-                    let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id);
+                    let value = ty::Const::from_inline_const(self.tcx, anon_const_def_id);
                     if matches!(value.val, ConstKind::Param(_)) {
                         let span = self.tcx.hir().span(anon_const.hir_id);
                         self.errors.push(PatternError::ConstParamInPattern(span));
index c000e49c14bc1b72483803e310601e420be49193..ba6b566a304a5d75804d24a1150e634c67eb09ae 100644 (file)
@@ -64,6 +64,13 @@ pub fn new(body: &'mir mir::Body<'tcx>, results: R) -> Self {
         }
     }
 
+    /// Allows inspection of unreachable basic blocks even with `debug_assertions` enabled.
+    #[cfg(test)]
+    pub(crate) fn allow_unreachable(&mut self) {
+        #[cfg(debug_assertions)]
+        self.reachable_blocks.insert_all()
+    }
+
     /// Returns the underlying `Results`.
     pub fn results(&self) -> &Results<'tcx, A> {
         &self.results.borrow()
index a5989121679c4fa8fb2014cd9910581e30520a48..6efa8daec489a9e1da66a566e11bc7bb7ff8eb74 100644 (file)
@@ -268,6 +268,8 @@ fn test_cursor<D: Direction>(analysis: MockAnalysis<'tcx, D>) {
     let mut cursor =
         Results { entry_sets: analysis.mock_entry_sets(), analysis }.into_results_cursor(body);
 
+    cursor.allow_unreachable();
+
     let every_target = || {
         body.basic_blocks()
             .iter_enumerated()
index 158ba1b942528072c7416f70fe9cb434590e83a6..d38b567a95849be35d1995a6e2e8c3707dd2e1e4 100644 (file)
@@ -3,25 +3,14 @@
 use crate::{AnalysisDomain, GenKill, GenKillAnalysis};
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
-use rustc_middle::ty::{ParamEnv, TyCtxt};
-use rustc_span::DUMMY_SP;
-
-pub type MaybeMutBorrowedLocals<'mir, 'tcx> = MaybeBorrowedLocals<MutBorrow<'mir, 'tcx>>;
 
 /// A dataflow analysis that tracks whether a pointer or reference could possibly exist that points
 /// to a given local.
 ///
-/// The `K` parameter determines what kind of borrows are tracked. By default,
-/// `MaybeBorrowedLocals` looks for *any* borrow of a local. If you are only interested in borrows
-/// that might allow mutation, use the `MaybeMutBorrowedLocals` type alias instead.
-///
 /// At present, this is used as a very limited form of alias analysis. For example,
 /// `MaybeBorrowedLocals` is used to compute which locals are live during a yield expression for
-/// immovable generators. `MaybeMutBorrowedLocals` is used during const checking to prove that a
-/// local has not been mutated via indirect assignment (e.g., `*p = 42`), the side-effects of a
-/// function call or inline assembly.
-pub struct MaybeBorrowedLocals<K = AnyBorrow> {
-    kind: K,
+/// immovable generators.
+pub struct MaybeBorrowedLocals {
     ignore_borrow_on_drop: bool,
 }
 
@@ -29,29 +18,11 @@ impl MaybeBorrowedLocals {
     /// A dataflow analysis that records whether a pointer or reference exists that may alias the
     /// given local.
     pub fn all_borrows() -> Self {
-        MaybeBorrowedLocals { kind: AnyBorrow, ignore_borrow_on_drop: false }
-    }
-}
-
-impl MaybeMutBorrowedLocals<'mir, 'tcx> {
-    /// A dataflow analysis that records whether a pointer or reference exists that may *mutably*
-    /// alias the given local.
-    ///
-    /// This includes `&mut` and pointers derived from an `&mut`, as well as shared borrows of
-    /// types with interior mutability.
-    pub fn mut_borrows_only(
-        tcx: TyCtxt<'tcx>,
-        body: &'mir mir::Body<'tcx>,
-        param_env: ParamEnv<'tcx>,
-    ) -> Self {
-        MaybeBorrowedLocals {
-            kind: MutBorrow { body, tcx, param_env },
-            ignore_borrow_on_drop: false,
-        }
+        MaybeBorrowedLocals { ignore_borrow_on_drop: false }
     }
 }
 
-impl<K> MaybeBorrowedLocals<K> {
+impl MaybeBorrowedLocals {
     /// During dataflow analysis, ignore the borrow that may occur when a place is dropped.
     ///
     /// Drop terminators may call custom drop glue (`Drop::drop`), which takes `&mut self` as a
@@ -69,21 +40,14 @@ pub fn unsound_ignore_borrow_on_drop(self) -> Self {
         MaybeBorrowedLocals { ignore_borrow_on_drop: true, ..self }
     }
 
-    fn transfer_function<'a, T>(&'a self, trans: &'a mut T) -> TransferFunction<'a, T, K> {
-        TransferFunction {
-            kind: &self.kind,
-            trans,
-            ignore_borrow_on_drop: self.ignore_borrow_on_drop,
-        }
+    fn transfer_function<'a, T>(&'a self, trans: &'a mut T) -> TransferFunction<'a, T> {
+        TransferFunction { trans, ignore_borrow_on_drop: self.ignore_borrow_on_drop }
     }
 }
 
-impl<K> AnalysisDomain<'tcx> for MaybeBorrowedLocals<K>
-where
-    K: BorrowAnalysisKind<'tcx>,
-{
+impl AnalysisDomain<'tcx> for MaybeBorrowedLocals {
     type Domain = BitSet<Local>;
-    const NAME: &'static str = K::ANALYSIS_NAME;
+    const NAME: &'static str = "maybe_borrowed_locals";
 
     fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
         // bottom = unborrowed
@@ -95,10 +59,7 @@ fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) {
     }
 }
 
-impl<K> GenKillAnalysis<'tcx> for MaybeBorrowedLocals<K>
-where
-    K: BorrowAnalysisKind<'tcx>,
-{
+impl GenKillAnalysis<'tcx> for MaybeBorrowedLocals {
     type Idx = Local;
 
     fn statement_effect(
@@ -131,16 +92,14 @@ fn call_return_effect(
 }
 
 /// A `Visitor` that defines the transfer function for `MaybeBorrowedLocals`.
-struct TransferFunction<'a, T, K> {
+struct TransferFunction<'a, T> {
     trans: &'a mut T,
-    kind: &'a K,
     ignore_borrow_on_drop: bool,
 }
 
-impl<T, K> Visitor<'tcx> for TransferFunction<'a, T, K>
+impl<T> Visitor<'tcx> for TransferFunction<'a, T>
 where
     T: GenKill<Local>,
-    K: BorrowAnalysisKind<'tcx>,
 {
     fn visit_statement(&mut self, stmt: &Statement<'tcx>, location: Location) {
         self.super_statement(stmt, location);
@@ -156,14 +115,14 @@ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
         self.super_rvalue(rvalue, location);
 
         match rvalue {
-            mir::Rvalue::AddressOf(mt, borrowed_place) => {
-                if !borrowed_place.is_indirect() && self.kind.in_address_of(*mt, *borrowed_place) {
+            mir::Rvalue::AddressOf(_mt, borrowed_place) => {
+                if !borrowed_place.is_indirect() {
                     self.trans.gen(borrowed_place.local);
                 }
             }
 
-            mir::Rvalue::Ref(_, kind, borrowed_place) => {
-                if !borrowed_place.is_indirect() && self.kind.in_ref(*kind, *borrowed_place) {
+            mir::Rvalue::Ref(_, _kind, borrowed_place) => {
+                if !borrowed_place.is_indirect() {
                     self.trans.gen(borrowed_place.local);
                 }
             }
@@ -211,64 +170,3 @@ fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Loc
         }
     }
 }
-
-pub struct AnyBorrow;
-
-pub struct MutBorrow<'mir, 'tcx> {
-    tcx: TyCtxt<'tcx>,
-    body: &'mir Body<'tcx>,
-    param_env: ParamEnv<'tcx>,
-}
-
-impl MutBorrow<'mir, 'tcx> {
-    /// `&` and `&raw` only allow mutation if the borrowed place is `!Freeze`.
-    ///
-    /// This assumes that it is UB to take the address of a struct field whose type is
-    /// `Freeze`, then use pointer arithmetic to derive a pointer to a *different* field of
-    /// that same struct whose type is `!Freeze`. If we decide that this is not UB, we will
-    /// have to check the type of the borrowed **local** instead of the borrowed **place**
-    /// below. See [rust-lang/unsafe-code-guidelines#134].
-    ///
-    /// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134
-    fn shared_borrow_allows_mutation(&self, place: Place<'tcx>) -> bool {
-        !place.ty(self.body, self.tcx).ty.is_freeze(self.tcx.at(DUMMY_SP), self.param_env)
-    }
-}
-
-pub trait BorrowAnalysisKind<'tcx> {
-    const ANALYSIS_NAME: &'static str;
-
-    fn in_address_of(&self, mt: Mutability, place: Place<'tcx>) -> bool;
-    fn in_ref(&self, kind: mir::BorrowKind, place: Place<'tcx>) -> bool;
-}
-
-impl BorrowAnalysisKind<'tcx> for AnyBorrow {
-    const ANALYSIS_NAME: &'static str = "maybe_borrowed_locals";
-
-    fn in_ref(&self, _: mir::BorrowKind, _: Place<'_>) -> bool {
-        true
-    }
-    fn in_address_of(&self, _: Mutability, _: Place<'_>) -> bool {
-        true
-    }
-}
-
-impl BorrowAnalysisKind<'tcx> for MutBorrow<'mir, 'tcx> {
-    const ANALYSIS_NAME: &'static str = "maybe_mut_borrowed_locals";
-
-    fn in_ref(&self, kind: mir::BorrowKind, place: Place<'tcx>) -> bool {
-        match kind {
-            mir::BorrowKind::Mut { .. } => true,
-            mir::BorrowKind::Shared | mir::BorrowKind::Shallow | mir::BorrowKind::Unique => {
-                self.shared_borrow_allows_mutation(place)
-            }
-        }
-    }
-
-    fn in_address_of(&self, mt: Mutability, place: Place<'tcx>) -> bool {
-        match mt {
-            Mutability::Mut => true,
-            Mutability::Not => self.shared_borrow_allows_mutation(place),
-        }
-    }
-}
index 474f4f2a79b2a7475a25344d49f0f9193b48d04c..91dddc6cd55c5d415b76548051dd488b0774bb4a 100644 (file)
@@ -22,7 +22,7 @@
 mod liveness;
 mod storage_liveness;
 
-pub use self::borrowed_locals::{MaybeBorrowedLocals, MaybeMutBorrowedLocals};
+pub use self::borrowed_locals::MaybeBorrowedLocals;
 pub use self::init_locals::MaybeInitializedLocals;
 pub use self::liveness::MaybeLiveLocals;
 pub use self::storage_liveness::{MaybeRequiresStorage, MaybeStorageLive};
index 2f3de52965db1dbe6d3f70bae30a9b3c54115ca4..77a72ce63ce5ee53ccc2ed8e74ce159fcafc1d27 100644 (file)
@@ -2,7 +2,6 @@
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![cfg_attr(bootstrap, feature(const_panic))]
 #![feature(exact_size_is_empty)]
 #![feature(in_band_lifetimes)]
 #![feature(iter_zip)]
index 2d27d085b489398440fb2e4a3640624b469063ad..28e5d76783aa4015cb8af5bc2cce5b2a618cf584 100644 (file)
@@ -11,8 +11,7 @@
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
 use crate::impls::{
-    DefinitelyInitializedPlaces, MaybeInitializedPlaces, MaybeLiveLocals, MaybeMutBorrowedLocals,
-    MaybeUninitializedPlaces,
+    DefinitelyInitializedPlaces, MaybeInitializedPlaces, MaybeLiveLocals, MaybeUninitializedPlaces,
 };
 use crate::move_paths::{HasMoveData, MoveData};
 use crate::move_paths::{LookupResult, MovePathIndex};
@@ -62,14 +61,6 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             sanity_check_via_rustc_peek(tcx, body, &attributes, &flow_def_inits);
         }
 
-        if has_rustc_mir_with(sess, &attributes, sym::rustc_peek_indirectly_mutable).is_some() {
-            let flow_mut_borrowed = MaybeMutBorrowedLocals::mut_borrows_only(tcx, body, param_env)
-                .into_engine(tcx, body)
-                .iterate_to_fixpoint();
-
-            sanity_check_via_rustc_peek(tcx, body, &attributes, &flow_mut_borrowed);
-        }
-
         if has_rustc_mir_with(sess, &attributes, sym::rustc_peek_liveness).is_some() {
             let flow_liveness = MaybeLiveLocals.into_engine(tcx, body).iterate_to_fixpoint();
 
@@ -281,26 +272,6 @@ fn peek_at(
     }
 }
 
-impl<'tcx> RustcPeekAt<'tcx> for MaybeMutBorrowedLocals<'_, 'tcx> {
-    fn peek_at(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        place: mir::Place<'tcx>,
-        flow_state: &BitSet<Local>,
-        call: PeekCall,
-    ) {
-        info!(?place, "peek_at");
-        let Some(local) = place.as_local() else {
-            tcx.sess.span_err(call.span, "rustc_peek: argument was not a local");
-            return;
-        };
-
-        if !flow_state.contains(local) {
-            tcx.sess.span_err(call.span, "rustc_peek: bit not set");
-        }
-    }
-}
-
 impl<'tcx> RustcPeekAt<'tcx> for MaybeLiveLocals {
     fn peek_at(
         &self,
index 4ac93f716192308709d3c18b73b58d8cb63041f6..6807d02519e2b3305f46278f1b33f861fafb14bd 100644 (file)
@@ -485,7 +485,7 @@ fn inject_statement(
 
 // Non-code expressions are injected into the coverage map, without generating executable code.
 fn inject_intermediate_expression(mir_body: &mut mir::Body<'tcx>, expression: CoverageKind) {
-    debug_assert!(if let CoverageKind::Expression { .. } = expression { true } else { false });
+    debug_assert!(matches!(expression, CoverageKind::Expression { .. }));
     debug!("  injecting non-code expression {:?}", expression);
     let inject_in_bb = mir::START_BLOCK;
     let data = &mut mir_body[inject_in_bb];
index cc525a4d6b91ca1a1ab9e491b4086c57a6c46885..d13fa0729cd9562a0306ef1be170dd3a302fb3a4 100644 (file)
@@ -94,10 +94,9 @@ pub fn for_statement(
         stmt_index: usize,
     ) -> Self {
         let is_closure = match statement.kind {
-            StatementKind::Assign(box (_, Rvalue::Aggregate(box ref kind, _))) => match kind {
-                AggregateKind::Closure(_, _) | AggregateKind::Generator(_, _, _) => true,
-                _ => false,
-            },
+            StatementKind::Assign(box (_, Rvalue::Aggregate(box ref kind, _))) => {
+                matches!(kind, AggregateKind::Closure(_, _) | AggregateKind::Generator(_, _, _))
+            }
             _ => false,
         };
 
index cd42edce23d7eab1ec566c508075c02f38df2e96..f9ef31462780731a9375aa0ec7f4f379c17da875 100644 (file)
@@ -1,7 +1,6 @@
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(crate_visibility_modifier)]
-#![cfg_attr(bootstrap, feature(const_panic))]
 #![feature(in_band_lifetimes)]
 #![feature(iter_zip)]
 #![feature(let_else)]
@@ -13,7 +12,6 @@
 #![feature(trusted_step)]
 #![feature(try_blocks)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate tracing;
index 7b4eb4912cb366a99319ceb5a309131cad6db06f..6c423a2bb5756c79476adf6a8186781b61c29914 100644 (file)
@@ -11,7 +11,7 @@ impl<'tcx> MirPass<'tcx> for RevealAll {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // This pass must run before inlining, since we insert callee bodies in RevealAll mode.
         // Do not apply this transformation to generators.
-        if (tcx.sess.mir_opt_level() >= 3 || !super::inline::is_enabled(tcx))
+        if (tcx.sess.mir_opt_level() >= 3 || super::inline::is_enabled(tcx))
             && body.generator.is_none()
         {
             let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
index baf381081ddab019de0e25c8ef10278fbf82f2cc..64cd6f56a9ffa0a15d254c302587bb0f4e9cccc6 100644 (file)
@@ -27,9 +27,8 @@ fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             // This is a temporary solution that handles possibly diverging asm statements.
             // Accompanying testcases: mir-opt/unreachable_asm.rs and mir-opt/unreachable_asm_2.rs
             let asm_stmt_in_block = || {
-                bb_data.statements.iter().any(|stmt: &Statement<'_>| match stmt.kind {
-                    StatementKind::LlvmInlineAsm(..) => true,
-                    _ => false,
+                bb_data.statements.iter().any(|stmt: &Statement<'_>| {
+                    matches!(stmt.kind, StatementKind::LlvmInlineAsm(..))
                 })
             };
 
index 5147408210ef538ef24b1166b3c759b3dc5edb93..59988e69b5d3a0d3af3dc8c516c459fd19391af0 100644 (file)
@@ -806,13 +806,22 @@ fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Loc
                     }
                 }
             }
+            mir::TerminatorKind::Assert { ref msg, .. } => {
+                let lang_item = match msg {
+                    mir::AssertKind::BoundsCheck { .. } => LangItem::PanicBoundsCheck,
+                    _ => LangItem::Panic,
+                };
+                let instance = Instance::mono(tcx, tcx.require_lang_item(lang_item, Some(source)));
+                if should_codegen_locally(tcx, &instance) {
+                    self.output.push(create_fn_mono_item(tcx, instance, source));
+                }
+            }
             mir::TerminatorKind::Goto { .. }
             | mir::TerminatorKind::SwitchInt { .. }
             | mir::TerminatorKind::Resume
             | mir::TerminatorKind::Abort
             | mir::TerminatorKind::Return
-            | mir::TerminatorKind::Unreachable
-            | mir::TerminatorKind::Assert { .. } => {}
+            | mir::TerminatorKind::Unreachable => {}
             mir::TerminatorKind::GeneratorDrop
             | mir::TerminatorKind::Yield { .. }
             | mir::TerminatorKind::FalseEdge { .. }
index 51a6f7e3e406da47d0f2f1210a6a8c6f1e6f794c..f4082153b684048d1310b9a1990ee6b721dd128b 100644 (file)
@@ -5,7 +5,6 @@
 #![feature(let_else)]
 #![feature(in_band_lifetimes)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate tracing;
index e6e4438b6d41afa63bb448bbc1db8b81cfd51e17..595080619da6faaac8be4cf5b91b93beb4cbf45a 100644 (file)
@@ -167,6 +167,7 @@ fn mark_used_by_default_parameters<'tcx>(
         | DefKind::Use
         | DefKind::ForeignMod
         | DefKind::AnonConst
+        | DefKind::InlineConst
         | DefKind::OpaqueTy
         | DefKind::Field
         | DefKind::LifetimeParam
@@ -195,7 +196,7 @@ fn emit_unused_generic_params_error<'tcx>(
     generics: &'tcx ty::Generics,
     unused_parameters: &FiniteBitSet<u32>,
 ) {
-    let base_def_id = tcx.closure_base_def_id(def_id);
+    let base_def_id = tcx.typeck_root_def_id(def_id);
     if !tcx.get_attrs(base_def_id).iter().any(|a| a.has_name(sym::rustc_polymorphize_error)) {
         return;
     }
@@ -303,7 +304,7 @@ fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
                 ControlFlow::CONTINUE
             }
             ty::ConstKind::Unevaluated(uv)
-                if self.tcx.def_kind(uv.def.did) == DefKind::AnonConst =>
+                if matches!(self.tcx.def_kind(uv.def.did), DefKind::AnonConst | DefKind::InlineConst) =>
             {
                 self.visit_child_body(uv.def.did, uv.substs(self.tcx));
                 ControlFlow::CONTINUE
index 799b4e18c240f24afedae9073453384356f2c5ad..4392c02f874d4da47001ca3f167f7baf37a85dda 100644 (file)
@@ -67,7 +67,7 @@
             src_file.prefer_local(),
             line_nos
         ) {
-            eprintln!("Error writting to file {}", e.to_string())
+            eprintln!("Error writing to file {}", e)
         }
     }
 }
index 1decaaa955f023075367e523b4e801eec49a2cb1..a823607ab0ec2191c86a3630fd2488d0c9198fb2 100644 (file)
@@ -18,3 +18,4 @@ rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_ast = { path = "../rustc_ast" }
 unicode-normalization = "0.1.11"
+unicode-width = "0.1.4"
index 1e65cc27154a818bd19889f40810dbef788acecc..cf35c3cd53b2fb146abf8d69f28d1423dca85db6 100644 (file)
@@ -1,10 +1,13 @@
 use rustc_ast::ast::{self, AttrStyle};
 use rustc_ast::token::{self, CommentKind, Token, TokenKind};
 use rustc_ast::tokenstream::{Spacing, TokenStream};
+use rustc_ast::util::unicode::contains_text_flow_control_chars;
 use rustc_errors::{error_code, Applicability, DiagnosticBuilder, FatalError, PResult};
 use rustc_lexer::unescape::{self, Mode};
 use rustc_lexer::{Base, DocStyle, RawStrError};
-use rustc_session::lint::builtin::RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX;
+use rustc_session::lint::builtin::{
+    RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
+};
 use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::{sym, Symbol};
@@ -129,6 +132,24 @@ fn struct_fatal_span_char(
             .struct_span_fatal(self.mk_sp(from_pos, to_pos), &format!("{}: {}", m, escaped_char(c)))
     }
 
+    /// Detect usages of Unicode codepoints changing the direction of the text on screen and loudly
+    /// complain about it.
+    fn lint_unicode_text_flow(&self, start: BytePos) {
+        // Opening delimiter of the length 2 is not included into the comment text.
+        let content_start = start + BytePos(2);
+        let content = self.str_from(content_start);
+        if contains_text_flow_control_chars(content) {
+            let span = self.mk_sp(start, self.pos);
+            self.sess.buffer_lint_with_diagnostic(
+                &TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
+                span,
+                ast::CRATE_NODE_ID,
+                "unicode codepoint changing visible direction of text present in comment",
+                BuiltinLintDiagnostics::UnicodeTextFlow(span, content.to_string()),
+            );
+        }
+    }
+
     /// Turns simple `rustc_lexer::TokenKind` enum into a rich
     /// `rustc_ast::TokenKind`. This turns strings into interned
     /// symbols and runs additional validation.
@@ -136,7 +157,12 @@ fn cook_lexer_token(&self, token: rustc_lexer::TokenKind, start: BytePos) -> Opt
         Some(match token {
             rustc_lexer::TokenKind::LineComment { doc_style } => {
                 // Skip non-doc comments
-                let doc_style = doc_style?;
+                let doc_style = if let Some(doc_style) = doc_style {
+                    doc_style
+                } else {
+                    self.lint_unicode_text_flow(start);
+                    return None;
+                };
 
                 // Opening delimiter of the length 3 is not included into the symbol.
                 let content_start = start + BytePos(3);
@@ -158,7 +184,12 @@ fn cook_lexer_token(&self, token: rustc_lexer::TokenKind, start: BytePos) -> Opt
                 }
 
                 // Skip non-doc comments
-                let doc_style = doc_style?;
+                let doc_style = if let Some(doc_style) = doc_style {
+                    doc_style
+                } else {
+                    self.lint_unicode_text_flow(start);
+                    return None;
+                };
 
                 // Opening delimiter of the length 3 and closing delimiter of the length 2
                 // are not included into the symbol.
index cef5b3a226bff81a65f1fa69da5bdfc227e06a77..569f186a72766f45aed97f560400a3cc91c5f6e7 100644 (file)
@@ -187,12 +187,17 @@ pub(crate) fn emit_unescape_error(
             assert!(mode.is_bytes());
             let (c, span) = last_char();
             let mut err = handler.struct_span_err(span, "non-ASCII character in byte constant");
-            err.span_label(span, "byte constant must be ASCII");
+            let postfix = if unicode_width::UnicodeWidthChar::width(c).unwrap_or(1) == 0 {
+                format!(" but is {:?}", c)
+            } else {
+                String::new()
+            };
+            err.span_label(span, &format!("byte constant must be ASCII{}", postfix));
             if (c as u32) <= 0xFF {
                 err.span_suggestion(
                     span,
                     &format!(
-                        "if you meant to use the unicode code point for '{}', use a \\xHH escape",
+                        "if you meant to use the unicode code point for {:?}, use a \\xHH escape",
                         c
                     ),
                     format!("\\x{:X}", c as u32),
@@ -206,7 +211,7 @@ pub(crate) fn emit_unescape_error(
                 err.span_suggestion(
                     span,
                     &format!(
-                        "if you meant to use the UTF-8 encoding of '{}', use \\xHH escapes",
+                        "if you meant to use the UTF-8 encoding of {:?}, use \\xHH escapes",
                         c
                     ),
                     utf8.as_bytes()
@@ -220,10 +225,15 @@ pub(crate) fn emit_unescape_error(
         }
         EscapeError::NonAsciiCharInByteString => {
             assert!(mode.is_bytes());
-            let (_c, span) = last_char();
+            let (c, span) = last_char();
+            let postfix = if unicode_width::UnicodeWidthChar::width(c).unwrap_or(1) == 0 {
+                format!(" but is {:?}", c)
+            } else {
+                String::new()
+            };
             handler
                 .struct_span_err(span, "raw byte string must be ASCII")
-                .span_label(span, "must be ASCII")
+                .span_label(span, &format!("must be ASCII{}", postfix))
                 .emit();
         }
         EscapeError::OutOfRangeHexEscape => {
index d2167c7a5db0c8f642f61c047f5b3b54b39372eb..73ca809ab1d3a53f72523025251250e2bd842f18 100644 (file)
@@ -220,7 +220,7 @@ fn parse_item_kind(
         } else if self.check_fn_front_matter(def_final) {
             // FUNCTION ITEM
             let (ident, sig, generics, body) = self.parse_fn(attrs, req_name, lo)?;
-            (ident, ItemKind::Fn(Box::new(FnKind(def(), sig, generics, body))))
+            (ident, ItemKind::Fn(Box::new(Fn { defaultness: def(), sig, generics, body })))
         } else if self.eat_keyword(kw::Extern) {
             if self.eat_keyword(kw::Crate) {
                 // EXTERN CRATE
@@ -560,7 +560,7 @@ fn parse_item_impl(
                 };
                 let trait_ref = TraitRef { path, ref_id: ty_first.id };
 
-                ItemKind::Impl(Box::new(ImplKind {
+                ItemKind::Impl(Box::new(Impl {
                     unsafety,
                     polarity,
                     defaultness,
@@ -573,7 +573,7 @@ fn parse_item_impl(
             }
             None => {
                 // impl Type
-                ItemKind::Impl(Box::new(ImplKind {
+                ItemKind::Impl(Box::new(Impl {
                     unsafety,
                     polarity,
                     defaultness,
@@ -682,7 +682,7 @@ fn parse_item_trait(&mut self, attrs: &mut Vec<Attribute>, lo: Span) -> PResult<
 
         self.expect_keyword(kw::Trait)?;
         let ident = self.parse_ident()?;
-        let mut tps = self.parse_generics()?;
+        let mut generics = self.parse_generics()?;
 
         // Parse optional colon and supertrait bounds.
         let had_colon = self.eat(&token::Colon);
@@ -702,7 +702,7 @@ fn parse_item_trait(&mut self, attrs: &mut Vec<Attribute>, lo: Span) -> PResult<
             }
 
             let bounds = self.parse_generic_bounds(None)?;
-            tps.where_clause = self.parse_where_clause()?;
+            generics.where_clause = self.parse_where_clause()?;
             self.expect_semi()?;
 
             let whole_span = lo.to(self.prev_token.span);
@@ -717,12 +717,15 @@ fn parse_item_trait(&mut self, attrs: &mut Vec<Attribute>, lo: Span) -> PResult<
 
             self.sess.gated_spans.gate(sym::trait_alias, whole_span);
 
-            Ok((ident, ItemKind::TraitAlias(tps, bounds)))
+            Ok((ident, ItemKind::TraitAlias(generics, bounds)))
         } else {
             // It's a normal trait.
-            tps.where_clause = self.parse_where_clause()?;
+            generics.where_clause = self.parse_where_clause()?;
             let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?;
-            Ok((ident, ItemKind::Trait(Box::new(TraitKind(is_auto, unsafety, tps, bounds, items)))))
+            Ok((
+                ident,
+                ItemKind::Trait(Box::new(Trait { is_auto, unsafety, generics, bounds, items })),
+            ))
         }
     }
 
@@ -769,7 +772,7 @@ fn parse_assoc_item(
     /// TypeAlias = "type" Ident Generics {":" GenericBounds}? {"=" Ty}? ";" ;
     /// ```
     /// The `"type"` has already been eaten.
-    fn parse_type_alias(&mut self, def: Defaultness) -> PResult<'a, ItemInfo> {
+    fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemInfo> {
         let ident = self.parse_ident()?;
         let mut generics = self.parse_generics()?;
 
@@ -778,10 +781,10 @@ fn parse_type_alias(&mut self, def: Defaultness) -> PResult<'a, ItemInfo> {
             if self.eat(&token::Colon) { self.parse_generic_bounds(None)? } else { Vec::new() };
         generics.where_clause = self.parse_where_clause()?;
 
-        let default = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None };
+        let ty = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None };
         self.expect_semi()?;
 
-        Ok((ident, ItemKind::TyAlias(Box::new(TyAliasKind(def, generics, bounds, default)))))
+        Ok((ident, ItemKind::TyAlias(Box::new(TyAlias { defaultness, generics, bounds, ty }))))
     }
 
     /// Parses a `UseTree`.
@@ -1039,9 +1042,7 @@ fn recover_const_impl(
         };
 
         match impl_info.1 {
-            ItemKind::Impl(box ImplKind {
-                of_trait: Some(ref trai), ref mut constness, ..
-            }) => {
+            ItemKind::Impl(box Impl { of_trait: Some(ref trai), ref mut constness, .. }) => {
                 *constness = Const::Yes(const_span);
 
                 let before_trait = trai.path.span.shrink_to_lo();
index 92d9e89c3a383ed10a4f21413240db53bd1771cb..596d13d2d9acbb7aa8c79b2f79820e88f76db106 100644 (file)
@@ -62,7 +62,7 @@ impl CheckAttrVisitor<'tcx> {
     fn check_attributes(
         &self,
         hir_id: HirId,
-        span: Span,
+        span: &Span,
         target: Target,
         item: Option<ItemLike<'_>>,
     ) {
@@ -78,7 +78,7 @@ fn check_attributes(
                 sym::marker => self.check_marker(hir_id, attr, span, target),
                 sym::target_feature => self.check_target_feature(hir_id, attr, span, target),
                 sym::track_caller => {
-                    self.check_track_caller(hir_id, attr.span, attrs, span, target)
+                    self.check_track_caller(hir_id, &attr.span, attrs, span, target)
                 }
                 sym::doc => self.check_doc_attrs(
                     attr,
@@ -103,9 +103,6 @@ fn check_attributes(
                 sym::rustc_legacy_const_generics => {
                     self.check_rustc_legacy_const_generics(&attr, span, target, item)
                 }
-                sym::rustc_lint_query_instability => {
-                    self.check_rustc_lint_query_instability(&attr, span, target)
-                }
                 sym::rustc_clean
                 | sym::rustc_dirty
                 | sym::rustc_if_this_changed
@@ -233,7 +230,7 @@ fn inline_attr_str_error_without_macro_def(&self, hir_id: HirId, attr: &Attribut
     }
 
     /// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid.
-    fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
+    fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) -> bool {
         match target {
             Target::Fn
             | Target::Closure
@@ -276,7 +273,7 @@ fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Targ
                     E0518,
                     "attribute should be applied to function or closure",
                 )
-                .span_label(span, "not a function or closure")
+                .span_label(*span, "not a function or closure")
                 .emit();
                 false
             }
@@ -315,7 +312,7 @@ fn check_generic_attr(
     }
 
     /// Checks if `#[naked]` is applied to a function definition.
-    fn check_naked(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
+    fn check_naked(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) -> bool {
         match target {
             Target::Fn
             | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
@@ -334,7 +331,7 @@ fn check_naked(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Targe
                         attr.span,
                         "attribute should be applied to a function definition",
                     )
-                    .span_label(span, "not a function definition")
+                    .span_label(*span, "not a function definition")
                     .emit();
                 false
             }
@@ -342,7 +339,7 @@ fn check_naked(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Targe
     }
 
     /// Checks if `#[cmse_nonsecure_entry]` is applied to a function definition.
-    fn check_cmse_nonsecure_entry(&self, attr: &Attribute, span: Span, target: Target) -> bool {
+    fn check_cmse_nonsecure_entry(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
         match target {
             Target::Fn
             | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
@@ -353,7 +350,7 @@ fn check_cmse_nonsecure_entry(&self, attr: &Attribute, span: Span, target: Targe
                         attr.span,
                         "attribute should be applied to a function definition",
                     )
-                    .span_label(span, "not a function definition")
+                    .span_label(*span, "not a function definition")
                     .emit();
                 false
             }
@@ -364,16 +361,16 @@ fn check_cmse_nonsecure_entry(&self, attr: &Attribute, span: Span, target: Targe
     fn check_track_caller(
         &self,
         hir_id: HirId,
-        attr_span: Span,
+        attr_span: &Span,
         attrs: &'hir [Attribute],
-        span: Span,
+        span: &Span,
         target: Target,
     ) -> bool {
         match target {
             _ if attrs.iter().any(|attr| attr.has_name(sym::naked)) => {
                 struct_span_err!(
                     self.tcx.sess,
-                    attr_span,
+                    *attr_span,
                     E0736,
                     "cannot use `#[track_caller]` with `#[naked]`",
                 )
@@ -394,11 +391,11 @@ fn check_track_caller(
             _ => {
                 struct_span_err!(
                     self.tcx.sess,
-                    attr_span,
+                    *attr_span,
                     E0739,
                     "attribute should be applied to function"
                 )
-                .span_label(span, "not a function")
+                .span_label(*span, "not a function")
                 .emit();
                 false
             }
@@ -410,7 +407,7 @@ fn check_non_exhaustive(
         &self,
         hir_id: HirId,
         attr: &Attribute,
-        span: Span,
+        span: &Span,
         target: Target,
     ) -> bool {
         match target {
@@ -430,7 +427,7 @@ fn check_non_exhaustive(
                     E0701,
                     "attribute can only be applied to a struct or enum"
                 )
-                .span_label(span, "not a struct or enum")
+                .span_label(*span, "not a struct or enum")
                 .emit();
                 false
             }
@@ -438,7 +435,7 @@ fn check_non_exhaustive(
     }
 
     /// Checks if the `#[marker]` attribute on an `item` is valid. Returns `true` if valid.
-    fn check_marker(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
+    fn check_marker(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) -> bool {
         match target {
             Target::Trait => true,
             // FIXME(#80564): We permit struct fields, match arms and macro defs to have an
@@ -453,7 +450,7 @@ fn check_marker(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Targ
                 self.tcx
                     .sess
                     .struct_span_err(attr.span, "attribute can only be applied to a trait")
-                    .span_label(span, "not a trait")
+                    .span_label(*span, "not a trait")
                     .emit();
                 false
             }
@@ -465,7 +462,7 @@ fn check_target_feature(
         &self,
         hir_id: HirId,
         attr: &Attribute,
-        span: Span,
+        span: &Span,
         target: Target,
     ) -> bool {
         match target {
@@ -481,7 +478,7 @@ fn check_target_feature(
                              being phased out; it will become a hard error in \
                              a future release!",
                         )
-                        .span_label(span, "not a function")
+                        .span_label(*span, "not a function")
                         .emit();
                 });
                 true
@@ -498,7 +495,7 @@ fn check_target_feature(
                 self.tcx
                     .sess
                     .struct_span_err(attr.span, "attribute should be applied to a function")
-                    .span_label(span, "not a function")
+                    .span_label(*span, "not a function")
                     .emit();
                 false
             }
@@ -768,7 +765,7 @@ fn check_doc_inline(
                             "not a `use` item",
                         );
                     }
-                    err.note("read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information")
+                    err.note("read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline for more information")
                         .emit();
                 },
             );
@@ -1050,14 +1047,14 @@ fn check_doc_attrs(
     }
 
     /// Checks if `#[must_not_suspend]` is applied to a function. Returns `true` if valid.
-    fn check_must_not_suspend(&self, attr: &Attribute, span: Span, target: Target) -> bool {
+    fn check_must_not_suspend(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
         match target {
             Target::Struct | Target::Enum | Target::Union | Target::Trait => true,
             _ => {
                 self.tcx
                     .sess
                     .struct_span_err(attr.span, "`must_not_suspend` attribute should be applied to a struct, enum, or trait")
-                        .span_label(span, "is not a struct, enum, or trait")
+                        .span_label(*span, "is not a struct, enum, or trait")
                         .emit();
                 false
             }
@@ -1065,7 +1062,7 @@ fn check_must_not_suspend(&self, attr: &Attribute, span: Span, target: Target) -
     }
 
     /// Checks if `#[cold]` is applied to a non-function. Returns `true` if valid.
-    fn check_cold(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
+    fn check_cold(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) {
         match target {
             Target::Fn | Target::Method(..) | Target::ForeignFn | Target::Closure => {}
             // FIXME(#80564): We permit struct fields, match arms and macro defs to have an
@@ -1085,7 +1082,7 @@ fn check_cold(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target
                              being phased out; it will become a hard error in \
                              a future release!",
                         )
-                        .span_label(span, "not a function")
+                        .span_label(*span, "not a function")
                         .emit();
                 });
             }
@@ -1093,7 +1090,7 @@ fn check_cold(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target
     }
 
     /// Checks if `#[link_name]` is applied to an item other than a foreign function or static.
-    fn check_link_name(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
+    fn check_link_name(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) {
         match target {
             Target::ForeignFn | Target::ForeignStatic => {}
             // FIXME(#80564): We permit struct fields, match arms and macro defs to have an
@@ -1127,7 +1124,7 @@ fn check_link_name(&self, hir_id: HirId, attr: &Attribute, span: Span, target: T
                         }
                     }
 
-                    diag.span_label(span, "not a foreign function or static");
+                    diag.span_label(*span, "not a foreign function or static");
                     diag.emit();
                 });
             }
@@ -1135,7 +1132,7 @@ fn check_link_name(&self, hir_id: HirId, attr: &Attribute, span: Span, target: T
     }
 
     /// Checks if `#[no_link]` is applied to an `extern crate`. Returns `true` if valid.
-    fn check_no_link(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
+    fn check_no_link(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) -> bool {
         match target {
             Target::ExternCrate => true,
             // FIXME(#80564): We permit struct fields, match arms and macro defs to have an
@@ -1153,7 +1150,7 @@ fn check_no_link(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Tar
                         attr.span,
                         "attribute should be applied to an `extern crate` item",
                     )
-                    .span_label(span, "not an `extern crate` item")
+                    .span_label(*span, "not an `extern crate` item")
                     .emit();
                 false
             }
@@ -1169,7 +1166,7 @@ fn check_export_name(
         &self,
         hir_id: HirId,
         attr: &Attribute,
-        span: Span,
+        span: &Span,
         target: Target,
     ) -> bool {
         match target {
@@ -1190,7 +1187,7 @@ fn check_export_name(
                         attr.span,
                         "attribute should be applied to a free function, impl method or static",
                     )
-                    .span_label(span, "not a free function, impl method or static")
+                    .span_label(*span, "not a free function, impl method or static")
                     .emit();
                 false
             }
@@ -1200,14 +1197,14 @@ fn check_export_name(
     fn check_rustc_layout_scalar_valid_range(
         &self,
         attr: &Attribute,
-        span: Span,
+        span: &Span,
         target: Target,
     ) -> bool {
         if target != Target::Struct {
             self.tcx
                 .sess
                 .struct_span_err(attr.span, "attribute should be applied to a struct")
-                .span_label(span, "not a struct")
+                .span_label(*span, "not a struct")
                 .emit();
             return false;
         }
@@ -1232,7 +1229,7 @@ fn check_rustc_layout_scalar_valid_range(
     fn check_rustc_legacy_const_generics(
         &self,
         attr: &Attribute,
-        span: Span,
+        span: &Span,
         target: Target,
         item: Option<ItemLike<'_>>,
     ) -> bool {
@@ -1241,7 +1238,7 @@ fn check_rustc_legacy_const_generics(
             self.tcx
                 .sess
                 .struct_span_err(attr.span, "attribute should be applied to a function")
-                .span_label(span, "not a function")
+                .span_label(*span, "not a function")
                 .emit();
             return false;
         }
@@ -1327,25 +1324,6 @@ fn check_rustc_legacy_const_generics(
         }
     }
 
-    fn check_rustc_lint_query_instability(
-        &self,
-        attr: &Attribute,
-        span: Span,
-        target: Target,
-    ) -> bool {
-        let is_function = matches!(target, Target::Fn | Target::Method(..));
-        if !is_function {
-            self.tcx
-                .sess
-                .struct_span_err(attr.span, "attribute should be applied to a function")
-                .span_label(span, "not a function")
-                .emit();
-            false
-        } else {
-            true
-        }
-    }
-
     /// Checks that the dep-graph debugging attributes are only present when the query-dep-graph
     /// option is passed to the compiler.
     fn check_rustc_dirty_clean(&self, attr: &Attribute) -> bool {
@@ -1361,7 +1339,7 @@ fn check_rustc_dirty_clean(&self, attr: &Attribute) -> bool {
     }
 
     /// Checks if `#[link_section]` is applied to a function or static.
-    fn check_link_section(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
+    fn check_link_section(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) {
         match target {
             Target::Static | Target::Fn | Target::Method(..) => {}
             // FIXME(#80564): We permit struct fields, match arms and macro defs to have an
@@ -1381,7 +1359,7 @@ fn check_link_section(&self, hir_id: HirId, attr: &Attribute, span: Span, target
                              being phased out; it will become a hard error in \
                              a future release!",
                         )
-                        .span_label(span, "not a function or static")
+                        .span_label(*span, "not a function or static")
                         .emit();
                 });
             }
@@ -1389,7 +1367,7 @@ fn check_link_section(&self, hir_id: HirId, attr: &Attribute, span: Span, target
     }
 
     /// Checks if `#[no_mangle]` is applied to a function or static.
-    fn check_no_mangle(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
+    fn check_no_mangle(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) {
         match target {
             Target::Static | Target::Fn => {}
             Target::Method(..) if self.is_impl_item(hir_id) => {}
@@ -1419,7 +1397,7 @@ fn check_no_mangle(&self, hir_id: HirId, attr: &Attribute, span: Span, target: T
                             being phased out; it will become a hard error in \
                             a future release!",
                     )
-                    .span_label(span, format!("foreign {}", foreign_item_kind))
+                    .span_label(*span, format!("foreign {}", foreign_item_kind))
                     .note("symbol names in extern blocks are not mangled")
                     .span_suggestion(
                         attr.span,
@@ -1442,7 +1420,7 @@ fn check_no_mangle(&self, hir_id: HirId, attr: &Attribute, span: Span, target: T
                          being phased out; it will become a hard error in \
                          a future release!",
                     )
-                    .span_label(span, "not a free function, impl method or static")
+                    .span_label(*span, "not a free function, impl method or static")
                     .emit();
                 });
             }
@@ -1453,7 +1431,7 @@ fn check_no_mangle(&self, hir_id: HirId, attr: &Attribute, span: Span, target: T
     fn check_repr(
         &self,
         attrs: &'hir [Attribute],
-        span: Span,
+        span: &Span,
         target: Target,
         item: Option<ItemLike<'_>>,
         hir_id: HirId,
@@ -1587,7 +1565,7 @@ fn check_repr(
                 "{}",
                 &format!("attribute should be applied to {} {}", article, allowed_targets)
             )
-            .span_label(span, &format!("not {} {}", article, allowed_targets))
+            .span_label(*span, &format!("not {} {}", article, allowed_targets))
             .emit();
         }
 
@@ -1650,7 +1628,7 @@ fn check_allow_internal_unstable(
         &self,
         hir_id: HirId,
         attr: &Attribute,
-        span: Span,
+        span: &Span,
         target: Target,
         attrs: &[Attribute],
     ) -> bool {
@@ -1683,7 +1661,7 @@ fn check_allow_internal_unstable(
                 self.tcx
                     .sess
                     .struct_span_err(attr.span, "attribute should be applied to a macro")
-                    .span_label(span, "not a macro")
+                    .span_label(*span, "not a macro")
                     .emit();
                 false
             }
@@ -1696,7 +1674,7 @@ fn check_rustc_allow_const_fn_unstable(
         &self,
         hir_id: HirId,
         attr: &Attribute,
-        span: Span,
+        span: &Span,
         target: Target,
     ) -> bool {
         match target {
@@ -1717,7 +1695,7 @@ fn check_rustc_allow_const_fn_unstable(
                 self.tcx
                     .sess
                     .struct_span_err(attr.span, "attribute should be applied to `const fn`")
-                    .span_label(span, "not a `const fn`")
+                    .span_label(*span, "not a `const fn`")
                     .emit();
                 false
             }
@@ -1728,7 +1706,7 @@ fn check_rustc_allow_const_fn_unstable(
     fn check_default_method_body_is_const(
         &self,
         attr: &Attribute,
-        span: Span,
+        span: &Span,
         target: Target,
     ) -> bool {
         match target {
@@ -1740,14 +1718,14 @@ fn check_default_method_body_is_const(
                         attr.span,
                         "attribute should be applied to a trait method with body",
                     )
-                    .span_label(span, "not a trait method or missing a body")
+                    .span_label(*span, "not a trait method or missing a body")
                     .emit();
                 false
             }
         }
     }
 
-    fn check_stability_promotable(&self, attr: &Attribute, _span: Span, target: Target) -> bool {
+    fn check_stability_promotable(&self, attr: &Attribute, _span: &Span, target: Target) -> bool {
         match target {
             Target::Expression => {
                 self.tcx
@@ -1760,7 +1738,7 @@ fn check_stability_promotable(&self, attr: &Attribute, _span: Span, target: Targ
         }
     }
 
-    fn check_deprecated(&self, hir_id: HirId, attr: &Attribute, _span: Span, target: Target) {
+    fn check_deprecated(&self, hir_id: HirId, attr: &Attribute, _span: &Span, target: Target) {
         match target {
             Target::Closure | Target::Expression | Target::Statement | Target::Arm => {
                 self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
@@ -1832,29 +1810,29 @@ fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
         }
 
         let target = Target::from_item(item);
-        self.check_attributes(item.hir_id(), item.span, target, Some(ItemLike::Item(item)));
+        self.check_attributes(item.hir_id(), &item.span, target, Some(ItemLike::Item(item)));
         intravisit::walk_item(self, item)
     }
 
     fn visit_generic_param(&mut self, generic_param: &'tcx hir::GenericParam<'tcx>) {
         let target = Target::from_generic_param(generic_param);
-        self.check_attributes(generic_param.hir_id, generic_param.span, target, None);
+        self.check_attributes(generic_param.hir_id, &generic_param.span, target, None);
         intravisit::walk_generic_param(self, generic_param)
     }
 
     fn visit_trait_item(&mut self, trait_item: &'tcx TraitItem<'tcx>) {
         let target = Target::from_trait_item(trait_item);
-        self.check_attributes(trait_item.hir_id(), trait_item.span, target, None);
+        self.check_attributes(trait_item.hir_id(), &trait_item.span, target, None);
         intravisit::walk_trait_item(self, trait_item)
     }
 
     fn visit_field_def(&mut self, struct_field: &'tcx hir::FieldDef<'tcx>) {
-        self.check_attributes(struct_field.hir_id, struct_field.span, Target::Field, None);
+        self.check_attributes(struct_field.hir_id, &struct_field.span, Target::Field, None);
         intravisit::walk_field_def(self, struct_field);
     }
 
     fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) {
-        self.check_attributes(arm.hir_id, arm.span, Target::Arm, None);
+        self.check_attributes(arm.hir_id, &arm.span, Target::Arm, None);
         intravisit::walk_arm(self, arm);
     }
 
@@ -1862,7 +1840,7 @@ fn visit_foreign_item(&mut self, f_item: &'tcx ForeignItem<'tcx>) {
         let target = Target::from_foreign_item(f_item);
         self.check_attributes(
             f_item.hir_id(),
-            f_item.span,
+            &f_item.span,
             target,
             Some(ItemLike::ForeignItem(f_item)),
         );
@@ -1871,14 +1849,14 @@ fn visit_foreign_item(&mut self, f_item: &'tcx ForeignItem<'tcx>) {
 
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         let target = target_from_impl_item(self.tcx, impl_item);
-        self.check_attributes(impl_item.hir_id(), impl_item.span, target, None);
+        self.check_attributes(impl_item.hir_id(), &impl_item.span, target, None);
         intravisit::walk_impl_item(self, impl_item)
     }
 
     fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) {
         // When checking statements ignore expressions, they will be checked later.
         if let hir::StmtKind::Local(ref l) = stmt.kind {
-            self.check_attributes(l.hir_id, stmt.span, Target::Statement, None);
+            self.check_attributes(l.hir_id, &stmt.span, Target::Statement, None);
         }
         intravisit::walk_stmt(self, stmt)
     }
@@ -1889,7 +1867,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
             _ => Target::Expression,
         };
 
-        self.check_attributes(expr.hir_id, expr.span, target, None);
+        self.check_attributes(expr.hir_id, &expr.span, target, None);
         intravisit::walk_expr(self, expr)
     }
 
@@ -1899,12 +1877,12 @@ fn visit_variant(
         generics: &'tcx hir::Generics<'tcx>,
         item_id: HirId,
     ) {
-        self.check_attributes(variant.id, variant.span, Target::Variant, None);
+        self.check_attributes(variant.id, &variant.span, Target::Variant, None);
         intravisit::walk_variant(self, variant, generics, item_id)
     }
 
     fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
-        self.check_attributes(param.hir_id, param.span, Target::Param, None);
+        self.check_attributes(param.hir_id, &param.span, Target::Param, None);
 
         intravisit::walk_param(self, param);
     }
@@ -1972,7 +1950,7 @@ fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
     let check_attr_visitor = &mut CheckAttrVisitor { tcx };
     tcx.hir().visit_item_likes_in_module(module_def_id, &mut check_attr_visitor.as_deep_visitor());
     if module_def_id.is_top_level_module() {
-        check_attr_visitor.check_attributes(CRATE_HIR_ID, DUMMY_SP, Target::Mod, None);
+        check_attr_visitor.check_attributes(CRATE_HIR_ID, &DUMMY_SP, Target::Mod, None);
         check_invalid_crate_level_attr(tcx, tcx.hir().krate_attrs());
     }
 }
index a0ceb567f25a6f8d13b6d04bc860153e86a3c478..82486a6a5f2e277a75b639edd84c5127e1af0750 100644 (file)
@@ -210,10 +210,10 @@ fn const_check_violated(&self, expr: NonConstExpr, span: Span) {
             required_gates.iter().copied().filter(|&g| !features.enabled(g)).collect();
 
         match missing_gates.as_slice() {
-            &[] => struct_span_err!(tcx.sess, span, E0744, "{}", msg).emit(),
+            [] => struct_span_err!(tcx.sess, span, E0744, "{}", msg).emit(),
 
-            &[missing_primary, ref missing_secondary @ ..] => {
-                let mut err = feature_err(&tcx.sess.parse_sess, missing_primary, span, &msg);
+            [missing_primary, ref missing_secondary @ ..] => {
+                let mut err = feature_err(&tcx.sess.parse_sess, *missing_primary, span, &msg);
 
                 // If multiple feature gates would be required to enable this expression, include
                 // them as help messages. Don't emit a separate error for each missing feature gate.
index c698333c8e222a1005191449fd017a51c2353ce7..4adec3c4f608d78e93c412ccb6a5476a370fad7d 100644 (file)
@@ -14,7 +14,6 @@
 #![feature(nll)]
 #![feature(try_blocks)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate rustc_middle;
index 5fc8e230d72a3eba67aca78d8a258115f9d21e31..6a8feb041da19f5978c4cf6055f79e127bf61ffc 100644 (file)
@@ -334,9 +334,10 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
     // properly, we can't miss any types.
 
     match expr.kind {
-        // Manually recurse over closures, because they are the only
+        // Manually recurse over closures and inline consts, because they are the only
         // case of nested bodies that share the parent environment.
-        hir::ExprKind::Closure(.., body, _, _) => {
+        hir::ExprKind::Closure(.., body, _, _)
+        | hir::ExprKind::ConstBlock(hir::AnonConst { body, .. }) => {
             let body = visitor.tcx.hir().body(body);
             visitor.visit_body(body);
         }
@@ -817,9 +818,9 @@ fn visit_local(&mut self, l: &'tcx Local<'tcx>) {
 }
 
 fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree {
-    let closure_base_def_id = tcx.closure_base_def_id(def_id);
-    if closure_base_def_id != def_id {
-        return tcx.region_scope_tree(closure_base_def_id);
+    let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
+    if typeck_root_def_id != def_id {
+        return tcx.region_scope_tree(typeck_root_def_id);
     }
 
     let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
index d228a34046cef7b3800e333f4b93e2df63c7c024..a01efc5d85c6e765bd263855f0575656d1daf247 100644 (file)
@@ -5,7 +5,6 @@
 #![feature(try_blocks)]
 #![feature(associated_type_defaults)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 use rustc_ast::MacroDef;
 use rustc_attr as attr;
@@ -619,6 +618,7 @@ fn update_macro_reachable_def(
             | DefKind::Use
             | DefKind::ForeignMod
             | DefKind::AnonConst
+            | DefKind::InlineConst
             | DefKind::Field
             | DefKind::GlobalAsm
             | DefKind::Impl
index 2fcca326925b0ea82126fe20a5dacb631bc5477b..440b6f1983e6eee7d8e7cbfcf3784268412de789 100644 (file)
@@ -8,22 +8,19 @@
 #![feature(once_cell)]
 #![feature(rustc_attrs)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate rustc_macros;
 #[macro_use]
 extern crate rustc_middle;
 
-use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_errors::DiagnosticBuilder;
 use rustc_middle::arena::Arena;
-use rustc_middle::dep_graph::{self, DepKindStruct};
+use rustc_middle::dep_graph::{self, DepKindStruct, SerializedDepNodeIndex};
 use rustc_middle::ty::query::{query_keys, query_storage, query_stored, query_values};
-use rustc_middle::ty::query::{Providers, QueryEngine};
+use rustc_middle::ty::query::{ExternProviders, Providers, QueryEngine};
 use rustc_middle::ty::{self, TyCtxt};
-use rustc_query_system::ich::StableHashingContext;
+use rustc_span::def_id::LocalDefId;
 use rustc_span::Span;
 
 #[macro_use]
@@ -40,9 +37,8 @@
 mod values;
 use self::values::Value;
 
-use rustc_query_system::query::QueryAccessors;
 pub use rustc_query_system::query::QueryConfig;
-pub(crate) use rustc_query_system::query::QueryDescription;
+pub(crate) use rustc_query_system::query::{QueryDescription, QueryVtable};
 
 mod on_disk_cache;
 pub use on_disk_cache::OnDiskCache;
 
 mod util;
 
+fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
+    if def_id.is_top_level_module() {
+        "top-level module".to_string()
+    } else {
+        format!("module `{}`", tcx.def_path_str(def_id.to_def_id()))
+    }
+}
+
 rustc_query_append! { [define_queries!][<'tcx>] }
 
 impl<'tcx> Queries<'tcx> {
index 7678c86596b5a5efff88585e2ecdc933899acc30..552906aac31a7f5ac79b3abd45e612dd981f8de4 100644 (file)
@@ -1018,7 +1018,7 @@ pub fn encode_query_results<'a, 'tcx, CTX, Q>(
 ) -> FileEncodeResult
 where
     CTX: QueryContext + 'tcx,
-    Q: super::QueryDescription<CTX> + super::QueryAccessors<CTX>,
+    Q: super::QueryDescription<CTX>,
     Q::Value: Encodable<CacheEncoder<'a, 'tcx, FileEncoder>>,
 {
     let _timer = tcx
@@ -1033,7 +1033,7 @@ pub fn encode_query_results<'a, 'tcx, CTX, Q>(
         if res.is_err() {
             return;
         }
-        if Q::cache_on_disk(tcx, &key) {
+        if Q::cache_on_disk(*tcx.dep_context(), &key) {
             let dep_node = SerializedDepNodeIndex::new(dep_node.index());
 
             // Record position of the cache entry.
index a822ef1477808025967239fd18a511a7331c3d78..81a36e0d59eff601769bb373d03bf3b047e62df1 100644 (file)
@@ -2,20 +2,17 @@
 //! generate the actual methods on tcx which find and execute the provider,
 //! manage the caches, and so forth.
 
-use crate::{on_disk_cache, queries, Queries};
+use crate::{on_disk_cache, Queries};
 use rustc_middle::dep_graph::{DepKind, DepNodeIndex, SerializedDepNodeIndex};
 use rustc_middle::ty::tls::{self, ImplicitCtxt};
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::TyCtxt;
 use rustc_query_system::dep_graph::HasDepContext;
-use rustc_query_system::query::{
-    QueryContext, QueryDescription, QueryJobId, QueryMap, QuerySideEffects,
-};
+use rustc_query_system::query::{QueryContext, QueryJobId, QueryMap, QuerySideEffects};
 
 use rustc_data_structures::sync::Lock;
 use rustc_data_structures::thin_vec::ThinVec;
 use rustc_errors::{Diagnostic, Handler};
 use rustc_serialize::opaque;
-use rustc_span::def_id::LocalDefId;
 
 use std::any::Any;
 
@@ -218,6 +215,22 @@ macro_rules! hash_result {
     };
 }
 
+macro_rules! get_provider {
+    ([][$tcx:expr, $name:ident, $key:expr]) => {{
+        $tcx.queries.local_providers.$name
+    }};
+    ([(separate_provide_extern) $($rest:tt)*][$tcx:expr, $name:ident, $key:expr]) => {{
+        if $key.query_crate_is_local() {
+            $tcx.queries.local_providers.$name
+        } else {
+            $tcx.queries.extern_providers.$name
+        }
+    }};
+    ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
+        get_provider!([$($modifiers)*][$($args)*])
+    };
+}
+
 macro_rules! define_queries {
     (<$tcx:tt>
      $($(#[$attr:meta])*
@@ -290,11 +303,8 @@ pub mod queries {
             const NAME: &'static str = stringify!($name);
         }
 
-        impl<$tcx> QueryAccessors<QueryCtxt<$tcx>> for queries::$name<$tcx> {
-            const ANON: bool = is_anon!([$($modifiers)*]);
-            const EVAL_ALWAYS: bool = is_eval_always!([$($modifiers)*]);
-            const DEP_KIND: dep_graph::DepKind = dep_graph::DepKind::$name;
-            const HASH_RESULT: Option<fn(&mut StableHashingContext<'_>, &Self::Value) -> Fingerprint> = hash_result!([$($modifiers)*]);
+        impl<$tcx> QueryDescription<QueryCtxt<$tcx>> for queries::$name<$tcx> {
+            rustc_query_description! { $name<$tcx> }
 
             type Cache = query_storage::$name<$tcx>;
 
@@ -313,22 +323,22 @@ fn query_cache<'a>(tcx: QueryCtxt<$tcx>) -> &'a QueryCacheStore<Self::Cache>
             }
 
             #[inline]
-            fn compute_fn(tcx: QueryCtxt<'tcx>, key: &Self::Key) ->
-                fn(TyCtxt<'tcx>, Self::Key) -> Self::Value
+            fn make_vtable(tcx: QueryCtxt<'tcx>, key: &Self::Key) ->
+                QueryVtable<QueryCtxt<$tcx>, Self::Key, Self::Value>
             {
-                if key.query_crate_is_local() {
-                    tcx.queries.local_providers.$name
-                } else {
-                    tcx.queries.extern_providers.$name
+                let compute = get_provider!([$($modifiers)*][tcx, $name, key]);
+                let cache_on_disk = Self::cache_on_disk(tcx.tcx, key);
+                QueryVtable {
+                    anon: is_anon!([$($modifiers)*]),
+                    eval_always: is_eval_always!([$($modifiers)*]),
+                    dep_kind: dep_graph::DepKind::$name,
+                    hash_result: hash_result!([$($modifiers)*]),
+                    handle_cycle_error: |tcx, mut error| handle_cycle_error!([$($modifiers)*][tcx, error]),
+                    compute,
+                    cache_on_disk,
+                    try_load_from_disk: Self::TRY_LOAD_FROM_DISK,
                 }
             }
-
-            fn handle_cycle_error(
-                tcx: QueryCtxt<'tcx>,
-                mut error: DiagnosticBuilder<'_>,
-            ) -> Self::Value {
-                handle_cycle_error!([$($modifiers)*][tcx, error])
-            }
         })*
 
         #[allow(nonstandard_style)]
@@ -417,7 +427,6 @@ fn try_load_from_on_disk_cache(tcx: TyCtxt<'_>, dep_node: DepNode) {
                     debug_assert!(tcx.dep_graph.is_green(&dep_node));
 
                     let key = recover(tcx, dep_node).unwrap_or_else(|| panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash));
-                    let tcx = QueryCtxt::from_tcx(tcx);
                     if queries::$name::cache_on_disk(tcx, &key) {
                         let _ = tcx.$name(key);
                     }
@@ -447,7 +456,7 @@ macro_rules! define_queries_struct {
      input: ($(([$($modifiers:tt)*] [$($attr:tt)*] [$name:ident]))*)) => {
         pub struct Queries<$tcx> {
             local_providers: Box<Providers>,
-            extern_providers: Box<Providers>,
+            extern_providers: Box<ExternProviders>,
 
             pub on_disk_cache: Option<OnDiskCache<$tcx>>,
 
@@ -460,7 +469,7 @@ pub struct Queries<$tcx> {
         impl<$tcx> Queries<$tcx> {
             pub fn new(
                 local_providers: Providers,
-                extern_providers: Providers,
+                extern_providers: ExternProviders,
                 on_disk_cache: Option<OnDiskCache<$tcx>>,
             ) -> Self {
                 Queries {
@@ -518,13 +527,3 @@ fn $name(
         }
     };
 }
-
-fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
-    if def_id.is_top_level_module() {
-        "top-level module".to_string()
-    } else {
-        format!("module `{}`", tcx.def_path_str(def_id.to_def_id()))
-    }
-}
-
-rustc_query_description! {}
index cfef2073373cc93c71bdbc91ec22735361ad323d..5f31fa04b8a6e1c099a846cf76a28ffa09462e65 100644 (file)
@@ -1,12 +1,12 @@
 use crate::ich;
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::sorted_map::SortedMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::Lrc;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::definitions::{DefPathHash, Definitions};
-use rustc_index::vec::IndexVec;
 use rustc_session::cstore::CrateStore;
 use rustc_session::Session;
 use rustc_span::source_map::SourceMap;
@@ -51,7 +51,7 @@ pub(super) enum BodyResolver<'tcx> {
     Traverse {
         hash_bodies: bool,
         owner: LocalDefId,
-        bodies: &'tcx IndexVec<hir::ItemLocalId, Option<&'tcx hir::Body<'tcx>>>,
+        bodies: &'tcx SortedMap<hir::ItemLocalId, &'tcx hir::Body<'tcx>>,
     },
 }
 
@@ -122,7 +122,7 @@ pub fn with_hir_bodies(
         &mut self,
         hash_bodies: bool,
         owner: LocalDefId,
-        bodies: &'a IndexVec<hir::ItemLocalId, Option<&'a hir::Body<'a>>>,
+        bodies: &'a SortedMap<hir::ItemLocalId, &'a hir::Body<'a>>,
         f: impl FnOnce(&mut Self),
     ) {
         let prev = self.body_resolver;
index 24f3a2e7de0a9926945fe569a37a4104d27219c1..3a0aab81fdb7b257b32908ba0aaf26482bc8195e 100644 (file)
@@ -33,7 +33,7 @@ fn hash_body_id(&mut self, id: hir::BodyId, hasher: &mut StableHasher) {
             BodyResolver::Traverse { hash_bodies: false, .. } => {}
             BodyResolver::Traverse { hash_bodies: true, owner, bodies } => {
                 assert_eq!(id.hir_id.owner, owner);
-                bodies[id.hir_id.local_id].unwrap().hash_stable(hcx, hasher);
+                bodies[&id.hir_id.local_id].hash_stable(hcx, hasher);
             }
         }
     }
index 8f57855b230c30ace8cf6077e4813be05fbe3e8c..1b992cdb0c94b2f0a3fbc7c491aa3bfc2fecff08 100644 (file)
@@ -6,7 +6,6 @@
 #![feature(let_else)]
 #![feature(min_specialization)]
 #![feature(thread_local_const_init)]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate tracing;
index 07b2e2b1080b8da3f0fac286904623476bf514f6..d2b102b6f89681358bca92bfb1cd9b3bf8d53b87 100644 (file)
@@ -19,16 +19,16 @@ pub trait QueryConfig {
     type Stored: Clone;
 }
 
-pub(crate) struct QueryVtable<CTX: QueryContext, K, V> {
+pub struct QueryVtable<CTX: QueryContext, K, V> {
     pub anon: bool,
     pub dep_kind: CTX::DepKind,
     pub eval_always: bool,
+    pub cache_on_disk: bool,
 
     pub compute: fn(CTX::DepContext, K) -> V,
     pub hash_result: Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>,
     pub handle_cycle_error: fn(CTX, DiagnosticBuilder<'_>) -> V,
-    pub cache_on_disk: fn(CTX, &K) -> bool,
-    pub try_load_from_disk: fn(CTX, SerializedDepNodeIndex) -> Option<V>,
+    pub try_load_from_disk: Option<fn(CTX, SerializedDepNodeIndex) -> Option<V>>,
 }
 
 impl<CTX: QueryContext, K, V> QueryVtable<CTX, K, V> {
@@ -43,25 +43,21 @@ pub(crate) fn compute(&self, tcx: CTX::DepContext, key: K) -> V {
         (self.compute)(tcx, key)
     }
 
-    pub(crate) fn cache_on_disk(&self, tcx: CTX, key: &K) -> bool {
-        (self.cache_on_disk)(tcx, key)
-    }
-
     pub(crate) fn try_load_from_disk(&self, tcx: CTX, index: SerializedDepNodeIndex) -> Option<V> {
-        (self.try_load_from_disk)(tcx, index)
+        self.try_load_from_disk
+            .expect("QueryDescription::load_from_disk() called for an unsupported query.")(
+            tcx, index,
+        )
     }
 }
 
-pub trait QueryAccessors<CTX: QueryContext>: QueryConfig {
-    const ANON: bool;
-    const EVAL_ALWAYS: bool;
-    const DEP_KIND: CTX::DepKind;
-    const HASH_RESULT: Option<
-        fn(hcx: &mut StableHashingContext<'_>, result: &Self::Value) -> Fingerprint,
-    >;
+pub trait QueryDescription<CTX: QueryContext>: QueryConfig {
+    const TRY_LOAD_FROM_DISK: Option<fn(CTX, SerializedDepNodeIndex) -> Option<Self::Value>>;
 
     type Cache: QueryCache<Key = Self::Key, Stored = Self::Stored, Value = Self::Value>;
 
+    fn describe(tcx: CTX, key: Self::Key) -> String;
+
     // Don't use this method to access query results, instead use the methods on TyCtxt
     fn query_state<'a>(tcx: CTX) -> &'a QueryState<CTX::DepKind, Self::Key>
     where
@@ -73,43 +69,7 @@ fn query_cache<'a>(tcx: CTX) -> &'a QueryCacheStore<Self::Cache>
         CTX: 'a;
 
     // Don't use this method to compute query results, instead use the methods on TyCtxt
-    fn compute_fn(tcx: CTX, key: &Self::Key) -> fn(CTX::DepContext, Self::Key) -> Self::Value;
-
-    fn handle_cycle_error(tcx: CTX, diag: DiagnosticBuilder<'_>) -> Self::Value;
-}
-
-pub trait QueryDescription<CTX: QueryContext>: QueryAccessors<CTX> {
-    fn describe(tcx: CTX, key: Self::Key) -> String;
+    fn make_vtable(tcx: CTX, key: &Self::Key) -> QueryVtable<CTX, Self::Key, Self::Value>;
 
-    #[inline]
-    fn cache_on_disk(_: CTX, _: &Self::Key) -> bool {
-        false
-    }
-
-    fn try_load_from_disk(_: CTX, _: SerializedDepNodeIndex) -> Option<Self::Value> {
-        panic!("QueryDescription::load_from_disk() called for an unsupported query.")
-    }
-}
-
-pub(crate) trait QueryVtableExt<CTX: QueryContext, K, V> {
-    fn make_vtable(tcx: CTX, key: &K) -> QueryVtable<CTX, K, V>;
-}
-
-impl<CTX, Q> QueryVtableExt<CTX, Q::Key, Q::Value> for Q
-where
-    CTX: QueryContext,
-    Q: QueryDescription<CTX>,
-{
-    fn make_vtable(tcx: CTX, key: &Q::Key) -> QueryVtable<CTX, Q::Key, Q::Value> {
-        QueryVtable {
-            anon: Q::ANON,
-            dep_kind: Q::DEP_KIND,
-            eval_always: Q::EVAL_ALWAYS,
-            hash_result: Q::HASH_RESULT,
-            compute: Q::compute_fn(tcx, key),
-            handle_cycle_error: Q::handle_cycle_error,
-            cache_on_disk: Q::cache_on_disk,
-            try_load_from_disk: Q::try_load_from_disk,
-        }
-    }
+    fn cache_on_disk(tcx: CTX::DepContext, key: &Self::Key) -> bool;
 }
index e2b0a65ab77b17e013cc3c088aa87efb13474955..a2f7843baaa680b2c1b52cf679646d470102f0ae 100644 (file)
@@ -12,7 +12,7 @@
 };
 
 mod config;
-pub use self::config::{QueryAccessors, QueryConfig, QueryDescription};
+pub use self::config::{QueryConfig, QueryDescription, QueryVtable};
 
 use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex};
 
index 5506666b6a1bfb6761e4898b56261129343482a8..9703f0c3d9605269089498686272447cc188bb9e 100644 (file)
@@ -4,7 +4,7 @@
 
 use crate::dep_graph::{DepContext, DepNode, DepNodeIndex, DepNodeParams};
 use crate::query::caches::QueryCache;
-use crate::query::config::{QueryDescription, QueryVtable, QueryVtableExt};
+use crate::query::config::{QueryDescription, QueryVtable};
 use crate::query::job::{
     report_cycle, QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryShardJobId,
 };
@@ -512,15 +512,28 @@ fn try_load_from_disk_and_cache_in_memory<CTX, K, V>(
 
     // First we try to load the result from the on-disk cache.
     // Some things are never cached on disk.
-    if query.cache_on_disk(tcx, key) {
+    if query.cache_on_disk {
         let prof_timer = tcx.dep_context().profiler().incr_cache_loading();
         let result = query.try_load_from_disk(tcx, prev_dep_node_index);
         prof_timer.finish_with_query_invocation_id(dep_node_index.into());
 
         if let Some(result) = result {
+            let prev_fingerprint = tcx
+                .dep_context()
+                .dep_graph()
+                .prev_fingerprint_of(dep_node)
+                .unwrap_or(Fingerprint::ZERO);
             // If `-Zincremental-verify-ich` is specified, re-hash results from
             // the cache and make sure that they have the expected fingerprint.
-            if unlikely!(tcx.dep_context().sess().opts.debugging_opts.incremental_verify_ich) {
+            //
+            // If not, we still seek to verify a subset of fingerprints loaded
+            // from disk. Re-hashing results is fairly expensive, so we can't
+            // currently afford to verify every hash. This subset should still
+            // give us some coverage of potential bugs though.
+            let try_verify = prev_fingerprint.as_value().1 % 32 == 0;
+            if unlikely!(
+                try_verify || tcx.dep_context().sess().opts.debugging_opts.incremental_verify_ich
+            ) {
                 incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query);
             }
 
@@ -713,8 +726,6 @@ pub fn force_query<Q, CTX>(tcx: CTX, key: Q::Key, dep_node: DepNode<CTX::DepKind
     Q::Key: DepNodeParams<CTX::DepContext>,
     CTX: QueryContext,
 {
-    assert!(!Q::ANON);
-
     // We may be concurrently trying both execute and force a query.
     // Ensure that only one of them runs the query.
     let cache = Q::query_cache(tcx);
@@ -731,5 +742,7 @@ pub fn force_query<Q, CTX>(tcx: CTX, key: Q::Key, dep_node: DepNode<CTX::DepKind
 
     let query = Q::make_vtable(tcx, &key);
     let state = Q::query_state(tcx);
+    debug_assert!(!query.anon);
+
     try_execute_query(tcx, state, cache, DUMMY_SP, key, lookup, Some(dep_node), &query);
 }
index 2a562a06cb3cdc001544b01959bca02811a4c7b5..4173e0fbf5668e546a878ece896cfb026c8b491f 100644 (file)
@@ -15,7 +15,7 @@
 
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
 use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind};
-use rustc_ast::{Block, FnKind, ForeignItem, ForeignItemKind, ImplKind, Item, ItemKind, NodeId};
+use rustc_ast::{Block, Fn, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId};
 use rustc_ast_lowering::ResolverAstLowering;
 use rustc_attr as attr;
 use rustc_data_structures::sync::Lrc;
@@ -145,17 +145,11 @@ pub fn expect_module(&mut self, def_id: DefId) -> Module<'a> {
                     } else {
                         def_key.disambiguated_data.data.get_opt_name().expect("module without name")
                     };
-                    let expn_id = if def_kind == DefKind::Mod {
-                        self.cstore().module_expansion_untracked(def_id, &self.session)
-                    } else {
-                        // FIXME: Parent expansions for enums and traits are not kept in metadata.
-                        ExpnId::root()
-                    };
 
                     Some(self.new_module(
                         parent,
                         ModuleKind::Def(def_kind, def_id, name),
-                        expn_id,
+                        self.cstore().module_expansion_untracked(def_id, &self.session),
                         self.cstore().get_span_untracked(def_id, &self.session),
                         // FIXME: Account for `#[no_implicit_prelude]` attributes.
                         parent.map_or(false, |module| module.no_implicit_prelude),
@@ -886,7 +880,7 @@ fn build_reduced_graph_for_item(&mut self, item: &'b Item) {
             }
 
             // These items do not add names to modules.
-            ItemKind::Impl(box ImplKind { of_trait: Some(..), .. }) => {
+            ItemKind::Impl(box Impl { of_trait: Some(..), .. }) => {
                 self.r.trait_impl_items.insert(local_def_id);
             }
             ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {}
@@ -973,6 +967,7 @@ fn build_reduced_graph_for_external_crate_res(&mut self, child: Export) {
                 | DefKind::Use
                 | DefKind::ForeignMod
                 | DefKind::AnonConst
+                | DefKind::InlineConst
                 | DefKind::Field
                 | DefKind::LifetimeParam
                 | DefKind::GlobalAsm
@@ -1386,7 +1381,7 @@ fn visit_assoc_item(&mut self, item: &'b AssocItem, ctxt: AssocCtxt) {
         if ctxt == AssocCtxt::Trait {
             let (def_kind, ns) = match item.kind {
                 AssocItemKind::Const(..) => (DefKind::AssocConst, ValueNS),
-                AssocItemKind::Fn(box FnKind(_, ref sig, _, _)) => {
+                AssocItemKind::Fn(box Fn { ref sig, .. }) => {
                     if sig.decl.has_self() {
                         self.r.has_self.insert(def_id);
                     }
index 63000a9d13d412eb2920c7d894dbb1c2008b450a..ff0d76e94fdf5c231a8b8f193e034c4a0d4201f1 100644 (file)
@@ -66,6 +66,8 @@ impl TypoSuggestion {
     pub descr: &'static str,
     pub path: Path,
     pub accessible: bool,
+    /// An extra note that should be issued if this item is suggested
+    pub note: Option<String>,
 }
 
 /// Adjust the impl span so that just the `impl` keyword is taken by removing
@@ -418,6 +420,10 @@ impl<'a> Resolver<'a> {
                 err.span_label(span, label);
 
                 if let Some((suggestions, msg, applicability)) = suggestion {
+                    if suggestions.is_empty() {
+                        err.help(&msg);
+                        return err;
+                    }
                     err.multipart_suggestion(&msg, suggestions, applicability);
                 }
 
@@ -829,11 +835,22 @@ fn lookup_import_candidates_from_module<FilterFn>(
                     return;
                 }
 
+                // #90113: Do not count an inaccessible reexported item as a candidate.
+                if let NameBindingKind::Import { binding, .. } = name_binding.kind {
+                    if this.is_accessible_from(binding.vis, parent_scope.module)
+                        && !this.is_accessible_from(name_binding.vis, parent_scope.module)
+                    {
+                        return;
+                    }
+                }
+
                 // collect results based on the filter function
                 // avoid suggesting anything from the same module in which we are resolving
+                // avoid suggesting anything with a hygienic name
                 if ident.name == lookup_ident.name
                     && ns == namespace
                     && !ptr::eq(in_module, parent_scope.module)
+                    && !ident.span.normalize_to_macros_2_0().from_expansion()
                 {
                     let res = name_binding.res();
                     if filter_fn(res) {
@@ -863,11 +880,38 @@ fn lookup_import_candidates_from_module<FilterFn>(
                         }
 
                         if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
+                            // See if we're recommending TryFrom, TryInto, or FromIterator and add
+                            // a note about editions
+                            let note = if let Some(did) = did {
+                                let requires_note = !did.is_local()
+                                    && this.cstore().item_attrs(did, this.session).iter().any(
+                                        |attr| {
+                                            if attr.has_name(sym::rustc_diagnostic_item) {
+                                                [sym::TryInto, sym::TryFrom, sym::FromIterator]
+                                                    .map(|x| Some(x))
+                                                    .contains(&attr.value_str())
+                                            } else {
+                                                false
+                                            }
+                                        },
+                                    );
+
+                                requires_note.then(|| {
+                                    format!(
+                                        "'{}' is included in the prelude starting in Edition 2021",
+                                        path_names_to_string(&path)
+                                    )
+                                })
+                            } else {
+                                None
+                            };
+
                             candidates.push(ImportSuggestion {
                                 did,
                                 descr: res.descr(),
                                 path,
                                 accessible: child_accessible,
+                                note,
                             });
                         }
                     }
@@ -1156,14 +1200,9 @@ fn binding_description(&self, b: &NameBinding<'_>, ident: Ident, from_prelude: b
             (b1, b2, misc1, misc2, false)
         };
 
-        let mut err = struct_span_err!(
-            self.session,
-            ident.span,
-            E0659,
-            "`{ident}` is ambiguous ({why})",
-            why = kind.descr()
-        );
+        let mut err = struct_span_err!(self.session, ident.span, E0659, "`{ident}` is ambiguous");
         err.span_label(ident.span, "ambiguous name");
+        err.note(&format!("ambiguous because of {}", kind.descr()));
 
         let mut could_refer_to = |b: &NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| {
             let what = self.binding_description(b, ident, misc == AmbiguityErrorMisc::FromPrelude);
@@ -1760,12 +1799,14 @@ fn find_span_immediately_after_crate_name(
         return;
     }
 
-    let mut accessible_path_strings: Vec<(String, &str, Option<DefId>)> = Vec::new();
-    let mut inaccessible_path_strings: Vec<(String, &str, Option<DefId>)> = Vec::new();
+    let mut accessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>)> =
+        Vec::new();
+    let mut inaccessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>)> =
+        Vec::new();
 
     candidates.iter().for_each(|c| {
         (if c.accessible { &mut accessible_path_strings } else { &mut inaccessible_path_strings })
-            .push((path_names_to_string(&c.path), c.descr, c.did))
+            .push((path_names_to_string(&c.path), c.descr, c.did, &c.note))
     });
 
     // we want consistent results across executions, but candidates are produced
@@ -1788,6 +1829,10 @@ fn find_span_immediately_after_crate_name(
         let instead = if instead { " instead" } else { "" };
         let mut msg = format!("consider importing {} {}{}", determiner, kind, instead);
 
+        for note in accessible_path_strings.iter().map(|cand| cand.3.as_ref()).flatten() {
+            err.note(note);
+        }
+
         if let Some(span) = use_placement_span {
             for candidate in &mut accessible_path_strings {
                 // produce an additional newline to separate the new use statement
@@ -1816,7 +1861,7 @@ fn find_span_immediately_after_crate_name(
         assert!(!inaccessible_path_strings.is_empty());
 
         if inaccessible_path_strings.len() == 1 {
-            let (name, descr, def_id) = &inaccessible_path_strings[0];
+            let (name, descr, def_id, note) = &inaccessible_path_strings[0];
             let msg = format!("{} `{}` exists but is inaccessible", descr, name);
 
             if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) {
@@ -1828,12 +1873,15 @@ fn find_span_immediately_after_crate_name(
             } else {
                 err.note(&msg);
             }
+            if let Some(note) = (*note).as_deref() {
+                err.note(note);
+            }
         } else {
-            let (_, descr_first, _) = &inaccessible_path_strings[0];
+            let (_, descr_first, _, _) = &inaccessible_path_strings[0];
             let descr = if inaccessible_path_strings
                 .iter()
                 .skip(1)
-                .all(|(_, descr, _)| descr == descr_first)
+                .all(|(_, descr, _, _)| descr == descr_first)
             {
                 descr_first.to_string()
             } else {
@@ -1844,7 +1892,7 @@ fn find_span_immediately_after_crate_name(
             let mut has_colon = false;
 
             let mut spans = Vec::new();
-            for (name, _, def_id) in &inaccessible_path_strings {
+            for (name, _, def_id, _) in &inaccessible_path_strings {
                 if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) {
                     let span = definitions.def_span(local_def_id);
                     let span = session.source_map().guess_head_span(span);
@@ -1864,6 +1912,10 @@ fn find_span_immediately_after_crate_name(
                 multi_span.push_span_label(span, format!("`{}`: not accessible", name));
             }
 
+            for note in inaccessible_path_strings.iter().map(|cand| cand.3.as_ref()).flatten() {
+                err.note(note);
+            }
+
             err.span_note(multi_span, &msg);
         }
     }
index 0a24e00ee4bf5137b88eadef81b20a09266b4ebb..e67f7f03516803c0a7cb7ca7acfb57b9f05f4846 100644 (file)
@@ -498,8 +498,8 @@ fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef, m: &'ast TraitBound
     }
     fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
         match foreign_item.kind {
-            ForeignItemKind::Fn(box FnKind(_, _, ref generics, _))
-            | ForeignItemKind::TyAlias(box TyAliasKind(_, ref generics, ..)) => {
+            ForeignItemKind::Fn(box Fn { ref generics, .. })
+            | ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
                 self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
                     visit::walk_foreign_item(this, foreign_item);
                 });
@@ -953,8 +953,8 @@ fn resolve_item(&mut self, item: &'ast Item) {
         debug!("(resolving item) resolving {} ({:?})", name, item.kind);
 
         match item.kind {
-            ItemKind::TyAlias(box TyAliasKind(_, ref generics, _, _))
-            | ItemKind::Fn(box FnKind(_, _, ref generics, _)) => {
+            ItemKind::TyAlias(box TyAlias { ref generics, .. })
+            | ItemKind::Fn(box Fn { ref generics, .. }) => {
                 self.compute_num_lifetime_params(item.id, generics);
                 self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
                     visit::walk_item(this, item)
@@ -968,7 +968,7 @@ fn resolve_item(&mut self, item: &'ast Item) {
                 self.resolve_adt(item, generics);
             }
 
-            ItemKind::Impl(box ImplKind {
+            ItemKind::Impl(box Impl {
                 ref generics,
                 ref of_trait,
                 ref self_ty,
@@ -979,7 +979,7 @@ fn resolve_item(&mut self, item: &'ast Item) {
                 self.resolve_implementation(generics, of_trait, &self_ty, item.id, impl_items);
             }
 
-            ItemKind::Trait(box TraitKind(.., ref generics, ref bounds, ref trait_items)) => {
+            ItemKind::Trait(box Trait { ref generics, ref bounds, ref items, .. }) => {
                 self.compute_num_lifetime_params(item.id, generics);
                 // Create a new rib for the trait-wide type parameters.
                 self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
@@ -994,8 +994,8 @@ fn resolve_item(&mut self, item: &'ast Item) {
                             });
                         };
 
-                        this.with_trait_items(trait_items, |this| {
-                            for item in trait_items {
+                        this.with_trait_items(items, |this| {
+                            for item in items {
                                 match &item.kind {
                                     AssocItemKind::Const(_, ty, default) => {
                                         this.visit_ty(ty);
@@ -1015,10 +1015,10 @@ fn resolve_item(&mut self, item: &'ast Item) {
                                             );
                                         }
                                     }
-                                    AssocItemKind::Fn(box FnKind(_, _, generics, _)) => {
+                                    AssocItemKind::Fn(box Fn { generics, .. }) => {
                                         walk_assoc_item(this, generics, item);
                                     }
-                                    AssocItemKind::TyAlias(box TyAliasKind(_, generics, _, _)) => {
+                                    AssocItemKind::TyAlias(box TyAlias { generics, .. }) => {
                                         walk_assoc_item(this, generics, item);
                                     }
                                     AssocItemKind::MacCall(_) => {
@@ -1338,7 +1338,7 @@ fn resolve_implementation(
                                                 },
                                             );
                                         }
-                                        AssocItemKind::Fn(box FnKind(.., generics, _)) => {
+                                        AssocItemKind::Fn(box Fn { generics, .. }) => {
                                             debug!("resolve_implementation AssocItemKind::Fn");
                                             // We also need a new scope for the impl item type parameters.
                                             this.with_generic_param_rib(
@@ -1363,12 +1363,9 @@ fn resolve_implementation(
                                                 },
                                             );
                                         }
-                                        AssocItemKind::TyAlias(box TyAliasKind(
-                                            _,
-                                            generics,
-                                            _,
-                                            _,
-                                        )) => {
+                                        AssocItemKind::TyAlias(box TyAlias {
+                                            generics, ..
+                                        }) => {
                                             debug!("resolve_implementation AssocItemKind::TyAlias");
                                             // We also need a new scope for the impl item type parameters.
                                             this.with_generic_param_rib(
index 1748a9be8e13e80cd0194e76ceafc14e2cb405b5..4acbb11b13f76295a290e49519088776416e605b 100644 (file)
@@ -333,7 +333,7 @@ pub(crate) fn smart_resolve_report_errors(
         let candidates = self
             .r
             .lookup_import_candidates(ident, ns, &self.parent_scope, is_expected)
-            .drain(..)
+            .into_iter()
             .filter(|ImportSuggestion { did, .. }| {
                 match (did, res.and_then(|res| res.opt_def_id())) {
                     (Some(suggestion_did), Some(actual_did)) => *suggestion_did != actual_did,
@@ -1235,9 +1235,7 @@ fn extract_node_id(t: &Ty) -> Option<NodeId> {
                 if assoc_item.ident == ident {
                     return Some(match &assoc_item.kind {
                         ast::AssocItemKind::Const(..) => AssocSuggestion::AssocConst,
-                        ast::AssocItemKind::Fn(box ast::FnKind(_, sig, ..))
-                            if sig.decl.has_self() =>
-                        {
+                        ast::AssocItemKind::Fn(box ast::Fn { sig, .. }) if sig.decl.has_self() => {
                             AssocSuggestion::MethodWithSelf
                         }
                         ast::AssocItemKind::Fn(..) => AssocSuggestion::AssocFn,
@@ -1346,12 +1344,10 @@ fn lookup_typo_candidate(
         } else {
             // Search in module.
             let mod_path = &path[..path.len() - 1];
-            if let PathResult::Module(module) =
+            if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
                 self.resolve_path(mod_path, Some(TypeNS), false, span, CrateLint::No)
             {
-                if let ModuleOrUniformRoot::Module(module) = module {
-                    self.r.add_module_candidates(module, &mut names, &filter_fn);
-                }
+                self.r.add_module_candidates(module, &mut names, &filter_fn);
             }
         }
 
@@ -1502,6 +1498,7 @@ fn find_module(&mut self, def_id: DefId) -> Option<(Module<'a>, ImportSuggestion
                                 descr: "module",
                                 path,
                                 accessible: true,
+                                note: None,
                             },
                         ));
                     } else {
@@ -1553,7 +1550,7 @@ fn suggest_using_enum_variant(
         if suggest_only_tuple_variants {
             // Suggest only tuple variants regardless of whether they have fields and do not
             // suggest path with added parentheses.
-            let mut suggestable_variants = variants
+            let suggestable_variants = variants
                 .iter()
                 .filter(|(.., kind)| *kind == CtorKind::Fn)
                 .map(|(variant, ..)| path_names_to_string(variant))
@@ -1579,7 +1576,7 @@ fn suggest_using_enum_variant(
                 err.span_suggestions(
                     span,
                     &msg,
-                    suggestable_variants.drain(..),
+                    suggestable_variants.into_iter(),
                     Applicability::MaybeIncorrect,
                 );
             }
@@ -1637,7 +1634,7 @@ fn suggest_using_enum_variant(
                 );
             }
 
-            let mut suggestable_variants_with_placeholders = variants
+            let suggestable_variants_with_placeholders = variants
                 .iter()
                 .filter(|(_, def_id, kind)| needs_placeholder(*def_id, *kind))
                 .map(|(variant, _, kind)| (path_names_to_string(variant), kind))
@@ -1662,7 +1659,7 @@ fn suggest_using_enum_variant(
                 err.span_suggestions(
                     span,
                     msg,
-                    suggestable_variants_with_placeholders.drain(..),
+                    suggestable_variants_with_placeholders.into_iter(),
                     Applicability::HasPlaceholders,
                 );
             }
index 94563400a8b53580578424ca2251b4169e3c4391..39e710cb77f3fafd9129d6ad80061aea48ef3837 100644 (file)
@@ -540,7 +540,7 @@ fn is_late_bound_map<'tcx>(
     def_id: LocalDefId,
 ) -> Option<(LocalDefId, &'tcx FxHashSet<ItemLocalId>)> {
     match tcx.def_kind(def_id) {
-        DefKind::AnonConst => {
+        DefKind::AnonConst | DefKind::InlineConst => {
             let mut def_id = tcx
                 .parent(def_id.to_def_id())
                 .unwrap_or_else(|| bug!("anon const or closure without a parent"));
@@ -887,10 +887,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
                 let (lifetimes, binders): (FxIndexMap<hir::ParamName, Region>, Vec<_>) = c
                     .generic_params
                     .iter()
-                    .filter_map(|param| match param.kind {
-                        GenericParamKind::Lifetime { .. } => Some(param),
-                        _ => None,
-                    })
+                    .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
                     .enumerate()
                     .map(|(late_bound_idx, param)| {
                         let pair = Region::late(late_bound_idx as u32, &self.tcx.hir(), param);
@@ -1370,9 +1367,8 @@ fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
                         let (lifetimes, binders): (FxIndexMap<hir::ParamName, Region>, Vec<_>) =
                             bound_generic_params
                                 .iter()
-                                .filter_map(|param| match param.kind {
-                                    GenericParamKind::Lifetime { .. } => Some(param),
-                                    _ => None,
+                                .filter(|param| {
+                                    matches!(param.kind, GenericParamKind::Lifetime { .. })
                                 })
                                 .enumerate()
                                 .map(|(late_bound_idx, param)| {
@@ -1469,10 +1465,7 @@ fn visit_poly_trait_ref(
         let binders_iter = trait_ref
             .bound_generic_params
             .iter()
-            .filter_map(|param| match param.kind {
-                GenericParamKind::Lifetime { .. } => Some(param),
-                _ => None,
-            })
+            .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
             .enumerate()
             .map(|(late_bound_idx, param)| {
                 let pair = Region::late(
@@ -1931,20 +1924,18 @@ fn suggest_eliding_single_use_lifetime(
                             break;
                         }
                     }
-                    hir::TyKind::Path(ref qpath) => {
-                        if let QPath::Resolved(_, path) = qpath {
-                            let last_segment = &path.segments[path.segments.len() - 1];
-                            let generics = last_segment.args();
-                            for arg in generics.args.iter() {
-                                if let GenericArg::Lifetime(lt) = arg {
-                                    if lt.name.ident() == name {
-                                        elide_use = Some(lt.span);
-                                        break;
-                                    }
+                    hir::TyKind::Path(QPath::Resolved(_, path)) => {
+                        let last_segment = &path.segments[path.segments.len() - 1];
+                        let generics = last_segment.args();
+                        for arg in generics.args.iter() {
+                            if let GenericArg::Lifetime(lt) = arg {
+                                if lt.name.ident() == name {
+                                    elide_use = Some(lt.span);
+                                    break;
                                 }
                             }
-                            break;
                         }
+                        break;
                     }
                     _ => {}
                 }
@@ -2237,19 +2228,14 @@ fn visit_early_late<F>(
         let binders: Vec<_> = generics
             .params
             .iter()
-            .filter_map(|param| match param.kind {
-                GenericParamKind::Lifetime { .. }
-                    if self.map.late_bound.contains(&param.hir_id) =>
-                {
-                    Some(param)
-                }
-                _ => None,
+            .filter(|param| {
+                matches!(param.kind, GenericParamKind::Lifetime { .. })
+                    && self.map.late_bound.contains(&param.hir_id)
             })
             .enumerate()
             .map(|(late_bound_idx, param)| {
                 let pair = Region::late(late_bound_idx as u32, &self.tcx.hir(), param);
-                let r = late_region_as_bound_region(self.tcx, &pair.1);
-                r
+                late_region_as_bound_region(self.tcx, &pair.1)
             })
             .collect();
         self.map.late_bound_vars.insert(hir_id, binders);
index af062af532927da61e4b6b019427f8d0fdec26c2..5f3620b247e26e1885a7361d282316268b84b1fb 100644 (file)
@@ -20,7 +20,6 @@
 #![feature(nll)]
 #![recursion_limit = "256"]
 #![allow(rustdoc::private_intra_doc_links)]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate tracing;
@@ -728,23 +727,21 @@ enum AmbiguityKind {
 impl AmbiguityKind {
     fn descr(self) -> &'static str {
         match self {
-            AmbiguityKind::Import => "name vs any other name during import resolution",
-            AmbiguityKind::BuiltinAttr => "built-in attribute vs any other name",
-            AmbiguityKind::DeriveHelper => "derive helper attribute vs any other name",
+            AmbiguityKind::Import => "multiple potential import sources",
+            AmbiguityKind::BuiltinAttr => "a name conflict with a builtin attribute",
+            AmbiguityKind::DeriveHelper => "a name conflict with a derive helper attribute",
             AmbiguityKind::MacroRulesVsModularized => {
-                "`macro_rules` vs non-`macro_rules` from other module"
+                "a conflict between a `macro_rules` name and a non-`macro_rules` name from another module"
             }
             AmbiguityKind::GlobVsOuter => {
-                "glob import vs any other name from outer scope during import/macro resolution"
+                "a conflict between a name from a glob import and an outer scope during import or macro resolution"
             }
-            AmbiguityKind::GlobVsGlob => "glob import vs glob import in the same module",
+            AmbiguityKind::GlobVsGlob => "multiple glob imports of a name in the same module",
             AmbiguityKind::GlobVsExpanded => {
-                "glob import vs macro-expanded name in the same \
-                 module during import/macro resolution"
+                "a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution"
             }
             AmbiguityKind::MoreExpandedVsOuter => {
-                "macro-expanded name vs less macro-expanded name \
-                 from outer scope during import/macro resolution"
+                "a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution"
             }
         }
     }
@@ -2526,19 +2523,29 @@ enum FindBindingResult<'a> {
                         } else {
                             (
                                 format!("use of undeclared crate or module `{}`", ident),
-                                self.find_similarly_named_module_or_crate(
-                                    ident.name,
-                                    &parent_scope.module,
-                                )
-                                .map(|sugg| {
-                                    (
-                                        vec![(ident.span, sugg.to_string())],
+                                if ident.name == sym::alloc {
+                                    Some((
+                                        vec![],
                                         String::from(
-                                            "there is a crate or module with a similar name",
+                                            "add `extern crate alloc` to use the `alloc` crate",
                                         ),
                                         Applicability::MaybeIncorrect,
+                                    ))
+                                } else {
+                                    self.find_similarly_named_module_or_crate(
+                                        ident.name,
+                                        &parent_scope.module,
                                     )
-                                }),
+                                    .map(|sugg| {
+                                        (
+                                            vec![(ident.span, sugg.to_string())],
+                                            String::from(
+                                                "there is a crate or module with a similar name",
+                                            ),
+                                            Applicability::MaybeIncorrect,
+                                        )
+                                    })
+                                },
                             )
                         }
                     } else {
index f4567b334836ae476984386399dafba9f1d10a48..f1a5282b08871323aa2b0a18be0103481ae1fffd 100644 (file)
@@ -236,7 +236,7 @@ fn process_formals(&mut self, formals: &'tcx [hir::Param<'tcx>], qualname: &str)
                             id,
                             span,
                             name: ident.to_string(),
-                            qualname: format!("{}::{}", qualname, ident.to_string()),
+                            qualname: format!("{}::{}", qualname, ident),
                             value: typ,
                             parent: None,
                             children: vec![],
@@ -889,7 +889,7 @@ fn process_var_decl(&mut self, pat: &'tcx hir::Pat<'tcx>) {
 
                     // Rust uses the id of the pattern for var lookups, so we'll use it too.
                     if !self.span.filter_generated(ident.span) {
-                        let qualname = format!("{}${}", ident.to_string(), hir_id);
+                        let qualname = format!("{}${}", ident, hir_id);
                         let id = id_from_hir_id(hir_id, &self.save_ctxt);
                         let span = self.span_from_span(ident.span);
 
index 8fd2011ac46e08fa2dcef9d9aa493d86a363dfc9..c7f8fe3a88a64b1dc4ea99a8456f852f54083995 100644 (file)
@@ -2,7 +2,6 @@
 #![feature(if_let_guard)]
 #![feature(nll)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 mod dump_visitor;
 mod dumper;
@@ -740,6 +739,7 @@ fn fn_type(seg: &hir::PathSegment<'_>) -> bool {
                 | HirDefKind::ForeignMod
                 | HirDefKind::LifetimeParam
                 | HirDefKind::AnonConst
+                | HirDefKind::InlineConst
                 | HirDefKind::Use
                 | HirDefKind::Field
                 | HirDefKind::GlobalAsm
index 299dfed9d5dcea7845f2898b3cb612e1ddc96d80..8a9e8739d037cef48304a5cbd443cbd38918b37f 100644 (file)
@@ -914,7 +914,7 @@ pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateCo
 pub(super) fn build_target_config(
     opts: &Options,
     target_override: Option<Target>,
-    sysroot: &PathBuf,
+    sysroot: &Path,
 ) -> Target {
     let target_result = target_override.map_or_else(
         || Target::search(&opts.target_triple, sysroot),
index 1a6cab7ecde81f379304d7caa1931b6376757340..6c86f86ecd9bb210a4d71b1d7eca891bd44a52ec 100644 (file)
@@ -2,7 +2,6 @@
 #![feature(min_specialization)]
 #![feature(once_cell)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate rustc_macros;
index 782055b9a77da2a68c5a90a24497dd06d3d7ddf5..71464ad97145bafe9e4266ee91ec8284be129c24 100644 (file)
@@ -351,8 +351,7 @@ mod desc {
     pub const parse_panic_strategy: &str = "either `unwind` or `abort`";
     pub const parse_opt_panic_strategy: &str = parse_panic_strategy;
     pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
-    pub const parse_sanitizers: &str =
-        "comma separated list of sanitizers: `address`, `hwaddress`, `leak`, `memory` or `thread`";
+    pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `leak`, `memory` or `thread`";
     pub const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2";
     pub const parse_cfguard: &str =
         "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`";
@@ -605,6 +604,7 @@ mod parse {
             for s in v.split(',') {
                 *slot |= match s {
                     "address" => SanitizerSet::ADDRESS,
+                    "cfi" => SanitizerSet::CFI,
                     "leak" => SanitizerSet::LEAK,
                     "memory" => SanitizerSet::MEMORY,
                     "thread" => SanitizerSet::THREAD,
@@ -881,7 +881,7 @@ mod parse {
         match v {
             Some(s) => {
                 if !slot.is_empty() {
-                    slot.push_str(",");
+                    slot.push(',');
                 }
                 slot.push_str(s);
                 true
@@ -1193,7 +1193,7 @@ mod parse {
     move_size_limit: Option<usize> = (None, parse_opt_number, [TRACKED],
         "the size at which the `large_assignments` lint starts to be emitted"),
     mutable_noalias: Option<bool> = (None, parse_opt_bool, [TRACKED],
-        "emit noalias metadata for mutable references (default: yes for LLVM >= 12, otherwise no)"),
+        "emit noalias metadata for mutable references (default: yes)"),
     new_llvm_pass_manager: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "use new LLVM pass manager (default: no)"),
     nll_facts: bool = (false, parse_bool, [UNTRACKED],
@@ -1214,6 +1214,8 @@ mod parse {
         "compile without linking"),
     no_parallel_llvm: bool = (false, parse_no_flag, [UNTRACKED],
         "run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)"),
+    no_unique_section_names: bool = (false, parse_bool, [TRACKED],
+        "do not use unique names for text and data sections when -Z function-sections is used"),
     no_profiler_runtime: bool = (false, parse_no_flag, [TRACKED],
         "prevent automatic injection of the profiler_builtins crate"),
     normalize_docs: bool = (false, parse_bool, [TRACKED],
index b6ba6cc1dd659861202d40b14ff8c75dd8fea001..74b3cfa44c31aaa0e8847ddd5705daa841566e62 100644 (file)
@@ -411,7 +411,7 @@ pub fn abort_if_errors(&self) {
         self.diagnostic().abort_if_errors();
     }
     pub fn compile_status(&self) -> Result<(), ErrorReported> {
-        if self.has_errors() {
+        if self.diagnostic().has_errors_or_lint_errors() {
             self.diagnostic().emit_stashed_diagnostics();
             Err(ErrorReported)
         } else {
@@ -672,6 +672,9 @@ pub fn unstable_options(&self) -> bool {
     pub fn is_nightly_build(&self) -> bool {
         self.opts.unstable_features.is_nightly_build()
     }
+    pub fn is_sanitizer_cfi_enabled(&self) -> bool {
+        self.opts.debugging_opts.sanitizer.contains(SanitizerSet::CFI)
+    }
     pub fn overflow_checks(&self) -> bool {
         self.opts
             .cg
@@ -1398,6 +1401,16 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
                                 disable it using `-C target-feature=-crt-static`",
         );
     }
+
+    // LLVM CFI requires LTO.
+    if sess.is_sanitizer_cfi_enabled() {
+        if sess.opts.cg.lto == config::LtoCli::Unspecified
+            || sess.opts.cg.lto == config::LtoCli::No
+            || sess.opts.cg.lto == config::LtoCli::Thin
+        {
+            sess.err("`-Zsanitizer=cfi` requires `-Clto`");
+        }
+    }
 }
 
 /// Holds data on the current incremental compilation session, if there is one.
index aa15febe8853d709855a1ffc919dc18c67f4e5c9..724d1904dc33c7125d7231f2190abc64d7d4f7c9 100644 (file)
@@ -709,7 +709,7 @@ pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<
     ///         pub fn f() {} // `f`'s `SyntaxContext` has a single `ExpnId` from `m`.
     ///         pub fn $i() {} // `$i`'s `SyntaxContext` is empty.
     ///     }
-    ///     n(f);
+    ///     n!(f);
     ///     macro n($j:ident) {
     ///         use foo::*;
     ///         f(); // `f`'s `SyntaxContext` has a mark from `m` and a mark from `n`
index 4eafa7cebb3270534bc1aa952c77dc14c715b074..dfc64f37e4c46b84c7e1ee9a02ee1282a6feba67 100644 (file)
@@ -21,7 +21,6 @@
 #![feature(nll)]
 #![feature(min_specialization)]
 #![feature(thread_local_const_init)]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate rustc_macros;
@@ -195,10 +194,8 @@ fn encode(&self, encoder: &mut S) -> Result<(), S::Error> {
         encoder.emit_enum(|encoder| match *self {
             RealFileName::LocalPath(ref local_path) => {
                 encoder.emit_enum_variant("LocalPath", 0, 1, |encoder| {
-                    Ok({
-                        encoder
-                            .emit_enum_variant_arg(true, |encoder| local_path.encode(encoder))?;
-                    })
+                    encoder.emit_enum_variant_arg(true, |encoder| local_path.encode(encoder))?;
+                    Ok(())
                 })
             }
 
@@ -207,12 +204,9 @@ fn encode(&self, encoder: &mut S) -> Result<(), S::Error> {
                     // For privacy and build reproducibility, we must not embed host-dependant path in artifacts
                     // if they have been remapped by --remap-path-prefix
                     assert!(local_path.is_none());
-                    Ok({
-                        encoder
-                            .emit_enum_variant_arg(true, |encoder| local_path.encode(encoder))?;
-                        encoder
-                            .emit_enum_variant_arg(false, |encoder| virtual_name.encode(encoder))?;
-                    })
+                    encoder.emit_enum_variant_arg(true, |encoder| local_path.encode(encoder))?;
+                    encoder.emit_enum_variant_arg(false, |encoder| virtual_name.encode(encoder))?;
+                    Ok(())
                 }),
         })
     }
index 5bdc9cd616e0db3d1bfbb28142adb06f1b4839f6..99fa9f000944df2b6e66f6227ac44f85105641dd 100644 (file)
         __S,
         __next,
         __try_var,
+        _args,
         _d,
         _e,
         _task_context,
         as_ptr,
         as_str,
         asm,
+        asm_const,
+        asm_experimental_arch,
+        asm_sym,
         assert,
         assert_inhabited,
         assert_macro,
         cfg_target_thread_local,
         cfg_target_vendor,
         cfg_version,
+        cfi,
         char,
         client,
         clippy,
         div_assign,
         doc,
         doc_alias,
+        doc_auto_cfg,
         doc_cfg,
         doc_cfg_hide,
         doc_keyword,
         rustc_layout_scalar_valid_range_end,
         rustc_layout_scalar_valid_range_start,
         rustc_legacy_const_generics,
-        rustc_lint_query_instability,
         rustc_macro_transparency,
         rustc_main,
         rustc_mir,
         rustc_partition_reused,
         rustc_peek,
         rustc_peek_definite_init,
-        rustc_peek_indirectly_mutable,
         rustc_peek_liveness,
         rustc_peek_maybe_init,
         rustc_peek_maybe_uninit,
index f6517610da26271a1237031860e2c61965de1d53..bb7b4529556091923e6c947750e1fa1a0c6fa8df 100644 (file)
@@ -93,7 +93,6 @@
 #![feature(in_band_lifetimes)]
 #![feature(iter_zip)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate rustc_middle;
 use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, Instance, TyCtxt};
+use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_session::config::SymbolManglingVersion;
+use rustc_target::abi::call::FnAbi;
 
 use tracing::debug;
 
@@ -151,6 +151,11 @@ fn symbol_name_provider(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> ty::Symb
     ty::SymbolName::new(tcx, &symbol_name)
 }
 
+/// This function computes the typeid for the given function ABI.
+pub fn typeid_for_fnabi(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> String {
+    v0::mangle_typeid_for_fnabi(tcx, fn_abi)
+}
+
 /// Computes the symbol name for the given instance. This function will call
 /// `compute_instantiating_crate` if it needs to factor the instantiating crate
 /// into the symbol name.
index 521730dfeb01cc22266da68404b104321abf2c39..0363ddb0e6eee17b2e9d79ce3ad334a20459a6bf 100644 (file)
@@ -9,6 +9,7 @@
 use rustc_middle::ty::print::{Print, Printer};
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
 use rustc_middle::ty::{self, FloatTy, Instance, IntTy, Ty, TyCtxt, TypeFoldable, UintTy};
+use rustc_target::abi::call::FnAbi;
 use rustc_target::abi::Integer;
 use rustc_target::spec::abi::Abi;
 
@@ -55,6 +56,41 @@ pub(super) fn mangle(
     std::mem::take(&mut cx.out)
 }
 
+pub(super) fn mangle_typeid_for_fnabi(
+    _tcx: TyCtxt<'tcx>,
+    fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
+) -> String {
+    // LLVM uses type metadata to allow IR modules to aggregate pointers by their types.[1] This
+    // type metadata is used by LLVM Control Flow Integrity to test whether a given pointer is
+    // associated with a type identifier (i.e., test type membership).
+    //
+    // Clang uses the Itanium C++ ABI's[2] virtual tables and RTTI typeinfo structure name[3] as
+    // type metadata identifiers for function pointers. The typeinfo name encoding is a
+    // two-character code (i.e., “TS”) prefixed to the type encoding for the function.
+    //
+    // For cross-language LLVM CFI support, a compatible encoding must be used by either
+    //
+    //  a. Using a superset of types that encompasses types used by Clang (i.e., Itanium C++ ABI's
+    //     type encodings[4]), or at least types used at the FFI boundary.
+    //  b. Reducing the types to the least common denominator between types used by Clang (or at
+    //     least types used at the FFI boundary) and Rust compilers (if even possible).
+    //  c. Creating a new ABI for cross-language CFI and using it for Clang and Rust compilers (and
+    //     possibly other compilers).
+    //
+    // Option (b) may weaken the protection for Rust-compiled only code, so it should be provided
+    // as an alternative to a Rust-specific encoding for when mixing Rust and C and C++ -compiled
+    // code. Option (c) would require changes to Clang to use the new ABI.
+    //
+    // [1] https://llvm.org/docs/TypeMetadata.html
+    // [2] https://itanium-cxx-abi.github.io/cxx-abi/abi.html
+    // [3] https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-special-vtables
+    // [4] https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-type
+    //
+    // FIXME(rcvalle): See comment above.
+    let arg_count = fn_abi.args.len() + fn_abi.ret.is_indirect() as usize;
+    format!("typeid{}", arg_count)
+}
+
 struct BinderLevel {
     /// The range of distances from the root of what's
     /// being printed, to the lifetimes in a binder.
index d9eb299e2fd350781725927aade13b5bfad1166c..4768c9e2db5e109ddca539d463d9b8fb381968ed 100644 (file)
@@ -68,8 +68,10 @@ pub struct ArgAttribute: u16 {
             const NonNull   = 1 << 3;
             const ReadOnly  = 1 << 4;
             const InReg     = 1 << 5;
-            // NoAlias on &mut arguments can only be used with LLVM >= 12 due to miscompiles
-            // in earlier versions. FIXME: Remove this distinction once possible.
+            // Due to past miscompiles in LLVM, we use a separate attribute for
+            // &mut arguments, so that the codegen backend can decide whether
+            // or not to actually emit the attribute. It can also be controlled
+            // with the `-Zmutable-noalias` debugging option.
             const NoAliasMutRef = 1 << 6;
         }
     }
index dc91f1230964921d22bd30924373df7fc78744cf..ca3550e9278d10426b2a7902e695c01849f60157 100644 (file)
@@ -2,11 +2,11 @@
 
 pub fn target() -> Target {
     let mut base = super::apple_base::opts("macos");
-    base.cpu = "apple-a12".to_string();
+    base.cpu = "apple-a14".to_string();
     base.max_atomic_width = Some(128);
 
     // FIXME: The leak sanitizer currently fails the tests, see #88132.
-    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
+    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD;
 
     base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-arch".to_string(), "arm64".to_string()]);
     base.link_env_remove.extend(super::apple_base::macos_link_env_remove());
index 71ee6deb07f903b5c64b9b46d8e5ec59e9c6c1bd..a393858879bfe725ab4c239e6da04dbec1622cb5 100644 (file)
@@ -8,6 +8,7 @@ pub fn target() -> Target {
         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: TargetOptions {
+            features: "+outline-atomics".to_string(),
             max_atomic_width: Some(128),
             mcount: "\u{1}_mcount".to_string(),
             endian: Endian::Big,
index e05360ea45c6c5b677f07ace67752a0a11f3a31b..e75100f1435115300f61dd274db7b86988d5ed17 100644 (file)
@@ -12,6 +12,7 @@ pub fn target() -> Target {
         arch: "aarch64".to_string(),
         options: TargetOptions {
             abi: "ilp32".to_string(),
+            features: "+outline-atomics".to_string(),
             mcount: "\u{1}_mcount".to_string(),
             endian: Endian::Big,
             ..base
index 56d71df6bda242af9d55c0dace7aa5d6689868dd..05e0c65dd5c38654b001db52bb786972476cca21 100644 (file)
@@ -8,7 +8,7 @@ pub fn target() -> Target {
         arch: "aarch64".to_string(),
         options: TargetOptions {
             max_atomic_width: Some(128),
-            supported_sanitizers: SanitizerSet::ADDRESS,
+            supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI,
             ..super::fuchsia_base::opts()
         },
     }
index 409cab72ec2196898ba478fa53d379c6041cb51d..1e9abbbe1e7878c5553f39983046d01b758acf86 100644 (file)
@@ -14,7 +14,7 @@ pub fn target() -> Target {
             // As documented in https://developer.android.com/ndk/guides/cpu-features.html
             // the neon (ASIMD) and FP must exist on all android aarch64 targets.
             features: "+neon,+fp-armv8".to_string(),
-            supported_sanitizers: SanitizerSet::HWADDRESS,
+            supported_sanitizers: SanitizerSet::CFI | SanitizerSet::HWADDRESS,
             ..super::android_base::opts()
         },
     }
index 0caecd2987bd52e845430949f43f9b466112ed4b..03ee7ba4875c956a8d2b67628f87d8b6f848d8ce 100644 (file)
@@ -9,6 +9,7 @@ pub fn target() -> Target {
         options: TargetOptions {
             max_atomic_width: Some(128),
             supported_sanitizers: SanitizerSet::ADDRESS
+                | SanitizerSet::CFI
                 | SanitizerSet::MEMORY
                 | SanitizerSet::THREAD,
             ..super::freebsd_base::opts()
index 3e92ecbae054cc429c1ab49d97c698250ffeee67..850381f7fb073e6fb12c3dd1dc736cc7cdcb2dc5 100644 (file)
@@ -7,9 +7,11 @@ pub fn target() -> Target {
         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: TargetOptions {
+            features: "+outline-atomics".to_string(),
             mcount: "\u{1}_mcount".to_string(),
             max_atomic_width: Some(128),
             supported_sanitizers: SanitizerSet::ADDRESS
+                | SanitizerSet::CFI
                 | SanitizerSet::LEAK
                 | SanitizerSet::MEMORY
                 | SanitizerSet::THREAD
index 8522405f61feb50fbb2972a9990f72994b6816f6..1c931d5a705f0df3b95f75363f15ffb93bedf7c4 100644 (file)
@@ -8,6 +8,7 @@ pub fn target() -> Target {
         arch: "aarch64".to_string(),
         options: TargetOptions {
             abi: "ilp32".to_string(),
+            features: "+outline-atomics".to_string(),
             max_atomic_width: Some(128),
             mcount: "\u{1}_mcount".to_string(),
             ..super::linux_gnu_base::opts()
index 6a16b4ce419647f0569220f47e35f6f68540b0c1..0770f3496c2792bc87fbed8dc393fa6c4e9e385d 100644 (file)
@@ -9,6 +9,10 @@ pub fn target() -> Target {
         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: TargetOptions { mcount: "\u{1}_mcount".to_string(), ..base },
+        options: TargetOptions {
+            features: "+outline-atomics".to_string(),
+            mcount: "\u{1}_mcount".to_string(),
+            ..base
+        },
     }
 }
index 01f5c197d2023c477d14277c129d0f2281da8d02..afe8bbb352886a214d1b8bb7f3fd3c3d130b6000 100644 (file)
@@ -1,4 +1,4 @@
-use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{LinkArgs, LinkerFlavor, RelocModel, Target, TargetOptions};
 
 /// A base target for Nintendo 3DS devices using the devkitARM toolchain.
 ///
@@ -36,7 +36,6 @@ pub fn target() -> Target {
             features: "+vfp2".to_string(),
             pre_link_args,
             exe_suffix: ".elf".to_string(),
-            panic_strategy: PanicStrategy::Abort,
             ..Default::default()
         },
     }
index 414b0f7ff230c723d0a2b15aaeaaf6207ba9aa46..ce3dad26458d0c3d113b4e63f76e4275466002c9 100644 (file)
@@ -8,7 +8,6 @@ pub fn opts() -> TargetOptions {
     );
 
     TargetOptions {
-        os: "hermit".to_string(),
         linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
         disable_redzone: true,
         linker: Some("rust-lld".to_owned()),
index ff5dfa3f746254b0364c4faf37b17f81e941346b..69b90bf10fe6a131d3c96e6da2b27d1db190ffe1 100644 (file)
@@ -602,6 +602,7 @@ pub struct SanitizerSet: u8 {
         const MEMORY  = 1 << 2;
         const THREAD  = 1 << 3;
         const HWADDRESS = 1 << 4;
+        const CFI     = 1 << 5;
     }
 }
 
@@ -612,6 +613,7 @@ impl SanitizerSet {
     fn as_str(self) -> Option<&'static str> {
         Some(match self {
             SanitizerSet::ADDRESS => "address",
+            SanitizerSet::CFI => "cfi",
             SanitizerSet::LEAK => "leak",
             SanitizerSet::MEMORY => "memory",
             SanitizerSet::THREAD => "thread",
@@ -644,6 +646,7 @@ impl IntoIterator for SanitizerSet {
     fn into_iter(self) -> Self::IntoIter {
         [
             SanitizerSet::ADDRESS,
+            SanitizerSet::CFI,
             SanitizerSet::LEAK,
             SanitizerSet::MEMORY,
             SanitizerSet::THREAD,
@@ -954,6 +957,8 @@ fn $module() {
     ("armv6k-nintendo-3ds", armv6k_nintendo_3ds),
 
     ("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf),
+
+    ("x86_64-unknown-none", x86_64_unknown_none),
 }
 
 /// Warnings encountered when parsing the target `json`.
@@ -1522,6 +1527,7 @@ pub fn is_abi_supported(&self, abi: Abi) -> Option<bool> {
             AmdGpuKernel => self.arch == "amdgcn",
             AvrInterrupt | AvrNonBlockingInterrupt => self.arch == "avr",
             Wasm => ["wasm32", "wasm64"].contains(&&self.arch[..]),
+            Thiscall { .. } => self.arch == "x86",
             // On windows these fall-back to platform native calling convention (C) when the
             // architecture is not supported.
             //
@@ -1552,15 +1558,13 @@ pub fn is_abi_supported(&self, abi: Abi) -> Option<bool> {
             // > convention is used.
             //
             // -- https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions
-            Stdcall { .. } | Fastcall | Thiscall { .. } | Vectorcall if self.is_like_windows => {
-                true
-            }
+            Stdcall { .. } | Fastcall | Vectorcall if self.is_like_windows => true,
             // Outside of Windows we want to only support these calling conventions for the
             // architectures for which these calling conventions are actually well defined.
-            Stdcall { .. } | Fastcall | Thiscall { .. } if self.arch == "x86" => true,
+            Stdcall { .. } | Fastcall if self.arch == "x86" => true,
             Vectorcall if ["x86", "x86_64"].contains(&&self.arch[..]) => true,
             // Return a `None` for other cases so that we know to emit a future compat lint.
-            Stdcall { .. } | Fastcall | Thiscall { .. } | Vectorcall => return None,
+            Stdcall { .. } | Fastcall | Vectorcall => return None,
         })
     }
 
@@ -1805,6 +1809,7 @@ macro_rules! key {
                         for s in a {
                             base.$key_name |= match s.as_string() {
                                 Some("address") => SanitizerSet::ADDRESS,
+                                Some("cfi") => SanitizerSet::CFI,
                                 Some("leak") => SanitizerSet::LEAK,
                                 Some("memory") => SanitizerSet::MEMORY,
                                 Some("thread") => SanitizerSet::THREAD,
@@ -2066,7 +2071,7 @@ macro_rules! key {
     /// JSON decoding.
     pub fn search(
         target_triple: &TargetTriple,
-        sysroot: &PathBuf,
+        sysroot: &Path,
     ) -> Result<(Target, TargetWarnings), String> {
         use rustc_serialize::json;
         use std::env;
index 60fd42970c7d6c908ee152473841654081a9bf6d..22fdaabfcb89b68821fde9b65c7a137c2b1439ba 100644 (file)
@@ -13,7 +13,8 @@ pub fn target() -> Target {
     base.link_env_remove.extend(super::apple_base::macos_link_env_remove());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
-    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD;
+    base.supported_sanitizers =
+        SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD;
 
     // Clang automatically chooses a more specific target based on
     // MACOSX_DEPLOYMENT_TARGET.  To enable cross-language LTO to work
index aa65ebe1f9dbd77615e0f381b5ef7eb098b6438c..c253c0c30b3d34c442baa2995e63e4c645b3e7fb 100644 (file)
@@ -6,7 +6,7 @@ pub fn target() -> Target {
     base.max_atomic_width = Some(64);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
-    base.supported_sanitizers = SanitizerSet::ADDRESS;
+    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI;
 
     Target {
         llvm_target: "x86_64-fuchsia".to_string(),
index 34b6d2901c82039010871fc2376b12c4a815ec9d..6aa0728668277f52e723f14a42ce3a67218c2e87 100644 (file)
@@ -8,7 +8,7 @@ pub fn target() -> Target {
     base.max_atomic_width = Some(64);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
-    base.supported_sanitizers = SanitizerSet::ADDRESS;
+    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI;
 
     Target {
         llvm_target: "x86_64-pc-solaris".to_string(),
index b5fc15f5e04bf200038118a5f9ae0d5db909c0fc..24cc7ae788b458dbfa268841cfba06f7fc202502 100644 (file)
@@ -7,7 +7,8 @@ pub fn target() -> Target {
     base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
-    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::MEMORY | SanitizerSet::THREAD;
+    base.supported_sanitizers =
+        SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::MEMORY | SanitizerSet::THREAD;
 
     Target {
         llvm_target: "x86_64-unknown-freebsd".to_string(),
index ec196a7f823296d651a4ea9c8ead65122f29f4eb..79ccf63acfada71a1d2d268bf0a963b97f3368b6 100644 (file)
@@ -5,7 +5,7 @@ pub fn target() -> Target {
     base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string(), "-std=c99".to_string()]);
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
-    base.supported_sanitizers = SanitizerSet::ADDRESS;
+    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI;
 
     Target {
         // LLVM does not currently have a separate illumos target,
index 085079e06e570a0e3f7aea0aa4f119c8eb4f8638..c2484f2d8f66d88b8bfd23f3d88497b255a4eb24 100644 (file)
@@ -7,8 +7,11 @@ pub fn target() -> Target {
     base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
-    base.supported_sanitizers =
-        SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::THREAD;
+    base.supported_sanitizers = SanitizerSet::ADDRESS
+        | SanitizerSet::CFI
+        | SanitizerSet::LEAK
+        | SanitizerSet::MEMORY
+        | SanitizerSet::THREAD;
 
     Target {
         llvm_target: "x86_64-unknown-linux-gnu".to_string(),
index 5ad243aa4075e2c3616e24a053e213cf22a3c96e..a5e79803335b7ae027f2c678740288ee72a39f7c 100644 (file)
@@ -8,8 +8,11 @@ pub fn target() -> Target {
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
     base.static_position_independent_executables = true;
-    base.supported_sanitizers =
-        SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::THREAD;
+    base.supported_sanitizers = SanitizerSet::ADDRESS
+        | SanitizerSet::CFI
+        | SanitizerSet::LEAK
+        | SanitizerSet::MEMORY
+        | SanitizerSet::THREAD;
 
     Target {
         llvm_target: "x86_64-unknown-linux-musl".to_string(),
index 9ba86280d519731d78e5fa13b73ce7feb7ff49c8..bdb2be4f863e2bed0d37e2f1c60247568ec9baf5 100644 (file)
@@ -7,8 +7,11 @@ pub fn target() -> Target {
     base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
-    base.supported_sanitizers =
-        SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::THREAD;
+    base.supported_sanitizers = SanitizerSet::ADDRESS
+        | SanitizerSet::CFI
+        | SanitizerSet::LEAK
+        | SanitizerSet::MEMORY
+        | SanitizerSet::THREAD;
 
     Target {
         llvm_target: "x86_64-unknown-netbsd".to_string(),
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none.rs
new file mode 100644 (file)
index 0000000..722409d
--- /dev/null
@@ -0,0 +1,41 @@
+// Generic x86-64 target for bare-metal code - Floating point disabled
+//
+// Can be used in conjunction with the `target-feature` and
+// `target-cpu` compiler flags to opt-in more hardware-specific
+// features.
+
+use super::{
+    CodeModel, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, RelroLevel, StackProbeType,
+    Target, TargetOptions,
+};
+
+pub fn target() -> Target {
+    let opts = TargetOptions {
+        cpu: "x86-64".to_string(),
+        max_atomic_width: Some(64),
+        // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+        stack_probes: StackProbeType::Call,
+        position_independent_executables: true,
+        static_position_independent_executables: true,
+        relro_level: RelroLevel::Full,
+        relocation_model: RelocModel::Pic,
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+        linker: Some("rust-lld".to_owned()),
+        features:
+            "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
+                .to_string(),
+        executables: true,
+        disable_redzone: true,
+        panic_strategy: PanicStrategy::Abort,
+        code_model: Some(CodeModel::Kernel),
+        ..Default::default()
+    };
+    Target {
+        llvm_target: "x86_64-unknown-none-elf".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: opts,
+    }
+}
index 53afe4ca068c4cf24f0601ee3c38ddb7a8cbc855..4c80483fc1f1e7750b5c3e68200c75ccb6a6ec23 100644 (file)
@@ -152,11 +152,12 @@ fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
             },
             cause,
         );
-        if let Err(e) = fulfillcx.select_where_possible(&self.infcx) {
+        let errors = fulfillcx.select_where_possible(&self.infcx);
+        if !errors.is_empty() {
             // This shouldn't happen, except for evaluate/fulfill mismatches,
             // but that's not a reason for an ICE (`predicate_may_hold` is conservative
             // by design).
-            debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", e);
+            debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", errors);
             return None;
         }
         let obligations = fulfillcx.pending_obligations();
index 94c9c1f2e584d2449c1bd948691e32dc5bd6cf9b..1a049e6ec649da4bcd0c63408e40b7e5106f6d0a 100644 (file)
@@ -22,7 +22,6 @@
 #![feature(crate_visibility_modifier)]
 #![feature(control_flow_enum)]
 #![recursion_limit = "512"] // For rustdoc
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate rustc_macros;
index 6c5e6b1cfc385fbc0b5e2e9daa8d55ce649726da..75d57d78e3b0294be8d2138590248c775ddb6048 100644 (file)
@@ -1,45 +1,14 @@
-use crate::traits::{self, ObligationCause, PredicateObligation};
+use crate::traits;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::Lrc;
-use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::DefId;
 use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
-use rustc_infer::infer::opaque_types::OpaqueTypeDecl;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::infer::{InferCtxt, InferOk};
-use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor};
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst};
+use rustc_infer::infer::InferCtxt;
+use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
+use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts};
 use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt};
 use rustc_span::Span;
 
-use std::ops::ControlFlow;
-
 pub trait InferCtxtExt<'tcx> {
-    fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
-        &self,
-        body_id: hir::HirId,
-        param_env: ty::ParamEnv<'tcx>,
-        value: T,
-        value_span: Span,
-    ) -> InferOk<'tcx, T>;
-
-    fn constrain_opaque_types(&self);
-
-    fn constrain_opaque_type(
-        &self,
-        opaque_type_key: OpaqueTypeKey<'tcx>,
-        opaque_defn: &OpaqueTypeDecl<'tcx>,
-    );
-
-    /*private*/
-    fn generate_member_constraint(
-        &self,
-        concrete_ty: Ty<'tcx>,
-        opaque_defn: &OpaqueTypeDecl<'tcx>,
-        opaque_type_key: OpaqueTypeKey<'tcx>,
-        first_own_region_index: usize,
-    );
-
     fn infer_opaque_definition_from_instantiation(
         &self,
         opaque_type_key: OpaqueTypeKey<'tcx>,
@@ -49,305 +18,6 @@ fn infer_opaque_definition_from_instantiation(
 }
 
 impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
-    /// Replaces all opaque types in `value` with fresh inference variables
-    /// and creates appropriate obligations. For example, given the input:
-    ///
-    ///     impl Iterator<Item = impl Debug>
-    ///
-    /// this method would create two type variables, `?0` and `?1`. It would
-    /// return the type `?0` but also the obligations:
-    ///
-    ///     ?0: Iterator<Item = ?1>
-    ///     ?1: Debug
-    ///
-    /// Moreover, it returns an `OpaqueTypeMap` that would map `?0` to
-    /// info about the `impl Iterator<..>` type and `?1` to info about
-    /// the `impl Debug` type.
-    ///
-    /// # Parameters
-    ///
-    /// - `parent_def_id` -- the `DefId` of the function in which the opaque type
-    ///   is defined
-    /// - `body_id` -- the body-id with which the resulting obligations should
-    ///   be associated
-    /// - `param_env` -- the in-scope parameter environment to be used for
-    ///   obligations
-    /// - `value` -- the value within which we are instantiating opaque types
-    /// - `value_span` -- the span where the value came from, used in error reporting
-    fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
-        &self,
-        body_id: hir::HirId,
-        param_env: ty::ParamEnv<'tcx>,
-        value: T,
-        value_span: Span,
-    ) -> InferOk<'tcx, T> {
-        debug!(
-            "instantiate_opaque_types(value={:?}, body_id={:?}, \
-             param_env={:?}, value_span={:?})",
-            value, body_id, param_env, value_span,
-        );
-        let mut instantiator =
-            Instantiator { infcx: self, body_id, param_env, value_span, obligations: vec![] };
-        let value = instantiator.instantiate_opaque_types_in_map(value);
-        InferOk { value, obligations: instantiator.obligations }
-    }
-
-    /// Given the map `opaque_types` containing the opaque
-    /// `impl Trait` types whose underlying, hidden types are being
-    /// inferred, this method adds constraints to the regions
-    /// appearing in those underlying hidden types to ensure that they
-    /// at least do not refer to random scopes within the current
-    /// function. These constraints are not (quite) sufficient to
-    /// guarantee that the regions are actually legal values; that
-    /// final condition is imposed after region inference is done.
-    ///
-    /// # The Problem
-    ///
-    /// Let's work through an example to explain how it works. Assume
-    /// the current function is as follows:
-    ///
-    /// ```text
-    /// fn foo<'a, 'b>(..) -> (impl Bar<'a>, impl Bar<'b>)
-    /// ```
-    ///
-    /// Here, we have two `impl Trait` types whose values are being
-    /// inferred (the `impl Bar<'a>` and the `impl
-    /// Bar<'b>`). Conceptually, this is sugar for a setup where we
-    /// define underlying opaque types (`Foo1`, `Foo2`) and then, in
-    /// the return type of `foo`, we *reference* those definitions:
-    ///
-    /// ```text
-    /// type Foo1<'x> = impl Bar<'x>;
-    /// type Foo2<'x> = impl Bar<'x>;
-    /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
-    ///                    //  ^^^^ ^^
-    ///                    //  |    |
-    ///                    //  |    substs
-    ///                    //  def_id
-    /// ```
-    ///
-    /// As indicating in the comments above, each of those references
-    /// is (in the compiler) basically a substitution (`substs`)
-    /// applied to the type of a suitable `def_id` (which identifies
-    /// `Foo1` or `Foo2`).
-    ///
-    /// Now, at this point in compilation, what we have done is to
-    /// replace each of the references (`Foo1<'a>`, `Foo2<'b>`) with
-    /// fresh inference variables C1 and C2. We wish to use the values
-    /// of these variables to infer the underlying types of `Foo1` and
-    /// `Foo2`. That is, this gives rise to higher-order (pattern) unification
-    /// constraints like:
-    ///
-    /// ```text
-    /// for<'a> (Foo1<'a> = C1)
-    /// for<'b> (Foo1<'b> = C2)
-    /// ```
-    ///
-    /// For these equation to be satisfiable, the types `C1` and `C2`
-    /// can only refer to a limited set of regions. For example, `C1`
-    /// can only refer to `'static` and `'a`, and `C2` can only refer
-    /// to `'static` and `'b`. The job of this function is to impose that
-    /// constraint.
-    ///
-    /// Up to this point, C1 and C2 are basically just random type
-    /// inference variables, and hence they may contain arbitrary
-    /// regions. In fact, it is fairly likely that they do! Consider
-    /// this possible definition of `foo`:
-    ///
-    /// ```text
-    /// fn foo<'a, 'b>(x: &'a i32, y: &'b i32) -> (impl Bar<'a>, impl Bar<'b>) {
-    ///         (&*x, &*y)
-    ///     }
-    /// ```
-    ///
-    /// Here, the values for the concrete types of the two impl
-    /// traits will include inference variables:
-    ///
-    /// ```text
-    /// &'0 i32
-    /// &'1 i32
-    /// ```
-    ///
-    /// Ordinarily, the subtyping rules would ensure that these are
-    /// sufficiently large. But since `impl Bar<'a>` isn't a specific
-    /// type per se, we don't get such constraints by default. This
-    /// is where this function comes into play. It adds extra
-    /// constraints to ensure that all the regions which appear in the
-    /// inferred type are regions that could validly appear.
-    ///
-    /// This is actually a bit of a tricky constraint in general. We
-    /// want to say that each variable (e.g., `'0`) can only take on
-    /// values that were supplied as arguments to the opaque type
-    /// (e.g., `'a` for `Foo1<'a>`) or `'static`, which is always in
-    /// scope. We don't have a constraint quite of this kind in the current
-    /// region checker.
-    ///
-    /// # The Solution
-    ///
-    /// We generally prefer to make `<=` constraints, since they
-    /// integrate best into the region solver. To do that, we find the
-    /// "minimum" of all the arguments that appear in the substs: that
-    /// is, some region which is less than all the others. In the case
-    /// of `Foo1<'a>`, that would be `'a` (it's the only choice, after
-    /// all). Then we apply that as a least bound to the variables
-    /// (e.g., `'a <= '0`).
-    ///
-    /// In some cases, there is no minimum. Consider this example:
-    ///
-    /// ```text
-    /// fn baz<'a, 'b>() -> impl Trait<'a, 'b> { ... }
-    /// ```
-    ///
-    /// Here we would report a more complex "in constraint", like `'r
-    /// in ['a, 'b, 'static]` (where `'r` is some region appearing in
-    /// the hidden type).
-    ///
-    /// # Constrain regions, not the hidden concrete type
-    ///
-    /// Note that generating constraints on each region `Rc` is *not*
-    /// the same as generating an outlives constraint on `Tc` iself.
-    /// For example, if we had a function like this:
-    ///
-    /// ```rust
-    /// fn foo<'a, T>(x: &'a u32, y: T) -> impl Foo<'a> {
-    ///   (x, y)
-    /// }
-    ///
-    /// // Equivalent to:
-    /// type FooReturn<'a, T> = impl Foo<'a>;
-    /// fn foo<'a, T>(..) -> FooReturn<'a, T> { .. }
-    /// ```
-    ///
-    /// then the hidden type `Tc` would be `(&'0 u32, T)` (where `'0`
-    /// is an inference variable). If we generated a constraint that
-    /// `Tc: 'a`, then this would incorrectly require that `T: 'a` --
-    /// but this is not necessary, because the opaque type we
-    /// create will be allowed to reference `T`. So we only generate a
-    /// constraint that `'0: 'a`.
-    ///
-    /// # The `free_region_relations` parameter
-    ///
-    /// The `free_region_relations` argument is used to find the
-    /// "minimum" of the regions supplied to a given opaque type.
-    /// It must be a relation that can answer whether `'a <= 'b`,
-    /// where `'a` and `'b` are regions that appear in the "substs"
-    /// for the opaque type references (the `<'a>` in `Foo1<'a>`).
-    ///
-    /// Note that we do not impose the constraints based on the
-    /// generic regions from the `Foo1` definition (e.g., `'x`). This
-    /// is because the constraints we are imposing here is basically
-    /// the concern of the one generating the constraining type C1,
-    /// which is the current function. It also means that we can
-    /// take "implied bounds" into account in some cases:
-    ///
-    /// ```text
-    /// trait SomeTrait<'a, 'b> { }
-    /// fn foo<'a, 'b>(_: &'a &'b u32) -> impl SomeTrait<'a, 'b> { .. }
-    /// ```
-    ///
-    /// Here, the fact that `'b: 'a` is known only because of the
-    /// implied bounds from the `&'a &'b u32` parameter, and is not
-    /// "inherent" to the opaque type definition.
-    ///
-    /// # Parameters
-    ///
-    /// - `opaque_types` -- the map produced by `instantiate_opaque_types`
-    /// - `free_region_relations` -- something that can be used to relate
-    ///   the free regions (`'a`) that appear in the impl trait.
-    fn constrain_opaque_types(&self) {
-        let opaque_types = self.inner.borrow().opaque_types.clone();
-        for (opaque_type_key, opaque_defn) in opaque_types {
-            self.constrain_opaque_type(opaque_type_key, &opaque_defn);
-        }
-    }
-
-    /// See `constrain_opaque_types` for documentation.
-    #[instrument(level = "debug", skip(self))]
-    fn constrain_opaque_type(
-        &self,
-        opaque_type_key: OpaqueTypeKey<'tcx>,
-        opaque_defn: &OpaqueTypeDecl<'tcx>,
-    ) {
-        let def_id = opaque_type_key.def_id;
-
-        let tcx = self.tcx;
-
-        let concrete_ty = self.resolve_vars_if_possible(opaque_defn.concrete_ty);
-
-        debug!(?concrete_ty);
-
-        let first_own_region = match opaque_defn.origin {
-            hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => {
-                // We lower
-                //
-                // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
-                //
-                // into
-                //
-                // type foo::<'p0..'pn>::Foo<'q0..'qm>
-                // fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
-                //
-                // For these types we only iterate over `'l0..lm` below.
-                tcx.generics_of(def_id).parent_count
-            }
-            // These opaque type inherit all lifetime parameters from their
-            // parent, so we have to check them all.
-            hir::OpaqueTyOrigin::TyAlias => 0,
-        };
-
-        // The regions that appear in the hidden type must be equal to
-        // one of the regions in scope for the opaque type.
-        self.generate_member_constraint(
-            concrete_ty,
-            opaque_defn,
-            opaque_type_key,
-            first_own_region,
-        );
-    }
-
-    /// As a fallback, we sometimes generate an "in constraint". For
-    /// a case like `impl Foo<'a, 'b>`, where `'a` and `'b` cannot be
-    /// related, we would generate a constraint `'r in ['a, 'b,
-    /// 'static]` for each region `'r` that appears in the hidden type
-    /// (i.e., it must be equal to `'a`, `'b`, or `'static`).
-    ///
-    /// `conflict1` and `conflict2` are the two region bounds that we
-    /// detected which were unrelated. They are used for diagnostics.
-    fn generate_member_constraint(
-        &self,
-        concrete_ty: Ty<'tcx>,
-        opaque_defn: &OpaqueTypeDecl<'tcx>,
-        opaque_type_key: OpaqueTypeKey<'tcx>,
-        first_own_region: usize,
-    ) {
-        // Create the set of choice regions: each region in the hidden
-        // type can be equal to any of the region parameters of the
-        // opaque type definition.
-        let choice_regions: Lrc<Vec<ty::Region<'tcx>>> = Lrc::new(
-            opaque_type_key.substs[first_own_region..]
-                .iter()
-                .filter_map(|arg| match arg.unpack() {
-                    GenericArgKind::Lifetime(r) => Some(r),
-                    GenericArgKind::Type(_) | GenericArgKind::Const(_) => None,
-                })
-                .chain(std::iter::once(self.tcx.lifetimes.re_static))
-                .collect(),
-        );
-
-        concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
-            tcx: self.tcx,
-            op: |r| {
-                self.member_constraint(
-                    opaque_type_key.def_id,
-                    opaque_defn.definition_span,
-                    concrete_ty,
-                    r,
-                    &choice_regions,
-                )
-            },
-        });
-    }
-
     /// Given the fully resolved, instantiated type for an opaque
     /// type, i.e., the value of an inference variable like C1 or C2
     /// (*), computes the "definition type" for an opaque type
@@ -363,7 +33,7 @@ fn generate_member_constraint(
     /// purpose of this function is to do that translation.
     ///
     /// (*) C1 and C2 were introduced in the comments on
-    /// `constrain_opaque_types`. Read that comment for more context.
+    /// `constrain_opaque_type`. Read that comment for more context.
     ///
     /// # Parameters
     ///
@@ -409,83 +79,6 @@ fn infer_opaque_definition_from_instantiation(
     }
 }
 
-// Visitor that requires that (almost) all regions in the type visited outlive
-// `least_region`. We cannot use `push_outlives_components` because regions in
-// closure signatures are not included in their outlives components. We need to
-// ensure all regions outlive the given bound so that we don't end up with,
-// say, `ReVar` appearing in a return type and causing ICEs when other
-// functions end up with region constraints involving regions from other
-// functions.
-//
-// We also cannot use `for_each_free_region` because for closures it includes
-// the regions parameters from the enclosing item.
-//
-// We ignore any type parameters because impl trait values are assumed to
-// capture all the in-scope type parameters.
-struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP> {
-    tcx: TyCtxt<'tcx>,
-    op: OP,
-}
-
-impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP>
-where
-    OP: FnMut(ty::Region<'tcx>),
-{
-    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
-        Some(self.tcx)
-    }
-
-    fn visit_binder<T: TypeFoldable<'tcx>>(
-        &mut self,
-        t: &ty::Binder<'tcx, T>,
-    ) -> ControlFlow<Self::BreakTy> {
-        t.as_ref().skip_binder().visit_with(self);
-        ControlFlow::CONTINUE
-    }
-
-    fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
-        match *r {
-            // ignore bound regions, keep visiting
-            ty::ReLateBound(_, _) => ControlFlow::CONTINUE,
-            _ => {
-                (self.op)(r);
-                ControlFlow::CONTINUE
-            }
-        }
-    }
-
-    fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-        // We're only interested in types involving regions
-        if !ty.flags().intersects(ty::TypeFlags::HAS_POTENTIAL_FREE_REGIONS) {
-            return ControlFlow::CONTINUE;
-        }
-
-        match ty.kind() {
-            ty::Closure(_, ref substs) => {
-                // Skip lifetime parameters of the enclosing item(s)
-
-                substs.as_closure().tupled_upvars_ty().visit_with(self);
-                substs.as_closure().sig_as_fn_ptr_ty().visit_with(self);
-            }
-
-            ty::Generator(_, ref substs, _) => {
-                // Skip lifetime parameters of the enclosing item(s)
-                // Also skip the witness type, because that has no free regions.
-
-                substs.as_generator().tupled_upvars_ty().visit_with(self);
-                substs.as_generator().return_ty().visit_with(self);
-                substs.as_generator().yield_ty().visit_with(self);
-                substs.as_generator().resume_ty().visit_with(self);
-            }
-            _ => {
-                ty.super_visit_with(self);
-            }
-        }
-
-        ControlFlow::CONTINUE
-    }
-}
-
 struct ReverseMapper<'tcx> {
     tcx: TyCtxt<'tcx>,
 
@@ -728,235 +321,6 @@ fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
     }
 }
 
-struct Instantiator<'a, 'tcx> {
-    infcx: &'a InferCtxt<'a, 'tcx>,
-    body_id: hir::HirId,
-    param_env: ty::ParamEnv<'tcx>,
-    value_span: Span,
-    obligations: Vec<PredicateObligation<'tcx>>,
-}
-
-impl<'a, 'tcx> Instantiator<'a, 'tcx> {
-    fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
-        let tcx = self.infcx.tcx;
-        value.fold_with(&mut BottomUpFolder {
-            tcx,
-            ty_op: |ty| {
-                if ty.references_error() {
-                    return tcx.ty_error();
-                } else if let ty::Opaque(def_id, substs) = ty.kind() {
-                    // Check that this is `impl Trait` type is
-                    // declared by `parent_def_id` -- i.e., one whose
-                    // value we are inferring.  At present, this is
-                    // always true during the first phase of
-                    // type-check, but not always true later on during
-                    // NLL. Once we support named opaque types more fully,
-                    // this same scenario will be able to arise during all phases.
-                    //
-                    // Here is an example using type alias `impl Trait`
-                    // that indicates the distinction we are checking for:
-                    //
-                    // ```rust
-                    // mod a {
-                    //   pub type Foo = impl Iterator;
-                    //   pub fn make_foo() -> Foo { .. }
-                    // }
-                    //
-                    // mod b {
-                    //   fn foo() -> a::Foo { a::make_foo() }
-                    // }
-                    // ```
-                    //
-                    // Here, the return type of `foo` references an
-                    // `Opaque` indeed, but not one whose value is
-                    // presently being inferred. You can get into a
-                    // similar situation with closure return types
-                    // today:
-                    //
-                    // ```rust
-                    // fn foo() -> impl Iterator { .. }
-                    // fn bar() {
-                    //     let x = || foo(); // returns the Opaque assoc with `foo`
-                    // }
-                    // ```
-                    if let Some(def_id) = def_id.as_local() {
-                        let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-                        let parent_def_id = self.infcx.defining_use_anchor;
-                        let def_scope_default = || {
-                            let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
-                            parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id)
-                        };
-                        let (in_definition_scope, origin) =
-                            match tcx.hir().expect_item(opaque_hir_id).kind {
-                                // Anonymous `impl Trait`
-                                hir::ItemKind::OpaqueTy(hir::OpaqueTy {
-                                    impl_trait_fn: Some(parent),
-                                    origin,
-                                    ..
-                                }) => (parent == parent_def_id.to_def_id(), origin),
-                                // Named `type Foo = impl Bar;`
-                                hir::ItemKind::OpaqueTy(hir::OpaqueTy {
-                                    impl_trait_fn: None,
-                                    origin,
-                                    ..
-                                }) => (
-                                    may_define_opaque_type(tcx, parent_def_id, opaque_hir_id),
-                                    origin,
-                                ),
-                                _ => (def_scope_default(), hir::OpaqueTyOrigin::TyAlias),
-                            };
-                        if in_definition_scope {
-                            let opaque_type_key =
-                                OpaqueTypeKey { def_id: def_id.to_def_id(), substs };
-                            return self.fold_opaque_ty(ty, opaque_type_key, origin);
-                        }
-
-                        debug!(
-                            "instantiate_opaque_types_in_map: \
-                             encountered opaque outside its definition scope \
-                             def_id={:?}",
-                            def_id,
-                        );
-                    }
-                }
-
-                ty
-            },
-            lt_op: |lt| lt,
-            ct_op: |ct| ct,
-        })
-    }
-
-    #[instrument(skip(self), level = "debug")]
-    fn fold_opaque_ty(
-        &mut self,
-        ty: Ty<'tcx>,
-        opaque_type_key: OpaqueTypeKey<'tcx>,
-        origin: hir::OpaqueTyOrigin,
-    ) -> Ty<'tcx> {
-        let infcx = self.infcx;
-        let tcx = infcx.tcx;
-        let OpaqueTypeKey { def_id, substs } = opaque_type_key;
-
-        // Use the same type variable if the exact same opaque type appears more
-        // than once in the return type (e.g., if it's passed to a type alias).
-        if let Some(opaque_defn) = infcx.inner.borrow().opaque_types.get(&opaque_type_key) {
-            debug!("re-using cached concrete type {:?}", opaque_defn.concrete_ty.kind());
-            return opaque_defn.concrete_ty;
-        }
-
-        let ty_var = infcx.next_ty_var(TypeVariableOrigin {
-            kind: TypeVariableOriginKind::TypeInference,
-            span: self.value_span,
-        });
-
-        // Ideally, we'd get the span where *this specific `ty` came
-        // from*, but right now we just use the span from the overall
-        // value being folded. In simple cases like `-> impl Foo`,
-        // these are the same span, but not in cases like `-> (impl
-        // Foo, impl Bar)`.
-        let definition_span = self.value_span;
-
-        {
-            let mut infcx = self.infcx.inner.borrow_mut();
-            infcx.opaque_types.insert(
-                OpaqueTypeKey { def_id, substs },
-                OpaqueTypeDecl { opaque_type: ty, definition_span, concrete_ty: ty_var, origin },
-            );
-            infcx.opaque_types_vars.insert(ty_var, ty);
-        }
-
-        debug!("generated new type inference var {:?}", ty_var.kind());
-
-        let item_bounds = tcx.explicit_item_bounds(def_id);
-
-        self.obligations.reserve(item_bounds.len());
-        for (predicate, _) in item_bounds {
-            debug!(?predicate);
-            let predicate = predicate.subst(tcx, substs);
-            debug!(?predicate);
-
-            // We can't normalize associated types from `rustc_infer`, but we can eagerly register inference variables for them.
-            let predicate = predicate.fold_with(&mut BottomUpFolder {
-                tcx,
-                ty_op: |ty| match ty.kind() {
-                    ty::Projection(projection_ty) => infcx.infer_projection(
-                        self.param_env,
-                        *projection_ty,
-                        ObligationCause::misc(self.value_span, self.body_id),
-                        0,
-                        &mut self.obligations,
-                    ),
-                    _ => ty,
-                },
-                lt_op: |lt| lt,
-                ct_op: |ct| ct,
-            });
-            debug!(?predicate);
-
-            if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() {
-                if projection.ty.references_error() {
-                    // No point on adding these obligations since there's a type error involved.
-                    return tcx.ty_error();
-                }
-            }
-            // Change the predicate to refer to the type variable,
-            // which will be the concrete type instead of the opaque type.
-            // This also instantiates nested instances of `impl Trait`.
-            let predicate = self.instantiate_opaque_types_in_map(predicate);
-
-            let cause =
-                traits::ObligationCause::new(self.value_span, self.body_id, traits::OpaqueType);
-
-            // Require that the predicate holds for the concrete type.
-            debug!(?predicate);
-            self.obligations.push(traits::Obligation::new(cause, self.param_env, predicate));
-        }
-
-        ty_var
-    }
-}
-
-/// Returns `true` if `opaque_hir_id` is a sibling or a child of a sibling of `def_id`.
-///
-/// Example:
-/// ```rust
-/// pub mod foo {
-///     pub mod bar {
-///         pub trait Bar { .. }
-///
-///         pub type Baz = impl Bar;
-///
-///         fn f1() -> Baz { .. }
-///     }
-///
-///     fn f2() -> bar::Baz { .. }
-/// }
-/// ```
-///
-/// Here, `def_id` is the `LocalDefId` of the defining use of the opaque type (e.g., `f1` or `f2`),
-/// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`.
-/// For the above example, this function returns `true` for `f1` and `false` for `f2`.
-fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hir::HirId) -> bool {
-    let mut hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-
-    // Named opaque types can be defined by any siblings or children of siblings.
-    let scope = tcx.hir().get_defining_scope(opaque_hir_id);
-    // We walk up the node tree until we hit the root or the scope of the opaque type.
-    while hir_id != scope && hir_id != hir::CRATE_HIR_ID {
-        hir_id = tcx.hir().get_parent_item(hir_id);
-    }
-    // Syntactically, we are allowed to define the concrete type if:
-    let res = hir_id == scope;
-    trace!(
-        "may_define_opaque_type(def={:?}, opaque_node={:?}) = {}",
-        tcx.hir().find(hir_id),
-        tcx.hir().get(opaque_hir_id),
-        res
-    );
-    res
-}
-
 /// Given a set of predicates that apply to an object type, returns
 /// the region bounds that the (erased) `Self` type must
 /// outlive. Precisely *because* the `Self` type is erased, the
index 6452b520452d6802b157c023ecf457620a3da1c3..54f7b91080dd9fb0a9cae74dea7ecd43517972a5 100644 (file)
@@ -187,9 +187,11 @@ pub fn find_auto_trait_generics<A>(
             // an additional sanity check.
             let mut fulfill = FulfillmentContext::new();
             fulfill.register_bound(&infcx, full_env, ty, trait_did, ObligationCause::dummy());
-            fulfill.select_all_or_error(&infcx).unwrap_or_else(|e| {
-                panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, e)
-            });
+            let errors = fulfill.select_all_or_error(&infcx);
+
+            if !errors.is_empty() {
+                panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, errors);
+            }
 
             let body_id_map: FxHashMap<_, _> = infcx
                 .inner
index ec62ee400688ca2f62cae140fc32b1f40da8bf5e..2ccb25349173ff300d88e636ad59848fcad44e92 100644 (file)
@@ -49,34 +49,32 @@ fn register_predicate_obligation(
         self.obligations.insert(obligation);
     }
 
-    fn select_all_or_error(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
-        self.select_where_possible(infcx)?;
-
-        if self.obligations.is_empty() {
-            Ok(())
-        } else {
-            let errors = self
-                .obligations
-                .iter()
-                .map(|obligation| FulfillmentError {
-                    obligation: obligation.clone(),
-                    code: FulfillmentErrorCode::CodeAmbiguity,
-                    // FIXME - does Chalk have a notation of 'root obligation'?
-                    // This is just for diagnostics, so it's okay if this is wrong
-                    root_obligation: obligation.clone(),
-                })
-                .collect();
-            Err(errors)
+    fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
+        {
+            let errors = self.select_where_possible(infcx);
+
+            if !errors.is_empty() {
+                return errors;
+            }
         }
+
+        // any remaining obligations are errors
+        self.obligations
+            .iter()
+            .map(|obligation| FulfillmentError {
+                obligation: obligation.clone(),
+                code: FulfillmentErrorCode::CodeAmbiguity,
+                // FIXME - does Chalk have a notation of 'root obligation'?
+                // This is just for diagnostics, so it's okay if this is wrong
+                root_obligation: obligation.clone(),
+            })
+            .collect()
     }
 
     fn select_where_possible(
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+    ) -> Vec<FulfillmentError<'tcx>> {
         assert!(!infcx.is_in_snapshot());
 
         let mut errors = Vec::new();
@@ -147,7 +145,7 @@ fn select_where_possible(
             }
         }
 
-        if errors.is_empty() { Ok(()) } else { Err(errors) }
+        errors
     }
 
     fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
index f06f0e32f414b73f90e35192996ba41ba780fcb3..bdd4fdd40438c6fb5e4ce219847bd106146f559a 100644 (file)
@@ -120,7 +120,8 @@ fn drain_fulfillment_cx_or_panic<T>(
     // In principle, we only need to do this so long as `result`
     // contains unbound type parameters. It could be a slight
     // optimization to stop iterating early.
-    if let Err(errors) = fulfill_cx.select_all_or_error(infcx) {
+    let errors = fulfill_cx.select_all_or_error(infcx);
+    if !errors.is_empty() {
         infcx.tcx.sess.delay_span_bug(
             rustc_span::DUMMY_SP,
             &format!("Encountered errors `{:?}` resolving bounds after type-checking", errors),
index 8edb7069fc45f9a19c55f3c66f75a0bc79b9870f..6b5d37c0f43086516d57425d66807dd3b6ca72b7 100644 (file)
@@ -151,7 +151,7 @@ enum FailureKind {
 
     if concrete.is_ok() && uv.substs(infcx.tcx).definitely_has_param_types_or_consts(infcx.tcx) {
         match infcx.tcx.def_kind(uv.def.did) {
-            DefKind::AnonConst => {
+            DefKind::AnonConst | DefKind::InlineConst => {
                 let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def);
 
                 if mir_body.is_polymorphic {
@@ -495,7 +495,7 @@ pub(super) fn thir_abstract_const<'tcx>(
             // we want to look into them or treat them as opaque projections.
             //
             // Right now we do neither of that and simply always fail to unify them.
-            DefKind::AnonConst => (),
+            DefKind::AnonConst | DefKind::InlineConst => (),
             _ => return Ok(None),
         }
 
index 8396e3263f9a469e46cddf878e8b00ba60a54ce8..0b88eb7572ad0fd3f240113bc9171fd3aa87c599 100644 (file)
@@ -1492,6 +1492,9 @@ fn get_parent_trait_ref(
                     }
                 }
             }
+            ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => {
+                self.get_parent_trait_ref(&parent_code)
+            }
             _ => None,
         }
     }
@@ -1835,7 +1838,7 @@ fn annotate_source_of_ambiguity(
                 post.iter().map(|p| format!("- {}", p)).take(4).collect::<Vec<_>>().join("\n"),
                 post.len() - 4,
             )
-        } else if post.len() > 1 || (post.len() == 1 && post[0].contains("\n")) {
+        } else if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) {
             format!(":\n{}", post.iter().map(|p| format!("- {}", p)).collect::<Vec<_>>().join("\n"),)
         } else if post.len() == 1 {
             format!(": `{}`", post[0])
@@ -1997,19 +2000,14 @@ fn maybe_suggest_unsized_generics(
         let sized_trait = self.tcx.lang_items().sized_trait();
         debug!("maybe_suggest_unsized_generics: generics.params={:?}", generics.params);
         debug!("maybe_suggest_unsized_generics: generics.where_clause={:?}", generics.where_clause);
-        let param = generics
-            .params
-            .iter()
-            .filter(|param| param.span == span)
-            .filter(|param| {
-                // Check that none of the explicit trait bounds is `Sized`. Assume that an explicit
-                // `Sized` bound is there intentionally and we don't need to suggest relaxing it.
-                param
-                    .bounds
-                    .iter()
-                    .all(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) != sized_trait)
-            })
-            .next();
+        let param = generics.params.iter().filter(|param| param.span == span).find(|param| {
+            // Check that none of the explicit trait bounds is `Sized`. Assume that an explicit
+            // `Sized` bound is there intentionally and we don't need to suggest relaxing it.
+            param
+                .bounds
+                .iter()
+                .all(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) != sized_trait)
+        });
         let param = match param {
             Some(param) => param,
             _ => return,
index b4fd851f456361d5e841a59ad5c1bdfeb2fe3fd2..b21936a00b04fae8c104dd81668dc4992de6af37 100644 (file)
@@ -151,7 +151,7 @@ fn note_obligation_cause_for_async_await(
         outer_generator: Option<DefId>,
         trait_ref: ty::TraitRef<'tcx>,
         target_ty: Ty<'tcx>,
-        typeck_results: &ty::TypeckResults<'tcx>,
+        typeck_results: Option<&ty::TypeckResults<'tcx>>,
         obligation: &PredicateObligation<'tcx>,
         next_code: Option<&ObligationCauseCode<'tcx>>,
     );
@@ -1422,6 +1422,9 @@ fn maybe_note_obligation_cause_for_async_await(
         while let Some(code) = next_code {
             debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code);
             match code {
+                ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => {
+                    next_code = Some(parent_code.as_ref());
+                }
                 ObligationCauseCode::DerivedObligation(derived_obligation)
                 | ObligationCauseCode::BuiltinDerivedObligation(derived_obligation)
                 | ObligationCauseCode::ImplDerivedObligation(derived_obligation) => {
@@ -1460,11 +1463,7 @@ fn maybe_note_obligation_cause_for_async_await(
         }
 
         // Only continue if a generator was found.
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: generator={:?} trait_ref={:?} \
-                target_ty={:?}",
-            generator, trait_ref, target_ty
-        );
+        debug!(?generator, ?trait_ref, ?target_ty, "maybe_note_obligation_cause_for_async_await");
         let (generator_did, trait_ref, target_ty) = match (generator, trait_ref, target_ty) {
             (Some(generator_did), Some(trait_ref), Some(target_ty)) => {
                 (generator_did, trait_ref, target_ty)
@@ -1474,16 +1473,8 @@ fn maybe_note_obligation_cause_for_async_await(
 
         let span = self.tcx.def_span(generator_did);
 
-        // Do not ICE on closure typeck (#66868).
-        if !generator_did.is_local() {
-            return false;
-        }
-
-        // Get the typeck results from the infcx if the generator is the function we are
-        // currently type-checking; otherwise, get them by performing a query.
-        // This is needed to avoid cycles.
         let in_progress_typeck_results = self.in_progress_typeck_results.map(|t| t.borrow());
-        let generator_did_root = self.tcx.closure_base_def_id(generator_did);
+        let generator_did_root = self.tcx.typeck_root_def_id(generator_did);
         debug!(
             "maybe_note_obligation_cause_for_async_await: generator_did={:?} \
              generator_did_root={:?} in_progress_typeck_results.hir_owner={:?} span={:?}",
@@ -1492,14 +1483,6 @@ fn maybe_note_obligation_cause_for_async_await(
             in_progress_typeck_results.as_ref().map(|t| t.hir_owner),
             span
         );
-        let query_typeck_results;
-        let typeck_results: &TypeckResults<'tcx> = match &in_progress_typeck_results {
-            Some(t) if t.hir_owner.to_def_id() == generator_did_root => t,
-            _ => {
-                query_typeck_results = self.tcx.typeck(generator_did.expect_local());
-                &query_typeck_results
-            }
-        };
 
         let generator_body = generator_did
             .as_local()
@@ -1542,51 +1525,59 @@ fn maybe_note_obligation_cause_for_async_await(
         let mut interior_or_upvar_span = None;
         let mut interior_extra_info = None;
 
-        if let Some(upvars) = self.tcx.upvars_mentioned(generator_did) {
-            interior_or_upvar_span = upvars.iter().find_map(|(upvar_id, upvar)| {
-                let upvar_ty = typeck_results.node_type(*upvar_id);
-                let upvar_ty = self.resolve_vars_if_possible(upvar_ty);
-                if ty_matches(ty::Binder::dummy(upvar_ty)) {
-                    Some(GeneratorInteriorOrUpvar::Upvar(upvar.span))
-                } else {
-                    None
-                }
-            });
+        // Get the typeck results from the infcx if the generator is the function we are currently
+        // type-checking; otherwise, get them by performing a query.  This is needed to avoid
+        // cycles. If we can't use resolved types because the generator comes from another crate,
+        // we still provide a targeted error but without all the relevant spans.
+        let query_typeck_results;
+        let typeck_results: Option<&TypeckResults<'tcx>> = match &in_progress_typeck_results {
+            Some(t) if t.hir_owner.to_def_id() == generator_did_root => Some(&t),
+            _ if generator_did.is_local() => {
+                query_typeck_results = self.tcx.typeck(generator_did.expect_local());
+                Some(&query_typeck_results)
+            }
+            _ => None, // Do not ICE on closure typeck (#66868).
         };
+        if let Some(typeck_results) = typeck_results {
+            if let Some(upvars) = self.tcx.upvars_mentioned(generator_did) {
+                interior_or_upvar_span = upvars.iter().find_map(|(upvar_id, upvar)| {
+                    let upvar_ty = typeck_results.node_type(*upvar_id);
+                    let upvar_ty = self.resolve_vars_if_possible(upvar_ty);
+                    if ty_matches(ty::Binder::dummy(upvar_ty)) {
+                        Some(GeneratorInteriorOrUpvar::Upvar(upvar.span))
+                    } else {
+                        None
+                    }
+                });
+            };
 
-        // The generator interior types share the same binders
-        if let Some(cause) =
-            typeck_results.generator_interior_types.as_ref().skip_binder().iter().find(
-                |ty::GeneratorInteriorTypeCause { ty, .. }| {
-                    ty_matches(typeck_results.generator_interior_types.rebind(ty))
-                },
-            )
-        {
-            // Check to see if any awaited expressions have the target type.
-            let from_awaited_ty = visitor
-                .awaits
-                .into_iter()
-                .map(|id| hir.expect_expr(id))
-                .find(|await_expr| {
-                    let ty = typeck_results.expr_ty_adjusted(&await_expr);
-                    debug!(
-                        "maybe_note_obligation_cause_for_async_await: await_expr={:?}",
-                        await_expr
-                    );
-                    ty_matches(ty::Binder::dummy(ty))
-                })
-                .map(|expr| expr.span);
-            let ty::GeneratorInteriorTypeCause { span, scope_span, yield_span, expr, .. } = cause;
+            // The generator interior types share the same binders
+            if let Some(cause) =
+                typeck_results.generator_interior_types.as_ref().skip_binder().iter().find(
+                    |ty::GeneratorInteriorTypeCause { ty, .. }| {
+                        ty_matches(typeck_results.generator_interior_types.rebind(ty))
+                    },
+                )
+            {
+                // Check to see if any awaited expressions have the target type.
+                let from_awaited_ty = visitor
+                    .awaits
+                    .into_iter()
+                    .map(|id| hir.expect_expr(id))
+                    .find(|await_expr| {
+                        ty_matches(ty::Binder::dummy(typeck_results.expr_ty_adjusted(&await_expr)))
+                    })
+                    .map(|expr| expr.span);
+                let ty::GeneratorInteriorTypeCause { span, scope_span, yield_span, expr, .. } =
+                    cause;
 
-            interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(*span));
-            interior_extra_info = Some((*scope_span, *yield_span, *expr, from_awaited_ty));
-        };
+                interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(*span));
+                interior_extra_info = Some((*scope_span, *yield_span, *expr, from_awaited_ty));
+            };
+        } else {
+            interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(span));
+        }
 
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: interior_or_upvar={:?} \
-                generator_interior_types={:?}",
-            interior_or_upvar_span, typeck_results.generator_interior_types
-        );
         if let Some(interior_or_upvar_span) = interior_or_upvar_span {
             self.note_obligation_cause_for_async_await(
                 err,
@@ -1617,7 +1608,7 @@ fn note_obligation_cause_for_async_await(
         outer_generator: Option<DefId>,
         trait_ref: ty::TraitRef<'tcx>,
         target_ty: Ty<'tcx>,
-        typeck_results: &ty::TypeckResults<'tcx>,
+        typeck_results: Option<&ty::TypeckResults<'tcx>>,
         obligation: &PredicateObligation<'tcx>,
         next_code: Option<&ObligationCauseCode<'tcx>>,
     ) {
@@ -1828,7 +1819,7 @@ fn note_obligation_cause_for_async_await(
                         // Look at the last interior type to get a span for the `.await`.
                         debug!(
                             "note_obligation_cause_for_async_await generator_interior_types: {:#?}",
-                            typeck_results.generator_interior_types
+                            typeck_results.as_ref().map(|t| &t.generator_interior_types)
                         );
                         explain_yield(interior_span, yield_span, scope_span);
                     }
@@ -1849,10 +1840,14 @@ fn note_obligation_cause_for_async_await(
                             // ^^^^^^^ a temporary `&T` created inside this method call due to `&self`
                             // ```
                             //
-                            let is_region_borrow = typeck_results
-                                .expr_adjustments(expr)
-                                .iter()
-                                .any(|adj| adj.is_region_borrow());
+                            let is_region_borrow = if let Some(typeck_results) = typeck_results {
+                                typeck_results
+                                    .expr_adjustments(expr)
+                                    .iter()
+                                    .any(|adj| adj.is_region_borrow())
+                            } else {
+                                false
+                            };
 
                             // ```rust
                             // struct Foo(*const u8);
@@ -1865,15 +1860,16 @@ fn note_obligation_cause_for_async_await(
                                     DefKind::Fn | DefKind::Ctor(..) => target_ty.is_unsafe_ptr(),
                                     _ => false,
                                 };
-
-                            if (typeck_results.is_method_call(e) && is_region_borrow)
-                                || is_raw_borrow_inside_fn_like_call
-                            {
-                                err.span_help(
-                                    parent_span,
-                                    "consider moving this into a `let` \
+                            if let Some(typeck_results) = typeck_results {
+                                if (typeck_results.is_method_call(e) && is_region_borrow)
+                                    || is_raw_borrow_inside_fn_like_call
+                                {
+                                    err.span_help(
+                                        parent_span,
+                                        "consider moving this into a `let` \
                         binding to create a shorter lived borrow",
-                                );
+                                    );
+                                }
                             }
                         }
                     }
index 465d1465d5d3538325def6ae9dcf226b730f9aa6..e121837c987ae9b694ea1b45281abca63da8e8c7 100644 (file)
@@ -126,10 +126,7 @@ pub fn new_ignoring_regions() -> FulfillmentContext<'tcx> {
     }
 
     /// Attempts to select obligations using `selcx`.
-    fn select(
-        &mut self,
-        selcx: &mut SelectionContext<'a, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+    fn select(&mut self, selcx: &mut SelectionContext<'a, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
         let span = debug_span!("select", obligation_forest_size = ?self.predicates.len());
         let _enter = span.enter();
 
@@ -163,7 +160,7 @@ fn select(
             errors.len()
         );
 
-        if errors.is_empty() { Ok(()) } else { Err(errors) }
+        errors
     }
 }
 
@@ -223,41 +220,36 @@ fn register_predicate_obligation(
             .register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] });
     }
 
-    fn select_all_or_error(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
-        self.select_where_possible(infcx)?;
-
-        let errors: Vec<_> = self
-            .predicates
-            .to_errors(CodeAmbiguity)
-            .into_iter()
-            .map(to_fulfillment_error)
-            .collect();
-        if errors.is_empty() { Ok(()) } else { Err(errors) }
+    fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
+        {
+            let errors = self.select_where_possible(infcx);
+            if !errors.is_empty() {
+                return errors;
+            }
+        }
+
+        self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect()
     }
 
     fn select_all_with_constness_or_error(
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
         constness: rustc_hir::Constness,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
-        self.select_with_constness_where_possible(infcx, constness)?;
-
-        let errors: Vec<_> = self
-            .predicates
-            .to_errors(CodeAmbiguity)
-            .into_iter()
-            .map(to_fulfillment_error)
-            .collect();
-        if errors.is_empty() { Ok(()) } else { Err(errors) }
+    ) -> Vec<FulfillmentError<'tcx>> {
+        {
+            let errors = self.select_with_constness_where_possible(infcx, constness);
+            if !errors.is_empty() {
+                return errors;
+            }
+        }
+
+        self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect()
     }
 
     fn select_where_possible(
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+    ) -> Vec<FulfillmentError<'tcx>> {
         let mut selcx = SelectionContext::new(infcx);
         self.select(&mut selcx)
     }
@@ -266,7 +258,7 @@ fn select_with_constness_where_possible(
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
         constness: hir::Constness,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+    ) -> Vec<FulfillmentError<'tcx>> {
         let mut selcx = SelectionContext::with_constness(infcx, constness);
         self.select(&mut selcx)
     }
index 428873b8d3dda8ae2676f93c3527f030deb8bbad..d4a586b0124a20b1bd790bebc98f0ccc991f0611 100644 (file)
@@ -180,8 +180,8 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
         // Note: we only assume something is `Copy` if we can
         // *definitively* show that it implements `Copy`. Otherwise,
         // assume it is move; linear is always ok.
-        match fulfill_cx.select_all_or_error(infcx) {
-            Ok(()) => {
+        match fulfill_cx.select_all_or_error(infcx).as_slice() {
+            [] => {
                 debug!(
                     "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success",
                     ty,
@@ -189,12 +189,12 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
                 );
                 true
             }
-            Err(e) => {
+            errors => {
                 debug!(
-                    "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} errors={:?}",
-                    ty,
-                    infcx.tcx.def_path_str(def_id),
-                    e
+                    ?ty,
+                    bound = %infcx.tcx.def_path_str(def_id),
+                    ?errors,
+                    "type_known_to_meet_bound_modulo_regions"
                 );
                 false
             }
@@ -410,7 +410,10 @@ pub fn fully_normalize<'a, 'tcx, T>(
     }
 
     debug!("fully_normalize: select_all_or_error start");
-    fulfill_cx.select_all_or_error(infcx)?;
+    let errors = fulfill_cx.select_all_or_error(infcx);
+    if !errors.is_empty() {
+        return Err(errors);
+    }
     debug!("fully_normalize: select_all_or_error complete");
     let resolved_value = infcx.resolve_vars_if_possible(normalized_value);
     debug!("fully_normalize: resolved_value={:?}", resolved_value);
@@ -441,7 +444,9 @@ pub fn impossible_predicates<'tcx>(
             fulfill_cx.register_predicate_obligation(&infcx, obligation);
         }
 
-        fulfill_cx.select_all_or_error(&infcx).is_err()
+        let errors = fulfill_cx.select_all_or_error(&infcx);
+
+        !errors.is_empty()
     });
     debug!("impossible_predicates = {:?}", result);
     result
@@ -748,6 +753,9 @@ fn vtable_trait_first_method_offset<'tcx>(
 ) -> usize {
     let (trait_to_be_found, trait_owning_vtable) = key;
 
+    // #90177
+    let trait_to_be_found_erased = tcx.erase_regions(trait_to_be_found);
+
     let vtable_segment_callback = {
         let mut vtable_base = 0;
 
@@ -757,7 +765,7 @@ fn vtable_trait_first_method_offset<'tcx>(
                     vtable_base += COMMON_VTABLE_ENTRIES.len();
                 }
                 VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
-                    if trait_ref == trait_to_be_found {
+                    if tcx.erase_regions(trait_ref) == trait_to_be_found_erased {
                         return ControlFlow::Break(vtable_base);
                     }
                     vtable_base += util::count_own_vtable_entries(tcx, trait_ref);
index db8a6d962049540f9e257c8e50b1e6a136697dfe..b8c66931cbe52ef093ce8cfb2629d29f72ec7268 100644 (file)
@@ -1734,7 +1734,7 @@ fn confirm_callable_candidate<'cx, 'tcx>(
         ty: ret_type,
     });
 
-    confirm_param_env_candidate(selcx, obligation, predicate, false)
+    confirm_param_env_candidate(selcx, obligation, predicate, true)
 }
 
 fn confirm_param_env_candidate<'cx, 'tcx>(
@@ -1754,8 +1754,18 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
     );
 
     let cache_projection = cache_entry.projection_ty;
-    let obligation_projection = obligation.predicate;
     let mut nested_obligations = Vec::new();
+    let obligation_projection = obligation.predicate;
+    let obligation_projection = ensure_sufficient_stack(|| {
+        normalize_with_depth_to(
+            selcx,
+            obligation.param_env,
+            obligation.cause.clone(),
+            obligation.recursion_depth + 1,
+            obligation_projection,
+            &mut nested_obligations,
+        )
+    });
     let cache_projection = if potentially_unnormalized_candidate {
         ensure_sufficient_stack(|| {
             normalize_with_depth_to(
@@ -1771,6 +1781,8 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
         cache_projection
     };
 
+    debug!(?cache_projection, ?obligation_projection);
+
     match infcx.at(cause, param_env).eq(cache_projection, obligation_projection) {
         Ok(InferOk { value: _, obligations }) => {
             nested_obligations.extend(obligations);
index b5398f8a4353b222599a49f008bb91a8ccc47035..0a85676f4315e36a88893a759201e899d87b0754 100644 (file)
@@ -77,10 +77,11 @@ fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
     let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?;
     debug_assert!(obligations.iter().all(|o| o.cause.body_id == dummy_body_id));
     fulfill_cx.register_predicate_obligations(infcx, obligations);
-    if let Err(e) = fulfill_cx.select_all_or_error(infcx) {
+    let errors = fulfill_cx.select_all_or_error(infcx);
+    if !errors.is_empty() {
         infcx.tcx.sess.diagnostic().delay_span_bug(
             DUMMY_SP,
-            &format!("errors selecting obligation during MIR typeck: {:?}", e),
+            &format!("errors selecting obligation during MIR typeck: {:?}", errors),
         );
     }
 
index 84721922c8dd738493f79e10186638894a32c9a4..2f1f7971a7926aa433352e92bfe306c48d26d8b0 100644 (file)
@@ -620,23 +620,37 @@ fn confirm_closure_candidate(
             _ => bug!("closure candidate for non-closure {:?}", obligation),
         };
 
+        let obligation_predicate = obligation.predicate.to_poly_trait_ref();
+        let Normalized { value: obligation_predicate, mut obligations } =
+            ensure_sufficient_stack(|| {
+                normalize_with_depth(
+                    self,
+                    obligation.param_env,
+                    obligation.cause.clone(),
+                    obligation.recursion_depth + 1,
+                    obligation_predicate,
+                )
+            });
+
         let trait_ref = self.closure_trait_ref_unnormalized(obligation, substs);
-        let Normalized { value: trait_ref, mut obligations } = ensure_sufficient_stack(|| {
-            normalize_with_depth(
-                self,
-                obligation.param_env,
-                obligation.cause.clone(),
-                obligation.recursion_depth + 1,
-                trait_ref,
-            )
-        });
+        let Normalized { value: trait_ref, obligations: trait_ref_obligations } =
+            ensure_sufficient_stack(|| {
+                normalize_with_depth(
+                    self,
+                    obligation.param_env,
+                    obligation.cause.clone(),
+                    obligation.recursion_depth + 1,
+                    trait_ref,
+                )
+            });
 
         debug!(?closure_def_id, ?trait_ref, ?obligations, "confirm closure candidate obligations");
 
+        obligations.extend(trait_ref_obligations);
         obligations.extend(self.confirm_poly_trait_refs(
             obligation.cause.clone(),
             obligation.param_env,
-            obligation.predicate.to_poly_trait_ref(),
+            obligation_predicate,
             trait_ref,
         )?);
 
@@ -948,52 +962,24 @@ fn confirm_builtin_unsize_candidate(
                 let tail_field_ty = tcx.type_of(tail_field.did);
 
                 let mut unsizing_params = GrowableBitSet::new_empty();
-                if tcx.features().relaxed_struct_unsize {
-                    for arg in tail_field_ty.walk(tcx) {
-                        if let Some(i) = maybe_unsizing_param_idx(arg) {
-                            unsizing_params.insert(i);
-                        }
-                    }
-
-                    // Ensure none of the other fields mention the parameters used
-                    // in unsizing.
-                    for field in prefix_fields {
-                        for arg in tcx.type_of(field.did).walk(tcx) {
-                            if let Some(i) = maybe_unsizing_param_idx(arg) {
-                                unsizing_params.remove(i);
-                            }
-                        }
+                for arg in tail_field_ty.walk(tcx) {
+                    if let Some(i) = maybe_unsizing_param_idx(arg) {
+                        unsizing_params.insert(i);
                     }
+                }
 
-                    if unsizing_params.is_empty() {
-                        return Err(Unimplemented);
-                    }
-                } else {
-                    let mut found = false;
-                    for arg in tail_field_ty.walk(tcx) {
+                // Ensure none of the other fields mention the parameters used
+                // in unsizing.
+                for field in prefix_fields {
+                    for arg in tcx.type_of(field.did).walk(tcx) {
                         if let Some(i) = maybe_unsizing_param_idx(arg) {
-                            unsizing_params.insert(i);
-                            found = true;
+                            unsizing_params.remove(i);
                         }
                     }
-                    if !found {
-                        return Err(Unimplemented);
-                    }
+                }
 
-                    // Ensure none of the other fields mention the parameters used
-                    // in unsizing.
-                    // FIXME(eddyb) cache this (including computing `unsizing_params`)
-                    // by putting it in a query; it would only need the `DefId` as it
-                    // looks at declared field types, not anything substituted.
-                    for field in prefix_fields {
-                        for arg in tcx.type_of(field.did).walk(tcx) {
-                            if let Some(i) = maybe_unsizing_param_idx(arg) {
-                                if unsizing_params.contains(i) {
-                                    return Err(Unimplemented);
-                                }
-                            }
-                        }
-                    }
+                if unsizing_params.is_empty() {
+                    return Err(Unimplemented);
                 }
 
                 // Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`.
index 1b26e38fe0e4d437b0f5245d16949e8c6c72fc87..481bfa4a26b36f6c79b1ce3db2833bebdcd8f085 100644 (file)
@@ -320,10 +320,7 @@ pub fn is_intercrate(&self) -> bool {
 
     /// Returns `true` if the trait predicate is considerd `const` to this selection context.
     pub fn is_trait_predicate_const(&self, pred: ty::TraitPredicate<'_>) -> bool {
-        match pred.constness {
-            ty::BoundConstness::ConstIfConst if self.is_in_const_context => true,
-            _ => false,
-        }
+        matches!(pred.constness, ty::BoundConstness::ConstIfConst) && self.is_in_const_context
     }
 
     /// Returns `true` if the predicate is considered `const` to
@@ -1547,8 +1544,9 @@ fn candidate_should_be_dropped_in_favor_of(
         // Check if a bound would previously have been removed when normalizing
         // the param_env so that it can be given the lowest priority. See
         // #50825 for the motivation for this.
-        let is_global =
-            |cand: &ty::PolyTraitRef<'_>| cand.is_known_global() && !cand.has_late_bound_regions();
+        let is_global = |cand: &ty::PolyTraitRef<'tcx>| {
+            cand.is_global(self.infcx.tcx) && !cand.has_late_bound_regions()
+        };
 
         // (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`,
         // and `DiscriminantKindCandidate` to anything else.
index f9867f0671e59fbd7478629fcd114f4dfea652de..f81a74a67dce57626d4fbd66d8cd4365ff50bc02 100644 (file)
@@ -225,8 +225,18 @@ fn fulfill_implication<'a, 'tcx>(
         for oblig in obligations.chain(more_obligations) {
             fulfill_cx.register_predicate_obligation(&infcx, oblig);
         }
-        match fulfill_cx.select_all_or_error(infcx) {
-            Err(errors) => {
+        match fulfill_cx.select_all_or_error(infcx).as_slice() {
+            [] => {
+                debug!(
+                    "fulfill_implication: an impl for {:?} specializes {:?}",
+                    source_trait_ref, target_trait_ref
+                );
+
+                // Now resolve the *substitution* we built for the target earlier, replacing
+                // the inference variables inside with whatever we got from fulfillment.
+                Ok(infcx.resolve_vars_if_possible(target_substs))
+            }
+            errors => {
                 // no dice!
                 debug!(
                     "fulfill_implication: for impls on {:?} and {:?}, \
@@ -238,17 +248,6 @@ fn fulfill_implication<'a, 'tcx>(
                 );
                 Err(())
             }
-
-            Ok(()) => {
-                debug!(
-                    "fulfill_implication: an impl for {:?} specializes {:?}",
-                    source_trait_ref, target_trait_ref
-                );
-
-                // Now resolve the *substitution* we built for the target earlier, replacing
-                // the inference variables inside with whatever we got from fulfillment.
-                Ok(infcx.resolve_vars_if_possible(target_substs))
-            }
         }
     })
 }
index a398e847b935458a003fab06e30ed423802e255c..3d71382227868df2c1ccd43ddb0cbafa19ece152 100644 (file)
@@ -103,7 +103,7 @@ fn type_marked_structural(
     //
     // 2. We are sometimes doing future-incompatibility lints for
     //    now, so we do not want unconditional errors here.
-    fulfillment_cx.select_all_or_error(infcx).is_ok()
+    fulfillment_cx.select_all_or_error(infcx).is_empty()
 }
 
 /// This implements the traversal over the structure of a given type to try to
index 37e007337374fd2553af77fcff1f307c2062e2c1..92f2760e62c7e86ef62e460bc320126f73cb996d 100644 (file)
@@ -128,9 +128,9 @@ fn compute_implied_outlives_bounds<'tcx>(
 
     // Ensure that those obligations that we had to solve
     // get solved *here*.
-    match fulfill_cx.select_all_or_error(infcx) {
-        Ok(()) => Ok(implied_bounds),
-        Err(_) => Err(NoSolution),
+    match fulfill_cx.select_all_or_error(infcx).as_slice() {
+        [] => Ok(implied_bounds),
+        _ => Err(NoSolution),
     }
 }
 
index 98415a84c569bc0191dadf2bf06e08f7788a5dae..3f66e5b4ebfbeb80c2894201bd3d153e2c58f974 100644 (file)
 type NeedsDropResult<T> = Result<T, AlwaysRequiresDrop>;
 
 fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-    let adt_components =
-        move |adt_def: &ty::AdtDef, _| tcx.adt_drop_tys(adt_def.did).map(|tys| tys.iter());
-
     // If we don't know a type doesn't need drop, for example if it's a type
     // parameter without a `Copy` bound, then we conservatively return that it
     // needs drop.
-    let res =
-        NeedsDropTypes::new(tcx, query.param_env, query.value, adt_components).next().is_some();
+    let adt_has_dtor =
+        |adt_def: &ty::AdtDef| adt_def.destructor(tcx).map(|_| DtorType::Significant);
+    let res = drop_tys_helper(tcx, query.value, query.param_env, adt_has_dtor).next().is_some();
 
     debug!("needs_drop_raw({:?}) = {:?}", query, res);
     res
@@ -29,12 +27,10 @@ fn has_significant_drop_raw<'tcx>(
     tcx: TyCtxt<'tcx>,
     query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
 ) -> bool {
-    let significant_drop_fields = move |adt_def: &ty::AdtDef, _| {
-        tcx.adt_significant_drop_tys(adt_def.did).map(|tys| tys.iter())
-    };
-    let res = NeedsDropTypes::new(tcx, query.param_env, query.value, significant_drop_fields)
-        .next()
-        .is_some();
+    let res =
+        drop_tys_helper(tcx, query.value, query.param_env, adt_consider_insignificant_dtor(tcx))
+            .next()
+            .is_some();
     debug!("has_significant_drop_raw({:?}) = {:?}", query, res);
     res
 }
@@ -145,10 +141,8 @@ fn next(&mut self) -> Option<NeedsDropResult<Ty<'tcx>>> {
                             Ok(tys) => tys,
                         };
                         for required_ty in tys {
-                            let subst_ty = tcx.normalize_erasing_regions(
-                                self.param_env,
-                                required_ty.subst(tcx, substs),
-                            );
+                            let subst_ty =
+                                tcx.normalize_erasing_regions(self.param_env, required_ty);
                             queue_type(self, subst_ty);
                         }
                     }
@@ -187,23 +181,24 @@ enum DtorType {
 // Depending on the implentation of `adt_has_dtor`, it is used to check if the
 // ADT has a destructor or if the ADT only has a significant destructor. For
 // understanding significant destructor look at `adt_significant_drop_tys`.
-fn adt_drop_tys_helper<'tcx>(
+fn drop_tys_helper<'tcx>(
     tcx: TyCtxt<'tcx>,
-    def_id: DefId,
+    ty: Ty<'tcx>,
+    param_env: rustc_middle::ty::ParamEnv<'tcx>,
     adt_has_dtor: impl Fn(&ty::AdtDef) -> Option<DtorType>,
-) -> Result<&ty::List<Ty<'tcx>>, AlwaysRequiresDrop> {
+) -> impl Iterator<Item = NeedsDropResult<Ty<'tcx>>> {
     let adt_components = move |adt_def: &ty::AdtDef, substs: SubstsRef<'tcx>| {
         if adt_def.is_manually_drop() {
-            debug!("adt_drop_tys: `{:?}` is manually drop", adt_def);
+            debug!("drop_tys_helper: `{:?}` is manually drop", adt_def);
             return Ok(Vec::new().into_iter());
         } else if let Some(dtor_info) = adt_has_dtor(adt_def) {
             match dtor_info {
                 DtorType::Significant => {
-                    debug!("adt_drop_tys: `{:?}` implements `Drop`", adt_def);
+                    debug!("drop_tys_helper: `{:?}` implements `Drop`", adt_def);
                     return Err(AlwaysRequiresDrop);
                 }
                 DtorType::Insignificant => {
-                    debug!("adt_drop_tys: `{:?}` drop is insignificant", adt_def);
+                    debug!("drop_tys_helper: `{:?}` drop is insignificant", adt_def);
 
                     // Since the destructor is insignificant, we just want to make sure all of
                     // the passed in type parameters are also insignificant.
@@ -212,34 +207,27 @@ fn adt_drop_tys_helper<'tcx>(
                 }
             }
         } else if adt_def.is_union() {
-            debug!("adt_drop_tys: `{:?}` is a union", adt_def);
+            debug!("drop_tys_helper: `{:?}` 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())
+        Ok(adt_def
+            .all_fields()
+            .map(|field| {
+                let r = tcx.type_of(field.did).subst(tcx, substs);
+                debug!("drop_tys_helper: Subst into {:?} with {:?} gettng {:?}", field, substs, r);
+                r
+            })
+            .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))
+    NeedsDropTypes::new(tcx, param_env, ty, adt_components)
 }
 
-fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
-    // This is for the "needs_drop" query, that considers all `Drop` impls, therefore all dtors are
-    // significant.
-    let adt_has_dtor =
-        |adt_def: &ty::AdtDef| adt_def.destructor(tcx).map(|_| DtorType::Significant);
-    adt_drop_tys_helper(tcx, def_id, adt_has_dtor)
-}
-
-fn adt_significant_drop_tys(
-    tcx: TyCtxt<'_>,
-    def_id: DefId,
-) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
-    let adt_has_dtor = |adt_def: &ty::AdtDef| {
+fn adt_consider_insignificant_dtor<'tcx>(
+    tcx: TyCtxt<'tcx>,
+) -> impl Fn(&ty::AdtDef) -> Option<DtorType> + 'tcx {
+    move |adt_def: &ty::AdtDef| {
         let is_marked_insig = tcx.has_attr(adt_def.did, sym::rustc_insignificant_dtor);
         if is_marked_insig {
             // In some cases like `std::collections::HashMap` where the struct is a wrapper around
@@ -256,8 +244,31 @@ fn adt_significant_drop_tys(
             // treat this as the simple case of Drop impl for type.
             None
         }
-    };
-    adt_drop_tys_helper(tcx, def_id, adt_has_dtor)
+    }
+}
+
+fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
+    // This is for the "adt_drop_tys" query, that considers all `Drop` impls, therefore all dtors are
+    // significant.
+    let adt_has_dtor =
+        |adt_def: &ty::AdtDef| adt_def.destructor(tcx).map(|_| DtorType::Significant);
+    drop_tys_helper(tcx, tcx.type_of(def_id), tcx.param_env(def_id), adt_has_dtor)
+        .collect::<Result<Vec<_>, _>>()
+        .map(|components| tcx.intern_type_list(&components))
+}
+
+fn adt_significant_drop_tys(
+    tcx: TyCtxt<'_>,
+    def_id: DefId,
+) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
+    drop_tys_helper(
+        tcx,
+        tcx.type_of(def_id),
+        tcx.param_env(def_id),
+        adt_consider_insignificant_dtor(tcx),
+    )
+    .collect::<Result<Vec<_>, _>>()
+    .map(|components| tcx.intern_type_list(&components))
 }
 
 pub(crate) fn provide(providers: &mut ty::query::Providers) {
index bc77c94809eb58ca47c0f47932b3c6a0f20e08d0..af3706f886e9cbce53fb4e6be54c5ee1872432e4 100644 (file)
@@ -247,6 +247,7 @@ fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
 }
 
 /// See `ParamEnv` struct definition for details.
+#[instrument(level = "debug", skip(tcx))]
 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) {
@@ -274,9 +275,20 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
         predicates.extend(environment);
     }
 
+    // It's important that we include the default substs in unevaluated
+    // constants, since `Unevaluated` instances in predicates whose substs are None
+    // can lead to "duplicate" caller bounds candidates during trait selection,
+    // duplicate in the sense that both have their default substs, but the
+    // candidate that resulted from a superpredicate still uses `None` in its
+    // `substs_` field of `Unevaluated` to indicate that it has its default substs,
+    // whereas the other candidate has `substs_: Some(default_substs)`, see
+    // issue #89334
+    predicates = tcx.expose_default_const_substs(predicates);
+
     let unnormalized_env =
         ty::ParamEnv::new(tcx.intern_predicates(&predicates), traits::Reveal::UserFacing);
 
+    debug!("unnormalized_env caller bounds: {:?}", unnormalized_env.caller_bounds());
     let body_id = def_id
         .as_local()
         .map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
index 5befe44802f54a1341e140109ffb92625fffd426..2f187997b55de0fbf10a7028524a44649b5d3a68 100644 (file)
@@ -344,7 +344,7 @@ pub fn create_substs_for_generic_args<'a>(
                                             "reorder the arguments: {}: `<{}>`",
                                             param_types_present
                                                 .into_iter()
-                                                .map(|ord| format!("{}s", ord.to_string()))
+                                                .map(|ord| format!("{}s", ord))
                                                 .collect::<Vec<String>>()
                                                 .join(", then "),
                                             ordered_params
@@ -672,6 +672,17 @@ pub(crate) fn check_impl_trait(
                 err.span_label(span, "explicit generic argument not allowed");
             }
 
+            err.note(
+                "see issue #83701 <https://github.com/rust-lang/rust/issues/83701> \
+                 for more information",
+            );
+            if tcx.sess.is_nightly_build() {
+                err.help(
+                    "add `#![feature(explicit_generic_args_with_impl_trait)]` \
+                     to the crate attributes to enable",
+                );
+            }
+
             err.emit();
         }
 
index c17c42c497fb36e9223b85a87ee5f4158749728d..a8160313228b6381b02f6e1633fce45ae07e639b 100644 (file)
@@ -6,7 +6,6 @@
 use rustc_infer::traits::Obligation;
 use rustc_middle::ty::{self, ToPredicate, Ty, TyS};
 use rustc_span::{MultiSpan, Span};
-use rustc_trait_selection::opaque_types::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::{
     IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
index 78849b276d6bfb80f610c574a021f4b7efb91d3a..511a2d7ddacf96e42f453690267c1094f0e995ef 100644 (file)
@@ -436,11 +436,8 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError) {
                     // Very crude check to see whether the expression must be wrapped
                     // in parentheses for the suggestion to work (issue #89497).
                     // Can/should be extended in the future.
-                    let needs_parens = !has_parens
-                        && match self.expr.kind {
-                            hir::ExprKind::Cast(..) => true,
-                            _ => false,
-                        };
+                    let needs_parens =
+                        !has_parens && matches!(self.expr.kind, hir::ExprKind::Cast(..));
 
                     let mut suggestion = vec![(self.expr.span.shrink_to_lo(), sugg)];
                     if needs_parens {
index 66316214e5e6644d58cfcae46557e4c6a0e432d0..f0a77cb39a62273b1fb3a18e9faa091da3b20840 100644 (file)
@@ -21,7 +21,6 @@
 use rustc_span::symbol::sym;
 use rustc_span::{self, MultiSpan, Span};
 use rustc_target::spec::abi::Abi;
-use rustc_trait_selection::opaque_types::InferCtxtExt as _;
 use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
 use rustc_ty_utils::representability::{self, Representability};
@@ -664,8 +663,9 @@ fn check_opaque_meets_bounds<'tcx>(
 
         // Check that all obligations are satisfied by the implementation's
         // version.
-        if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(errors, None, false);
+        let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
+        if !errors.is_empty() {
+            infcx.report_fulfillment_errors(&errors, None, false);
         }
 
         // Finally, resolve all regions. This catches wily misuses of
index 410ac24b1f19c84a8659e5186f31f5c264db201d..f7accbb430caae8375fb5a6c318244009f0b15d7 100644 (file)
@@ -92,7 +92,7 @@ fn check_closure(
 
         let parent_substs = InternalSubsts::identity_for_item(
             self.tcx,
-            self.tcx.closure_base_def_id(expr_def_id.to_def_id()),
+            self.tcx.typeck_root_def_id(expr_def_id.to_def_id()),
         );
 
         let tupled_upvars_ty = self.infcx.next_ty_var(TypeVariableOrigin {
index ad65a0ba62a8cc8b0372214abbc2da99f575a96c..28712e0658269d5338fdd39ace5c3a713cc6838e 100644 (file)
@@ -950,7 +950,7 @@ pub fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool {
             };
             let mut fcx = traits::FulfillmentContext::new_in_snapshot();
             fcx.register_predicate_obligations(self, ok.obligations);
-            fcx.select_where_possible(&self).is_ok()
+            fcx.select_where_possible(&self).is_empty()
         })
     }
 
index d5b631df058aef9c12428677dbfa52f7aec344d3..3eadb3f2363d2cdf7645292b1f1a3c310b41aaa1 100644 (file)
@@ -391,8 +391,9 @@ fn compare_predicate_entailment<'tcx>(
 
         // Check that all obligations are satisfied by the implementation's
         // version.
-        if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(errors, None, false);
+        let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
+        if !errors.is_empty() {
+            infcx.report_fulfillment_errors(&errors, None, false);
             return Err(ErrorReported);
         }
 
@@ -453,6 +454,7 @@ fn check_region_bounds_on_impl_item<'tcx>(
     Ok(())
 }
 
+#[instrument(level = "debug", skip(infcx))]
 fn extract_spans_for_error_reporting<'a, 'tcx>(
     infcx: &infer::InferCtxt<'a, 'tcx>,
     terr: &TypeError<'_>,
@@ -1093,8 +1095,9 @@ fn compare_const_param_types<'tcx>(
 
         // Check that all obligations are satisfied by the implementation's
         // version.
-        if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(errors, None, false);
+        let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
+        if !errors.is_empty() {
+            infcx.report_fulfillment_errors(&errors, None, false);
             return;
         }
 
@@ -1209,8 +1212,9 @@ fn compare_type_predicate_entailment<'tcx>(
 
         // Check that all obligations are satisfied by the implementation's
         // version.
-        if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(errors, None, false);
+        let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
+        if !errors.is_empty() {
+            infcx.report_fulfillment_errors(&errors, None, false);
             return Err(ErrorReported);
         }
 
@@ -1426,10 +1430,10 @@ pub fn check_type_bounds<'tcx>(
 
         // Check that all obligations are satisfied by the implementation's
         // version.
-        if let Err(ref errors) =
-            inh.fulfillment_cx.borrow_mut().select_all_with_constness_or_error(&infcx, constness)
-        {
-            infcx.report_fulfillment_errors(errors, None, false);
+        let errors =
+            inh.fulfillment_cx.borrow_mut().select_all_with_constness_or_error(&infcx, constness);
+        if !errors.is_empty() {
+            infcx.report_fulfillment_errors(&errors, None, false);
             return Err(ErrorReported);
         }
 
index 2b3672211e4f582e951922e2ff2c555c4b36866f..9bbe52591472885655471958f9bf7632c42385b4 100644 (file)
@@ -29,6 +29,7 @@ pub fn emit_coerce_suggestions(
         expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
     ) {
         self.annotate_expected_due_to_let_ty(err, expr);
+        self.suggest_box_deref(err, expr, expected, expr_ty);
         self.suggest_compatible_variants(err, expr, expected, expr_ty);
         self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr);
         if self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) {
@@ -167,6 +168,23 @@ fn annotate_expected_due_to_let_ty(
         }
     }
 
+    fn suggest_box_deref(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        expr: &hir::Expr<'_>,
+        expected: Ty<'tcx>,
+        expr_ty: Ty<'tcx>,
+    ) {
+        if expr_ty.is_box() && expr_ty.boxed_ty() == expected {
+            err.span_suggestion_verbose(
+                expr.span.shrink_to_lo(),
+                "try dereferencing the `Box`",
+                "*".to_string(),
+                Applicability::MachineApplicable,
+            );
+        }
+    }
+
     /// If the expected type is an enum (Issue #55250) with any variants whose
     /// sole field is of the found type, suggest such variants. (Issue #42764)
     fn suggest_compatible_variants(
@@ -428,7 +446,7 @@ pub fn check_ref(
                 (&ty::Str, &ty::Array(arr, _) | &ty::Slice(arr)) if arr == self.tcx.types.u8 => {
                     if let hir::ExprKind::Lit(_) = expr.kind {
                         if let Ok(src) = sm.span_to_snippet(sp) {
-                            if let Some(_) = replace_prefix(&src, "b\"", "\"") {
+                            if replace_prefix(&src, "b\"", "\"").is_some() {
                                 let pos = sp.lo() + BytePos(1);
                                 return Some((
                                     sp.with_hi(pos),
@@ -444,7 +462,7 @@ pub fn check_ref(
                 (&ty::Array(arr, _) | &ty::Slice(arr), &ty::Str) if arr == self.tcx.types.u8 => {
                     if let hir::ExprKind::Lit(_) = expr.kind {
                         if let Ok(src) = sm.span_to_snippet(sp) {
-                            if let Some(_) = replace_prefix(&src, "\"", "b\"") {
+                            if replace_prefix(&src, "\"", "b\"").is_some() {
                                 return Some((
                                     sp.shrink_to_lo(),
                                     "consider adding a leading `b`",
index fd150978f0074d8a5c4aea01e80090906b03221a..bfa0d92ab47ab9546bfde2ee8b4a42f886675343 100644 (file)
@@ -113,9 +113,10 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
             }
         }
 
-        if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) {
+        let errors = fulfillment_cx.select_all_or_error(&infcx);
+        if !errors.is_empty() {
             // this could be reached when we get lazy normalization
-            infcx.report_fulfillment_errors(errors, None, false);
+            infcx.report_fulfillment_errors(&errors, None, false);
             return Err(ErrorReported);
         }
 
index ab53d64e9bfb5810588cb805fb096a7a517c3616..a9c0b65a0981ee5f26372aef342ceb82dbd634e4 100644 (file)
@@ -30,6 +30,7 @@
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::Visitor;
 use rustc_hir::{ExprKind, QPath};
 use rustc_infer::infer;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -327,7 +328,9 @@ fn check_expr_kind(
             }
             ExprKind::DropTemps(e) => self.check_expr_with_expectation(e, expected),
             ExprKind::Array(args) => self.check_expr_array(args, expected, expr),
-            ExprKind::ConstBlock(ref anon_const) => self.to_const(anon_const).ty,
+            ExprKind::ConstBlock(ref anon_const) => {
+                self.check_expr_const_block(anon_const, expected, expr)
+            }
             ExprKind::Repeat(element, ref count) => {
                 self.check_expr_repeat(element, count, expected, expr)
             }
@@ -1170,6 +1173,24 @@ fn check_expr_array(
         self.tcx.mk_array(element_ty, args.len() as u64)
     }
 
+    fn check_expr_const_block(
+        &self,
+        anon_const: &'tcx hir::AnonConst,
+        expected: Expectation<'tcx>,
+        _expr: &'tcx hir::Expr<'tcx>,
+    ) -> Ty<'tcx> {
+        let body = self.tcx.hir().body(anon_const.body);
+
+        // Create a new function context.
+        let fcx = FnCtxt::new(self, self.param_env, body.value.hir_id);
+        crate::check::GatherLocalsVisitor::new(&fcx).visit_body(body);
+
+        let ty = fcx.check_expr_with_expectation(&body.value, expected);
+        fcx.require_type_is_sized(ty, body.value.span, traits::ConstSized);
+        fcx.write_ty(anon_const.hir_id, ty);
+        ty
+    }
+
     fn check_expr_repeat(
         &self,
         element: &'tcx hir::Expr<'tcx>,
@@ -1777,15 +1798,15 @@ fn check_field(
                         // Save the index of all fields regardless of their visibility in case
                         // of error recovery.
                         self.write_field_index(expr.hir_id, index);
+                        let adjustments = self.adjust_steps(&autoderef);
                         if field.vis.is_accessible_from(def_scope, self.tcx) {
-                            let adjustments = self.adjust_steps(&autoderef);
                             self.apply_adjustments(base, adjustments);
                             self.register_predicates(autoderef.into_obligations());
 
                             self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None);
                             return field_ty;
                         }
-                        private_candidate = Some((base_def.did, field_ty));
+                        private_candidate = Some((adjustments, base_def.did, field_ty));
                     }
                 }
                 ty::Tuple(tys) => {
@@ -1808,7 +1829,10 @@ fn check_field(
         }
         self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
 
-        if let Some((did, field_ty)) = private_candidate {
+        if let Some((adjustments, did, field_ty)) = private_candidate {
+            // (#90483) apply adjustments to avoid ExprUseVisitor from
+            // creating erroneous projection.
+            self.apply_adjustments(base, adjustments);
             self.ban_private_field_access(expr, expr_t, field, did);
             return field_ty;
         }
@@ -2134,8 +2158,7 @@ fn get_field_candidates(
     ) -> Option<(&Vec<ty::FieldDef>, SubstsRef<'tcx>)> {
         debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_t);
 
-        let mut autoderef = self.autoderef(span, base_t);
-        while let Some((base_t, _)) = autoderef.next() {
+        for (base_t, _) in self.autoderef(span, base_t) {
             match base_t.kind() {
                 ty::Adt(base_def, substs) if !base_def.is_enum() => {
                     let fields = &base_def.non_enum_variant().fields;
index 296e45337ed1035b3ed1868396f371ba6b045c86..e5da33d113e7c48e95ab6e626d4e0dc8ff0711f8 100644 (file)
@@ -176,7 +176,7 @@ fn fallback_opaque_type_vars(&self, ty: Ty<'tcx>) -> bool {
             .type_var_origin(ty)
             .map(|origin| origin.span)
             .unwrap_or(rustc_span::DUMMY_SP);
-        let oty = self.inner.borrow().opaque_types_vars.get(ty).map(|v| *v);
+        let oty = self.inner.borrow().opaque_types_vars.get(ty).copied();
         if let Some(opaque_ty) = oty {
             debug!(
                 "fallback_opaque_type_vars(ty={:?}): falling back to opaque type {:?}",
index 41e43321a8f0a07da9b0326dc6c53a48dc98f5cf..93b2a595259722923447a3a5de4bbdc192c8f498 100644 (file)
@@ -35,7 +35,6 @@
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{self, BytePos, MultiSpan, Span};
 use rustc_trait_selection::infer::InferCtxtExt as _;
-use rustc_trait_selection::opaque_types::InferCtxtExt as _;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
 use rustc_trait_selection::traits::{
     self, ObligationCause, ObligationCauseCode, StatementAsExpression, TraitEngine, TraitEngineExt,
@@ -643,11 +642,12 @@ pub(in super::super) fn resolve_generator_interiors(&self, def_id: DefId) {
 
     #[instrument(skip(self), level = "debug")]
     pub(in super::super) fn select_all_obligations_or_error(&self) {
-        if let Err(errors) = self
+        let errors = self
             .fulfillment_cx
             .borrow_mut()
-            .select_all_with_constness_or_error(&self, self.inh.constness)
-        {
+            .select_all_with_constness_or_error(&self, self.inh.constness);
+
+        if !errors.is_empty() {
             self.report_fulfillment_errors(&errors, self.inh.body_id, false);
         }
     }
@@ -658,13 +658,13 @@ pub(in super::super) fn select_obligations_where_possible(
         fallback_has_occurred: bool,
         mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
     ) {
-        let result = self
+        let mut result = self
             .fulfillment_cx
             .borrow_mut()
             .select_with_constness_where_possible(self, self.inh.constness);
-        if let Err(mut errors) = result {
-            mutate_fulfillment_errors(&mut errors);
-            self.report_fulfillment_errors(&errors, self.inh.body_id, fallback_has_occurred);
+        if !result.is_empty() {
+            mutate_fulfillment_errors(&mut result);
+            self.report_fulfillment_errors(&result, self.inh.body_id, fallback_has_occurred);
         }
     }
 
@@ -794,14 +794,17 @@ pub(in super::super) fn expected_inputs_for_expected_output(
                         // we can.  We don't care if some things turn
                         // out unconstrained or ambiguous, as we're
                         // just trying to get hints here.
-                        self.save_and_restore_in_snapshot_flag(|_| {
+                        let errors = self.save_and_restore_in_snapshot_flag(|_| {
                             let mut fulfill = <dyn TraitEngine<'_>>::new(self.tcx);
                             for obligation in ok.obligations {
                                 fulfill.register_predicate_obligation(self, obligation);
                             }
                             fulfill.select_where_possible(self)
-                        })
-                        .map_err(|_| ())?;
+                        });
+
+                        if !errors.is_empty() {
+                            return Err(());
+                        }
                     }
                     Err(_) => return Err(()),
                 }
@@ -830,7 +833,6 @@ pub(in super::super) fn resolve_lang_item_path(
             self.tcx.type_of(def_id)
         };
         let substs = self.infcx.fresh_substs_for_item(span, def_id);
-        self.write_substs(hir_id, substs);
         let ty = item_ty.subst(self.tcx, substs);
 
         self.write_resolution(hir_id, Ok((def_kind, def_id)));
index 551522334aa00a7d9d328bdeb7a361c0f0e36854..7d9483201f6a547c5e3ae407e473a8ad19f7e729 100644 (file)
@@ -370,6 +370,8 @@ pub(in super::super) fn check_argument_types(
                 //    `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
                 let coerce_ty = expected.only_has_type(self).unwrap_or(formal_ty);
 
+                final_arg_types.push((i, checked_ty, coerce_ty));
+
                 // Cause selection errors caused by resolving a single argument to point at the
                 // argument and not the call. This is otherwise redundant with the `demand_coerce`
                 // call immediately after, but it lets us customize the span pointed to in the
@@ -377,38 +379,20 @@ pub(in super::super) fn check_argument_types(
                 let _ = self.resolve_vars_with_obligations_and_mutate_fulfillment(
                     coerce_ty,
                     |errors| {
-                        // This is not coming from a macro or a `derive`.
-                        if sp.desugaring_kind().is_none()
-                        && !arg.span.from_expansion()
-                        // Do not change the spans of `async fn`s.
-                        && !matches!(
-                            expr.kind,
-                            hir::ExprKind::Call(
-                                hir::Expr {
-                                    kind: hir::ExprKind::Path(hir::QPath::LangItem(_, _)),
-                                    ..
-                                },
-                                _
-                            )
-                        ) {
-                            for error in errors {
-                                error.obligation.cause.make_mut().span = arg.span;
-                                let code = error.obligation.cause.code.clone();
-                                error.obligation.cause.make_mut().code =
-                                    ObligationCauseCode::FunctionArgumentObligation {
-                                        arg_hir_id: arg.hir_id,
-                                        call_hir_id: expr.hir_id,
-                                        parent_code: Lrc::new(code),
-                                    };
-                            }
-                        }
+                        self.point_at_type_arg_instead_of_call_if_possible(errors, expr);
+                        self.point_at_arg_instead_of_call_if_possible(
+                            errors,
+                            &final_arg_types,
+                            expr,
+                            sp,
+                            args,
+                        );
                     },
                 );
 
                 // We're processing function arguments so we definitely want to use
                 // two-phase borrows.
                 self.demand_coerce(&arg, checked_ty, coerce_ty, None, AllowTwoPhase::Yes);
-                final_arg_types.push((i, checked_ty, coerce_ty));
 
                 // 3. Relate the expected type and the formal one,
                 //    if the expected type was used for the coercion.
@@ -973,45 +957,79 @@ fn point_at_arg_instead_of_call_if_possible(
                 continue;
             }
 
-            if let ty::PredicateKind::Trait(predicate) =
-                error.obligation.predicate.kind().skip_binder()
-            {
-                // Collect the argument position for all arguments that could have caused this
-                // `FulfillmentError`.
-                let mut referenced_in = final_arg_types
-                    .iter()
-                    .map(|&(i, checked_ty, _)| (i, checked_ty))
-                    .chain(final_arg_types.iter().map(|&(i, _, coerced_ty)| (i, coerced_ty)))
-                    .flat_map(|(i, ty)| {
-                        let ty = self.resolve_vars_if_possible(ty);
-                        // We walk the argument type because the argument's type could have
-                        // been `Option<T>`, but the `FulfillmentError` references `T`.
-                        if ty.walk(self.tcx).any(|arg| arg == predicate.self_ty().into()) {
-                            Some(i)
-                        } else {
-                            None
-                        }
-                    })
-                    .collect::<Vec<usize>>();
-
-                // Both checked and coerced types could have matched, thus we need to remove
-                // duplicates.
-
-                // We sort primitive type usize here and can use unstable sort
-                referenced_in.sort_unstable();
-                referenced_in.dedup();
-
-                if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) {
-                    // We make sure that only *one* argument matches the obligation failure
-                    // and we assign the obligation's span to its expression's.
-                    error.obligation.cause.make_mut().span = args[ref_in].span;
-                    let code = error.obligation.cause.code.clone();
-                    error.obligation.cause.make_mut().code =
-                        ObligationCauseCode::FunctionArgumentObligation {
-                            arg_hir_id: args[ref_in].hir_id,
-                            call_hir_id: expr.hir_id,
-                            parent_code: Lrc::new(code),
-                        };
+            // Peel derived obligation, because it's the type that originally
+            // started this inference chain that matters, not the one we wound
+            // up with at the end.
+            fn unpeel_to_top(
+                mut code: Lrc<ObligationCauseCode<'_>>,
+            ) -> Lrc<ObligationCauseCode<'_>> {
+                let mut result_code = code.clone();
+                loop {
+                    let parent = match &*code {
+                        ObligationCauseCode::BuiltinDerivedObligation(c)
+                        | ObligationCauseCode::ImplDerivedObligation(c)
+                        | ObligationCauseCode::DerivedObligation(c) => c.parent_code.clone(),
+                        _ => break,
+                    };
+                    result_code = std::mem::replace(&mut code, parent);
+                }
+                result_code
+            }
+            let self_: ty::subst::GenericArg<'_> = match &*unpeel_to_top(Lrc::new(error.obligation.cause.code.clone())) {
+                ObligationCauseCode::BuiltinDerivedObligation(code) |
+                ObligationCauseCode::ImplDerivedObligation(code) |
+                ObligationCauseCode::DerivedObligation(code) => {
+                    code.parent_trait_ref.self_ty().skip_binder().into()
+                }
+                _ if let ty::PredicateKind::Trait(predicate) =
+                    error.obligation.predicate.kind().skip_binder() => {
+                        predicate.self_ty().into()
+                    }
+                _ =>  continue,
+            };
+            let self_ = self.resolve_vars_if_possible(self_);
+
+            // Collect the argument position for all arguments that could have caused this
+            // `FulfillmentError`.
+            let mut referenced_in = final_arg_types
+                .iter()
+                .map(|&(i, checked_ty, _)| (i, checked_ty))
+                .chain(final_arg_types.iter().map(|&(i, _, coerced_ty)| (i, coerced_ty)))
+                .flat_map(|(i, ty)| {
+                    let ty = self.resolve_vars_if_possible(ty);
+                    // We walk the argument type because the argument's type could have
+                    // been `Option<T>`, but the `FulfillmentError` references `T`.
+                    if ty.walk(self.tcx).any(|arg| arg == self_) { Some(i) } else { None }
+                })
+                .collect::<Vec<usize>>();
+
+            // Both checked and coerced types could have matched, thus we need to remove
+            // duplicates.
+
+            // We sort primitive type usize here and can use unstable sort
+            referenced_in.sort_unstable();
+            referenced_in.dedup();
+
+            if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) {
+                // Do not point at the inside of a macro.
+                // That would often result in poor error messages.
+                if args[ref_in].span.from_expansion() {
+                    return;
+                }
+                // We make sure that only *one* argument matches the obligation failure
+                // and we assign the obligation's span to its expression's.
+                error.obligation.cause.make_mut().span = args[ref_in].span;
+                let code = error.obligation.cause.code.clone();
+                error.obligation.cause.make_mut().code =
+                    ObligationCauseCode::FunctionArgumentObligation {
+                        arg_hir_id: args[ref_in].hir_id,
+                        call_hir_id: expr.hir_id,
+                        parent_code: Lrc::new(code),
+                    };
+            } else if error.obligation.cause.make_mut().span == call_sp {
+                // Make function calls point at the callee, not the whole thing.
+                if let hir::ExprKind::Call(callee, _) = expr.kind {
+                    error.obligation.cause.make_mut().span = callee.span;
                 }
             }
         }
@@ -1027,34 +1045,32 @@ fn point_at_type_arg_instead_of_call_if_possible(
         call_expr: &'tcx hir::Expr<'tcx>,
     ) {
         if let hir::ExprKind::Call(path, _) = &call_expr.kind {
-            if let hir::ExprKind::Path(qpath) = &path.kind {
-                if let hir::QPath::Resolved(_, path) = &qpath {
-                    for error in errors {
-                        if let ty::PredicateKind::Trait(predicate) =
-                            error.obligation.predicate.kind().skip_binder()
+            if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &path.kind {
+                for error in errors {
+                    if let ty::PredicateKind::Trait(predicate) =
+                        error.obligation.predicate.kind().skip_binder()
+                    {
+                        // If any of the type arguments in this path segment caused the
+                        // `FulfillmentError`, point at its span (#61860).
+                        for arg in path
+                            .segments
+                            .iter()
+                            .filter_map(|seg| seg.args.as_ref())
+                            .flat_map(|a| a.args.iter())
                         {
-                            // If any of the type arguments in this path segment caused the
-                            // `FulfillmentError`, point at its span (#61860).
-                            for arg in path
-                                .segments
-                                .iter()
-                                .filter_map(|seg| seg.args.as_ref())
-                                .flat_map(|a| a.args.iter())
-                            {
-                                if let hir::GenericArg::Type(hir_ty) = &arg {
-                                    if let hir::TyKind::Path(hir::QPath::TypeRelative(..)) =
-                                        &hir_ty.kind
-                                    {
-                                        // Avoid ICE with associated types. As this is best
-                                        // effort only, it's ok to ignore the case. It
-                                        // would trigger in `is_send::<T::AssocType>();`
-                                        // from `typeck-default-trait-impl-assoc-type.rs`.
-                                    } else {
-                                        let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, hir_ty);
-                                        let ty = self.resolve_vars_if_possible(ty);
-                                        if ty == predicate.self_ty() {
-                                            error.obligation.cause.make_mut().span = hir_ty.span;
-                                        }
+                            if let hir::GenericArg::Type(hir_ty) = &arg {
+                                if let hir::TyKind::Path(hir::QPath::TypeRelative(..)) =
+                                    &hir_ty.kind
+                                {
+                                    // Avoid ICE with associated types. As this is best
+                                    // effort only, it's ok to ignore the case. It
+                                    // would trigger in `is_send::<T::AssocType>();`
+                                    // from `typeck-default-trait-impl-assoc-type.rs`.
+                                } else {
+                                    let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, hir_ty);
+                                    let ty = self.resolve_vars_if_possible(ty);
+                                    if ty == predicate.self_ty() {
+                                        error.obligation.cause.make_mut().span = hir_ty.span;
                                     }
                                 }
                             }
index 183ebc559ae42ba0cd1a978349246c882fca57e9..13f475cd9e02681073e542c3e961e3f373e5e6f5 100644 (file)
@@ -15,7 +15,7 @@
 use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
 use rustc_span::lev_distance;
 use rustc_span::symbol::{kw, sym, Ident};
-use rustc_span::{source_map, FileName, MultiSpan, Span};
+use rustc_span::{source_map, FileName, MultiSpan, Span, Symbol};
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::{FulfillmentError, Obligation};
 
@@ -1203,6 +1203,13 @@ fn suggest_valid_traits(
             let mut candidates = valid_out_of_scope_traits;
             candidates.sort();
             candidates.dedup();
+
+            // `TryFrom` and `FromIterator` have no methods
+            let edition_fix = candidates
+                .iter()
+                .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
+                .copied();
+
             err.help("items from traits can only be used if the trait is in scope");
             let msg = format!(
                 "the following {traits_are} implemented but not in scope; \
@@ -1212,6 +1219,13 @@ fn suggest_valid_traits(
             );
 
             self.suggest_use_candidates(err, msg, candidates);
+            if let Some(did) = edition_fix {
+                err.note(&format!(
+                    "'{}' is included in the prelude starting in Edition 2021",
+                    with_crate_prefix(|| self.tcx.def_path_str(did))
+                ));
+            }
+
             true
         } else {
             false
@@ -1237,6 +1251,7 @@ fn suggest_traits_to_import(
                 self.tcx.lang_items().deref_trait(),
                 self.tcx.lang_items().deref_mut_trait(),
                 self.tcx.lang_items().drop_trait(),
+                self.tcx.get_diagnostic_item(sym::AsRef),
             ];
             // Try alternative arbitrary self types that could fulfill this call.
             // FIXME: probe for all types that *could* be arbitrary self-types, not
@@ -1286,7 +1301,11 @@ fn suggest_traits_to_import(
                             // We don't want to suggest a container type when the missing
                             // method is `.clone()` or `.deref()` otherwise we'd suggest
                             // `Arc::new(foo).clone()`, which is far from what the user wants.
-                            let skip = skippable.contains(&did);
+                            // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
+                            // implement the `AsRef` trait.
+                            let skip = skippable.contains(&did)
+                                || (("Pin::new" == *pre)
+                                    && (Symbol::intern("as_ref") == item_name.name));
                             // Make sure the method is defined for the *actual* receiver: we don't
                             // want to treat `Box<Self>` as a receiver if it only works because of
                             // an autoderef to `&self`
index 7450b4a4ef1c3f23c0f1554a044f9c6b708df1b4..d19e99606bcd8eec3f0d54d7e921de2ec1e463a9 100644 (file)
@@ -297,9 +297,9 @@ fn primary_body_of(
 fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     // Closures' typeck results come from their outermost function,
     // as they are part of the same "inference environment".
-    let outer_def_id = tcx.closure_base_def_id(def_id);
-    if outer_def_id != def_id {
-        return tcx.has_typeck_results(outer_def_id);
+    let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
+    if typeck_root_def_id != def_id {
+        return tcx.has_typeck_results(typeck_root_def_id);
     }
 
     if let Some(def_id) = def_id.as_local() {
@@ -348,9 +348,9 @@ fn typeck_with_fallback<'tcx>(
 ) -> &'tcx ty::TypeckResults<'tcx> {
     // Closures' typeck results come from their outermost function,
     // as they are part of the same "inference environment".
-    let outer_def_id = tcx.closure_base_def_id(def_id.to_def_id()).expect_local();
-    if outer_def_id != def_id {
-        return tcx.typeck(outer_def_id);
+    let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()).expect_local();
+    if typeck_root_def_id != def_id {
+        return tcx.typeck(typeck_root_def_id);
     }
 
     let id = tcx.hir().local_def_id_to_hir_id(def_id);
index aea1bcd95df21a63504981b9e25075a54882d89f..9c53a1d4eb68dacc98fba193e2e9efb3963d9f88 100644 (file)
@@ -399,12 +399,9 @@ fn check_overloaded_binop(
                     }
                 };
                 if let Ref(_, rty, _) = lhs_ty.kind() {
-                    if {
-                        self.infcx.type_is_copy_modulo_regions(self.param_env, rty, lhs_expr.span)
-                            && self
-                                .lookup_op_method(rty, &[rhs_ty], Op::Binary(op, is_assign))
-                                .is_ok()
-                    } {
+                    if self.infcx.type_is_copy_modulo_regions(self.param_env, rty, lhs_expr.span)
+                        && self.lookup_op_method(rty, &[rhs_ty], Op::Binary(op, is_assign)).is_ok()
+                    {
                         if let Ok(lstring) = source_map.span_to_snippet(lhs_expr.span) {
                             let msg = &format!(
                                 "`{}{}` can be used on `{}`, you can dereference `{}`",
@@ -829,10 +826,7 @@ fn lookup_op_method(
                     self.obligation_for_method(span, trait_did, lhs_ty, Some(other_tys));
                 let mut fulfill = <dyn TraitEngine<'_>>::new(self.tcx);
                 fulfill.register_predicate_obligation(self, obligation);
-                Err(match fulfill.select_where_possible(&self.infcx) {
-                    Err(errors) => errors,
-                    _ => vec![],
-                })
+                Err(fulfill.select_where_possible(&self.infcx))
             }
         }
     }
index 5aa11cce25fb6d5247d38f9757f3bea37c5d6487..cbf33cf1b78a147112c2ad55cd868a845a813eb3 100644 (file)
@@ -292,7 +292,9 @@ fn calc_adjust_mode(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option<Res>) -> A
             // String and byte-string literals result in types `&str` and `&[u8]` respectively.
             // All other literals result in non-reference types.
             // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo {}`.
-            PatKind::Lit(lt) => match self.check_expr(lt).kind() {
+            //
+            // Call `resolve_vars_if_possible` here for inline const blocks.
+            PatKind::Lit(lt) => match self.resolve_vars_if_possible(self.check_expr(lt)).kind() {
                 ty::Ref(..) => AdjustMode::Pass,
                 _ => AdjustMode::Peel,
             },
index f945a2e506301c5fd337dde43d6d49a927584933..d2d8b14dd9695e917bd27d2dc4a08d7683993991 100644 (file)
@@ -88,7 +88,6 @@
 use rustc_middle::ty::adjustment;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::Span;
-use rustc_trait_selection::opaque_types::InferCtxtExt as _;
 use std::ops::Deref;
 
 // a variation on try that just returns unit
@@ -104,7 +103,7 @@ macro_rules! ignore_err {
     };
 }
 
-trait OutlivesEnvironmentExt<'tcx> {
+pub(crate) trait OutlivesEnvironmentExt<'tcx> {
     fn add_implied_bounds(
         &mut self,
         infcx: &InferCtxt<'a, 'tcx>,
@@ -340,8 +339,29 @@ fn visit_fn_body(
         self.link_fn_params(body.params);
         self.visit_body(body);
         self.visit_region_obligations(body_id.hir_id);
+    }
+
+    fn visit_inline_const(&mut self, id: hir::HirId, body: &'tcx hir::Body<'tcx>) {
+        debug!("visit_inline_const(id={:?})", id);
+
+        // Save state of current function. We will restore afterwards.
+        let old_body_id = self.body_id;
+        let old_body_owner = self.body_owner;
+        let env_snapshot = self.outlives_environment.push_snapshot_pre_typeck_child();
 
-        self.constrain_opaque_types();
+        let body_id = body.id();
+        self.body_id = body_id.hir_id;
+        self.body_owner = self.tcx.hir().body_owner_def_id(body_id);
+
+        self.outlives_environment.save_implied_bounds(body_id.hir_id);
+
+        self.visit_body(body);
+        self.visit_region_obligations(body_id.hir_id);
+
+        // Restore state from previous function.
+        self.outlives_environment.pop_snapshot_post_typeck_child(env_snapshot);
+        self.body_id = old_body_id;
+        self.body_owner = old_body_owner;
     }
 
     fn visit_region_obligations(&mut self, hir_id: hir::HirId) {
@@ -409,13 +429,13 @@ fn visit_fn(
         // `visit_fn_body`.  We will restore afterwards.
         let old_body_id = self.body_id;
         let old_body_owner = self.body_owner;
-        let env_snapshot = self.outlives_environment.push_snapshot_pre_closure();
+        let env_snapshot = self.outlives_environment.push_snapshot_pre_typeck_child();
 
         let body = self.tcx.hir().body(body_id);
         self.visit_fn_body(hir_id, body, span);
 
         // Restore state from previous function.
-        self.outlives_environment.pop_snapshot_post_closure(env_snapshot);
+        self.outlives_environment.pop_snapshot_post_typeck_child(env_snapshot);
         self.body_id = old_body_id;
         self.body_owner = old_body_owner;
     }
@@ -463,6 +483,11 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
                 intravisit::walk_expr(self, expr);
             }
 
+            hir::ExprKind::ConstBlock(anon_const) => {
+                let body = self.tcx.hir().body(anon_const.body);
+                self.visit_inline_const(anon_const.hir_id, body);
+            }
+
             _ => intravisit::walk_expr(self, expr),
         }
     }
index 9c7b0b2cacb062e397ed86fedc7b8fa8f518b4bb..5f5d308a3329bdf5c7f3c3fe2cbd1e0a445c4f8c 100644 (file)
@@ -86,18 +86,55 @@ pub fn closure_analyze(&self, body: &'tcx hir::Body<'tcx>) {
 /// Intermediate format to store the hir_id pointing to the use that resulted in the
 /// corresponding place being captured and a String which contains the captured value's
 /// name (i.e: a.b.c)
-type CapturesInfo = (Option<hir::HirId>, String);
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+enum UpvarMigrationInfo {
+    /// We previously captured all of `x`, but now we capture some sub-path.
+    CapturingPrecise { source_expr: Option<hir::HirId>, var_name: String },
+    CapturingNothing {
+        // where the variable appears in the closure (but is not captured)
+        use_span: Span,
+    },
+}
+
+/// Reasons that we might issue a migration warning.
+#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
+struct MigrationWarningReason {
+    /// When we used to capture `x` in its entirety, we implemented the auto-trait(s)
+    /// in this vec, but now we don't.
+    auto_traits: Vec<&'static str>,
+
+    /// When we used to capture `x` in its entirety, we would execute some destructors
+    /// at a different time.
+    drop_order: bool,
+}
 
-/// Intermediate format to store information needed to generate migration lint. The tuple
-/// contains the hir_id pointing to the use that resulted in the
-/// corresponding place being captured, a String which contains the captured value's
-/// name (i.e: a.b.c) and a String which contains the reason why migration is needed for that
-/// capture
-type MigrationNeededForCapture = (Option<hir::HirId>, String, String);
+impl MigrationWarningReason {
+    fn migration_message(&self) -> String {
+        let base = "changes to closure capture in Rust 2021 will affect";
+        if !self.auto_traits.is_empty() && self.drop_order {
+            format!("{} drop order and which traits the closure implements", base)
+        } else if self.drop_order {
+            format!("{} drop order", base)
+        } else {
+            format!("{} which traits the closure implements", base)
+        }
+    }
+}
+
+/// Intermediate format to store information needed to generate a note in the migration lint.
+struct MigrationLintNote {
+    captures_info: UpvarMigrationInfo,
+
+    /// reasons why migration is needed for this capture
+    reason: MigrationWarningReason,
+}
 
 /// Intermediate format to store the hir id of the root variable and a HashSet containing
 /// information on why the root variable should be fully captured
-type MigrationDiagnosticInfo = (hir::HirId, Vec<MigrationNeededForCapture>);
+struct NeededMigration {
+    var_hir_id: hir::HirId,
+    diagnostics_info: Vec<MigrationLintNote>,
+}
 
 struct InferBorrowKindVisitor<'a, 'tcx> {
     fcx: &'a FnCtxt<'a, 'tcx>,
@@ -111,10 +148,17 @@ fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
     }
 
     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
-        if let hir::ExprKind::Closure(cc, _, body_id, _, _) = expr.kind {
-            let body = self.fcx.tcx.hir().body(body_id);
-            self.visit_body(body);
-            self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, cc);
+        match expr.kind {
+            hir::ExprKind::Closure(cc, _, body_id, _, _) => {
+                let body = self.fcx.tcx.hir().body(body_id);
+                self.visit_body(body);
+                self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, cc);
+            }
+            hir::ExprKind::ConstBlock(anon_const) => {
+                let body = self.fcx.tcx.hir().body(anon_const.body);
+                self.visit_body(body);
+            }
+            _ => {}
         }
 
         intravisit::walk_expr(self, expr);
@@ -707,47 +751,66 @@ fn perform_2229_migration_anaysis(
                  closure_head_span,
                 |lint| {
                     let mut diagnostics_builder = lint.build(
-                        format!(
-                            "changes to closure capture in Rust 2021 will affect {}",
-                            reasons
-                        )
-                        .as_str(),
+                        &reasons.migration_message(),
                     );
-                    for (var_hir_id, diagnostics_info) in need_migrations.iter() {
+                    for NeededMigration { var_hir_id, diagnostics_info } in &need_migrations {
                         // Labels all the usage of the captured variable and why they are responsible
                         // for migration being needed
-                        for (captured_hir_id, captured_name, reasons) in diagnostics_info.iter() {
-                            if let Some(captured_hir_id) = captured_hir_id {
-                                let cause_span = self.tcx.hir().span(*captured_hir_id);
-                                diagnostics_builder.span_label(cause_span, format!("in Rust 2018, this closure captures all of `{}`, but in Rust 2021, it will only capture `{}`",
-                                    self.tcx.hir().name(*var_hir_id),
-                                    captured_name,
-                                ));
+                        for lint_note in diagnostics_info.iter() {
+                            match &lint_note.captures_info {
+                                UpvarMigrationInfo::CapturingPrecise { source_expr: Some(capture_expr_id), var_name: captured_name } => {
+                                    let cause_span = self.tcx.hir().span(*capture_expr_id);
+                                    diagnostics_builder.span_label(cause_span, format!("in Rust 2018, this closure captures all of `{}`, but in Rust 2021, it will only capture `{}`",
+                                        self.tcx.hir().name(*var_hir_id),
+                                        captured_name,
+                                    ));
+                                }
+                                UpvarMigrationInfo::CapturingNothing { use_span } => {
+                                    diagnostics_builder.span_label(*use_span, format!("in Rust 2018, this causes the closure to capture `{}`, but in Rust 2021, it has no effect",
+                                        self.tcx.hir().name(*var_hir_id),
+                                    ));
+                                }
+
+                                _ => { }
                             }
 
                             // Add a label pointing to where a captured variable affected by drop order
                             // is dropped
-                            if reasons.contains("drop order") {
+                            if lint_note.reason.drop_order {
                                 let drop_location_span = drop_location_span(self.tcx, &closure_hir_id);
 
-                                diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{}` is dropped here, but in Rust 2021, only `{}` will be dropped here as part of the closure",
-                                    self.tcx.hir().name(*var_hir_id),
-                                    captured_name,
-                                ));
+                                match &lint_note.captures_info {
+                                    UpvarMigrationInfo::CapturingPrecise { var_name: captured_name, .. } => {
+                                        diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{}` is dropped here, but in Rust 2021, only `{}` will be dropped here as part of the closure",
+                                            self.tcx.hir().name(*var_hir_id),
+                                            captured_name,
+                                        ));
+                                    }
+                                    UpvarMigrationInfo::CapturingNothing { use_span: _ } => {
+                                        diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{v}` is dropped here along with the closure, but in Rust 2021 `{v}` is not part of the closure",
+                                            v = self.tcx.hir().name(*var_hir_id),
+                                        ));
+                                    }
+                                }
                             }
 
                             // Add a label explaining why a closure no longer implements a trait
-                            if reasons.contains("trait implementation") {
-                                let missing_trait = &reasons[..reasons.find("trait implementation").unwrap() - 1];
-
-                                diagnostics_builder.span_label(closure_head_span, format!("in Rust 2018, this closure implements {} as `{}` implements {}, but in Rust 2021, this closure will no longer implement {} as `{}` does not implement {}",
-                                    missing_trait,
-                                    self.tcx.hir().name(*var_hir_id),
-                                    missing_trait,
-                                    missing_trait,
-                                    captured_name,
-                                    missing_trait,
-                                ));
+                            for &missing_trait in &lint_note.reason.auto_traits {
+                                // not capturing something anymore cannot cause a trait to fail to be implemented:
+                                match &lint_note.captures_info {
+                                    UpvarMigrationInfo::CapturingPrecise { var_name: captured_name, .. } => {
+                                        let var_name = self.tcx.hir().name(*var_hir_id);
+                                        diagnostics_builder.span_label(closure_head_span, format!("\
+                                        in Rust 2018, this closure implements {missing_trait} \
+                                        as `{var_name}` implements {missing_trait}, but in Rust 2021, \
+                                        this closure will no longer implement {missing_trait} \
+                                        because `{var_name}` is not fully captured \
+                                        and `{captured_name}` does not implement {missing_trait}"));
+                                    }
+
+                                    // Cannot happen: if we don't capture a variable, we impl strictly more traits
+                                    UpvarMigrationInfo::CapturingNothing { use_span } => span_bug!(*use_span, "missing trait from not capturing something"),
+                                }
                             }
                         }
                     }
@@ -840,25 +903,16 @@ fn perform_2229_migration_anaysis(
     /// Combines all the reasons for 2229 migrations
     fn compute_2229_migrations_reasons(
         &self,
-        auto_trait_reasons: FxHashSet<&str>,
-        drop_reason: bool,
-    ) -> String {
-        let mut reasons = String::new();
-
-        if !auto_trait_reasons.is_empty() {
-            reasons = format!(
-                "{} trait implementation for closure",
-                auto_trait_reasons.clone().into_iter().collect::<Vec<&str>>().join(", ")
-            );
-        }
+        auto_trait_reasons: FxHashSet<&'static str>,
+        drop_order: bool,
+    ) -> MigrationWarningReason {
+        let mut reasons = MigrationWarningReason::default();
 
-        if !auto_trait_reasons.is_empty() && drop_reason {
-            reasons = format!("{} and ", reasons);
+        for auto_trait in auto_trait_reasons {
+            reasons.auto_traits.push(auto_trait);
         }
 
-        if drop_reason {
-            reasons = format!("{}drop order", reasons);
-        }
+        reasons.drop_order = drop_order;
 
         reasons
     }
@@ -874,7 +928,7 @@ fn compute_2229_migrations_for_trait(
         min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
         var_hir_id: hir::HirId,
         closure_clause: hir::CaptureBy,
-    ) -> Option<FxHashMap<CapturesInfo, FxHashSet<&str>>> {
+    ) -> Option<FxHashMap<UpvarMigrationInfo, FxHashSet<&'static str>>> {
         let auto_traits_def_id = vec![
             self.tcx.lang_items().clone_trait(),
             self.tcx.lang_items().sync_trait(),
@@ -963,7 +1017,10 @@ fn compute_2229_migrations_for_trait(
 
             if !capture_problems.is_empty() {
                 problematic_captures.insert(
-                    (capture.info.path_expr_id, capture.to_string(self.tcx)),
+                    UpvarMigrationInfo::CapturingPrecise {
+                        source_expr: capture.info.path_expr_id,
+                        var_name: capture.to_string(self.tcx),
+                    },
                     capture_problems,
                 );
             }
@@ -986,6 +1043,7 @@ fn compute_2229_migrations_for_trait(
     ///
     /// This function only returns a HashSet of CapturesInfo for significant drops. If there
     /// are no significant drops than None is returned
+    #[instrument(level = "debug", skip(self))]
     fn compute_2229_migrations_for_drop(
         &self,
         closure_def_id: DefId,
@@ -993,25 +1051,41 @@ fn compute_2229_migrations_for_drop(
         min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
         closure_clause: hir::CaptureBy,
         var_hir_id: hir::HirId,
-    ) -> Option<FxHashSet<CapturesInfo>> {
+    ) -> Option<FxHashSet<UpvarMigrationInfo>> {
         let ty = self.infcx.resolve_vars_if_possible(self.node_ty(var_hir_id));
 
         if !ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) {
+            debug!("does not have significant drop");
             return None;
         }
 
         let Some(root_var_min_capture_list) = min_captures.and_then(|m| m.get(&var_hir_id)) else {
             // The upvar is mentioned within the closure but no path starting from it is
-            // used.
+            // used. This occurs when you have (e.g.)
+            //
+            // ```
+            // let x = move || {
+            //     let _ = y;
+            // });
+            // ```
+            debug!("no path starting from it is used");
+
 
             match closure_clause {
                 // Only migrate if closure is a move closure
-                hir::CaptureBy::Value => return Some(FxHashSet::default()),
+                hir::CaptureBy::Value => {
+                    let mut diagnostics_info = FxHashSet::default();
+                    let upvars = self.tcx.upvars_mentioned(closure_def_id).expect("must be an upvar");
+                    let upvar = upvars[&var_hir_id];
+                    diagnostics_info.insert(UpvarMigrationInfo::CapturingNothing { use_span: upvar.span });
+                    return Some(diagnostics_info);
+                }
                 hir::CaptureBy::Ref => {}
             }
 
             return None;
         };
+        debug!(?root_var_min_capture_list);
 
         let mut projections_list = Vec::new();
         let mut diagnostics_info = FxHashSet::default();
@@ -1021,19 +1095,24 @@ fn compute_2229_migrations_for_drop(
                 // Only care about captures that are moved into the closure
                 ty::UpvarCapture::ByValue(..) => {
                     projections_list.push(captured_place.place.projections.as_slice());
-                    diagnostics_info.insert((
-                        captured_place.info.path_expr_id,
-                        captured_place.to_string(self.tcx),
-                    ));
+                    diagnostics_info.insert(UpvarMigrationInfo::CapturingPrecise {
+                        source_expr: captured_place.info.path_expr_id,
+                        var_name: captured_place.to_string(self.tcx),
+                    });
                 }
                 ty::UpvarCapture::ByRef(..) => {}
             }
         }
 
+        debug!(?projections_list);
+        debug!(?diagnostics_info);
+
         let is_moved = !projections_list.is_empty();
+        debug!(?is_moved);
 
         let is_not_completely_captured =
             root_var_min_capture_list.iter().any(|capture| !capture.place.projections.is_empty());
+        debug!(?is_not_completely_captured);
 
         if is_moved
             && is_not_completely_captured
@@ -1066,15 +1145,16 @@ fn compute_2229_migrations_for_drop(
     /// Returns a tuple containing a vector of MigrationDiagnosticInfo, as well as a String
     /// containing the reason why root variables whose HirId is contained in the vector should
     /// be captured
+    #[instrument(level = "debug", skip(self))]
     fn compute_2229_migrations(
         &self,
         closure_def_id: DefId,
         closure_span: Span,
         closure_clause: hir::CaptureBy,
         min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
-    ) -> (Vec<MigrationDiagnosticInfo>, String) {
+    ) -> (Vec<NeededMigration>, MigrationWarningReason) {
         let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) else {
-            return (Vec::new(), String::new());
+            return (Vec::new(), MigrationWarningReason::default());
         };
 
         let mut need_migrations = Vec::new();
@@ -1083,7 +1163,7 @@ fn compute_2229_migrations(
 
         // Perform auto-trait analysis
         for (&var_hir_id, _) in upvars.iter() {
-            let mut responsible_captured_hir_ids = Vec::new();
+            let mut diagnostics_info = Vec::new();
 
             let auto_trait_diagnostic = if let Some(diagnostics_info) =
                 self.compute_2229_migrations_for_trait(min_captures, var_hir_id, closure_clause)
@@ -1115,34 +1195,33 @@ fn compute_2229_migrations(
 
             let mut capture_diagnostic = capture_diagnostic.into_iter().collect::<Vec<_>>();
             capture_diagnostic.sort();
-            for captured_info in capture_diagnostic.iter() {
+            for captures_info in capture_diagnostic {
                 // Get the auto trait reasons of why migration is needed because of that capture, if there are any
                 let capture_trait_reasons =
-                    if let Some(reasons) = auto_trait_diagnostic.get(captured_info) {
+                    if let Some(reasons) = auto_trait_diagnostic.get(&captures_info) {
                         reasons.clone()
                     } else {
                         FxHashSet::default()
                     };
 
                 // Check if migration is needed because of drop reorder as a result of that capture
-                let capture_drop_reorder_reason = drop_reorder_diagnostic.contains(captured_info);
+                let capture_drop_reorder_reason = drop_reorder_diagnostic.contains(&captures_info);
 
                 // Combine all the reasons of why the root variable should be captured as a result of
                 // auto trait implementation issues
                 auto_trait_migration_reasons.extend(capture_trait_reasons.clone());
 
-                responsible_captured_hir_ids.push((
-                    captured_info.0,
-                    captured_info.1.clone(),
-                    self.compute_2229_migrations_reasons(
+                diagnostics_info.push(MigrationLintNote {
+                    captures_info,
+                    reason: self.compute_2229_migrations_reasons(
                         capture_trait_reasons,
                         capture_drop_reorder_reason,
                     ),
-                ));
+                });
             }
 
-            if !capture_diagnostic.is_empty() {
-                need_migrations.push((var_hir_id, responsible_captured_hir_ids));
+            if !diagnostics_info.is_empty() {
+                need_migrations.push(NeededMigration { var_hir_id, diagnostics_info });
             }
         }
         (
@@ -2087,6 +2166,7 @@ fn var_name(tcx: TyCtxt<'_>, var_hir_id: hir::HirId) -> Symbol {
     tcx.hir().name(var_hir_id)
 }
 
+#[instrument(level = "debug", skip(tcx))]
 fn should_do_rust_2021_incompatible_closure_captures_analysis(
     tcx: TyCtxt<'_>,
     closure_id: hir::HirId,
@@ -2102,10 +2182,12 @@ fn should_do_rust_2021_incompatible_closure_captures_analysis(
 /// - s2: Comma separated names of the variables being migrated.
 fn migration_suggestion_for_2229(
     tcx: TyCtxt<'_>,
-    need_migrations: &Vec<MigrationDiagnosticInfo>,
+    need_migrations: &Vec<NeededMigration>,
 ) -> (String, String) {
-    let need_migrations_variables =
-        need_migrations.iter().map(|(v, _)| var_name(tcx, *v)).collect::<Vec<_>>();
+    let need_migrations_variables = need_migrations
+        .iter()
+        .map(|NeededMigration { var_hir_id: v, .. }| var_name(tcx, *v))
+        .collect::<Vec<_>>();
 
     let migration_ref_concat =
         need_migrations_variables.iter().map(|v| format!("&{}", v)).collect::<Vec<_>>().join(", ");
index 30aab38b1eb8522cd41e8689ca86e6f0ec4280d0..c1adc2894ccfcd365541de28932c886fb71ae4f5 100644 (file)
@@ -1,3 +1,4 @@
+use crate::check::regionck::OutlivesEnvironmentExt;
 use crate::check::{FnCtxt, Inherited};
 use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
 
 use rustc_hir::itemlikevisit::ParItemLikeVisitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::ItemKind;
+use rustc_infer::infer::outlives::env::OutlivesEnvironment;
+use rustc_infer::infer::outlives::obligations::TypeOutlives;
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::infer::{self, RegionckMode, SubregionOrigin};
 use rustc_middle::hir::map as hir_map;
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
 use rustc_middle::ty::{
-    self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
+    self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitor,
+    WithConstness,
 };
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::{sym, Ident, Symbol};
-use rustc_span::Span;
-use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
+use rustc_span::{Span, DUMMY_SP};
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, WellFormedLoc};
 
 use std::convert::TryInto;
@@ -253,6 +259,362 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
                 .emit();
         }
     }
+
+    check_gat_where_clauses(tcx, trait_item, encl_trait_def_id);
+}
+
+/// Require that the user writes where clauses on GATs for the implicit
+/// outlives bounds involving trait parameters in trait functions and
+/// lifetimes passed as GAT substs. See `self-outlives-lint` test.
+///
+/// This trait will be our running example. We are currently WF checking the `Item` item...
+///
+/// ```rust
+/// trait LendingIterator {
+///   type Item<'me>; // <-- WF checking this trait item
+///
+///   fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>;
+/// }
+/// ```
+fn check_gat_where_clauses(
+    tcx: TyCtxt<'_>,
+    trait_item: &hir::TraitItem<'_>,
+    encl_trait_def_id: DefId,
+) {
+    let item = tcx.associated_item(trait_item.def_id);
+    // If the current trait item isn't a type, it isn't a GAT
+    if !matches!(item.kind, ty::AssocKind::Type) {
+        return;
+    }
+    let generics: &ty::Generics = tcx.generics_of(trait_item.def_id);
+    // If the current associated type doesn't have any (own) params, it's not a GAT
+    // FIXME(jackh726): we can also warn in the more general case
+    if generics.params.len() == 0 {
+        return;
+    }
+    let associated_items: &ty::AssocItems<'_> = tcx.associated_items(encl_trait_def_id);
+    let mut clauses: Option<FxHashSet<ty::Predicate<'_>>> = None;
+    // For every function in this trait...
+    // In our example, this would be the `next` method
+    for item in
+        associated_items.in_definition_order().filter(|item| matches!(item.kind, ty::AssocKind::Fn))
+    {
+        // The clauses we that we would require from this function
+        let mut function_clauses = FxHashSet::default();
+
+        let id = hir::HirId::make_owner(item.def_id.expect_local());
+        let param_env = tcx.param_env(item.def_id.expect_local());
+
+        let sig = tcx.fn_sig(item.def_id);
+        // Get the signature using placeholders. In our example, this would
+        // convert the late-bound 'a into a free region.
+        let sig = tcx.liberate_late_bound_regions(item.def_id, sig);
+        // Collect the arguments that are given to this GAT in the return type
+        // of  the function signature. In our example, the GAT in the return
+        // type is `<Self as LendingIterator>::Item<'a>`, so 'a and Self are arguments.
+        let (regions, types) =
+            GATSubstCollector::visit(tcx, trait_item.def_id.to_def_id(), sig.output());
+
+        // If both regions and types are empty, then this GAT isn't in the
+        // return type, and we shouldn't try to do clause analysis
+        // (particularly, doing so would end up with an empty set of clauses,
+        // since the current method would require none, and we take the
+        // intersection of requirements of all methods)
+        if types.is_empty() && regions.is_empty() {
+            continue;
+        }
+
+        // The types we can assume to be well-formed. In our example, this
+        // would be &'a mut Self, from the first argument.
+        let mut wf_tys = FxHashSet::default();
+        wf_tys.extend(sig.inputs());
+
+        // For each region argument (e.g., 'a in our example), check for a
+        // relationship to the type arguments (e.g., Self). If there is an
+        // outlives relationship (`Self: 'a`), then we want to ensure that is
+        // reflected in a where clause on the GAT itself.
+        for (region, region_idx) in &regions {
+            for (ty, ty_idx) in &types {
+                // In our example, requires that Self: 'a
+                if ty_known_to_outlive(tcx, id, param_env, &wf_tys, *ty, *region) {
+                    debug!(?ty_idx, ?region_idx);
+                    debug!("required clause: {} must outlive {}", ty, region);
+                    // Translate into the generic parameters of the GAT. In
+                    // our example, the type was Self, which will also be
+                    // Self in the GAT.
+                    let ty_param = generics.param_at(*ty_idx, tcx);
+                    let ty_param = tcx.mk_ty(ty::Param(ty::ParamTy {
+                        index: ty_param.index,
+                        name: ty_param.name,
+                    }));
+                    // Same for the region. In our example, 'a corresponds
+                    // to the 'me parameter.
+                    let region_param = generics.param_at(*region_idx, tcx);
+                    let region_param =
+                        tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion {
+                            def_id: region_param.def_id,
+                            index: region_param.index,
+                            name: region_param.name,
+                        }));
+                    // The predicate we expect to see. (In our example,
+                    // `Self: 'me`.)
+                    let clause = ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(
+                        ty_param,
+                        region_param,
+                    ));
+                    let clause = tcx.mk_predicate(ty::Binder::dummy(clause));
+                    function_clauses.insert(clause);
+                }
+            }
+        }
+
+        // For each region argument (e.g., 'a in our example), also check for a
+        // relationship to the other region arguments. If there is an
+        // outlives relationship, then we want to ensure that is
+        // reflected in a where clause on the GAT itself.
+        for (region_a, region_a_idx) in &regions {
+            for (region_b, region_b_idx) in &regions {
+                if region_a == region_b {
+                    continue;
+                }
+
+                if region_known_to_outlive(tcx, id, param_env, &wf_tys, *region_a, *region_b) {
+                    debug!(?region_a_idx, ?region_b_idx);
+                    debug!("required clause: {} must outlive {}", region_a, region_b);
+                    // Translate into the generic parameters of the GAT.
+                    let region_a_param = generics.param_at(*region_a_idx, tcx);
+                    let region_a_param =
+                        tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion {
+                            def_id: region_a_param.def_id,
+                            index: region_a_param.index,
+                            name: region_a_param.name,
+                        }));
+                    // Same for the region.
+                    let region_b_param = generics.param_at(*region_b_idx, tcx);
+                    let region_b_param =
+                        tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion {
+                            def_id: region_b_param.def_id,
+                            index: region_b_param.index,
+                            name: region_b_param.name,
+                        }));
+                    // The predicate we expect to see.
+                    let clause = ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(
+                        region_a_param,
+                        region_b_param,
+                    ));
+                    let clause = tcx.mk_predicate(ty::Binder::dummy(clause));
+                    function_clauses.insert(clause);
+                }
+            }
+        }
+
+        // Imagine we have:
+        // ```
+        // trait Foo {
+        //   type Bar<'me>;
+        //   fn gimme(&self) -> Self::Bar<'_>;
+        //   fn gimme_default(&self) -> Self::Bar<'static>;
+        // }
+        // ```
+        // We only want to require clauses on `Bar` that we can prove from *all* functions (in this
+        // case, `'me` can be `static` from `gimme_default`)
+        match clauses.as_mut() {
+            Some(clauses) => {
+                clauses.drain_filter(|p| !function_clauses.contains(p));
+            }
+            None => {
+                clauses = Some(function_clauses);
+            }
+        }
+    }
+
+    // If there are any missing clauses, emit an error
+    let mut clauses = clauses.unwrap_or_default();
+    debug!(?clauses);
+    if !clauses.is_empty() {
+        let written_predicates: ty::GenericPredicates<'_> =
+            tcx.explicit_predicates_of(trait_item.def_id);
+        let mut clauses: Vec<_> = clauses
+            .drain_filter(|clause| !written_predicates.predicates.iter().any(|p| &p.0 == clause))
+            .map(|clause| format!("{}", clause))
+            .collect();
+        // We sort so that order is predictable
+        clauses.sort();
+        if !clauses.is_empty() {
+            let mut err = tcx.sess.struct_span_err(
+                trait_item.span,
+                &format!("Missing required bounds on {}", trait_item.ident),
+            );
+
+            let suggestion = format!(
+                "{} {}",
+                if !trait_item.generics.where_clause.predicates.is_empty() {
+                    ","
+                } else {
+                    " where"
+                },
+                clauses.join(", "),
+            );
+            err.span_suggestion(
+                trait_item.generics.where_clause.tail_span_for_suggestion(),
+                "add the required where clauses",
+                suggestion,
+                Applicability::MachineApplicable,
+            );
+
+            err.emit()
+        }
+    }
+}
+
+// FIXME(jackh726): refactor some of the shared logic between the two functions below
+
+/// Given a known `param_env` and a set of well formed types, can we prove that
+/// `ty` outlives `region`.
+fn ty_known_to_outlive<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    id: hir::HirId,
+    param_env: ty::ParamEnv<'tcx>,
+    wf_tys: &FxHashSet<Ty<'tcx>>,
+    ty: Ty<'tcx>,
+    region: ty::Region<'tcx>,
+) -> bool {
+    // Unfortunately, we have to use a new `InferCtxt` each call, because
+    // region constraints get added and solved there and we need to test each
+    // call individually.
+    tcx.infer_ctxt().enter(|infcx| {
+        let mut outlives_environment = OutlivesEnvironment::new(param_env);
+        outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id, DUMMY_SP);
+        outlives_environment.save_implied_bounds(id);
+        let region_bound_pairs = outlives_environment.region_bound_pairs_map().get(&id).unwrap();
+
+        let cause = ObligationCause::new(DUMMY_SP, id, ObligationCauseCode::MiscObligation);
+
+        let sup_type = ty;
+        let sub_region = region;
+
+        let origin = SubregionOrigin::from_obligation_cause(&cause, || {
+            infer::RelateParamBound(cause.span, sup_type, None)
+        });
+
+        let outlives = &mut TypeOutlives::new(
+            &infcx,
+            tcx,
+            &region_bound_pairs,
+            Some(infcx.tcx.lifetimes.re_root_empty),
+            param_env,
+        );
+        outlives.type_must_outlive(origin, sup_type, sub_region);
+
+        let errors = infcx.resolve_regions(
+            id.expect_owner().to_def_id(),
+            &outlives_environment,
+            RegionckMode::default(),
+        );
+
+        debug!(?errors, "errors");
+
+        // If we were able to prove that the type outlives the region without
+        // an error, it must be because of the implied or explicit bounds...
+        errors.is_empty()
+    })
+}
+
+fn region_known_to_outlive<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    id: hir::HirId,
+    param_env: ty::ParamEnv<'tcx>,
+    wf_tys: &FxHashSet<Ty<'tcx>>,
+    region_a: ty::Region<'tcx>,
+    region_b: ty::Region<'tcx>,
+) -> bool {
+    // Unfortunately, we have to use a new `InferCtxt` each call, because
+    // region constraints get added and solved there and we need to test each
+    // call individually.
+    tcx.infer_ctxt().enter(|infcx| {
+        let mut outlives_environment = OutlivesEnvironment::new(param_env);
+        outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id, DUMMY_SP);
+        outlives_environment.save_implied_bounds(id);
+
+        let cause = ObligationCause::new(DUMMY_SP, id, ObligationCauseCode::MiscObligation);
+
+        let origin = SubregionOrigin::from_obligation_cause(&cause, || {
+            infer::RelateRegionParamBound(cause.span)
+        });
+
+        use rustc_infer::infer::outlives::obligations::TypeOutlivesDelegate;
+        (&infcx).push_sub_region_constraint(origin, region_a, region_b);
+
+        let errors = infcx.resolve_regions(
+            id.expect_owner().to_def_id(),
+            &outlives_environment,
+            RegionckMode::default(),
+        );
+
+        debug!(?errors, "errors");
+
+        // If we were able to prove that the type outlives the region without
+        // an error, it must be because of the implied or explicit bounds...
+        errors.is_empty()
+    })
+}
+
+/// TypeVisitor that looks for uses of GATs like
+/// `<P0 as Trait<P1..Pn>>::GAT<Pn..Pm>` and adds the arguments `P0..Pm` into
+/// the two vectors, `regions` and `types` (depending on their kind). For each
+/// parameter `Pi` also track the index `i`.
+struct GATSubstCollector<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    gat: DefId,
+    // Which region appears and which parameter index its subsituted for
+    regions: FxHashSet<(ty::Region<'tcx>, usize)>,
+    // Which params appears and which parameter index its subsituted for
+    types: FxHashSet<(Ty<'tcx>, usize)>,
+}
+
+impl<'tcx> GATSubstCollector<'tcx> {
+    fn visit<T: TypeFoldable<'tcx>>(
+        tcx: TyCtxt<'tcx>,
+        gat: DefId,
+        t: T,
+    ) -> (FxHashSet<(ty::Region<'tcx>, usize)>, FxHashSet<(Ty<'tcx>, usize)>) {
+        let mut visitor = GATSubstCollector {
+            tcx,
+            gat,
+            regions: FxHashSet::default(),
+            types: FxHashSet::default(),
+        };
+        t.visit_with(&mut visitor);
+        (visitor.regions, visitor.types)
+    }
+}
+
+impl<'tcx> TypeVisitor<'tcx> for GATSubstCollector<'tcx> {
+    type BreakTy = !;
+
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+        match t.kind() {
+            ty::Projection(p) if p.item_def_id == self.gat => {
+                for (idx, subst) in p.substs.iter().enumerate() {
+                    match subst.unpack() {
+                        GenericArgKind::Lifetime(lt) => {
+                            self.regions.insert((lt, idx));
+                        }
+                        GenericArgKind::Type(t) => {
+                            self.types.insert((t, idx));
+                        }
+                        _ => {}
+                    }
+                }
+            }
+            _ => {}
+        }
+        t.super_visit_with(self)
+    }
+
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        Some(self.tcx)
+    }
 }
 
 fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
index d951df94dcf50fbb0a2d137feb5ebf182843a782..fdc8b6b5e64519d57642ad6549ec858d880fcc89 100644 (file)
@@ -282,6 +282,12 @@ fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
             hir::ExprKind::Field(..) => {
                 self.visit_field_id(e.hir_id);
             }
+            hir::ExprKind::ConstBlock(anon_const) => {
+                self.visit_node_id(e.span, anon_const.hir_id);
+
+                let body = self.tcx().hir().body(anon_const.body);
+                self.visit_body(body);
+            }
             _ => {}
         }
 
index 8cae61e8c22f6ffd3708e706de6fbd333d15f96e..372e83592b9c51335fcc04e529071d6684c5b06a 100644 (file)
@@ -180,14 +180,14 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
 
                 let coerced_fields = fields
                     .iter()
-                    .filter_map(|field| {
+                    .filter(|field| {
                         let ty_a = field.ty(tcx, substs_a);
                         let ty_b = field.ty(tcx, substs_b);
 
                         if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) {
                             if layout.is_zst() && layout.align.abi.bytes() == 1 {
                                 // ignore ZST fields with alignment of 1 byte
-                                return None;
+                                return false;
                             }
                         }
 
@@ -204,11 +204,11 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
                                 ))
                                 .emit();
 
-                                return None;
+                                return false;
                             }
                         }
 
-                        Some(field)
+                        return true;
                     })
                     .collect::<Vec<_>>();
 
@@ -263,7 +263,8 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
                     }
 
                     // Check that all transitive obligations are satisfied.
-                    if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) {
+                    let errors = fulfill_cx.select_all_or_error(&infcx);
+                    if !errors.is_empty() {
                         infcx.report_fulfillment_errors(&errors, None, false);
                     }
 
@@ -522,7 +523,8 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI
         fulfill_cx.register_predicate_obligation(&infcx, predicate);
 
         // Check that all transitive obligations are satisfied.
-        if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) {
+        let errors = fulfill_cx.select_all_or_error(&infcx);
+        if !errors.is_empty() {
             infcx.report_fulfillment_errors(&errors, None, false);
         }
 
index df7f2aea9c3ac08ec51b1dc406ff1065d8a091ea..2274db76c05fb264be490cb2043398dbf23e575c 100644 (file)
@@ -1494,13 +1494,15 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
                     {
                         Some(parent_def_id.to_def_id())
                     }
-
+                    Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) => {
+                        Some(tcx.typeck_root_def_id(def_id))
+                    }
                     _ => None,
                 }
             }
         }
         Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => {
-            Some(tcx.closure_base_def_id(def_id))
+            Some(tcx.typeck_root_def_id(def_id))
         }
         Node::Item(item) => match item.kind {
             ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => {
@@ -1692,6 +1694,24 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
         }));
     }
 
+    // provide junk type parameter defs for const blocks.
+    if let Node::AnonConst(_) = node {
+        let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
+        if let Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) = parent_node {
+            params.push(ty::GenericParamDef {
+                index: type_start,
+                name: Symbol::intern("<const_ty>"),
+                def_id,
+                pure_wrt_drop: false,
+                kind: ty::GenericParamDefKind::Type {
+                    has_default: false,
+                    object_lifetime_default: rl::Set1::Empty,
+                    synthetic: None,
+                },
+            });
+        }
+    }
+
     let param_def_id_to_index = params.iter().map(|param| (param.def_id, param.index)).collect();
 
     ty::Generics {
@@ -2879,6 +2899,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
                 for item in list.iter() {
                     if item.has_name(sym::address) {
                         codegen_fn_attrs.no_sanitize |= SanitizerSet::ADDRESS;
+                    } else if item.has_name(sym::cfi) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI;
                     } else if item.has_name(sym::memory) {
                         codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY;
                     } else if item.has_name(sym::thread) {
index cee3679d0a052207e79ba3f14e72c81dd190771a..04a68250ced0cd0a44387b6fa7d3abf868b03351 100644 (file)
@@ -292,7 +292,8 @@ pub(super) fn default_anon_const_substs(tcx: TyCtxt<'_>, def_id: DefId) -> Subst
     // Getting this wrong can lead to ICE and unsoundness, so we assert it here.
     for arg in substs.iter() {
         let allowed_flags = ty::TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS
-            | ty::TypeFlags::STILL_FURTHER_SPECIALIZABLE;
+            | ty::TypeFlags::STILL_FURTHER_SPECIALIZABLE
+            | ty::TypeFlags::HAS_ERROR;
         assert!(!arg.has_type_flags(!allowed_flags));
     }
     substs
@@ -493,7 +494,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                 Node::Expr(&Expr { kind: ExprKind::ConstBlock(ref anon_const), .. })
                     if anon_const.hir_id == hir_id =>
                 {
-                    tcx.typeck(def_id).node_type(anon_const.hir_id)
+                    let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+                    substs.as_inline_const().ty()
                 }
 
                 Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
@@ -771,7 +773,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 } else {
                     err.span_note(
                         tcx.hir().body(body_id).value.span,
-                        &format!("however, the inferred type `{}` cannot be named", ty.to_string()),
+                        &format!("however, the inferred type `{}` cannot be named", ty),
                     );
                 }
             }
@@ -795,7 +797,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 } else {
                     diag.span_note(
                         tcx.hir().body(body_id).value.span,
-                        &format!("however, the inferred type `{}` cannot be named", ty.to_string()),
+                        &format!("however, the inferred type `{}` cannot be named", ty),
                     );
                 }
             }
index 39bcf8999323d7fb7a9a877cda60ee0d4b355bdb..a49eda6572de2cb3cf3248d6a5e317a3ab8ee893 100644 (file)
@@ -88,7 +88,8 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
                     ),
                 );
 
-                if let Err(errors) = fulfill.select_all_or_error(&infcx) {
+                let errors = fulfill.select_all_or_error(&infcx);
+                if !errors.is_empty() {
                     tracing::debug!("Wf-check got errors for {:?}: {:?}", ty, errors);
                     for error in errors {
                         if error.obligation.predicate == self.predicate {
index b19008e42a4ea85118d7616352e156dc1184bf66..ba0fd12a2755f480568093ea79f6ee7acde5c994 100644 (file)
@@ -70,8 +70,8 @@
 #![feature(never_type)]
 #![feature(slice_partition_dedup)]
 #![feature(control_flow_enum)]
+#![feature(hash_drain_filter)]
 #![recursion_limit = "256"]
-#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate tracing;
@@ -157,10 +157,10 @@ fn require_same_types<'tcx>(
             }
         }
 
-        match fulfill_cx.select_all_or_error(infcx) {
-            Ok(()) => true,
-            Err(errors) => {
-                infcx.report_fulfillment_errors(&errors, None, false);
+        match fulfill_cx.select_all_or_error(infcx).as_slice() {
+            [] => true,
+            errors => {
+                infcx.report_fulfillment_errors(errors, None, false);
                 false
             }
         }
@@ -352,8 +352,9 @@ fn main_fn_return_type_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
                 term_id,
                 cause,
             );
-            if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
-                infcx.report_fulfillment_errors(&err, None, false);
+            let errors = fulfillment_cx.select_all_or_error(&infcx);
+            if !errors.is_empty() {
+                infcx.report_fulfillment_errors(&errors, None, false);
                 error = true;
             }
         });
index 4ab5fe26abe56098cc4210db94e1c804cd90afbc..91727d57ddf4e498364f9c317b42c8b9f3c614b4 100644 (file)
@@ -83,7 +83,8 @@ fn implied_outlives_bounds(
         // variables. Process these constraints.
         let mut fulfill_cx = FulfillmentContext::new();
         fulfill_cx.register_predicate_obligations(self, result.obligations);
-        if fulfill_cx.select_all_or_error(self).is_err() {
+        let errors = fulfill_cx.select_all_or_error(self);
+        if !errors.is_empty() {
             self.tcx.sess.delay_span_bug(
                 span,
                 "implied_outlives_bounds failed to solve obligations from instantiation",
index 8d3862ffc8f01c027907081f5a19ca71d0094c9d..a1c2945770920c1f73dfa6743523e6ebfaa87148 100644 (file)
@@ -300,7 +300,7 @@ fn get_type_or_const_args_suggestions_from_param_names(
                     hir::TyKind::Path(hir::QPath::Resolved(
                         None,
                         hir::Path { res: hir::def::Res::Def(_, id), .. },
-                    )) if *id == def_id => true,
+                    )) => *id == def_id,
                     _ => false,
                 })
             })
index c304f74884721a60d976eef7abe200e00999f68e..89c21929dbcda121f7e1183515775682a492e472 100644 (file)
@@ -290,7 +290,7 @@ fn bench_range<F, R>(b: &mut Bencher, f: F)
         let mut c = 0;
         for i in 0..BENCH_RANGE_SIZE {
             for j in i + 1..BENCH_RANGE_SIZE {
-                black_box(map.range(f(i, j)));
+                let _ = black_box(map.range(f(i, j)));
                 c += 1;
             }
         }
@@ -322,7 +322,7 @@ fn bench_iter(b: &mut Bencher, repeats: i32, size: i32) {
     let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
     b.iter(|| {
         for _ in 0..repeats {
-            black_box(map.iter());
+            let _ = black_box(map.iter());
         }
     });
 }
index 4a5b0fcf03709ff944fe4e612327bbeaee3cb70e..66ef92558d8b563c4d149fe5966c54ad60a657ad 100644 (file)
@@ -81,6 +81,7 @@
 /// }
 /// ```
 #[stable(feature = "global_alloc", since = "1.28.0")]
+#[must_use = "losing the pointer will leak memory"]
 #[inline]
 pub unsafe fn alloc(layout: Layout) -> *mut u8 {
     unsafe { __rust_alloc(layout.size(), layout.align()) }
@@ -117,6 +118,7 @@ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
 ///
 /// See [`GlobalAlloc::realloc`].
 #[stable(feature = "global_alloc", since = "1.28.0")]
+#[must_use = "losing the pointer will leak memory"]
 #[inline]
 pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
     unsafe { __rust_realloc(ptr, layout.size(), layout.align(), new_size) }
@@ -150,6 +152,7 @@ pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8
 /// }
 /// ```
 #[stable(feature = "global_alloc", since = "1.28.0")]
+#[must_use = "losing the pointer will leak memory"]
 #[inline]
 pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
     unsafe { __rust_alloc_zeroed(layout.size(), layout.align()) }
index d7620c68f2cae7cb62c8210f27ccc369d577a8b4..7fb7686a6e29790a5320cddb774adcf73e92d91a 100644 (file)
@@ -512,6 +512,7 @@ pub fn push(&mut self, item: T) {
     /// let vec = heap.into_sorted_vec();
     /// assert_eq!(vec, [1, 2, 3, 4, 5, 6, 7]);
     /// ```
+    #[must_use = "`self` will be dropped if the result is not used"]
     #[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
     pub fn into_sorted_vec(mut self) -> Vec<T> {
         let mut end = self.len();
@@ -850,7 +851,6 @@ pub fn iter(&self) -> Iter<'_, T> {
     ///
     /// assert_eq!(heap.into_iter_sorted().take(2).collect::<Vec<_>>(), vec![5, 4]);
     /// ```
-    #[must_use = "`self` will be dropped if the result is not used"]
     #[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
     pub fn into_iter_sorted(self) -> IntoIterSorted<T> {
         IntoIterSorted { inner: self }
@@ -877,6 +877,7 @@ pub fn into_iter_sorted(self) -> IntoIterSorted<T> {
     /// # Time complexity
     ///
     /// Cost is *O*(1) in the worst case.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn peek(&self) -> Option<&T> {
         self.data.get(0)
@@ -894,6 +895,7 @@ pub fn peek(&self) -> Option<&T> {
     /// assert!(heap.capacity() >= 100);
     /// heap.push(4);
     /// ```
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn capacity(&self) -> usize {
         self.data.capacity()
@@ -1050,6 +1052,7 @@ pub fn into_vec(self) -> Vec<T> {
     ///
     /// assert_eq!(heap.len(), 2);
     /// ```
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> usize {
         self.data.len()
@@ -1073,6 +1076,7 @@ pub fn len(&self) -> usize {
     ///
     /// assert!(!heap.is_empty());
     /// ```
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_empty(&self) -> bool {
         self.len() == 0
@@ -1203,6 +1207,7 @@ fn drop(&mut self) {
 /// documentation for more.
 ///
 /// [`iter`]: BinaryHeap::iter
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, T: 'a> {
     iter: slice::Iter<'a, T>,
@@ -1337,6 +1342,7 @@ fn as_into_iter(&mut self) -> &mut vec::IntoIter<Self::Item> {
     }
 }
 
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
 #[derive(Clone, Debug)]
 pub struct IntoIterSorted<T> {
index 07920a6dba61978514032192cbe0443b3655d4e2..2ff7b0fbb759c0c64cbb46210b749bc142afc94f 100644 (file)
@@ -55,7 +55,7 @@
 /// performance on *small* nodes of elements which are cheap to compare. However in the future we
 /// would like to further explore choosing the optimal search strategy based on the choice of B,
 /// and possibly other factors. Using linear search, searching for a random element is expected
-/// to take O(B * log(n)) comparisons, which is generally worse than a BST. In practice,
+/// to take B * log(n) comparisons, which is generally worse than a BST. In practice,
 /// however, performance is excellent.
 ///
 /// It is a logic error for a key to be modified in such a way that the key's ordering relative to
@@ -288,6 +288,7 @@ fn replace(&mut self, key: K) -> Option<K> {
 /// documentation for more.
 ///
 /// [`iter`]: BTreeMap::iter
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, K: 'a, V: 'a> {
     range: LazyLeafRange<marker::Immut<'a>, K, V>,
@@ -316,6 +317,7 @@ pub struct IterMut<'a, K: 'a, V: 'a> {
     _marker: PhantomData<&'a mut (K, V)>,
 }
 
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "collection_debug", since = "1.17.0")]
 impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IterMut<'_, K, V> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -359,6 +361,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// documentation for more.
 ///
 /// [`keys`]: BTreeMap::keys
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Keys<'a, K: 'a, V: 'a> {
     inner: Iter<'a, K, V>,
@@ -377,6 +380,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// documentation for more.
 ///
 /// [`values`]: BTreeMap::values
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Values<'a, K: 'a, V: 'a> {
     inner: Iter<'a, K, V>,
@@ -395,6 +399,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// documentation for more.
 ///
 /// [`values_mut`]: BTreeMap::values_mut
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "map_values_mut", since = "1.10.0")]
 pub struct ValuesMut<'a, K: 'a, V: 'a> {
     inner: IterMut<'a, K, V>,
@@ -413,6 +418,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// See its documentation for more.
 ///
 /// [`into_keys`]: BTreeMap::into_keys
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "map_into_keys_values", since = "1.54.0")]
 pub struct IntoKeys<K, V> {
     inner: IntoIter<K, V>,
@@ -431,6 +437,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// See its documentation for more.
 ///
 /// [`into_values`]: BTreeMap::into_values
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "map_into_keys_values", since = "1.54.0")]
 pub struct IntoValues<K, V> {
     inner: IntoIter<K, V>,
@@ -449,6 +456,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// documentation for more.
 ///
 /// [`range`]: BTreeMap::range
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "btree_range", since = "1.17.0")]
 pub struct Range<'a, K: 'a, V: 'a> {
     inner: LeafRange<marker::Immut<'a>, K, V>,
@@ -467,6 +475,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// documentation for more.
 ///
 /// [`range_mut`]: BTreeMap::range_mut
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "btree_range", since = "1.17.0")]
 pub struct RangeMut<'a, K: 'a, V: 'a> {
     inner: LeafRange<marker::ValMut<'a>, K, V>,
@@ -1265,7 +1274,6 @@ pub(super) fn drain_filter_inner(&mut self) -> DrainFilterInner<'_, K, V>
     /// assert_eq!(keys, [1, 2]);
     /// ```
     #[inline]
-    #[must_use = "`self` will be dropped if the result is not used"]
     #[stable(feature = "map_into_keys_values", since = "1.54.0")]
     pub fn into_keys(self) -> IntoKeys<K, V> {
         IntoKeys { inner: self.into_iter() }
@@ -1288,7 +1296,6 @@ pub fn into_keys(self) -> IntoKeys<K, V> {
     /// assert_eq!(values, ["hello", "goodbye"]);
     /// ```
     #[inline]
-    #[must_use = "`self` will be dropped if the result is not used"]
     #[stable(feature = "map_into_keys_values", since = "1.54.0")]
     pub fn into_values(self) -> IntoValues<K, V> {
         IntoValues { inner: self.into_iter() }
@@ -2205,6 +2212,7 @@ pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> {
     /// a.insert(1, "a");
     /// assert_eq!(a.len(), 1);
     /// ```
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")]
     pub const fn len(&self) -> usize {
@@ -2225,6 +2233,7 @@ pub const fn len(&self) -> usize {
     /// a.insert(1, "a");
     /// assert!(!a.is_empty());
     /// ```
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")]
     pub const fn is_empty(&self) -> bool {
index 3e9048b17688fb78f7d589c0dac2ba352a773415..5cef007a46f0d1ea9d725fd87c3b8f703288426c 100644 (file)
@@ -347,6 +347,7 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> {
     /// map.entry("poneyland").or_insert(12);
     /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
     /// ```
+    #[must_use]
     #[stable(feature = "map_entry_keys", since = "1.10.0")]
     pub fn key(&self) -> &K {
         self.handle.reborrow().into_kv().0
@@ -391,6 +392,7 @@ pub fn remove_entry(self) -> (K, V) {
     ///     assert_eq!(o.get(), &12);
     /// }
     /// ```
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get(&self) -> &V {
         self.handle.reborrow().into_kv().1
index 173960341f859b5acab3b8b8f094de9c6b1ee36e..17389657afb92564e0371865ff1f5a43f707446a 100644 (file)
@@ -744,35 +744,35 @@ fn test_range_equal_empty_cases() {
 #[should_panic]
 fn test_range_equal_excluded() {
     let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
-    map.range((Excluded(2), Excluded(2)));
+    let _ = map.range((Excluded(2), Excluded(2)));
 }
 
 #[test]
 #[should_panic]
 fn test_range_backwards_1() {
     let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
-    map.range((Included(3), Included(2)));
+    let _ = map.range((Included(3), Included(2)));
 }
 
 #[test]
 #[should_panic]
 fn test_range_backwards_2() {
     let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
-    map.range((Included(3), Excluded(2)));
+    let _ = map.range((Included(3), Excluded(2)));
 }
 
 #[test]
 #[should_panic]
 fn test_range_backwards_3() {
     let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
-    map.range((Excluded(3), Included(2)));
+    let _ = map.range((Excluded(3), Included(2)));
 }
 
 #[test]
 #[should_panic]
 fn test_range_backwards_4() {
     let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
-    map.range((Excluded(3), Excluded(2)));
+    let _ = map.range((Excluded(3), Excluded(2)));
 }
 
 #[test]
@@ -783,7 +783,7 @@ fn test_range_finding_ill_order_in_map() {
     // we cause a different panic than `test_range_backwards_1` does.
     // A more refined `should_panic` would be welcome.
     if Cyclic3::C < Cyclic3::A {
-        map.range(Cyclic3::C..=Cyclic3::A);
+        let _ = map.range(Cyclic3::C..=Cyclic3::A);
     }
 }
 
@@ -824,7 +824,7 @@ fn borrow(&self) -> &EvilTwin {
     }
 
     let map = (0..12).map(|i| (CompositeKey(i, EvilTwin(i)), ())).collect::<BTreeMap<_, _>>();
-    map.range(EvilTwin(5)..=EvilTwin(7));
+    let _ = map.range(EvilTwin(5)..=EvilTwin(7));
 }
 
 #[test]
@@ -1239,32 +1239,32 @@ fn test_borrow() {
 
     #[allow(dead_code)]
     fn get<T: Ord>(v: &BTreeMap<Box<T>, ()>, t: &T) {
-        v.get(t);
+        let _ = v.get(t);
     }
 
     #[allow(dead_code)]
     fn get_mut<T: Ord>(v: &mut BTreeMap<Box<T>, ()>, t: &T) {
-        v.get_mut(t);
+        let _ = v.get_mut(t);
     }
 
     #[allow(dead_code)]
     fn get_key_value<T: Ord>(v: &BTreeMap<Box<T>, ()>, t: &T) {
-        v.get_key_value(t);
+        let _ = v.get_key_value(t);
     }
 
     #[allow(dead_code)]
     fn contains_key<T: Ord>(v: &BTreeMap<Box<T>, ()>, t: &T) {
-        v.contains_key(t);
+        let _ = v.contains_key(t);
     }
 
     #[allow(dead_code)]
     fn range<T: Ord>(v: &BTreeMap<Box<T>, ()>, t: T) {
-        v.range(t..);
+        let _ = v.range(t..);
     }
 
     #[allow(dead_code)]
     fn range_mut<T: Ord>(v: &mut BTreeMap<Box<T>, ()>, t: T) {
-        v.range_mut(t..);
+        let _ = v.range_mut(t..);
     }
 
     #[allow(dead_code)]
index 237e0107f247585c169202c1c6afa5b5d35b174a..0322cabccde4b0f830acaf9f423de435cc36f9db 100644 (file)
@@ -92,6 +92,7 @@ fn clone_from(&mut self, other: &Self) {
 /// See its documentation for more.
 ///
 /// [`iter`]: BTreeSet::iter
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, T: 'a> {
     iter: Keys<'a, T, ()>,
@@ -123,6 +124,7 @@ pub struct IntoIter<T> {
 /// See its documentation for more.
 ///
 /// [`range`]: BTreeSet::range
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[derive(Debug)]
 #[stable(feature = "btree_range", since = "1.17.0")]
 pub struct Range<'a, T: 'a> {
@@ -135,6 +137,8 @@ pub struct Range<'a, T: 'a> {
 /// See its documentation for more.
 ///
 /// [`difference`]: BTreeSet::difference
+#[must_use = "this returns the difference as an iterator, \
+              without modifying either input set"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Difference<'a, T: 'a> {
     inner: DifferenceInner<'a, T>,
@@ -167,6 +171,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// [`BTreeSet`]. See its documentation for more.
 ///
 /// [`symmetric_difference`]: BTreeSet::symmetric_difference
+#[must_use = "this returns the difference as an iterator, \
+              without modifying either input set"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct SymmetricDifference<'a, T: 'a>(MergeIterInner<Iter<'a, T>>);
 
@@ -183,6 +189,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// See its documentation for more.
 ///
 /// [`intersection`]: BTreeSet::intersection
+#[must_use = "this returns the intersection as an iterator, \
+              without modifying either input set"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Intersection<'a, T: 'a> {
     inner: IntersectionInner<'a, T>,
@@ -215,6 +223,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// See its documentation for more.
 ///
 /// [`union`]: BTreeSet::union
+#[must_use = "this returns the union as an iterator, \
+              without modifying either input set"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Union<'a, T: 'a>(MergeIterInner<Iter<'a, T>>);
 
@@ -668,6 +678,7 @@ pub fn is_superset(&self, other: &BTreeSet<T>) -> bool
     /// set.insert(2);
     /// assert_eq!(set.first(), Some(&1));
     /// ```
+    #[must_use]
     #[unstable(feature = "map_first_last", issue = "62924")]
     pub fn first(&self) -> Option<&T>
     where
@@ -694,6 +705,7 @@ pub fn first(&self) -> Option<&T>
     /// set.insert(2);
     /// assert_eq!(set.last(), Some(&2));
     /// ```
+    #[must_use]
     #[unstable(feature = "map_first_last", issue = "62924")]
     pub fn last(&self) -> Option<&T>
     where
@@ -1034,6 +1046,7 @@ pub fn iter(&self) -> Iter<'_, T> {
     /// v.insert(1);
     /// assert_eq!(v.len(), 1);
     /// ```
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")]
     pub const fn len(&self) -> usize {
@@ -1052,6 +1065,7 @@ pub const fn len(&self) -> usize {
     /// v.insert(1);
     /// assert!(!v.is_empty());
     /// ```
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")]
     pub const fn is_empty(&self) -> bool {
index 0a87ae12d61a59a34f957903aef3d0958010b9e6..2fc17a7c8603fc0b32afab1a79058d9043554d95 100644 (file)
@@ -610,11 +610,11 @@ fn union<T: Send + Sync + Ord>(v: &BTreeSet<T>) -> impl Send + '_ {
 #[test]
 fn test_ord_absence() {
     fn set<K>(mut set: BTreeSet<K>) {
-        set.is_empty();
-        set.len();
+        let _ = set.is_empty();
+        let _ = set.len();
         set.clear();
-        set.iter();
-        set.into_iter();
+        let _ = set.iter();
+        let _ = set.into_iter();
     }
 
     fn set_debug<K: Debug>(set: BTreeSet<K>) {
index ea010c1f89d24ee1d9820933860cf340d4b9f488..e4913b16adbe7722b14e755f25e5954ecda47168 100644 (file)
@@ -64,6 +64,7 @@ struct Node<T> {
 ///
 /// This `struct` is created by [`LinkedList::iter()`]. See its
 /// documentation for more.
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, T: 'a> {
     head: Option<NonNull<Node<T>>>,
@@ -99,6 +100,7 @@ fn clone(&self) -> Self {
 ///
 /// This `struct` is created by [`LinkedList::iter_mut()`]. See its
 /// documentation for more.
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, T: 'a> {
     head: Option<NonNull<Node<T>>>,
@@ -529,6 +531,7 @@ pub fn iter_mut(&mut self) -> IterMut<'_, T> {
     ///
     /// The cursor is pointing to the "ghost" non-element if the list is empty.
     #[inline]
+    #[must_use]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
     pub fn cursor_front(&self) -> Cursor<'_, T> {
         Cursor { index: 0, current: self.head, list: self }
@@ -538,6 +541,7 @@ pub fn cursor_front(&self) -> Cursor<'_, T> {
     ///
     /// The cursor is pointing to the "ghost" non-element if the list is empty.
     #[inline]
+    #[must_use]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
     pub fn cursor_front_mut(&mut self) -> CursorMut<'_, T> {
         CursorMut { index: 0, current: self.head, list: self }
@@ -547,6 +551,7 @@ pub fn cursor_front_mut(&mut self) -> CursorMut<'_, T> {
     ///
     /// The cursor is pointing to the "ghost" non-element if the list is empty.
     #[inline]
+    #[must_use]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
     pub fn cursor_back(&self) -> Cursor<'_, T> {
         Cursor { index: self.len.checked_sub(1).unwrap_or(0), current: self.tail, list: self }
@@ -556,6 +561,7 @@ pub fn cursor_back(&self) -> Cursor<'_, T> {
     ///
     /// The cursor is pointing to the "ghost" non-element if the list is empty.
     #[inline]
+    #[must_use]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
     pub fn cursor_back_mut(&mut self) -> CursorMut<'_, T> {
         CursorMut { index: self.len.checked_sub(1).unwrap_or(0), current: self.tail, list: self }
@@ -577,6 +583,7 @@ pub fn cursor_back_mut(&mut self) -> CursorMut<'_, T> {
     /// assert!(!dl.is_empty());
     /// ```
     #[inline]
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_empty(&self) -> bool {
         self.head.is_none()
@@ -603,6 +610,7 @@ pub fn is_empty(&self) -> bool {
     /// assert_eq!(dl.len(), 3);
     /// ```
     #[inline]
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> usize {
         self.len
@@ -678,6 +686,7 @@ pub fn contains(&self, x: &T) -> bool
     /// assert_eq!(dl.front(), Some(&1));
     /// ```
     #[inline]
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn front(&self) -> Option<&T> {
         unsafe { self.head.as_ref().map(|node| &node.as_ref().element) }
@@ -706,6 +715,7 @@ pub fn front(&self) -> Option<&T> {
     /// assert_eq!(dl.front(), Some(&5));
     /// ```
     #[inline]
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn front_mut(&mut self) -> Option<&mut T> {
         unsafe { self.head.as_mut().map(|node| &mut node.as_mut().element) }
@@ -728,6 +738,7 @@ pub fn front_mut(&mut self) -> Option<&mut T> {
     /// assert_eq!(dl.back(), Some(&1));
     /// ```
     #[inline]
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn back(&self) -> Option<&T> {
         unsafe { self.tail.as_ref().map(|node| &node.as_ref().element) }
@@ -1178,6 +1189,7 @@ impl<'a, T> Cursor<'a, T> {
     ///
     /// This returns `None` if the cursor is currently pointing to the
     /// "ghost" non-element.
+    #[must_use]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
     pub fn index(&self) -> Option<usize> {
         let _ = self.current?;
@@ -1232,6 +1244,7 @@ pub fn move_prev(&mut self) {
     ///
     /// This returns `None` if the cursor is currently pointing to the
     /// "ghost" non-element.
+    #[must_use]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
     pub fn current(&self) -> Option<&'a T> {
         unsafe { self.current.map(|current| &(*current.as_ptr()).element) }
@@ -1242,6 +1255,7 @@ pub fn current(&self) -> Option<&'a T> {
     /// If the cursor is pointing to the "ghost" non-element then this returns
     /// the first element of the `LinkedList`. If it is pointing to the last
     /// element of the `LinkedList` then this returns `None`.
+    #[must_use]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
     pub fn peek_next(&self) -> Option<&'a T> {
         unsafe {
@@ -1258,6 +1272,7 @@ pub fn peek_next(&self) -> Option<&'a T> {
     /// If the cursor is pointing to the "ghost" non-element then this returns
     /// the last element of the `LinkedList`. If it is pointing to the first
     /// element of the `LinkedList` then this returns `None`.
+    #[must_use]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
     pub fn peek_prev(&self) -> Option<&'a T> {
         unsafe {
@@ -1271,6 +1286,7 @@ pub fn peek_prev(&self) -> Option<&'a T> {
 
     /// Provides a reference to the front element of the cursor's parent list,
     /// or None if the list is empty.
+    #[must_use]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
     pub fn front(&self) -> Option<&'a T> {
         self.list.front()
@@ -1278,6 +1294,7 @@ pub fn front(&self) -> Option<&'a T> {
 
     /// Provides a reference to the back element of the cursor's parent list,
     /// or None if the list is empty.
+    #[must_use]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
     pub fn back(&self) -> Option<&'a T> {
         self.list.back()
@@ -1289,6 +1306,7 @@ impl<'a, T> CursorMut<'a, T> {
     ///
     /// This returns `None` if the cursor is currently pointing to the
     /// "ghost" non-element.
+    #[must_use]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
     pub fn index(&self) -> Option<usize> {
         let _ = self.current?;
@@ -1343,6 +1361,7 @@ pub fn move_prev(&mut self) {
     ///
     /// This returns `None` if the cursor is currently pointing to the
     /// "ghost" non-element.
+    #[must_use]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
     pub fn current(&mut self) -> Option<&mut T> {
         unsafe { self.current.map(|current| &mut (*current.as_ptr()).element) }
@@ -1631,6 +1650,7 @@ pub fn pop_back(&mut self) -> Option<T> {
 
     /// Provides a reference to the front element of the cursor's parent list,
     /// or None if the list is empty.
+    #[must_use]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
     pub fn front(&self) -> Option<&T> {
         self.list.front()
@@ -1638,6 +1658,7 @@ pub fn front(&self) -> Option<&T> {
 
     /// Provides a mutable reference to the front element of the cursor's
     /// parent list, or None if the list is empty.
+    #[must_use]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
     pub fn front_mut(&mut self) -> Option<&mut T> {
         self.list.front_mut()
@@ -1645,6 +1666,7 @@ pub fn front_mut(&mut self) -> Option<&mut T> {
 
     /// Provides a reference to the back element of the cursor's parent list,
     /// or None if the list is empty.
+    #[must_use]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
     pub fn back(&self) -> Option<&T> {
         self.list.back()
@@ -1671,6 +1693,7 @@ pub fn back(&self) -> Option<&T> {
     /// assert_eq!(contents.next(), Some(0));
     /// assert_eq!(contents.next(), None);
     /// ```
+    #[must_use]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
     pub fn back_mut(&mut self) -> Option<&mut T> {
         self.list.back_mut()
index 77d28bdfe647598892f9da5a3f44fb2df0504270..1ea135a2aed82aaa12d71598a977e7737eda0277 100644 (file)
@@ -65,6 +65,7 @@ pub struct TryReserveError {
 impl TryReserveError {
     /// Details about the allocation that caused the error
     #[inline]
+    #[must_use]
     #[unstable(
         feature = "try_reserve_kind",
         reason = "Uncertain how much info should be exposed",
index 878d8dc5502df8d552dc4bed84165ad592876d33..50e789d76b7f3b951bf2f581f8d74e3f7ebdc633 100644 (file)
 /// [`format_args!`]: core::format_args
 /// [`format!`]: crate::format
 #[cfg(not(no_global_oom_handling))]
+#[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn format(args: Arguments<'_>) -> string::String {
     let capacity = args.estimated_capacity();
index 285d7755c0689c69d817439a65a0a3795650caee..5dda7bfa37c71ea94aabb6a68bd95f6781472fbd 100644 (file)
 #![feature(extend_one)]
 #![feature(fmt_internals)]
 #![feature(fn_traits)]
+#![feature(inherent_ascii_escape)]
 #![feature(inplace_iteration)]
 #![feature(iter_advance_by)]
 #![feature(iter_zip)]
 #![feature(maybe_uninit_slice)]
 #![cfg_attr(test, feature(new_uninit))]
 #![feature(nonnull_slice_from_raw_parts)]
-#![feature(option_result_unwrap_unchecked)]
 #![feature(pattern)]
 #![feature(ptr_internals)]
 #![feature(receiver_trait)]
 //
 // Rustdoc features:
 #![feature(doc_cfg)]
-#![cfg_attr(not(bootstrap), feature(doc_cfg_hide))]
+#![feature(doc_cfg_hide)]
 // Technically, this is a bug in rustdoc: rustdoc sees the documentation on `#[lang = slice_alloc]`
 // blocks is for `&[T]`, which also has documentation using this feature in `core`, and gets mad
 // that the feature-gate isn't enabled. Ideally, it wouldn't check for the feature gate for docs
index 493cf3117edf6a8b113f3772900c644c23facb47..03e33a1ff2bc3b77f1223b8056497f8e40763b29 100644 (file)
@@ -41,7 +41,7 @@
 //! use std::rc::Rc;
 //!
 //! let my_rc = Rc::new(());
-//! Rc::downgrade(&my_rc);
+//! let my_weak = Rc::downgrade(&my_rc);
 //! ```
 //!
 //! `Rc<T>`'s implementations of traits like `Clone` may also be called using
@@ -313,11 +313,19 @@ pub struct Rc<T: ?Sized> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> !marker::Send for Rc<T> {}
+
+// Note that this negative impl isn't strictly necessary for correctness,
+// as `Rc` transitively contains a `Cell`, which is itself `!Sync`.
+// However, given how important `Rc`'s `!Sync`-ness is,
+// having an explicit negative impl is nice for documentation purposes
+// and results in nicer error messages.
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> !marker::Sync for Rc<T> {}
 
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Rc<T> {}
+#[stable(feature = "rc_ref_unwind_safe", since = "1.58.0")]
+impl<T: RefUnwindSafe + ?Sized> RefUnwindSafe for Rc<T> {}
 
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Rc<U>> for Rc<T> {}
@@ -889,6 +897,8 @@ pub unsafe fn from_raw(ptr: *const T) -> Self {
     ///
     /// let weak_five = Rc::downgrade(&five);
     /// ```
+    #[must_use = "this returns a new `Weak` pointer, \
+                  without modifying the original `Rc`"]
     #[stable(feature = "rc_weak", since = "1.4.0")]
     pub fn downgrade(this: &Self) -> Weak<T> {
         this.inner().inc_weak();
@@ -2246,6 +2256,7 @@ pub fn upgrade(&self) -> Option<Rc<T>> {
     /// Gets the number of strong (`Rc`) pointers pointing to this allocation.
     ///
     /// If `self` was created using [`Weak::new`], this will return 0.
+    #[must_use]
     #[stable(feature = "weak_counts", since = "1.41.0")]
     pub fn strong_count(&self) -> usize {
         if let Some(inner) = self.inner() { inner.strong() } else { 0 }
@@ -2254,6 +2265,7 @@ pub fn strong_count(&self) -> usize {
     /// Gets the number of `Weak` pointers pointing to this allocation.
     ///
     /// If no strong pointers remain, this will return zero.
+    #[must_use]
     #[stable(feature = "weak_counts", since = "1.41.0")]
     pub fn weak_count(&self) -> usize {
         self.inner()
@@ -2324,6 +2336,7 @@ fn inner(&self) -> Option<WeakInner<'_>> {
     /// assert!(!first.ptr_eq(&third));
     /// ```
     #[inline]
+    #[must_use]
     #[stable(feature = "weak_ptr_eq", since = "1.39.0")]
     pub fn ptr_eq(&self, other: &Self) -> bool {
         self.ptr.as_ptr() == other.ptr.as_ptr()
index 860f21085f32542ffc1854ba2dfe55bea5ee2106..ae730be0d25a57155e6e2cc8cf99bec1e9d902ae 100644 (file)
 pub use core::slice::ArrayChunksMut;
 #[unstable(feature = "array_windows", issue = "75027")]
 pub use core::slice::ArrayWindows;
+#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+pub use core::slice::EscapeAscii;
 #[stable(feature = "slice_get_slice", since = "1.28.0")]
 pub use core::slice::SliceIndex;
 #[stable(feature = "from_ref", since = "1.28.0")]
 pub use core::slice::{RSplit, RSplitMut};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::slice::{RSplitN, RSplitNMut, SplitN, SplitNMut};
+#[stable(feature = "split_inclusive", since = "1.51.0")]
+pub use core::slice::{SplitInclusive, SplitInclusiveMut};
 
 ////////////////////////////////////////////////////////////////////////////////
 // Basic slice extension methods
index e1d0ee42f4e901a8c7839c80f6f6fb0b25475b28..104f5556566f4e5370c6dde8d0c9654b6bffc406 100644 (file)
@@ -46,7 +46,7 @@
 pub use core::str::EncodeUtf16;
 #[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
 pub use core::str::SplitAsciiWhitespace;
-#[stable(feature = "split_inclusive", since = "1.53.0")]
+#[stable(feature = "split_inclusive", since = "1.51.0")]
 pub use core::str::SplitInclusive;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::str::SplitWhitespace;
@@ -243,6 +243,7 @@ impl str {
     /// assert_eq!(*boxed_bytes, *s.as_bytes());
     /// ```
     #[stable(feature = "str_box_extras", since = "1.20.0")]
+    #[must_use = "`self` will be dropped if the result is not used"]
     #[inline]
     pub fn into_boxed_bytes(self: Box<str>) -> Box<[u8]> {
         self.into()
@@ -484,6 +485,7 @@ pub fn to_uppercase(&self) -> String {
     /// assert_eq!(boxed_str.into_string(), string);
     /// ```
     #[stable(feature = "box_str", since = "1.4.0")]
+    #[must_use = "`self` will be dropped if the result is not used"]
     #[inline]
     pub fn into_string(self: Box<str>) -> String {
         let slice = Box::<[u8]>::from(self);
@@ -508,9 +510,10 @@ pub fn into_string(self: Box<str>) -> String {
     ///
     /// ```should_panic
     /// // this will panic at runtime
-    /// "0123456789abcdef".repeat(usize::MAX);
+    /// let huge = "0123456789abcdef".repeat(usize::MAX);
     /// ```
     #[cfg(not(no_global_oom_handling))]
+    #[must_use]
     #[stable(feature = "repeat_str", since = "1.16.0")]
     pub fn repeat(&self, n: usize) -> String {
         unsafe { String::from_utf8_unchecked(self.as_bytes().repeat(n)) }
index f479bf231b37681402bfb410926c81ec6d835716..906b0187f7babf540932b2cd408f71b88b308782 100644 (file)
@@ -552,6 +552,7 @@ pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error> {
     ///
     /// assert_eq!("Hello �World", output);
     /// ```
+    #[must_use]
     #[cfg(not(no_global_oom_handling))]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str> {
@@ -646,6 +647,7 @@ pub fn from_utf16(v: &[u16]) -> Result<String, FromUtf16Error> {
     ///            String::from_utf16_lossy(v));
     /// ```
     #[cfg(not(no_global_oom_handling))]
+    #[must_use]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn from_utf16_lossy(v: &[u16]) -> String {
@@ -898,6 +900,7 @@ pub fn extend_from_within<R>(&mut self, src: R)
     /// assert!(s.capacity() >= 10);
     /// ```
     #[inline]
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn capacity(&self) -> usize {
         self.vec.capacity()
@@ -1500,10 +1503,11 @@ pub fn insert_str(&mut self, idx: usize, string: &str) {
     ///
     /// # Safety
     ///
-    /// This function is unsafe because it does not check that the bytes passed
-    /// to it are valid UTF-8. If this constraint is violated, it may cause
-    /// memory unsafety issues with future users of the `String`, as the rest of
-    /// the standard library assumes that `String`s are valid UTF-8.
+    /// This function is unsafe because the returned `&mut Vec` allows writing
+    /// bytes which are not valid UTF-8. If this constraint is violated, using
+    /// the original `String` after dropping the `&mut Vec` may violate memory
+    /// safety, as the rest of the standard library assumes that `String`s are
+    /// valid UTF-8.
     ///
     /// # Examples
     ///
@@ -1543,6 +1547,7 @@ pub unsafe fn as_mut_vec(&mut self) -> &mut Vec<u8> {
     /// assert_eq!(fancy_f.chars().count(), 3);
     /// ```
     #[inline]
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> usize {
         self.vec.len()
@@ -1562,6 +1567,7 @@ pub fn len(&self) -> usize {
     /// assert!(!v.is_empty());
     /// ```
     #[inline]
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_empty(&self) -> bool {
         self.len() == 0
@@ -1822,6 +1828,7 @@ pub fn into_bytes(self) -> Vec<u8> {
     /// // the first byte is invalid here
     /// assert_eq!(1, error.valid_up_to());
     /// ```
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn utf8_error(&self) -> Utf8Error {
         self.error
index b75e9a2f3c71ea77b0c1cd1ac717020317e79d45..b738337a2ddd19805fc0d623f6570077f6991a22 100644 (file)
@@ -804,6 +804,7 @@ impl<T: ?Sized> Arc<T> {
     /// let x_ptr = Arc::into_raw(x);
     /// assert_eq!(unsafe { &*x_ptr }, "hello");
     /// ```
+    #[must_use = "losing the pointer will leak memory"]
     #[stable(feature = "rc_raw", since = "1.17.0")]
     pub fn into_raw(this: Self) -> *const T {
         let ptr = Self::as_ptr(&this);
@@ -953,6 +954,7 @@ pub fn downgrade(this: &Self) -> Weak<T> {
     /// assert_eq!(1, Arc::weak_count(&five));
     /// ```
     #[inline]
+    #[must_use]
     #[stable(feature = "arc_counts", since = "1.15.0")]
     pub fn weak_count(this: &Self) -> usize {
         let cnt = this.inner().weak.load(SeqCst);
@@ -982,6 +984,7 @@ pub fn weak_count(this: &Self) -> usize {
     /// assert_eq!(2, Arc::strong_count(&five));
     /// ```
     #[inline]
+    #[must_use]
     #[stable(feature = "arc_counts", since = "1.15.0")]
     pub fn strong_count(this: &Self) -> usize {
         this.inner().strong.load(SeqCst)
@@ -1079,8 +1082,6 @@ unsafe fn drop_slow(&mut self) {
         drop(Weak { ptr: self.ptr });
     }
 
-    #[inline]
-    #[stable(feature = "ptr_eq", since = "1.17.0")]
     /// Returns `true` if the two `Arc`s point to the same allocation
     /// (in a vein similar to [`ptr::eq`]).
     ///
@@ -1098,6 +1099,9 @@ unsafe fn drop_slow(&mut self) {
     /// ```
     ///
     /// [`ptr::eq`]: core::ptr::eq "ptr::eq"
+    #[inline]
+    #[must_use]
+    #[stable(feature = "ptr_eq", since = "1.17.0")]
     pub fn ptr_eq(this: &Self, other: &Self) -> bool {
         this.ptr.as_ptr() == other.ptr.as_ptr()
     }
@@ -1904,6 +1908,7 @@ pub fn upgrade(&self) -> Option<Arc<T>> {
     /// Gets the number of strong (`Arc`) pointers pointing to this allocation.
     ///
     /// If `self` was created using [`Weak::new`], this will return 0.
+    #[must_use]
     #[stable(feature = "weak_counts", since = "1.41.0")]
     pub fn strong_count(&self) -> usize {
         if let Some(inner) = self.inner() { inner.strong.load(SeqCst) } else { 0 }
@@ -1920,6 +1925,7 @@ pub fn strong_count(&self) -> usize {
     /// Due to implementation details, the returned value can be off by 1 in
     /// either direction when other threads are manipulating any `Arc`s or
     /// `Weak`s pointing to the same allocation.
+    #[must_use]
     #[stable(feature = "weak_counts", since = "1.41.0")]
     pub fn weak_count(&self) -> usize {
         self.inner()
@@ -1999,6 +2005,7 @@ fn inner(&self) -> Option<WeakInner<'_>> {
     ///
     /// [`ptr::eq`]: core::ptr::eq "ptr::eq"
     #[inline]
+    #[must_use]
     #[stable(feature = "weak_ptr_eq", since = "1.39.0")]
     pub fn ptr_eq(&self, other: &Self) -> bool {
         self.ptr.as_ptr() == other.ptr.as_ptr()
index e643940d017ba690b5873a84ac36de9d86e47a95..ff98091a0d2abf18924b663e78634c827fce6e38 100644 (file)
@@ -60,6 +60,7 @@ pub fn as_slice(&self) -> &[T] {
 
     /// Returns a reference to the underlying allocator.
     #[unstable(feature = "allocator_api", issue = "32838")]
+    #[must_use]
     #[inline]
     pub fn allocator(&self) -> &A {
         unsafe { self.vec.as_ref().allocator() }
index d3a87c056cfb1867b588ad58fd33892a23de3587..dc7d0bff9a404ba8ec417b4ecfd17c3445e4c92d 100644 (file)
@@ -1031,7 +1031,7 @@ fn test_split_at_mut() {
 #[should_panic]
 fn test_split_at_boundscheck() {
     let s = "ศไทย中华Việt Nam";
-    s.split_at(1);
+    let _ = s.split_at(1);
 }
 
 #[test]
index 7f14f76c8ba6945c052fab77022e6e768b58e0b4..b02ed04a7e915659eea6fb1607df469b84a30638 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 7f14f76c8ba6945c052fab77022e6e768b58e0b4
+Subproject commit b02ed04a7e915659eea6fb1607df469b84a30638
index 780f82d8afaee1fbd50b0944123a5fd976aede17..cc32d5223b49f655f691017d675c0d363b5de444 100644 (file)
@@ -104,6 +104,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_stable(feature = "const_alloc_layout", since = "1.50.0")]
+    #[must_use]
     #[inline]
     pub const fn size(&self) -> usize {
         self.size_
@@ -137,6 +138,7 @@ pub const fn new<T>() -> Self {
     /// allocate backing structure for `T` (which could be a trait
     /// or other unsized type like a slice).
     #[stable(feature = "alloc_layout", since = "1.28.0")]
+    #[must_use]
     #[inline]
     pub fn for_value<T: ?Sized>(t: &T) -> Self {
         let (size, align) = (mem::size_of_val(t), mem::align_of_val(t));
@@ -171,6 +173,7 @@ pub fn for_value<T: ?Sized>(t: &T) -> Self {
     /// [trait object]: ../../book/ch17-02-trait-objects.html
     /// [extern type]: ../../unstable-book/language-features/extern-types.html
     #[unstable(feature = "layout_for_ptr", issue = "69835")]
+    #[must_use]
     pub unsafe fn for_value_raw<T: ?Sized>(t: *const T) -> Self {
         // SAFETY: we pass along the prerequisites of these functions to the caller
         let (size, align) = unsafe { (mem::size_of_val_raw(t), mem::align_of_val_raw(t)) };
@@ -187,6 +190,7 @@ pub unsafe fn for_value_raw<T: ?Sized>(t: *const T) -> Self {
     /// some other means.
     #[unstable(feature = "alloc_layout_extra", issue = "55724")]
     #[rustc_const_unstable(feature = "alloc_layout_extra", issue = "55724")]
+    #[must_use]
     #[inline]
     pub const fn dangling(&self) -> NonNull<u8> {
         // SAFETY: align is guaranteed to be non-zero
index 19652106b3d01325f5f9f9266b7932447e594cd1..1fd5aa27fce46562c51ddc6d3b80a7bfc9b45464 100644 (file)
@@ -458,6 +458,7 @@ impl TypeId {
     /// assert_eq!(is_string(&0), false);
     /// assert_eq!(is_string(&"cookie monster".to_string()), true);
     /// ```
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
     pub const fn of<T: ?Sized + 'static>() -> TypeId {
@@ -492,6 +493,7 @@ pub const fn of<T: ?Sized + 'static>() -> TypeId {
 ///     "core::option::Option<alloc::string::String>",
 /// );
 /// ```
+#[must_use]
 #[stable(feature = "type_name", since = "1.38.0")]
 #[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
 pub const fn type_name<T: ?Sized>() -> &'static str {
@@ -534,6 +536,7 @@ pub const fn type_name<T: ?Sized>() -> &'static str {
 /// let y = 1.0;
 /// println!("{}", type_name_of_val(&y));
 /// ```
+#[must_use]
 #[unstable(feature = "type_name_of_val", issue = "66359")]
 #[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
 pub const fn type_name_of_val<T: ?Sized>(_val: &T) -> &'static str {
index 0a456ee1eb2d59fde0ac9d7c2b56382ee0a1da1a..532208e41afa2ba2b01169da64c061d0d5587347 100644 (file)
@@ -18,6 +18,7 @@
 ///
 /// This `struct` is created by the [`escape_default`] function. See its
 /// documentation for more.
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Clone)]
 pub struct EscapeDefault {
index ed464700cd3579764d72bc0c684614f3405970f1..06dc5ecf2ffa610a4f93509ad05e348c2a56b984 100644 (file)
@@ -240,6 +240,11 @@ pub struct Cell<T: ?Sized> {
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<T: ?Sized> Send for Cell<T> where T: Send {}
 
+// Note that this negative impl isn't strictly necessary for correctness,
+// as `Cell` wraps `UnsafeCell`, which is itself `!Sync`.
+// However, given how important `Cell`'s `!Sync`-ness is,
+// having an explicit negative impl is nice for documentation purposes
+// and results in nicer error messages.
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> !Sync for Cell<T> {}
 
@@ -1335,6 +1340,7 @@ impl<'b, T: ?Sized> Ref<'b, T> {
     /// with the widespread use of `r.borrow().clone()` to clone the contents of
     /// a `RefCell`.
     #[stable(feature = "cell_extras", since = "1.15.0")]
+    #[must_use]
     #[inline]
     pub fn clone(orig: &Ref<'b, T>) -> Ref<'b, T> {
         Ref { value: orig.value, borrow: orig.borrow.clone() }
index 4784418f98c507d0313a14c314ac90191b1ce640..5dd8c5ef78941835b3619b63636e2214d00c4620 100644 (file)
@@ -128,6 +128,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 
 impl DecodeUtf16Error {
     /// Returns the unpaired surrogate which caused this error.
+    #[must_use]
     #[stable(feature = "decode_utf16", since = "1.9.0")]
     pub fn unpaired_surrogate(&self) -> u16 {
         self.code
index b02333b028850fd7a831adeb811e3bd6c7b37e61..281ff3badfbd8de32fc47e83cfeec042890dbd67 100644 (file)
 #[stable(feature = "rust1", since = "1.0.0")]
 #[lang = "clone"]
 #[rustc_diagnostic_item = "Clone"]
-#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)]
+#[rustc_trivial_field_reads]
 pub trait Clone: Sized {
     /// Returns a copy of the value.
     ///
index 0ee8cd59ba4ff8c500356d7a407ae315f46c4d61..fb862f7df947bc5d688cf1bb46446a8de968ffee 100644 (file)
@@ -155,6 +155,7 @@ pub trait Default: Sized {
 /// }
 /// ```
 #[unstable(feature = "default_free_fn", issue = "73014")]
+#[must_use]
 #[inline]
 pub fn default<T: Default>() -> T {
     Default::default()
index b8ad7720e0c554590226f08f3d3da7dcbc4b307e..80d3270d73cc824a80759b328ac5dd3eb4fecfe3 100644 (file)
@@ -374,7 +374,6 @@ pub const fn new_v1(pieces: &'a [&'static str], args: &'a [ArgumentV1<'a>]) -> A
     ///    valid index of `args`.
     /// 3. Every [`Count::Param`] within `fmt` must contain a valid index of
     ///    `args`.
-    #[cfg(not(bootstrap))]
     #[doc(hidden)]
     #[inline]
     #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
@@ -388,19 +387,6 @@ pub const fn new_v1_formatted(
         Arguments { pieces, fmt: Some(fmt), args }
     }
 
-    #[cfg(bootstrap)]
-    #[doc(hidden)]
-    #[inline]
-    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
-    #[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
-    pub const unsafe fn new_v1_formatted(
-        pieces: &'a [&'static str],
-        args: &'a [ArgumentV1<'a>],
-        fmt: &'a [rt::v1::Argument],
-    ) -> Arguments<'a> {
-        Arguments { pieces, fmt: Some(fmt), args }
-    }
-
     /// Estimates the length of the formatted text.
     ///
     /// This is intended to be used for setting initial `String` capacity
@@ -619,7 +605,7 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
 )]
 #[doc(alias = "{:?}")]
 #[rustc_diagnostic_item = "Debug"]
-#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)]
+#[rustc_trivial_field_reads]
 pub trait Debug {
     /// Formats the value using the given formatter.
     ///
@@ -1618,6 +1604,7 @@ pub fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result {
     }
 
     /// Flags for formatting
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_deprecated(
         since = "1.24.0",
@@ -1655,6 +1642,7 @@ pub fn flags(&self) -> u32 {
     /// assert_eq!(&format!("{:G>3}", Foo), "GGG");
     /// assert_eq!(&format!("{:t>6}", Foo), "tttttt");
     /// ```
+    #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn fill(&self) -> char {
         self.fill
@@ -1691,6 +1679,7 @@ pub fn fill(&self) -> char {
     /// assert_eq!(&format!("{:^}", Foo), "center");
     /// assert_eq!(&format!("{}", Foo), "into the void");
     /// ```
+    #[must_use]
     #[stable(feature = "fmt_flags_align", since = "1.28.0")]
     pub fn align(&self) -> Option<Alignment> {
         match self.align {
@@ -1725,6 +1714,7 @@ pub fn align(&self) -> Option<Alignment> {
     /// assert_eq!(&format!("{:10}", Foo(23)), "Foo(23)   ");
     /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)");
     /// ```
+    #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn width(&self) -> Option<usize> {
         self.width
@@ -1755,6 +1745,7 @@ pub fn width(&self) -> Option<usize> {
     /// assert_eq!(&format!("{:.4}", Foo(23.2)), "Foo(23.2000)");
     /// assert_eq!(&format!("{}", Foo(23.2)), "Foo(23.20)");
     /// ```
+    #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn precision(&self) -> Option<usize> {
         self.precision
@@ -1785,6 +1776,7 @@ pub fn precision(&self) -> Option<usize> {
     /// assert_eq!(&format!("{:+}", Foo(23)), "Foo(+23)");
     /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)");
     /// ```
+    #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn sign_plus(&self) -> bool {
         self.flags & (1 << FlagV1::SignPlus as u32) != 0
@@ -1813,6 +1805,7 @@ pub fn sign_plus(&self) -> bool {
     /// assert_eq!(&format!("{:-}", Foo(23)), "-Foo(23)");
     /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)");
     /// ```
+    #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn sign_minus(&self) -> bool {
         self.flags & (1 << FlagV1::SignMinus as u32) != 0
@@ -1840,6 +1833,7 @@ pub fn sign_minus(&self) -> bool {
     /// assert_eq!(&format!("{:#}", Foo(23)), "Foo(23)");
     /// assert_eq!(&format!("{}", Foo(23)), "23");
     /// ```
+    #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn alternate(&self) -> bool {
         self.flags & (1 << FlagV1::Alternate as u32) != 0
@@ -1865,6 +1859,7 @@ pub fn alternate(&self) -> bool {
     ///
     /// assert_eq!(&format!("{:04}", Foo(23)), "23");
     /// ```
+    #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn sign_aware_zero_pad(&self) -> bool {
         self.flags & (1 << FlagV1::SignAwareZeroPad as u32) != 0
index cdde0941470121cd172bc0f9d8497bee772bc498..7a3af70d6d97c3fa6533199960b94087ec83e3ce 100644 (file)
@@ -90,6 +90,7 @@ fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
 #[lang = "get_context"]
 #[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
+#[must_use]
 #[inline]
 pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> {
     // SAFETY: the caller must guarantee that `cx.0` is a valid pointer
index be12f90464084306b2b1b8beaba0984936b16320..9c6acfb1e8c94f823ef1cb864dc62541074f9da1 100644 (file)
@@ -5,6 +5,23 @@ macro_rules! forward_ref_unop {
         forward_ref_unop!(impl $imp, $method for $t,
                 #[stable(feature = "rust1", since = "1.0.0")]);
     };
+    (impl const $imp:ident, $method:ident for $t:ty) => {
+        forward_ref_unop!(impl const $imp, $method for $t,
+                #[stable(feature = "rust1", since = "1.0.0")]);
+    };
+    // Equivalent to the non-const version, with the addition of `rustc_const_unstable`
+    (impl const $imp:ident, $method:ident for $t:ty, #[$attr:meta]) => {
+        #[$attr]
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const $imp for &$t {
+            type Output = <$t as $imp>::Output;
+
+            #[inline]
+            fn $method(self) -> <$t as $imp>::Output {
+                $imp::$method(*self)
+            }
+        }
+    };
     (impl $imp:ident, $method:ident for $t:ty, #[$attr:meta]) => {
         #[$attr]
         impl $imp for &$t {
@@ -25,6 +42,45 @@ macro_rules! forward_ref_binop {
         forward_ref_binop!(impl $imp, $method for $t, $u,
                 #[stable(feature = "rust1", since = "1.0.0")]);
     };
+    (impl const $imp:ident, $method:ident for $t:ty, $u:ty) => {
+        forward_ref_binop!(impl const $imp, $method for $t, $u,
+                #[stable(feature = "rust1", since = "1.0.0")]);
+    };
+    // Equivalent to the non-const version, with the addition of `rustc_const_unstable`
+    (impl const $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => {
+        #[$attr]
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl<'a> const $imp<$u> for &'a $t {
+            type Output = <$t as $imp<$u>>::Output;
+
+            #[inline]
+            fn $method(self, other: $u) -> <$t as $imp<$u>>::Output {
+                $imp::$method(*self, other)
+            }
+        }
+
+        #[$attr]
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const $imp<&$u> for $t {
+            type Output = <$t as $imp<$u>>::Output;
+
+            #[inline]
+            fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output {
+                $imp::$method(self, *other)
+            }
+        }
+
+        #[$attr]
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const $imp<&$u> for &$t {
+            type Output = <$t as $imp<$u>>::Output;
+
+            #[inline]
+            fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output {
+                $imp::$method(*self, *other)
+            }
+        }
+    };
     (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => {
         #[$attr]
         impl<'a> $imp<$u> for &'a $t {
@@ -65,6 +121,21 @@ macro_rules! forward_ref_op_assign {
         forward_ref_op_assign!(impl $imp, $method for $t, $u,
                 #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]);
     };
+    (impl const $imp:ident, $method:ident for $t:ty, $u:ty) => {
+        forward_ref_op_assign!(impl const $imp, $method for $t, $u,
+                #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]);
+    };
+    // Equivalent to the non-const version, with the addition of `rustc_const_unstable`
+    (impl const $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => {
+        #[$attr]
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const $imp<&$u> for $t {
+            #[inline]
+            fn $method(&mut self, other: &$u) {
+                $imp::$method(self, *other);
+            }
+        }
+    };
     (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => {
         #[$attr]
         impl $imp<&$u> for $t {
index 1aeb83931e5aa52fa90a53673ade1958fc01bd7e..91230c027c2d2f6e91031b1af3c397e01c1a00dd 100644 (file)
@@ -2252,7 +2252,6 @@ pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
 /// or have any other observable side-effects, the behavior is undefined.
 ///
 /// [referential transparency]: https://en.wikipedia.org/wiki/Referential_transparency
-#[cfg(not(bootstrap))]
 #[unstable(
     feature = "const_eval_select",
     issue = "none",
@@ -2273,7 +2272,6 @@ pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
     called_at_rt.call_once(arg)
 }
 
-#[cfg(not(bootstrap))]
 #[unstable(
     feature = "const_eval_select",
     issue = "none",
index a7d4646f5c5973e63c291142191a519782b2eb38..7abe01d17c90bd46668d87fcb437f8d35b113a25 100644 (file)
@@ -25,6 +25,7 @@ pub const fn empty<T>() -> Empty<T> {
 /// An iterator that yields nothing.
 ///
 /// This `struct` is created by the [`empty()`] function. See its documentation for more.
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "iter_empty", since = "1.2.0")]
 pub struct Empty<T>(marker::PhantomData<T>);
 
index 63c42068aadf93fed9ad6d5c787f2a11409d1f48..4b16a269f2d738c2a93b4811525c88d8cc9cd965 100644 (file)
 #![feature(const_caller_location)]
 #![feature(const_cell_into_inner)]
 #![feature(const_discriminant)]
+#![cfg_attr(not(bootstrap), feature(const_eval_select))]
 #![feature(const_float_bits_conv)]
 #![feature(const_float_classify)]
+#![feature(const_fmt_arguments_new)]
 #![feature(const_heap)]
 #![feature(const_inherent_unchecked_arith)]
 #![feature(const_int_unchecked_arith)]
 #![feature(const_maybe_uninit_as_ptr)]
 #![feature(const_maybe_uninit_assume_init)]
 #![feature(const_num_from_num)]
+#![feature(const_ops)]
 #![feature(const_option)]
 #![feature(const_pin)]
 #![feature(const_replace)]
 #![feature(const_fn_trait_bound)]
 #![feature(const_impl_trait)]
 #![feature(const_mut_refs)]
-#![cfg_attr(bootstrap, feature(const_panic))]
 #![feature(const_precise_live_drops)]
 #![feature(const_raw_ptr_deref)]
 #![feature(const_refs_to_cell)]
 #![feature(doc_notable_trait)]
 #![feature(doc_primitive)]
 #![feature(exhaustive_patterns)]
-#![cfg_attr(not(bootstrap), feature(doc_cfg_hide))]
+#![feature(doc_cfg_hide)]
 #![feature(extern_types)]
 #![feature(fundamental)]
 #![feature(if_let_guard)]
 #![feature(llvm_asm)]
 #![feature(min_specialization)]
 #![feature(mixed_integer_ops)]
-#![cfg_attr(not(bootstrap), feature(must_not_suspend))]
+#![feature(must_not_suspend)]
 #![feature(negative_impls)]
 #![feature(never_type)]
 #![feature(no_core)]
 #![feature(try_blocks)]
 #![feature(unboxed_closures)]
 #![feature(unsized_fn_params)]
+#![cfg_attr(not(bootstrap), feature(asm_const))]
 //
 // Target features:
 #![feature(aarch64_target_feature)]
index e5c3fafe5f1f0a1b097eecc34af57f8ee92430d9..37446bafacb240740873234b3f51dce261457b67 100644 (file)
@@ -30,8 +30,7 @@
 /// [arc]: ../../std/sync/struct.Arc.html
 /// [ub]: ../../reference/behavior-considered-undefined.html
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(all(not(test), bootstrap), rustc_diagnostic_item = "send_trait")]
-#[cfg_attr(all(not(test), not(bootstrap)), rustc_diagnostic_item = "Send")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "Send")]
 #[rustc_on_unimplemented(
     message = "`{Self}` cannot be sent between threads safely",
     label = "`{Self}` cannot be sent between threads safely"
index 894ae10e1b4bae80af9b05996d8e6aa04e10c2c2..7d005666a74a6514e32bd7b55e15e00f87236c74 100644 (file)
@@ -296,6 +296,7 @@ pub fn forget_unsized<T: ?Sized>(t: T) {
 ///
 /// [alignment]: align_of
 #[inline(always)]
+#[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_promotable]
 #[rustc_const_stable(feature = "const_size_of", since = "1.24.0")]
@@ -324,6 +325,7 @@ pub const fn size_of<T>() -> usize {
 /// assert_eq!(13, mem::size_of_val(y));
 /// ```
 #[inline]
+#[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "mem_size_of_val")]
@@ -373,6 +375,7 @@ pub const fn size_of_val<T: ?Sized>(val: &T) -> usize {
 /// assert_eq!(13, unsafe { mem::size_of_val_raw(y) });
 /// ```
 #[inline]
+#[must_use]
 #[unstable(feature = "layout_for_ptr", issue = "69835")]
 #[rustc_const_unstable(feature = "const_size_of_val_raw", issue = "46571")]
 pub const unsafe fn size_of_val_raw<T: ?Sized>(val: *const T) -> usize {
@@ -397,6 +400,7 @@ pub const fn size_of_val<T: ?Sized>(val: &T) -> usize {
 /// assert_eq!(4, mem::min_align_of::<i32>());
 /// ```
 #[inline]
+#[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_deprecated(reason = "use `align_of` instead", since = "1.2.0")]
 pub fn min_align_of<T>() -> usize {
@@ -418,6 +422,7 @@ pub fn min_align_of<T>() -> usize {
 /// assert_eq!(4, mem::min_align_of_val(&5i32));
 /// ```
 #[inline]
+#[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_deprecated(reason = "use `align_of_val` instead", since = "1.2.0")]
 pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
@@ -441,6 +446,7 @@ pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
 /// assert_eq!(4, mem::align_of::<i32>());
 /// ```
 #[inline(always)]
+#[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_promotable]
 #[rustc_const_stable(feature = "const_align_of", since = "1.24.0")]
@@ -462,6 +468,7 @@ pub const fn align_of<T>() -> usize {
 /// assert_eq!(4, mem::align_of_val(&5i32));
 /// ```
 #[inline]
+#[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")]
 #[allow(deprecated)]
@@ -507,6 +514,7 @@ pub const fn align_of_val<T: ?Sized>(val: &T) -> usize {
 /// assert_eq!(4, unsafe { mem::align_of_val_raw(&5i32) });
 /// ```
 #[inline]
+#[must_use]
 #[unstable(feature = "layout_for_ptr", issue = "69835")]
 #[rustc_const_unstable(feature = "const_align_of_val_raw", issue = "46571")]
 pub const unsafe fn align_of_val_raw<T: ?Sized>(val: *const T) -> usize {
@@ -571,6 +579,7 @@ pub const fn align_of_val<T: ?Sized>(val: &T) -> usize {
 /// }
 /// ```
 #[inline]
+#[must_use]
 #[stable(feature = "needs_drop", since = "1.21.0")]
 #[rustc_const_stable(feature = "const_needs_drop", since = "1.36.0")]
 #[rustc_diagnostic_item = "needs_drop"]
@@ -618,6 +627,7 @@ pub const fn needs_drop<T>() -> bool {
 /// let _y: fn() = unsafe { mem::zeroed() }; // And again!
 /// ```
 #[inline(always)]
+#[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow(deprecated_in_future)]
 #[allow(deprecated)]
@@ -653,6 +663,7 @@ pub unsafe fn zeroed<T>() -> T {
 /// [assume_init]: MaybeUninit::assume_init
 /// [inv]: MaybeUninit#initialization-invariant
 #[inline(always)]
+#[must_use]
 #[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow(deprecated_in_future)]
@@ -938,6 +949,7 @@ pub fn drop<T>(_x: T) {}
 /// assert_eq!(foo_array, [10]);
 /// ```
 #[inline]
+#[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_transmute_copy", issue = "83165")]
 pub const unsafe fn transmute_copy<T, U>(src: &T) -> U {
@@ -1051,6 +1063,7 @@ pub const fn discriminant<T>(v: &T) -> Discriminant<T> {
 /// assert_eq!(mem::variant_count::<Result<!, !>>(), 2);
 /// ```
 #[inline(always)]
+#[must_use]
 #[unstable(feature = "variant_count", issue = "73662")]
 #[rustc_const_unstable(feature = "variant_count", issue = "73662")]
 #[rustc_diagnostic_item = "mem_variant_count"]
index 2af61a0748236dd639168e7cd5cd3dcc0a9f8e77..8a9ecbe98dff604a3bc158005236aa66e8dda68e 100644 (file)
@@ -115,6 +115,7 @@ pub enum IntErrorKind {
 
 impl ParseIntError {
     /// Outputs the detailed cause of parsing an integer failing.
+    #[must_use]
     #[stable(feature = "int_error_matching", since = "1.55.0")]
     pub fn kind(&self) -> &IntErrorKind {
         &self.kind
index 83a922ae34891b969d5616ce1ed20d30e60bae2a..905b0c4245801e87c4be00d2684ab3f51cf34564 100644 (file)
@@ -980,6 +980,7 @@ pub const fn from_bits(v: u32) -> Self {
     /// #     .all(|(a, b)| a.to_bits() == b.to_bits()))
     /// ```
     #[unstable(feature = "total_cmp", issue = "72599")]
+    #[must_use]
     #[inline]
     pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
         let mut left = self.to_bits() as i32;
index 4267260eea38cbbb6cc294da4fd7692ffc68344f..112a239a145f6ea374c8c2365157364b512dc3a0 100644 (file)
@@ -996,6 +996,7 @@ pub const fn from_bits(v: u64) -> Self {
     /// #     .all(|(a, b)| a.to_bits() == b.to_bits()))
     /// ```
     #[unstable(feature = "total_cmp", issue = "72599")]
+    #[must_use]
     #[inline]
     pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
         let mut left = self.to_bits() as i64;
index 5ef2558a5fe4bff2fa464e32bac10af17e6a1819..052e1a21b32cbd0379424aae6672ac6bed183856 100644 (file)
@@ -608,8 +608,7 @@ pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
                       without modifying the original"]
         #[inline]
         pub const fn checked_div(self, rhs: Self) -> Option<Self> {
-            // Using `&` helps LLVM see that it is the same check made in division.
-            if unlikely!(rhs == 0 || ((self == Self::MIN) & (rhs == -1))) {
+            if unlikely!(rhs == 0 || ((self == Self::MIN) && (rhs == -1))) {
                 None
             } else {
                 // SAFETY: div by zero and by INT_MIN have been checked above
@@ -662,8 +661,7 @@ pub const fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
                       without modifying the original"]
         #[inline]
         pub const fn checked_rem(self, rhs: Self) -> Option<Self> {
-            // Using `&` helps LLVM see that it is the same check made in division.
-            if unlikely!(rhs == 0 || ((self == Self::MIN) & (rhs == -1))) {
+            if unlikely!(rhs == 0 || ((self == Self::MIN) && (rhs == -1))) {
                 None
             } else {
                 // SAFETY: div by zero and by INT_MIN have been checked above
index 18ebf1cbb1063e51fe3a9970612054d075f2f390..0c00db5fdf37aa38142116eeb970919bb320fda3 100644 (file)
@@ -94,7 +94,13 @@ macro_rules! usize_isize_from_xe_bytes_doc {
 }
 
 macro_rules! widening_impl {
-    ($SelfT:ty, $WideT:ty, $BITS:literal) => {
+    ($SelfT:ty, $WideT:ty, $BITS:literal, unsigned) => {
+        widening_impl!($SelfT, $WideT, $BITS, "");
+    };
+    ($SelfT:ty, $WideT:ty, $BITS:literal, signed) => {
+        widening_impl!($SelfT, $WideT, $BITS, "# //");
+    };
+    ($SelfT:ty, $WideT:ty, $BITS:literal, $AdaptiveTestPrefix:literal) => {
         /// Calculates the complete product `self * rhs` without the possibility to overflow.
         ///
         /// This returns the low-order (wrapping) bits and the high-order (overflow) bits
@@ -148,6 +154,33 @@ pub const fn widening_mul(self, rhs: Self) -> (Self, Self) {
         /// assert_eq!(5u32.carrying_mul(2, 10), (20, 0));
         /// assert_eq!(1_000_000_000u32.carrying_mul(10, 0), (1410065408, 2));
         /// assert_eq!(1_000_000_000u32.carrying_mul(10, 10), (1410065418, 2));
+        #[doc = concat!($AdaptiveTestPrefix, "assert_eq!(",
+            stringify!($SelfT), "::MAX.carrying_mul(", stringify!($SelfT), "::MAX, ", stringify!($SelfT), "::MAX), ",
+            "(0, ", stringify!($SelfT), "::MAX));"
+        )]
+        /// ```
+        ///
+        /// If `carry` is zero, this is similar to [`overflowing_mul`](Self::overflowing_mul),
+        /// except that it gives the value of the overflow instead of just whether one happened:
+        ///
+        /// ```
+        /// #![feature(bigint_helper_methods)]
+        /// let r = u8::carrying_mul(7, 13, 0);
+        /// assert_eq!((r.0, r.1 != 0), u8::overflowing_mul(7, 13));
+        /// let r = u8::carrying_mul(13, 42, 0);
+        /// assert_eq!((r.0, r.1 != 0), u8::overflowing_mul(13, 42));
+        /// ```
+        ///
+        /// The value of the first field in the returned tuple matches what you'd get
+        /// by combining the [`wrapping_mul`](Self::wrapping_mul) and
+        /// [`wrapping_add`](Self::wrapping_add) methods:
+        ///
+        /// ```
+        /// #![feature(bigint_helper_methods)]
+        /// assert_eq!(
+        ///     789_u16.carrying_mul(456, 123).0,
+        ///     789_u16.wrapping_mul(456).wrapping_add(123),
+        /// );
         /// ```
         #[unstable(feature = "bigint_helper_methods", issue = "85532")]
         #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")]
@@ -168,33 +201,33 @@ pub const fn carrying_mul(self, rhs: Self, carry: Self) -> (Self, Self) {
 
 #[lang = "i8"]
 impl i8 {
-    widening_impl! { i8, i16, 8 }
     int_impl! { i8, i8, u8, 8, 7, -128, 127, 2, "-0x7e", "0xa", "0x12", "0x12", "0x48",
     "[0x12]", "[0x12]", "", "" }
+    widening_impl! { i8, i16, 8, signed }
 }
 
 #[lang = "i16"]
 impl i16 {
-    widening_impl! { i16, i32, 16 }
     int_impl! { i16, i16, u16, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412",
     "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
+    widening_impl! { i16, i32, 16, signed }
 }
 
 #[lang = "i32"]
 impl i32 {
-    widening_impl! { i32, i64, 32 }
     int_impl! { i32, i32, u32, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301",
     "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
     "[0x12, 0x34, 0x56, 0x78]", "", "" }
+    widening_impl! { i32, i64, 32, signed }
 }
 
 #[lang = "i64"]
 impl i64 {
-    widening_impl! { i64, i128, 64 }
     int_impl! { i64, i64, u64, 64, 63, -9223372036854775808, 9223372036854775807, 12,
     "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
     "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
     "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "" }
+    widening_impl! { i64, i128, 64, signed }
 }
 
 #[lang = "i128"]
@@ -212,31 +245,31 @@ impl i128 {
 #[cfg(target_pointer_width = "16")]
 #[lang = "isize"]
 impl isize {
-    widening_impl! { isize, i32, 16 }
     int_impl! { isize, i16, usize, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234",
     "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]",
     usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+    widening_impl! { isize, i32, 16, signed }
 }
 
 #[cfg(target_pointer_width = "32")]
 #[lang = "isize"]
 impl isize {
-    widening_impl! { isize, i64, 32 }
     int_impl! { isize, i32, usize, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301",
     "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
     "[0x12, 0x34, 0x56, 0x78]",
     usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+    widening_impl! { isize, i64, 32, signed }
 }
 
 #[cfg(target_pointer_width = "64")]
 #[lang = "isize"]
 impl isize {
-    widening_impl! { isize, i128, 64 }
     int_impl! { isize, i64, usize, 64, 63, -9223372036854775808, 9223372036854775807,
     12, "0xaa00000000006e1", "0x6e10aa",  "0x1234567890123456", "0x5634129078563412",
-     "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
-     "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
-     usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+    "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
+    "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
+    usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+    widening_impl! { isize, i128, 64, signed }
 }
 
 /// If 6th bit set ascii is upper case.
@@ -244,9 +277,9 @@ impl isize {
 
 #[lang = "u8"]
 impl u8 {
-    widening_impl! { u8, u16, 8 }
     uint_impl! { u8, u8, i8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]",
     "[0x12]", "", "" }
+    widening_impl! { u8, u16, 8, unsigned }
 
     /// Checks if the value is within the ASCII range.
     ///
@@ -793,26 +826,26 @@ pub fn escape_ascii(&self) -> ascii::EscapeDefault {
 
 #[lang = "u16"]
 impl u16 {
-    widening_impl! { u16, u32, 16 }
     uint_impl! { u16, u16, i16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
     "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
+    widening_impl! { u16, u32, 16, unsigned }
 }
 
 #[lang = "u32"]
 impl u32 {
-    widening_impl! { u32, u64, 32 }
     uint_impl! { u32, u32, i32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
     "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" }
+    widening_impl! { u32, u64, 32, unsigned }
 }
 
 #[lang = "u64"]
 impl u64 {
-    widening_impl! { u64, u128, 64 }
     uint_impl! { u64, u64, i64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
     "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
     "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
     "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
     "", ""}
+    widening_impl! { u64, u128, 64, unsigned }
 }
 
 #[lang = "u128"]
@@ -830,29 +863,29 @@ impl u128 {
 #[cfg(target_pointer_width = "16")]
 #[lang = "usize"]
 impl usize {
-    widening_impl! { usize, u32, 16 }
     uint_impl! { usize, u16, isize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
     "[0x34, 0x12]", "[0x12, 0x34]",
     usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+    widening_impl! { usize, u32, 16, unsigned }
 }
 #[cfg(target_pointer_width = "32")]
 #[lang = "usize"]
 impl usize {
-    widening_impl! { usize, u64, 32 }
     uint_impl! { usize, u32, isize, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
     "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]",
     usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+    widening_impl! { usize, u64, 32, unsigned }
 }
 
 #[cfg(target_pointer_width = "64")]
 #[lang = "usize"]
 impl usize {
-    widening_impl! { usize, u128, 64 }
     uint_impl! { usize, u64, isize, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
     "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
     "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
-     "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
+    "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
     usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+    widening_impl! { usize, u128, 64, unsigned }
 }
 
 /// A classification of floating point numbers.
index 9b1a4de5d80378ce7016c058f575f6f481241cff..7708094e1fceab656457dbd297339a35f914319e 100644 (file)
@@ -92,7 +92,8 @@ fn from(nonzero: $Ty) -> Self {
             }
 
             #[stable(feature = "nonzero_bitor", since = "1.45.0")]
-            impl BitOr for $Ty {
+            #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+            impl const BitOr for $Ty {
                 type Output = Self;
                 #[inline]
                 fn bitor(self, rhs: Self) -> Self::Output {
@@ -103,7 +104,8 @@ fn bitor(self, rhs: Self) -> Self::Output {
             }
 
             #[stable(feature = "nonzero_bitor", since = "1.45.0")]
-            impl BitOr<$Int> for $Ty {
+            #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+            impl const BitOr<$Int> for $Ty {
                 type Output = Self;
                 #[inline]
                 fn bitor(self, rhs: $Int) -> Self::Output {
@@ -115,7 +117,8 @@ fn bitor(self, rhs: $Int) -> Self::Output {
             }
 
             #[stable(feature = "nonzero_bitor", since = "1.45.0")]
-            impl BitOr<$Ty> for $Int {
+            #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+            impl const BitOr<$Ty> for $Int {
                 type Output = $Ty;
                 #[inline]
                 fn bitor(self, rhs: $Ty) -> Self::Output {
@@ -127,7 +130,8 @@ fn bitor(self, rhs: $Ty) -> Self::Output {
             }
 
             #[stable(feature = "nonzero_bitor", since = "1.45.0")]
-            impl BitOrAssign for $Ty {
+            #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+            impl const BitOrAssign for $Ty {
                 #[inline]
                 fn bitor_assign(&mut self, rhs: Self) {
                     *self = *self | rhs;
@@ -135,7 +139,8 @@ fn bitor_assign(&mut self, rhs: Self) {
             }
 
             #[stable(feature = "nonzero_bitor", since = "1.45.0")]
-            impl BitOrAssign<$Int> for $Ty {
+            #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+            impl const BitOrAssign<$Int> for $Ty {
                 #[inline]
                 fn bitor_assign(&mut self, rhs: $Int) {
                     *self = *self | rhs;
@@ -257,7 +262,8 @@ macro_rules! nonzero_integers_div {
     ( $( $Ty: ident($Int: ty); )+ ) => {
         $(
             #[stable(feature = "nonzero_div", since = "1.51.0")]
-            impl Div<$Ty> for $Int {
+            #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+            impl const Div<$Ty> for $Int {
                 type Output = $Int;
                 /// This operation rounds towards zero,
                 /// truncating any fractional part of the exact result, and cannot panic.
@@ -270,7 +276,8 @@ fn div(self, other: $Ty) -> $Int {
             }
 
             #[stable(feature = "nonzero_div", since = "1.51.0")]
-            impl Rem<$Ty> for $Int {
+            #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+            impl const Rem<$Ty> for $Int {
                 type Output = $Int;
                 /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic.
                 #[inline]
index 507ff516a8f2813124b924665d6653885549dedd..a15eabf7966d8ab2fd7cdc18ea7c6a535b7c7354 100644 (file)
@@ -1504,6 +1504,8 @@ pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
         /// additional bit of overflow. This allows for chaining together multiple additions
         /// to create "big integers" which represent larger values.
         ///
+        #[doc = concat!("This can be thought of as a ", stringify!($BITS), "-bit \"full adder\", in the electronics sense.")]
+        ///
         /// # Examples
         ///
         /// Basic usage
@@ -1513,7 +1515,20 @@ pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
         #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, false), (7, false));")]
         #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, true), (8, false));")]
         #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), (0, true));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(0, true), (0, true));")]
         #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, true), (1, true));")]
+        #[doc = concat!("assert_eq!(",
+            stringify!($SelfT), "::MAX.carrying_add(", stringify!($SelfT), "::MAX, true), ",
+            "(", stringify!($SelfT), "::MAX, true));"
+        )]
+        /// ```
+        ///
+        /// If `carry` is false, this method is equivalent to [`overflowing_add`](Self::overflowing_add):
+        ///
+        /// ```
+        /// #![feature(bigint_helper_methods)]
+        #[doc = concat!("assert_eq!(5_", stringify!($SelfT), ".carrying_add(2, false), 5_", stringify!($SelfT), ".overflowing_add(2));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), ", stringify!($SelfT), "::MAX.overflowing_add(1));")]
         /// ```
         #[unstable(feature = "bigint_helper_methods", issue = "85532")]
         #[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
@@ -1525,7 +1540,7 @@ pub const fn carrying_add(self, rhs: Self, carry: bool) -> (Self, bool) {
             //   to generate optimal code for now, and LLVM doesn't have an equivalent intrinsic
             let (a, b) = self.overflowing_add(rhs);
             let (c, d) = a.overflowing_add(carry as $SelfT);
-            (c, b | d)
+            (c, b || d)
         }
 
         /// Calculates `self` + `rhs` with a signed `rhs`
@@ -1606,7 +1621,7 @@ pub const fn borrowing_sub(self, rhs: Self, borrow: bool) -> (Self, bool) {
             //   to generate optimal code for now, and LLVM doesn't have an equivalent intrinsic
             let (a, b) = self.overflowing_sub(rhs);
             let (c, d) = a.overflowing_sub(borrow as $SelfT);
-            (c, b | d)
+            (c, b || d)
         }
 
         /// Computes the absolute difference between `self` and `other`.
index f387bd5b41cc453ef9cd956af7f5e65341ff06bc..a0e42c51e4517a8091baa59893d90752983cac9b 100644 (file)
@@ -87,7 +87,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 macro_rules! sh_impl_signed {
     ($t:ident, $f:ident) => {
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl Shl<$f> for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Shl<$f> for Wrapping<$t> {
             type Output = Wrapping<$t>;
 
             #[inline]
@@ -99,20 +100,22 @@ fn shl(self, other: $f) -> Wrapping<$t> {
                 }
             }
         }
-        forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f,
+        forward_ref_binop! { impl const Shl, shl for Wrapping<$t>, $f,
         #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl ShlAssign<$f> for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const ShlAssign<$f> for Wrapping<$t> {
             #[inline]
             fn shl_assign(&mut self, other: $f) {
                 *self = *self << other;
             }
         }
-        forward_ref_op_assign! { impl ShlAssign, shl_assign for Wrapping<$t>, $f }
+        forward_ref_op_assign! { impl const ShlAssign, shl_assign for Wrapping<$t>, $f }
 
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl Shr<$f> for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Shr<$f> for Wrapping<$t> {
             type Output = Wrapping<$t>;
 
             #[inline]
@@ -124,24 +127,26 @@ fn shr(self, other: $f) -> Wrapping<$t> {
                 }
             }
         }
-        forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f,
+        forward_ref_binop! { impl const Shr, shr for Wrapping<$t>, $f,
         #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl ShrAssign<$f> for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const ShrAssign<$f> for Wrapping<$t> {
             #[inline]
             fn shr_assign(&mut self, other: $f) {
                 *self = *self >> other;
             }
         }
-        forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f }
+        forward_ref_op_assign! { impl const ShrAssign, shr_assign for Wrapping<$t>, $f }
     };
 }
 
 macro_rules! sh_impl_unsigned {
     ($t:ident, $f:ident) => {
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl Shl<$f> for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Shl<$f> for Wrapping<$t> {
             type Output = Wrapping<$t>;
 
             #[inline]
@@ -149,20 +154,22 @@ fn shl(self, other: $f) -> Wrapping<$t> {
                 Wrapping(self.0.wrapping_shl((other & self::shift_max::$t as $f) as u32))
             }
         }
-        forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f,
+        forward_ref_binop! { impl const Shl, shl for Wrapping<$t>, $f,
         #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl ShlAssign<$f> for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const ShlAssign<$f> for Wrapping<$t> {
             #[inline]
             fn shl_assign(&mut self, other: $f) {
                 *self = *self << other;
             }
         }
-        forward_ref_op_assign! { impl ShlAssign, shl_assign for Wrapping<$t>, $f }
+        forward_ref_op_assign! { impl const ShlAssign, shl_assign for Wrapping<$t>, $f }
 
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl Shr<$f> for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Shr<$f> for Wrapping<$t> {
             type Output = Wrapping<$t>;
 
             #[inline]
@@ -170,17 +177,18 @@ fn shr(self, other: $f) -> Wrapping<$t> {
                 Wrapping(self.0.wrapping_shr((other & self::shift_max::$t as $f) as u32))
             }
         }
-        forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f,
+        forward_ref_binop! { impl const Shr, shr for Wrapping<$t>, $f,
         #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl ShrAssign<$f> for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const ShrAssign<$f> for Wrapping<$t> {
             #[inline]
             fn shr_assign(&mut self, other: $f) {
                 *self = *self >> other;
             }
         }
-        forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f }
+        forward_ref_op_assign! { impl const ShrAssign, shr_assign for Wrapping<$t>, $f }
     };
 }
 
@@ -209,7 +217,8 @@ macro_rules! sh_impl_all {
 macro_rules! wrapping_impl {
     ($($t:ty)*) => ($(
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl Add for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Add for Wrapping<$t> {
             type Output = Wrapping<$t>;
 
             #[inline]
@@ -217,20 +226,22 @@ fn add(self, other: Wrapping<$t>) -> Wrapping<$t> {
                 Wrapping(self.0.wrapping_add(other.0))
             }
         }
-        forward_ref_binop! { impl Add, add for Wrapping<$t>, Wrapping<$t>,
+        forward_ref_binop! { impl const Add, add for Wrapping<$t>, Wrapping<$t>,
                 #[stable(feature = "wrapping_ref", since = "1.14.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl AddAssign for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const AddAssign for Wrapping<$t> {
             #[inline]
             fn add_assign(&mut self, other: Wrapping<$t>) {
                 *self = *self + other;
             }
         }
-        forward_ref_op_assign! { impl AddAssign, add_assign for Wrapping<$t>, Wrapping<$t> }
+        forward_ref_op_assign! { impl const AddAssign, add_assign for Wrapping<$t>, Wrapping<$t> }
 
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl Sub for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Sub for Wrapping<$t> {
             type Output = Wrapping<$t>;
 
             #[inline]
@@ -238,20 +249,22 @@ fn sub(self, other: Wrapping<$t>) -> Wrapping<$t> {
                 Wrapping(self.0.wrapping_sub(other.0))
             }
         }
-        forward_ref_binop! { impl Sub, sub for Wrapping<$t>, Wrapping<$t>,
+        forward_ref_binop! { impl const Sub, sub for Wrapping<$t>, Wrapping<$t>,
                 #[stable(feature = "wrapping_ref", since = "1.14.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl SubAssign for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const SubAssign for Wrapping<$t> {
             #[inline]
             fn sub_assign(&mut self, other: Wrapping<$t>) {
                 *self = *self - other;
             }
         }
-        forward_ref_op_assign! { impl SubAssign, sub_assign for Wrapping<$t>, Wrapping<$t> }
+        forward_ref_op_assign! { impl const SubAssign, sub_assign for Wrapping<$t>, Wrapping<$t> }
 
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl Mul for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Mul for Wrapping<$t> {
             type Output = Wrapping<$t>;
 
             #[inline]
@@ -263,16 +276,18 @@ fn mul(self, other: Wrapping<$t>) -> Wrapping<$t> {
                 #[stable(feature = "wrapping_ref", since = "1.14.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl MulAssign for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const MulAssign for Wrapping<$t> {
             #[inline]
             fn mul_assign(&mut self, other: Wrapping<$t>) {
                 *self = *self * other;
             }
         }
-        forward_ref_op_assign! { impl MulAssign, mul_assign for Wrapping<$t>, Wrapping<$t> }
+        forward_ref_op_assign! { impl const MulAssign, mul_assign for Wrapping<$t>, Wrapping<$t> }
 
         #[stable(feature = "wrapping_div", since = "1.3.0")]
-        impl Div for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Div for Wrapping<$t> {
             type Output = Wrapping<$t>;
 
             #[inline]
@@ -280,20 +295,22 @@ fn div(self, other: Wrapping<$t>) -> Wrapping<$t> {
                 Wrapping(self.0.wrapping_div(other.0))
             }
         }
-        forward_ref_binop! { impl Div, div for Wrapping<$t>, Wrapping<$t>,
+        forward_ref_binop! { impl const Div, div for Wrapping<$t>, Wrapping<$t>,
                 #[stable(feature = "wrapping_ref", since = "1.14.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl DivAssign for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const DivAssign for Wrapping<$t> {
             #[inline]
             fn div_assign(&mut self, other: Wrapping<$t>) {
                 *self = *self / other;
             }
         }
-        forward_ref_op_assign! { impl DivAssign, div_assign for Wrapping<$t>, Wrapping<$t> }
+        forward_ref_op_assign! { impl const DivAssign, div_assign for Wrapping<$t>, Wrapping<$t> }
 
         #[stable(feature = "wrapping_impls", since = "1.7.0")]
-        impl Rem for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Rem for Wrapping<$t> {
             type Output = Wrapping<$t>;
 
             #[inline]
@@ -301,20 +318,22 @@ fn rem(self, other: Wrapping<$t>) -> Wrapping<$t> {
                 Wrapping(self.0.wrapping_rem(other.0))
             }
         }
-        forward_ref_binop! { impl Rem, rem for Wrapping<$t>, Wrapping<$t>,
+        forward_ref_binop! { impl const Rem, rem for Wrapping<$t>, Wrapping<$t>,
                 #[stable(feature = "wrapping_ref", since = "1.14.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl RemAssign for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const RemAssign for Wrapping<$t> {
             #[inline]
             fn rem_assign(&mut self, other: Wrapping<$t>) {
                 *self = *self % other;
             }
         }
-        forward_ref_op_assign! { impl RemAssign, rem_assign for Wrapping<$t>, Wrapping<$t> }
+        forward_ref_op_assign! { impl const RemAssign, rem_assign for Wrapping<$t>, Wrapping<$t> }
 
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl Not for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Not for Wrapping<$t> {
             type Output = Wrapping<$t>;
 
             #[inline]
@@ -322,11 +341,12 @@ fn not(self) -> Wrapping<$t> {
                 Wrapping(!self.0)
             }
         }
-        forward_ref_unop! { impl Not, not for Wrapping<$t>,
+        forward_ref_unop! { impl const Not, not for Wrapping<$t>,
                 #[stable(feature = "wrapping_ref", since = "1.14.0")] }
 
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl BitXor for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const BitXor for Wrapping<$t> {
             type Output = Wrapping<$t>;
 
             #[inline]
@@ -334,20 +354,22 @@ fn bitxor(self, other: Wrapping<$t>) -> Wrapping<$t> {
                 Wrapping(self.0 ^ other.0)
             }
         }
-        forward_ref_binop! { impl BitXor, bitxor for Wrapping<$t>, Wrapping<$t>,
+        forward_ref_binop! { impl const BitXor, bitxor for Wrapping<$t>, Wrapping<$t>,
                 #[stable(feature = "wrapping_ref", since = "1.14.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl BitXorAssign for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const BitXorAssign for Wrapping<$t> {
             #[inline]
             fn bitxor_assign(&mut self, other: Wrapping<$t>) {
                 *self = *self ^ other;
             }
         }
-        forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Wrapping<$t>, Wrapping<$t> }
+        forward_ref_op_assign! { impl const BitXorAssign, bitxor_assign for Wrapping<$t>, Wrapping<$t> }
 
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl BitOr for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const BitOr for Wrapping<$t> {
             type Output = Wrapping<$t>;
 
             #[inline]
@@ -355,20 +377,22 @@ fn bitor(self, other: Wrapping<$t>) -> Wrapping<$t> {
                 Wrapping(self.0 | other.0)
             }
         }
-        forward_ref_binop! { impl BitOr, bitor for Wrapping<$t>, Wrapping<$t>,
+        forward_ref_binop! { impl const BitOr, bitor for Wrapping<$t>, Wrapping<$t>,
                 #[stable(feature = "wrapping_ref", since = "1.14.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl BitOrAssign for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const BitOrAssign for Wrapping<$t> {
             #[inline]
             fn bitor_assign(&mut self, other: Wrapping<$t>) {
                 *self = *self | other;
             }
         }
-        forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Wrapping<$t>, Wrapping<$t> }
+        forward_ref_op_assign! { impl const BitOrAssign, bitor_assign for Wrapping<$t>, Wrapping<$t> }
 
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl BitAnd for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const BitAnd for Wrapping<$t> {
             type Output = Wrapping<$t>;
 
             #[inline]
@@ -376,27 +400,29 @@ fn bitand(self, other: Wrapping<$t>) -> Wrapping<$t> {
                 Wrapping(self.0 & other.0)
             }
         }
-        forward_ref_binop! { impl BitAnd, bitand for Wrapping<$t>, Wrapping<$t>,
+        forward_ref_binop! { impl const BitAnd, bitand for Wrapping<$t>, Wrapping<$t>,
                 #[stable(feature = "wrapping_ref", since = "1.14.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl BitAndAssign for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const BitAndAssign for Wrapping<$t> {
             #[inline]
             fn bitand_assign(&mut self, other: Wrapping<$t>) {
                 *self = *self & other;
             }
         }
-        forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Wrapping<$t>, Wrapping<$t> }
+        forward_ref_op_assign! { impl const BitAndAssign, bitand_assign for Wrapping<$t>, Wrapping<$t> }
 
         #[stable(feature = "wrapping_neg", since = "1.10.0")]
-        impl Neg for Wrapping<$t> {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Neg for Wrapping<$t> {
             type Output = Self;
             #[inline]
             fn neg(self) -> Self {
                 Wrapping(0) - self
             }
         }
-        forward_ref_unop! { impl Neg, neg for Wrapping<$t>,
+        forward_ref_unop! { impl const Neg, neg for Wrapping<$t>,
                 #[stable(feature = "wrapping_ref", since = "1.14.0")] }
 
     )*)
index a0577b287ce24fa886e715298111b082e128f880..e954742938910cc4f36ea5f2432e7fe761a7a851 100644 (file)
@@ -92,7 +92,8 @@ pub trait Add<Rhs = Self> {
 macro_rules! add_impl {
     ($($t:ty)*) => ($(
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl Add for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Add for $t {
             type Output = $t;
 
             #[inline]
@@ -100,7 +101,7 @@ impl Add for $t {
             fn add(self, other: $t) -> $t { self + other }
         }
 
-        forward_ref_binop! { impl Add, add for $t, $t }
+        forward_ref_binop! { impl const Add, add for $t, $t }
     )*)
 }
 
@@ -198,7 +199,8 @@ pub trait Sub<Rhs = Self> {
 macro_rules! sub_impl {
     ($($t:ty)*) => ($(
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl Sub for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Sub for $t {
             type Output = $t;
 
             #[inline]
@@ -206,7 +208,7 @@ impl Sub for $t {
             fn sub(self, other: $t) -> $t { self - other }
         }
 
-        forward_ref_binop! { impl Sub, sub for $t, $t }
+        forward_ref_binop! { impl const Sub, sub for $t, $t }
     )*)
 }
 
@@ -326,7 +328,8 @@ pub trait Mul<Rhs = Self> {
 macro_rules! mul_impl {
     ($($t:ty)*) => ($(
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl Mul for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Mul for $t {
             type Output = $t;
 
             #[inline]
@@ -334,7 +337,7 @@ impl Mul for $t {
             fn mul(self, other: $t) -> $t { self * other }
         }
 
-        forward_ref_binop! { impl Mul, mul for $t, $t }
+        forward_ref_binop! { impl const Mul, mul for $t, $t }
     )*)
 }
 
@@ -464,14 +467,15 @@ macro_rules! div_impl_integer {
         ///
         #[doc = $panic]
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl Div for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Div for $t {
             type Output = $t;
 
             #[inline]
             fn div(self, other: $t) -> $t { self / other }
         }
 
-        forward_ref_binop! { impl Div, div for $t, $t }
+        forward_ref_binop! { impl const Div, div for $t, $t }
     )*)*)
 }
 
@@ -483,14 +487,15 @@ fn div(self, other: $t) -> $t { self / other }
 macro_rules! div_impl_float {
     ($($t:ty)*) => ($(
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl Div for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Div for $t {
             type Output = $t;
 
             #[inline]
             fn div(self, other: $t) -> $t { self / other }
         }
 
-        forward_ref_binop! { impl Div, div for $t, $t }
+        forward_ref_binop! { impl const Div, div for $t, $t }
     )*)
 }
 
@@ -564,14 +569,15 @@ macro_rules! rem_impl_integer {
         ///
         #[doc = $panic]
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl Rem for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Rem for $t {
             type Output = $t;
 
             #[inline]
             fn rem(self, other: $t) -> $t { self % other }
         }
 
-        forward_ref_binop! { impl Rem, rem for $t, $t }
+        forward_ref_binop! { impl const Rem, rem for $t, $t }
     )*)*)
 }
 
@@ -598,14 +604,15 @@ macro_rules! rem_impl_float {
         /// assert_eq!(x % y, remainder);
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl Rem for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Rem for $t {
             type Output = $t;
 
             #[inline]
             fn rem(self, other: $t) -> $t { self % other }
         }
 
-        forward_ref_binop! { impl Rem, rem for $t, $t }
+        forward_ref_binop! { impl const Rem, rem for $t, $t }
     )*)
 }
 
@@ -671,7 +678,8 @@ pub trait Neg {
 macro_rules! neg_impl {
     ($($t:ty)*) => ($(
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl Neg for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Neg for $t {
             type Output = $t;
 
             #[inline]
@@ -679,7 +687,7 @@ impl Neg for $t {
             fn neg(self) -> $t { -self }
         }
 
-        forward_ref_unop! { impl Neg, neg for $t }
+        forward_ref_unop! { impl const Neg, neg for $t }
     )*)
 }
 
@@ -739,13 +747,14 @@ pub trait AddAssign<Rhs = Self> {
 macro_rules! add_assign_impl {
     ($($t:ty)+) => ($(
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl AddAssign for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const AddAssign for $t {
             #[inline]
             #[rustc_inherit_overflow_checks]
             fn add_assign(&mut self, other: $t) { *self += other }
         }
 
-        forward_ref_op_assign! { impl AddAssign, add_assign for $t, $t }
+        forward_ref_op_assign! { impl const AddAssign, add_assign for $t, $t }
     )+)
 }
 
@@ -805,13 +814,14 @@ pub trait SubAssign<Rhs = Self> {
 macro_rules! sub_assign_impl {
     ($($t:ty)+) => ($(
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl SubAssign for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const SubAssign for $t {
             #[inline]
             #[rustc_inherit_overflow_checks]
             fn sub_assign(&mut self, other: $t) { *self -= other }
         }
 
-        forward_ref_op_assign! { impl SubAssign, sub_assign for $t, $t }
+        forward_ref_op_assign! { impl const SubAssign, sub_assign for $t, $t }
     )+)
 }
 
@@ -862,13 +872,14 @@ pub trait MulAssign<Rhs = Self> {
 macro_rules! mul_assign_impl {
     ($($t:ty)+) => ($(
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl MulAssign for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const MulAssign for $t {
             #[inline]
             #[rustc_inherit_overflow_checks]
             fn mul_assign(&mut self, other: $t) { *self *= other }
         }
 
-        forward_ref_op_assign! { impl MulAssign, mul_assign for $t, $t }
+        forward_ref_op_assign! { impl const MulAssign, mul_assign for $t, $t }
     )+)
 }
 
@@ -919,12 +930,13 @@ pub trait DivAssign<Rhs = Self> {
 macro_rules! div_assign_impl {
     ($($t:ty)+) => ($(
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl DivAssign for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const DivAssign for $t {
             #[inline]
             fn div_assign(&mut self, other: $t) { *self /= other }
         }
 
-        forward_ref_op_assign! { impl DivAssign, div_assign for $t, $t }
+        forward_ref_op_assign! { impl const DivAssign, div_assign for $t, $t }
     )+)
 }
 
@@ -979,12 +991,13 @@ pub trait RemAssign<Rhs = Self> {
 macro_rules! rem_assign_impl {
     ($($t:ty)+) => ($(
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl RemAssign for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const RemAssign for $t {
             #[inline]
             fn rem_assign(&mut self, other: $t) { *self %= other }
         }
 
-        forward_ref_op_assign! { impl RemAssign, rem_assign for $t, $t }
+        forward_ref_op_assign! { impl const RemAssign, rem_assign for $t, $t }
     )+)
 }
 
index 92f45ac9e7ea9251c39e9cdd4d9cd1a6703cff16..255f6cb7933a244271100cc9cd556cf06e8938c8 100644 (file)
@@ -54,14 +54,15 @@ pub trait Not {
 macro_rules! not_impl {
     ($($t:ty)*) => ($(
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl Not for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Not for $t {
             type Output = $t;
 
             #[inline]
             fn not(self) -> $t { !self }
         }
 
-        forward_ref_unop! { impl Not, not for $t }
+        forward_ref_unop! { impl const Not, not for $t }
     )*)
 }
 
@@ -154,14 +155,15 @@ pub trait BitAnd<Rhs = Self> {
 macro_rules! bitand_impl {
     ($($t:ty)*) => ($(
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl BitAnd for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const BitAnd for $t {
             type Output = $t;
 
             #[inline]
             fn bitand(self, rhs: $t) -> $t { self & rhs }
         }
 
-        forward_ref_binop! { impl BitAnd, bitand for $t, $t }
+        forward_ref_binop! { impl const BitAnd, bitand for $t, $t }
     )*)
 }
 
@@ -254,14 +256,15 @@ pub trait BitOr<Rhs = Self> {
 macro_rules! bitor_impl {
     ($($t:ty)*) => ($(
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl BitOr for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const BitOr for $t {
             type Output = $t;
 
             #[inline]
             fn bitor(self, rhs: $t) -> $t { self | rhs }
         }
 
-        forward_ref_binop! { impl BitOr, bitor for $t, $t }
+        forward_ref_binop! { impl const BitOr, bitor for $t, $t }
     )*)
 }
 
@@ -354,14 +357,15 @@ pub trait BitXor<Rhs = Self> {
 macro_rules! bitxor_impl {
     ($($t:ty)*) => ($(
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl BitXor for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const BitXor for $t {
             type Output = $t;
 
             #[inline]
             fn bitxor(self, other: $t) -> $t { self ^ other }
         }
 
-        forward_ref_binop! { impl BitXor, bitxor for $t, $t }
+        forward_ref_binop! { impl const BitXor, bitxor for $t, $t }
     )*)
 }
 
@@ -451,7 +455,8 @@ pub trait Shl<Rhs = Self> {
 macro_rules! shl_impl {
     ($t:ty, $f:ty) => {
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl Shl<$f> for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Shl<$f> for $t {
             type Output = $t;
 
             #[inline]
@@ -461,7 +466,7 @@ fn shl(self, other: $f) -> $t {
             }
         }
 
-        forward_ref_binop! { impl Shl, shl for $t, $f }
+        forward_ref_binop! { impl const Shl, shl for $t, $f }
     };
 }
 
@@ -569,7 +574,8 @@ pub trait Shr<Rhs = Self> {
 macro_rules! shr_impl {
     ($t:ty, $f:ty) => {
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl Shr<$f> for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const Shr<$f> for $t {
             type Output = $t;
 
             #[inline]
@@ -579,7 +585,7 @@ fn shr(self, other: $f) -> $t {
             }
         }
 
-        forward_ref_binop! { impl Shr, shr for $t, $f }
+        forward_ref_binop! { impl const Shr, shr for $t, $f }
     };
 }
 
@@ -704,12 +710,13 @@ pub trait BitAndAssign<Rhs = Self> {
 macro_rules! bitand_assign_impl {
     ($($t:ty)+) => ($(
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl BitAndAssign for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const BitAndAssign for $t {
             #[inline]
             fn bitand_assign(&mut self, other: $t) { *self &= other }
         }
 
-        forward_ref_op_assign! { impl BitAndAssign, bitand_assign for $t, $t }
+        forward_ref_op_assign! { impl const BitAndAssign, bitand_assign for $t, $t }
     )+)
 }
 
@@ -775,12 +782,13 @@ pub trait BitOrAssign<Rhs = Self> {
 macro_rules! bitor_assign_impl {
     ($($t:ty)+) => ($(
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl BitOrAssign for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const BitOrAssign for $t {
             #[inline]
             fn bitor_assign(&mut self, other: $t) { *self |= other }
         }
 
-        forward_ref_op_assign! { impl BitOrAssign, bitor_assign for $t, $t }
+        forward_ref_op_assign! { impl const BitOrAssign, bitor_assign for $t, $t }
     )+)
 }
 
@@ -846,12 +854,13 @@ pub trait BitXorAssign<Rhs = Self> {
 macro_rules! bitxor_assign_impl {
     ($($t:ty)+) => ($(
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl BitXorAssign for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const BitXorAssign for $t {
             #[inline]
             fn bitxor_assign(&mut self, other: $t) { *self ^= other }
         }
 
-        forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for $t, $t }
+        forward_ref_op_assign! { impl const BitXorAssign, bitxor_assign for $t, $t }
     )+)
 }
 
@@ -907,7 +916,8 @@ pub trait ShlAssign<Rhs = Self> {
 macro_rules! shl_assign_impl {
     ($t:ty, $f:ty) => {
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl ShlAssign<$f> for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const ShlAssign<$f> for $t {
             #[inline]
             #[rustc_inherit_overflow_checks]
             fn shl_assign(&mut self, other: $f) {
@@ -915,7 +925,7 @@ fn shl_assign(&mut self, other: $f) {
             }
         }
 
-        forward_ref_op_assign! { impl ShlAssign, shl_assign for $t, $f }
+        forward_ref_op_assign! { impl const ShlAssign, shl_assign for $t, $f }
     };
 }
 
@@ -989,7 +999,8 @@ pub trait ShrAssign<Rhs = Self> {
 macro_rules! shr_assign_impl {
     ($t:ty, $f:ty) => {
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl ShrAssign<$f> for $t {
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const ShrAssign<$f> for $t {
             #[inline]
             #[rustc_inherit_overflow_checks]
             fn shr_assign(&mut self, other: $f) {
@@ -997,7 +1008,7 @@ fn shr_assign(&mut self, other: $f) {
             }
         }
 
-        forward_ref_op_assign! { impl ShrAssign, shr_assign for $t, $f }
+        forward_ref_op_assign! { impl const ShrAssign, shr_assign for $t, $f }
     };
 }
 
index cd2d57699c92c95e797b647c68480d0c60905377..b0c15898a1fd86a362db3c931ea5bf499a5e34d1 100644 (file)
@@ -7,6 +7,10 @@
 /// Having the enum makes it clearer -- no more wondering "wait, what did `false`
 /// mean again?" -- and allows including a value.
 ///
+/// Similar to [`Option`] and [`Result`], this enum can be used with the `?` operator
+/// to return immediately if the [`Break`] variant is present or otherwise continue normally
+/// with the value inside the [`Continue`] variant.
+///
 /// # Examples
 ///
 /// Early-exiting from [`Iterator::try_for_each`]:
@@ -24,7 +28,7 @@
 /// ```
 ///
 /// A basic tree traversal:
-/// ```no_run
+/// ```
 /// use std::ops::ControlFlow;
 ///
 /// pub struct TreeNode<T> {
 /// }
 ///
 /// impl<T> TreeNode<T> {
-///     pub fn traverse_inorder<B>(&self, mut f: impl FnMut(&T) -> ControlFlow<B>) -> ControlFlow<B> {
+///     pub fn traverse_inorder<B>(&self, f: &mut impl FnMut(&T) -> ControlFlow<B>) -> ControlFlow<B> {
 ///         if let Some(left) = &self.left {
-///             left.traverse_inorder(&mut f)?;
+///             left.traverse_inorder(f)?;
 ///         }
 ///         f(&self.value)?;
 ///         if let Some(right) = &self.right {
-///             right.traverse_inorder(&mut f)?;
+///             right.traverse_inorder(f)?;
 ///         }
 ///         ControlFlow::Continue(())
 ///     }
+///     fn leaf(value: T) -> Option<Box<TreeNode<T>>> {
+///         Some(Box::new(Self { value, left: None, right: None }))
+///     }
 /// }
+///
+/// let node = TreeNode {
+///     value: 0,
+///     left: TreeNode::leaf(1),
+///     right: Some(Box::new(TreeNode {
+///         value: -1,
+///         left: TreeNode::leaf(5),
+///         right: TreeNode::leaf(2),
+///     }))
+/// };
+/// let mut sum = 0;
+///
+/// let res = node.traverse_inorder(&mut |val| {
+///     if *val < 0 {
+///         ControlFlow::Break(*val)
+///     } else {
+///         sum += *val;
+///         ControlFlow::Continue(())
+///     }
+/// });
+/// assert_eq!(res, ControlFlow::Break(-1));
+/// assert_eq!(sum, 6);
 /// ```
+///
+/// [`Break`]: ControlFlow::Break
+/// [`Continue`]: ControlFlow::Continue
 #[stable(feature = "control_flow_enum_type", since = "1.55.0")]
 #[derive(Debug, Clone, Copy, PartialEq)]
 pub enum ControlFlow<B, C = ()> {
index 347a346359f8cf5e9f25d9b58ab68b8bb554ce05..b74ba92c76eb6e459c5989c40e8b1388503f20fe 100644 (file)
@@ -743,6 +743,7 @@ impl<T: Clone> Bound<&T> {
     /// assert_eq!((1..12).start_bound(), Included(&1));
     /// assert_eq!((1..12).start_bound().cloned(), Included(1));
     /// ```
+    #[must_use = "`self` will be dropped if the result is not used"]
     #[stable(feature = "bound_cloned", since = "1.55.0")]
     pub fn cloned(self) -> Bound<T> {
         match self {
index f4ce7d1dfb334e9c973c5d381baba3033b897f6f..baf9948857bbe1e0c2d96eeaad6827e0727bebcd 100644 (file)
@@ -800,19 +800,17 @@ pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
     /// # Examples
     ///
     /// ```
-    /// #![feature(option_result_unwrap_unchecked)]
     /// let x = Some("air");
     /// assert_eq!(unsafe { x.unwrap_unchecked() }, "air");
     /// ```
     ///
     /// ```no_run
-    /// #![feature(option_result_unwrap_unchecked)]
     /// let x: Option<&str> = None;
     /// assert_eq!(unsafe { x.unwrap_unchecked() }, "air"); // Undefined behavior!
     /// ```
     #[inline]
     #[track_caller]
-    #[unstable(feature = "option_result_unwrap_unchecked", reason = "newly added", issue = "81383")]
+    #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")]
     pub unsafe fn unwrap_unchecked(self) -> T {
         debug_assert!(self.is_some());
         match self {
@@ -1451,6 +1449,7 @@ impl<T: Copy> Option<&T> {
     /// let copied = opt_x.copied();
     /// assert_eq!(copied, Some(12));
     /// ```
+    #[must_use = "`self` will be dropped if the result is not used"]
     #[stable(feature = "copied", since = "1.35.0")]
     #[rustc_const_unstable(feature = "const_option", issue = "67441")]
     pub const fn copied(self) -> Option<T> {
index a482414caaf9ae1c2149186bc6a849afe8452420..714e9b73c78a61f71e4c32e8c2a46dc51eeaa7d2 100644 (file)
@@ -79,6 +79,7 @@ impl<'a> Location<'a> {
     /// assert_ne!(this_location.line(), another_location.line());
     /// assert_ne!(this_location.column(), another_location.column());
     /// ```
+    #[must_use]
     #[stable(feature = "track_caller", since = "1.46.0")]
     #[rustc_const_unstable(feature = "const_caller_location", issue = "76156")]
     #[track_caller]
@@ -119,6 +120,7 @@ pub const fn caller() -> &'static Location<'static> {
     ///
     /// panic!("Normal panic");
     /// ```
+    #[must_use]
     #[stable(feature = "panic_hooks", since = "1.10.0")]
     pub fn file(&self) -> &str {
         self.file
@@ -141,6 +143,7 @@ pub fn file(&self) -> &str {
     ///
     /// panic!("Normal panic");
     /// ```
+    #[must_use]
     #[stable(feature = "panic_hooks", since = "1.10.0")]
     pub fn line(&self) -> u32 {
         self.line
@@ -163,6 +166,7 @@ pub fn line(&self) -> u32 {
     ///
     /// panic!("Normal panic");
     /// ```
+    #[must_use]
     #[stable(feature = "panic_col", since = "1.25.0")]
     pub fn column(&self) -> u32 {
         self.col
index 649bc3e44ad21e9462079b2d54324d7ce93c9cde..d8e421df5de5d321bd7e4d18d536091afa4e8c7a 100644 (file)
@@ -81,6 +81,7 @@ pub fn set_payload(&mut self, info: &'a (dyn Any + Send)) {
     ///
     /// panic!("Normal panic");
     /// ```
+    #[must_use]
     #[stable(feature = "panic_hooks", since = "1.10.0")]
     pub fn payload(&self) -> &(dyn Any + Send) {
         self.payload
@@ -89,6 +90,7 @@ pub fn payload(&self) -> &(dyn Any + Send) {
     /// If the `panic!` macro from the `core` crate (not from `std`)
     /// was used with a formatting string and some additional arguments,
     /// returns that message ready to be used for example with [`fmt::write`]
+    #[must_use]
     #[unstable(feature = "panic_info_message", issue = "66745")]
     pub fn message(&self) -> Option<&fmt::Arguments<'_>> {
         self.message
@@ -118,6 +120,7 @@ pub fn message(&self) -> Option<&fmt::Arguments<'_>> {
     ///
     /// panic!("Normal panic");
     /// ```
+    #[must_use]
     #[stable(feature = "panic_hooks", since = "1.10.0")]
     pub fn location(&self) -> Option<&Location<'_>> {
         // NOTE: If this is changed to sometimes return None,
index a12447acf7ec3c3221b92f563369ed033d71d71b..29124c87e1bc5ff805c466cdd1ef874843efbbb6 100644 (file)
 // never inline unless panic_immediate_abort to avoid code
 // bloat at the call sites as much as possible
 #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
+#[cfg_attr(feature = "panic_immediate_abort", inline)]
 #[track_caller]
 #[lang = "panic"] // needed by codegen for panic on overflow and other `Assert` MIR terminators
-pub fn panic(expr: &'static str) -> ! {
-    if cfg!(feature = "panic_immediate_abort") {
-        super::intrinsics::abort()
-    }
-
+pub const fn panic(expr: &'static str) -> ! {
     // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially
     // reduce size overhead. The format_args! macro uses str's Display trait to
     // write expr, which calls Formatter::pad, which must accommodate string
@@ -52,15 +49,16 @@ pub fn panic(expr: &'static str) -> ! {
 
 #[inline]
 #[track_caller]
-#[lang = "panic_str"] // needed for const-evaluated panics
-pub fn panic_str(expr: &str) -> ! {
-    panic_fmt(format_args!("{}", expr));
+#[lang = "panic_str"] // needed for `non-fmt-panics` lint
+pub const fn panic_str(expr: &str) -> ! {
+    panic_display(&expr);
 }
 
 #[inline]
 #[track_caller]
-#[cfg_attr(not(bootstrap), lang = "panic_display")] // needed for const-evaluated panics
-pub fn panic_display<T: fmt::Display>(x: &T) -> ! {
+#[lang = "panic_display"] // needed for const-evaluated panics
+#[rustc_do_not_const_check] // hooked by const-eval
+pub const fn panic_display<T: fmt::Display>(x: &T) -> ! {
     panic_fmt(format_args!("{}", *x));
 }
 
@@ -89,7 +87,8 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
 #[cfg_attr(feature = "panic_immediate_abort", inline)]
 #[track_caller]
 #[lang = "panic_fmt"] // needed for const-evaluated panics
-pub fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
+#[rustc_do_not_const_check] // hooked by const-eval
+pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
     if cfg!(feature = "panic_immediate_abort") {
         super::intrinsics::abort()
     }
index 34fc874ada09b7171017fcf43f9ec3b01462ab31..09fc6df5429759ce336bd08b7670b710d68dfce3 100644 (file)
@@ -705,6 +705,7 @@ pub unsafe fn map_unchecked<U, F>(self, func: F) -> Pin<&'a U>
     ///
     /// ["pinning projections"]: self#projections-and-structural-pinning
     #[inline(always)]
+    #[must_use]
     #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
     #[stable(feature = "pin", since = "1.33.0")]
     pub const fn get_ref(self) -> &'a T {
index 014170604ecaa573230c0de95f0d19709a694186..8ab72e6aeeafa3844d37b1c0e4abeee2b64c599f 100644 (file)
@@ -204,6 +204,7 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
 /// assert!(p.is_null());
 /// ```
 #[inline(always)]
+#[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_promotable]
 #[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
@@ -223,6 +224,7 @@ pub const fn null<T>() -> *const T {
 /// assert!(p.is_null());
 /// ```
 #[inline(always)]
+#[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_promotable]
 #[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
index 8bae66ca007a74bb68613d6163dacc3213bca307..58110b068094381e9ac2e74130dab235c9608bf2 100644 (file)
@@ -83,6 +83,7 @@ impl<T: Sized> NonNull<T> {
     /// ```
     #[stable(feature = "nonnull", since = "1.25.0")]
     #[rustc_const_stable(feature = "const_nonnull_dangling", since = "1.36.0")]
+    #[must_use]
     #[inline]
     pub const fn dangling() -> Self {
         // SAFETY: mem::align_of() returns a non-zero usize which is then casted
@@ -423,6 +424,7 @@ impl<T> NonNull<[T]> {
     /// but `let slice = NonNull::from(&x[..]);` would be a better way to write code like this.)
     #[unstable(feature = "nonnull_slice_from_raw_parts", issue = "71941")]
     #[rustc_const_unstable(feature = "const_nonnull_slice_from_raw_parts", issue = "71941")]
+    #[must_use]
     #[inline]
     pub const fn slice_from_raw_parts(data: NonNull<T>, len: usize) -> Self {
         // SAFETY: `data` is a `NonNull` pointer which is necessarily non-null
@@ -447,6 +449,7 @@ pub const fn slice_from_raw_parts(data: NonNull<T>, len: usize) -> Self {
     /// ```
     #[unstable(feature = "slice_ptr_len", issue = "71146")]
     #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")]
+    #[must_use]
     #[inline]
     pub const fn len(self) -> usize {
         self.as_ptr().len()
index f6eb48f2967c86f7c0a4c9e7d2f873b5e19febda..d650a6f974b972c209f8f4b8f89746c39782ed5c 100644 (file)
@@ -68,6 +68,7 @@ impl<T: Sized> Unique<T> {
     /// a `T`, which means this must not be used as a "not yet initialized"
     /// sentinel value. Types that lazily allocate must track initialization by
     /// some other means.
+    #[must_use]
     #[inline]
     pub const fn dangling() -> Self {
         // SAFETY: mem::align_of() returns a valid, non-null pointer. The
index 75f2c222ba83461bda54d49e52103c8f489930e7..8fec2e928aae2505b8154d91c813dec46c5e627d 100644 (file)
@@ -1096,19 +1096,17 @@ pub fn unwrap_or_else<F: FnOnce(E) -> T>(self, op: F) -> T {
     /// # Examples
     ///
     /// ```
-    /// #![feature(option_result_unwrap_unchecked)]
     /// let x: Result<u32, &str> = Ok(2);
     /// assert_eq!(unsafe { x.unwrap_unchecked() }, 2);
     /// ```
     ///
     /// ```no_run
-    /// #![feature(option_result_unwrap_unchecked)]
     /// let x: Result<u32, &str> = Err("emergency failure");
     /// unsafe { x.unwrap_unchecked(); } // Undefined behavior!
     /// ```
     #[inline]
     #[track_caller]
-    #[unstable(feature = "option_result_unwrap_unchecked", reason = "newly added", issue = "81383")]
+    #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")]
     pub unsafe fn unwrap_unchecked(self) -> T {
         debug_assert!(self.is_ok());
         match self {
@@ -1130,19 +1128,17 @@ pub unsafe fn unwrap_unchecked(self) -> T {
     /// # Examples
     ///
     /// ```no_run
-    /// #![feature(option_result_unwrap_unchecked)]
     /// let x: Result<u32, &str> = Ok(2);
     /// unsafe { x.unwrap_err_unchecked() }; // Undefined behavior!
     /// ```
     ///
     /// ```
-    /// #![feature(option_result_unwrap_unchecked)]
     /// let x: Result<u32, &str> = Err("emergency failure");
     /// assert_eq!(unsafe { x.unwrap_err_unchecked() }, "emergency failure");
     /// ```
     #[inline]
     #[track_caller]
-    #[unstable(feature = "option_result_unwrap_unchecked", reason = "newly added", issue = "81383")]
+    #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")]
     pub unsafe fn unwrap_err_unchecked(self) -> E {
         debug_assert!(self.is_err());
         match self {
index cbb5627cef9820b544ee98e3251d58efb65a29db..080256f493f5ffe95d2148d88f4f2ab384fb49c0 100644 (file)
@@ -11,6 +11,7 @@
 impl [u8] {
     /// Checks if all bytes in this slice are within the ASCII range.
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[must_use]
     #[inline]
     pub fn is_ascii(&self) -> bool {
         is_ascii(self)
@@ -21,6 +22,7 @@ pub fn is_ascii(&self) -> bool {
     /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
     /// but without allocating and copying temporaries.
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[must_use]
     #[inline]
     pub fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool {
         self.len() == other.len() && iter::zip(self, other).all(|(a, b)| a.eq_ignore_ascii_case(b))
index 07ecae7830351eac72860ea614923af9ab9d8ec1..ad1d6b8b846a00433e422a92918e795522b2a0e9 100644 (file)
@@ -1724,6 +1724,7 @@ pub(super) fn new(slice: &'a [T], chunk_size: usize) -> Self {
     /// Returns the remainder of the original slice that is not going to be
     /// returned by the iterator. The returned slice has at most `chunk_size-1`
     /// elements.
+    #[must_use]
     #[stable(feature = "chunks_exact", since = "1.31.0")]
     pub fn remainder(&self) -> &'a [T] {
         self.rem
@@ -2153,6 +2154,7 @@ pub(super) fn new(slice: &'a [T]) -> Self {
     /// Returns the remainder of the original slice that is not going to be
     /// returned by the iterator. The returned slice has at most `N-1`
     /// elements.
+    #[must_use]
     #[unstable(feature = "array_chunks", issue = "74985")]
     pub fn remainder(&self) -> &'a [T] {
         self.rem
@@ -2728,6 +2730,7 @@ pub(super) fn new(slice: &'a [T], chunk_size: usize) -> Self {
     /// Returns the remainder of the original slice that is not going to be
     /// returned by the iterator. The returned slice has at most `chunk_size-1`
     /// elements.
+    #[must_use]
     #[stable(feature = "rchunks", since = "1.31.0")]
     pub fn remainder(&self) -> &'a [T] {
         self.rem
index 08077c700da69c0991f611e0ec5e7265f9c84fca..6da99055f2d5af887c03997e0f90e7880d561a89 100644 (file)
@@ -37,6 +37,7 @@ fn repeat_byte(b: u8) -> usize {
 }
 
 /// Returns the first index matching the byte `x` in `text`.
+#[must_use]
 #[inline]
 pub fn memchr(x: u8, text: &[u8]) -> Option<usize> {
     // Fast path for small slices
@@ -91,6 +92,7 @@ fn memchr_general_case(x: u8, text: &[u8]) -> Option<usize> {
 }
 
 /// Returns the last index matching the byte `x` in `text`.
+#[must_use]
 pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
     // Scan for a single byte value by reading two `usize` words at a time.
     //
index aaa00653b99c274cc6fda272fe74402d3143bfaa..65ed72cb0cdbe24ca0a2bf493ca1db779ac0cce3 100644 (file)
@@ -553,9 +553,9 @@ pub const fn as_mut_ptr_range(&mut self) -> Range<*mut T> {
     /// # Examples
     ///
     /// ```
-    /// let mut v = ["a", "b", "c", "d"];
-    /// v.swap(1, 3);
-    /// assert!(v == ["a", "d", "c", "b"]);
+    /// let mut v = ["a", "b", "c", "d", "e"];
+    /// v.swap(2, 4);
+    /// assert!(v == ["a", "b", "e", "d", "c"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -3076,6 +3076,7 @@ pub fn fill_with<F>(&mut self, mut f: F)
     /// [`copy_from_slice`]: slice::copy_from_slice
     /// [`split_at_mut`]: slice::split_at_mut
     #[stable(feature = "clone_from_slice", since = "1.7.0")]
+    #[track_caller]
     pub fn clone_from_slice(&mut self, src: &[T])
     where
         T: Clone,
@@ -3139,6 +3140,7 @@ pub fn clone_from_slice(&mut self, src: &[T])
     /// [`split_at_mut`]: slice::split_at_mut
     #[doc(alias = "memcpy")]
     #[stable(feature = "copy_from_slice", since = "1.9.0")]
+    #[track_caller]
     pub fn copy_from_slice(&mut self, src: &[T])
     where
         T: Copy,
@@ -3259,6 +3261,7 @@ pub fn copy_within<R: RangeBounds<usize>>(&mut self, src: R, dest: usize)
     ///
     /// [`split_at_mut`]: slice::split_at_mut
     #[stable(feature = "swap_with_slice", since = "1.27.0")]
+    #[track_caller]
     pub fn swap_with_slice(&mut self, other: &mut [T]) {
         assert!(self.len() == other.len(), "destination and source slices have different lengths");
         // SAFETY: `self` is valid for `self.len()` elements by definition, and `src` was
@@ -3581,6 +3584,7 @@ impl<T> CloneFromSpec<T> for [T]
 where
     T: Clone,
 {
+    #[track_caller]
     default fn spec_clone_from(&mut self, src: &[T]) {
         assert!(self.len() == src.len(), "destination and source slices have different lengths");
         // NOTE: We need to explicitly slice them to the same length
@@ -3598,6 +3602,7 @@ impl<T> CloneFromSpec<T> for [T]
 where
     T: Copy,
 {
+    #[track_caller]
     fn spec_clone_from(&mut self, src: &[T]) {
         self.copy_from_slice(src);
     }
index ad38aaf9f8300f4d95e25ccf3111b4c83c72ad81..81bb16d54015e9551266e41068e1bb6ec63cd5a5 100644 (file)
@@ -1,8 +1,6 @@
 //! Free functions to create `&[T]` and `&mut [T]`.
 
 use crate::array;
-use crate::intrinsics::is_aligned_and_not_null;
-use crate::mem;
 use crate::ptr;
 
 /// Forms a slice from a pointer and a length.
 /// [`NonNull::dangling()`]: ptr::NonNull::dangling
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
-    debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice");
-    debug_assert!(
-        mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
-        "attempt to create slice covering at least half the address space"
-    );
+#[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")]
+pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
+    debug_check_data_len(data, len);
+
     // SAFETY: the caller must uphold the safety contract for `from_raw_parts`.
     unsafe { &*ptr::slice_from_raw_parts(data, len) }
 }
@@ -126,16 +122,48 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
 /// [`NonNull::dangling()`]: ptr::NonNull::dangling
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
-    debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice");
-    debug_assert!(
-        mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
-        "attempt to create slice covering at least half the address space"
-    );
+#[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")]
+pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
+    debug_check_data_len(data as _, len);
+
     // SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`.
     unsafe { &mut *ptr::slice_from_raw_parts_mut(data, len) }
 }
 
+// In debug builds checks that `data` pointer is aligned and non-null and that slice with given `len` would cover less than half the address space
+#[cfg(all(not(bootstrap), debug_assertions))]
+#[unstable(feature = "const_slice_from_raw_parts", issue = "67456")]
+#[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")]
+const fn debug_check_data_len<T>(data: *const T, len: usize) {
+    fn rt_check<T>(data: *const T) {
+        use crate::intrinsics::is_aligned_and_not_null;
+
+        assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice");
+    }
+
+    const fn noop<T>(_: *const T) {}
+
+    // SAFETY:
+    //
+    // `rt_check` is just a debug assert to hint users that they are causing UB,
+    // it is not required for safety (the safety must be guatanteed by
+    // the `from_raw_parts[_mut]` caller).
+    //
+    // Since the checks are not required, we ignore them in CTFE as they can't
+    // be done there (alignment does not make much sense there).
+    unsafe {
+        crate::intrinsics::const_eval_select((data,), noop, rt_check);
+    }
+
+    assert!(
+        crate::mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
+        "attempt to create slice covering at least half the address space"
+    );
+}
+
+#[cfg(not(all(not(bootstrap), debug_assertions)))]
+const fn debug_check_data_len<T>(_data: *const T, _len: usize) {}
+
 /// Converts a reference to T into a slice of length 1 (without copying).
 #[stable(feature = "from_ref", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_slice_from_ref", issue = "90206")]
index aa735a14cbd8fff3cab848c8a9340a0ee8243f3a..b6460d72fef32abc13f70a7a74581411131aaeaf 100644 (file)
@@ -72,6 +72,7 @@ impl Utf8Error {
     /// assert_eq!(1, error.valid_up_to());
     /// ```
     #[stable(feature = "utf8_error", since = "1.5.0")]
+    #[must_use]
     #[inline]
     pub fn valid_up_to(&self) -> usize {
         self.valid_up_to
@@ -93,6 +94,7 @@ pub fn valid_up_to(&self) -> usize {
     ///
     /// [U+FFFD]: ../../std/char/constant.REPLACEMENT_CHARACTER.html
     #[stable(feature = "utf8_error_error_len", since = "1.20.0")]
+    #[must_use]
     #[inline]
     pub fn error_len(&self) -> Option<usize> {
         self.error_len.map(|len| len as usize)
index 94cb81e9d41a1f2543c7b1afab56eccb0692b85d..94a534c6e797e8a65357c4d50dadffe7b2848513 100644 (file)
@@ -27,6 +27,7 @@
 /// [`char`]: prim@char
 /// [`chars`]: str::chars
 #[derive(Clone)]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Chars<'a> {
     pub(super) iter: slice::Iter<'a, u8>,
@@ -125,6 +126,7 @@ pub fn as_str(&self) -> &'a str {
 /// [`char`]: prim@char
 /// [`char_indices`]: str::char_indices
 #[derive(Clone, Debug)]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct CharIndices<'a> {
     pub(super) front_offset: usize,
@@ -211,6 +213,7 @@ pub fn as_str(&self) -> &'a str {
     /// assert_eq!(chars.next(), None);
     /// ```
     #[inline]
+    #[must_use]
     #[unstable(feature = "char_indices_offset", issue = "83871")]
     pub fn offset(&self) -> usize {
         self.front_offset
@@ -223,6 +226,7 @@ pub fn offset(&self) -> usize {
 /// See its documentation for more.
 ///
 /// [`bytes`]: str::bytes
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Clone, Debug)]
 pub struct Bytes<'a>(pub(super) Copied<slice::Iter<'a, u8>>);
@@ -1089,6 +1093,7 @@ fn next_back(&mut self) -> Option<&'a str>
 ///
 /// [`lines`]: str::lines
 #[stable(feature = "rust1", since = "1.0.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[derive(Clone, Debug)]
 pub struct Lines<'a>(pub(super) Map<SplitTerminator<'a, char>, LinesAnyMap>);
 
@@ -1128,6 +1133,7 @@ impl FusedIterator for Lines<'_> {}
 /// [`lines_any`]: str::lines_any
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_deprecated(since = "1.4.0", reason = "use lines()/Lines instead now")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[derive(Clone, Debug)]
 #[allow(deprecated)]
 pub struct LinesAny<'a>(pub(super) Lines<'a>);
index d3c9d21c3c756c0acaec68fa99ad823787d71aef..6c21a5e802026b858073de5ebe0f2abdc27377cc 100644 (file)
@@ -29,6 +29,7 @@ pub fn chunks(&self) -> Utf8LossyChunksIter<'_> {
 }
 
 /// Iterator over lossy UTF-8 string
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[unstable(feature = "str_internals", issue = "none")]
 #[allow(missing_debug_implementations)]
 pub struct Utf8LossyChunksIter<'a> {
index 607a0179ff4b9a515ca69bd02522291ea1e42788..cd5ed35be79ba6769938b11624d94b99d941e7c8 100644 (file)
@@ -140,6 +140,7 @@ impl str {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_str_len", since = "1.39.0")]
+    #[must_use]
     #[inline]
     pub const fn len(&self) -> usize {
         self.as_bytes().len()
@@ -158,9 +159,10 @@ pub const fn len(&self) -> usize {
     /// let s = "not empty";
     /// assert!(!s.is_empty());
     /// ```
-    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_str_is_empty", since = "1.39.0")]
+    #[must_use]
+    #[inline]
     pub const fn is_empty(&self) -> bool {
         self.len() == 0
     }
@@ -498,6 +500,7 @@ pub unsafe fn get_unchecked_mut<I: SliceIndex<str>>(&mut self, i: I) -> &mut I::
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_deprecated(since = "1.29.0", reason = "use `get_unchecked(begin..end)` instead")]
+    #[must_use]
     #[inline]
     pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str {
         // SAFETY: the caller must uphold the safety contract for `get_unchecked`;
@@ -570,6 +573,7 @@ pub unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut s
     /// assert_eq!(" Martin-Löf", last);
     /// ```
     #[inline]
+    #[must_use]
     #[stable(feature = "str_split_at", since = "1.4.0")]
     pub fn split_at(&self, mid: usize) -> (&str, &str) {
         // is_char_boundary checks that the index is in [0, .len()]
@@ -613,6 +617,7 @@ pub fn split_at(&self, mid: usize) -> (&str, &str) {
     /// assert_eq!("PER Martin-Löf", s);
     /// ```
     #[inline]
+    #[must_use]
     #[stable(feature = "str_split_at", since = "1.4.0")]
     pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
         // is_char_boundary checks that the index is in [0, .len()]
@@ -1663,7 +1668,7 @@ pub fn rmatches<'a, P>(&'a self, pat: P) -> RMatches<'a, P>
     /// If the pattern allows a reverse search but its results might differ
     /// from a forward search, the [`rmatch_indices`] method can be used.
     ///
-    /// [`rmatch_indices`]: str::match_indices
+    /// [`rmatch_indices`]: str::rmatch_indices
     ///
     /// # Examples
     ///
@@ -2255,6 +2260,7 @@ pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
     /// assert!(!non_ascii.is_ascii());
     /// ```
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[must_use]
     #[inline]
     pub fn is_ascii(&self) -> bool {
         // We can treat each byte as character here: all multibyte characters
@@ -2276,6 +2282,7 @@ pub fn is_ascii(&self) -> bool {
     /// assert!(!"Ferrös".eq_ignore_ascii_case("FERRÖS"));
     /// ```
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[must_use]
     #[inline]
     pub fn eq_ignore_ascii_case(&self, other: &str) -> bool {
         self.as_bytes().eq_ignore_ascii_case(other.as_bytes())
index 55ac1aa765c1fabc0cdf6166a1d9dfabfb9c032e..031fb8e8b21fb8f853c859faf75b11ff801a438a 100644 (file)
@@ -22,6 +22,8 @@
 //! assert_eq!(s.find("you"), Some(4));
 //! // char pattern
 //! assert_eq!(s.find('n'), Some(2));
+//! // array of chars pattern
+//! assert_eq!(s.find(&['a', 'e', 'i', 'o', 'u']), Some(1));
 //! // slice of chars pattern
 //! assert_eq!(s.find(&['a', 'e', 'i', 'o', 'u'][..]), Some(1));
 //! // closure pattern
 /// assert_eq!("abaaa".find('b'), Some(1));
 /// assert_eq!("abaaa".find('c'), None);
 ///
+/// // &[char; N]
+/// assert_eq!("ab".find(&['b', 'a']), Some(0));
+/// assert_eq!("abaaa".find(&['a', 'z']), Some(0));
+/// assert_eq!("abaaa".find(&['c', 'd']), None);
+///
 /// // &[char]
 /// assert_eq!("ab".find(&['b', 'a'][..]), Some(0));
 /// assert_eq!("abaaa".find(&['a', 'z'][..]), Some(0));
@@ -601,6 +608,20 @@ fn matches(&mut self, c: char) -> bool {
     }
 }
 
+impl<const N: usize> MultiCharEq for [char; N] {
+    #[inline]
+    fn matches(&mut self, c: char) -> bool {
+        self.iter().any(|&m| m == c)
+    }
+}
+
+impl<const N: usize> MultiCharEq for &[char; N] {
+    #[inline]
+    fn matches(&mut self, c: char) -> bool {
+        self.iter().any(|&m| m == c)
+    }
+}
+
 impl MultiCharEq for &[char] {
     #[inline]
     fn matches(&mut self, c: char) -> bool {
@@ -752,6 +773,58 @@ fn next_reject_back(&mut self) -> Option<(usize, usize)> {
     };
 }
 
+/// Associated type for `<[char; N] as Pattern<'a>>::Searcher`.
+#[derive(Clone, Debug)]
+pub struct CharArraySearcher<'a, const N: usize>(
+    <MultiCharEqPattern<[char; N]> as Pattern<'a>>::Searcher,
+);
+
+/// Associated type for `<&[char; N] as Pattern<'a>>::Searcher`.
+#[derive(Clone, Debug)]
+pub struct CharArrayRefSearcher<'a, 'b, const N: usize>(
+    <MultiCharEqPattern<&'b [char; N]> as Pattern<'a>>::Searcher,
+);
+
+/// Searches for chars that are equal to any of the [`char`]s in the array.
+///
+/// # Examples
+///
+/// ```
+/// assert_eq!("Hello world".find(['l', 'l']), Some(2));
+/// assert_eq!("Hello world".find(['l', 'l']), Some(2));
+/// ```
+impl<'a, const N: usize> Pattern<'a> for [char; N] {
+    pattern_methods!(CharArraySearcher<'a, N>, MultiCharEqPattern, CharArraySearcher);
+}
+
+unsafe impl<'a, const N: usize> Searcher<'a> for CharArraySearcher<'a, N> {
+    searcher_methods!(forward);
+}
+
+unsafe impl<'a, const N: usize> ReverseSearcher<'a> for CharArraySearcher<'a, N> {
+    searcher_methods!(reverse);
+}
+
+/// Searches for chars that are equal to any of the [`char`]s in the array.
+///
+/// # Examples
+///
+/// ```
+/// assert_eq!("Hello world".find(&['l', 'l']), Some(2));
+/// assert_eq!("Hello world".find(&['l', 'l']), Some(2));
+/// ```
+impl<'a, 'b, const N: usize> Pattern<'a> for &'b [char; N] {
+    pattern_methods!(CharArrayRefSearcher<'a, 'b, N>, MultiCharEqPattern, CharArrayRefSearcher);
+}
+
+unsafe impl<'a, 'b, const N: usize> Searcher<'a> for CharArrayRefSearcher<'a, 'b, N> {
+    searcher_methods!(forward);
+}
+
+unsafe impl<'a, 'b, const N: usize> ReverseSearcher<'a> for CharArrayRefSearcher<'a, 'b, N> {
+    searcher_methods!(reverse);
+}
+
 /////////////////////////////////////////////////////////////////////////////
 // Impl for &[char]
 /////////////////////////////////////////////////////////////////////////////
index e225776bc647fe6d11e7d4e0f19e49d747303963..952676247489f938b1db7970fc9e97d94134e7b3 100644 (file)
@@ -234,7 +234,7 @@ fn index_mut(self, slice: &mut str) -> &mut Self::Output {
 /// Implements substring slicing with syntax `&self[.. end]` or `&mut
 /// self[.. end]`.
 ///
-/// Returns a slice of the given string from the byte range [`0`, `end`).
+/// Returns a slice of the given string from the byte range \[0, `end`).
 /// Equivalent to `&self[0 .. end]` or `&mut self[0 .. end]`.
 ///
 /// This operation is *O*(1).
@@ -304,9 +304,8 @@ fn index_mut(self, slice: &mut str) -> &mut Self::Output {
 /// Implements substring slicing with syntax `&self[begin ..]` or `&mut
 /// self[begin ..]`.
 ///
-/// Returns a slice of the given string from the byte range [`begin`,
-/// `len`). Equivalent to `&self[begin .. len]` or `&mut self[begin ..
-/// len]`.
+/// Returns a slice of the given string from the byte range \[`begin`, `len`).
+/// Equivalent to `&self[begin .. len]` or `&mut self[begin .. len]`.
 ///
 /// This operation is *O*(1).
 ///
@@ -433,7 +432,7 @@ fn index_mut(self, slice: &mut str) -> &mut Self::Output {
 /// Implements substring slicing with syntax `&self[..= end]` or `&mut
 /// self[..= end]`.
 ///
-/// Returns a slice of the given string from the byte range [0, `end`].
+/// Returns a slice of the given string from the byte range \[0, `end`\].
 /// Equivalent to `&self [0 .. end + 1]`, except if `end` has the maximum
 /// value for `usize`.
 ///
index 093c9c37b60b418b5be6481869946f26ae1f120e..9a1cf905e3b025c9aed55a9d56804da08d2482e3 100644 (file)
@@ -210,7 +210,7 @@ macro_rules! next {
                         // break if there is a nonascii byte
                         let zu = contains_nonascii(*block);
                         let zv = contains_nonascii(*block.offset(1));
-                        if zu | zv {
+                        if zu || zv {
                             break;
                         }
                     }
@@ -251,6 +251,7 @@ macro_rules! next {
 
 /// Given a first byte, determines how many bytes are in this UTF-8 character.
 #[unstable(feature = "str_internals", issue = "none")]
+#[must_use]
 #[inline]
 pub fn utf8_char_width(b: u8) -> usize {
     UTF8_CHAR_WIDTH[b as usize] as usize
index 620bff538799425c28ba158723712b072beca39f..6cba781c2ed8f6d41f1cc16b724b7c8022295aab 100644 (file)
@@ -167,6 +167,7 @@ pub fn from_waker(waker: &'a Waker) -> Self {
 
     /// Returns a reference to the `Waker` for the current task.
     #[stable(feature = "futures_api", since = "1.36.0")]
+    #[must_use]
     #[inline]
     pub fn waker(&self) -> &'a Waker {
         &self.waker
@@ -242,6 +243,7 @@ pub fn wake_by_ref(&self) {
     ///
     /// This function is primarily used for optimization purposes.
     #[inline]
+    #[must_use]
     #[stable(feature = "futures_api", since = "1.36.0")]
     pub fn will_wake(&self, other: &Waker) -> bool {
         self.waker == other.waker
index 7114f2d652e5407f006bdf6894d614270e79cd60..a054d72a8800add4d17e15b60929ac9265bcecb3 100644 (file)
@@ -357,6 +357,7 @@ pub const fn as_secs(&self) -> u64 {
     /// ```
     #[stable(feature = "duration_extras", since = "1.27.0")]
     #[rustc_const_stable(feature = "duration_extras", since = "1.32.0")]
+    #[must_use]
     #[inline]
     pub const fn subsec_millis(&self) -> u32 {
         self.nanos / NANOS_PER_MILLI
@@ -379,6 +380,7 @@ pub const fn subsec_millis(&self) -> u32 {
     /// ```
     #[stable(feature = "duration_extras", since = "1.27.0")]
     #[rustc_const_stable(feature = "duration_extras", since = "1.32.0")]
+    #[must_use]
     #[inline]
     pub const fn subsec_micros(&self) -> u32 {
         self.nanos / NANOS_PER_MICRO
@@ -401,6 +403,7 @@ pub const fn subsec_micros(&self) -> u32 {
     /// ```
     #[stable(feature = "duration", since = "1.3.0")]
     #[rustc_const_stable(feature = "duration", since = "1.32.0")]
+    #[must_use]
     #[inline]
     pub const fn subsec_nanos(&self) -> u32 {
         self.nanos
@@ -737,7 +740,6 @@ pub const fn from_secs_f64(secs: f64) -> Duration {
     /// # Examples
     /// ```
     /// #![feature(duration_checked_float)]
-    ///
     /// use std::time::Duration;
     ///
     /// let dur = Duration::try_from_secs_f64(2.7);
@@ -799,7 +801,6 @@ pub const fn from_secs_f32(secs: f32) -> Duration {
     /// # Examples
     /// ```
     /// #![feature(duration_checked_float)]
-    ///
     /// use std::time::Duration;
     ///
     /// let dur = Duration::try_from_secs_f32(2.7);
@@ -1258,7 +1259,6 @@ fn fmt_decimal(
 ///
 /// ```
 /// #![feature(duration_checked_float)]
-///
 /// use std::time::Duration;
 ///
 /// if let Err(e) = Duration::try_from_secs_f32(-1.0) {
index 66c25e449df2b9f7035404899ede8c331f53ed13..6d2cf3e83bce9683bbf9fea9dbd510072cb79c6c 100644 (file)
@@ -115,7 +115,7 @@ fn test_eq_ignore_ascii_case() {
 #[test]
 fn inference_works() {
     let x = "a".to_string();
-    x.eq_ignore_ascii_case("A");
+    let _ = x.eq_ignore_ascii_case("A");
 }
 
 // Shorthands used by the is_ascii_* tests.
index e1ba5020a50bb1ebe6af2db45797053b400c19e0..ce40bac3f31a515d300a0d2bfb540f1ad8c573ea 100644 (file)
@@ -11,7 +11,6 @@
 #![feature(const_cell_into_inner)]
 #![feature(const_convert)]
 #![feature(const_maybe_uninit_assume_init)]
-#![cfg_attr(bootstrap, feature(const_panic))]
 #![feature(const_ptr_read)]
 #![feature(const_ptr_write)]
 #![feature(const_ptr_offset)]
@@ -60,7 +59,6 @@
 #![feature(const_raw_ptr_deref)]
 #![feature(never_type)]
 #![feature(unwrap_infallible)]
-#![feature(option_result_unwrap_unchecked)]
 #![feature(result_into_ok_or_err)]
 #![feature(ptr_metadata)]
 #![feature(once_cell)]
index 3a06cd04ab146345e3d3198a9521d60b7bcc3a98..9d673d69687191dfb4525339593a7e2979506e11 100644 (file)
@@ -1074,7 +1074,11 @@ pub fn f32_unsuffixed(n: f32) -> Literal {
         if !n.is_finite() {
             panic!("Invalid float literal {}", n);
         }
-        Literal(bridge::client::Literal::float(&n.to_string()))
+        let mut repr = n.to_string();
+        if !repr.contains('.') {
+            repr.push_str(".0");
+        }
+        Literal(bridge::client::Literal::float(&repr))
     }
 
     /// Creates a new suffixed floating-point literal.
@@ -1115,7 +1119,11 @@ pub fn f64_unsuffixed(n: f64) -> Literal {
         if !n.is_finite() {
             panic!("Invalid float literal {}", n);
         }
-        Literal(bridge::client::Literal::float(&n.to_string()))
+        let mut repr = n.to_string();
+        if !repr.contains('.') {
+            repr.push_str(".0");
+        }
+        Literal(bridge::client::Literal::float(&repr))
     }
 
     /// Creates a new suffixed floating-point literal.
index 6bc445c6f2b07b084ca4c110747bdcd84eba14ef..248ecdf4befcef742ae2cdd5235c532412c67437 100644 (file)
@@ -15,7 +15,7 @@ cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] }
 panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core" }
-libc = { version = "0.2.103", default-features = false, features = ['rustc-dep-of-std'] }
+libc = { version = "0.2.106", default-features = false, features = ['rustc-dep-of-std'] }
 compiler_builtins = { version = "0.1.44" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
index 9ace3e1b60007c24dd16378358634da9817affba..0b86b4f30b959925834c25207fdb194ed434fda8 100644 (file)
 /// previous point in time. In some instances the `Backtrace` type may
 /// internally be empty due to configuration. For more information see
 /// `Backtrace::capture`.
+#[must_use]
 pub struct Backtrace {
     inner: Inner,
 }
@@ -355,6 +356,7 @@ fn create(ip: usize) -> Backtrace {
     /// Returns the status of this backtrace, indicating whether this backtrace
     /// request was unsupported, disabled, or a stack trace was actually
     /// captured.
+    #[must_use]
     pub fn status(&self) -> BacktraceStatus {
         match self.inner {
             Inner::Unsupported => BacktraceStatus::Unsupported,
@@ -366,6 +368,7 @@ pub fn status(&self) -> BacktraceStatus {
 
 impl<'a> Backtrace {
     /// Returns an iterator over the backtrace frames.
+    #[must_use]
     #[unstable(feature = "backtrace_frames", issue = "79676")]
     pub fn frames(&'a self) -> &'a [BacktraceFrame] {
         if let Inner::Captured(c) = &self.inner { &c.force().frames } else { &[] }
index d36a3eaea92575923010ff705d2d2583d8654d0e..12246b5173d394058c21dba7ef05acf70e110900 100644 (file)
@@ -414,7 +414,6 @@ pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> {
     ///     println!("key: {} val: {}", key, val);
     /// }
     /// ```
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter<'_, K, V> {
         Iter { base: self.base.iter() }
@@ -443,7 +442,6 @@ pub fn iter(&self) -> Iter<'_, K, V> {
     ///     println!("key: {} val: {}", key, val);
     /// }
     /// ```
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
         IterMut { base: self.base.iter_mut() }
@@ -504,7 +502,6 @@ pub fn is_empty(&self) -> bool {
     /// assert!(a.is_empty());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
     #[stable(feature = "drain", since = "1.6.0")]
     pub fn drain(&mut self) -> Drain<'_, K, V> {
         Drain { base: self.base.drain() }
@@ -546,7 +543,6 @@ pub fn drain(&mut self) -> Drain<'_, K, V> {
     /// assert_eq!(odds, vec![1, 3, 5, 7]);
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
     #[unstable(feature = "hash_drain_filter", issue = "59618")]
     pub fn drain_filter<F>(&mut self, pred: F) -> DrainFilter<'_, K, V, F>
     where
@@ -953,7 +949,6 @@ pub fn remove_entry<Q: ?Sized>(&mut self, k: &Q) -> Option<(K, V)>
     /// assert_eq!(map.len(), 4);
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
     #[stable(feature = "retain_hash_collection", since = "1.18.0")]
     pub fn retain<F>(&mut self, f: F)
     where
@@ -983,7 +978,6 @@ pub fn retain<F>(&mut self, f: F)
     /// assert_eq!(vec, ["a", "b", "c"]);
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
     #[stable(feature = "map_into_keys_values", since = "1.54.0")]
     pub fn into_keys(self) -> IntoKeys<K, V> {
         IntoKeys { inner: self.into_iter() }
@@ -1010,7 +1004,6 @@ pub fn into_keys(self) -> IntoKeys<K, V> {
     /// assert_eq!(vec, [1, 2, 3]);
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
     #[stable(feature = "map_into_keys_values", since = "1.54.0")]
     pub fn into_values(self) -> IntoValues<K, V> {
         IntoValues { inner: self.into_iter() }
@@ -1714,6 +1707,7 @@ pub fn and_modify<F>(self, f: F) -> Self
 impl<'a, K, V, S> RawOccupiedEntryMut<'a, K, V, S> {
     /// Gets a reference to the key in the entry.
     #[inline]
+    #[must_use]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn key(&self) -> &K {
         self.base.key()
@@ -1721,6 +1715,7 @@ pub fn key(&self) -> &K {
 
     /// Gets a mutable reference to the key in the entry.
     #[inline]
+    #[must_use]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn key_mut(&mut self) -> &mut K {
         self.base.key_mut()
@@ -1737,6 +1732,7 @@ pub fn into_key(self) -> &'a mut K {
 
     /// Gets a reference to the value in the entry.
     #[inline]
+    #[must_use]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn get(&self) -> &V {
         self.base.get()
@@ -1753,6 +1749,7 @@ pub fn into_mut(self) -> &'a mut V {
 
     /// Gets a mutable reference to the value in the entry.
     #[inline]
+    #[must_use]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn get_mut(&mut self) -> &mut V {
         self.base.get_mut()
@@ -1760,6 +1757,7 @@ pub fn get_mut(&mut self) -> &mut V {
 
     /// Gets a reference to the key and value in the entry.
     #[inline]
+    #[must_use]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn get_key_value(&mut self) -> (&K, &V) {
         self.base.get_key_value()
@@ -1976,7 +1974,6 @@ impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S> {
     type IntoIter = Iter<'a, K, V>;
 
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
     fn into_iter(self) -> Iter<'a, K, V> {
         self.iter()
     }
@@ -1988,7 +1985,6 @@ impl<'a, K, V, S> IntoIterator for &'a mut HashMap<K, V, S> {
     type IntoIter = IterMut<'a, K, V>;
 
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
     fn into_iter(self) -> IterMut<'a, K, V> {
         self.iter_mut()
     }
@@ -2017,7 +2013,6 @@ impl<K, V, S> IntoIterator for HashMap<K, V, S> {
     /// let vec: Vec<(&str, i32)> = map.into_iter().collect();
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
     fn into_iter(self) -> IntoIter<K, V> {
         IntoIter { base: self.base.into_iter() }
     }
index 76008e565b3907ed0630e1f23e765582bcf36145..1fc1d39b1816e63cd3e48c19defd8b486169ffed 100644 (file)
@@ -185,7 +185,6 @@ pub fn capacity(&self) -> usize {
     /// }
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter<'_, T> {
         Iter { base: self.base.iter() }
@@ -245,7 +244,6 @@ pub fn is_empty(&self) -> bool {
     /// assert!(set.is_empty());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
     #[stable(feature = "drain", since = "1.6.0")]
     pub fn drain(&mut self) -> Drain<'_, T> {
         Drain { base: self.base.drain() }
@@ -284,7 +282,6 @@ pub fn drain(&mut self) -> Drain<'_, T> {
     /// assert_eq!(odds, vec![1, 3, 5, 7]);
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
     #[unstable(feature = "hash_drain_filter", issue = "59618")]
     pub fn drain_filter<F>(&mut self, pred: F) -> DrainFilter<'_, T, F>
     where
@@ -509,7 +506,6 @@ pub fn shrink_to(&mut self, min_capacity: usize) {
     /// assert_eq!(diff, [4].iter().collect());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn difference<'a>(&'a self, other: &'a HashSet<T, S>) -> Difference<'a, T, S> {
         Difference { iter: self.iter(), other }
@@ -537,7 +533,6 @@ pub fn difference<'a>(&'a self, other: &'a HashSet<T, S>) -> Difference<'a, T, S
     /// assert_eq!(diff1, [1, 4].iter().collect());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn symmetric_difference<'a>(
         &'a self,
@@ -565,7 +560,6 @@ pub fn symmetric_difference<'a>(
     /// assert_eq!(intersection, [2, 3].iter().collect());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn intersection<'a>(&'a self, other: &'a HashSet<T, S>) -> Intersection<'a, T, S> {
         if self.len() <= other.len() {
@@ -594,7 +588,6 @@ pub fn intersection<'a>(&'a self, other: &'a HashSet<T, S>) -> Intersection<'a,
     /// assert_eq!(union, [1, 2, 3, 4].iter().collect());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn union<'a>(&'a self, other: &'a HashSet<T, S>) -> Union<'a, T, S> {
         if self.len() >= other.len() {
@@ -929,7 +922,6 @@ pub fn take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
     /// set.retain(|&k| k % 2 == 0);
     /// assert_eq!(set.len(), 3);
     /// ```
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
     #[stable(feature = "retain_hash_collection", since = "1.18.0")]
     pub fn retain<F>(&mut self, f: F)
     where
@@ -1328,6 +1320,8 @@ pub struct DrainFilter<'a, K, F>
 ///
 /// let mut intersection = a.intersection(&b);
 /// ```
+#[must_use = "this returns the intersection as an iterator, \
+              without modifying either input set"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Intersection<'a, T: 'a, S: 'a> {
     // iterator of the first set
@@ -1353,6 +1347,8 @@ pub struct Intersection<'a, T: 'a, S: 'a> {
 ///
 /// let mut difference = a.difference(&b);
 /// ```
+#[must_use = "this returns the difference as an iterator, \
+              without modifying either input set"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Difference<'a, T: 'a, S: 'a> {
     // iterator of the first set
@@ -1378,6 +1374,8 @@ pub struct Difference<'a, T: 'a, S: 'a> {
 ///
 /// let mut intersection = a.symmetric_difference(&b);
 /// ```
+#[must_use = "this returns the difference as an iterator, \
+              without modifying either input set"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct SymmetricDifference<'a, T: 'a, S: 'a> {
     iter: Chain<Difference<'a, T, S>, Difference<'a, T, S>>,
@@ -1400,6 +1398,8 @@ pub struct SymmetricDifference<'a, T: 'a, S: 'a> {
 ///
 /// let mut union_iter = a.union(&b);
 /// ```
+#[must_use = "this returns the union as an iterator, \
+              without modifying either input set"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Union<'a, T: 'a, S: 'a> {
     iter: Chain<Iter<'a, T>, Difference<'a, T, S>>,
@@ -1411,7 +1411,6 @@ impl<'a, T, S> IntoIterator for &'a HashSet<T, S> {
     type IntoIter = Iter<'a, T>;
 
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
     fn into_iter(self) -> Iter<'a, T> {
         self.iter()
     }
@@ -1443,7 +1442,6 @@ impl<T, S> IntoIterator for HashSet<T, S> {
     /// }
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
     fn into_iter(self) -> IntoIter<T> {
         IntoIter { base: self.base.into_iter() }
     }
index 40b46878cd8ba8c270f6780eafa2088c753a4321..c6af708f6cd0a99c9884dffd266475a067d89749 100644 (file)
@@ -113,6 +113,7 @@ pub struct VarsOs {
 /// ```
 ///
 /// [`env::vars_os()`]: vars_os
+#[must_use]
 #[stable(feature = "env", since = "1.0.0")]
 pub fn vars() -> Vars {
     Vars { inner: vars_os() }
@@ -140,6 +141,7 @@ pub fn vars() -> Vars {
 ///     println!("{:?}: {:?}", key, value);
 /// }
 /// ```
+#[must_use]
 #[stable(feature = "env", since = "1.0.0")]
 pub fn vars_os() -> VarsOs {
     VarsOs { inner: os_imp::env() }
@@ -244,6 +246,7 @@ fn _var(key: &OsStr) -> Result<String, VarError> {
 ///     None => println!("{} is not defined in the environment.", key)
 /// }
 /// ```
+#[must_use]
 #[stable(feature = "env", since = "1.0.0")]
 pub fn var_os<K: AsRef<OsStr>>(key: K) -> Option<OsString> {
     _var_os(key.as_ref())
@@ -384,6 +387,7 @@ fn _remove_var(key: &OsStr) {
 /// documentation for more.
 ///
 /// [`env::split_paths()`]: split_paths
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "env", since = "1.0.0")]
 pub struct SplitPaths<'a> {
     inner: os_imp::SplitPaths<'a>,
@@ -564,6 +568,7 @@ fn description(&self) -> &str {
     reason = "This function's behavior is unexpected and probably not what you want. \
               Consider using a crate from crates.io instead."
 )]
+#[must_use]
 #[stable(feature = "env", since = "1.0.0")]
 pub fn home_dir() -> Option<PathBuf> {
     os_imp::home_dir()
@@ -603,6 +608,7 @@ pub fn home_dir() -> Option<PathBuf> {
 ///     println!("Temporary directory: {}", dir.display());
 /// }
 /// ```
+#[must_use]
 #[stable(feature = "env", since = "1.0.0")]
 pub fn temp_dir() -> PathBuf {
     os_imp::temp_dir()
@@ -690,6 +696,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
 /// should not be relied upon for security purposes.
 ///
 /// [`env::args()`]: args
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "env", since = "1.0.0")]
 pub struct Args {
     inner: ArgsOs,
@@ -706,6 +713,7 @@ pub struct Args {
 /// should not be relied upon for security purposes.
 ///
 /// [`env::args_os()`]: args_os
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "env", since = "1.0.0")]
 pub struct ArgsOs {
     inner: sys::args::Args,
index 0b392897f9d8ac02b3505064f0849eca71eb457d..d23f5244d88d4e4f9999509c23900fcec7515bc5 100644 (file)
@@ -878,40 +878,4 @@ pub fn acosh(self) -> f32 {
     pub fn atanh(self) -> f32 {
         0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
     }
-
-    /// Linear interpolation between `start` and `end`.
-    ///
-    /// This enables linear interpolation between `start` and `end`, where start is represented by
-    /// `self == 0.0` and `end` is represented by `self == 1.0`. This is the basis of all
-    /// "transition", "easing", or "step" functions; if you change `self` from 0.0 to 1.0
-    /// at a given rate, the result will change from `start` to `end` at a similar rate.
-    ///
-    /// Values below 0.0 or above 1.0 are allowed, allowing you to extrapolate values outside the
-    /// range from `start` to `end`. This also is useful for transition functions which might
-    /// move slightly past the end or start for a desired effect. Mathematically, the values
-    /// returned are equivalent to `start + self * (end - start)`, although we make a few specific
-    /// guarantees that are useful specifically to linear interpolation.
-    ///
-    /// These guarantees are:
-    ///
-    /// * If `start` and `end` are [finite], the value at 0.0 is always `start` and the
-    ///   value at 1.0 is always `end`. (exactness)
-    /// * If `start` and `end` are [finite], the values will always move in the direction from
-    ///   `start` to `end` (monotonicity)
-    /// * If `self` is [finite] and `start == end`, the value at any point will always be
-    ///   `start == end`. (consistency)
-    ///
-    /// [finite]: #method.is_finite
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    #[unstable(feature = "float_interpolation", issue = "86269")]
-    pub fn lerp(self, start: f32, end: f32) -> f32 {
-        // consistent
-        if start == end {
-            start
-
-        // exact/monotonic
-        } else {
-            self.mul_add(end, (-self).mul_add(start, start))
-        }
-    }
 }
index fe66a73afd63ab7ef6d55f5dfe708640e22cde46..0d4b865f3392a66304e13e47e9fa652099428534 100644 (file)
@@ -757,66 +757,3 @@ fn s_nan() -> f32 {
     assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f32::INFINITY));
     assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
 }
-
-#[test]
-fn test_lerp_exact() {
-    // simple values
-    assert_eq!(f32::lerp(0.0, 2.0, 4.0), 2.0);
-    assert_eq!(f32::lerp(1.0, 2.0, 4.0), 4.0);
-
-    // boundary values
-    assert_eq!(f32::lerp(0.0, f32::MIN, f32::MAX), f32::MIN);
-    assert_eq!(f32::lerp(1.0, f32::MIN, f32::MAX), f32::MAX);
-}
-
-#[test]
-fn test_lerp_consistent() {
-    assert_eq!(f32::lerp(f32::MAX, f32::MIN, f32::MIN), f32::MIN);
-    assert_eq!(f32::lerp(f32::MIN, f32::MAX, f32::MAX), f32::MAX);
-
-    // as long as t is finite, a/b can be infinite
-    assert_eq!(f32::lerp(f32::MAX, f32::NEG_INFINITY, f32::NEG_INFINITY), f32::NEG_INFINITY);
-    assert_eq!(f32::lerp(f32::MIN, f32::INFINITY, f32::INFINITY), f32::INFINITY);
-}
-
-#[test]
-fn test_lerp_nan_infinite() {
-    // non-finite t is not NaN if a/b different
-    assert!(!f32::lerp(f32::INFINITY, f32::MIN, f32::MAX).is_nan());
-    assert!(!f32::lerp(f32::NEG_INFINITY, f32::MIN, f32::MAX).is_nan());
-}
-
-#[test]
-fn test_lerp_values() {
-    // just a few basic values
-    assert_eq!(f32::lerp(0.25, 1.0, 2.0), 1.25);
-    assert_eq!(f32::lerp(0.50, 1.0, 2.0), 1.50);
-    assert_eq!(f32::lerp(0.75, 1.0, 2.0), 1.75);
-}
-
-#[test]
-fn test_lerp_monotonic() {
-    // near 0
-    let below_zero = f32::lerp(-f32::EPSILON, f32::MIN, f32::MAX);
-    let zero = f32::lerp(0.0, f32::MIN, f32::MAX);
-    let above_zero = f32::lerp(f32::EPSILON, f32::MIN, f32::MAX);
-    assert!(below_zero <= zero);
-    assert!(zero <= above_zero);
-    assert!(below_zero <= above_zero);
-
-    // near 0.5
-    let below_half = f32::lerp(0.5 - f32::EPSILON, f32::MIN, f32::MAX);
-    let half = f32::lerp(0.5, f32::MIN, f32::MAX);
-    let above_half = f32::lerp(0.5 + f32::EPSILON, f32::MIN, f32::MAX);
-    assert!(below_half <= half);
-    assert!(half <= above_half);
-    assert!(below_half <= above_half);
-
-    // near 1
-    let below_one = f32::lerp(1.0 - f32::EPSILON, f32::MIN, f32::MAX);
-    let one = f32::lerp(1.0, f32::MIN, f32::MAX);
-    let above_one = f32::lerp(1.0 + f32::EPSILON, f32::MIN, f32::MAX);
-    assert!(below_one <= one);
-    assert!(one <= above_one);
-    assert!(below_one <= above_one);
-}
index 602cceb5d1a1ce55e13cc98faf9d0baaeaff8743..55e17b471905d29dd293be5e2db9a494e9a55d5c 100644 (file)
@@ -881,42 +881,6 @@ pub fn atanh(self) -> f64 {
         0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
     }
 
-    /// Linear interpolation between `start` and `end`.
-    ///
-    /// This enables linear interpolation between `start` and `end`, where start is represented by
-    /// `self == 0.0` and `end` is represented by `self == 1.0`. This is the basis of all
-    /// "transition", "easing", or "step" functions; if you change `self` from 0.0 to 1.0
-    /// at a given rate, the result will change from `start` to `end` at a similar rate.
-    ///
-    /// Values below 0.0 or above 1.0 are allowed, allowing you to extrapolate values outside the
-    /// range from `start` to `end`. This also is useful for transition functions which might
-    /// move slightly past the end or start for a desired effect. Mathematically, the values
-    /// returned are equivalent to `start + self * (end - start)`, although we make a few specific
-    /// guarantees that are useful specifically to linear interpolation.
-    ///
-    /// These guarantees are:
-    ///
-    /// * If `start` and `end` are [finite], the value at 0.0 is always `start` and the
-    ///   value at 1.0 is always `end`. (exactness)
-    /// * If `start` and `end` are [finite], the values will always move in the direction from
-    ///   `start` to `end` (monotonicity)
-    /// * If `self` is [finite] and `start == end`, the value at any point will always be
-    ///   `start == end`. (consistency)
-    ///
-    /// [finite]: #method.is_finite
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    #[unstable(feature = "float_interpolation", issue = "86269")]
-    pub fn lerp(self, start: f64, end: f64) -> f64 {
-        // consistent
-        if start == end {
-            start
-
-        // exact/monotonic
-        } else {
-            self.mul_add(end, (-self).mul_add(start, start))
-        }
-    }
-
     // Solaris/Illumos requires a wrapper around log, log2, and log10 functions
     // because of their non-standard behavior (e.g., log(-n) returns -Inf instead
     // of expected NaN).
index 04cb0109261a48068d54261a7c3cb381ed458220..5c163cfe90e0b2eff9030bc80dd0cfeb4c71532c 100644 (file)
@@ -753,58 +753,3 @@ fn s_nan() -> f64 {
     assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f64::INFINITY));
     assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
 }
-
-#[test]
-fn test_lerp_exact() {
-    // simple values
-    assert_eq!(f64::lerp(0.0, 2.0, 4.0), 2.0);
-    assert_eq!(f64::lerp(1.0, 2.0, 4.0), 4.0);
-
-    // boundary values
-    assert_eq!(f64::lerp(0.0, f64::MIN, f64::MAX), f64::MIN);
-    assert_eq!(f64::lerp(1.0, f64::MIN, f64::MAX), f64::MAX);
-}
-
-#[test]
-fn test_lerp_consistent() {
-    assert_eq!(f64::lerp(f64::MAX, f64::MIN, f64::MIN), f64::MIN);
-    assert_eq!(f64::lerp(f64::MIN, f64::MAX, f64::MAX), f64::MAX);
-
-    // as long as t is finite, a/b can be infinite
-    assert_eq!(f64::lerp(f64::MAX, f64::NEG_INFINITY, f64::NEG_INFINITY), f64::NEG_INFINITY);
-    assert_eq!(f64::lerp(f64::MIN, f64::INFINITY, f64::INFINITY), f64::INFINITY);
-}
-
-#[test]
-fn test_lerp_nan_infinite() {
-    // non-finite t is not NaN if a/b different
-    assert!(!f64::lerp(f64::INFINITY, f64::MIN, f64::MAX).is_nan());
-    assert!(!f64::lerp(f64::NEG_INFINITY, f64::MIN, f64::MAX).is_nan());
-}
-
-#[test]
-fn test_lerp_values() {
-    // just a few basic values
-    assert_eq!(f64::lerp(0.25, 1.0, 2.0), 1.25);
-    assert_eq!(f64::lerp(0.50, 1.0, 2.0), 1.50);
-    assert_eq!(f64::lerp(0.75, 1.0, 2.0), 1.75);
-}
-
-#[test]
-fn test_lerp_monotonic() {
-    // near 0
-    let below_zero = f64::lerp(-f64::EPSILON, f64::MIN, f64::MAX);
-    let zero = f64::lerp(0.0, f64::MIN, f64::MAX);
-    let above_zero = f64::lerp(f64::EPSILON, f64::MIN, f64::MAX);
-    assert!(below_zero <= zero);
-    assert!(zero <= above_zero);
-    assert!(below_zero <= above_zero);
-
-    // near 1
-    let below_one = f64::lerp(1.0 - f64::EPSILON, f64::MIN, f64::MAX);
-    let one = f64::lerp(1.0, f64::MIN, f64::MAX);
-    let above_one = f64::lerp(1.0 + f64::EPSILON, f64::MIN, f64::MAX);
-    assert!(below_one <= one);
-    assert!(one <= above_one);
-    assert!(below_one <= above_one);
-}
index 3cb3f480de31d44df06c63fb982519e141753498..465bbae8631c519b591a7b33ddb0f496f9f9ec4b 100644 (file)
@@ -1009,6 +1009,7 @@ impl NulError {
     /// let nul_error = CString::new("foo bar\0").unwrap_err();
     /// assert_eq!(nul_error.nul_position(), 7);
     /// ```
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn nul_position(&self) -> usize {
         self.0
@@ -1107,6 +1108,7 @@ pub fn into_cstring(self) -> CString {
     }
 
     /// Access the underlying UTF-8 error that was the cause of this error.
+    #[must_use]
     #[stable(feature = "cstring_into", since = "1.7.0")]
     pub fn utf8_error(&self) -> Utf8Error {
         self.error
@@ -1257,7 +1259,7 @@ pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&CStr, FromBytesWithNulError>
     #[inline]
     #[must_use]
     #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
-    #[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "none")]
+    #[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "90343")]
     pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
         // SAFETY: Casting to CStr is safe because its internal representation
         // is a [u8] too (safe only inside std).
@@ -1456,6 +1458,7 @@ pub fn to_string_lossy(&self) -> Cow<'_, str> {
     /// let boxed = c_string.into_boxed_c_str();
     /// assert_eq!(boxed.into_c_string(), CString::new("foo").expect("CString::new failed"));
     /// ```
+    #[must_use = "`self` will be dropped if the result is not used"]
     #[stable(feature = "into_boxed_c_str", since = "1.20.0")]
     pub fn into_c_string(self: Box<CStr>) -> CString {
         let raw = Box::into_raw(self) as *mut [u8];
index 46c9aa5e627c502082a5cabb691c5107eabd6ed6..0f9912fa64d8bef01dafbd44dfec39ca9da1f08f 100644 (file)
@@ -239,6 +239,7 @@ pub fn clear(&mut self) {
     /// assert!(os_string.capacity() >= 10);
     /// ```
     #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
+    #[must_use]
     #[inline]
     pub fn capacity(&self) -> usize {
         self.inner.capacity()
@@ -669,6 +670,7 @@ pub fn to_os_string(&self) -> OsString {
     /// assert!(!os_str.is_empty());
     /// ```
     #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
+    #[must_use]
     #[inline]
     pub fn is_empty(&self) -> bool {
         self.inner.inner.is_empty()
@@ -700,6 +702,7 @@ pub fn is_empty(&self) -> bool {
     /// assert_eq!(os_str.len(), 3);
     /// ```
     #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
+    #[must_use]
     #[inline]
     pub fn len(&self) -> usize {
         self.inner.inner.len()
@@ -707,6 +710,7 @@ pub fn len(&self) -> usize {
 
     /// Converts a <code>[Box]<[OsStr]></code> into an [`OsString`] without copying or allocating.
     #[stable(feature = "into_boxed_os_str", since = "1.20.0")]
+    #[must_use = "`self` will be dropped if the result is not used"]
     pub fn into_os_string(self: Box<OsStr>) -> OsString {
         let boxed = unsafe { Box::from_raw(Box::into_raw(self) as *mut Slice) };
         OsString { inner: Buf::from_box(boxed) }
@@ -829,6 +833,7 @@ pub fn to_ascii_uppercase(&self) -> OsString {
     /// assert!(!non_ascii.is_ascii());
     /// ```
     #[stable(feature = "osstring_ascii", since = "1.53.0")]
+    #[must_use]
     #[inline]
     pub fn is_ascii(&self) -> bool {
         self.inner.is_ascii()
index 9f45e89aa7504217fcb23f898c9c9073376ba9e4..e13add799bcb97804559fc6d918ea16f0fbf24a4 100644 (file)
@@ -374,6 +374,7 @@ pub fn create<P: AsRef<Path>>(path: P) -> io::Result<File> {
     ///     Ok(())
     /// }
     /// ```
+    #[must_use]
     #[unstable(feature = "with_options", issue = "65439")]
     pub fn with_options() -> OpenOptions {
         OpenOptions::new()
@@ -983,6 +984,7 @@ impl Metadata {
     ///     Ok(())
     /// }
     /// ```
+    #[must_use]
     #[stable(feature = "file_type", since = "1.1.0")]
     pub fn file_type(&self) -> FileType {
         FileType(self.0.file_type())
@@ -1046,7 +1048,6 @@ pub fn is_file(&self) -> bool {
     ///
     #[cfg_attr(unix, doc = "```no_run")]
     #[cfg_attr(not(unix), doc = "```ignore")]
-    /// #![feature(is_symlink)]
     /// use std::fs;
     /// use std::path::Path;
     /// use std::os::unix::fs::symlink;
@@ -1062,7 +1063,7 @@ pub fn is_file(&self) -> bool {
     /// }
     /// ```
     #[must_use]
-    #[unstable(feature = "is_symlink", issue = "85748")]
+    #[stable(feature = "is_symlink", since = "1.57.0")]
     pub fn is_symlink(&self) -> bool {
         self.file_type().is_symlink()
     }
@@ -1081,6 +1082,7 @@ pub fn is_symlink(&self) -> bool {
     ///     Ok(())
     /// }
     /// ```
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> u64 {
         self.0.size()
@@ -1100,6 +1102,7 @@ pub fn len(&self) -> u64 {
     ///     Ok(())
     /// }
     /// ```
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn permissions(&self) -> Permissions {
         Permissions(self.0.perm())
@@ -1247,6 +1250,7 @@ impl Permissions {
     ///     Ok(())
     /// }
     /// ```
+    #[must_use = "call `set_readonly` to modify the readonly flag"]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn readonly(&self) -> bool {
         self.0.readonly()
@@ -1441,6 +1445,7 @@ impl DirEntry {
     /// ```
     ///
     /// The exact text, of course, depends on what files you have in `.`.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn path(&self) -> PathBuf {
         self.0.path()
@@ -1536,6 +1541,7 @@ pub fn file_type(&self) -> io::Result<FileType> {
     ///     }
     /// }
     /// ```
+    #[must_use]
     #[stable(feature = "dir_entry_ext", since = "1.1.0")]
     pub fn file_name(&self) -> OsString {
         self.0.file_name()
index 13dbae3b7b580016ca1667d03d32832ee29af152..628de13156c67f4bff68fee4cff9f7d1161f45ed 100644 (file)
@@ -1411,3 +1411,32 @@ fn symlink_hard_link() {
     // "hard_link" should still appear as a symlink.
     assert!(check!(fs::symlink_metadata(tmpdir.join("hard_link"))).file_type().is_symlink());
 }
+
+/// Ensure `fs::create_dir` works on Windows with longer paths.
+#[test]
+#[cfg(windows)]
+fn create_dir_long_paths() {
+    use crate::{ffi::OsStr, iter, os::windows::ffi::OsStrExt};
+    const PATH_LEN: usize = 247;
+
+    let tmpdir = tmpdir();
+    let mut path = tmpdir.path().to_path_buf();
+    path.push("a");
+    let mut path = path.into_os_string();
+
+    let utf16_len = path.encode_wide().count();
+    if utf16_len >= PATH_LEN {
+        // Skip the test in the unlikely event the local user has a long temp directory path.
+        // This should not affect CI.
+        return;
+    }
+    // Increase the length of the path.
+    path.extend(iter::repeat(OsStr::new("a")).take(PATH_LEN - utf16_len));
+
+    // This should succeed.
+    fs::create_dir(&path).unwrap();
+
+    // This will fail if the path isn't converted to verbatim.
+    path.push("a");
+    fs::create_dir(&path).unwrap();
+}
index 59a9cd781cb99f32f83fd3f12fe83f9bcad7ef1b..3da28695b34bd951e9e3b84a1e5e28a3c99fbe8e 100644 (file)
@@ -442,6 +442,7 @@ pub(crate) const fn new_const(kind: ErrorKind, message: &'static &'static str) -
     /// println!("last OS error: {:?}", Error::last_os_error());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
     #[inline]
     pub fn last_os_error() -> Error {
         Error::from_raw_os_error(sys::os::errno() as i32)
@@ -509,6 +510,7 @@ pub fn from_raw_os_error(code: i32) -> Error {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
     #[inline]
     pub fn raw_os_error(&self) -> Option<i32> {
         match self.repr {
@@ -547,6 +549,7 @@ pub fn raw_os_error(&self) -> Option<i32> {
     /// }
     /// ```
     #[stable(feature = "io_error_inner", since = "1.3.0")]
+    #[must_use]
     #[inline]
     pub fn get_ref(&self) -> Option<&(dyn error::Error + Send + Sync + 'static)> {
         match self.repr {
@@ -620,6 +623,7 @@ pub fn get_ref(&self) -> Option<&(dyn error::Error + Send + Sync + 'static)> {
     /// }
     /// ```
     #[stable(feature = "io_error_inner", since = "1.3.0")]
+    #[must_use]
     #[inline]
     pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error + Send + Sync + 'static)> {
         match self.repr {
@@ -688,6 +692,7 @@ pub fn into_inner(self) -> Option<Box<dyn error::Error + Send + Sync>> {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
     #[inline]
     pub fn kind(&self) -> ErrorKind {
         match self.repr {
index abe29ba0f7caa379c339c2fde186777cfe3d17f2..8cc91566418dc957c57de39e3ca4f59e0ca8482b 100644 (file)
 
 const DEFAULT_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
 
-pub(crate) fn cleanup() {
-    stdio::cleanup()
-}
+pub(crate) use stdio::cleanup;
 
 struct Guard<'a> {
     buf: &'a mut Vec<u8>,
@@ -1310,6 +1308,7 @@ fn deref(&self) -> &[u8] {
 impl Initializer {
     /// Returns a new `Initializer` which will zero out buffers.
     #[unstable(feature = "read_initializer", issue = "42788")]
+    #[must_use]
     #[inline]
     pub fn zeroing() -> Initializer {
         Initializer(true)
@@ -1324,6 +1323,7 @@ pub fn zeroing() -> Initializer {
     /// the method accurately reflects the number of bytes that have been
     /// written to the head of the buffer.
     #[unstable(feature = "read_initializer", issue = "42788")]
+    #[must_use]
     #[inline]
     pub unsafe fn nop() -> Initializer {
         Initializer(false)
@@ -1331,6 +1331,7 @@ pub unsafe fn nop() -> Initializer {
 
     /// Indicates if a buffer should be initialized.
     #[unstable(feature = "read_initializer", issue = "42788")]
+    #[must_use]
     #[inline]
     pub fn should_initialize(&self) -> bool {
         self.0
index 9389501e0129e63b8a6d4d5a042b06a79e7a27a5..f7fc23c1e829c47b4701ad8503890d586b3c0b9a 100644 (file)
@@ -301,6 +301,7 @@ pub struct StdinLock<'a> {
 ///     Ok(())
 /// }
 /// ```
+#[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stdin() -> Stdin {
     static INSTANCE: SyncOnceCell<Mutex<BufReader<StdinRaw>>> = SyncOnceCell::new();
@@ -487,6 +488,7 @@ pub fn lines(self) -> Lines<StdinLock<'static>> {
     ///     println!("got a chunk: {}", String::from_utf8_lossy(&split.unwrap()));
     /// }
     /// ```
+    #[must_use = "`self` will be dropped if the result is not used"]
     #[unstable(feature = "stdin_forwarders", issue = "87096")]
     pub fn split(self, byte: u8) -> Split<StdinLock<'static>> {
         self.into_locked().split(byte)
@@ -673,6 +675,7 @@ pub struct StdoutLock<'a> {
 ///     Ok(())
 /// }
 /// ```
+#[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stdout() -> Stdout {
     Stdout {
@@ -953,6 +956,7 @@ pub struct StderrLock<'a> {
 ///     Ok(())
 /// }
 /// ```
+#[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stderr() -> Stderr {
     // Note that unlike `stdout()` we don't use `at_exit` here to register a
index 2f3520ae7a5a5fb4c9aab4c4364b64fe334b5d70..9cd7c5148499db87b228f260139b06f002100e0d 100644 (file)
@@ -32,6 +32,7 @@
 /// io::empty().read_to_string(&mut buffer).unwrap();
 /// assert!(buffer.is_empty());
 /// ```
+#[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_io_structs", issue = "78812")]
 pub const fn empty() -> Empty {
@@ -112,6 +113,7 @@ pub struct Repeat {
 /// io::repeat(0b101).read_exact(&mut buffer).unwrap();
 /// assert_eq!(buffer, [0b101, 0b101, 0b101]);
 /// ```
+#[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_io_structs", issue = "78812")]
 pub const fn repeat(byte: u8) -> Repeat {
@@ -192,6 +194,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// let num_bytes = io::sink().write(&buffer).unwrap();
 /// assert_eq!(num_bytes, 5);
 /// ```
+#[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_io_structs", issue = "78812")]
 pub const fn sink() -> Sink {
index e22748a4c8dc37c7262a6e4e9fcb8476050b9c14..c2243b259538aee080699b2f79fadf51663931a4 100644 (file)
 #![feature(const_cstr_unchecked)]
 #![feature(const_fn_floating_point_arithmetic)]
 #![feature(const_fn_fn_ptr_basics)]
+#![feature(const_fn_trait_bound)]
 #![feature(const_format_args)]
 #![feature(const_io_structs)]
 #![feature(const_ip)]
 #![feature(custom_test_frameworks)]
 #![feature(decl_macro)]
 #![feature(doc_cfg)]
-#![cfg_attr(not(bootstrap), feature(doc_cfg_hide))]
+#![feature(doc_cfg_hide)]
 #![feature(doc_keyword)]
 #![feature(doc_masked)]
 #![feature(doc_notable_trait)]
 #![feature(exact_size_is_empty)]
 #![feature(exhaustive_patterns)]
 #![feature(extend_one)]
-#![feature(float_interpolation)]
 #![feature(fn_traits)]
 #![feature(format_args_nl)]
 #![feature(gen_future)]
 #![feature(maybe_uninit_uninit_array)]
 #![feature(min_specialization)]
 #![feature(mixed_integer_ops)]
-#![cfg_attr(not(bootstrap), feature(must_not_suspend))]
+#![feature(must_not_suspend)]
 #![feature(needs_panic_runtime)]
 #![feature(negative_impls)]
 #![feature(never_type)]
index a689d2a56b721d2c8fd1574c907e0de28e21418c..201cbf3f08d28aad58e73f59350867298114f66f 100644 (file)
@@ -149,6 +149,7 @@ pub fn new(ip: IpAddr, port: u16) -> SocketAddr {
     /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
     /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
     /// ```
+    #[must_use]
     #[stable(feature = "ip_addr", since = "1.7.0")]
     #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
     pub const fn ip(&self) -> IpAddr {
@@ -189,6 +190,7 @@ pub fn set_ip(&mut self, new_ip: IpAddr) {
     /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
     /// assert_eq!(socket.port(), 8080);
     /// ```
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
     pub const fn port(&self) -> u16 {
@@ -297,6 +299,7 @@ pub fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 {
     /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
     /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1));
     /// ```
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
     pub const fn ip(&self) -> &Ipv4Addr {
@@ -331,6 +334,7 @@ pub fn set_ip(&mut self, new_ip: Ipv4Addr) {
     /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
     /// assert_eq!(socket.port(), 8080);
     /// ```
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
     pub const fn port(&self) -> u16 {
@@ -396,6 +400,7 @@ pub fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV
     /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
     /// assert_eq!(socket.ip(), &Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
     /// ```
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
     pub const fn ip(&self) -> &Ipv6Addr {
@@ -428,6 +433,7 @@ pub fn set_ip(&mut self, new_ip: Ipv6Addr) {
     /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
     /// assert_eq!(socket.port(), 8080);
     /// ```
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
     pub const fn port(&self) -> u16 {
@@ -470,6 +476,7 @@ pub fn set_port(&mut self, new_port: u16) {
     /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0);
     /// assert_eq!(socket.flowinfo(), 10);
     /// ```
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
     pub const fn flowinfo(&self) -> u32 {
@@ -509,6 +516,7 @@ pub fn set_flowinfo(&mut self, new_flowinfo: u32) {
     /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78);
     /// assert_eq!(socket.scope_id(), 78);
     /// ```
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
     pub const fn scope_id(&self) -> u32 {
index c080f783cbb36d76abfbb96eedacf446b44ff9eb..da95fe21ac9af8706e3d371d8b63382c1268efa7 100644 (file)
@@ -518,6 +518,7 @@ pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
     /// ```
     #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
     #[inline]
     pub const fn octets(&self) -> [u8; 4] {
         // This returns the order we want because s_addr is stored in big-endian.
@@ -877,12 +878,7 @@ pub const fn is_broadcast(&self) -> bool {
     #[must_use]
     #[inline]
     pub const fn is_documentation(&self) -> bool {
-        match self.octets() {
-            [192, 0, 2, _] => true,
-            [198, 51, 100, _] => true,
-            [203, 0, 113, _] => true,
-            _ => false,
-        }
+        matches!(self.octets(), [192, 0, 2, _] | [198, 51, 100, _] | [203, 0, 113, _])
     }
 
     /// Converts this address to an [IPv4-compatible] [`IPv6` address].
@@ -1284,6 +1280,7 @@ pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16)
     /// ```
     #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
     #[inline]
     pub const fn segments(&self) -> [u16; 8] {
         // All elements in `s6_addr` must be big endian.
@@ -1594,6 +1591,7 @@ pub const fn is_unicast_global(&self) -> bool {
     /// ```
     #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
     #[unstable(feature = "ip", issue = "27709")]
+    #[must_use]
     #[inline]
     pub const fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
         if self.is_multicast() {
@@ -1744,6 +1742,7 @@ pub const fn to_canonical(&self) -> IpAddr {
     /// ```
     #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
     #[stable(feature = "ipv6_to_octets", since = "1.12.0")]
+    #[must_use]
     #[inline]
     pub const fn octets(&self) -> [u8; 16] {
         self.inner.s6_addr
index 2c6e3930059905bd94f42b56c2305db7b4a72b2b..5738862fb58b2c7f6d5dc41d5e7926ce9f223e21 100644 (file)
@@ -90,6 +90,7 @@
 /// See its documentation for more.
 ///
 /// [`accept`]: TcpListener::accept
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
 pub struct Incoming<'a> {
index 30eeac14b43f5dde525fa633c2a4db89023dcf79..01392ffab79cac81f03288b789efce77ce064de4 100644 (file)
@@ -165,7 +165,14 @@ macro_rules! type_alias {
 #[unstable(feature = "c_size_t", issue = "88345")]
 pub type c_size_t = usize;
 
-/// Equivalent to C's `ssize_t` type, from `stddef.h` (or `cstddef` for C++).
+/// Equivalent to C's `ptrdiff_t` type, from `stddef.h` (or `cstddef` for C++).
+///
+/// This type is currently always [`isize`], however in the future there may be
+/// platforms where this is not the case.
+#[unstable(feature = "c_size_t", issue = "88345")]
+pub type c_ptrdiff_t = isize;
+
+/// Equivalent to C's `ssize_t` (on POSIX) or `SSIZE_T` (on Windows) type.
 ///
 /// This type is currently always [`isize`], however in the future there may be
 /// platforms where this is not the case.
index 887f605993918da58f6c156882f96c27be843744..f450e41bfea1e539a0c7d0a2e476164b68dba909 100644 (file)
@@ -159,7 +159,7 @@ pub(super) fn from_parts(
     #[must_use]
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn is_unnamed(&self) -> bool {
-        if let AddressKind::Unnamed = self.address() { true } else { false }
+        matches!(self.address(), AddressKind::Unnamed)
     }
 
     /// Returns the contents of this address if it is a `pathname` address.
index 57bb61903c147964c6d74b08ed6ba788e1c075cb..6e6f5212b4651d934290ffbb4f07216b214be378 100644 (file)
@@ -201,6 +201,7 @@ pub fn set_pid(&mut self, pid: libc::pid_t) {
     }
 
     /// Get the current PID.
+    #[must_use]
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     pub fn get_pid(&self) -> libc::pid_t {
         self.0.pid
@@ -213,6 +214,7 @@ pub fn set_uid(&mut self, uid: libc::uid_t) {
     }
 
     /// Get the current UID.
+    #[must_use]
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     pub fn get_uid(&self) -> libc::uid_t {
         self.0.uid
@@ -225,6 +227,7 @@ pub fn set_gid(&mut self, gid: libc::gid_t) {
     }
 
     /// Get the current GID.
+    #[must_use]
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     pub fn get_gid(&self) -> libc::gid_t {
         self.0.gid
@@ -330,6 +333,7 @@ fn try_from_cmsghdr(cmsg: &'a libc::cmsghdr) -> Result<Self, AncillaryError> {
 }
 
 /// This struct is used to iterate through the control messages.
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
 pub struct Messages<'a> {
     buffer: &'a [u8],
@@ -425,18 +429,21 @@ pub fn new(buffer: &'a mut [u8]) -> Self {
     }
 
     /// Returns the capacity of the buffer.
+    #[must_use]
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     pub fn capacity(&self) -> usize {
         self.buffer.len()
     }
 
     /// Returns `true` if the ancillary data is empty.
+    #[must_use]
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     pub fn is_empty(&self) -> bool {
         self.length == 0
     }
 
     /// Returns the number of used bytes.
+    #[must_use]
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     pub fn len(&self) -> usize {
         self.length
@@ -471,6 +478,7 @@ pub fn messages(&self) -> Messages<'_> {
     ///     Ok(())
     /// }
     /// ```
+    #[must_use]
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     pub fn truncated(&self) -> bool {
         self.truncated
index 97348afe7de12823e7c8e9388c15ac84b0290283..b23dd6062f6822fce6576454ee8ec4ca0e33aaf3 100644 (file)
@@ -365,6 +365,7 @@ fn into_iter(self) -> Incoming<'a> {
 /// }
 /// ```
 #[derive(Debug)]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "unix_socket", since = "1.10.0")]
 pub struct Incoming<'a> {
     listener: &'a UnixListener,
index 9b94615d24773b002c31129dfccaa51b78a31574..286a7c3b386f9d79e4d23c7db159242b91cdaa74 100644 (file)
@@ -436,6 +436,7 @@ fn from(child_stderr: crate::process::ChildStderr) -> OwnedFd {
 }
 
 /// Returns the OS-assigned process identifier associated with this process's parent.
+#[must_use]
 #[stable(feature = "unix_ppid", since = "1.27.0")]
 pub fn parent_id() -> u32 {
     crate::sys::os::getppid()
index 56646b72dd54f089cdc13e379a3fcb4e846a331f..6fc6b8daec0a6c76a15100194315271beecfa7ba 100644 (file)
@@ -160,6 +160,7 @@ pub fn set_hook(hook: Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>) {
 ///
 /// panic!("Normal panic");
 /// ```
+#[must_use]
 #[stable(feature = "panic_hooks", since = "1.10.0")]
 pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
     if thread::panicking() {
@@ -284,11 +285,13 @@ pub fn set_always_abort() {
     }
 
     // Disregards ALWAYS_ABORT_FLAG
+    #[must_use]
     pub fn get_count() -> usize {
         LOCAL_PANIC_COUNT.with(|c| c.get())
     }
 
     // Disregards ALWAYS_ABORT_FLAG
+    #[must_use]
     #[inline]
     pub fn count_is_zero() -> bool {
         if GLOBAL_PANIC_COUNT.load(Ordering::Relaxed) & !ALWAYS_ABORT_FLAG == 0 {
@@ -512,7 +515,8 @@ fn get(&mut self) -> &(dyn Any + Send) {
 #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
 #[cold]
 #[track_caller]
-pub fn begin_panic<M: Any + Send>(msg: M) -> ! {
+#[rustc_do_not_const_check] // hooked by const-eval
+pub const fn begin_panic<M: Any + Send>(msg: M) -> ! {
     if cfg!(feature = "panic_immediate_abort") {
         intrinsics::abort()
     }
index 8f00d2260e4c60b42b7827b5a382be20c640c334..dc0c735a06c6f5a4cd502ccc03cb228ea8d6be7a 100644 (file)
@@ -422,6 +422,7 @@ impl<'a> PrefixComponent<'a> {
     /// See [`Prefix`]'s documentation for more information on the different
     /// kinds of prefixes.
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
     #[inline]
     pub fn kind(&self) -> Prefix<'a> {
         self.parsed
@@ -583,6 +584,7 @@ fn as_ref(&self) -> &Path {
 ///
 /// [`components`]: Path::components
 #[derive(Clone)]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Components<'a> {
     // The path left to parse components from
@@ -609,6 +611,7 @@ pub struct Components<'a> {
 ///
 /// [`iter`]: Path::iter
 #[derive(Clone)]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a> {
     inner: Components<'a>,
@@ -1051,6 +1054,7 @@ fn compare_components(mut left: Components<'_>, mut right: Components<'_>) -> cm
 ///
 /// [`ancestors`]: Path::ancestors
 #[derive(Copy, Clone, Debug)]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "path_ancestors", since = "1.28.0")]
 pub struct Ancestors<'a> {
     next: Option<&'a Path>,
@@ -1459,6 +1463,7 @@ pub fn into_boxed_path(self) -> Box<Path> {
     ///
     /// [`capacity`]: OsString::capacity
     #[stable(feature = "path_buf_capacity", since = "1.44.0")]
+    #[must_use]
     #[inline]
     pub fn capacity(&self) -> usize {
         self.inner.capacity()
@@ -2103,6 +2108,7 @@ pub fn has_root(&self) -> bool {
     /// assert_eq!(grand_parent.parent(), None);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
     pub fn parent(&self) -> Option<&Path> {
         let mut comps = self.components();
         let comp = comps.next_back();
@@ -2169,6 +2175,7 @@ pub fn ancestors(&self) -> Ancestors<'_> {
     /// assert_eq!(None, Path::new("/").file_name());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
     pub fn file_name(&self) -> Option<&OsStr> {
         self.components().next_back().and_then(|p| match p {
             Component::Normal(p) => Some(p),
@@ -2241,6 +2248,7 @@ fn _strip_prefix(&self, base: &Path) -> Result<&Path, StripPrefixError> {
     /// assert!(!Path::new("/etc/foo.rs").starts_with("/etc/foo"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
     pub fn starts_with<P: AsRef<Path>>(&self, base: P) -> bool {
         self._starts_with(base.as_ref())
     }
@@ -2268,6 +2276,7 @@ fn _starts_with(&self, base: &Path) -> bool {
     /// assert!(!path.ends_with("conf")); // use .extension() instead
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
     pub fn ends_with<P: AsRef<Path>>(&self, child: P) -> bool {
         self._ends_with(child.as_ref())
     }
@@ -2303,6 +2312,7 @@ fn _ends_with(&self, child: &Path) -> bool {
     /// [`Path::file_prefix`]: Path::file_prefix
     ///
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
     pub fn file_stem(&self) -> Option<&OsStr> {
         self.file_name().map(rsplit_file_at_dot).and_then(|(before, after)| before.or(after))
     }
@@ -2336,6 +2346,7 @@ pub fn file_stem(&self) -> Option<&OsStr> {
     /// [`Path::file_stem`]: Path::file_stem
     ///
     #[unstable(feature = "path_file_prefix", issue = "86319")]
+    #[must_use]
     pub fn file_prefix(&self) -> Option<&OsStr> {
         self.file_name().map(split_file_at_dot).and_then(|(before, _after)| Some(before))
     }
@@ -2360,6 +2371,7 @@ pub fn file_prefix(&self) -> Option<&OsStr> {
     /// assert_eq!("gz", Path::new("foo.tar.gz").extension().unwrap());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
     pub fn extension(&self) -> Option<&OsStr> {
         self.file_name().map(rsplit_file_at_dot).and_then(|(before, after)| before.and(after))
     }
@@ -2403,6 +2415,7 @@ fn _join(&self, path: &Path) -> PathBuf {
     /// assert_eq!(path.with_file_name("var"), PathBuf::from("/var"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
     pub fn with_file_name<S: AsRef<OsStr>>(&self, file_name: S) -> PathBuf {
         self._with_file_name(file_name.as_ref())
     }
@@ -2660,6 +2673,7 @@ pub fn read_dir(&self) -> io::Result<fs::ReadDir> {
     /// This is a convenience function that coerces errors to false. If you want to
     /// check errors, call [`fs::metadata`].
     #[stable(feature = "path_ext", since = "1.5.0")]
+    #[must_use]
     #[inline]
     pub fn exists(&self) -> bool {
         fs::metadata(self).is_ok()
@@ -2751,7 +2765,7 @@ pub fn is_dir(&self) -> bool {
         fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
     }
 
-    /// Returns true if the path exists on disk and is pointing at a symbolic link.
+    /// Returns `true` if the path exists on disk and is pointing at a symbolic link.
     ///
     /// This function will not traverse symbolic links.
     /// In case of a broken symbolic link this will also return true.
@@ -2763,7 +2777,6 @@ pub fn is_dir(&self) -> bool {
     ///
     #[cfg_attr(unix, doc = "```no_run")]
     #[cfg_attr(not(unix), doc = "```ignore")]
-    /// #![feature(is_symlink)]
     /// use std::path::Path;
     /// use std::os::unix::fs::symlink;
     ///
@@ -2772,8 +2785,14 @@ pub fn is_dir(&self) -> bool {
     /// assert_eq!(link_path.is_symlink(), true);
     /// assert_eq!(link_path.exists(), false);
     /// ```
-    #[unstable(feature = "is_symlink", issue = "85748")]
+    ///
+    /// # See Also
+    ///
+    /// This is a convenience function that coerces errors to false. If you want to
+    /// check errors, call [`fs::symlink_metadata`] and handle its [`Result`]. Then call
+    /// [`fs::Metadata::is_symlink`] if it was [`Ok`].
     #[must_use]
+    #[stable(feature = "is_symlink", since = "1.57.0")]
     pub fn is_symlink(&self) -> bool {
         fs::symlink_metadata(self).map(|m| m.is_symlink()).unwrap_or(false)
     }
@@ -2781,6 +2800,7 @@ pub fn is_symlink(&self) -> bool {
     /// Converts a [`Box<Path>`](Box) into a [`PathBuf`] without copying or
     /// allocating.
     #[stable(feature = "into_boxed_path", since = "1.20.0")]
+    #[must_use = "`self` will be dropped if the result is not used"]
     pub fn into_path_buf(self: Box<Path>) -> PathBuf {
         let rw = Box::into_raw(self) as *mut OsStr;
         let inner = unsafe { Box::from_raw(rw) };
index 4bd06475e2761510fe681acd80de672683f0e094..9cc7fc2f0352e6e09b2fa7ab9565fc3936bc165a 100644 (file)
@@ -948,6 +948,7 @@ pub fn status(&mut self) -> io::Result<ExitStatus> {
     /// let cmd = Command::new("echo");
     /// assert_eq!(cmd.get_program(), "echo");
     /// ```
+    #[must_use]
     #[stable(feature = "command_access", since = "1.57.0")]
     pub fn get_program(&self) -> &OsStr {
         self.inner.get_program()
@@ -1021,6 +1022,7 @@ pub fn get_envs(&self) -> CommandEnvs<'_> {
     /// cmd.current_dir("/bin");
     /// assert_eq!(cmd.get_current_dir(), Some(Path::new("/bin")));
     /// ```
+    #[must_use]
     #[stable(feature = "command_access", since = "1.57.0")]
     pub fn get_current_dir(&self) -> Option<&Path> {
         self.inner.get_current_dir()
@@ -1053,6 +1055,7 @@ fn as_inner_mut(&mut self) -> &mut imp::Command {
 ///
 /// This struct is created by [`Command::get_args`]. See its documentation for
 /// more.
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "command_access", since = "1.57.0")]
 #[derive(Debug)]
 pub struct CommandArgs<'a> {
@@ -1183,6 +1186,7 @@ impl Stdio {
     /// its entire stdin before writing more than a pipe buffer's worth of output.
     /// The size of a pipe buffer varies on different targets.
     ///
+    #[must_use]
     #[stable(feature = "process", since = "1.0.0")]
     pub fn piped() -> Stdio {
         Stdio(imp::Stdio::MakePipe)
@@ -1222,6 +1226,7 @@ pub fn piped() -> Stdio {
     /// print!("You piped in the reverse of: ");
     /// io::stdout().write_all(&output.stdout).unwrap();
     /// ```
+    #[must_use]
     #[stable(feature = "process", since = "1.0.0")]
     pub fn inherit() -> Stdio {
         Stdio(imp::Stdio::Inherit)
@@ -1261,6 +1266,7 @@ pub fn inherit() -> Stdio {
     /// assert_eq!(String::from_utf8_lossy(&output.stdout), "");
     /// // Ignores any piped-in input
     /// ```
+    #[must_use]
     #[stable(feature = "process", since = "1.0.0")]
     pub fn null() -> Stdio {
         Stdio(imp::Stdio::Null)
@@ -1462,6 +1468,7 @@ pub fn exit_ok(&self) -> Result<(), ExitStatusError> {
     ///     println!("failed to create 'projects/' directory: {}", status);
     /// }
     /// ```
+    #[must_use]
     #[stable(feature = "process", since = "1.0.0")]
     pub fn success(&self) -> bool {
         self.0.exit_ok().is_ok()
@@ -1493,6 +1500,7 @@ pub fn success(&self) -> bool {
     ///     None       => println!("Process terminated by signal")
     /// }
     /// ```
+    #[must_use]
     #[stable(feature = "process", since = "1.0.0")]
     pub fn code(&self) -> Option<i32> {
         self.0.code()
@@ -1580,6 +1588,7 @@ impl ExitStatusError {
     /// assert_eq!(bad.code(), Some(1));
     /// # } // #[cfg(unix)]
     /// ```
+    #[must_use]
     pub fn code(&self) -> Option<i32> {
         self.code_nonzero().map(Into::into)
     }
@@ -1605,11 +1614,13 @@ pub fn code(&self) -> Option<i32> {
     /// assert_eq!(bad.code_nonzero().unwrap(), NonZeroI32::try_from(1).unwrap());
     /// # } // cfg!(unix)
     /// ```
+    #[must_use]
     pub fn code_nonzero(&self) -> Option<NonZeroI32> {
         self.0.code()
     }
 
     /// Converts an `ExitStatusError` (back) to an `ExitStatus`.
+    #[must_use]
     pub fn into_status(&self) -> ExitStatus {
         ExitStatus(self.0.into())
     }
@@ -1718,6 +1729,7 @@ pub fn kill(&mut self) -> io::Result<()> {
     ///     println!("ls command didn't start");
     /// }
     /// ```
+    #[must_use]
     #[stable(feature = "process_id", since = "1.3.0")]
     pub fn id(&self) -> u32 {
         self.handle.id()
@@ -1988,6 +2000,7 @@ pub fn abort() -> ! {
 /// ```
 ///
 ///
+#[must_use]
 #[stable(feature = "getpid", since = "1.26.0")]
 pub fn id() -> u32 {
     crate::sys::os::getpid()
index 121c214780d2d5e5ba371de3cd49c167ef4fbf6b..08e58257572b24fcfddeb1a18be409b6b124c8a6 100644 (file)
@@ -128,8 +128,7 @@ fn lang_start_internal(
     let ret_code = panic::catch_unwind(move || panic::catch_unwind(main).unwrap_or(101) as isize)
         .map_err(move |e| {
             mem::forget(e);
-            rtprintpanic!("drop of the panic payload panicked");
-            sys::abort_internal()
+            rtabort!("drop of the panic payload panicked");
         });
     panic::catch_unwind(cleanup).map_err(rt_abort)?;
     ret_code
index d8aca9651b8678726b24244920c2dc574badca15..b41918ec1cffc6c1f7613b70da2b4732026b87dc 100644 (file)
@@ -61,6 +61,7 @@ impl WaitTimeoutResult {
     ///     }
     /// }
     /// ```
+    #[must_use]
     #[stable(feature = "wait_timeout", since = "1.5.0")]
     pub fn timed_out(&self) -> bool {
         self.0
index b0842144328a8bfa2f21f11d2f2e338fc5bd04cf..f95b0ddd589ac4b311c4a7d4abfe96c186c80dd0 100644 (file)
@@ -2,10 +2,7 @@
 
 #[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[repr(align(64))]
-pub(super) struct Aligner;
-
-#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub(super) struct CacheAligned<T>(pub T, pub Aligner);
+pub(super) struct CacheAligned<T>(pub T);
 
 impl<T> Deref for CacheAligned<T> {
     type Target = T;
@@ -22,6 +19,6 @@ fn deref_mut(&mut self) -> &mut Self::Target {
 
 impl<T> CacheAligned<T> {
     pub(super) fn new(t: T) -> Self {
-        CacheAligned(t, Aligner)
+        CacheAligned(t)
     }
 }
index b4f4456537b9693f41b56df9208e5588ce4f88ab..2cf678ef69b073677b32a32774ba686272a0e4e6 100644 (file)
@@ -707,6 +707,7 @@ fn inner_unsafe(&self) -> &UnsafeCell<Flavor<T>> {
 /// // Let's see what that answer was
 /// println!("{:?}", receiver.recv().unwrap());
 /// ```
+#[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
     let a = Arc::new(oneshot::Packet::new());
@@ -755,6 +756,7 @@ pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
 /// assert_eq!(receiver.recv().unwrap(), 1);
 /// assert_eq!(receiver.recv().unwrap(), 2);
 /// ```
+#[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn sync_channel<T>(bound: usize) -> (SyncSender<T>, Receiver<T>) {
     let a = Arc::new(sync::Packet::new(bound));
index fa8ef8fc37a95d4ab3a1e4c75bd95346cbb3e042..b62f21a9dac02d705989c77295020fe630da2cc7 100644 (file)
@@ -55,8 +55,20 @@ pub unsafe fn wait(&self, mutex: &Mutex) {
         mutex.lock();
     }
 
-    pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
-        panic!("wait_timeout not supported on hermit");
+    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
+        self.counter.fetch_add(1, SeqCst);
+        mutex.unlock();
+        let millis = dur.as_millis().min(u32::MAX as u128) as u32;
+
+        let res = if millis > 0 {
+            abi::sem_timedwait(self.sem1, millis)
+        } else {
+            abi::sem_trywait(self.sem1)
+        };
+
+        abi::sem_post(self.sem2);
+        mutex.lock();
+        res == 0
     }
 
     pub unsafe fn destroy(&self) {
index 4feb9c5a6d74047155547994bab0c76fb931fa80..bb9fa54d02ea4174eb596c3df960b4a77540fafd 100644 (file)
@@ -347,6 +347,6 @@ unsafe fn terminate_and_delete_current_task() -> ! {
     unsafe { crate::hint::unreachable_unchecked() };
 }
 
-pub fn available_concurrency() -> io::Result<crate::num::NonZeroUsize> {
+pub fn available_parallelism() -> io::Result<crate::num::NonZeroUsize> {
     super::unsupported()
 }
index db1a2a26a8903c21797fce7449b14749c400aec6..1e8d1137ac8b865f1a8bbb8a74d57baec9ded908 100644 (file)
@@ -6,7 +6,7 @@
 pub use self::imp::init;
 
 pub struct Handler {
-    _data: *mut libc::c_void,
+    data: *mut libc::c_void,
 }
 
 impl Handler {
@@ -15,14 +15,14 @@ pub unsafe fn new() -> Handler {
     }
 
     fn null() -> Handler {
-        Handler { _data: crate::ptr::null_mut() }
+        Handler { data: crate::ptr::null_mut() }
     }
 }
 
 impl Drop for Handler {
     fn drop(&mut self) {
         unsafe {
-            drop_handler(self);
+            drop_handler(self.data);
         }
     }
 }
@@ -134,12 +134,12 @@ pub unsafe fn init() {
         }
 
         let handler = make_handler();
-        MAIN_ALTSTACK.store(handler._data, Ordering::Relaxed);
+        MAIN_ALTSTACK.store(handler.data, Ordering::Relaxed);
         mem::forget(handler);
     }
 
     pub unsafe fn cleanup() {
-        Handler { _data: MAIN_ALTSTACK.load(Ordering::Relaxed) };
+        drop_handler(MAIN_ALTSTACK.load(Ordering::Relaxed));
     }
 
     unsafe fn get_stackp() -> *mut libc::c_void {
@@ -176,14 +176,14 @@ pub unsafe fn make_handler() -> Handler {
         if stack.ss_flags & SS_DISABLE != 0 {
             stack = get_stack();
             sigaltstack(&stack, ptr::null_mut());
-            Handler { _data: stack.ss_sp as *mut libc::c_void }
+            Handler { data: stack.ss_sp as *mut libc::c_void }
         } else {
             Handler::null()
         }
     }
 
-    pub unsafe fn drop_handler(handler: &mut Handler) {
-        if !handler._data.is_null() {
+    pub unsafe fn drop_handler(data: *mut libc::c_void) {
+        if !data.is_null() {
             let stack = libc::stack_t {
                 ss_sp: ptr::null_mut(),
                 ss_flags: SS_DISABLE,
@@ -196,7 +196,7 @@ pub unsafe fn drop_handler(handler: &mut Handler) {
             sigaltstack(&stack, ptr::null_mut());
             // We know from `get_stackp` that the alternate stack we installed is part of a mapping
             // that started one page earlier, so walk back a page and unmap from there.
-            munmap(handler._data.sub(page_size()), SIGSTKSZ + page_size());
+            munmap(data.sub(page_size()), SIGSTKSZ + page_size());
         }
     }
 }
@@ -220,5 +220,5 @@ pub unsafe fn make_handler() -> super::Handler {
         super::Handler::null()
     }
 
-    pub unsafe fn drop_handler(_handler: &mut super::Handler) {}
+    pub unsafe fn drop_handler(_data: *mut libc::c_void) {}
 }
index 6f4863057aba431b0635eb11a4671e335e573913..b99eb2e553f08908effdf7385961767f75b30c88 100644 (file)
@@ -275,6 +275,14 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
             target_os = "solaris",
             target_os = "illumos",
         ))] {
+            #[cfg(any(target_os = "android", target_os = "linux"))]
+            {
+                let mut set: libc::cpu_set_t = unsafe { mem::zeroed() };
+                if unsafe { libc::sched_getaffinity(0, mem::size_of::<libc::cpu_set_t>(), &mut set) } == 0 {
+                    let count = unsafe { libc::CPU_COUNT(&set) };
+                    return Ok(unsafe { NonZeroUsize::new_unchecked(count as usize) });
+                }
+            }
             match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } {
                 -1 => Err(io::Error::last_os_error()),
                 0 => Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")),
index e5c550802a7abb8000d851d473296a396601eb01..9dfc8114eb596e29ad2079d4efd9d7586bee24f6 100644 (file)
@@ -977,6 +977,12 @@ pub fn CompareStringOrdinal(
         cchCount2: c_int,
         bIgnoreCase: BOOL,
     ) -> c_int;
+    pub fn GetFullPathNameW(
+        lpFileName: LPCWSTR,
+        nBufferLength: DWORD,
+        lpBuffer: LPWSTR,
+        lpFilePart: *mut LPWSTR,
+    ) -> DWORD;
 }
 
 #[link(name = "ws2_32")]
index ad550a823ae90e2596c26614d19c2911bbd953ad..9859000c8d417480f97823bc6c585341d1a92bfc 100644 (file)
@@ -14,6 +14,7 @@
 use crate::sys::{c, cvt};
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 
+use super::path::maybe_verbatim;
 use super::to_u16s;
 
 pub struct File {
@@ -281,7 +282,7 @@ fn get_flags_and_attributes(&self) -> c::DWORD {
 
 impl File {
     pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
-        let path = to_u16s(path)?;
+        let path = maybe_verbatim(path)?;
         let handle = unsafe {
             c::CreateFileW(
                 path.as_ptr(),
@@ -706,7 +707,7 @@ pub fn new() -> DirBuilder {
     }
 
     pub fn mkdir(&self, p: &Path) -> io::Result<()> {
-        let p = to_u16s(p)?;
+        let p = maybe_verbatim(p)?;
         cvt(unsafe { c::CreateDirectoryW(p.as_ptr(), ptr::null_mut()) })?;
         Ok(())
     }
@@ -715,7 +716,7 @@ pub fn mkdir(&self, p: &Path) -> io::Result<()> {
 pub fn readdir(p: &Path) -> io::Result<ReadDir> {
     let root = p.to_path_buf();
     let star = p.join("*");
-    let path = to_u16s(&star)?;
+    let path = maybe_verbatim(&star)?;
 
     unsafe {
         let mut wfd = mem::zeroed();
@@ -733,20 +734,20 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
 }
 
 pub fn unlink(p: &Path) -> io::Result<()> {
-    let p_u16s = to_u16s(p)?;
+    let p_u16s = maybe_verbatim(p)?;
     cvt(unsafe { c::DeleteFileW(p_u16s.as_ptr()) })?;
     Ok(())
 }
 
 pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
-    let old = to_u16s(old)?;
-    let new = to_u16s(new)?;
+    let old = maybe_verbatim(old)?;
+    let new = maybe_verbatim(new)?;
     cvt(unsafe { c::MoveFileExW(old.as_ptr(), new.as_ptr(), c::MOVEFILE_REPLACE_EXISTING) })?;
     Ok(())
 }
 
 pub fn rmdir(p: &Path) -> io::Result<()> {
-    let p = to_u16s(p)?;
+    let p = maybe_verbatim(p)?;
     cvt(unsafe { c::RemoveDirectoryW(p.as_ptr()) })?;
     Ok(())
 }
@@ -794,7 +795,7 @@ pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
 
 pub fn symlink_inner(original: &Path, link: &Path, dir: bool) -> io::Result<()> {
     let original = to_u16s(original)?;
-    let link = to_u16s(link)?;
+    let link = maybe_verbatim(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
@@ -823,8 +824,8 @@ pub fn symlink_inner(original: &Path, link: &Path, dir: bool) -> io::Result<()>
 
 #[cfg(not(target_vendor = "uwp"))]
 pub fn link(original: &Path, link: &Path) -> io::Result<()> {
-    let original = to_u16s(original)?;
-    let link = to_u16s(link)?;
+    let original = maybe_verbatim(original)?;
+    let link = maybe_verbatim(link)?;
     cvt(unsafe { c::CreateHardLinkW(link.as_ptr(), original.as_ptr(), ptr::null_mut()) })?;
     Ok(())
 }
@@ -857,7 +858,7 @@ pub fn lstat(path: &Path) -> io::Result<FileAttr> {
 }
 
 pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
-    let p = to_u16s(p)?;
+    let p = maybe_verbatim(p)?;
     unsafe {
         cvt(c::SetFileAttributesW(p.as_ptr(), perm.attrs))?;
         Ok(())
@@ -900,8 +901,8 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
         }
         c::PROGRESS_CONTINUE
     }
-    let pfrom = to_u16s(from)?;
-    let pto = to_u16s(to)?;
+    let pfrom = maybe_verbatim(from)?;
+    let pto = maybe_verbatim(to)?;
     let mut size = 0i64;
     cvt(unsafe {
         c::CopyFileExW(
index b8f512f6a232fc88fdf64fd3b2eb05fa1f3441f6..460c1eff7788d1cfd105002a9c3ab91f004bc6b0 100644 (file)
@@ -1,6 +1,10 @@
+use super::{c, fill_utf16_buf, to_u16s};
 use crate::ffi::OsStr;
+use crate::io;
 use crate::mem;
+use crate::path::Path;
 use crate::path::Prefix;
+use crate::ptr;
 
 #[cfg(test)]
 mod tests;
@@ -141,3 +145,100 @@ fn parse_next_component(path: &OsStr, verbatim: bool) -> (&OsStr, &OsStr) {
         None => (path, OsStr::new("")),
     }
 }
+
+/// Returns a UTF-16 encoded path capable of bypassing the legacy `MAX_PATH` limits.
+///
+/// This path may or may not have a verbatim prefix.
+pub(crate) fn maybe_verbatim(path: &Path) -> io::Result<Vec<u16>> {
+    // Normally the MAX_PATH is 260 UTF-16 code units (including the NULL).
+    // However, for APIs such as CreateDirectory[1], the limit is 248.
+    //
+    // [1]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createdirectorya#parameters
+    const LEGACY_MAX_PATH: usize = 248;
+    // UTF-16 encoded code points, used in parsing and building UTF-16 paths.
+    // All of these are in the ASCII range so they can be cast directly to `u16`.
+    const SEP: u16 = b'\\' as _;
+    const ALT_SEP: u16 = b'/' as _;
+    const QUERY: u16 = b'?' as _;
+    const COLON: u16 = b':' as _;
+    const DOT: u16 = b'.' as _;
+    const U: u16 = b'U' as _;
+    const N: u16 = b'N' as _;
+    const C: u16 = b'C' as _;
+
+    // \\?\
+    const VERBATIM_PREFIX: &[u16] = &[SEP, SEP, QUERY, SEP];
+    // \??\
+    const NT_PREFIX: &[u16] = &[SEP, QUERY, QUERY, SEP];
+    // \\?\UNC\
+    const UNC_PREFIX: &[u16] = &[SEP, SEP, QUERY, SEP, U, N, C, SEP];
+
+    let mut path = to_u16s(path)?;
+    if path.starts_with(VERBATIM_PREFIX) || path.starts_with(NT_PREFIX) {
+        // Early return for paths that are already verbatim.
+        return Ok(path);
+    } else if path.len() < LEGACY_MAX_PATH {
+        // Early return if an absolute path is less < 260 UTF-16 code units.
+        // This is an optimization to avoid calling `GetFullPathNameW` unnecessarily.
+        match path.as_slice() {
+            // Starts with `D:`, `D:\`, `D:/`, etc.
+            // Does not match if the path starts with a `\` or `/`.
+            [drive, COLON, 0] | [drive, COLON, SEP | ALT_SEP, ..]
+                if *drive != SEP && *drive != ALT_SEP =>
+            {
+                return Ok(path);
+            }
+            // Starts with `\\`, `//`, etc
+            [SEP | ALT_SEP, SEP | ALT_SEP, ..] => return Ok(path),
+            _ => {}
+        }
+    }
+
+    // Firstly, get the absolute path using `GetFullPathNameW`.
+    // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfullpathnamew
+    let lpfilename = path.as_ptr();
+    fill_utf16_buf(
+        // SAFETY: `fill_utf16_buf` ensures the `buffer` and `size` are valid.
+        // `lpfilename` is a pointer to a null terminated string that is not
+        // invalidated until after `GetFullPathNameW` returns successfully.
+        |buffer, size| unsafe {
+            // While the docs for `GetFullPathNameW` have the standard note
+            // about needing a `\\?\` path for a long lpfilename, this does not
+            // appear to be true in practice.
+            // See:
+            // https://stackoverflow.com/questions/38036943/getfullpathnamew-and-long-windows-file-paths
+            // https://googleprojectzero.blogspot.com/2016/02/the-definitive-guide-on-win32-to-nt.html
+            c::GetFullPathNameW(lpfilename, size, buffer, ptr::null_mut())
+        },
+        |mut absolute| {
+            path.clear();
+
+            // Secondly, add the verbatim prefix. This is easier here because we know the
+            // path is now absolute and fully normalized (e.g. `/` has been changed to `\`).
+            let prefix = match absolute {
+                // C:\ => \\?\C:\
+                [_, COLON, SEP, ..] => VERBATIM_PREFIX,
+                // \\.\ => \\?\
+                [SEP, SEP, DOT, SEP, ..] => {
+                    absolute = &absolute[4..];
+                    VERBATIM_PREFIX
+                }
+                // Leave \\?\ and \??\ as-is.
+                [SEP, SEP, QUERY, SEP, ..] | [SEP, QUERY, QUERY, SEP, ..] => &[],
+                // \\ => \\?\UNC\
+                [SEP, SEP, ..] => {
+                    absolute = &absolute[2..];
+                    UNC_PREFIX
+                }
+                // Anything else we leave alone.
+                _ => &[],
+            };
+
+            path.reserve_exact(prefix.len() + absolute.len() + 1);
+            path.extend_from_slice(prefix);
+            path.extend_from_slice(absolute);
+            path.push(0);
+        },
+    )?;
+    Ok(path)
+}
index 9675da6ff883bd0bbeeec68bf900a44ca9ba8cd4..c6c84519f419cbe750582153d96e906d59e7de69 100644 (file)
@@ -42,3 +42,56 @@ fn test_parse_next_component() {
         (OsStr::new(r"server"), OsStr::new(r"\\\\\\\\\\\\\share"))
     );
 }
+
+#[test]
+fn verbatim() {
+    use crate::path::Path;
+    fn check(path: &str, expected: &str) {
+        let verbatim = maybe_verbatim(Path::new(path)).unwrap();
+        let verbatim = String::from_utf16_lossy(verbatim.strip_suffix(&[0]).unwrap());
+        assert_eq!(&verbatim, expected, "{}", path);
+    }
+
+    // Ensure long paths are correctly prefixed.
+    check(
+        r"C:\Program Files\Rust\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\foo.txt",
+        r"\\?\C:\Program Files\Rust\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\foo.txt",
+    );
+    check(
+        r"\\server\share\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\foo.txt",
+        r"\\?\UNC\server\share\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\foo.txt",
+    );
+    check(
+        r"\\.\PIPE\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\foo.txt",
+        r"\\?\PIPE\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\foo.txt",
+    );
+    // `\\?\` prefixed paths are left unchanged...
+    check(
+        r"\\?\verbatim.\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\foo.txt",
+        r"\\?\verbatim.\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\foo.txt",
+    );
+    // But `//?/` is not a verbatim prefix so it will be normalized.
+    check(
+        r"//?/E:/verbatim.\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\foo.txt",
+        r"\\?\E:\verbatim\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\foo.txt",
+    );
+
+    // For performance, short absolute paths are left unchanged.
+    check(r"C:\Program Files\Rust", r"C:\Program Files\Rust");
+    check(r"\\server\share", r"\\server\share");
+    check(r"\\.\COM1", r"\\.\COM1");
+
+    // Check that paths of length 247 are converted to verbatim.
+    // This is necessary for `CreateDirectory`.
+    check(
+        r"C:\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+        r"\\?\C:\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+    );
+
+    // Make sure opening a drive will work.
+    check("Z:", "Z:");
+
+    // An empty path or a path that contains null are not valid paths.
+    assert!(maybe_verbatim(Path::new("")).is_err());
+    assert!(maybe_verbatim(Path::new("\0")).is_err());
+}
index 7be13bc4b2bc7cf7edb2653dfc929908af829a9c..25d1c6e8e87c2914908430fd4e92c17d11bb10aa 100644 (file)
@@ -1,4 +1,28 @@
+//! Implements thread-local destructors that are not associated with any
+//! particular data.
+
 #![unstable(feature = "thread_local_internals", issue = "none")]
 #![cfg(target_thread_local)]
 
-pub use crate::sys_common::thread_local_dtor::register_dtor_fallback as register_dtor;
+// Using a per-thread list avoids the problems in synchronizing global state.
+#[thread_local]
+static mut DESTRUCTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new();
+
+pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
+    DESTRUCTORS.push((t, dtor));
+}
+
+/// Runs destructors. This should not be called until thread exit.
+pub unsafe fn run_keyless_dtors() {
+    // Drop all the destructors.
+    //
+    // Note: While this is potentially an infinite loop, it *should* be
+    // the case that this loop always terminates because we provide the
+    // guarantee that a TLS key cannot be set after it is flagged for
+    // destruction.
+    while let Some((ptr, dtor)) = DESTRUCTORS.pop() {
+        (dtor)(ptr);
+    }
+    // We're done so free the memory.
+    DESTRUCTORS = Vec::new();
+}
index 0bc511146654b790fbbd6807c29d7ba266e84aa9..ec670238e6f0eaa9ba65ec60687f173d0ebbab6d 100644 (file)
@@ -196,6 +196,8 @@ unsafe fn register_dtor(key: Key, dtor: Dtor) {
 unsafe extern "system" fn on_tls_callback(h: c::LPVOID, dwReason: c::DWORD, pv: c::LPVOID) {
     if dwReason == c::DLL_THREAD_DETACH || dwReason == c::DLL_PROCESS_DETACH {
         run_dtors();
+        #[cfg(target_thread_local)]
+        super::thread_local_dtor::run_keyless_dtors();
     }
 
     // See comments above for what this is doing. Note that we don't need this
index 3d71219756a207bfaba82d9a6a980ef102e6e338..2cd1e29f6c45ddfcc05bb6b93c272e899fee6fca 100644 (file)
@@ -106,6 +106,7 @@ pub fn iter(&self) -> CommandEnvs<'_> {
 /// This struct is created by
 /// [`Command::get_envs`][crate::process::Command::get_envs]. See its
 /// documentation for more.
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "command_access", since = "1.57.0")]
 #[derive(Debug)]
 pub struct CommandEnvs<'a> {
index 9508bd7da594b8853e207b517e089d87bfcc55f6..0629859bd9dcc15bc232b502366bf21512500ff7 100644 (file)
@@ -686,7 +686,7 @@ pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
     }
 }
 
-/// Returns a slice of the given string for the byte range [`begin`..`end`).
+/// Returns a slice of the given string for the byte range \[`begin`..`end`).
 ///
 /// # Panics
 ///
index 1a5cf5ab8226a3b76d06fffae566afbe4274c790..2a155ce31173130d028af622c1944985ffb608d8 100644 (file)
@@ -257,6 +257,7 @@ pub const fn require_unstable_const_init_thread_local() {}
 /// [`unwrap`]: crate::result::Result::unwrap
 /// [naming-threads]: ./index.html#naming-threads
 /// [stack-size]: ./index.html#stack-size
+#[must_use = "must eventually spawn the thread"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
 pub struct Builder {
@@ -649,6 +650,7 @@ pub fn spawn<F, T>(f: F) -> JoinHandle<T>
 ///
 /// handler.join().unwrap();
 /// ```
+#[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn current() -> Thread {
     thread_info::current_thread().expect(
@@ -737,6 +739,7 @@ pub fn yield_now() {
 ///
 /// [Mutex]: crate::sync::Mutex
 #[inline]
+#[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn panicking() -> bool {
     panicking::panicking()
@@ -1131,6 +1134,7 @@ pub fn unpark(&self) {
     /// assert!(thread::current().id() != other_thread_id);
     /// ```
     #[stable(feature = "thread_id", since = "1.19.0")]
+    #[must_use]
     pub fn id(&self) -> ThreadId {
         self.inner.id
     }
@@ -1173,6 +1177,7 @@ pub fn id(&self) -> ThreadId {
     ///
     /// [naming-threads]: ./index.html#naming-threads
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
     pub fn name(&self) -> Option<&str> {
         self.cname().map(|s| unsafe { str::from_utf8_unchecked(s.to_bytes()) })
     }
@@ -1360,6 +1365,7 @@ impl<T> JoinHandle<T> {
     /// println!("thread id: {:?}", thread.id());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
     pub fn thread(&self) -> &Thread {
         &self.0.thread
     }
@@ -1401,6 +1407,15 @@ pub fn thread(&self) -> &Thread {
     pub fn join(mut self) -> Result<T> {
         self.0.join()
     }
+
+    /// Checks if the the associated thread is still running its main function.
+    ///
+    /// This might return `false` for a brief moment after the thread's main
+    /// function has returned, but before the thread itself has stopped running.
+    #[unstable(feature = "thread_is_running", issue = "90470")]
+    pub fn is_running(&self) -> bool {
+        Arc::strong_count(&self.0.packet.0) > 1
+    }
 }
 
 impl<T> AsInner<imp::Thread> for JoinHandle<T> {
index 16ad366fc126a3ece82d309c2b36873273ac3228..ca0d88135a5d8ae43fe35edb7654507da6b34bd7 100644 (file)
@@ -2,9 +2,13 @@
 use crate::any::Any;
 use crate::mem;
 use crate::result;
-use crate::sync::mpsc::{channel, Sender};
+use crate::sync::{
+    mpsc::{channel, Sender},
+    Arc, Barrier,
+};
 use crate::thread::{self, ThreadId};
 use crate::time::Duration;
+use crate::time::Instant;
 
 // !!! These tests are dangerous. If something is buggy, they will hang, !!!
 // !!! instead of exiting cleanly. This might wedge the buildbots.       !!!
@@ -46,6 +50,36 @@ fn test_run_basic() {
     rx.recv().unwrap();
 }
 
+#[test]
+fn test_is_running() {
+    let b = Arc::new(Barrier::new(2));
+    let t = thread::spawn({
+        let b = b.clone();
+        move || {
+            b.wait();
+            1234
+        }
+    });
+
+    // Thread is definitely running here, since it's still waiting for the barrier.
+    assert_eq!(t.is_running(), true);
+
+    // Unblock the barrier.
+    b.wait();
+
+    // Now check that t.is_running() becomes false within a reasonable time.
+    let start = Instant::now();
+    while t.is_running() {
+        assert!(start.elapsed() < Duration::from_secs(2));
+        thread::sleep(Duration::from_millis(15));
+    }
+
+    // Joining the thread should not block for a significant time now.
+    let join_time = Instant::now();
+    assert_eq!(t.join().unwrap(), 1234);
+    assert!(join_time.elapsed() < Duration::from_secs(2));
+}
+
 #[test]
 fn test_join_panic() {
     match thread::spawn(move || panic!()).join() {
index 3e27e3a4297717309aefcf62f6288a87c88fb1e9..a5e3bd0c29030731aaba4e6cfe7aa16c0575d664 100644 (file)
@@ -239,6 +239,7 @@ impl Instant {
     ///
     /// let now = Instant::now();
     /// ```
+    #[must_use]
     #[stable(feature = "time2", since = "1.8.0")]
     pub fn now() -> Instant {
         let os_now = time::Instant::now();
@@ -306,6 +307,7 @@ pub fn now() -> Instant {
     /// let new_now = Instant::now();
     /// println!("{:?}", new_now.duration_since(now));
     /// ```
+    #[must_use]
     #[stable(feature = "time2", since = "1.8.0")]
     pub fn duration_since(&self, earlier: Instant) -> Duration {
         self.0.checked_sub_instant(&earlier.0).expect("supplied instant is later than self")
@@ -326,6 +328,7 @@ pub fn duration_since(&self, earlier: Instant) -> Duration {
     /// println!("{:?}", new_now.checked_duration_since(now));
     /// println!("{:?}", now.checked_duration_since(new_now)); // None
     /// ```
+    #[must_use]
     #[stable(feature = "checked_duration_since", since = "1.39.0")]
     pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
         self.0.checked_sub_instant(&earlier.0)
@@ -346,6 +349,7 @@ pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
     /// println!("{:?}", new_now.saturating_duration_since(now));
     /// println!("{:?}", now.saturating_duration_since(new_now)); // 0ns
     /// ```
+    #[must_use]
     #[stable(feature = "checked_duration_since", since = "1.39.0")]
     pub fn saturating_duration_since(&self, earlier: Instant) -> Duration {
         self.checked_duration_since(earlier).unwrap_or_default()
@@ -370,6 +374,7 @@ pub fn saturating_duration_since(&self, earlier: Instant) -> Duration {
     /// sleep(three_secs);
     /// assert!(instant.elapsed() >= three_secs);
     /// ```
+    #[must_use]
     #[stable(feature = "time2", since = "1.8.0")]
     pub fn elapsed(&self) -> Duration {
         Instant::now() - *self
@@ -476,6 +481,7 @@ impl SystemTime {
     ///
     /// let sys_time = SystemTime::now();
     /// ```
+    #[must_use]
     #[stable(feature = "time2", since = "1.8.0")]
     pub fn now() -> SystemTime {
         SystemTime(time::SystemTime::now())
@@ -644,6 +650,7 @@ impl SystemTimeError {
     ///     Err(e) => println!("SystemTimeError difference: {:?}", e.duration()),
     /// }
     /// ```
+    #[must_use]
     #[stable(feature = "time2", since = "1.8.0")]
     pub fn duration(&self) -> Duration {
         self.0
index dc44c9346b6ef946be2cf61b92f22aacc5f37d9d..7279925a6d0bef166ad8b044d6b36bad1626afb8 100644 (file)
@@ -48,7 +48,7 @@ fn instant_monotonic_concurrent() -> crate::thread::Result<()> {
 #[test]
 fn instant_elapsed() {
     let a = Instant::now();
-    a.elapsed();
+    let _ = a.elapsed();
 }
 
 #[test]
@@ -93,7 +93,7 @@ fn instant_math_is_associative() {
 #[should_panic]
 fn instant_duration_since_panic() {
     let a = Instant::now();
-    (a - Duration::SECOND).duration_since(a);
+    let _ = (a - Duration::SECOND).duration_since(a);
 }
 
 #[test]
index e2aebee916d0eae7bb4f1364fec83f62660141fa..fa23cf2689671c14d8b7da1e14225bd8334d19d1 100644 (file)
@@ -55,8 +55,8 @@ fn write_result(
         _stdout: &[u8],
         _state: &ConsoleTestState,
     ) -> io::Result<()> {
-        // Because the testsuit node holds some of the information as attributes, we can't write it
-        // until all of the tests has ran. Instead of writting every result as they come in, we add
+        // Because the testsuite node holds some of the information as attributes, we can't write it
+        // until all of the tests have finished. Instead of writing every result as they come in, we add
         // them to a Vec and write them all at once when run is complete.
         let duration = exec_time.map(|t| t.0).unwrap_or_default();
         self.results.push((desc.clone(), result.clone(), duration));
index e263780bf38796dbdae16e73b90bb8774edf39eb..079626f0fea54c38755fbc1a7be8af9918890643 100644 (file)
@@ -5,7 +5,6 @@
 #![feature(native_link_modifiers_bundle)]
 #![feature(nll)]
 #![feature(staged_api)]
-#![feature(static_nobundle)]
 #![feature(c_unwind)]
 #![cfg_attr(not(target_env = "msvc"), feature(libc))]
 
index 0c5a0cbc06eb9ae1571c4fe00f53ec4ec5c551b5..38d3c7aec4941f5bfe12c1c7957a9eb93f9d5044 100644 (file)
@@ -1026,7 +1026,15 @@ class RustBuild(object):
         if self.git_version >= distutils.version.LooseVersion("2.11.0"):
             update_args.append("--progress")
         update_args.append(module)
-        run(update_args, cwd=self.rust_root, verbose=self.verbose, exception=True)
+        try:
+            run(update_args, cwd=self.rust_root, verbose=self.verbose, exception=True)
+        except RuntimeError:
+            print("Failed updating submodule. This is probably due to uncommitted local changes.")
+            print('Either stash the changes by running "git stash" within the submodule\'s')
+            print('directory, reset them by running "git reset --hard", or commit them.')
+            print("To reset all submodules' changes run", end=" ")
+            print('"git submodule foreach --recursive git reset --hard".')
+            raise SystemExit(1)
 
         run(["git", "reset", "-q", "--hard"],
             cwd=module_path, verbose=self.verbose)
index d5656f0f37e0389f336276d4942016847e60bc3a..6ba1b1b6036eae55f1ae9d78095f0dedf89e3ee0 100644 (file)
@@ -482,6 +482,7 @@ macro_rules! describe {
                 doc::RustByExample,
                 doc::RustcBook,
                 doc::CargoBook,
+                doc::Clippy,
                 doc::EmbeddedBook,
                 doc::EditionGuide,
             ),
index e9cc7662e6397a9b8bd9c5b2a0392cd4f9115194..007ca9f7f5a92f6431d3025767576f58427b3b4f 100644 (file)
@@ -197,7 +197,7 @@ fn copy_self_contained_objects(
     t!(fs::create_dir_all(&libdir_self_contained));
     let mut target_deps = vec![];
 
-    // Copies the CRT objects.
+    // Copies the libc and CRT objects.
     //
     // rustc historically provides a more self-contained installation for musl targets
     // not requiring the presence of a native musl toolchain. For example, it can fall back
@@ -208,7 +208,7 @@ fn copy_self_contained_objects(
         let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
             panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
         });
-        for &obj in &["crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
+        for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
             copy_and_stamp(
                 builder,
                 &libdir_self_contained,
@@ -235,7 +235,7 @@ fn copy_self_contained_objects(
                 panic!("Target {:?} does not have a \"wasi-root\" key", target.triple)
             })
             .join("lib/wasm32-wasi");
-        for &obj in &["crt1-command.o", "crt1-reactor.o"] {
+        for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
             copy_and_stamp(
                 builder,
                 &libdir_self_contained,
index 6f2470b706a64ff8d16b979376181196ce976230..2804e7119fbc14e8418365082bb879b22861d299 100644 (file)
@@ -755,6 +755,7 @@ fn run(self, builder: &Builder<'_>) {
     "src/tools/rustfmt",
     ["rustfmt-nightly", "rustfmt-config_proc_macro"],
 );
+tool_doc!(Clippy, "clippy", "src/tools/clippy", ["clippy_utils"]);
 
 #[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct ErrorIndex {
index 2d4e15278972469bacd9de44c1b11b34fcaf39f5..3b3c8a9227d95f4c98f76ddf150867eeff761d75 100644 (file)
@@ -277,7 +277,6 @@ pub struct Build {
 struct Crate {
     name: Interned<String>,
     deps: HashSet<Interned<String>>,
-    id: String,
     path: PathBuf,
 }
 
index a38391c7b88f28f31125681682e41bc4441e1d76..65e229697dc87aba4e5627c09f4d6352b344a5df 100644 (file)
@@ -14,7 +14,6 @@ struct Output {
 
 #[derive(Deserialize)]
 struct Package {
-    id: String,
     name: String,
     source: Option<String>,
     manifest_path: String,
@@ -50,7 +49,7 @@ pub fn build(build: &mut Build) {
                 .filter(|dep| dep.source.is_none())
                 .map(|dep| INTERNER.intern_string(dep.name))
                 .collect();
-            build.crates.insert(name, Crate { name, id: package.id, deps, path });
+            build.crates.insert(name, Crate { name, deps, path });
         }
     }
 }
index 63836654293f222908ada9a651c0f8f5b238129e..2b4b78e81350d5dd396e62e038781a837b3c308c 100644 (file)
@@ -1,3 +1,15 @@
+# We need recent curl, OpenSSL and CA certificates, so we can download further
+# dependencies in the debian:6 image. We use an ubuntu 20.04 image download
+# those.
+FROM ubuntu:20.04
+RUN apt-get update && \
+    apt-get install -y --no-install-recommends \
+        curl \
+        ca-certificates
+WORKDIR /tmp
+COPY host-x86_64/dist-x86_64-linux/download-openssl-curl.sh /tmp/
+RUN ./download-openssl-curl.sh
+
 # We use Debian 6 (glibc 2.11, kernel 2.6.32) as a common base for other
 # distros that still need Rust support: RHEL 6 (glibc 2.12, kernel 2.6.32) and
 # SLES 11 SP4 (glibc 2.11, kernel 3.0).
@@ -14,8 +26,6 @@ RUN apt-get update && \
     apt-get install --allow-unauthenticated -y --no-install-recommends \
       automake \
       bzip2 \
-      ca-certificates \
-      curl \
       file \
       g++ \
       g++-multilib \
@@ -34,11 +44,6 @@ RUN apt-get update && \
       xz-utils \
       zlib1g-dev
 
-# Install new Let's Encrypt root CA certificate and remove the expired one.
-COPY host-x86_64/shared/ISRG_Root_X1.crt /usr/local/share/ca-certificates/ISRG_Root_X1.crt
-RUN sed -i '/mozilla\/DST_Root_CA_X3\.crt/d' /etc/ca-certificates.conf
-RUN /usr/sbin/update-ca-certificates
-
 ENV PATH=/rustroot/bin:$PATH
 ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib32:/rustroot/lib
 ENV PKG_CONFIG_PATH=/rustroot/lib/pkgconfig
@@ -50,6 +55,7 @@ COPY host-x86_64/dist-x86_64-linux/shared.sh /tmp/
 # static.rust-lang.org. This'll be used to link into libcurl below (and used
 # later as well), so build a copy of OpenSSL with dynamic libraries into our
 # generic root.
+COPY --from=0 /tmp/openssl.tar.gz /tmp/openssl.tar.gz
 COPY host-x86_64/dist-x86_64-linux/build-openssl.sh /tmp/
 RUN ./build-openssl.sh
 
@@ -59,8 +65,13 @@ RUN ./build-openssl.sh
 #
 # Note that we also disable a bunch of optional features of curl that we don't
 # really need.
+COPY --from=0 /tmp/curl.tar.xz /tmp/curl.tar.xz
 COPY host-x86_64/dist-x86_64-linux/build-curl.sh /tmp/
-RUN ./build-curl.sh && apt-get remove -y curl
+RUN ./build-curl.sh
+
+# Use up-to-date curl CA bundle
+COPY --from=0 /tmp/cacert.pem /tmp/cacert.pem
+ENV CURL_CA_BUNDLE /tmp/cacert.pem
 
 # binutils < 2.22 has a bug where the 32-bit executables it generates
 # immediately segfault in Rust, so we need to install our own binutils.
index 7b560aaaaa68826af7441aab521281294b78d867..50452349931e84c9321a41512c283581859f9068 100644 (file)
@@ -1,3 +1,15 @@
+# We need recent curl, OpenSSL and CA certificates, so we can download further
+# dependencies in the debian:6 image. We use an ubuntu 20.04 image download
+# those.
+FROM ubuntu:20.04
+RUN apt-get update && \
+    apt-get install -y --no-install-recommends \
+        curl \
+        ca-certificates
+WORKDIR /tmp
+COPY host-x86_64/dist-x86_64-linux/download-openssl-curl.sh /tmp/
+RUN ./download-openssl-curl.sh
+
 # We use Debian 6 (glibc 2.11, kernel 2.6.32) as a common base for other
 # distros that still need Rust support: RHEL 6 (glibc 2.12, kernel 2.6.32) and
 # SLES 11 SP4 (glibc 2.11, kernel 3.0).
@@ -14,8 +26,6 @@ RUN apt-get update && \
     apt-get install --allow-unauthenticated -y --no-install-recommends \
       automake \
       bzip2 \
-      ca-certificates \
-      curl \
       file \
       g++ \
       g++-multilib \
@@ -34,11 +44,6 @@ RUN apt-get update && \
       xz-utils \
       zlib1g-dev
 
-# Install new Let's Encrypt root CA certificate and remove the expired one.
-COPY host-x86_64/shared/ISRG_Root_X1.crt /usr/local/share/ca-certificates/ISRG_Root_X1.crt
-RUN sed -i '/mozilla\/DST_Root_CA_X3\.crt/d' /etc/ca-certificates.conf
-RUN /usr/sbin/update-ca-certificates
-
 ENV PATH=/rustroot/bin:$PATH
 ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib32:/rustroot/lib
 ENV PKG_CONFIG_PATH=/rustroot/lib/pkgconfig
@@ -50,6 +55,7 @@ COPY host-x86_64/dist-x86_64-linux/shared.sh /tmp/
 # static.rust-lang.org. This'll be used to link into libcurl below (and used
 # later as well), so build a copy of OpenSSL with dynamic libraries into our
 # generic root.
+COPY --from=0 /tmp/openssl.tar.gz /tmp/openssl.tar.gz
 COPY host-x86_64/dist-x86_64-linux/build-openssl.sh /tmp/
 RUN ./build-openssl.sh
 
@@ -59,8 +65,13 @@ RUN ./build-openssl.sh
 #
 # Note that we also disable a bunch of optional features of curl that we don't
 # really need.
+COPY --from=0 /tmp/curl.tar.xz /tmp/curl.tar.xz
 COPY host-x86_64/dist-x86_64-linux/build-curl.sh /tmp/
-RUN ./build-curl.sh && apt-get remove -y curl
+RUN ./build-curl.sh
+
+# Use up-to-date curl CA bundle
+COPY --from=0 /tmp/cacert.pem /tmp/cacert.pem
+ENV CURL_CA_BUNDLE /tmp/cacert.pem
 
 # binutils < 2.22 has a bug where the 32-bit executables it generates
 # immediately segfault in Rust, so we need to install our own binutils.
index 6efa789756619fcaf3e318159da75bf2a1051c9b..88ee96eaa89b579c0a5e4ea56b7c594fb8a4482d 100755 (executable)
@@ -3,18 +3,11 @@
 set -ex
 source shared.sh
 
-VERSION=7.66.0
-
-# This needs to be downloaded directly from S3, it can't go through the CDN.
-# That's because the CDN is backed by CloudFront, which requires SNI and TLSv1
-# (without paying an absurd amount of money).
-curl https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/curl-$VERSION.tar.xz \
-  | xz --decompress \
-  | tar xf -
+tar xJf curl.tar.xz
 
 mkdir curl-build
 cd curl-build
-hide_output ../curl-$VERSION/configure \
+hide_output ../curl-*/configure \
       --prefix=/rustroot \
       --with-ssl=/rustroot \
       --disable-sspi \
@@ -35,4 +28,4 @@ hide_output make install
 
 cd ..
 rm -rf curl-build
-rm -rf curl-$VERSION
+rm -rf curl-*
index 34bbe19d2fac331cec92db088c24190512273174..b48b5c4c00aae59aa0a11917b46dd7daaf561cc4 100755 (executable)
@@ -3,21 +3,14 @@
 set -ex
 source shared.sh
 
-VERSION=1.0.2k
+tar xzf openssl.tar.gz
 
-# This needs to be downloaded directly from S3, it can't go through the CDN.
-# That's because the CDN is backed by CloudFront, which requires SNI and TLSv1
-# (without paying an absurd amount of money).
-URL=https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/openssl-$VERSION.tar.gz
-
-curl $URL | tar xzf -
-
-cd openssl-$VERSION
+cd openssl-*
 hide_output ./config --prefix=/rustroot shared -fPIC
 hide_output make -j$(nproc)
 hide_output make install
 cd ..
-rm -rf openssl-$VERSION
+rm -rf openssl-*
 
 # Make the system cert collection available to the new install.
 ln -nsf /etc/pki/tls/cert.pem /rustroot/ssl/
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/download-openssl-curl.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/download-openssl-curl.sh
new file mode 100755 (executable)
index 0000000..ca40a8c
--- /dev/null
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+
+set -ex
+
+OPENSSL_VERSION=1.0.2k
+CURL_VERSION=7.66.0
+
+curl -f https://ci-mirrors.rust-lang.org/rustc/openssl-$OPENSSL_VERSION.tar.gz -o openssl.tar.gz
+curl -f https://ci-mirrors.rust-lang.org/rustc/curl-$CURL_VERSION.tar.xz -o curl.tar.xz
+curl -f https://curl.se/ca/cacert.pem -o cacert.pem
diff --git a/src/ci/docker/host-x86_64/shared/ISRG_Root_X1.crt b/src/ci/docker/host-x86_64/shared/ISRG_Root_X1.crt
deleted file mode 100644 (file)
index b85c803..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
-TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
-cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
-WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
-ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
-MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
-h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
-0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
-A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
-T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
-B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
-B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
-KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
-OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
-jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
-qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
-rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
-HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
-hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
-ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
-3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
-NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
-ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
-TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
-jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
-oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
-4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
-mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
-emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
------END CERTIFICATE-----
index b1dacf79d269598d593a3429f567c49b471e549c..93b4f435d4db777c66e38c1b8a5bf160dd4e2c28 100755 (executable)
@@ -50,7 +50,8 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
       # Look for all source files involves in the COPY command
       copied_files=/tmp/.docker-copied-files.txt
       rm -f "$copied_files"
-      for i in $(sed -n -e 's/^COPY \(.*\) .*$/\1/p' "$docker_dir/$image/Dockerfile"); do
+      for i in $(sed -n -e '/^COPY --from=/! s/^COPY \(.*\) .*$/\1/p' \
+          "$docker_dir/$image/Dockerfile"); do
         # List the file names
         find "$script_dir/$i" -type f >> $copied_files
       done
index 70c57e07fdeab7faa5b7f17b277c60f5280bc86c..de6b52a5e001c6265617be41fd0262e30b69df77 100755 (executable)
@@ -53,7 +53,7 @@ files_to_extract=(
 for lib in c cxxrt gcc_s m thr util; do
   files_to_extract=("${files_to_extract[@]}" "./lib/lib${lib}.*" "./usr/lib/lib${lib}.*")
 done
-for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat; do
+for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat kvm; do
   files_to_extract=("${files_to_extract[@]}" "./usr/lib/lib${lib}.*")
 done
 
index 76ee324302e094551f3c6d95f5528f0e5a12e174..fbb3042d0d6ad1683d5365af46ecdcb208e9a7d0 100644 (file)
@@ -672,17 +672,9 @@ jobs:
     strategy:
       matrix:
         include:
-          - name: dist-x86_64-apple
-            env:
-              SCRIPT: ./x.py dist --exclude src/doc --exclude extended && ./x.py dist --target=x86_64-apple-darwin src/doc && ./x.py dist extended
-              RUST_CONFIGURE_ARGS: --host=x86_64-apple-darwin --target=x86_64-apple-darwin,aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.7
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              DIST_REQUIRE_ALL_TOOLS: 1
-            <<: *job-macos-xl
-
+          - &dist-x86_64-linux
+            name: dist-x86_64-linux
+            <<: *job-linux-xl
 
   master:
     name: master
index eb1282ec444db94055fa9531b6f3f803e86bb382..fd9299792852c9a368cb236748781852f75cdac6 160000 (submodule)
@@ -1 +1 @@
-Subproject commit eb1282ec444db94055fa9531b6f3f803e86bb382
+Subproject commit fd9299792852c9a368cb236748781852f75cdac6
index 270fccd339e5972d9c900e788f197e81a0bcd956..51739471276b1776dea27cf562b974ef07e24685 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 270fccd339e5972d9c900e788f197e81a0bcd956
+Subproject commit 51739471276b1776dea27cf562b974ef07e24685
index 2d66852a27c5d0ec50ae021820d1de22caa2b1bd..358e6a61d5f4f0496d0a81e70cdcd25d05307342 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 2d66852a27c5d0ec50ae021820d1de22caa2b1bd
+Subproject commit 358e6a61d5f4f0496d0a81e70cdcd25d05307342
index b5c68b02984f74e99d1f1b332029e05f607e2660..a01d151a7250a540a9cb7ccce5956f020c677c21 160000 (submodule)
@@ -1 +1 @@
-Subproject commit b5c68b02984f74e99d1f1b332029e05f607e2660
+Subproject commit a01d151a7250a540a9cb7ccce5956f020c677c21
index 9a60624fcad0140826c44389571dc622917cd632..27f1ff5e440ef78828b68ab882b98e1b10d9af32 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 9a60624fcad0140826c44389571dc622917cd632
+Subproject commit 27f1ff5e440ef78828b68ab882b98e1b10d9af32
index fba15a46ca8efa97e8a955794724ac7ce27805b8..b06008731af0f7d07cd0614e820c8276dfed1c18 160000 (submodule)
@@ -1 +1 @@
-Subproject commit fba15a46ca8efa97e8a955794724ac7ce27805b8
+Subproject commit b06008731af0f7d07cd0614e820c8276dfed1c18
index 8c41835183797a7a11a3bc4f03a66fa7aee47eb5..c251425d1b7ad34a2d05a38dc03bf66d9fdbca28 100644 (file)
@@ -15,6 +15,7 @@
 - [Platform Support](platform-support.md)
     - [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md)
     - [\*-kmc-solid_\*](platform-support/kmc-solid.md)
+    - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
 - [Target Tier Policy](target-tier-policy.md)
 - [Targets](targets/index.md)
     - [Built-in Targets](targets/built-in.md)
index 70df5170b21c1a2fa370b855021ee04a4f3c7331..fa38dd54d60c89bc7730daa6c20b1c501df0d6df 100644 (file)
@@ -123,9 +123,9 @@ equivalent.
   <tr>
    <td>Forward-edge control flow protection
    </td>
-   <td>No
+   <td>Yes
    </td>
-   <td>
+   <td>Nightly
    </td>
   </tr>
   <tr>
@@ -465,24 +465,27 @@ implementations such as [LLVM ControlFlowIntegrity
 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.
+The Rust compiler supports forward-edge control flow protection on nightly
+builds[40]-[41] <sup id="fnref:6" role="doc-noteref"><a href="#fn:6"
+class="footnote">6</a></sup>.
 
 ```text
-$ readelf -s target/release/hello-rust | grep __cfi_init
+$ readelf -s -W target/debug/rust-cfi | grep "\.cfi"
+    12: 0000000000005170    46 FUNC    LOCAL  DEFAULT   14 _RNvCsjaOHoaNjor6_8rust_cfi7add_one.cfi
+    15: 00000000000051a0    16 FUNC    LOCAL  DEFAULT   14 _RNvCsjaOHoaNjor6_8rust_cfi7add_two.cfi
+    17: 0000000000005270   396 FUNC    LOCAL  DEFAULT   14 _RNvCsjaOHoaNjor6_8rust_cfi4main.cfi
+...
 ```
-Fig. 15. Checking if LLVM CFI is enabled for a given binary.
+Fig. 15. Checking if LLVM CFI is enabled for a given binary[41].
 
-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).
+The presence of symbols suffixed with ".cfi" or 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
+symbols suffixed with ".cfi" or 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
+<small id="fn:6">6\. It also 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>
 
@@ -689,5 +692,8 @@ defaults (unrelated to `READ_IMPLIES_EXEC`).
 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>.
+40. R. de C Valle. “Tracking Issue for LLVM Control Flow Integrity (CFI) Support
+    for Rust #89653.” GitHub. <https://github.com/rust-lang/rust/issues/89653>.
+
+41. “ControlFlowIntegrity.” The Rust Unstable Book.
+    <https://doc.rust-lang.org/beta/unstable-book/compiler-flags/sanitizer.html#controlflowintegrity>.
index bbeab598f2292870baca8e070388fd632881b592..6b0c336b3c7994f47555de6327d7f7fcd4a89e81 100644 (file)
@@ -285,6 +285,7 @@ target | std | host | notes
 `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku
 `x86_64-unknown-hermit` | ? |  |
 `x86_64-unknown-l4re-uclibc` | ? |  |
+[`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * |  | Freestanding/bare-metal x86_64, softfloat
 `x86_64-unknown-none-hermitkernel` | ? |  | HermitCore kernel
 `x86_64-unknown-none-linuxkernel` | * |  | Linux kernel modules
 `x86_64-unknown-openbsd` | ✓ | ✓ | 64-bit OpenBSD
diff --git a/src/doc/rustc/src/platform-support/x86_64-unknown-none.md b/src/doc/rustc/src/platform-support/x86_64-unknown-none.md
new file mode 100644 (file)
index 0000000..afcc480
--- /dev/null
@@ -0,0 +1,76 @@
+# `x86_64-unknown-none`
+
+**Tier: 3**
+
+Freestanding/bare-metal x86-64 binaries in ELF format: firmware, kernels, etc.
+
+## Target maintainers
+
+- Harald Hoyer `harald@profian.com`, https://github.com/haraldh
+- Mike Leany, https://github.com/mikeleany
+
+## Requirements
+
+This target is cross-compiled. There is no support for `std`. There is no
+default allocator, but it's possible to use `alloc` by supplying an allocator.
+
+By default, Rust code generated for this target does not use any vector or
+floating-point registers (e.g. SSE, AVX). This allows the generated code to run
+in environments, such as kernels, which may need to avoid the use of such
+registers or which may have special considerations about the use of such
+registers (e.g. saving and restoring them to avoid breaking userspace code
+using the same registers). You can change code generation to use additional CPU
+features via the `-C target-feature=` codegen options to rustc, or via the
+`#[target_feature]` mechanism within Rust code.
+
+By default, code generated with this target should run on any `x86_64`
+hardware; enabling additional target features may raise this baseline.
+
+Code generated with this target will use the `kernel` code model by default.
+You can change this using the `-C code-model=` option to rustc.
+
+On `x86_64-unknown-none`, `extern "C"` uses the [standard System V calling
+convention](https://gitlab.com/x86-psABIs/x86-64-ABI), without red zones.
+
+This target generated binaries in the ELF format. Any alternate formats or
+special considerations for binary layout will require linker options or linker
+scripts.
+
+## Building the target
+
+You can build Rust with support for the target by adding it to the `target`
+list in `config.toml`:
+
+```toml
+[build]
+build-stage = 1
+target = ["x86_64-unknown-none"]
+```
+
+## Building Rust programs
+
+Rust does not yet ship pre-compiled artifacts for this target. To compile for
+this target, you will either need to build Rust with the target enabled (see
+"Building the target" above), or build your own copy of `core` by using
+`build-std` or similar.
+
+## Testing
+
+As `x86_64-unknown-none` supports a variety of different environments and does
+not support `std`, this target does not support running the Rust testsuite.
+
+## Cross-compilation toolchains and C code
+
+If you want to compile C code along with Rust (such as for Rust crates with C
+dependencies), you will need an appropriate `x86_64` toolchain.
+
+Rust *may* be able to use an `x86_64-linux-gnu-` toolchain with appropriate
+standalone flags to build for this toolchain (depending on the assumptions of
+that toolchain, see below), or you may wish to use a separate
+`x86_64-unknown-none` (or `x86_64-elf-`) toolchain.
+
+On some `x86_64` hosts that use ELF binaries, you *may* be able to use the host
+C toolchain, if it does not introduce assumptions about the host environment
+that don't match the expectations of a standalone environment. Otherwise, you
+may need a separate toolchain for standalone/freestanding development, just as
+when cross-compiling from a non-`x86_64` platform.
index 3fa91bb51f02fb7d8c0ee8d2a6fac50c6aa410da..eb18185945387cbaf5de34a8cfc6335ccfc89c9d 100644 (file)
@@ -1,6 +1,7 @@
 # The Rustdoc Book
 
 - [What is rustdoc?](what-is-rustdoc.md)
+- [How to read rustdoc output](how-to-read-rustdoc.md)
 - [How to write documentation](how-to-write-documentation.md)
 - [What to include (and exclude)](what-to-include.md)
 - [Command-line arguments](command-line-arguments.md)
diff --git a/src/doc/rustdoc/src/how-to-read-rustdoc.md b/src/doc/rustdoc/src/how-to-read-rustdoc.md
new file mode 100644 (file)
index 0000000..99724d8
--- /dev/null
@@ -0,0 +1,107 @@
+# How to read rustdoc output
+
+Rustdoc's HTML output includes a friendly and useful navigation interface which
+makes it easier for users to navigate and understand your code.
+This chapter covers the major features of that interface,
+and is a great starting point for documentation authors and users alike.
+
+## Structure
+
+The `rustdoc` output is divided into three sections.
+Along the left side of each page is a quick navigation bar,
+which shows contextual information about the current entry.
+The rest of the page is taken up by the search interface at the top
+and the documentation for the current item below that.
+
+## The Item Documentation
+
+The majority of the screen is taken up with the documentation text for the item
+currently being viewed.
+At the top is some at-a-glance info and controls:
+
+- the type and name of the item,
+  such as "Struct `std::time::Duration`",
+- a button to copy the item's path to the clipboard,
+  which is a clipboard item
+- a button to collapse or expand the top-level documentation for that item
+  (`[+]` or `[-]`),
+- a link to the source code (`[src]`),
+  if [configured](the-doc-attribute.html#html_no_source),
+  and present (the source may not be available if
+  the documentation was created with `cargo doc --no-deps`),
+- and the version in which the item became stable,
+  if it's a stable item in the standard library.
+
+Below this is the main documentation for the item,
+including a definition or function signature if appropriate,
+followed by a list of fields or variants for Rust types.
+Finally, the page lists associated functions and trait implementations,
+including automatic and blanket implementations that `rustdoc` knows about.
+
+### Navigation
+
+Subheadings, variants, fields, and many other things in this documentation
+are anchors and can be clicked on and deep-linked to,
+which is a great way to communicate exactly what you're talking about.
+The typograpical character "§" appears next to lines with anchors on them
+when hovered or given keyboard focus.
+
+## The Navigation Bar
+
+For example, when looking at documentation for the crate root,
+it shows all the crates documented in the documentation bundle,
+and quick links to the modules, structs, traits, functions, and macros available
+from the current crate.
+At the top, it displays a [configurable logo](the-doc-attribute.html#html_logo_url)
+alongside the current crate's name and version,
+or the current item whose documentation is being displayed.
+
+## The Theme Picker and Search Interface
+
+When viewing `rustdoc`'s output in a browser with JavaScript enabled,
+a dynamic interface appears at the top of the page.
+To the left is the theme picker, denoted with a paint-brush icon,
+and the search interface, help screen, and options appear to the right of that.
+
+### The Theme Picker
+
+Clicking on the theme picker provides a list of themes -
+by default `ayu`, `light`, and `dark` -
+which are available for viewing.
+
+### The Search Interface
+
+Typing in the search bar instantly searches the available documentation for
+the string entered with a fuzzy matching algorithm that is tolerant of minor
+typos.
+
+By default, the search results give are "In Names",
+meaning that the fuzzy match is made against the names of items.
+Matching names are shown on the left, and the first few words of their
+descriptions are given on the right.
+By clicking an item, you will navigate to its particular documentation.
+
+There are two other sets of results, shown as tabs in the search results pane.
+"In Parameters" shows matches for the string in the types of parameters to
+functions, and "In Return Types" shows matches in the return types of functions.
+Both are very useful when looking for a function whose name you can't quite
+bring to mind when you know the type you have or want.
+
+When typing in the search bar, you can prefix your search term with a type
+followed by a colon (such as `mod:`) to restrict the results to just that
+kind of item. (The available items are listed in the help popup.)
+
+### Shortcuts
+
+Pressing `S` while focused elsewhere on the page will move focus to the
+search bar, and pressing `?` shows the help screen,
+which includes all these shortcuts and more.
+Pressing `T` focuses the theme picker.
+
+When the search results are focused,
+the left and right arrows move between tabs and the up and down arrows move
+among the results.
+Pressing the enter or return key opens the highlighted result.
+
+When looking at the documentation for an item, the plus and minus keys expand
+and collapse all sections in the document.
index b17ea7cd8f5974c4bcbf4b1fda006a5b181ecf9e..a75b6d3893128a6205907b856b614968718c6616 100644 (file)
@@ -153,7 +153,9 @@ example, if you want your doctests to fail if they produce any warnings, you cou
 These forms of the `#[doc]` attribute are used on individual items, to control how
 they are documented.
 
-## `#[doc(no_inline)]`/`#[doc(inline)]`
+### `inline` and `no_inline`
+
+<span id="docno_inlinedocinline"></span>
 
 These attributes are used on `use` statements, and control where the documentation shows
 up. For example, consider this Rust code:
@@ -219,7 +221,56 @@ Now we'll have a `Re-exports` line, and `Bar` will not link to anywhere.
 One special case: In Rust 2018 and later, if you `pub use` one of your dependencies, `rustdoc` will
 not eagerly inline it as a module unless you add `#[doc(inline)]`.
 
-## `#[doc(hidden)]`
+### `hidden`
+
+<span id="dochidden"></span>
 
 Any item annotated with `#[doc(hidden)]` will not appear in the documentation, unless
 the `strip-hidden` pass is removed.
+
+### `alias`
+
+This attribute adds an alias in the search index.
+
+Let's take an example:
+
+```rust,no_run
+#[doc(alias = "TheAlias")]
+pub struct SomeType;
+```
+
+So now, if you enter "TheAlias" in the search, it'll display `SomeType`.
+Of course, if you enter `SomeType` it'll return `SomeType` as expected!
+
+#### FFI example
+
+This doc attribute is especially useful when writing bindings for a C library.
+For example, let's say we have a C function that looks like this:
+
+```c
+int lib_name_do_something(Obj *obj);
+```
+
+It takes a pointer to an `Obj` type and returns an integer. In Rust, it might
+be written like this:
+
+```ignore (using non-existing ffi types)
+pub struct Obj {
+    inner: *mut ffi::Obj,
+}
+
+impl Obj {
+    pub fn do_something(&mut self) -> i32 {
+        unsafe { ffi::lib_name_do_something(self.inner) }
+    }
+}
+```
+
+The function has been turned into a method to make it more convenient to use.
+However, if you want to look for the Rust equivalent of `lib_name_do_something`,
+you have no way to do so.
+
+To get around this limitation, we just add `#[doc(alias = "lib_name_do_something")]`
+on the `do_something` method and then it's all good!
+Users can now look for `lib_name_do_something` in our crate directly and find
+`Obj::do_something`.
index 51f365be922fa3225746cccbfa4e6c2723389819..b3b6422afab427cc26f749ca5d8b142c711518c7 100644 (file)
@@ -134,9 +134,27 @@ Book][unstable-masked] and [its tracking issue][issue-masked].
 
 ## Document primitives
 
+This is for Rust compiler internal use only.
+
 Since primitive types are defined in the compiler, there's no place to attach documentation
-attributes. The `#[doc(primitive)]` attribute is used by the standard library to provide a way to generate
-documentation for primitive types, and requires `#![feature(doc_primitive)]` to enable.
+attributes. The `#[doc(primitive)]` attribute is used by the standard library to provide a way
+to generate documentation for primitive types, and requires `#![feature(doc_primitive)]` to enable.
+
+## Document keywords
+
+This is for Rust compiler internal use only.
+
+Rust keywords are documented in the standard library (look for `match` for example).
+
+To do so, the `#[doc(keyword = "...")]` attribute is used. Example:
+
+```rust
+#![feature(doc_keyword)]
+
+/// Some documentation about the keyword.
+#[doc(keyword = "keyword")]
+mod empty_mod {}
+```
 
 ## Unstable command-line arguments
 
diff --git a/src/doc/unstable-book/src/compiler-flags/no-unique-section-names.md b/src/doc/unstable-book/src/compiler-flags/no-unique-section-names.md
new file mode 100644 (file)
index 0000000..5c1c7cd
--- /dev/null
@@ -0,0 +1,9 @@
+# `no-unique-section-names`
+
+------------------------
+
+This flag currently applies only to ELF-based targets using the LLVM codegen backend. It prevents the generation of unique ELF section names for each separate code and data item when `-Z function-sections` is also in use, which is the default for most targets. This option can reduce the size of object files, and depending on the linker, the final ELF binary as well.
+
+For example, a function `func` will by default generate a code section called `.text.func`. Normally this is fine because the linker will merge all those `.text.*` sections into a single one in the binary. However, starting with [LLVM 12](https://github.com/llvm/llvm-project/commit/ee5d1a04), the backend will also generate unique section names for exception handling, so you would see a section name of `.gcc_except_table.func` in the object file and potentially in the final ELF binary, which could add significant bloat to programs that contain many functions.
+
+This flag instructs LLVM to use the same `.text` and `.gcc_except_table` section name for each function, and it is analogous to Clang's `-fno-unique-section-names` option.
index 29a267053b47d109e1f3d68154104701ee802e22..b3dbc9a9956795273b3ec854ef72873681057206 100644 (file)
@@ -1,19 +1,24 @@
 # `sanitizer`
 
-The tracking issue for this feature is: [#39699](https://github.com/rust-lang/rust/issues/39699).
+The tracking issues for this feature are:
+
+* [#39699](https://github.com/rust-lang/rust/issues/39699).
+* [#89653](https://github.com/rust-lang/rust/issues/89653).
 
 ------------------------
 
 This feature allows for use of one of following sanitizers:
 
 * [AddressSanitizer][clang-asan] a fast memory error detector.
+* [ControlFlowIntegrity][clang-cfi] LLVM Control Flow Integrity (CFI) provides
+  forward-edge control flow protection.
 * [HWAddressSanitizer][clang-hwasan] a memory error detector similar to
   AddressSanitizer, but based on partial hardware assistance.
 * [LeakSanitizer][clang-lsan] a run-time memory leak detector.
 * [MemorySanitizer][clang-msan] a detector of uninitialized reads.
 * [ThreadSanitizer][clang-tsan] a fast data race detector.
 
-To enable a sanitizer compile with `-Zsanitizer=address`,
+To enable a sanitizer compile with `-Zsanitizer=address`,`-Zsanitizer=cfi`,
 `-Zsanitizer=hwaddress`, `-Zsanitizer=leak`, `-Zsanitizer=memory` or
 `-Zsanitizer=thread`.
 
@@ -177,6 +182,176 @@ Shadow byte legend (one shadow byte represents 8 application bytes):
 ==39249==ABORTING
 ```
 
+# ControlFlowIntegrity
+
+The LLVM Control Flow Integrity (CFI) support in the Rust compiler initially
+provides forward-edge control flow protection for Rust-compiled code only by
+aggregating function pointers in groups identified by their number of arguments.
+
+Forward-edge control flow protection for C or C++ and Rust -compiled code "mixed
+binaries" (i.e., for when C or C++ and Rust -compiled code share the same
+virtual address space) will be provided in later work by defining and using
+compatible type identifiers (see Type metadata in the design document in the
+tracking issue [#89653](https://github.com/rust-lang/rust/issues/89653)).
+
+LLVM CFI can be enabled with -Zsanitizer=cfi and requires LTO (i.e., -Clto).
+
+## Example
+
+```text
+#![feature(asm, naked_functions)]
+
+use std::mem;
+
+fn add_one(x: i32) -> i32 {
+    x + 1
+}
+
+#[naked]
+pub extern "C" fn add_two(x: i32) {
+    // x + 2 preceeded by a landing pad/nop block
+    unsafe {
+        asm!(
+            "
+             nop
+             nop
+             nop
+             nop
+             nop
+             nop
+             nop
+             nop
+             nop
+             lea rax, [rdi+2]
+             ret
+        ",
+            options(noreturn)
+        );
+    }
+}
+
+fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
+    f(arg) + f(arg)
+}
+
+fn main() {
+    let answer = do_twice(add_one, 5);
+
+    println!("The answer is: {}", answer);
+
+    println!("With CFI enabled, you should not see the next answer");
+    let f: fn(i32) -> i32 = unsafe {
+        // Offsets 0-8 make it land in the landing pad/nop block, and offsets 1-8 are
+        // invalid branch/call destinations (i.e., within the body of the function).
+        mem::transmute::<*const u8, fn(i32) -> i32>((add_two as *const u8).offset(5))
+    };
+    let next_answer = do_twice(f, 5);
+
+    println!("The next answer is: {}", next_answer);
+}
+```
+Fig. 1. Modified example from the [Advanced Functions and
+Closures][rust-book-ch19-05] chapter of the [The Rust Programming
+Language][rust-book] book.
+
+[//]: # (FIXME: Replace with output from cargo using nightly when #89652 is merged)
+
+```shell
+$ rustc rust_cfi.rs -o rust_cfi
+$ ./rust_cfi
+The answer is: 12
+With CFI enabled, you should not see the next answer
+The next answer is: 14
+$
+```
+Fig. 2. Build and execution of the modified example with LLVM CFI disabled.
+
+[//]: # (FIXME: Replace with output from cargo using nightly when #89652 is merged)
+
+```shell
+$ rustc -Clto -Zsanitizer=cfi rust_cfi.rs -o rust_cfi
+$ ./rust_cfi
+The answer is: 12
+With CFI enabled, you should not see the next answer
+Illegal instruction
+$
+```
+Fig. 3. Build and execution of the modified example with LLVM CFI enabled.
+
+When LLVM CFI is enabled, if there are any attempts to change/hijack control
+flow using an indirect branch/call to an invalid destination, the execution is
+terminated (see Fig. 3).
+
+```rust
+use std::mem;
+
+fn add_one(x: i32) -> i32 {
+    x + 1
+}
+
+fn add_two(x: i32, _y: i32) -> i32 {
+    x + 2
+}
+
+fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
+    f(arg) + f(arg)
+}
+
+fn main() {
+    let answer = do_twice(add_one, 5);
+
+    println!("The answer is: {}", answer);
+
+    println!("With CFI enabled, you should not see the next answer");
+    let f: fn(i32) -> i32 =
+        unsafe { mem::transmute::<*const u8, fn(i32) -> i32>(add_two as *const u8) };
+    let next_answer = do_twice(f, 5);
+
+    println!("The next answer is: {}", next_answer);
+}
+```
+Fig. 4. Another modified example from the [Advanced Functions and
+Closures][rust-book-ch19-05] chapter of the [The Rust Programming
+Language][rust-book] book.
+
+[//]: # (FIXME: Replace with output from cargo using nightly when #89652 is merged)
+
+```shell
+$ rustc rust_cfi.rs -o rust_cfi
+$ ./rust_cfi
+The answer is: 12
+With CFI enabled, you should not see the next answer
+The next answer is: 14
+$
+```
+Fig. 5. Build and execution of the modified example with LLVM CFI disabled.
+
+[//]: # (FIXME: Replace with output from cargo using nightly when #89652 is merged)
+
+```shell
+$ rustc -Clto -Zsanitizer=cfi rust_cfi.rs -o rust_cfi
+$ ./rust_cfi
+The answer is: 12
+With CFI enabled, you should not see the next answer
+Illegal instruction
+$
+```
+Fig. 6. Build and execution of the modified example with LLVM CFI enabled.
+
+When LLVM CFI is enabled, if there are any attempts to change/hijack control
+flow using an indirect branch/call to a function with different number of
+arguments than intended/passed in the call/branch site, the execution is also
+terminated (see Fig. 6).
+
+Forward-edge control flow protection not only by aggregating function pointers
+in groups identified by their number of arguments, but also their argument
+types, will also be provided in later work by defining and using compatible type
+identifiers (see Type metadata in the design document in the tracking
+issue [#89653](https://github.com/rust-lang/rust/issues/89653)).
+
+[rust-book-ch19-05]: https://doc.rust-lang.org/book/ch19-05-advanced-functions-and-closures.html
+[rust-book]: https://doc.rust-lang.org/book/title-page.html
+
 # HWAddressSanitizer
 
 HWAddressSanitizer is a newer variant of AddressSanitizer that consumes much
@@ -404,12 +579,14 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT
 
 * [Sanitizers project page](https://github.com/google/sanitizers/wiki/)
 * [AddressSanitizer in Clang][clang-asan]
+* [ControlFlowIntegrity in Clang][clang-cfi]
 * [HWAddressSanitizer in Clang][clang-hwasan]
 * [LeakSanitizer in Clang][clang-lsan]
 * [MemorySanitizer in Clang][clang-msan]
 * [ThreadSanitizer in Clang][clang-tsan]
 
 [clang-asan]: https://clang.llvm.org/docs/AddressSanitizer.html
+[clang-cfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html
 [clang-hwasan]: https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html
 [clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html
 [clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html
index 5a2cef24870be49daaff686d45f225e39cfdffd4..84fc6dcc33979d1605ab373e13cb00aa9bd622eb 100644 (file)
@@ -66,7 +66,7 @@ assert_eq!(x, 5);
 This will write the value `5` into the `u64` variable `x`.
 You can see that the string literal we use to specify instructions is actually a template string.
 It is governed by the same rules as Rust [format strings][format-syntax].
-The arguments that are inserted into the template however look a bit different then you may
+The arguments that are inserted into the template however look a bit different than you may
 be familiar with. First we need to specify if the variable is an input or an output of the
 inline assembly. In this case it is an output. We declared this by writing `out`.
 We also need to specify in what kind of register the assembly expects the variable.
@@ -106,7 +106,7 @@ code.
 Second, we can see that inputs are declared by writing `in` instead of `out`.
 
 Third, one of our operands has a type we haven't seen yet, `const`.
-This tells the compiler to expand this argument to value directly inside the assembly template.
+This tells the compiler to expand this argument to value directly inside the assembly template.
 This is only possible for constants and literals.
 
 Fourth, we can see that we can specify an argument number, or name as in any format string.
@@ -257,7 +257,7 @@ unsafe {
 }
 
 println!(
-    "L1 Cache: {}",
+    "L0 Cache: {}",
     ((ebx >> 22) + 1) * (((ebx >> 12) & 0x3ff) + 1) * ((ebx & 0xfff) + 1) * (ecx + 1)
 );
 ```
@@ -885,5 +885,7 @@ The compiler performs some additional checks on options:
     - You are responsible for switching any target-specific state (e.g. thread-local storage, stack bounds).
     - The set of memory locations that you may access is the intersection of those allowed by the `asm!` blocks you entered and exited.
 - You cannot assume that an `asm!` block will appear exactly once in the output binary. The compiler is allowed to instantiate multiple copies of the `asm!` block, for example when the function containing it is inlined in multiple places.
+- On x86, inline assembly must not end with an instruction prefix (such as `LOCK`) that would apply to instructions generated by the compiler.
+  - The compiler is currently unable to detect this due to the way inline assembly is compiled, but may catch and reject this in the future.
 
 > **Note**: As a general rule, the flags covered by `preserves_flags` are those which are *not* preserved when performing a function call.
index 146d17b4638c8357fcdac18ace09d2209836d299..3f8e165841d1421bb906720da5f8fc2171c4c26d 100644 (file)
@@ -75,7 +75,7 @@ are concatenated into one or assembled separately.
 constants defined in Rust to be used in assembly code:
 
 ```rust,no_run
-#![feature(global_asm)]
+#![feature(global_asm, asm_const)]
 # #[cfg(any(target_arch="x86", target_arch="x86_64"))]
 # mod x86 {
 const C: i32 = 1234;
@@ -96,7 +96,7 @@ override this by adding `options(att_syntax)` at the end of the macro
 arguments list:
 
 ```rust,no_run
-#![feature(global_asm)]
+#![feature(global_asm, asm_const)]
 # #[cfg(any(target_arch="x86", target_arch="x86_64"))]
 # mod x86 {
 global_asm!("movl ${}, %ecx", const 5, options(att_syntax));
index 945b2a8e9a80e75c8f011041f45f20264ce46a9a..268905bcb5339f9d45a3b12e7beb78fccc8934b8 100644 (file)
@@ -10,7 +10,7 @@ path = "lib.rs"
 arrayvec = { version = "0.7", default-features = false }
 pulldown-cmark = { version = "0.8", default-features = false }
 minifier = "0.0.41"
-rayon = { version = "0.3.0", package = "rustc-rayon" }
+rayon = "1.3.1"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
 smallvec = "1.6.1"
index 05817e1b1d99e7a45bb9c2d581bc7a3dd8273721..2ccf17387d1c701febec22a676ea264bd07bb845 100644 (file)
@@ -76,17 +76,17 @@ fn generate_for_trait(
             new_generics
         });
 
-        let negative_polarity;
+        let polarity;
         let new_generics = match result {
             AutoTraitResult::PositiveImpl(new_generics) => {
-                negative_polarity = false;
+                polarity = ty::ImplPolarity::Positive;
                 if discard_positive_impl {
                     return None;
                 }
                 new_generics
             }
             AutoTraitResult::NegativeImpl => {
-                negative_polarity = true;
+                polarity = ty::ImplPolarity::Negative;
 
                 // For negative impls, we use the generic params, but *not* the predicates,
                 // from the original type. Otherwise, the displayed impl appears to be a
@@ -115,15 +115,13 @@ fn generate_for_trait(
             visibility: Inherited,
             def_id: ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
             kind: box ImplItem(Impl {
-                span: Span::dummy(),
                 unsafety: hir::Unsafety::Normal,
                 generics: new_generics,
                 trait_: Some(trait_ref.clean(self.cx)),
                 for_: ty.clean(self.cx),
                 items: Vec::new(),
-                negative_polarity,
-                synthetic: true,
-                blanket_impl: None,
+                polarity,
+                kind: ImplKind::Auto,
             }),
             cfg: None,
         })
@@ -136,7 +134,7 @@ fn generate_for_trait(
         let f = auto_trait::AutoTraitFinder::new(tcx);
 
         debug!("get_auto_trait_impls({:?})", ty);
-        let auto_traits: Vec<_> = self.cx.auto_traits.iter().cloned().collect();
+        let auto_traits: Vec<_> = self.cx.auto_traits.iter().copied().collect();
         let mut auto_traits: Vec<Item> = auto_traits
             .into_iter()
             .filter_map(|trait_def_id| {
@@ -193,8 +191,8 @@ fn handle_lifetimes<'cx>(
         // to its smaller and larger regions. Note that 'larger' regions correspond
         // to sub-regions in Rust code (e.g., in 'a: 'b, 'a is the larger region).
         for constraint in regions.constraints.keys() {
-            match constraint {
-                &Constraint::VarSubVar(r1, r2) => {
+            match *constraint {
+                Constraint::VarSubVar(r1, r2) => {
                     {
                         let deps1 = vid_map.entry(RegionTarget::RegionVid(r1)).or_default();
                         deps1.larger.insert(RegionTarget::RegionVid(r2));
@@ -203,15 +201,15 @@ fn handle_lifetimes<'cx>(
                     let deps2 = vid_map.entry(RegionTarget::RegionVid(r2)).or_default();
                     deps2.smaller.insert(RegionTarget::RegionVid(r1));
                 }
-                &Constraint::RegSubVar(region, vid) => {
+                Constraint::RegSubVar(region, vid) => {
                     let deps = vid_map.entry(RegionTarget::RegionVid(vid)).or_default();
                     deps.smaller.insert(RegionTarget::Region(region));
                 }
-                &Constraint::VarSubReg(vid, region) => {
+                Constraint::VarSubReg(vid, region) => {
                     let deps = vid_map.entry(RegionTarget::RegionVid(vid)).or_default();
                     deps.larger.insert(RegionTarget::Region(region));
                 }
-                &Constraint::RegSubReg(r1, r2) => {
+                Constraint::RegSubReg(r1, r2) => {
                     // The constraint is already in the form that we want, so we're done with it
                     // Desired order is 'larger, smaller', so flip then
                     if region_name(r1) != region_name(r2) {
@@ -513,8 +511,8 @@ fn param_env_to_generics(
                         // as we want to combine them with any 'Output' qpaths
                         // later
 
-                        let is_fn = match &mut b {
-                            &mut GenericBound::TraitBound(ref mut p, _) => {
+                        let is_fn = match b {
+                            GenericBound::TraitBound(ref mut p, _) => {
                                 // Insert regions into the for_generics hash map first, to ensure
                                 // that we don't end up with duplicate bounds (e.g., for<'b, 'b>)
                                 for_generics.extend(p.generic_params.clone());
@@ -699,8 +697,8 @@ fn is_fn_trait(&self, path: &Path) -> bool {
 }
 
 fn region_name(region: Region<'_>) -> Option<Symbol> {
-    match region {
-        &ty::ReEarlyBound(r) => Some(r.name),
+    match *region {
+        ty::ReEarlyBound(r) => Some(r.name),
         _ => None,
     }
 }
@@ -717,8 +715,8 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
     }
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        (match r {
-            &ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(),
+        (match *r {
+            ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(),
             _ => None,
         })
         .unwrap_or_else(|| r.super_fold_with(self))
index 843dda324da7fb75842b6ca3457f17f1b69bdcdc..f44589f60675f5dbe8bb38c358121be812d540d1 100644 (file)
@@ -106,7 +106,6 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                     visibility: Inherited,
                     def_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
                     kind: box ImplItem(Impl {
-                        span: Span::new(self.cx.tcx.def_span(impl_def_id)),
                         unsafety: hir::Unsafety::Normal,
                         generics: (
                             self.cx.tcx.generics_of(impl_def_id),
@@ -122,11 +121,10 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                             .tcx
                             .associated_items(impl_def_id)
                             .in_definition_order()
-                            .collect::<Vec<_>>()
-                            .clean(self.cx),
-                        negative_polarity: false,
-                        synthetic: false,
-                        blanket_impl: Some(box trait_ref.self_ty().clean(self.cx)),
+                            .map(|x| x.clean(self.cx))
+                            .collect::<Vec<_>>(),
+                        polarity: ty::ImplPolarity::Positive,
+                        kind: ImplKind::Blanket(box trait_ref.self_ty().clean(self.cx)),
                     }),
                     cfg: None,
                 });
index e11b802a09a3b9d3961083494b9705b99f3535b7..d670288270a403cfb4b4c2757a56b36a973ed9d0 100644 (file)
@@ -15,7 +15,7 @@
 use rustc_span::symbol::{kw, sym, Symbol};
 
 use crate::clean::{
-    self, utils, Attributes, AttributesExt, GetDefId, ItemId, NestedAttributesExt, Type,
+    self, utils, Attributes, AttributesExt, ImplKind, ItemId, NestedAttributesExt, Type,
 };
 use crate::core::DocContext;
 use crate::formats::item_type::ItemType;
@@ -244,7 +244,7 @@ fn build_enum(cx: &mut DocContext<'_>, did: DefId) -> clean::Enum {
     clean::Enum {
         generics: (cx.tcx.generics_of(did), predicates).clean(cx),
         variants_stripped: false,
-        variants: cx.tcx.adt_def(did).variants.clean(cx),
+        variants: cx.tcx.adt_def(did).variants.iter().map(|v| v.clean(cx)).collect(),
     }
 }
 
@@ -255,7 +255,7 @@ fn build_struct(cx: &mut DocContext<'_>, did: DefId) -> clean::Struct {
     clean::Struct {
         struct_type: variant.ctor_kind,
         generics: (cx.tcx.generics_of(did), predicates).clean(cx),
-        fields: variant.fields.clean(cx),
+        fields: variant.fields.iter().map(|x| x.clean(cx)).collect(),
         fields_stripped: false,
     }
 }
@@ -264,11 +264,9 @@ fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union {
     let predicates = cx.tcx.explicit_predicates_of(did);
     let variant = cx.tcx.adt_def(did).non_enum_variant();
 
-    clean::Union {
-        generics: (cx.tcx.generics_of(did), predicates).clean(cx),
-        fields: variant.fields.clean(cx),
-        fields_stripped: false,
-    }
+    let generics = (cx.tcx.generics_of(did), predicates).clean(cx);
+    let fields = variant.fields.iter().map(|x| x.clean(cx)).collect();
+    clean::Union { generics, fields, fields_stripped: false }
 }
 
 fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> clean::Typedef {
@@ -325,7 +323,7 @@ fn merge_attrs(
     }
 }
 
-/// Builds a specific implementation of a type. The `did` could be a type method or trait method.
+/// Inline an `impl`, inherent or of a trait. The `did` must be for an `impl`.
 crate fn build_impl(
     cx: &mut DocContext<'_>,
     parent_module: impl Into<Option<DefId>>,
@@ -337,6 +335,8 @@ fn merge_attrs(
         return;
     }
 
+    let _prof_timer = cx.tcx.sess.prof.generic_activity("build_extern_trait_impl");
+
     let tcx = cx.tcx;
     let associated_trait = tcx.impl_trait_ref(did);
 
@@ -376,7 +376,7 @@ fn merge_attrs(
     // Only inline impl if the implementing type is
     // reachable in rustdoc generated documentation
     if !did.is_local() {
-        if let Some(did) = for_.def_id() {
+        if let Some(did) = for_.def_id(&cx.cache) {
             if !cx.cache.access_levels.is_public(did) {
                 return;
             }
@@ -446,7 +446,7 @@ fn merge_attrs(
         ),
     };
     let polarity = tcx.impl_polarity(did);
-    let trait_ = associated_trait.clean(cx);
+    let trait_ = associated_trait.map(|t| t.clean(cx));
     if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() {
         super::build_deref_target_impls(cx, &trait_items, ret);
     }
@@ -464,7 +464,7 @@ fn merge_attrs(
     }
 
     while let Some(ty) = stack.pop() {
-        if let Some(did) = ty.def_id() {
+        if let Some(did) = ty.def_id(&cx.cache) {
             if tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden) {
                 return;
             }
@@ -481,20 +481,22 @@ fn merge_attrs(
     let (merged_attrs, cfg) = merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs);
     trace!("merged_attrs={:?}", merged_attrs);
 
-    trace!("build_impl: impl {:?} for {:?}", trait_.as_ref().map(|t| t.def_id()), for_.def_id());
+    trace!(
+        "build_impl: impl {:?} for {:?}",
+        trait_.as_ref().map(|t| t.def_id()),
+        for_.def_id(&cx.cache)
+    );
     ret.push(clean::Item::from_def_id_and_attrs_and_parts(
         did,
         None,
         clean::ImplItem(clean::Impl {
-            span: clean::types::rustc_span(did, cx.tcx),
             unsafety: hir::Unsafety::Normal,
             generics,
             trait_,
             for_,
             items: trait_items,
-            negative_polarity: polarity.clean(cx),
-            synthetic: false,
-            blanket_impl: None,
+            polarity,
+            kind: ImplKind::Normal,
         }),
         box merged_attrs,
         cx,
index 7a1c561c8e53125dd6ef5f7fc0361b752621cd92..3db0ef17fd81064aa52efd07d4a2ea656a4e3d1d 100644 (file)
@@ -16,7 +16,6 @@
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
 use rustc_middle::middle::resolve_lifetime as rl;
 use rustc_middle::ty::fold::TypeFolder;
@@ -34,7 +33,6 @@
 use std::collections::hash_map::Entry;
 use std::default::Default;
 use std::hash::Hash;
-use std::rc::Rc;
 use std::{mem, vec};
 
 use crate::core::{self, DocContext, ImplTraitParam};
     fn clean(&self, cx: &mut DocContext<'_>) -> T;
 }
 
-impl<T: Clean<U>, U> Clean<Vec<U>> for [T] {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Vec<U> {
-        self.iter().map(|x| x.clean(cx)).collect()
-    }
-}
-
-impl<T: Clean<U>, U, V: Idx> Clean<IndexVec<V, U>> for IndexVec<V, T> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> IndexVec<V, U> {
-        self.iter().map(|x| x.clean(cx)).collect()
-    }
-}
-
-impl<T: Clean<U>, U> Clean<U> for &T {
-    fn clean(&self, cx: &mut DocContext<'_>) -> U {
-        (**self).clean(cx)
-    }
-}
-
-impl<T: Clean<U>, U> Clean<U> for Rc<T> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> U {
-        (**self).clean(cx)
-    }
-}
-
-impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Option<U> {
-        self.as_ref().map(|v| v.clean(cx))
-    }
-}
-
 impl Clean<Item> for doctree::Module<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> Item {
         let mut items: Vec<Item> = vec![];
@@ -216,17 +184,15 @@ fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
 impl Clean<Lifetime> for hir::Lifetime {
     fn clean(&self, cx: &mut DocContext<'_>) -> Lifetime {
         let def = cx.tcx.named_region(self.hir_id);
-        match def {
-            Some(
-                rl::Region::EarlyBound(_, node_id, _)
-                | rl::Region::LateBound(_, _, node_id, _)
-                | rl::Region::Free(_, node_id),
-            ) => {
-                if let Some(lt) = cx.lt_substs.get(&node_id).cloned() {
-                    return lt;
-                }
+        if let Some(
+            rl::Region::EarlyBound(_, node_id, _)
+            | rl::Region::LateBound(_, _, node_id, _)
+            | rl::Region::Free(_, node_id),
+        ) = def
+        {
+            if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() {
+                return lt;
             }
-            _ => {}
         }
         Lifetime(self.name.ident().name)
     }
@@ -289,14 +255,14 @@ fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate {
                     .collect();
                 WherePredicate::BoundPredicate {
                     ty: wbp.bounded_ty.clean(cx),
-                    bounds: wbp.bounds.clean(cx),
+                    bounds: wbp.bounds.iter().map(|x| x.clean(cx)).collect(),
                     bound_params,
                 }
             }
 
             hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
                 lifetime: wrp.lifetime.clean(cx),
-                bounds: wrp.bounds.clean(cx),
+                bounds: wrp.bounds.iter().map(|x| x.clean(cx)).collect(),
             },
 
             hir::WherePredicate::EqPredicate(ref wrp) => {
@@ -385,7 +351,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
         let self_type = self.self_ty().clean(cx);
         Type::QPath {
             name: cx.tcx.associated_item(self.item_def_id).ident.name,
-            self_def_id: self_type.def_id(),
+            self_def_id: self_type.def_id(&cx.cache),
             self_type: box self_type,
             trait_,
         }
@@ -461,8 +427,8 @@ fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef {
                 self.name.ident().name,
                 GenericParamDefKind::Type {
                     did: cx.tcx.hir().local_def_id(self.hir_id).to_def_id(),
-                    bounds: self.bounds.clean(cx),
-                    default: default.clean(cx).map(Box::new),
+                    bounds: self.bounds.iter().map(|x| x.clean(cx)).collect(),
+                    default: default.map(|t| t.clean(cx)).map(Box::new),
                     synthetic,
                 },
             ),
@@ -532,8 +498,10 @@ fn is_elided_lifetime(param: &hir::GenericParam<'_>) -> bool {
         }
         params.extend(impl_trait_params);
 
-        let mut generics =
-            Generics { params, where_predicates: self.where_clause.predicates.clean(cx) };
+        let mut generics = Generics {
+            params,
+            where_predicates: self.where_clause.predicates.iter().map(|x| x.clean(cx)).collect(),
+        };
 
         // Some duplicates are generated for ?Sized bounds between type params and where
         // predicates. The point in here is to move the bounds definitions from type params
@@ -828,7 +796,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Arguments {
                 .iter()
                 .enumerate()
                 .map(|(i, ty)| Argument {
-                    name: name_from_pat(&body.params[i].pat),
+                    name: name_from_pat(body.params[i].pat),
                     type_: ty.clean(cx),
                 })
                 .collect(),
@@ -902,7 +870,7 @@ impl Clean<PolyTrait> for hir::PolyTraitRef<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> PolyTrait {
         PolyTrait {
             trait_: self.trait_ref.clean(cx),
-            generic_params: self.bound_generic_params.clean(cx),
+            generic_params: self.bound_generic_params.iter().map(|x| x.clean(cx)).collect(),
         }
     }
 }
@@ -924,9 +892,9 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
                     }
                     MethodItem(m, None)
                 }
-                hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref names)) => {
+                hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => {
                     let (generics, decl) = enter_impl_trait(cx, |cx| {
-                        (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
+                        (self.generics.clean(cx), (sig.decl, names).clean(cx))
                     });
                     let mut t = Function { header: sig.header, decl, generics };
                     if t.header.constness == hir::Constness::Const
@@ -936,8 +904,10 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
                     }
                     TyMethodItem(t)
                 }
-                hir::TraitItemKind::Type(ref bounds, ref default) => {
-                    AssocTypeItem(bounds.clean(cx), default.clean(cx))
+                hir::TraitItemKind::Type(bounds, ref default) => {
+                    let bounds = bounds.iter().map(|x| x.clean(cx)).collect();
+                    let default = default.map(|t| t.clean(cx));
+                    AssocTypeItem(bounds, default)
                 }
             };
             let what_rustc_thinks =
@@ -1129,7 +1099,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
                         None
                     };
 
-                    AssocTypeItem(bounds, ty.clean(cx))
+                    AssocTypeItem(bounds, ty.map(|t| t.clean(cx)))
                 } else {
                     // FIXME: when could this happen? Associated items in inherent impls?
                     let type_ = tcx.type_of(self.def_id).clean(cx);
@@ -1150,7 +1120,6 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
 }
 
 fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
-    use rustc_hir::GenericParamCount;
     let hir::Ty { hir_id: _, span, ref kind } = *hir_ty;
     let qpath = match kind {
         hir::TyKind::Path(qpath) => qpath,
@@ -1160,7 +1129,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
     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.get(&did).cloned() {
+                if let Some(new_ty) = cx.substs.get(&did).and_then(|p| p.as_ty()).cloned() {
                     return new_ty;
                 }
                 if let Some(bounds) = cx.impl_trait_bounds.remove(&did.into()) {
@@ -1168,99 +1137,14 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
                 }
             }
 
-            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.cache.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.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, |cx| ty.clean(cx));
+            if let Some(expanded) = maybe_expand_private_type_alias(cx, path) {
+                expanded
+            } else {
+                let path = path.clean(cx);
+                resolve_type(cx, path)
             }
-            let path = path.clean(cx);
-            resolve_type(cx, path)
         }
-        hir::QPath::Resolved(Some(ref qself), ref p) => {
+        hir::QPath::Resolved(Some(ref qself), 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) {
@@ -1271,7 +1155,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
             let trait_def = cx.tcx.associated_item(p.res.def_id()).container.id();
             let trait_ = self::Path {
                 res: Res::Def(DefKind::Trait, trait_def),
-                segments: trait_segments.clean(cx),
+                segments: trait_segments.iter().map(|x| x.clean(cx)).collect(),
             };
             register_res(cx, trait_.res);
             Type::QPath {
@@ -1281,7 +1165,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
                 trait_,
             }
         }
-        hir::QPath::TypeRelative(ref qself, ref segment) => {
+        hir::QPath::TypeRelative(ref qself, segment) => {
             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
             let res = match ty.kind() {
                 ty::Projection(proj) => Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id),
@@ -1302,6 +1186,94 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
     }
 }
 
+fn maybe_expand_private_type_alias(cx: &mut DocContext<'_>, path: &hir::Path<'_>) -> Option<Type> {
+    let Res::Def(DefKind::TyAlias, def_id) = path.res else { return None };
+    // Substitute private type aliases
+    let Some(def_id) = def_id.as_local() else { return None };
+    let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
+    let alias = if !cx.cache.access_levels.is_exported(def_id.to_def_id()) {
+        &cx.tcx.hir().expect_item(hir_id).kind
+    } else {
+        return None;
+    };
+    let hir::ItemKind::TyAlias(ty, generics) = alias else { return None };
+
+    let provided_params = &path.segments.last().expect("segments were empty");
+    let mut substs = FxHashMap::default();
+    let generic_args = provided_params.args();
+
+    let mut indices: hir::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()
+                    };
+                    substs.insert(lt_def_id.to_def_id(), SubstParam::Lifetime(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_ {
+                    substs.insert(ty_param_def_id.to_def_id(), SubstParam::Type(ty.clean(cx)));
+                } else if let Some(default) = *default {
+                    substs.insert(ty_param_def_id.to_def_id(), SubstParam::Type(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_ {
+                    substs
+                        .insert(const_param_def_id.to_def_id(), SubstParam::Constant(ct.clean(cx)));
+                }
+                // FIXME(const_generics_defaults)
+                indices.consts += 1;
+            }
+        }
+    }
+
+    Some(cx.enter_alias(substs, |cx| ty.clean(cx)))
+}
+
 impl Clean<Type> for hir::Ty<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> Type {
         use rustc_hir::*;
@@ -1337,17 +1309,17 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
                 let length = print_const(cx, ct.eval(cx.tcx, param_env));
                 Array(box ty.clean(cx), length)
             }
-            TyKind::Tup(ref tys) => Tuple(tys.clean(cx)),
+            TyKind::Tup(tys) => Tuple(tys.iter().map(|x| x.clean(cx)).collect()),
             TyKind::OpaqueDef(item_id, _) => {
                 let item = cx.tcx.hir().item(item_id);
                 if let hir::ItemKind::OpaqueTy(ref ty) = item.kind {
-                    ImplTrait(ty.bounds.clean(cx))
+                    ImplTrait(ty.bounds.iter().map(|x| x.clean(cx)).collect())
                 } else {
                     unreachable!()
                 }
             }
-            TyKind::Path(_) => clean_qpath(&self, cx),
-            TyKind::TraitObject(ref bounds, ref lifetime, _) => {
+            TyKind::Path(_) => clean_qpath(self, cx),
+            TyKind::TraitObject(bounds, ref lifetime, _) => {
                 let bounds = bounds.iter().map(|bound| bound.clean(cx)).collect();
                 let lifetime = if !lifetime.is_elided() { Some(lifetime.clean(cx)) } else { None };
                 DynTrait(bounds, lifetime)
@@ -1441,7 +1413,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
                 let path = external_path(cx, did, false, vec![], InternalSubsts::empty());
                 ResolvedPath { path, did }
             }
-            ty::Dynamic(ref obj, ref reg) => {
+            ty::Dynamic(obj, ref reg) => {
                 // HACK: pick the first `did` as the `did` of the trait object. Someone
                 // might want to implement "native" support for marker-trait-only
                 // trait objects.
@@ -1481,9 +1453,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
 
                 DynTrait(bounds, lifetime)
             }
-            ty::Tuple(ref t) => {
-                Tuple(t.iter().map(|t| t.expect_ty()).collect::<Vec<_>>().clean(cx))
-            }
+            ty::Tuple(t) => Tuple(t.iter().map(|t| t.expect_ty().clean(cx)).collect()),
 
             ty::Projection(ref data) => data.clean(cx),
 
@@ -1716,7 +1686,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Variant {
 
 impl Clean<Path> for hir::Path<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> Path {
-        Path { res: self.res, segments: self.segments.clean(cx) }
+        Path { res: self.res, segments: self.segments.iter().map(|x| x.clean(cx)).collect() }
     }
 }
 
@@ -1726,24 +1696,24 @@ fn clean(&self, cx: &mut DocContext<'_>) -> GenericArgs {
             let output = self.bindings[0].ty().clean(cx);
             let output =
                 if output != Type::Tuple(Vec::new()) { Some(Box::new(output)) } else { None };
-            GenericArgs::Parenthesized { inputs: self.inputs().clean(cx), output }
+            let inputs = self.inputs().iter().map(|x| x.clean(cx)).collect();
+            GenericArgs::Parenthesized { inputs, output }
         } else {
-            GenericArgs::AngleBracketed {
-                args: self
-                    .args
-                    .iter()
-                    .map(|arg| match arg {
-                        hir::GenericArg::Lifetime(lt) if !lt.is_elided() => {
-                            GenericArg::Lifetime(lt.clean(cx))
-                        }
-                        hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
-                        hir::GenericArg::Type(ty) => GenericArg::Type(ty.clean(cx)),
-                        hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(ct.clean(cx))),
-                        hir::GenericArg::Infer(_inf) => GenericArg::Infer,
-                    })
-                    .collect(),
-                bindings: self.bindings.clean(cx),
-            }
+            let args = self
+                .args
+                .iter()
+                .map(|arg| match arg {
+                    hir::GenericArg::Lifetime(lt) if !lt.is_elided() => {
+                        GenericArg::Lifetime(lt.clean(cx))
+                    }
+                    hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
+                    hir::GenericArg::Type(ty) => GenericArg::Type(ty.clean(cx)),
+                    hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(ct.clean(cx))),
+                    hir::GenericArg::Infer(_inf) => GenericArg::Infer,
+                })
+                .collect();
+            let bindings = self.bindings.iter().map(|x| x.clean(cx)).collect();
+            GenericArgs::AngleBracketed { args, bindings }
         }
     }
 }
@@ -1757,7 +1727,9 @@ fn clean(&self, cx: &mut DocContext<'_>) -> PathSegment {
 impl Clean<BareFunctionDecl> for hir::BareFnTy<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> BareFunctionDecl {
         let (generic_params, decl) = enter_impl_trait(cx, |cx| {
-            (self.generic_params.clean(cx), (&*self.decl, self.param_names).clean(cx))
+            let generic_params = self.generic_params.iter().map(|x| x.clean(cx)).collect();
+            let decl = (self.decl, self.param_names).clean(cx);
+            (generic_params, decl)
         });
         BareFunctionDecl { unsafety: self.unsafety, abi: self.abi, decl, generic_params }
     }
@@ -1780,7 +1752,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Vec<Item> {
                     kind: ConstantKind::Local { body: body_id, def_id },
                 }),
                 ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
-                    bounds: ty.bounds.clean(cx),
+                    bounds: ty.bounds.iter().map(|x| x.clean(cx)).collect(),
                     generics: ty.generics.clean(cx),
                 }),
                 ItemKind::TyAlias(hir_ty, ref generics) => {
@@ -1802,17 +1774,17 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Vec<Item> {
                 }),
                 ItemKind::TraitAlias(ref generics, bounds) => TraitAliasItem(TraitAlias {
                     generics: generics.clean(cx),
-                    bounds: bounds.clean(cx),
+                    bounds: bounds.iter().map(|x| x.clean(cx)).collect(),
                 }),
                 ItemKind::Union(ref variant_data, ref generics) => UnionItem(Union {
                     generics: generics.clean(cx),
-                    fields: variant_data.fields().clean(cx),
+                    fields: variant_data.fields().iter().map(|x| x.clean(cx)).collect(),
                     fields_stripped: false,
                 }),
                 ItemKind::Struct(ref variant_data, ref generics) => StructItem(Struct {
                     struct_type: CtorKind::from_hir(variant_data),
                     generics: generics.clean(cx),
-                    fields: variant_data.fields().clean(cx),
+                    fields: variant_data.fields().iter().map(|x| x.clean(cx)).collect(),
                     fields_stripped: false,
                 }),
                 ItemKind::Impl(ref impl_) => return clean_impl(impl_, item.hir_id(), cx),
@@ -1821,9 +1793,9 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Vec<Item> {
                     clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
                 }
                 ItemKind::Macro(ref macro_def) => MacroItem(Macro {
-                    source: display_macro_source(cx, name, &macro_def, def_id, &item.vis),
+                    source: display_macro_source(cx, name, macro_def, def_id, item.vis),
                 }),
-                ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => {
+                ItemKind::Trait(is_auto, unsafety, ref generics, bounds, item_ids) => {
                     let items = item_ids
                         .iter()
                         .map(|ti| cx.tcx.hir().trait_item(ti.id).clean(cx))
@@ -1832,7 +1804,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Vec<Item> {
                         unsafety,
                         items,
                         generics: generics.clean(cx),
-                        bounds: bounds.clean(cx),
+                        bounds: bounds.iter().map(|x| x.clean(cx)).collect(),
                         is_auto: is_auto.clean(cx),
                     })
                 }
@@ -1860,22 +1832,10 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
     }
 }
 
-impl Clean<bool> for ty::ImplPolarity {
-    /// Returns whether the impl has negative polarity.
-    fn clean(&self, _: &mut DocContext<'_>) -> bool {
-        match self {
-            &ty::ImplPolarity::Positive |
-            // FIXME: do we want to do something else here?
-            &ty::ImplPolarity::Reservation => false,
-            &ty::ImplPolarity::Negative => true,
-        }
-    }
-}
-
 fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_>) -> Vec<Item> {
     let tcx = cx.tcx;
     let mut ret = Vec::new();
-    let trait_ = impl_.of_trait.clean(cx);
+    let trait_ = impl_.of_trait.as_ref().map(|t| t.clean(cx));
     let items =
         impl_.items.iter().map(|ii| tcx.hir().impl_item(ii.id).clean(cx)).collect::<Vec<_>>();
     let def_id = tcx.hir().local_def_id(hir_id);
@@ -1887,21 +1847,19 @@ fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_>
     }
 
     let for_ = impl_.self_ty.clean(cx);
-    let type_alias = for_.def_id().and_then(|did| match tcx.def_kind(did) {
+    let type_alias = for_.def_id(&cx.cache).and_then(|did| match tcx.def_kind(did) {
         DefKind::TyAlias => Some(tcx.type_of(did).clean(cx)),
         _ => None,
     });
     let mut make_item = |trait_: Option<Path>, for_: Type, items: Vec<Item>| {
         let kind = ImplItem(Impl {
-            span: types::rustc_span(tcx.hir().local_def_id(hir_id).to_def_id(), tcx),
             unsafety: impl_.unsafety,
             generics: impl_.generics.clean(cx),
             trait_,
             for_,
             items,
-            negative_polarity: tcx.impl_polarity(def_id).clean(cx),
-            synthetic: false,
-            blanket_impl: None,
+            polarity: tcx.impl_polarity(def_id),
+            kind: ImplKind::Normal,
         });
         Item::from_hir_id_and_parts(hir_id, None, kind, cx)
     };
@@ -2065,11 +2023,10 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
         let def_id = item.def_id.to_def_id();
         cx.with_param_env(def_id, |cx| {
             let kind = match item.kind {
-                hir::ForeignItemKind::Fn(ref decl, ref names, ref generics) => {
+                hir::ForeignItemKind::Fn(decl, names, ref generics) => {
                     let abi = cx.tcx.hir().get_foreign_abi(item.hir_id());
-                    let (generics, decl) = enter_impl_trait(cx, |cx| {
-                        (generics.clean(cx), (&**decl, &names[..]).clean(cx))
-                    });
+                    let (generics, decl) =
+                        enter_impl_trait(cx, |cx| (generics.clean(cx), (decl, names).clean(cx)));
                     ForeignFunctionItem(Function {
                         decl,
                         generics,
@@ -2113,7 +2070,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> TypeBindingKind {
             hir::TypeBindingKind::Equality { ref ty } => {
                 TypeBindingKind::Equality { ty: ty.clean(cx) }
             }
-            hir::TypeBindingKind::Constraint { ref bounds } => {
+            hir::TypeBindingKind::Constraint { bounds } => {
                 TypeBindingKind::Constraint { bounds: bounds.iter().map(|b| b.clean(cx)).collect() }
             }
         }
index d25e166629fa261ef78b59c26f4c178f442c5991..fd4d620c9591e12ab03359b7e5fe6c0177abd807 100644 (file)
@@ -113,10 +113,9 @@ fn from(id: DefId) -> Self {
     }
 }
 
+/// The crate currently being documented.
 #[derive(Clone, Debug)]
 crate struct Crate {
-    crate name: Symbol,
-    crate src: FileName,
     crate module: Item,
     crate externs: Vec<ExternalCrate>,
     crate primitives: ThinVec<(DefId, PrimitiveType)>,
@@ -125,6 +124,20 @@ fn from(id: DefId) -> Self {
     crate collapsed: bool,
 }
 
+// `Crate` is frequently moved by-value. Make sure it doesn't unintentionally get bigger.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+rustc_data_structures::static_assert_size!(Crate, 104);
+
+impl Crate {
+    crate fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
+        ExternalCrate::LOCAL.name(tcx)
+    }
+
+    crate fn src(&self, tcx: TyCtxt<'_>) -> FileName {
+        ExternalCrate::LOCAL.src(tcx)
+    }
+}
+
 /// This struct is used to wrap additional information added by rustdoc on a `trait` item.
 #[derive(Clone, Debug)]
 crate struct TraitWithExtraInfo {
@@ -138,6 +151,8 @@ fn from(id: DefId) -> Self {
 }
 
 impl ExternalCrate {
+    const LOCAL: Self = Self { crate_num: LOCAL_CRATE };
+
     #[inline]
     crate fn def_id(&self) -> DefId {
         DefId { krate: self.crate_num, index: CRATE_DEF_INDEX }
@@ -204,7 +219,7 @@ fn to_remote(url: impl ToString) -> ExternalLocation {
             .filter_map(|a| a.value_str())
             .map(to_remote)
             .next()
-            .or(extern_url.map(to_remote)) // NOTE: only matters if `extern_url_takes_precedence` is false
+            .or_else(|| extern_url.map(to_remote)) // NOTE: only matters if `extern_url_takes_precedence` is false
             .unwrap_or(Unknown) // Well, at least we tried.
     }
 
@@ -238,7 +253,7 @@ fn to_remote(url: impl ToString) -> ExternalLocation {
                         hir::ItemKind::Mod(_) => {
                             as_keyword(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
                         }
-                        hir::ItemKind::Use(ref path, hir::UseKind::Single)
+                        hir::ItemKind::Use(path, hir::UseKind::Single)
                             if item.vis.node.is_pub() =>
                         {
                             as_keyword(path.res.expect_non_local())
@@ -304,7 +319,7 @@ fn to_remote(url: impl ToString) -> ExternalLocation {
                         hir::ItemKind::Mod(_) => {
                             as_primitive(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
                         }
-                        hir::ItemKind::Use(ref path, hir::UseKind::Single)
+                        hir::ItemKind::Use(path, hir::UseKind::Single)
                             if item.vis.node.is_pub() =>
                         {
                             as_primitive(path.res.expect_non_local()).map(|(_, prim)| {
@@ -376,12 +391,19 @@ impl Item {
             ItemKind::StrippedItem(k) => k,
             _ => &*self.kind,
         };
-        if let ItemKind::ModuleItem(Module { span, .. }) | ItemKind::ImplItem(Impl { span, .. }) =
-            kind
-        {
-            *span
-        } else {
-            self.def_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(|| Span::dummy())
+        match kind {
+            ItemKind::ModuleItem(Module { span, .. }) => *span,
+            ItemKind::ImplItem(Impl { kind: ImplKind::Auto, .. }) => Span::dummy(),
+            ItemKind::ImplItem(Impl { kind: ImplKind::Blanket(_), .. }) => {
+                if let ItemId::Blanket { impl_id, .. } = self.def_id {
+                    rustc_span(impl_id, tcx)
+                } else {
+                    panic!("blanket impl item has non-blanket ID")
+                }
+            }
+            _ => {
+                self.def_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(Span::dummy)
+            }
         }
     }
 
@@ -562,7 +584,7 @@ pub fn from_def_id_and_attrs_and_parts(
     }
 
     crate fn stability_class(&self, tcx: TyCtxt<'_>) -> Option<String> {
-        self.stability(tcx).as_ref().and_then(|ref s| {
+        self.stability(tcx).as_ref().and_then(|s| {
             let mut classes = Vec::with_capacity(2);
 
             if s.level.is_unstable() {
@@ -774,6 +796,7 @@ fn other_attrs(&self) -> Vec<ast::Attribute> {
     fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>> {
         let sess = tcx.sess;
         let doc_cfg_active = tcx.features().doc_cfg;
+        let doc_auto_cfg_active = tcx.features().doc_auto_cfg;
 
         fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
             let mut iter = it.into_iter();
@@ -784,24 +807,26 @@ fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
             Some(item)
         }
 
-        let mut cfg = if doc_cfg_active {
+        let mut cfg = if doc_cfg_active || doc_auto_cfg_active {
             let mut doc_cfg = self
                 .iter()
                 .filter(|attr| attr.has_name(sym::doc))
                 .flat_map(|attr| attr.meta_item_list().unwrap_or_else(Vec::new))
                 .filter(|attr| attr.has_name(sym::cfg))
                 .peekable();
-            if doc_cfg.peek().is_some() {
+            if doc_cfg.peek().is_some() && doc_cfg_active {
                 doc_cfg
                     .filter_map(|attr| Cfg::parse(attr.meta_item()?).ok())
                     .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
-            } else {
+            } else if doc_auto_cfg_active {
                 self.iter()
                     .filter(|attr| attr.has_name(sym::cfg))
                     .filter_map(|attr| single(attr.meta_item_list()?))
                     .filter_map(|attr| Cfg::parse(attr.meta_item()?).ok())
                     .filter(|cfg| !hidden_cfg.contains(cfg))
                     .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
+            } else {
+                Cfg::True
             }
         } else {
             Cfg::True
@@ -820,9 +845,9 @@ fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
                         // #[doc(cfg(...))]
                         if let Some(cfg_mi) = item
                             .meta_item()
-                            .and_then(|item| rustc_expand::config::parse_cfg(&item, sess))
+                            .and_then(|item| rustc_expand::config::parse_cfg(item, sess))
                         {
-                            match Cfg::parse(&cfg_mi) {
+                            match Cfg::parse(cfg_mi) {
                                 Ok(new_cfg) => cfg &= new_cfg,
                                 Err(e) => sess.span_err(e.span, e.msg),
                             }
@@ -934,7 +959,7 @@ fn from_iter<T>(iter: T) -> Self
         T: IntoIterator<Item = &'a DocFragment>,
     {
         iter.into_iter().fold(String::new(), |mut acc, frag| {
-            add_doc_fragment(&mut acc, &frag);
+            add_doc_fragment(&mut acc, frag);
             acc
         })
     }
@@ -1061,12 +1086,12 @@ fn update_need_backline(doc_strings: &mut Vec<DocFragment>) {
 
         let ori = iter.next()?;
         let mut out = String::new();
-        add_doc_fragment(&mut out, &ori);
-        while let Some(new_frag) = iter.next() {
+        add_doc_fragment(&mut out, ori);
+        for new_frag in iter {
             if new_frag.kind != ori.kind || new_frag.parent_module != ori.parent_module {
                 break;
             }
-            add_doc_fragment(&mut out, &new_frag);
+            add_doc_fragment(&mut out, new_frag);
         }
         if out.is_empty() { None } else { Some(out) }
     }
@@ -1079,7 +1104,7 @@ fn update_need_backline(doc_strings: &mut Vec<DocFragment>) {
 
         for new_frag in self.doc_strings.iter() {
             let out = ret.entry(new_frag.parent_module).or_default();
-            add_doc_fragment(out, &new_frag);
+            add_doc_fragment(out, new_frag);
         }
         ret
     }
@@ -1370,17 +1395,10 @@ impl Argument {
     DefaultReturn,
 }
 
-impl GetDefId for FnRetTy {
-    fn def_id(&self) -> Option<DefId> {
-        match *self {
-            Return(ref ty) => ty.def_id(),
-            DefaultReturn => None,
-        }
-    }
-
-    fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
-        match *self {
-            Return(ref ty) => ty.def_id_full(cache),
+impl FnRetTy {
+    crate fn as_return(&self) -> Option<&Type> {
+        match self {
+            Return(ret) => Some(ret),
             DefaultReturn => None,
         }
     }
@@ -1458,34 +1476,6 @@ fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 rustc_data_structures::static_assert_size!(Type, 72);
 
-crate trait GetDefId {
-    /// Use this method to get the [`DefId`] of a [`clean`] AST node.
-    /// This will return [`None`] when called on a primitive [`clean::Type`].
-    /// Use [`Self::def_id_full`] if you want to include primitives.
-    ///
-    /// [`clean`]: crate::clean
-    /// [`clean::Type`]: crate::clean::Type
-    // FIXME: get rid of this function and always use `def_id_full`
-    fn def_id(&self) -> Option<DefId>;
-
-    /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s.
-    ///
-    /// See [`Self::def_id`] for more.
-    ///
-    /// [clean]: crate::clean
-    fn def_id_full(&self, cache: &Cache) -> Option<DefId>;
-}
-
-impl<T: GetDefId> GetDefId for Option<T> {
-    fn def_id(&self) -> Option<DefId> {
-        self.as_ref().and_then(|d| d.def_id())
-    }
-
-    fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
-        self.as_ref().and_then(|d| d.def_id_full(cache))
-    }
-}
-
 impl Type {
     crate fn primitive_type(&self) -> Option<PrimitiveType> {
         match *self {
@@ -1564,17 +1554,27 @@ fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
             QPath { ref self_type, .. } => return self_type.inner_def_id(cache),
             Generic(_) | Infer | ImplTrait(_) => return None,
         };
-        cache.and_then(|c| Primitive(t).def_id_full(c))
+        cache.and_then(|c| Primitive(t).def_id(c))
     }
-}
 
-impl GetDefId for Type {
-    fn def_id(&self) -> Option<DefId> {
-        self.inner_def_id(None)
+    /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s.
+    ///
+    /// See [`Self::def_id_no_primitives`] for more.
+    ///
+    /// [clean]: crate::clean
+    crate fn def_id(&self, cache: &Cache) -> Option<DefId> {
+        self.inner_def_id(Some(cache))
     }
 
-    fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
-        self.inner_def_id(Some(cache))
+    /// Use this method to get the [`DefId`] of a [`clean`] AST node.
+    /// This will return [`None`] when called on a primitive [`clean::Type`].
+    /// Use [`Self::def_id`] if you want to include primitives.
+    ///
+    /// [`clean`]: crate::clean
+    /// [`clean::Type`]: crate::clean::Type
+    // FIXME: get rid of this function and always use `def_id`
+    crate fn def_id_no_primitives(&self) -> Option<DefId> {
+        self.inner_def_id(None)
     }
 }
 
@@ -2092,16 +2092,6 @@ impl Path {
     crate item_type: Option<Type>,
 }
 
-impl GetDefId for Typedef {
-    fn def_id(&self) -> Option<DefId> {
-        self.type_.def_id()
-    }
-
-    fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
-        self.type_.def_id_full(cache)
-    }
-}
-
 #[derive(Clone, Debug)]
 crate struct OpaqueTy {
     crate bounds: Vec<GenericBound>,
@@ -2182,15 +2172,13 @@ impl Constant {
 
 #[derive(Clone, Debug)]
 crate struct Impl {
-    crate span: Span,
     crate unsafety: hir::Unsafety,
     crate generics: Generics,
     crate trait_: Option<Path>,
     crate for_: Type,
     crate items: Vec<Item>,
-    crate negative_polarity: bool,
-    crate synthetic: bool,
-    crate blanket_impl: Option<Box<Type>>,
+    crate polarity: ty::ImplPolarity,
+    crate kind: ImplKind,
 }
 
 impl Impl {
@@ -2203,6 +2191,30 @@ impl Impl {
     }
 }
 
+#[derive(Clone, Debug)]
+crate enum ImplKind {
+    Normal,
+    Auto,
+    Blanket(Box<Type>),
+}
+
+impl ImplKind {
+    crate fn is_auto(&self) -> bool {
+        matches!(self, ImplKind::Auto)
+    }
+
+    crate fn is_blanket(&self) -> bool {
+        matches!(self, ImplKind::Blanket(_))
+    }
+
+    crate fn as_blanket_ty(&self) -> Option<&Type> {
+        match self {
+            ImplKind::Blanket(ty) => Some(ty),
+            _ => None,
+        }
+    }
+}
+
 #[derive(Clone, Debug)]
 crate struct Import {
     crate kind: ImportKind,
@@ -2267,3 +2279,32 @@ impl TypeBinding {
         }
     }
 }
+
+/// The type, lifetime, or constant that a private type alias's parameter should be
+/// replaced with when expanding a use of that type alias.
+///
+/// For example:
+///
+/// ```
+/// type PrivAlias<T> = Vec<T>;
+///
+/// pub fn public_fn() -> PrivAlias<i32> { vec![] }
+/// ```
+///
+/// `public_fn`'s docs will show it as returning `Vec<i32>`, since `PrivAlias` is private.
+/// [`SubstParam`] is used to record that `T` should be mapped to `i32`.
+crate enum SubstParam {
+    Type(Type),
+    Lifetime(Lifetime),
+    Constant(Constant),
+}
+
+impl SubstParam {
+    crate fn as_ty(&self) -> Option<&Type> {
+        if let Self::Type(ty) = self { Some(ty) } else { None }
+    }
+
+    crate fn as_lt(&self) -> Option<&Lifetime> {
+        if let Self::Lifetime(lt) = self { Some(lt) } else { None }
+    }
+}
index de43daff6f0d7c8416420d53ee86103a2a4f892a..2fa7efcc6509b143e69b5192d06cf4bf8d507669 100644 (file)
     let module = crate::visit_ast::RustdocVisitor::new(cx).visit();
 
     let mut externs = Vec::new();
-    for &cnum in cx.tcx.crates(()).iter() {
+    for &cnum in cx.tcx.crates(()) {
         externs.push(ExternalCrate { crate_num: cnum });
         // Analyze doc-reachability for extern items
         LibEmbargoVisitor::new(cx).visit_lib(cnum);
     }
-    externs.sort_unstable_by_key(|e| e.crate_num);
 
     // Clean the crate, translating the entire librustc_ast AST to one that is
     // understood by rustdoc.
@@ -57,8 +56,6 @@
     }
 
     let local_crate = ExternalCrate { crate_num: LOCAL_CRATE };
-    let src = local_crate.src(cx.tcx);
-    let name = local_crate.name(cx.tcx);
     let primitives = local_crate.primitives(cx.tcx);
     let keywords = local_crate.keywords(cx.tcx);
     {
@@ -80,8 +77,6 @@
     }
 
     Crate {
-        name,
-        src,
         module,
         externs,
         primitives,
@@ -171,8 +166,8 @@ pub(super) fn external_path(
 
 crate fn qpath_to_string(p: &hir::QPath<'_>) -> String {
     let segments = match *p {
-        hir::QPath::Resolved(_, ref path) => &path.segments,
-        hir::QPath::TypeRelative(_, ref segment) => return segment.ident.to_string(),
+        hir::QPath::Resolved(_, path) => &path.segments,
+        hir::QPath::TypeRelative(_, segment) => return segment.ident.to_string(),
         hir::QPath::LangItem(lang_item, ..) => return lang_item.name().to_string(),
     };
 
@@ -217,15 +212,15 @@ pub(super) fn external_path(
         PatKind::Wild | PatKind::Struct(..) => return kw::Underscore,
         PatKind::Binding(_, _, ident, _) => return ident.name,
         PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
-        PatKind::Or(ref pats) => {
+        PatKind::Or(pats) => {
             pats.iter().map(|p| name_from_pat(p).to_string()).collect::<Vec<String>>().join(" | ")
         }
-        PatKind::Tuple(ref elts, _) => format!(
+        PatKind::Tuple(elts, _) => format!(
             "({})",
             elts.iter().map(|p| name_from_pat(p).to_string()).collect::<Vec<String>>().join(", ")
         ),
-        PatKind::Box(ref p) => return name_from_pat(&**p),
-        PatKind::Ref(ref p, _) => return name_from_pat(&**p),
+        PatKind::Box(p) => return name_from_pat(&*p),
+        PatKind::Ref(p, _) => return name_from_pat(&*p),
         PatKind::Lit(..) => {
             warn!(
                 "tried to get argument name from PatKind::Lit, which is silly in function arguments"
@@ -233,7 +228,7 @@ pub(super) fn external_path(
             return Symbol::intern("()");
         }
         PatKind::Range(..) => return kw::Underscore,
-        PatKind::Slice(ref begin, ref mid, ref end) => {
+        PatKind::Slice(begin, ref mid, end) => {
             let begin = begin.iter().map(|p| name_from_pat(p).to_string());
             let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter();
             let end = end.iter().map(|p| name_from_pat(p).to_string());
@@ -435,8 +430,9 @@ fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: &'tcx ty::Const<'tc
         | Res::NonMacroAttr(_)
         | Res::Err => return res.def_id(),
         Res::Def(
-            TyParam | ConstParam | Ctor(..) | ExternCrate | Use | ForeignMod | AnonConst | OpaqueTy
-            | Field | LifetimeParam | GlobalAsm | Impl | Closure | Generator,
+            TyParam | ConstParam | Ctor(..) | ExternCrate | Use | ForeignMod | AnonConst
+            | InlineConst | OpaqueTy | Field | LifetimeParam | GlobalAsm | Impl | Closure
+            | Generator,
             id,
         ) => return id,
     };
@@ -507,7 +503,7 @@ fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: &'tcx ty::Const<'tc
 /// so that the channel is consistent.
 ///
 /// Set by `bootstrap::Builder::doc_rust_lang_org_channel` in order to keep tests passing on beta/stable.
-crate const DOC_RUST_LANG_ORG_CHANNEL: &'static str = env!("DOC_RUST_LANG_ORG_CHANNEL");
+crate const DOC_RUST_LANG_ORG_CHANNEL: &str = env!("DOC_RUST_LANG_ORG_CHANNEL");
 
 /// Render a sequence of macro arms in a format suitable for displaying to the user
 /// as part of an item declaration.
index 7342478c3ec0d257d83193cb19dfc638b6b2339c..493aa56fce6efe061a2b12ba673628625ba88731 100644 (file)
@@ -321,13 +321,13 @@ impl Options {
     /// been printed, returns `Err` with the exit code.
     crate fn from_matches(matches: &getopts::Matches) -> Result<Options, i32> {
         // Check for unstable options.
-        nightly_options::check_nightly_options(&matches, &opts());
+        nightly_options::check_nightly_options(matches, &opts());
 
         if matches.opt_present("h") || matches.opt_present("help") {
             crate::usage("rustdoc");
             return Err(0);
         } else if matches.opt_present("version") {
-            rustc_driver::version("rustdoc", &matches);
+            rustc_driver::version("rustdoc", matches);
             return Err(0);
         }
 
@@ -363,10 +363,10 @@ fn println_condition(condition: Condition) {
             return Err(0);
         }
 
-        let color = config::parse_color(&matches);
+        let color = config::parse_color(matches);
         let config::JsonConfig { json_rendered, json_unused_externs, .. } =
-            config::parse_json(&matches);
-        let error_format = config::parse_error_format(&matches, color, json_rendered);
+            config::parse_json(matches);
+        let error_format = config::parse_error_format(matches, color, json_rendered);
 
         let codegen_options = CodegenOptions::build(matches, error_format);
         let debugging_opts = DebuggingOptions::build(matches, error_format);
@@ -374,7 +374,7 @@ fn println_condition(condition: Condition) {
         let diag = new_handler(error_format, None, &debugging_opts);
 
         // check for deprecated options
-        check_deprecated_options(&matches, &diag);
+        check_deprecated_options(matches, &diag);
 
         let mut emit = Vec::new();
         for list in matches.opt_strs("emit") {
@@ -440,8 +440,8 @@ fn println_condition(condition: Condition) {
             .iter()
             .map(|s| SearchPath::from_cli_opt(s, error_format))
             .collect();
-        let externs = parse_externs(&matches, &debugging_opts, error_format);
-        let extern_html_root_urls = match parse_extern_html_roots(&matches) {
+        let externs = parse_externs(matches, &debugging_opts, error_format);
+        let extern_html_root_urls = match parse_extern_html_roots(matches) {
             Ok(ex) => ex,
             Err(err) => {
                 diag.struct_err(err).emit();
@@ -560,7 +560,7 @@ fn println_condition(condition: Condition) {
             }
         }
 
-        let edition = config::parse_crate_edition(&matches);
+        let edition = config::parse_crate_edition(matches);
 
         let mut id_map = html::markdown::IdMap::new();
         let external_html = match ExternalHtml::load(
@@ -569,7 +569,7 @@ fn println_condition(condition: Condition) {
             &matches.opt_strs("html-after-content"),
             &matches.opt_strs("markdown-before-content"),
             &matches.opt_strs("markdown-after-content"),
-            nightly_options::match_is_nightly_build(&matches),
+            nightly_options::match_is_nightly_build(matches),
             &diag,
             &mut id_map,
             edition,
index 074744b3d11e2443cb4f9cf4a2b5a7ce99e8a251..92278179a51c96ade994997c336d3e34a811179f 100644 (file)
     /// Used while populating `external_traits` to ensure we don't process the same trait twice at
     /// the same time.
     crate active_extern_traits: FxHashSet<DefId>,
-    // The current set of type and lifetime substitutions,
+    // The current set of parameter substitutions,
     // for expanding type aliases at the HIR level:
-    /// Table `DefId` of type parameter -> substituted type
-    crate ty_substs: FxHashMap<DefId, clean::Type>,
-    /// Table `DefId` of lifetime parameter -> substituted lifetime
-    crate lt_substs: FxHashMap<DefId, clean::Lifetime>,
-    /// Table `DefId` of const parameter -> substituted const
-    crate ct_substs: FxHashMap<DefId, clean::Constant>,
+    /// Table `DefId` of type, lifetime, or const parameter -> substituted type, lifetime, or const
+    crate substs: FxHashMap<DefId, clean::SubstParam>,
     /// Table synthetic type parameter for `impl Trait` in argument position -> bounds
     crate impl_trait_bounds: FxHashMap<ImplTraitParam, Vec<clean::GenericBound>>,
     /// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`.
@@ -85,7 +81,7 @@
 
 impl<'tcx> DocContext<'tcx> {
     crate fn sess(&self) -> &'tcx Session {
-        &self.tcx.sess
+        self.tcx.sess
     }
 
     crate fn with_param_env<T, F: FnOnce(&mut Self) -> T>(&mut self, def_id: DefId, f: F) -> T {
@@ -104,25 +100,13 @@ impl<'tcx> DocContext<'tcx> {
 
     /// Call the closure with the given parameters set as
     /// the substitutions for a type alias' RHS.
-    crate fn enter_alias<F, R>(
-        &mut self,
-        ty_substs: FxHashMap<DefId, clean::Type>,
-        lt_substs: FxHashMap<DefId, clean::Lifetime>,
-        ct_substs: FxHashMap<DefId, clean::Constant>,
-        f: F,
-    ) -> R
+    crate fn enter_alias<F, R>(&mut self, substs: FxHashMap<DefId, clean::SubstParam>, f: F) -> R
     where
         F: FnOnce(&mut Self) -> R,
     {
-        let (old_tys, old_lts, old_cts) = (
-            mem::replace(&mut self.ty_substs, ty_substs),
-            mem::replace(&mut self.lt_substs, lt_substs),
-            mem::replace(&mut self.ct_substs, ct_substs),
-        );
+        let old_substs = mem::replace(&mut self.substs, substs);
         let r = f(self);
-        self.ty_substs = old_tys;
-        self.lt_substs = old_lts;
-        self.ct_substs = old_cts;
+        self.substs = old_substs;
         r
     }
 
@@ -281,9 +265,9 @@ impl<'tcx> DocContext<'tcx> {
                 // Closures' tables come from their outermost function,
                 // as they are part of the same "inference environment".
                 // This avoids emitting errors for the parent twice (see similar code in `typeck_with_fallback`)
-                let outer_def_id = tcx.closure_base_def_id(def_id.to_def_id()).expect_local();
-                if outer_def_id != def_id {
-                    return tcx.typeck(outer_def_id);
+                let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()).expect_local();
+                if typeck_root_def_id != def_id {
+                    return tcx.typeck(typeck_root_def_id);
                 }
 
                 let hir = tcx.hir();
@@ -350,9 +334,7 @@ impl<'tcx> DocContext<'tcx> {
         param_env: ParamEnv::empty(),
         external_traits: Default::default(),
         active_extern_traits: Default::default(),
-        ty_substs: Default::default(),
-        lt_substs: Default::default(),
-        ct_substs: Default::default(),
+        substs: Default::default(),
         impl_trait_bounds: Default::default(),
         generated_synthetics: Default::default(),
         auto_traits: tcx
@@ -464,7 +446,7 @@ fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler, sp: Span) {
                 _ => continue,
             };
             for name in value.as_str().split_whitespace() {
-                let span = attr.name_value_literal_span().unwrap_or(attr.span());
+                let span = attr.name_value_literal_span().unwrap_or_else(|| attr.span());
                 manual_passes.extend(parse_pass(name, Some(span)));
             }
         }
@@ -486,11 +468,13 @@ fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler, sp: Span) {
         };
         if run {
             debug!("running pass {}", p.pass.name);
-            krate = ctxt.tcx.sess.time(p.pass.name, || (p.pass.run)(krate, &mut ctxt));
+            krate = tcx.sess.time(p.pass.name, || (p.pass.run)(krate, &mut ctxt));
         }
     }
 
-    ctxt.sess().abort_if_errors();
+    if tcx.sess.diagnostic().has_errors_or_lint_errors() {
+        rustc_errors::FatalError.raise();
+    }
 
     let render_options = ctxt.render_options;
     let mut cache = ctxt.cache;
index a5fab1b3d42170c7f7ccdd527dae9dca37820cf6..d59273db08b4f9f50fe7155816a55340893f3ed2 100644 (file)
 use std::string::ToString;
 use std::sync::mpsc::Sender;
 
-macro_rules! try_err {
-    ($e:expr, $file:expr) => {
-        match $e {
-            Ok(e) => e,
-            Err(e) => return Err(E::new(e, $file)),
-        }
-    };
-}
-
 crate trait PathError {
     fn new<S, P: AsRef<Path>>(e: S, path: P) -> Self
     where
@@ -75,7 +66,7 @@ impl DocFS {
                 });
             });
         } else {
-            try_err!(fs::write(&path, contents), path);
+            fs::write(&path, contents).map_err(|e| E::new(e, path))?;
         }
         Ok(())
     }
index 9e64d200b437339abf5d20ba337c43f0e63bea69..c10eebf49fc8d657af5b333fcccf83af486d678d 100644 (file)
@@ -1,7 +1,7 @@
 use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
-use rustc_errors::{ColorConfig, ErrorReported};
+use rustc_errors::{ColorConfig, ErrorReported, FatalError};
 use rustc_hir as hir;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::intravisit;
@@ -73,7 +73,7 @@
         search_paths: options.libs.clone(),
         crate_types,
         lint_opts: if !options.display_doctest_warnings { lint_opts } else { vec![] },
-        lint_cap: Some(options.lint_cap.unwrap_or_else(|| lint::Forbid)),
+        lint_cap: Some(options.lint_cap.unwrap_or(lint::Forbid)),
         cg: options.codegen_options.clone(),
         externs: options.externs.clone(),
         unstable_features: options.render_options.unstable_features,
 
                 collector
             });
-            compiler.session().abort_if_errors();
+            if compiler.session().diagnostic().has_errors_or_lint_errors() {
+                FatalError.raise();
+            }
 
             let unused_extern_reports = collector.unused_extern_reports.clone();
             let compiling_test_count = collector.compiling_test_count.load(Ordering::SeqCst);
                 .iter()
                 .map(|uexts| uexts.unused_extern_names.iter().collect::<FxHashSet<&String>>())
                 .fold(extern_names, |uextsa, uextsb| {
-                    uextsa.intersection(&uextsb).map(|v| *v).collect::<FxHashSet<&String>>()
+                    uextsa.intersection(&uextsb).copied().collect::<FxHashSet<&String>>()
                 })
                 .iter()
                 .map(|v| (*v).clone())
@@ -423,7 +425,7 @@ fn drop(&mut self) {
 
     // Add a \n to the end to properly terminate the last line,
     // but only if there was output to be printed
-    if out_lines.len() > 0 {
+    if !out_lines.is_empty() {
         out_lines.push("");
     }
 
@@ -1124,7 +1126,7 @@ fn visit_testable<F: FnOnce(&mut Self)>(
         let mut attrs = Attributes::from_ast(ast_attrs, None);
 
         if let Some(ref cfg) = ast_attrs.cfg(self.tcx, &FxHashSet::default()) {
-            if !cfg.matches(&self.sess.parse_sess, Some(&self.sess.features_untracked())) {
+            if !cfg.matches(&self.sess.parse_sess, Some(self.sess.features_untracked())) {
                 return;
             }
         }
index f84850c0fe1f1c1531ccd4b59d06698fa516cebb..cd0f44e5696fec3e2038dcb5d5a76f24b8fbfbb5 100644 (file)
@@ -20,22 +20,28 @@ fn fold_inner_recur(&mut self, kind: ItemKind) -> ItemKind {
             StructItem(mut i) => {
                 let num_fields = i.fields.len();
                 i.fields = i.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
-                i.fields_stripped |=
-                    num_fields != i.fields.len() || i.fields.iter().any(|f| f.is_stripped());
+                if !i.fields_stripped {
+                    i.fields_stripped =
+                        num_fields != i.fields.len() || i.fields.iter().any(|f| f.is_stripped());
+                }
                 StructItem(i)
             }
             UnionItem(mut i) => {
                 let num_fields = i.fields.len();
                 i.fields = i.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
-                i.fields_stripped |=
-                    num_fields != i.fields.len() || i.fields.iter().any(|f| f.is_stripped());
+                if !i.fields_stripped {
+                    i.fields_stripped =
+                        num_fields != i.fields.len() || i.fields.iter().any(|f| f.is_stripped());
+                }
                 UnionItem(i)
             }
             EnumItem(mut i) => {
                 let num_variants = i.variants.len();
                 i.variants = i.variants.into_iter().filter_map(|x| self.fold_item(x)).collect();
-                i.variants_stripped |=
-                    num_variants != i.variants.len() || i.variants.iter().any(|f| f.is_stripped());
+                if !i.variants_stripped {
+                    i.variants_stripped = num_variants != i.variants.len()
+                        || i.variants.iter().any(|f| f.is_stripped());
+                }
                 EnumItem(i)
             }
             TraitItem(mut i) => {
@@ -46,24 +52,42 @@ fn fold_inner_recur(&mut self, kind: ItemKind) -> ItemKind {
                 i.items = i.items.into_iter().filter_map(|x| self.fold_item(x)).collect();
                 ImplItem(i)
             }
-            VariantItem(i) => {
-                let i2 = i.clone(); // this clone is small
-                match i {
-                    Variant::Struct(mut j) => {
-                        let num_fields = j.fields.len();
-                        j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
-                        j.fields_stripped |= num_fields != j.fields.len()
+            VariantItem(i) => match i {
+                Variant::Struct(mut j) => {
+                    let num_fields = j.fields.len();
+                    j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
+                    if !j.fields_stripped {
+                        j.fields_stripped = num_fields != j.fields.len()
                             || j.fields.iter().any(|f| f.is_stripped());
-                        VariantItem(Variant::Struct(j))
-                    }
-                    Variant::Tuple(fields) => {
-                        let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
-                        VariantItem(Variant::Tuple(fields))
                     }
-                    _ => VariantItem(i2),
+                    VariantItem(Variant::Struct(j))
                 }
-            }
-            x => x,
+                Variant::Tuple(fields) => {
+                    let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
+                    VariantItem(Variant::Tuple(fields))
+                }
+                Variant::CLike => VariantItem(Variant::CLike),
+            },
+            ExternCrateItem { src: _ }
+            | ImportItem(_)
+            | FunctionItem(_)
+            | TypedefItem(_, _)
+            | OpaqueTyItem(_)
+            | StaticItem(_)
+            | ConstantItem(_)
+            | TraitAliasItem(_)
+            | TyMethodItem(_)
+            | MethodItem(_, _)
+            | StructFieldItem(_)
+            | ForeignFunctionItem(_)
+            | ForeignStaticItem(_)
+            | ForeignTypeItem
+            | MacroItem(_)
+            | ProcMacroItem(_)
+            | PrimitiveItem(_)
+            | AssocConstItem(_, _)
+            | AssocTypeItem(_, _)
+            | KeywordItem(_) => kind,
         }
     }
 
@@ -86,14 +110,12 @@ fn fold_mod(&mut self, m: Module) -> Module {
     fn fold_crate(&mut self, mut c: Crate) -> Crate {
         c.module = self.fold_item(c.module).unwrap();
 
-        {
-            let external_traits = { std::mem::take(&mut *c.external_traits.borrow_mut()) };
-            for (k, mut v) in external_traits {
-                v.trait_.items =
-                    v.trait_.items.into_iter().filter_map(|i| self.fold_item(i)).collect();
-                c.external_traits.borrow_mut().insert(k, v);
-            }
+        let external_traits = { std::mem::take(&mut *c.external_traits.borrow_mut()) };
+        for (k, mut v) in external_traits {
+            v.trait_.items = v.trait_.items.into_iter().filter_map(|i| self.fold_item(i)).collect();
+            c.external_traits.borrow_mut().insert(k, v);
         }
+
         c
     }
 }
index 8b883ffaaf095cb4419f12f96bab71f6807b4002..a929cd094f8c3bcb6417d1f35c937786540c4888 100644 (file)
@@ -6,7 +6,7 @@
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::sym;
 
-use crate::clean::{self, GetDefId, ItemId, PrimitiveType};
+use crate::clean::{self, ItemId, PrimitiveType};
 use crate::config::RenderOptions;
 use crate::fold::DocFolder;
 use crate::formats::item_type::ItemType;
@@ -206,7 +206,9 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                 || i.trait_
                     .as_ref()
                     .map_or(false, |t| self.cache.masked_crates.contains(&t.def_id().krate))
-                || i.for_.def_id().map_or(false, |d| self.cache.masked_crates.contains(&d.krate))
+                || i.for_
+                    .def_id(self.cache)
+                    .map_or(false, |d| self.cache.masked_crates.contains(&d.krate))
             {
                 return None;
             }
@@ -226,7 +228,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
         // Collect all the implementors of traits.
         if let clean::ImplItem(ref i) = *item.kind {
             if let Some(trait_) = &i.trait_ {
-                if i.blanket_impl.is_none() {
+                if !i.kind.is_blanket() {
                     self.cache
                         .implementors
                         .entry(trait_.def_id())
@@ -292,7 +294,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                     // inserted later on when serializing the search-index.
                     if item.def_id.index().map_or(false, |idx| idx != CRATE_DEF_INDEX) {
                         let desc = item.doc_value().map_or_else(String::new, |x| {
-                            short_markdown_summary(&x.as_str(), &item.link_names(&self.cache))
+                            short_markdown_summary(x.as_str(), &item.link_names(self.cache))
                         });
                         self.cache.search_index.push(IndexItem {
                             ty: item.type_(),
@@ -454,7 +456,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
 
             if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) {
                 for bound in generics {
-                    if let Some(did) = bound.def_id() {
+                    if let Some(did) = bound.def_id(self.cache) {
                         dids.insert(did);
                     }
                 }
@@ -462,7 +464,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
             let impl_item = Impl { impl_item: item };
             if impl_item.trait_did().map_or(true, |d| self.cache.traits.contains_key(&d)) {
                 for did in dids {
-                    self.cache.impls.entry(did).or_insert(vec![]).push(impl_item.clone());
+                    self.cache.impls.entry(did).or_insert_with(Vec::new).push(impl_item.clone());
                 }
             } else {
                 let trait_did = impl_item.trait_did().expect("no trait did");
index 955de57dc0e5f3ea9a3b231869ef33bb7fbb3706..3979d29b673fd3bd37a8fc6865b6b0ee3e46bcb0 100644 (file)
@@ -48,6 +48,7 @@
     ProcAttribute = 23,
     ProcDerive = 24,
     TraitAlias = 25,
+    Generic = 26,
 }
 
 impl Serialize for ItemType {
@@ -133,6 +134,7 @@ fn from(other: DefKind) -> Self {
             | DefKind::Use
             | DefKind::ForeignMod
             | DefKind::AnonConst
+            | DefKind::InlineConst
             | DefKind::OpaqueTy
             | DefKind::Field
             | DefKind::LifetimeParam
@@ -173,6 +175,7 @@ impl ItemType {
             ItemType::ProcAttribute => "attr",
             ItemType::ProcDerive => "derive",
             ItemType::TraitAlias => "traitalias",
+            ItemType::Generic => "generic",
         }
     }
 }
index f2751947c7eb95a6db9b8d8154e11e7e17228f84..4f2049132046d8a534a9c8e9069a15d836d5be84 100644 (file)
@@ -14,6 +14,7 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_middle::ty;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::CRATE_DEF_INDEX;
 use rustc_target::spec::abi::Abi;
@@ -597,7 +598,7 @@ fn to_module_fqp(shortty: ItemType, fqp: &[String]) -> &[String] {
 
 /// Used when rendering a `ResolvedPath` structure. This invokes the `path`
 /// rendering function with the necessary arguments for linking to a local path.
-fn resolved_path<'a, 'cx: 'a>(
+fn resolved_path<'cx>(
     w: &mut fmt::Formatter<'_>,
     did: DefId,
     path: &clean::Path,
@@ -696,7 +697,7 @@ fn primitive_link(
 
 /// Helper to render type parameters
 fn tybounds<'a, 'tcx: 'a>(
-    bounds: &'a Vec<clean::PolyTrait>,
+    bounds: &'a [clean::PolyTrait],
     lt: &'a Option<clean::Lifetime>,
     cx: &'a Context<'tcx>,
 ) -> impl fmt::Display + 'a + Captures<'tcx> {
@@ -886,7 +887,7 @@ fn fmt_type<'cx>(
                     if bounds.len() > 1 || trait_lt.is_some() =>
                 {
                     write!(f, "{}{}{}(", amp, lt, m)?;
-                    fmt_type(&ty, f, use_absolute, cx)?;
+                    fmt_type(ty, f, use_absolute, cx)?;
                     write!(f, ")")
                 }
                 clean::Generic(..) => {
@@ -896,11 +897,11 @@ fn fmt_type<'cx>(
                         &format!("{}{}{}", amp, lt, m),
                         cx,
                     )?;
-                    fmt_type(&ty, f, use_absolute, cx)
+                    fmt_type(ty, f, use_absolute, cx)
                 }
                 _ => {
                     write!(f, "{}{}{}", amp, lt, m)?;
-                    fmt_type(&ty, f, use_absolute, cx)
+                    fmt_type(ty, f, use_absolute, cx)
                 }
             }
         }
@@ -990,14 +991,15 @@ impl clean::Impl {
             }
 
             if let Some(ref ty) = self.trait_ {
-                if self.negative_polarity {
-                    write!(f, "!")?;
+                match self.polarity {
+                    ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => {}
+                    ty::ImplPolarity::Negative => write!(f, "!")?,
                 }
                 fmt::Display::fmt(&ty.print(cx), f)?;
                 write!(f, " for ")?;
             }
 
-            if let Some(ref ty) = self.blanket_impl {
+            if let Some(ref ty) = self.kind.as_blanket_ty() {
                 fmt_type(ty, f, use_absolute, cx)?;
             } else {
                 fmt_type(&self.for_, f, use_absolute, cx)?;
index fa8ad2a37e726d3419f6635d151fcc3b0965f5cf..e177a11303643d645ef0a9aac29cfaff9bc54047 100644 (file)
@@ -62,7 +62,7 @@
     }
 
     write_header(out, class, extra_content);
-    write_code(out, &src, edition, context_info, decoration_info);
+    write_code(out, src, edition, context_info, decoration_info);
     write_footer(out, playground_button);
 }
 
@@ -270,12 +270,18 @@ struct Decorations {
 
 impl Decorations {
     fn new(info: DecorationInfo) -> Self {
-        let (starts, ends) = info
+        // Extract tuples (start, end, kind) into separate sequences of (start, kind) and (end).
+        let (mut starts, mut ends): (Vec<_>, Vec<_>) = info
             .0
             .into_iter()
             .map(|(kind, ranges)| ranges.into_iter().map(move |(lo, hi)| ((lo, kind), hi)))
             .flatten()
             .unzip();
+
+        // Sort the sequences in document order.
+        starts.sort_by_key(|(lo, _)| *lo);
+        ends.sort();
+
         Decorations { starts, ends }
     }
 }
@@ -469,22 +475,37 @@ fn advance(
             // Assume that '&' or '*' is the reference or dereference operator
             // or a reference or pointer type. Unless, of course, it looks like
             // a logical and or a multiplication operator: `&&` or `* `.
-            TokenKind::Star => match self.peek() {
-                Some(TokenKind::Whitespace) => Class::Op,
+            TokenKind::Star => match self.tokens.peek() {
+                Some((TokenKind::Whitespace, _)) => Class::Op,
+                Some((TokenKind::Ident, "mut")) => {
+                    self.next();
+                    sink(Highlight::Token { text: "*mut", class: Some(Class::RefKeyWord) });
+                    return;
+                }
+                Some((TokenKind::Ident, "const")) => {
+                    self.next();
+                    sink(Highlight::Token { text: "*const", class: Some(Class::RefKeyWord) });
+                    return;
+                }
                 _ => Class::RefKeyWord,
             },
-            TokenKind::And => match lookahead {
-                Some(TokenKind::And) => {
+            TokenKind::And => match self.tokens.peek() {
+                Some((TokenKind::And, _)) => {
                     self.next();
                     sink(Highlight::Token { text: "&&", class: Some(Class::Op) });
                     return;
                 }
-                Some(TokenKind::Eq) => {
+                Some((TokenKind::Eq, _)) => {
                     self.next();
                     sink(Highlight::Token { text: "&=", class: Some(Class::Op) });
                     return;
                 }
-                Some(TokenKind::Whitespace) => Class::Op,
+                Some((TokenKind::Whitespace, _)) => Class::Op,
+                Some((TokenKind::Ident, "mut")) => {
+                    self.next();
+                    sink(Highlight::Token { text: "&mut", class: Some(Class::RefKeyWord) });
+                    return;
+                }
                 _ => Class::RefKeyWord,
             },
 
@@ -718,7 +739,7 @@ fn string<T: Display>(
                             .map(|(url, _, _)| url)
                     }
                     LinkFromSrc::Primitive(prim) => format::href_with_root_path(
-                        PrimitiveType::primitive_locations(context.tcx())[&prim],
+                        PrimitiveType::primitive_locations(context.tcx())[prim],
                         context,
                         Some(context_info.root_path),
                     )
index 22e650af7e22b1a977928c540adadda782a27c92..b117a12e39f4a45bf1e0938ce9f4eb51e1d13e1c 100644 (file)
 <span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">target_os</span> <span class="op">=</span> <span class="string">&quot;linux&quot;</span>)]</span>
 <span class="kw">fn</span> <span class="ident">main</span>() -&gt; () {
     <span class="kw">let</span> <span class="ident">foo</span> <span class="op">=</span> <span class="bool-val">true</span> <span class="op">&amp;&amp;</span> <span class="bool-val">false</span> <span class="op">|</span><span class="op">|</span> <span class="bool-val">true</span>;
-    <span class="kw">let</span> <span class="kw">_</span>: <span class="kw-2">*</span><span class="kw">const</span> () <span class="op">=</span> <span class="number">0</span>;
+    <span class="kw">let</span> <span class="kw">_</span>: <span class="kw-2">*const</span> () <span class="op">=</span> <span class="number">0</span>;
     <span class="kw">let</span> <span class="kw">_</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">foo</span>;
     <span class="kw">let</span> <span class="kw">_</span> <span class="op">=</span> <span class="op">&amp;&amp;</span><span class="ident">foo</span>;
     <span class="kw">let</span> <span class="kw">_</span> <span class="op">=</span> <span class="kw-2">*</span><span class="ident">foo</span>;
-    <span class="macro">mac!</span>(<span class="ident">foo</span>, <span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="ident">bar</span>);
+    <span class="macro">mac!</span>(<span class="ident">foo</span>, <span class="kw-2">&amp;mut</span> <span class="ident">bar</span>);
     <span class="macro">assert!</span>(<span class="self">self</span>.<span class="ident">length</span> <span class="op">&lt;</span> <span class="ident">N</span> <span class="op">&amp;&amp;</span> <span class="ident">index</span> <span class="op">&lt;</span><span class="op">=</span> <span class="self">self</span>.<span class="ident">length</span>);
     <span class="ident">::std::env::var</span>(<span class="string">&quot;gateau&quot;</span>).<span class="ident">is_ok</span>();
     <span class="attribute">#[<span class="ident">rustfmt::skip</span>]</span>
index bd06f88cb3587def54ae87baace749e5549c5330..71d7cc1a09dce5b9656d6e3c9556b5db38fd6776 100644 (file)
@@ -68,10 +68,8 @@ struct PageLayout<'a> {
     let krate_with_trailing_slash = ensure_trailing_slash(&layout.krate).to_string();
     let style_files = style_files
         .iter()
-        .filter_map(|t| {
-            if let Some(stem) = t.path.file_stem() { Some((stem, t.disabled)) } else { None }
-        })
-        .filter_map(|t| if let Some(path) = t.0.to_str() { Some((path, t.1)) } else { None })
+        .filter_map(|t| t.path.file_stem().map(|stem| (stem, t.disabled)))
+        .filter_map(|t| t.0.to_str().map(|path| (path, t.1)))
         .map(|t| {
             format!(
                 r#"<link rel="stylesheet" type="text/css" href="{}.css" {} {}>"#,
index bda0f0aa3f13efb139f577ca25af474cc0581f62..47772651bf9b9e92defd25a9ea1d0b8e32504228 100644 (file)
@@ -178,7 +178,7 @@ fn map_line(s: &str) -> Line<'_> {
         Line::Shown(Cow::Owned(s.replacen("##", "#", 1)))
     } else if let Some(stripped) = trimmed.strip_prefix("# ") {
         // # text
-        Line::Hidden(&stripped)
+        Line::Hidden(stripped)
     } else if trimmed == "#" {
         // We cannot handle '#text' because it could be #[attr].
         Line::Hidden("")
@@ -258,7 +258,7 @@ fn next(&mut self) -> Option<Self::Item> {
         let parse_result = match kind {
             CodeBlockKind::Fenced(ref lang) => {
                 let parse_result =
-                    LangString::parse_without_check(&lang, self.check_error_codes, false);
+                    LangString::parse_without_check(lang, self.check_error_codes, false);
                 if !parse_result.rust {
                     return Some(Event::Html(
                         format!(
@@ -669,7 +669,7 @@ fn next(&mut self) -> Option<Self::Item> {
         loop {
             match self.inner.next() {
                 Some((Event::FootnoteReference(ref reference), range)) => {
-                    let entry = self.get_entry(&reference);
+                    let entry = self.get_entry(reference);
                     let reference = format!(
                         "<sup id=\"fnref{0}\"><a href=\"#fn{0}\">{0}</a></sup>",
                         (*entry).1
@@ -904,7 +904,7 @@ fn tokens(string: &str) -> impl Iterator<Item = &str> {
         string
             .split(|c| c == ',' || c == ' ' || c == '\t')
             .map(str::trim)
-            .map(|token| if token.chars().next() == Some('.') { &token[1..] } else { token })
+            .map(|token| token.strip_prefix('.').unwrap_or(token))
             .filter(|token| !token.is_empty())
     }
 
@@ -974,7 +974,10 @@ fn parse(
                 }
                 x if extra.is_some() => {
                     let s = x.to_lowercase();
-                    match if s == "compile-fail" || s == "compile_fail" || s == "compilefail" {
+                    if let Some((flag, help)) = if s == "compile-fail"
+                        || s == "compile_fail"
+                        || s == "compilefail"
+                    {
                         Some((
                             "compile_fail",
                             "the code block will either not be tested if not marked as a rust one \
@@ -1007,15 +1010,12 @@ fn parse(
                     } else {
                         None
                     } {
-                        Some((flag, help)) => {
-                            if let Some(ref extra) = extra {
-                                extra.error_invalid_codeblock_attr(
-                                    &format!("unknown attribute `{}`. Did you mean `{}`?", x, flag),
-                                    help,
-                                );
-                            }
+                        if let Some(extra) = extra {
+                            extra.error_invalid_codeblock_attr(
+                                &format!("unknown attribute `{}`. Did you mean `{}`?", x, flag),
+                                help,
+                            );
                         }
-                        None => {}
                     }
                     seen_other_tags = true;
                 }
@@ -1051,13 +1051,10 @@ pub fn into_string(self) -> String {
             return String::new();
         }
         let mut replacer = |broken_link: BrokenLink<'_>| {
-            if let Some(link) =
-                links.iter().find(|link| &*link.original_text == broken_link.reference)
-            {
-                Some((link.href.as_str().into(), link.new_text.as_str().into()))
-            } else {
-                None
-            }
+            links
+                .iter()
+                .find(|link| &*link.original_text == broken_link.reference)
+                .map(|link| (link.href.as_str().into(), link.new_text.as_str().into()))
         };
 
         let p = Parser::new_with_broken_link_callback(md, main_body_opts(), Some(&mut replacer));
@@ -1135,13 +1132,10 @@ impl MarkdownSummaryLine<'_> {
         }
 
         let mut replacer = |broken_link: BrokenLink<'_>| {
-            if let Some(link) =
-                links.iter().find(|link| &*link.original_text == broken_link.reference)
-            {
-                Some((link.href.as_str().into(), link.new_text.as_str().into()))
-            } else {
-                None
-            }
+            links
+                .iter()
+                .find(|link| &*link.original_text == broken_link.reference)
+                .map(|link| (link.href.as_str().into(), link.new_text.as_str().into()))
         };
 
         let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer));
@@ -1172,13 +1166,10 @@ fn markdown_summary_with_limit(
     }
 
     let mut replacer = |broken_link: BrokenLink<'_>| {
-        if let Some(link) =
-            link_names.iter().find(|link| &*link.original_text == broken_link.reference)
-        {
-            Some((link.href.as_str().into(), link.new_text.as_str().into()))
-        } else {
-            None
-        }
+        link_names
+            .iter()
+            .find(|link| &*link.original_text == broken_link.reference)
+            .map(|link| (link.href.as_str().into(), link.new_text.as_str().into()))
     };
 
     let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer));
@@ -1413,7 +1404,7 @@ fn markdown_summary_with_limit(
                 CodeBlockKind::Indented => {
                     // The ending of the offset goes too far sometime so we reduce it by one in
                     // these cases.
-                    if offset.end > offset.start && md.get(offset.end..=offset.end) == Some(&"\n") {
+                    if offset.end > offset.start && md.get(offset.end..=offset.end) == Some("\n") {
                         (
                             LangString::default(),
                             offset.start,
index 9c05c80d55dfea35a5b8c820657ec6950d6a1394..ff1bd5e7ff289565c06076f8f7437743e1427ec4 100644 (file)
@@ -1,14 +1,13 @@
+use std::collections::hash_map::Entry;
 use std::collections::BTreeMap;
 
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::Symbol;
 use serde::ser::{Serialize, SerializeStruct, Serializer};
 
 use crate::clean;
-use crate::clean::types::{
-    FnDecl, FnRetTy, GenericBound, Generics, GetDefId, Type, WherePredicate,
-};
+use crate::clean::types::{FnDecl, FnRetTy, GenericBound, Generics, Type, WherePredicate};
 use crate::formats::cache::Cache;
 use crate::formats::item_type::ItemType;
 use crate::html::markdown::short_markdown_summary;
@@ -36,7 +35,7 @@
         if let Some(&(ref fqp, _)) = cache.paths.get(&did) {
             let desc = item
                 .doc_value()
-                .map_or_else(String::new, |s| short_markdown_summary(&s, &item.link_names(&cache)));
+                .map_or_else(String::new, |s| short_markdown_summary(&s, &item.link_names(cache)));
             cache.search_index.push(IndexItem {
                 ty: item.type_(),
                 name: item.name.unwrap().to_string(),
@@ -44,7 +43,7 @@
                 desc,
                 parent: Some(did),
                 parent_idx: None,
-                search_type: get_index_search_type(&item, tcx),
+                search_type: get_index_search_type(item, tcx),
                 aliases: item.attrs.get_doc_aliases(),
             });
         }
@@ -53,7 +52,7 @@
     let crate_doc = krate
         .module
         .doc_value()
-        .map_or_else(String::new, |s| short_markdown_summary(&s, &krate.module.link_names(&cache)));
+        .map_or_else(String::new, |s| short_markdown_summary(&s, &krate.module.link_names(cache)));
 
     let Cache { ref mut search_index, ref paths, .. } = *cache;
 
@@ -72,7 +71,7 @@
     // Set up alias indexes.
     for (i, item) in search_index.iter().enumerate() {
         for alias in &item.aliases[..] {
-            aliases.entry(alias.to_lowercase()).or_insert(Vec::new()).push(i);
+            aliases.entry(alias.to_lowercase()).or_insert_with(Vec::new).push(i);
         }
     }
 
     let mut lastpathid = 0usize;
 
     for item in search_index {
-        item.parent_idx = item.parent.and_then(|defid| {
-            if defid_to_pathid.contains_key(&defid) {
-                defid_to_pathid.get(&defid).copied()
-            } else {
+        item.parent_idx = item.parent.and_then(|defid| match defid_to_pathid.entry(defid) {
+            Entry::Occupied(entry) => Some(*entry.get()),
+            Entry::Vacant(entry) => {
                 let pathid = lastpathid;
-                defid_to_pathid.insert(defid, pathid);
+                entry.insert(pathid);
                 lastpathid += 1;
 
                 if let Some(&(ref fqp, short)) = paths.get(&defid) {
@@ -174,7 +172,7 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
     // Collect the index into a string
     format!(
         r#""{}":{}"#,
-        krate.name,
+        krate.name(tcx),
         serde_json::to_string(&CrateData {
             doc: crate_doc,
             items: crate_items,
@@ -194,32 +192,24 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
     item: &clean::Item,
     tcx: TyCtxt<'tcx>,
 ) -> Option<IndexItemFunctionType> {
-    let (all_types, ret_types) = match *item.kind {
+    let (mut inputs, mut output) = match *item.kind {
         clean::FunctionItem(ref f) => get_all_types(&f.generics, &f.decl, tcx),
         clean::MethodItem(ref m, _) => get_all_types(&m.generics, &m.decl, tcx),
         clean::TyMethodItem(ref m) => get_all_types(&m.generics, &m.decl, tcx),
         _ => return None,
     };
 
-    let inputs = all_types
-        .iter()
-        .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind)))
-        .filter(|a| a.ty.name.is_some())
-        .collect();
-    let output = ret_types
-        .iter()
-        .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind)))
-        .filter(|a| a.ty.name.is_some())
-        .collect::<Vec<_>>();
+    inputs.retain(|a| a.ty.name.is_some());
+    output.retain(|a| a.ty.name.is_some());
     let output = if output.is_empty() { None } else { Some(output) };
 
     Some(IndexItemFunctionType { inputs, output })
 }
 
-fn get_index_type(clean_type: &clean::Type) -> RenderType {
+fn get_index_type(clean_type: &clean::Type, generics: Vec<TypeWithKind>) -> RenderType {
     RenderType {
         name: get_index_type_name(clean_type, true).map(|s| s.as_str().to_ascii_lowercase()),
-        generics: get_generics(clean_type),
+        generics: if generics.is_empty() { None } else { Some(generics) },
     }
 }
 
@@ -248,23 +238,6 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option
     }
 }
 
-/// Return a list of generic parameters for use in the search index.
-///
-/// This function replaces bounds with types, so that `T where T: Debug` just becomes `Debug`.
-/// It does return duplicates, and that's intentional, since search queries like `Result<usize, usize>`
-/// are supposed to match only results where both parameters are `usize`.
-fn get_generics(clean_type: &clean::Type) -> Option<Vec<String>> {
-    clean_type.generics().and_then(|types| {
-        let r = types
-            .iter()
-            .filter_map(|t| {
-                get_index_type_name(t, false).map(|name| name.as_str().to_ascii_lowercase())
-            })
-            .collect::<Vec<_>>();
-        if r.is_empty() { None } else { Some(r) }
-    })
-}
-
 /// The point of this function is to replace bounds with types.
 ///
 /// i.e. `[T, U]` when you have the following bounds: `T: Display, U: Option<T>` will return
@@ -274,33 +247,86 @@ fn get_generics(clean_type: &clean::Type) -> Option<Vec<String>> {
     generics: &Generics,
     arg: &Type,
     tcx: TyCtxt<'tcx>,
-    recurse: i32,
-    res: &mut FxHashSet<(Type, ItemType)>,
-) -> usize {
-    fn insert(res: &mut FxHashSet<(Type, ItemType)>, tcx: TyCtxt<'_>, ty: Type) -> usize {
-        if let Some(kind) = ty.def_id().map(|did| tcx.def_kind(did).into()) {
-            res.insert((ty, kind));
-            1
+    recurse: usize,
+    res: &mut Vec<TypeWithKind>,
+) {
+    fn insert_ty(
+        res: &mut Vec<TypeWithKind>,
+        tcx: TyCtxt<'_>,
+        ty: Type,
+        mut generics: Vec<TypeWithKind>,
+    ) {
+        let is_full_generic = ty.is_full_generic();
+
+        if is_full_generic && generics.len() == 1 {
+            // In this case, no need to go through an intermediate state if the generics
+            // contains only one element.
+            //
+            // For example:
+            //
+            // fn foo<T: Display>(r: Option<T>) {}
+            //
+            // In this case, it would contain:
+            //
+            // ```
+            // [{
+            //     name: "option",
+            //     generics: [{
+            //         name: "",
+            //         generics: [
+            //             name: "Display",
+            //             generics: []
+            //         }]
+            //     }]
+            // }]
+            // ```
+            //
+            // After removing the intermediate (unnecessary) full generic, it'll become:
+            //
+            // ```
+            // [{
+            //     name: "option",
+            //     generics: [{
+            //         name: "Display",
+            //         generics: []
+            //     }]
+            // }]
+            // ```
+            //
+            // To be noted that it can work if there is ONLY ONE generic, otherwise we still
+            // need to keep it as is!
+            res.push(generics.pop().unwrap());
+            return;
+        }
+        let mut index_ty = get_index_type(&ty, generics);
+        if index_ty.name.as_ref().map(|s| s.is_empty()).unwrap_or(true) {
+            return;
+        }
+        if is_full_generic {
+            // We remove the name of the full generic because we have no use for it.
+            index_ty.name = Some(String::new());
+            res.push(TypeWithKind::from((index_ty, ItemType::Generic)));
+        } else if let Some(kind) = ty.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) {
+            res.push(TypeWithKind::from((index_ty, kind)));
         } else if ty.is_primitive() {
             // This is a primitive, let's store it as such.
-            res.insert((ty, ItemType::Primitive));
-            1
-        } else {
-            0
+            res.push(TypeWithKind::from((index_ty, ItemType::Primitive)));
         }
     }
 
     if recurse >= 10 {
         // FIXME: remove this whole recurse thing when the recursion bug is fixed
-        return 0;
+        return;
     }
-    let mut nb_added = 0;
 
-    if let &Type::Generic(arg_s) = arg {
+    if let Type::Generic(arg_s) = *arg {
         if let Some(where_pred) = generics.where_predicates.iter().find(|g| match g {
-            WherePredicate::BoundPredicate { ty, .. } => ty.def_id() == arg.def_id(),
+            WherePredicate::BoundPredicate { ty, .. } => {
+                ty.def_id_no_primitives() == arg.def_id_no_primitives()
+            }
             _ => false,
         }) {
+            let mut ty_generics = Vec::new();
             let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]);
             for bound in bounds.iter() {
                 if let GenericBound::TraitBound(poly_trait, _) = bound {
@@ -309,41 +335,32 @@ fn insert(res: &mut FxHashSet<(Type, ItemType)>, tcx: TyCtxt<'_>, ty: Type) -> u
                             continue;
                         }
                         if let Some(ty) = x.get_type() {
-                            let adds = get_real_types(generics, &ty, tcx, recurse + 1, res);
-                            nb_added += adds;
-                            if adds == 0 && !ty.is_full_generic() {
-                                nb_added += insert(res, tcx, ty);
-                            }
+                            get_real_types(generics, &ty, tcx, recurse + 1, &mut ty_generics);
                         }
                     }
                 }
             }
+            insert_ty(res, tcx, arg.clone(), ty_generics);
         }
         if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) {
+            let mut ty_generics = Vec::new();
             for bound in bound.get_bounds().unwrap_or(&[]) {
                 if let Some(path) = bound.get_trait_path() {
                     let ty = Type::ResolvedPath { did: path.def_id(), path };
-                    let adds = get_real_types(generics, &ty, tcx, recurse + 1, res);
-                    nb_added += adds;
-                    if adds == 0 && !ty.is_full_generic() {
-                        nb_added += insert(res, tcx, ty);
-                    }
+                    get_real_types(generics, &ty, tcx, recurse + 1, &mut ty_generics);
                 }
             }
+            insert_ty(res, tcx, arg.clone(), ty_generics);
         }
     } else {
-        nb_added += insert(res, tcx, arg.clone());
-        if let Some(gens) = arg.generics() {
-            for gen in gens.iter() {
-                if gen.is_full_generic() {
-                    nb_added += get_real_types(generics, gen, tcx, recurse + 1, res);
-                } else {
-                    nb_added += insert(res, tcx, (*gen).clone());
-                }
+        let mut ty_generics = Vec::new();
+        if let Some(arg_generics) = arg.generics() {
+            for gen in arg_generics.iter() {
+                get_real_types(generics, gen, tcx, recurse + 1, &mut ty_generics);
             }
         }
+        insert_ty(res, tcx, arg.clone(), ty_generics);
     }
-    nb_added
 }
 
 /// Return the full list of types when bounds have been resolved.
@@ -354,35 +371,41 @@ fn insert(res: &mut FxHashSet<(Type, ItemType)>, tcx: TyCtxt<'_>, ty: Type) -> u
     generics: &Generics,
     decl: &FnDecl,
     tcx: TyCtxt<'tcx>,
-) -> (Vec<(Type, ItemType)>, Vec<(Type, ItemType)>) {
-    let mut all_types = FxHashSet::default();
+) -> (Vec<TypeWithKind>, Vec<TypeWithKind>) {
+    let mut all_types = Vec::new();
     for arg in decl.inputs.values.iter() {
         if arg.type_.is_self_type() {
             continue;
         }
-        let mut args = FxHashSet::default();
+        // FIXME: performance wise, it'd be much better to move `args` declaration outside of the
+        // loop and replace this line with `args.clear()`.
+        let mut args = Vec::new();
         get_real_types(generics, &arg.type_, tcx, 0, &mut args);
         if !args.is_empty() {
+            // FIXME: once back to performance improvements, replace this line with:
+            // `all_types.extend(args.drain(..));`.
             all_types.extend(args);
         } else {
-            if let Some(kind) = arg.type_.def_id().map(|did| tcx.def_kind(did).into()) {
-                all_types.insert((arg.type_.clone(), kind));
+            if let Some(kind) = arg.type_.def_id_no_primitives().map(|did| tcx.def_kind(did).into())
+            {
+                all_types.push(TypeWithKind::from((get_index_type(&arg.type_, vec![]), kind)));
             }
         }
     }
 
-    let ret_types = match decl.output {
+    let mut ret_types = Vec::new();
+    match decl.output {
         FnRetTy::Return(ref return_type) => {
-            let mut ret = FxHashSet::default();
-            get_real_types(generics, &return_type, tcx, 0, &mut ret);
-            if ret.is_empty() {
-                if let Some(kind) = return_type.def_id().map(|did| tcx.def_kind(did).into()) {
-                    ret.insert((return_type.clone(), kind));
+            get_real_types(generics, return_type, tcx, 0, &mut ret_types);
+            if ret_types.is_empty() {
+                if let Some(kind) =
+                    return_type.def_id_no_primitives().map(|did| tcx.def_kind(did).into())
+                {
+                    ret_types.push(TypeWithKind::from((get_index_type(return_type, vec![]), kind)));
                 }
             }
-            ret.into_iter().collect()
         }
-        _ => Vec::new(),
+        _ => {}
     };
-    (all_types.into_iter().collect(), ret_types)
+    (all_types, ret_types)
 }
index d7ef8513d6a8958eaa80ffcc37cee25975eec5d6..069862efde6409a0a49891cd32263b08b836a5c7 100644 (file)
@@ -6,7 +6,7 @@
 use std::sync::mpsc::{channel, Receiver};
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
 use rustc_span::edition::Edition;
@@ -22,8 +22,7 @@
     BASIC_KEYWORDS,
 };
 
-use crate::clean;
-use crate::clean::ExternalCrate;
+use crate::clean::{self, ExternalCrate};
 use crate::config::RenderOptions;
 use crate::docfs::{DocFS, PathError};
 use crate::error::Error;
@@ -35,6 +34,7 @@
 use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap};
 use crate::html::{layout, sources};
 use crate::scrape_examples::AllCallLocations;
+use crate::try_err;
 
 /// Major driving force in all rustdoc rendering. This contains information
 /// about where in the tree-like hierarchy rendering is occurring and controls
@@ -54,6 +54,9 @@
     /// real location of an item. This is used to allow external links to
     /// publicly reused items to redirect to the right location.
     pub(super) render_redirect_pages: bool,
+    /// Tracks section IDs for `Deref` targets so they match in both the main
+    /// body and the sidebar.
+    pub(super) deref_id_map: RefCell<FxHashMap<DefId, String>>,
     /// The map used to ensure all generated 'id=' attributes are unique.
     pub(super) id_map: RefCell<IdMap>,
     /// Shared mutable state.
@@ -70,7 +73,7 @@
 
 // `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Context<'_>, 104);
+rustc_data_structures::static_assert_size!(Context<'_>, 144);
 
 /// Shared mutable state used in [`Context`] and elsewhere.
 crate struct SharedContext<'tcx> {
@@ -160,7 +163,7 @@ pub(crate) fn cache(&self) -> &Cache {
     }
 
     pub(super) fn sess(&self) -> &'tcx Session {
-        &self.shared.tcx.sess
+        self.shared.tcx.sess
     }
 
     pub(super) fn derive_id(&self, id: String) -> String {
@@ -188,7 +191,7 @@ fn render_item(&self, it: &clean::Item, is_module: bool) -> String {
         };
         title.push_str(" - Rust");
         let tyname = it.type_();
-        let desc = it.doc_value().as_ref().map(|doc| plain_text_summary(&doc));
+        let desc = it.doc_value().as_ref().map(|doc| plain_text_summary(doc));
         let desc = if let Some(desc) = desc {
             desc
         } else if it.is_crate() {
@@ -405,7 +408,7 @@ fn init(
             ..
         } = options;
 
-        let src_root = match krate.src {
+        let src_root = match krate.src(tcx) {
             FileName::Real(ref p) => match p.local_path_if_available().parent() {
                 Some(p) => p.to_path_buf(),
                 None => PathBuf::new(),
@@ -416,14 +419,14 @@ fn init(
         let mut playground = None;
         if let Some(url) = playground_url {
             playground =
-                Some(markdown::Playground { crate_name: Some(krate.name.to_string()), url });
+                Some(markdown::Playground { crate_name: Some(krate.name(tcx).to_string()), url });
         }
         let mut layout = layout::Layout {
             logo: String::new(),
             favicon: String::new(),
             external_html,
             default_settings,
-            krate: krate.name.to_string(),
+            krate: krate.name(tcx).to_string(),
             css_file_extension: extension_css,
             generate_search_filter,
             scrape_examples_extension: !call_locations.is_empty(),
@@ -444,7 +447,7 @@ fn init(
                 }
                 (sym::html_playground_url, Some(s)) => {
                     playground = Some(markdown::Playground {
-                        crate_name: Some(krate.name.to_string()),
+                        crate_name: Some(krate.name(tcx).to_string()),
                         url: s.to_string(),
                     });
                 }
@@ -458,9 +461,9 @@ fn init(
             }
         }
 
-        let (mut krate, local_sources, matches) = collect_spans_and_sources(
+        let (local_sources, matches) = collect_spans_and_sources(
             tcx,
-            krate,
+            &krate,
             &src_root,
             include_sources,
             generate_link_to_definition,
@@ -513,12 +516,13 @@ fn init(
             dst,
             render_redirect_pages: false,
             id_map: RefCell::new(id_map),
+            deref_id_map: RefCell::new(FxHashMap::default()),
             shared: Rc::new(scx),
             include_sources,
         };
 
         if emit_crate {
-            krate = sources::render(&mut cx, krate)?;
+            sources::render(&mut cx, &krate)?;
         }
 
         // Build our search index
@@ -536,6 +540,7 @@ fn make_child_renderer(&self) -> Self {
             current: self.current.clone(),
             dst: self.dst.clone(),
             render_redirect_pages: self.render_redirect_pages,
+            deref_id_map: RefCell::new(FxHashMap::default()),
             id_map: RefCell::new(IdMap::new()),
             shared: Rc::clone(&self.shared),
             include_sources: self.include_sources,
index bd6cb9c2988429319786a0d73f34161dddd3be9b..fdadc68998dc663f98609c190841b75d3f09f5f8 100644 (file)
@@ -34,8 +34,8 @@
 mod templates;
 mod write_shared;
 
-crate use context::*;
-crate use span_map::{collect_spans_and_sources, LinkFromSrc};
+crate use self::context::*;
+crate use self::span_map::{collect_spans_and_sources, LinkFromSrc};
 
 use std::collections::VecDeque;
 use std::default::Default;
@@ -54,6 +54,7 @@
 use rustc_hir::def_id::DefId;
 use rustc_hir::Mutability;
 use rustc_middle::middle::stability;
+use rustc_middle::ty;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::{
     symbol::{kw, sym, Symbol},
@@ -62,7 +63,7 @@
 use serde::ser::SerializeSeq;
 use serde::{Serialize, Serializer};
 
-use crate::clean::{self, GetDefId, ItemId, RenderedLink, SelfTy};
+use crate::clean::{self, ItemId, RenderedLink, SelfTy};
 use crate::docfs::PathError;
 use crate::error::Error;
 use crate::formats::cache::Cache;
@@ -76,7 +77,8 @@
 use crate::html::highlight;
 use crate::html::markdown::{HeadingOffset, Markdown, MarkdownHtml, MarkdownSummaryLine};
 use crate::html::sources;
-use crate::scrape_examples::CallData;
+use crate::scrape_examples::{CallData, CallLocation};
+use crate::try_none;
 
 /// A pair of name and its optional document.
 crate type NameDoc = (String, Option<String>);
 #[derive(Debug)]
 crate struct RenderType {
     name: Option<String>,
-    generics: Option<Vec<String>>,
+    generics: Option<Vec<TypeWithKind>>,
 }
 
 /// Full type of functions/methods in the search index.
@@ -126,8 +128,8 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
         // If we couldn't figure out a type, just write `null`.
         let mut iter = self.inputs.iter();
         if match self.output {
-            Some(ref output) => iter.chain(output.iter()).any(|ref i| i.ty.name.is_none()),
-            None => iter.any(|ref i| i.ty.name.is_none()),
+            Some(ref output) => iter.chain(output.iter()).any(|i| i.ty.name.is_none()),
+            None => iter.any(|i| i.ty.name.is_none()),
         } {
             serializer.serialize_none()
         } else {
@@ -906,7 +908,7 @@ fn method(
             AssocItemLink::GotoSource(did, provided_methods) => {
                 // We're creating a link from an impl-item to the corresponding
                 // trait-item and need to map the anchored type accordingly.
-                let ty = if provided_methods.contains(&name) {
+                let ty = if provided_methods.contains(name) {
                     ItemType::Method
                 } else {
                     ItemType::TyMethod
@@ -965,7 +967,7 @@ fn method(
             name = name,
             generics = g.print(cx),
             decl = d.full_print(header_len, indent, header.asyncness, cx),
-            notable_traits = notable_traits_decl(&d, cx),
+            notable_traits = notable_traits_decl(d, cx),
             where_clause = print_where_clause(g, cx, indent, end_newline),
         )
     }
@@ -1008,7 +1010,7 @@ fn attributes(it: &clean::Item) -> Vec<String> {
         .iter()
         .filter_map(|attr| {
             if ALLOWED_ATTRIBUTES.contains(&attr.name_or_empty()) {
-                Some(pprust::attribute_to_string(&attr).replace("\n", "").replace("  ", " "))
+                Some(pprust::attribute_to_string(attr).replace("\n", "").replace("  ", " "))
             } else {
                 None
             }
@@ -1041,7 +1043,7 @@ enum AssocItemLink<'a> {
 impl<'a> AssocItemLink<'a> {
     fn anchor(&self, id: &'a str) -> Self {
         match *self {
-            AssocItemLink::Anchor(_) => AssocItemLink::Anchor(Some(&id)),
+            AssocItemLink::Anchor(_) => AssocItemLink::Anchor(Some(id)),
             ref other => *other,
         }
     }
@@ -1053,6 +1055,19 @@ fn render_assoc_items(
     containing_item: &clean::Item,
     it: DefId,
     what: AssocItemRender<'_>,
+) {
+    let mut derefs = FxHashSet::default();
+    derefs.insert(it);
+    render_assoc_items_inner(w, cx, containing_item, it, what, &mut derefs)
+}
+
+fn render_assoc_items_inner(
+    w: &mut Buffer,
+    cx: &Context<'_>,
+    containing_item: &clean::Item,
+    it: DefId,
+    what: AssocItemRender<'_>,
+    derefs: &mut FxHashSet<DefId>,
 ) {
     info!("Documenting associated items of {:?}", containing_item.name);
     let cache = cx.cache();
@@ -1062,9 +1077,10 @@ fn render_assoc_items(
     };
     let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none());
     if !non_trait.is_empty() {
+        let mut tmp_buf = Buffer::empty_from(w);
         let render_mode = match what {
             AssocItemRender::All => {
-                w.write_str(
+                tmp_buf.write_str(
                     "<h2 id=\"implementations\" class=\"small-section-header\">\
                          Implementations<a href=\"#implementations\" class=\"anchor\"></a>\
                     </h2>",
@@ -1072,21 +1088,28 @@ fn render_assoc_items(
                 RenderMode::Normal
             }
             AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
+                let id =
+                    cx.derive_id(small_url_encode(format!("deref-methods-{:#}", type_.print(cx))));
+                if let Some(def_id) = type_.def_id(cx.cache()) {
+                    cx.deref_id_map.borrow_mut().insert(def_id, id.clone());
+                }
                 write!(
-                    w,
-                    "<h2 id=\"deref-methods\" class=\"small-section-header\">\
+                    tmp_buf,
+                    "<h2 id=\"{id}\" class=\"small-section-header\">\
                          <span>Methods from {trait_}&lt;Target = {type_}&gt;</span>\
-                         <a href=\"#deref-methods\" class=\"anchor\"></a>\
+                         <a href=\"#{id}\" class=\"anchor\"></a>\
                      </h2>",
+                    id = id,
                     trait_ = trait_.print(cx),
                     type_ = type_.print(cx),
                 );
                 RenderMode::ForDeref { mut_: deref_mut_ }
             }
         };
+        let mut impls_buf = Buffer::empty_from(w);
         for i in &non_trait {
             render_impl(
-                w,
+                &mut impls_buf,
                 cx,
                 i,
                 containing_item,
@@ -1103,24 +1126,33 @@ fn render_assoc_items(
                 },
             );
         }
+        if !impls_buf.is_empty() {
+            w.push_buffer(tmp_buf);
+            w.push_buffer(impls_buf);
+        }
     }
-    if let AssocItemRender::DerefFor { .. } = what {
-        return;
-    }
+
     if !traits.is_empty() {
         let deref_impl =
             traits.iter().find(|t| t.trait_did() == cx.tcx().lang_items().deref_trait());
         if let Some(impl_) = deref_impl {
             let has_deref_mut =
                 traits.iter().any(|t| t.trait_did() == cx.tcx().lang_items().deref_mut_trait());
-            render_deref_methods(w, cx, impl_, containing_item, has_deref_mut);
+            render_deref_methods(w, cx, impl_, containing_item, has_deref_mut, derefs);
+        }
+
+        // If we were already one level into rendering deref methods, we don't want to render
+        // anything after recursing into any further deref methods above.
+        if let AssocItemRender::DerefFor { .. } = what {
+            return;
         }
+
         let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) =
-            traits.iter().partition(|t| t.inner_impl().synthetic);
+            traits.iter().partition(|t| t.inner_impl().kind.is_auto());
         let (blanket_impl, concrete): (Vec<&&Impl>, _) =
-            concrete.into_iter().partition(|t| t.inner_impl().blanket_impl.is_some());
+            concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket());
 
-        let mut impls = Buffer::empty_from(&w);
+        let mut impls = Buffer::empty_from(w);
         render_impls(cx, &mut impls, &concrete, containing_item);
         let impls = impls.into_inner();
         if !impls.is_empty() {
@@ -1166,6 +1198,7 @@ fn render_deref_methods(
     impl_: &Impl,
     container_item: &clean::Item,
     deref_mut: bool,
+    derefs: &mut FxHashSet<DefId>,
 ) {
     let cache = cx.cache();
     let deref_type = impl_.inner_impl().trait_.as_ref().unwrap();
@@ -1184,19 +1217,19 @@ fn render_deref_methods(
     debug!("Render deref methods for {:#?}, target {:#?}", impl_.inner_impl().for_, target);
     let what =
         AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut };
-    if let Some(did) = target.def_id_full(cache) {
-        if let Some(type_did) = impl_.inner_impl().for_.def_id_full(cache) {
+    if let Some(did) = target.def_id(cache) {
+        if let Some(type_did) = impl_.inner_impl().for_.def_id(cache) {
             // `impl Deref<Target = S> for S`
-            if did == type_did {
+            if did == type_did || !derefs.insert(did) {
                 // Avoid infinite cycles
                 return;
             }
         }
-        render_assoc_items(w, cx, container_item, did, what);
+        render_assoc_items_inner(w, cx, container_item, did, what, derefs);
     } else {
         if let Some(prim) = target.primitive_type() {
             if let Some(&did) = cache.primitive_locations.get(&prim) {
-                render_assoc_items(w, cx, container_item, did, what);
+                render_assoc_items_inner(w, cx, container_item, did, what, derefs);
             }
         }
     }
@@ -1231,7 +1264,7 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) ->
 fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String {
     let mut out = Buffer::html();
 
-    if let Some(did) = decl.output.def_id_full(cx.cache()) {
+    if let Some(did) = decl.output.as_return().and_then(|t| t.def_id(cx.cache())) {
         if let Some(impls) = cx.cache().impls.get(&did) {
             for i in impls {
                 let impl_ = i.inner_impl();
@@ -1333,7 +1366,7 @@ fn doc_impl_item(
             && match render_mode {
                 RenderMode::Normal => true,
                 RenderMode::ForDeref { mut_: deref_mut_ } => {
-                    should_render_item(&item, deref_mut_, cx.tcx())
+                    should_render_item(item, deref_mut_, cx.tcx())
                 }
             };
 
@@ -1566,7 +1599,7 @@ fn render_default_items(
                 &mut impl_items,
                 cx,
                 &t.trait_,
-                &i.inner_impl(),
+                i.inner_impl(),
                 &i.impl_item,
                 parent,
                 render_mode,
@@ -1612,7 +1645,7 @@ fn render_default_items(
                     error_codes: cx.shared.codes,
                     edition: cx.shared.edition(),
                     playground: &cx.shared.playground,
-                    heading_offset: HeadingOffset::H2
+                    heading_offset: HeadingOffset::H4
                 }
                 .into_string()
             );
@@ -1986,7 +2019,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
             if let Some(impl_) =
                 v.iter().find(|i| i.trait_did() == cx.tcx().lang_items().deref_trait())
             {
-                sidebar_deref_methods(cx, out, impl_, v);
+                let mut derefs = FxHashSet::default();
+                derefs.insert(did);
+                sidebar_deref_methods(cx, out, impl_, v, &mut derefs);
             }
 
             let format_impls = |impls: Vec<&Impl>| {
@@ -1999,12 +2034,12 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
                             let i_display = format!("{:#}", i.print(cx));
                             let out = Escape(&i_display);
                             let encoded = small_url_encode(format!("{:#}", i.print(cx)));
-                            let generated = format!(
-                                "<a href=\"#impl-{}\">{}{}</a>",
-                                encoded,
-                                if it.inner_impl().negative_polarity { "!" } else { "" },
-                                out
-                            );
+                            let prefix = match it.inner_impl().polarity {
+                                ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
+                                ty::ImplPolarity::Negative => "!",
+                            };
+                            let generated =
+                                format!("<a href=\"#impl-{}\">{}{}</a>", encoded, prefix, out);
                             if links.insert(generated.clone()) { Some(generated) } else { None }
                         } else {
                             None
@@ -2024,10 +2059,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
             };
 
             let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
-                v.iter().partition::<Vec<_>, _>(|i| i.inner_impl().synthetic);
-            let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) = concrete
-                .into_iter()
-                .partition::<Vec<_>, _>(|i| i.inner_impl().blanket_impl.is_some());
+                v.iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_auto());
+            let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) =
+                concrete.into_iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_blanket());
 
             let concrete_format = format_impls(concrete);
             let synthetic_format = format_impls(synthetic);
@@ -2060,7 +2094,13 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
     }
 }
 
-fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &Vec<Impl>) {
+fn sidebar_deref_methods(
+    cx: &Context<'_>,
+    out: &mut Buffer,
+    impl_: &Impl,
+    v: &[Impl],
+    derefs: &mut FxHashSet<DefId>,
+) {
     let c = cx.cache();
 
     debug!("found Deref: {:?}", impl_);
@@ -2074,10 +2114,10 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
         })
     {
         debug!("found target, real_target: {:?} {:?}", target, real_target);
-        if let Some(did) = target.def_id_full(c) {
-            if let Some(type_did) = impl_.inner_impl().for_.def_id_full(c) {
+        if let Some(did) = target.def_id(c) {
+            if let Some(type_did) = impl_.inner_impl().for_.def_id(c) {
                 // `impl Deref<Target = S> for S`
-                if did == type_did {
+                if did == type_did || !derefs.insert(did) {
                     // Avoid infinite cycles
                     return;
                 }
@@ -2085,7 +2125,7 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
         }
         let deref_mut = v.iter().any(|i| i.trait_did() == cx.tcx().lang_items().deref_mut_trait());
         let inner_impl = target
-            .def_id_full(c)
+            .def_id(c)
             .or_else(|| {
                 target.primitive_type().and_then(|prim| c.primitive_locations.get(&prim).cloned())
             })
@@ -2101,9 +2141,17 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
                 })
                 .collect::<Vec<_>>();
             if !ret.is_empty() {
+                let map;
+                let id = if let Some(target_def_id) = real_target.def_id(c) {
+                    map = cx.deref_id_map.borrow();
+                    map.get(&target_def_id).expect("Deref section without derived id")
+                } else {
+                    "deref-methods"
+                };
                 write!(
                     out,
-                    "<h3 class=\"sidebar-title\"><a href=\"#deref-methods\">Methods from {}&lt;Target={}&gt;</a></h3>",
+                    "<h3 class=\"sidebar-title\"><a href=\"#{}\">Methods from {}&lt;Target={}&gt;</a></h3>",
+                    id,
                     Escape(&format!("{:#}", impl_.inner_impl().trait_.as_ref().unwrap().print(cx))),
                     Escape(&format!("{:#}", real_target.print(cx))),
                 );
@@ -2116,6 +2164,21 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
                 out.push_str("</div>");
             }
         }
+
+        // Recurse into any further impls that might exist for `target`
+        if let Some(target_did) = target.def_id_no_primitives() {
+            if let Some(target_impls) = c.impls.get(&target_did) {
+                if let Some(target_deref_impl) = target_impls.iter().find(|i| {
+                    i.inner_impl()
+                        .trait_
+                        .as_ref()
+                        .map(|t| Some(t.def_id()) == cx.tcx().lang_items().deref_trait())
+                        .unwrap_or(false)
+                }) {
+                    sidebar_deref_methods(cx, out, target_deref_impl, target_impls, derefs);
+                }
+            }
+        }
     }
 }
 
@@ -2159,16 +2222,14 @@ fn get_id_for_impl_on_foreign_type(
 fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String, String)> {
     match *item.kind {
         clean::ItemKind::ImplItem(ref i) => {
-            if let Some(ref trait_) = i.trait_ {
+            i.trait_.as_ref().map(|trait_| {
                 // Alternative format produces no URLs,
                 // so this parameter does nothing.
-                Some((
+                (
                     format!("{:#}", i.for_.print(cx)),
                     get_id_for_impl_on_foreign_type(&i.for_, trait_, cx),
-                ))
-            } else {
-                None
-            }
+                )
+            })
         }
         _ => None,
     }
@@ -2248,10 +2309,7 @@ fn print_sidebar_section(
         let mut res = implementors
             .iter()
             .filter(|i| {
-                i.inner_impl()
-                    .for_
-                    .def_id_full(cache)
-                    .map_or(false, |d| !cache.paths.contains_key(&d))
+                i.inner_impl().for_.def_id(cache).map_or(false, |d| !cache.paths.contains_key(&d))
             })
             .filter_map(|i| extract_for_impl_name(&i.impl_item, cx))
             .collect::<Vec<_>>();
@@ -2343,9 +2401,10 @@ fn sidebar_enum(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, e: &clean:
     let mut variants = e
         .variants
         .iter()
-        .filter_map(|v| match v.name {
-            Some(ref name) => Some(format!("<a href=\"#variant.{name}\">{name}</a>", name = name)),
-            _ => None,
+        .filter_map(|v| {
+            v.name
+                .as_ref()
+                .map(|name| format!("<a href=\"#variant.{name}\">{name}</a>", name = name))
         })
         .collect::<Vec<_>>();
     if !variants.is_empty() {
@@ -2391,6 +2450,7 @@ fn item_ty_to_strs(ty: ItemType) -> (&'static str, &'static str) {
         ItemType::ProcAttribute => ("attributes", "Attribute Macros"),
         ItemType::ProcDerive => ("derives", "Derive Macros"),
         ItemType::TraitAlias => ("trait-aliases", "Trait aliases"),
+        ItemType::Generic => unreachable!(),
     }
 }
 
@@ -2534,6 +2594,21 @@ fn render_call_locations(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item) {
         id = id
     );
 
+    // Create a URL to a particular location in a reverse-dependency's source file
+    let link_to_loc = |call_data: &CallData, loc: &CallLocation| -> (String, String) {
+        let (line_lo, line_hi) = loc.call_expr.line_span;
+        let (anchor, title) = if line_lo == line_hi {
+            ((line_lo + 1).to_string(), format!("line {}", line_lo + 1))
+        } else {
+            (
+                format!("{}-{}", line_lo + 1, line_hi + 1),
+                format!("lines {}-{}", line_lo + 1, line_hi + 1),
+            )
+        };
+        let url = format!("{}{}#{}", cx.root_path(), call_data.url, anchor);
+        (url, title)
+    };
+
     // Generate the HTML for a single example, being the title and code block
     let write_example = |w: &mut Buffer, (path, call_data): (&PathBuf, &CallData)| -> bool {
         let contents = match fs::read_to_string(&path) {
@@ -2571,15 +2646,7 @@ fn render_call_locations(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item) {
                 let (line_lo, line_hi) = loc.call_expr.line_span;
                 let byte_range = (byte_lo - byte_min, byte_hi - byte_min);
                 let line_range = (line_lo - line_min, line_hi - line_min);
-                let (anchor, line_title) = if line_lo == line_hi {
-                    (format!("{}", line_lo + 1), format!("line {}", line_lo + 1))
-                } else {
-                    (
-                        format!("{}-{}", line_lo + 1, line_hi + 1),
-                        format!("lines {}-{}", line_lo + 1, line_hi + 1),
-                    )
-                };
-                let line_url = format!("{}{}#{}", cx.root_path(), call_data.url, anchor);
+                let (line_url, line_title) = link_to_loc(call_data, loc);
 
                 (byte_range, (line_range, line_url, line_title))
             })
@@ -2708,11 +2775,11 @@ fn render_call_locations(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item) {
         if it.peek().is_some() {
             write!(w, r#"<div class="example-links">Additional examples can be found in:<br><ul>"#);
             it.for_each(|(_, call_data)| {
+                let (url, _) = link_to_loc(&call_data, &call_data.locations[0]);
                 write!(
                     w,
-                    r#"<li><a href="{root}{url}">{name}</a></li>"#,
-                    root = cx.root_path(),
-                    url = call_data.url,
+                    r#"<li><a href="{url}">{name}</a></li>"#,
+                    url = url,
                     name = call_data.display_name
                 );
             });
index f4528369622271b9acebe0d5a90dde6259ddccc6..7ef773fe5ff29dde2338ef963426cb4d5b2b419f 100644 (file)
@@ -21,7 +21,7 @@
     render_impl, render_stability_since_raw, write_srclink, AssocItemLink, Context,
     ImplRenderingParameters,
 };
-use crate::clean::{self, GetDefId};
+use crate::clean;
 use crate::formats::item_type::ItemType;
 use crate::formats::{AssocItemRender, Impl, RenderMode};
 use crate::html::escape::Escape;
 
 use serde::Serialize;
 
-const ITEM_TABLE_OPEN: &'static str = "<div class=\"item-table\">";
-const ITEM_TABLE_CLOSE: &'static str = "</div>";
-const ITEM_TABLE_ROW_OPEN: &'static str = "<div class=\"item-row\">";
-const ITEM_TABLE_ROW_CLOSE: &'static str = "</div>";
+const ITEM_TABLE_OPEN: &str = "<div class=\"item-table\">";
+const ITEM_TABLE_CLOSE: &str = "</div>";
+const ITEM_TABLE_ROW_OPEN: &str = "<div class=\"item-row\">";
+const ITEM_TABLE_ROW_CLOSE: &str = "</div>";
 
 // A component in a `use` path, like `string` in std::string::ToString
 #[derive(Serialize)]
@@ -742,11 +742,11 @@ fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item
         }
 
         let (local, foreign) = implementors.iter().partition::<Vec<_>, _>(|i| {
-            i.inner_impl().for_.def_id_full(cache).map_or(true, |d| cache.paths.contains_key(&d))
+            i.inner_impl().for_.def_id(cache).map_or(true, |d| cache.paths.contains_key(&d))
         });
 
         let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) =
-            local.iter().partition(|i| i.inner_impl().synthetic);
+            local.iter().partition(|i| i.inner_impl().kind.is_auto());
 
         synthetic.sort_by(|a, b| compare_impl(a, b, cx));
         concrete.sort_by(|a, b| compare_impl(a, b, cx));
@@ -761,7 +761,7 @@ fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item
                 render_impl(
                     w,
                     cx,
-                    &implementor,
+                    implementor,
                     it,
                     assoc_link,
                     RenderMode::Normal,
@@ -983,7 +983,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
             if let Some(stability_class) = field.stability_class(cx.tcx()) {
                 write!(w, "<span class=\"stab {stab}\"></span>", stab = stability_class);
             }
-            document(w, cx, field, Some(it), HeadingOffset::H2);
+            document(w, cx, field, Some(it), HeadingOffset::H3);
         }
     }
     let def_id = it.def_id.expect_def_id();
@@ -1094,7 +1094,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
             w.write_str("</code>");
             render_stability_since(w, variant, it, cx.tcx());
             w.write_str("</div>");
-            document(w, cx, variant, Some(it), HeadingOffset::H2);
+            document(w, cx, variant, Some(it), HeadingOffset::H3);
             document_non_exhaustive(w, variant);
 
             use crate::clean::Variant;
@@ -1134,7 +1134,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                                 f = field.name.as_ref().unwrap(),
                                 t = ty.print(cx)
                             );
-                            document(w, cx, field, Some(variant), HeadingOffset::H2);
+                            document(w, cx, field, Some(variant), HeadingOffset::H4);
                         }
                         _ => unreachable!(),
                     }
@@ -1286,7 +1286,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
                     name = field_name,
                     ty = ty.print(cx)
                 );
-                document(w, cx, field, Some(it), HeadingOffset::H2);
+                document(w, cx, field, Some(it), HeadingOffset::H3);
             }
         }
     }
@@ -1497,7 +1497,7 @@ fn render_union(
     );
     if let Some(g) = g {
         write!(w, "{}", g.print(cx));
-        write!(w, "{}", print_where_clause(&g, cx, 0, true));
+        write!(w, "{}", print_where_clause(g, cx, 0, true));
     }
 
     write!(w, " {{\n{}", tab);
index d517f3ac0e3a9e1a16db7d886a31dc263bedc90b..7803a779727c5b09e8ef033f6ecc343dd41b6c90 100644 (file)
 /// only keep the `lo` and `hi`.
 crate fn collect_spans_and_sources(
     tcx: TyCtxt<'_>,
-    krate: clean::Crate,
+    krate: &clean::Crate,
     src_root: &Path,
     include_sources: bool,
     generate_link_to_definition: bool,
-) -> (clean::Crate, FxHashMap<PathBuf, String>, FxHashMap<Span, LinkFromSrc>) {
+) -> (FxHashMap<PathBuf, String>, FxHashMap<Span, LinkFromSrc>) {
     let mut visitor = SpanMapVisitor { tcx, matches: FxHashMap::default() };
 
     if include_sources {
         if generate_link_to_definition {
             tcx.hir().walk_toplevel_module(&mut visitor);
         }
-        let (krate, sources) = sources::collect_local_sources(tcx, src_root, krate);
-        (krate, sources, visitor.matches)
+        let sources = sources::collect_local_sources(tcx, src_root, &krate);
+        (sources, visitor.matches)
     } else {
-        (krate, Default::default(), Default::default())
+        (Default::default(), Default::default())
     }
 }
 
@@ -105,7 +105,7 @@ fn visit_generic_param(&mut self, p: &'tcx GenericParam<'tcx>) {
         }
         for bound in p.bounds {
             if let Some(trait_ref) = bound.trait_ref() {
-                self.handle_path(&trait_ref.path, None);
+                self.handle_path(trait_ref.path, None);
             }
         }
     }
@@ -121,42 +121,33 @@ fn visit_mod(&mut self, m: &'tcx Mod<'tcx>, span: Span, id: HirId) {
         if !span.overlaps(m.inner) {
             // Now that we confirmed it's a file import, we want to get the span for the module
             // name only and not all the "mod foo;".
-            if let Some(node) = self.tcx.hir().find(id) {
-                match node {
-                    Node::Item(item) => {
-                        self.matches
-                            .insert(item.ident.span, LinkFromSrc::Local(clean::Span::new(m.inner)));
-                    }
-                    _ => {}
-                }
+            if let Some(Node::Item(item)) = self.tcx.hir().find(id) {
+                self.matches.insert(item.ident.span, LinkFromSrc::Local(clean::Span::new(m.inner)));
             }
         }
         intravisit::walk_mod(self, m, id);
     }
 
     fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'tcx>) {
-        match expr.kind {
-            ExprKind::MethodCall(segment, method_span, _, _) => {
-                if let Some(hir_id) = segment.hir_id {
-                    let hir = self.tcx.hir();
-                    let body_id = hir.enclosing_body_owner(hir_id);
-                    let typeck_results = self.tcx.sess.with_disabled_diagnostic(|| {
-                        self.tcx.typeck_body(
-                            hir.maybe_body_owned_by(body_id).expect("a body which isn't a body"),
-                        )
-                    });
-                    if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) {
-                        self.matches.insert(
-                            method_span,
-                            match hir.span_if_local(def_id) {
-                                Some(span) => LinkFromSrc::Local(clean::Span::new(span)),
-                                None => LinkFromSrc::External(def_id),
-                            },
-                        );
-                    }
+        if let ExprKind::MethodCall(segment, method_span, _, _) = expr.kind {
+            if let Some(hir_id) = segment.hir_id {
+                let hir = self.tcx.hir();
+                let body_id = hir.enclosing_body_owner(hir_id);
+                let typeck_results = self.tcx.sess.with_disabled_diagnostic(|| {
+                    self.tcx.typeck_body(
+                        hir.maybe_body_owned_by(body_id).expect("a body which isn't a body"),
+                    )
+                });
+                if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) {
+                    self.matches.insert(
+                        method_span,
+                        match hir.span_if_local(def_id) {
+                            Some(span) => LinkFromSrc::Local(clean::Span::new(span)),
+                            None => LinkFromSrc::External(def_id),
+                        },
+                    );
                 }
             }
-            _ => {}
         }
         intravisit::walk_expr(self, expr);
     }
index 31aaf46d7d595aadb32a6fefcc74343a8e3db597..2d3b2490677e9b3e029cbad752a3a58368f6a965 100644 (file)
@@ -17,6 +17,7 @@
 use crate::docfs::PathError;
 use crate::error::Error;
 use crate::html::{layout, static_files};
+use crate::{try_err, try_none};
 
 static FILES_UNVERSIONED: Lazy<FxHashMap<&str, &[u8]>> = Lazy::new(|| {
     map! {
@@ -39,9 +40,9 @@
         "SourceCodePro-Semibold.ttf.woff" => static_files::source_code_pro::SEMIBOLD,
         "SourceCodePro-It.ttf.woff" => static_files::source_code_pro::ITALIC,
         "SourceCodePro-LICENSE.txt" => static_files::source_code_pro::LICENSE,
-        "noto-sans-kr-regular.woff2" => static_files::noto_sans_kr::REGULAR2,
-        "noto-sans-kr-regular.woff" => static_files::noto_sans_kr::REGULAR,
-        "noto-sans-kr-LICENSE.txt" => static_files::noto_sans_kr::LICENSE,
+        "NanumBarunGothic.ttf.woff2" => static_files::nanum_barun_gothic::REGULAR2,
+        "NanumBarunGothic.ttf.woff" => static_files::nanum_barun_gothic::REGULAR,
+        "NanumBarunGothic-LICENSE.txt" => static_files::nanum_barun_gothic::LICENSE,
         "LICENSE-MIT.txt" => static_files::LICENSE_MIT,
         "LICENSE-APACHE.txt" => static_files::LICENSE_APACHE,
         "COPYRIGHT.txt" => static_files::COPYRIGHT,
@@ -128,7 +129,7 @@ fn write_minify(
     ) -> Result<(), Error> {
         if minify {
             let contents = contents.as_ref();
-            let contents = if resource.extension() == Some(&OsStr::new("css")) {
+            let contents = if resource.extension() == Some(OsStr::new("css")) {
                 minifier::css::minify(contents).map_err(|e| {
                     Error::new(format!("failed to minify CSS file: {}", e), resource.path(self))
                 })?
@@ -455,10 +456,10 @@ fn to_json_string(&self) -> String {
         let dst = cx.dst.join(&format!("source-files{}.js", cx.shared.resource_suffix));
         let make_sources = || {
             let (mut all_sources, _krates) =
-                try_err!(collect(&dst, &krate.name.as_str(), "sourcesIndex"), &dst);
+                try_err!(collect(&dst, &krate.name(cx.tcx()).as_str(), "sourcesIndex"), &dst);
             all_sources.push(format!(
                 "sourcesIndex[\"{}\"] = {};",
-                &krate.name,
+                &krate.name(cx.tcx()),
                 hierarchy.to_json_string()
             ));
             all_sources.sort();
@@ -473,9 +474,10 @@ fn to_json_string(&self) -> String {
 
     // Update the search index and crate list.
     let dst = cx.dst.join(&format!("search-index{}.js", cx.shared.resource_suffix));
-    let (mut all_indexes, mut krates) = try_err!(collect_json(&dst, &krate.name.as_str()), &dst);
+    let (mut all_indexes, mut krates) =
+        try_err!(collect_json(&dst, &krate.name(cx.tcx()).as_str()), &dst);
     all_indexes.push(search_index);
-    krates.push(krate.name.to_string());
+    krates.push(krate.name(cx.tcx()).to_string());
     krates.sort();
 
     // Sort the indexes by crate so the file will be generated identically even
@@ -583,7 +585,7 @@ struct Implementor {
                 } else {
                     Some(Implementor {
                         text: imp.inner_impl().print(false, cx).to_string(),
-                        synthetic: imp.inner_impl().synthetic,
+                        synthetic: imp.inner_impl().kind.is_auto(),
                         types: collect_paths_for_type(imp.inner_impl().for_.clone(), cache),
                     })
                 }
@@ -599,7 +601,7 @@ struct Implementor {
 
         let implementors = format!(
             r#"implementors["{}"] = {};"#,
-            krate.name,
+            krate.name(cx.tcx()),
             serde_json::to_string(&implementors).unwrap()
         );
 
@@ -611,7 +613,7 @@ struct Implementor {
         mydst.push(&format!("{}.{}.js", remote_item_type, remote_path[remote_path.len() - 1]));
 
         let (mut all_implementors, _) =
-            try_err!(collect(&mydst, &krate.name.as_str(), "implementors"), &mydst);
+            try_err!(collect(&mydst, &krate.name(cx.tcx()).as_str(), "implementors"), &mydst);
         all_implementors.push(implementors);
         // Sort the implementors by crate so the file will be generated
         // identically even with rustdoc running in parallel.
index ffefc5450cd730c594393dc3d050089e73084861..c8e93374e63ccd7abf8827a15c5e03cf31ef363d 100644 (file)
@@ -1,11 +1,11 @@
 use crate::clean;
 use crate::docfs::PathError;
 use crate::error::Error;
-use crate::fold::DocFolder;
 use crate::html::format::Buffer;
 use crate::html::highlight;
 use crate::html::layout;
 use crate::html::render::{Context, BASIC_KEYWORDS};
+use crate::visit::DocVisitor;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::ty::TyCtxt;
 use std::fs;
 use std::path::{Component, Path, PathBuf};
 
-crate fn render(cx: &mut Context<'_>, krate: clean::Crate) -> Result<clean::Crate, Error> {
+crate fn render(cx: &mut Context<'_>, krate: &clean::Crate) -> Result<(), Error> {
     info!("emitting source files");
-    let dst = cx.dst.join("src").join(&*krate.name.as_str());
+
+    let dst = cx.dst.join("src").join(&*krate.name(cx.tcx()).as_str());
     cx.shared.ensure_dir(&dst)?;
-    let mut folder = SourceCollector { dst, cx, emitted_local_sources: FxHashSet::default() };
-    Ok(folder.fold_crate(krate))
+
+    let mut collector = SourceCollector { dst, cx, emitted_local_sources: FxHashSet::default() };
+    collector.visit_crate(krate);
+    Ok(())
 }
 
 crate fn collect_local_sources<'tcx>(
     tcx: TyCtxt<'tcx>,
     src_root: &Path,
-    krate: clean::Crate,
-) -> (clean::Crate, FxHashMap<PathBuf, String>) {
+    krate: &clean::Crate,
+) -> FxHashMap<PathBuf, String> {
     let mut lsc = LocalSourcesCollector { tcx, local_sources: FxHashMap::default(), src_root };
-
-    let krate = lsc.fold_crate(krate);
-    (krate, lsc.local_sources)
+    lsc.visit_crate(krate);
+    lsc.local_sources
 }
 
 struct LocalSourcesCollector<'a, 'tcx> {
@@ -42,7 +44,7 @@ struct LocalSourcesCollector<'a, 'tcx> {
 }
 
 fn is_real_and_local(span: clean::Span, sess: &Session) -> bool {
-    span.filename(sess).is_real() && span.cnum(sess) == LOCAL_CRATE
+    span.cnum(sess) == LOCAL_CRATE && span.filename(sess).is_real()
 }
 
 impl LocalSourcesCollector<'_, '_> {
@@ -54,12 +56,13 @@ fn add_local_source(&mut self, item: &clean::Item) {
             return;
         }
         let filename = span.filename(sess);
-        let p = match filename {
-            FileName::Real(ref file) => match file.local_path() {
-                Some(p) => p.to_path_buf(),
-                _ => return,
-            },
-            _ => return,
+        let p = if let FileName::Real(file) = filename {
+            match file.into_local_path() {
+                Some(p) => p,
+                None => return,
+            }
+        } else {
+            return;
         };
         if self.local_sources.contains_key(&*p) {
             // We've already emitted this source
@@ -67,7 +70,7 @@ fn add_local_source(&mut self, item: &clean::Item) {
         }
 
         let mut href = String::new();
-        clean_path(&self.src_root, &p, false, |component| {
+        clean_path(self.src_root, &p, false, |component| {
             href.push_str(&component.to_string_lossy());
             href.push('/');
         });
@@ -79,13 +82,11 @@ fn add_local_source(&mut self, item: &clean::Item) {
     }
 }
 
-impl DocFolder for LocalSourcesCollector<'_, '_> {
-    fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
-        self.add_local_source(&item);
+impl DocVisitor for LocalSourcesCollector<'_, '_> {
+    fn visit_item(&mut self, item: &clean::Item) {
+        self.add_local_source(item);
 
-        // FIXME: if `include_sources` isn't set and DocFolder didn't require consuming the crate by value,
-        // we could return None here without having to walk the rest of the crate.
-        Some(self.fold_item_recur(item))
+        self.visit_item_recur(item)
     }
 }
 
@@ -98,8 +99,12 @@ struct SourceCollector<'a, 'tcx> {
     emitted_local_sources: FxHashSet<PathBuf>,
 }
 
-impl DocFolder for SourceCollector<'_, '_> {
-    fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
+impl DocVisitor for SourceCollector<'_, '_> {
+    fn visit_item(&mut self, item: &clean::Item) {
+        if !self.cx.include_sources {
+            return;
+        }
+
         let tcx = self.cx.tcx();
         let span = item.span(tcx);
         let sess = tcx.sess;
@@ -107,7 +112,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
         // If we're not rendering sources, there's nothing to do.
         // If we're including source files, and we haven't seen this file yet,
         // then we need to render it out to the filesystem.
-        if self.cx.include_sources && is_real_and_local(span, sess) {
+        if is_real_and_local(span, sess) {
             let filename = span.filename(sess);
             let span = span.inner();
             let pos = sess.source_map().lookup_source_file(span.lo());
@@ -132,9 +137,8 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                 }
             };
         }
-        // FIXME: if `include_sources` isn't set and DocFolder didn't require consuming the crate by value,
-        // we could return None here without having to walk the rest of the crate.
-        Some(self.fold_item_recur(item))
+
+        self.visit_item_recur(item)
     }
 }
 
@@ -168,7 +172,7 @@ fn emit_source(
         };
 
         // Remove the utf-8 BOM if any
-        let contents = if contents.starts_with('\u{feff}') { &contents[3..] } else { &contents };
+        let contents = contents.strip_prefix('\u{feff}').unwrap_or(&contents);
 
         // Create the intermediate directories
         let mut cur = self.dst.clone();
@@ -209,7 +213,7 @@ fn emit_source(
                     contents,
                     self.cx.shared.edition(),
                     file_span,
-                    &self.cx,
+                    self.cx,
                     &root_path,
                     None,
                     SourceContext::Standalone,
index 0a196edd53b1dd063900a27a45a598e8e49be2f8..37ea7b000339f0de6d57ed9b62afc5298eaa6f5d 100644 (file)
@@ -13,3 +13,12 @@ rules.
        /* It requires JS to work so no need to display it in this case. */
        display: none;
 }
+
+.sub {
+       /* The search bar and related controls don't work without JS */
+       display: none;
+}
+
+#theme-picker {
+       display: none;
+}
index 6c908a21c39adacb097ccce682d9c2b5ec9f028a..89a763ef6d707fbf79a7117e261c4f4102230e74 100644 (file)
 
 /* Avoid using legacy CJK serif fonts in Windows like Batang. */
 @font-face {
-       font-family: 'Noto Sans KR';
-       src: url("noto-sans-kr-regular.woff2") format("woff2"),
-               url("noto-sans-kr-regular.woff") format("woff");
+       font-family: 'NanumBarunGothic';
+       src: url("NanumBarunGothic.ttf.woff2") format("woff2"),
+               url("NanumBarunGothic.ttf.woff") format("woff");
        font-display: swap;
-       unicode-range: U+AC00-D7AF, U+3130-318F, U+1100-11FF, U+A960-A97F, U+D7B0-D7FF;
+       unicode-range: U+AC00-D7AF, U+1100-11FF, U+3130-318F, U+A960-A97F, U+D7B0-D7FF;
 }
 
 * {
@@ -108,7 +108,7 @@ html {
 /* General structure and fonts */
 
 body {
-       font: 16px/1.4 "Source Serif 4", "Noto Sans KR", serif;
+       font: 16px/1.4 "Source Serif 4", NanumBarunGothic, serif;
        margin: 0;
        position: relative;
        padding: 10px 15px 20px 15px;
@@ -134,7 +134,7 @@ h1, h2, h3, h4 {
        margin: 20px 0 15px 0;
        padding-bottom: 6px;
 }
-h5, h6 {
+.docblock h3, .docblock h4, h5, h6 {
        margin: 15px 0 5px 0;
 }
 h1.fqn {
@@ -149,7 +149,15 @@ h1.fqn {
 h1.fqn > .in-band > a:hover {
        text-decoration: underline;
 }
-h2, h3, h4 {
+/* The only headings that get underlines are:
+        Markdown-generated headings within the top-doc
+        Rustdoc-generated h2 section headings (e.g. "Implementations", "Required Methods", etc)
+       Underlines elsewhere in the documentation break up visual flow and tend to invert
+       section hierarchies. */
+h2,
+.top-doc h3,
+.top-doc h4,
+.sidebar .others h3 {
        border-bottom: 1px solid;
 }
 h3.code-header {
@@ -196,7 +204,7 @@ div.impl-items > div:not(.docblock):not(.item-info),
 .content ul.crate a.crate, a.srclink,
 /* This selector is for the items listed in the "all items" page. */
 #main > ul.docblock > li > a {
-       font-family: "Fira Sans", Arial, sans-serif;
+       font-family: "Fira Sans", Arial, NanumBarunGothic, sans-serif;
 }
 
 .content ul.crate a.crate {
@@ -532,7 +540,7 @@ nav.sub {
        position: relative;
 }
 
-.docblock > * {
+.docblock > :not(.information) {
        max-width: 100%;
        overflow-x: auto;
 }
index f9c84dc3e318dc9e5023131c8c76e39143eb65b3..ba7fb3b5456a55425d76939bab0e56775f9da13e 100644 (file)
@@ -255,10 +255,6 @@ details.undocumented > summary::before {
        box-shadow: 0 0 0 1px #148099,0 0 0 2px transparent;
 }
 
-.search-input:disabled {
-       background-color: #3e3e3e;
-}
-
 .module-item .stab,
 .import-item .stab {
        color: #000;
index 9a38277d55905ca7a56e8b79b4d134c0059da7a8..77ac217e6f41dd9f76efc9b9c298ab4bc38d2889 100644 (file)
@@ -219,10 +219,6 @@ details.undocumented > summary::before {
        border-color: #008dfd;
 }
 
-.search-input:disabled {
-       background-color: #c5c4c4;
-}
-
 #crate-search + .search-input:focus {
        box-shadow: 0 0 8px 4px #078dd8;
 }
index fba8231caac31188420629851af0a03176b03768..6df137e39141508a88674a94a53c516efc79d9f1 100644 (file)
@@ -209,10 +209,6 @@ details.undocumented > summary::before {
        border-color: #66afe9;
 }
 
-.search-input:disabled {
-       background-color: #e6e6e6;
-}
-
 #crate-search + .search-input:focus {
        box-shadow: 0 0 8px #078dd8;
 }
diff --git a/src/librustdoc/html/static/fonts/NanumBarunGothic-LICENSE.txt b/src/librustdoc/html/static/fonts/NanumBarunGothic-LICENSE.txt
new file mode 100644 (file)
index 0000000..0bf4668
--- /dev/null
@@ -0,0 +1,99 @@
+Copyright (c) 2010, NAVER Corporation (https://www.navercorp.com/),
+
+with Reserved Font Name Nanum, Naver Nanum, NanumGothic, Naver NanumGothic,
+NanumMyeongjo, Naver NanumMyeongjo, NanumBrush, Naver NanumBrush, NanumPen,
+Naver NanumPen, Naver NanumGothicEco, NanumGothicEco, Naver NanumMyeongjoEco,
+NanumMyeongjoEco, Naver NanumGothicLight, NanumGothicLight, NanumBarunGothic,
+Naver NanumBarunGothic, NanumSquareRound, NanumBarunPen, MaruBuri
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/src/librustdoc/html/static/fonts/NanumBarunGothic.ttf.woff b/src/librustdoc/html/static/fonts/NanumBarunGothic.ttf.woff
new file mode 100644 (file)
index 0000000..fb063e8
Binary files /dev/null and b/src/librustdoc/html/static/fonts/NanumBarunGothic.ttf.woff differ
diff --git a/src/librustdoc/html/static/fonts/NanumBarunGothic.ttf.woff2 b/src/librustdoc/html/static/fonts/NanumBarunGothic.ttf.woff2
new file mode 100644 (file)
index 0000000..1866ad4
Binary files /dev/null and b/src/librustdoc/html/static/fonts/NanumBarunGothic.ttf.woff2 differ
diff --git a/src/librustdoc/html/static/fonts/noto-sans-kr-LICENSE.txt b/src/librustdoc/html/static/fonts/noto-sans-kr-LICENSE.txt
deleted file mode 100644 (file)
index 922d5fd..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-Copyright 2014, 2015 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.
-
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-
-This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
-
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font creation
-efforts of academic and linguistic communities, and to provide a free and
-open framework in which fonts may be shared and improved in partnership
-with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded,
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply
-to any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software components as
-distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to, deleting,
-or substituting -- in part or in whole -- any of the components of the
-Original Version, by changing formats or by porting the Font Software to a
-new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION & CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed, modify,
-redistribute, and sell modified and unmodified copies of the Font
-Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components,
-in Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the corresponding
-Copyright Holder. This restriction only applies to the primary font name as
-presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created
-using the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/src/librustdoc/html/static/fonts/noto-sans-kr-regular.woff b/src/librustdoc/html/static/fonts/noto-sans-kr-regular.woff
deleted file mode 100644 (file)
index 65e939c..0000000
Binary files a/src/librustdoc/html/static/fonts/noto-sans-kr-regular.woff and /dev/null differ
diff --git a/src/librustdoc/html/static/fonts/noto-sans-kr-regular.woff2 b/src/librustdoc/html/static/fonts/noto-sans-kr-regular.woff2
deleted file mode 100644 (file)
index 8126492..0000000
Binary files a/src/librustdoc/html/static/fonts/noto-sans-kr-regular.woff2 and /dev/null differ
index e396fd9d288db1cc34da37279113f4a65683b0c7..4b55a0a69b66358c2987337484c50e9e76cfd338 100644 (file)
@@ -263,7 +263,9 @@ function hideThemeButtonState() {
                 search_input.placeholder = searchState.input.origPlaceholder;
             });
 
-            search_input.removeAttribute('disabled');
+            if (search_input.value != '') {
+                loadSearch();
+            }
 
             // `crates{version}.js` should always be loaded before this script, so we can use it
             // safely.
@@ -564,6 +566,7 @@ function hideThemeButtonState() {
     // delayed sidebar rendering.
     window.initSidebarItems = function(items) {
         var sidebar = document.getElementsByClassName("sidebar-elems")[0];
+        var others;
         var current = window.sidebarCurrent;
 
         function addSidebarCrates(crates) {
@@ -592,7 +595,7 @@ function hideThemeButtonState() {
                 li.appendChild(link);
                 ul.appendChild(li);
             }
-            sidebar.appendChild(div);
+            others.appendChild(div);
         }
 
         function block(shortty, longty) {
@@ -633,10 +636,14 @@ function hideThemeButtonState() {
                 ul.appendChild(li);
             }
             div.appendChild(ul);
-            sidebar.appendChild(div);
+            others.appendChild(div);
         }
 
         if (sidebar) {
+            others = document.createElement("div");
+            others.className = "others";
+            sidebar.appendChild(others);
+
             var isModule = hasClass(document.body, "mod");
             if (!isModule) {
                 block("primitive", "Primitive Types");
index 5eb545f758247788aac28d2977098492699d3571..c2ea54abd2ea8390743b1af965dc9b3d17a02ca6 100644 (file)
@@ -299,10 +299,10 @@ window.initSearch = function(rawSearchIndex) {
                     var elems = Object.create(null);
                     var elength = obj[GENERICS_DATA].length;
                     for (var x = 0; x < elength; ++x) {
-                        if (!elems[obj[GENERICS_DATA][x]]) {
-                            elems[obj[GENERICS_DATA][x]] = 0;
+                        if (!elems[obj[GENERICS_DATA][x][NAME]]) {
+                            elems[obj[GENERICS_DATA][x][NAME]] = 0;
                         }
-                        elems[obj[GENERICS_DATA][x]] += 1;
+                        elems[obj[GENERICS_DATA][x][NAME]] += 1;
                     }
                     var total = 0;
                     var done = 0;
@@ -345,6 +345,7 @@ window.initSearch = function(rawSearchIndex) {
         // Check for type name and type generics (if any).
         function checkType(obj, val, literalSearch) {
             var lev_distance = MAX_LEV_DISTANCE + 1;
+            var tmp_lev = MAX_LEV_DISTANCE + 1;
             var len, x, firstGeneric;
             if (obj[NAME] === val.name) {
                 if (literalSearch) {
@@ -354,10 +355,10 @@ window.initSearch = function(rawSearchIndex) {
                             var elems = Object.create(null);
                             len = obj[GENERICS_DATA].length;
                             for (x = 0; x < len; ++x) {
-                                if (!elems[obj[GENERICS_DATA][x]]) {
-                                    elems[obj[GENERICS_DATA][x]] = 0;
+                                if (!elems[obj[GENERICS_DATA][x][NAME]]) {
+                                    elems[obj[GENERICS_DATA][x][NAME]] = 0;
                                 }
-                                elems[obj[GENERICS_DATA][x]] += 1;
+                                elems[obj[GENERICS_DATA][x][NAME]] += 1;
                             }
 
                             var allFound = true;
@@ -382,7 +383,7 @@ window.initSearch = function(rawSearchIndex) {
                     // If the type has generics but don't match, then it won't return at this point.
                     // Otherwise, `checkGenerics` will return 0 and it'll return.
                     if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length !== 0) {
-                        var tmp_lev = checkGenerics(obj, val);
+                        tmp_lev = checkGenerics(obj, val);
                         if (tmp_lev <= MAX_LEV_DISTANCE) {
                             return tmp_lev;
                         }
@@ -392,8 +393,8 @@ window.initSearch = function(rawSearchIndex) {
                 if ((!val.generics || val.generics.length === 0) &&
                       obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
                     return obj[GENERICS_DATA].some(
-                        function(name) {
-                            return name === val.name;
+                        function(gen) {
+                            return gen[NAME] === val.name;
                         });
                 }
                 return false;
@@ -404,17 +405,27 @@ window.initSearch = function(rawSearchIndex) {
                 // a levenshtein distance value that isn't *this* good so it goes
                 // into the search results but not too high.
                 lev_distance = Math.ceil((checkGenerics(obj, val) + lev_distance) / 2);
-            } else if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
+            }
+            if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
                 // We can check if the type we're looking for is inside the generics!
                 var olength = obj[GENERICS_DATA].length;
                 for (x = 0; x < olength; ++x) {
-                    lev_distance = Math.min(levenshtein(obj[GENERICS_DATA][x], val.name),
-                                            lev_distance);
+                    tmp_lev = Math.min(levenshtein(obj[GENERICS_DATA][x][NAME], val.name), tmp_lev);
+                }
+                if (tmp_lev !== 0) {
+                    // If we didn't find a good enough result, we go check inside the generics of
+                    // the generics.
+                    for (x = 0; x < olength && tmp_lev !== 0; ++x) {
+                        tmp_lev = Math.min(
+                            checkType(obj[GENERICS_DATA][x], val, literalSearch),
+                            tmp_lev
+                        );
+                    }
                 }
             }
             // Now whatever happens, the returned distance is "less good" so we should mark it
             // as such, and so we add 1 to the distance to make it "less good".
-            return lev_distance + 1;
+            return Math.min(lev_distance, tmp_lev) + 1;
         }
 
         function findArg(obj, val, literalSearch, typeFilter) {
index 9029933ad100ed67a6686327356a34edc8ebc124..56c5399d074b64c8f5479416a6f1a90a5ce020ec 100644 (file)
     crate static LICENSE: &[u8] = include_bytes!("static/fonts/SourceCodePro-LICENSE.txt");
 }
 
-crate mod noto_sans_kr {
-    /// The file `noto-sans-kr.woff`, the Regular variant of the Noto Sans KR font.
-    crate static REGULAR: &[u8] = include_bytes!("static/fonts/noto-sans-kr-regular.woff");
-
-    /// The file `noto-sans-kr.woff2`, the Regular variant of the Noto Sans KR font.
-    crate static REGULAR2: &[u8] = include_bytes!("static/fonts/noto-sans-kr-regular.woff2");
-
-    /// The file `noto-sans-kr-LICENSE.txt`, the license text of the Noto Sans KR font.
-    crate static LICENSE: &[u8] = include_bytes!("static/fonts/noto-sans-kr-LICENSE.txt");
+/// Files related to the Nanum Barun Gothic font.
+///
+/// These files are used to avoid some legacy CJK serif fonts in Windows.
+///
+/// Note that the Noto Sans KR font, which was used previously but was not very readable on Windows,
+/// has been replaced by the Nanum Barun Gothic font. This is due to Windows' implementation of font
+/// rendering that distorts OpenType fonts too much.
+///
+/// The font files were generated with these commands:
+///
+/// ```sh
+/// pyftsubset NanumBarunGothic.ttf \
+/// --unicodes=U+AC00-D7AF,U+1100-11FF,U+3130-318F,U+A960-A97F,U+D7B0-D7FF \
+/// --output-file=NanumBarunGothic.ttf.woff --flavor=woff
+/// ```
+/// ```sh
+/// pyftsubset NanumBarunGothic.ttf \
+/// --unicodes=U+AC00-D7AF,U+1100-11FF,U+3130-318F,U+A960-A97F,U+D7B0-D7FF \
+/// --output-file=NanumBarunGothic.ttf.woff2 --flavor=woff2
+/// ```
+crate mod nanum_barun_gothic {
+    /// The file `NanumBarunGothic.ttf.woff`, the Regular variant of the Nanum Barun Gothic font.
+    crate static REGULAR: &[u8] = include_bytes!("static/fonts/NanumBarunGothic.ttf.woff");
+
+    /// The file `NanumBarunGothic.ttf.woff2`, the Regular variant of the Nanum Barun Gothic font.
+    crate static REGULAR2: &[u8] = include_bytes!("static/fonts/NanumBarunGothic.ttf.woff2");
+
+    /// The file `NanumBarunGothic-LICENSE.txt`, the license text of the Nanum Barun Gothic font.
+    crate static LICENSE: &[u8] = include_bytes!("static/fonts/NanumBarunGothic-LICENSE.txt");
 }
 
 /// Files related to the sidebar in rustdoc sources.
index b0174d59a7be21463e999fccd92f968c8a9c066d..9fafea6914524ad3f8cb6ab503f179a5fbf797d6 100644 (file)
@@ -85,7 +85,6 @@
                     <input {# -#}
                         class="search-input" {# -#}
                         name="search" {# -#}
-                        disabled {# -#}
                         autocomplete="off" {# -#}
                         spellcheck="false" {# -#}
                         placeholder="Click or press ‘S’ to search, ‘?’ for more options…" {# -#}
          data-search-js="{{static_root_path | safe}}search{{page.resource_suffix}}.js"> {#- -#}
     </div>
     <script src="{{static_root_path | safe}}main{{page.resource_suffix}}.js"></script> {#- -#}
-    {%- if layout.scrape_examples_extension -%}
-    <script src="{{static_root_path | safe}}scrape-examples{{page.resource_suffix}}.js"></script> {#- -#}
-    {%- endif -%}
     {%- for script in page.static_extra_scripts -%}
     <script src="{{static_root_path | safe}}{{script}}.js"></script> {#- -#}
     {% endfor %}
+    {%- if layout.scrape_examples_extension -%}
+    <script src="{{page.root_path | safe}}scrape-examples{{page.resource_suffix}}.js"></script> {#- -#}
+    {%- endif -%}
     {%- for script in page.extra_scripts -%}
     <script src="{{page.root_path | safe}}{{script}}.js"></script> {#- -#}
     {% endfor %}
index 924275dc1858885bd7e7a2cb6d6ef148d101479d..a46518ef489aa1b3bc1a53d38ad358800826b1ce 100644 (file)
@@ -9,7 +9,7 @@
 
 use rustc_ast::ast;
 use rustc_hir::{def::CtorKind, def_id::DefId};
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::def_id::CRATE_DEF_INDEX;
 use rustc_span::Pos;
 
@@ -412,7 +412,7 @@ fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
                         .map(|t| {
                             clean::GenericBound::TraitBound(t, rustc_hir::TraitBoundModifier::None)
                         })
-                        .chain(lt.into_iter().map(|lt| clean::GenericBound::Outlives(lt)))
+                        .chain(lt.map(clean::GenericBound::Outlives))
                         .map(|bound| bound.into_tcx(tcx))
                         .collect(),
                 }
@@ -500,22 +500,22 @@ fn from_tcx(trait_: clean::Trait, tcx: TyCtxt<'_>) -> Self {
 impl FromWithTcx<clean::Impl> for Impl {
     fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self {
         let provided_trait_methods = impl_.provided_trait_methods(tcx);
-        let clean::Impl {
-            unsafety,
-            generics,
-            trait_,
-            for_,
-            items,
-            negative_polarity,
-            synthetic,
-            blanket_impl,
-            span: _span,
-        } = impl_;
+        let clean::Impl { unsafety, generics, trait_, for_, items, polarity, kind } = impl_;
         // FIXME: should `trait_` be a clean::Path equivalent in JSON?
         let trait_ = trait_.map(|path| {
             let did = path.def_id();
             clean::ResolvedPath { path, did }.into_tcx(tcx)
         });
+        // FIXME: use something like ImplKind in JSON?
+        let (synthetic, blanket_impl) = match kind {
+            clean::ImplKind::Normal => (false, None),
+            clean::ImplKind::Auto => (true, None),
+            clean::ImplKind::Blanket(ty) => (false, Some(*ty)),
+        };
+        let negative_polarity = match polarity {
+            ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => false,
+            ty::ImplPolarity::Negative => true,
+        };
         Impl {
             is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe,
             generics: generics.into_tcx(tcx),
@@ -528,7 +528,7 @@ fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self {
             items: ids(items),
             negative: negative_polarity,
             synthetic,
-            blanket_impl: blanket_impl.map(|x| (*x).into_tcx(tcx)),
+            blanket_impl: blanket_impl.map(|x| x.into_tcx(tcx)),
         }
     }
 }
@@ -697,6 +697,7 @@ fn from_tcx(kind: ItemType, _tcx: TyCtxt<'_>) -> Self {
             TraitAlias => ItemKind::TraitAlias,
             ProcAttribute => ItemKind::ProcAttribute,
             ProcDerive => ItemKind::ProcDerive,
+            Generic => unreachable!(),
         }
     }
 }
index 17e00e4b66271a181233ba78867bb8531c4db50a..fb252a9c73934b1d243008634dc1caf02da0c047 100644 (file)
@@ -9,6 +9,7 @@
 #![feature(control_flow_enum)]
 #![feature(box_syntax)]
 #![feature(in_band_lifetimes)]
+#![feature(let_else)]
 #![feature(nll)]
 #![feature(test)]
 #![feature(crate_visibility_modifier)]
@@ -103,17 +104,14 @@ macro_rules! map {
     }}
 }
 
-#[macro_use]
-mod externalfiles;
-
 mod clean;
 mod config;
 mod core;
 mod docfs;
+mod doctest;
 mod doctree;
-#[macro_use]
 mod error;
-mod doctest;
+mod externalfiles;
 mod fold;
 mod formats;
 // used by the error-index generator, so it needs to be public
@@ -124,6 +122,7 @@ macro_rules! map {
 mod passes;
 mod scrape_examples;
 mod theme;
+mod visit;
 mod visit_ast;
 mod visit_lib;
 
@@ -775,9 +774,9 @@ fn main_options(options: config::Options) -> MainResult {
             // We need to hold on to the complete resolver, so we cause everything to be
             // cloned for the analysis passes to use. Suboptimal, but necessary in the
             // current architecture.
-            let resolver = core::create_resolver(queries, &sess);
+            let resolver = core::create_resolver(queries, sess);
 
-            if sess.has_errors() {
+            if sess.diagnostic().has_errors_or_lint_errors() {
                 sess.fatal("Compilation failed, aborting rustdoc");
             }
 
index 37faa6742927a2860a543ab97f36f5a42dd92ce7..4e146a07d154a64b3f8d99eedd4b419d8f61d3db 100644 (file)
@@ -1,8 +1,8 @@
 use super::Pass;
 use crate::clean::*;
 use crate::core::DocContext;
-use crate::fold::DocFolder;
 use crate::html::markdown::main_body_opts;
+use crate::visit::DocVisitor;
 use core::ops::Range;
 use pulldown_cmark::{Event, Parser, Tag};
 use regex::Regex;
@@ -39,7 +39,7 @@ fn find_raw_urls(
     ) {
         trace!("looking for raw urls in {}", text);
         // For now, we only check "full" URLs (meaning, starting with "http://" or "https://").
-        for match_ in URL_REGEX.find_iter(&text) {
+        for match_ in URL_REGEX.find_iter(text) {
             let url = match_.as_str();
             let url_range = match_.range();
             f(
@@ -53,16 +53,17 @@ fn find_raw_urls(
 }
 
 crate fn check_bare_urls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
-    BareUrlsLinter { cx }.fold_crate(krate)
+    BareUrlsLinter { cx }.visit_crate(&krate);
+    krate
 }
 
-impl<'a, 'tcx> DocFolder for BareUrlsLinter<'a, 'tcx> {
-    fn fold_item(&mut self, item: Item) -> Option<Item> {
+impl<'a, 'tcx> DocVisitor for BareUrlsLinter<'a, 'tcx> {
+    fn visit_item(&mut self, item: &Item) {
         let hir_id = match DocContext::as_local_hir_id(self.cx.tcx, item.def_id) {
             Some(hir_id) => hir_id,
             None => {
                 // If non-local, no need to check anything.
-                return Some(self.fold_item_recur(item));
+                return;
             }
         };
         let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
@@ -106,6 +107,6 @@ fn fold_item(&mut self, item: Item) -> Option<Item> {
             }
         }
 
-        Some(self.fold_item_recur(item))
+        self.visit_item_recur(item)
     }
 }
index 5e3bd41b85c7e060c89d94eb829a30f717f7b1c6..85542ebd9ac559f4c5ddcfc546bdc34b893bcac8 100644 (file)
@@ -1,9 +1,9 @@
 use crate::clean;
 use crate::core::DocContext;
-use crate::fold::{self, DocFolder};
 use crate::html::markdown::{find_testable_code, ErrorCodes};
 use crate::passes::check_doc_test_visibility::{should_have_doc_example, Tests};
 use crate::passes::Pass;
+use crate::visit::DocVisitor;
 use rustc_hir as hir;
 use rustc_lint::builtin::MISSING_DOCS;
 use rustc_middle::lint::LintLevelSource;
@@ -23,7 +23,7 @@
 
 fn calculate_doc_coverage(krate: clean::Crate, ctx: &mut DocContext<'_>) -> clean::Crate {
     let mut calc = CoverageCalculator { items: Default::default(), ctx };
-    let krate = calc.fold_crate(krate);
+    calc.visit_crate(&krate);
 
     calc.print_results();
 
@@ -182,17 +182,18 @@ fn print_table_record(
     }
 }
 
-impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> {
-    fn fold_item(&mut self, i: clean::Item) -> Option<clean::Item> {
+impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> {
+    fn visit_item(&mut self, i: &clean::Item) {
+        if !i.def_id.is_local() {
+            // non-local items are skipped because they can be out of the users control,
+            // especially in the case of trait impls, which rustdoc eagerly inlines
+            return;
+        }
+
         match *i.kind {
-            _ if !i.def_id.is_local() => {
-                // non-local items are skipped because they can be out of the users control,
-                // especially in the case of trait impls, which rustdoc eagerly inlines
-                return Some(i);
-            }
             clean::StrippedItem(..) => {
                 // don't count items in stripped modules
-                return Some(i);
+                return;
             }
             // docs on `use` and `extern crate` statements are not displayed, so they're not
             // worth counting
@@ -269,6 +270,6 @@ fn fold_item(&mut self, i: clean::Item) -> Option<clean::Item> {
             }
         }
 
-        Some(self.fold_item_recur(i))
+        self.visit_item_recur(i)
     }
 }
index d2b3c5239c778f4b5c83b1b327e8e95b5a810f33..fd2ab0dc97cb2230373a3cfb9832eb6400170336 100644 (file)
@@ -8,9 +8,9 @@
 
 use crate::clean;
 use crate::core::DocContext;
-use crate::fold::DocFolder;
 use crate::html::markdown::{self, RustCodeBlock};
 use crate::passes::Pass;
+use crate::visit::DocVisitor;
 
 crate const CHECK_CODE_BLOCK_SYNTAX: Pass = Pass {
     name: "check-code-block-syntax",
@@ -19,7 +19,8 @@
 };
 
 crate fn check_code_block_syntax(krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate {
-    SyntaxChecker { cx }.fold_crate(krate)
+    SyntaxChecker { cx }.visit_crate(&krate);
+    krate
 }
 
 struct SyntaxChecker<'a, 'tcx> {
@@ -36,7 +37,7 @@ fn check_rust_syntax(&self, item: &clean::Item, dox: &str, code_block: RustCodeB
         let source = dox[code_block.code].to_owned();
         let sess = ParseSess::with_span_handler(handler, sm);
 
-        let edition = code_block.lang_string.edition.unwrap_or(self.cx.tcx.sess.edition());
+        let edition = code_block.lang_string.edition.unwrap_or_else(|| self.cx.tcx.sess.edition());
         let expn_data = ExpnData::default(
             ExpnKind::AstPass(AstPass::TestHarness),
             DUMMY_SP,
@@ -77,7 +78,7 @@ fn check_rust_syntax(&self, item: &clean::Item, dox: &str, code_block: RustCodeB
         // The span and whether it is precise or not.
         let (sp, precise_span) = match super::source_span_for_markdown_range(
             self.cx.tcx,
-            &dox,
+            dox,
             &code_block.range,
             &item.attrs,
         ) {
@@ -123,7 +124,7 @@ fn check_rust_syntax(&self, item: &clean::Item, dox: &str, code_block: RustCodeB
 
             // FIXME(#67563): Provide more context for these errors by displaying the spans inline.
             for message in buffer.messages.iter() {
-                diag.note(&message);
+                diag.note(message);
             }
 
             diag.emit();
@@ -141,8 +142,8 @@ fn check_rust_syntax(&self, item: &clean::Item, dox: &str, code_block: RustCodeB
     }
 }
 
-impl<'a, 'tcx> DocFolder for SyntaxChecker<'a, 'tcx> {
-    fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
+impl<'a, 'tcx> DocVisitor for SyntaxChecker<'a, 'tcx> {
+    fn visit_item(&mut self, item: &clean::Item) {
         if let Some(dox) = &item.attrs.collapsed_doc_value() {
             let sp = item.attr_span(self.cx.tcx);
             let extra = crate::html::markdown::ExtraInfo::new_did(
@@ -150,12 +151,12 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                 item.def_id.expect_def_id(),
                 sp,
             );
-            for code_block in markdown::rust_code_blocks(&dox, &extra) {
-                self.check_rust_syntax(&item, &dox, code_block);
+            for code_block in markdown::rust_code_blocks(dox, &extra) {
+                self.check_rust_syntax(&item, dox, code_block);
             }
         }
 
-        Some(self.fold_item_recur(item))
+        self.visit_item_recur(item)
     }
 }
 
index 1f7d6054233dd987b5bb8e0f05b858d3b7791226..7d3010cf3325b327c03f2b67b93d2c7190de34eb 100644 (file)
@@ -7,8 +7,8 @@
 use crate::clean;
 use crate::clean::*;
 use crate::core::DocContext;
-use crate::fold::DocFolder;
 use crate::html::markdown::{find_testable_code, ErrorCodes, Ignore, LangString};
+use crate::visit::DocVisitor;
 use crate::visit_ast::inherits_doc_hidden;
 use rustc_hir as hir;
 use rustc_middle::lint::LintLevelSource;
@@ -27,17 +27,17 @@ struct DocTestVisibilityLinter<'a, 'tcx> {
 
 crate fn check_doc_test_visibility(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
     let mut coll = DocTestVisibilityLinter { cx };
-
-    coll.fold_crate(krate)
+    coll.visit_crate(&krate);
+    krate
 }
 
-impl<'a, 'tcx> DocFolder for DocTestVisibilityLinter<'a, 'tcx> {
-    fn fold_item(&mut self, item: Item) -> Option<Item> {
+impl<'a, 'tcx> DocVisitor for DocTestVisibilityLinter<'a, 'tcx> {
+    fn visit_item(&mut self, item: &Item) {
         let dox = item.attrs.collapsed_doc_value().unwrap_or_else(String::new);
 
         look_for_tests(self.cx, &dox, &item);
 
-        Some(self.fold_item_recur(item))
+        self.visit_item_recur(item)
     }
 }
 
@@ -115,10 +115,10 @@ fn add_test(&mut self, _: String, config: LangString, _: usize) {
 
     let mut tests = Tests { found_tests: 0 };
 
-    find_testable_code(&dox, &mut tests, ErrorCodes::No, false, None);
+    find_testable_code(dox, &mut tests, ErrorCodes::No, false, None);
 
     if tests.found_tests == 0 && cx.tcx.sess.is_nightly_build() {
-        if should_have_doc_example(cx, &item) {
+        if should_have_doc_example(cx, item) {
             debug!("reporting error for {:?} (hir_id={:?})", item, hir_id);
             let sp = item.attr_span(cx.tcx);
             cx.tcx.struct_span_lint_hir(
index 318c897bcbdf6f1c395effdc447d09cd689f1a16..4e5812d7f8429e38a5a5f11042f5912b0a5ee0a4 100644 (file)
 
 use crate::clean::{self, utils::find_nearest_parent_module, Crate, Item, ItemLink, PrimitiveType};
 use crate::core::DocContext;
-use crate::fold::DocFolder;
 use crate::html::markdown::{markdown_links, MarkdownLink};
 use crate::lint::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS};
 use crate::passes::Pass;
+use crate::visit::DocVisitor;
 
 mod early;
 crate use early::load_intra_link_crates;
 };
 
 fn collect_intra_doc_links(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
-    LinkCollector {
+    let mut collector = LinkCollector {
         cx,
         mod_ids: Vec::new(),
         kind_side_channel: Cell::new(None),
         visited_links: FxHashMap::default(),
-    }
-    .fold_crate(krate)
+    };
+    collector.visit_crate(&krate);
+    krate
 }
 
 /// Top-level errors emitted by this pass.
@@ -289,7 +290,7 @@ fn variant_field(
     ) -> Result<(Res, Option<String>), ErrorKind<'path>> {
         let tcx = self.cx.tcx;
         let no_res = || ResolutionFailure::NotResolved {
-            module_id: module_id,
+            module_id,
             partial_res: None,
             unresolved: path_str.into(),
         };
@@ -437,7 +438,7 @@ fn resolve_macro(
     fn resolve_path(&self, path_str: &str, ns: Namespace, module_id: DefId) -> Option<Res> {
         let result = self.cx.enter_resolver(|resolver| {
             resolver
-                .resolve_str_path_error(DUMMY_SP, &path_str, ns, module_id)
+                .resolve_str_path_error(DUMMY_SP, path_str, ns, module_id)
                 .and_then(|(_, res)| res.try_into())
         });
         debug!("{} resolved to {:?} in namespace {:?}", path_str, result, ns);
@@ -543,7 +544,7 @@ fn def_id_to_res(&self, ty_id: DefId) -> Option<Res> {
             ty::Uint(uty) => Res::Primitive(uty.into()),
             ty::Float(fty) => Res::Primitive(fty.into()),
             ty::Str => Res::Primitive(Str),
-            ty::Tuple(ref tys) if tys.is_empty() => Res::Primitive(Unit),
+            ty::Tuple(tys) if tys.is_empty() => Res::Primitive(Unit),
             ty::Tuple(_) => Res::Primitive(Tuple),
             ty::Array(..) => Res::Primitive(Array),
             ty::Slice(_) => Res::Primitive(Slice),
@@ -816,8 +817,8 @@ fn is_derive_trait_collision<T>(ns: &PerNS<Result<(Res, T), ResolutionFailure<'_
     )
 }
 
-impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
-    fn fold_item(&mut self, item: Item) -> Option<Item> {
+impl<'a, 'tcx> DocVisitor for LinkCollector<'a, 'tcx> {
+    fn visit_item(&mut self, item: &Item) {
         use rustc_middle::ty::DefIdTree;
 
         let parent_node =
@@ -911,17 +912,16 @@ fn fold_item(&mut self, item: Item) -> Option<Item> {
             }
         }
 
-        Some(if item.is_mod() {
+        if item.is_mod() {
             if !inner_docs {
                 self.mod_ids.push(item.def_id.expect_def_id());
             }
 
-            let ret = self.fold_item_recur(item);
+            self.visit_item_recur(item);
             self.mod_ids.pop();
-            ret
         } else {
-            self.fold_item_recur(item)
-        })
+            self.visit_item_recur(item)
+        }
     }
 }
 
@@ -978,13 +978,13 @@ fn preprocess_link<'a>(
     }
 
     // Parse and strip the disambiguator from the link, if present.
-    let (disambiguator, path_str, link_text) = match Disambiguator::from_str(&link) {
+    let (disambiguator, path_str, link_text) = match Disambiguator::from_str(link) {
         Ok(Some((d, path, link_text))) => (Some(d), path.trim(), link_text.trim()),
         Ok(None) => (None, link.trim(), link.trim()),
         Err((err_msg, relative_range)) => {
             // Only report error if we would not have ignored this link. See issue #83859.
             if !should_ignore_link_with_disambiguators(link) {
-                let no_backticks_range = range_between_backticks(&ori_link);
+                let no_backticks_range = range_between_backticks(ori_link);
                 let disambiguator_range = (no_backticks_range.start + relative_range.start)
                     ..(no_backticks_range.start + relative_range.end);
                 return Some(Err(PreprocessingError::Disambiguator(disambiguator_range, err_msg)));
@@ -1000,7 +1000,7 @@ fn preprocess_link<'a>(
 
     // Strip generics from the path.
     let path_str = if path_str.contains(['<', '>'].as_slice()) {
-        match strip_generics_from_path(&path_str) {
+        match strip_generics_from_path(path_str) {
             Ok(path) => path,
             Err(err_kind) => {
                 debug!("link has malformed generics: {}", path_str);
@@ -1228,7 +1228,7 @@ fn resolve_link(
                 if self.cx.tcx.privacy_access_levels(()).is_exported(src_id)
                     && !self.cx.tcx.privacy_access_levels(()).is_exported(dst_id)
                 {
-                    privacy_error(self.cx, &diag_info, &path_str);
+                    privacy_error(self.cx, &diag_info, path_str);
                 }
             }
 
@@ -1766,8 +1766,8 @@ fn report_diagnostic(
 
         let span =
             super::source_span_for_markdown_range(tcx, dox, link_range, &item.attrs).map(|sp| {
-                if dox.bytes().nth(link_range.start) == Some(b'`')
-                    && dox.bytes().nth(link_range.end - 1) == Some(b'`')
+                if dox.as_bytes().get(link_range.start) == Some(&b'`')
+                    && dox.as_bytes().get(link_range.end - 1) == Some(&b'`')
                 {
                     sp.with_lo(sp.lo() + BytePos(1)).with_hi(sp.hi() - BytePos(1))
                 } else {
@@ -1868,8 +1868,7 @@ fn split(path: &str) -> Option<(&str, &str)> {
                         };
                         name = start;
                         for ns in [TypeNS, ValueNS, MacroNS] {
-                            if let Some(res) =
-                                collector.check_full_res(ns, &start, module_id, &None)
+                            if let Some(res) = collector.check_full_res(ns, start, module_id, &None)
                             {
                                 debug!("found partial_res={:?}", res);
                                 *partial_res = Some(res);
@@ -1938,7 +1937,8 @@ fn split(path: &str) -> Option<(&str, &str)> {
                             | Use
                             | LifetimeParam
                             | Ctor(_, _)
-                            | AnonConst => {
+                            | AnonConst
+                            | InlineConst => {
                                 let note = assoc_item_not_allowed(res);
                                 if let Some(span) = sp {
                                     diag.span_label(span, &note);
index cd90528ab9c8a9b6dd18040052680cb08ba4eef2..565bcb8bd1340c4763a24c33a800894f3c9f5f9a 100644 (file)
@@ -34,7 +34,7 @@ fn load_links_in_attrs(&mut self, attrs: &[ast::Attribute], span: Span) {
         let attrs = crate::clean::Attributes::from_ast(attrs, None);
         for (parent_module, doc) in attrs.collapsed_doc_value_by_module_level() {
             debug!(?doc);
-            for link in markdown_links(&doc.as_str()) {
+            for link in markdown_links(doc.as_str()) {
                 debug!(?link.link);
                 let path_str = if let Some(Ok(x)) = preprocess_link(&link) {
                     x.path_str
@@ -46,7 +46,7 @@ fn load_links_in_attrs(&mut self, attrs: &[ast::Attribute], span: Span) {
                         span,
                         &path_str,
                         TypeNS,
-                        parent_module.unwrap_or(self.current_mod.to_def_id()),
+                        parent_module.unwrap_or_else(|| self.current_mod.to_def_id()),
                     );
                 });
             }
index 319dd7b42b0ee69cb4d2d23d656f79188977aa82..ea50134f00d477c485322b5ef9c0f423a4086d4c 100644 (file)
@@ -1,9 +1,10 @@
 use super::Pass;
 use crate::clean::*;
 use crate::core::DocContext;
-use crate::fold::DocFolder;
+use crate::visit::DocVisitor;
 
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir::def_id::DefId;
 use rustc_middle::ty::DefIdTree;
 use rustc_span::symbol::sym;
 
     description: "retrieves trait impls for items in the crate",
 };
 
-crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
-    let (mut krate, synth_impls) = cx.sess().time("collect_synthetic_impls", || {
+crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate {
+    let synth_impls = cx.sess().time("collect_synthetic_impls", || {
         let mut synth = SyntheticImplCollector { cx, impls: Vec::new() };
-        (synth.fold_crate(krate), synth.impls)
+        synth.visit_crate(&krate);
+        synth.impls
     });
 
     let prims: FxHashSet<PrimitiveType> = krate.primitives.iter().map(|p| p.1).collect();
 
     let crate_items = {
         let mut coll = ItemCollector::new();
-        krate = cx.sess().time("collect_items_for_trait_impls", || coll.fold_crate(krate));
+        cx.sess().time("collect_items_for_trait_impls", || coll.visit_crate(&krate));
         coll.items
     };
 
@@ -31,9 +33,7 @@
 
     for &cnum in cx.tcx.crates(()).iter() {
         for &(did, _) in cx.tcx.all_trait_implementations(cnum).iter() {
-            cx.tcx.sess.prof.generic_activity("build_extern_trait_impl").run(|| {
-                inline::build_impl(cx, None, did, None, &mut new_items);
-            });
+            inline::build_impl(cx, None, did, None, &mut new_items);
         }
     }
 
     }
 
     let mut cleaner = BadImplStripper { prims, items: crate_items };
+    let mut type_did_to_deref_target: FxHashMap<DefId, &Type> = FxHashMap::default();
+
+    // Follow all `Deref` targets of included items and recursively add them as valid
+    fn add_deref_target(
+        map: &FxHashMap<DefId, &Type>,
+        cleaner: &mut BadImplStripper,
+        type_did: DefId,
+    ) {
+        if let Some(target) = map.get(&type_did) {
+            debug!("add_deref_target: type {:?}, target {:?}", type_did, target);
+            if let Some(target_prim) = target.primitive_type() {
+                cleaner.prims.insert(target_prim);
+            } else if let Some(target_did) = target.def_id_no_primitives() {
+                // `impl Deref<Target = S> for S`
+                if target_did == type_did {
+                    // Avoid infinite cycles
+                    return;
+                }
+                cleaner.items.insert(target_did.into());
+                add_deref_target(map, cleaner, target_did);
+            }
+        }
+    }
 
     // scan through included items ahead of time to splice in Deref targets to the "valid" sets
     for it in &new_items {
         if let ImplItem(Impl { ref for_, ref trait_, ref items, .. }) = *it.kind {
-            if cleaner.keep_impl(for_)
-                && trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait()
+            if trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait()
+                && cleaner.keep_impl(for_, true)
             {
                 let target = items
                     .iter()
 
                 if let Some(prim) = target.primitive_type() {
                     cleaner.prims.insert(prim);
-                } else if let Some(did) = target.def_id() {
+                } else if let Some(did) = target.def_id(&cx.cache) {
                     cleaner.items.insert(did.into());
                 }
+                if let Some(for_did) = for_.def_id_no_primitives() {
+                    if type_did_to_deref_target.insert(for_did, target).is_none() {
+                        // Since only the `DefId` portion of the `Type` instances is known to be same for both the
+                        // `Deref` target type and the impl for type positions, this map of types is keyed by
+                        // `DefId` and for convenience uses a special cleaner that accepts `DefId`s directly.
+                        if cleaner.keep_impl_with_def_id(for_did.into()) {
+                            add_deref_target(&type_did_to_deref_target, &mut cleaner, for_did);
+                        }
+                    }
+                }
             }
         }
     }
 
     new_items.retain(|it| {
-        if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = *it.kind {
-            cleaner.keep_impl(for_)
-                || trait_
-                    .as_ref()
-                    .map_or(false, |t| cleaner.keep_impl_with_def_id(t.def_id().into()))
-                || blanket_impl.is_some()
+        if let ImplItem(Impl { ref for_, ref trait_, ref kind, .. }) = *it.kind {
+            cleaner.keep_impl(
+                for_,
+                trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait(),
+            ) || trait_.as_ref().map_or(false, |t| cleaner.keep_impl_with_def_id(t.def_id().into()))
+                || kind.is_blanket()
         } else {
             true
         }
         }
     }
 
-    let items = if let ModuleItem(Module { ref mut items, .. }) = *krate.module.kind {
-        items
+    if let ModuleItem(Module { items, .. }) = &mut *krate.module.kind {
+        items.extend(synth_impls);
+        items.extend(new_items);
     } else {
         panic!("collect-trait-impls can't run");
     };
 
-    items.extend(synth_impls);
-    items.extend(new_items);
     krate
 }
 
@@ -136,8 +168,8 @@ struct SyntheticImplCollector<'a, 'tcx> {
     impls: Vec<Item>,
 }
 
-impl<'a, 'tcx> DocFolder for SyntheticImplCollector<'a, 'tcx> {
-    fn fold_item(&mut self, i: Item) -> Option<Item> {
+impl<'a, 'tcx> DocVisitor for SyntheticImplCollector<'a, 'tcx> {
+    fn visit_item(&mut self, i: &Item) {
         if i.is_struct() || i.is_enum() || i.is_union() {
             // FIXME(eddyb) is this `doc(hidden)` check needed?
             if !self
@@ -152,7 +184,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
             }
         }
 
-        Some(self.fold_item_recur(i))
+        self.visit_item_recur(i)
     }
 }
 
@@ -167,11 +199,11 @@ fn new() -> Self {
     }
 }
 
-impl DocFolder for ItemCollector {
-    fn fold_item(&mut self, i: Item) -> Option<Item> {
+impl DocVisitor for ItemCollector {
+    fn visit_item(&mut self, i: &Item) {
         self.items.insert(i.def_id);
 
-        Some(self.fold_item_recur(i))
+        self.visit_item_recur(i)
     }
 }
 
@@ -181,14 +213,14 @@ struct BadImplStripper {
 }
 
 impl BadImplStripper {
-    fn keep_impl(&self, ty: &Type) -> bool {
+    fn keep_impl(&self, ty: &Type, is_deref: bool) -> bool {
         if let Generic(_) = ty {
             // keep impls made on generics
             true
         } else if let Some(prim) = ty.primitive_type() {
             self.prims.contains(&prim)
-        } else if let Some(did) = ty.def_id() {
-            self.keep_impl_with_def_id(did.into())
+        } else if let Some(did) = ty.def_id_no_primitives() {
+            is_deref || self.keep_impl_with_def_id(did.into())
         } else {
             false
         }
index a3fde92d7655d776e9bb27dbe1bff1ce7c5ee19c..56b222d893262148d94d4e9e794e37022fc90afd 100644 (file)
@@ -1,11 +1,13 @@
 use super::Pass;
 use crate::clean::*;
 use crate::core::DocContext;
-use crate::fold::DocFolder;
 use crate::html::markdown::main_body_opts;
-use core::ops::Range;
+use crate::visit::DocVisitor;
+
 use pulldown_cmark::{Event, Parser, Tag};
+
 use std::iter::Peekable;
+use std::ops::Range;
 use std::str::CharIndices;
 
 crate const CHECK_INVALID_HTML_TAGS: Pass = Pass {
@@ -19,13 +21,11 @@ struct InvalidHtmlTagsLinter<'a, 'tcx> {
 }
 
 crate fn check_invalid_html_tags(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
-    if !cx.tcx.sess.is_nightly_build() {
-        krate
-    } else {
+    if cx.tcx.sess.is_nightly_build() {
         let mut coll = InvalidHtmlTagsLinter { cx };
-
-        coll.fold_crate(krate)
+        coll.visit_crate(&krate);
     }
+    krate
 }
 
 const ALLOWED_UNCLOSED: &[&str] = &[
@@ -165,14 +165,14 @@ fn extract_tags(
     }
 }
 
-impl<'a, 'tcx> DocFolder for InvalidHtmlTagsLinter<'a, 'tcx> {
-    fn fold_item(&mut self, item: Item) -> Option<Item> {
+impl<'a, 'tcx> DocVisitor for InvalidHtmlTagsLinter<'a, 'tcx> {
+    fn visit_item(&mut self, item: &Item) {
         let tcx = self.cx.tcx;
         let hir_id = match DocContext::as_local_hir_id(tcx, item.def_id) {
             Some(hir_id) => hir_id,
             None => {
                 // If non-local, no need to check anything.
-                return Some(self.fold_item_recur(item));
+                return;
             }
         };
         let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
@@ -217,6 +217,6 @@ fn fold_item(&mut self, item: Item) -> Option<Item> {
             }
         }
 
-        Some(self.fold_item_recur(item))
+        self.visit_item_recur(item)
     }
 }
index 8b1fd662f85fdef57602ae5c3891b28af3547076..74a9a2da06d36db0b117a930f588435c5dbb91ee 100644 (file)
@@ -2,7 +2,7 @@
 use rustc_middle::middle::privacy::AccessLevels;
 use std::mem;
 
-use crate::clean::{self, GetDefId, Item, ItemIdSet};
+use crate::clean::{self, Item, ItemIdSet};
 use crate::fold::{strip_item, DocFolder};
 
 crate struct Stripper<'a> {
@@ -127,7 +127,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
             if imp.trait_.is_none() && imp.items.is_empty() {
                 return None;
             }
-            if let Some(did) = imp.for_.def_id() {
+            if let Some(did) = imp.for_.def_id_no_primitives() {
                 if did.is_local() && !imp.for_.is_assoc_ty() && !self.retained.contains(&did.into())
                 {
                     debug!("ImplStripper: impl item for stripped type; removing");
@@ -142,7 +142,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
             }
             if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) {
                 for typaram in generics {
-                    if let Some(did) = typaram.def_id() {
+                    if let Some(did) = typaram.def_id_no_primitives() {
                         if did.is_local() && !self.retained.contains(&did.into()) {
                             debug!(
                                 "ImplStripper: stripped item in trait's generics; removing impl"
index fc54e55b87655e5cf7baa10961086ce07498532d..3b39e3576e69a39d22f577b29dd3ab4c173feebf 100644 (file)
@@ -10,7 +10,6 @@
 use rustc_hir::{
     self as hir,
     intravisit::{self, Visitor},
-    HirId,
 };
 use rustc_interface::interface;
 use rustc_macros::{Decodable, Encodable};
@@ -49,7 +48,7 @@ impl ScrapeExamplesOptions {
                 target_crates,
             })),
             (Some(_), false) | (None, true) => {
-                diag.err(&format!("must use --scrape-examples-output-path and --scrape-examples-target-crate together"));
+                diag.err("must use --scrape-examples-output-path and --scrape-examples-target-crate together");
                 Err(1)
             }
             (None, false) => Ok(None),
@@ -83,15 +82,10 @@ fn new(span: rustc_span::Span, file: &SourceFile) -> Self {
 
 impl CallLocation {
     fn new(
-        tcx: TyCtxt<'_>,
         expr_span: rustc_span::Span,
-        expr_id: HirId,
+        enclosing_item_span: rustc_span::Span,
         source_file: &SourceFile,
     ) -> Self {
-        let enclosing_item_span =
-            tcx.hir().span_with_body(tcx.hir().get_parent_item(expr_id)).source_callsite();
-        assert!(enclosing_item_span.contains(expr_span));
-
         CallLocation {
             call_expr: SyntaxRange::new(expr_span, source_file),
             enclosing_item: SyntaxRange::new(enclosing_item_span, source_file),
@@ -132,12 +126,28 @@ fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
     fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
         intravisit::walk_expr(self, ex);
 
-        // Get type of function if expression is a function call
         let tcx = self.tcx;
+
+        // If we visit an item that contains an expression outside a function body,
+        // then we need to exit before calling typeck (which will panic). See
+        // test/run-make/rustdoc-scrape-examples-invalid-expr for an example.
+        let hir = tcx.hir();
+        let owner = hir.local_def_id_to_hir_id(ex.hir_id.owner);
+        if hir.maybe_body_owned_by(owner).is_none() {
+            return;
+        }
+
+        // Get type of function if expression is a function call
         let (ty, span) = match ex.kind {
             hir::ExprKind::Call(f, _) => {
                 let types = tcx.typeck(ex.hir_id.owner);
-                (types.node_type(f.hir_id), ex.span)
+
+                match types.node_type_opt(f.hir_id) {
+                    Some(ty) => (ty, ex.span),
+                    None => {
+                        return;
+                    }
+                }
             }
             hir::ExprKind::MethodCall(_, _, _, span) => {
                 let types = tcx.typeck(ex.hir_id.owner);
@@ -152,13 +162,29 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
         // If this span comes from a macro expansion, then the source code may not actually show
         // a use of the given item, so it would be a poor example. Hence, we skip all uses in macros.
         if span.from_expansion() {
+            trace!("Rejecting expr from macro: {:?}", span);
             return;
         }
 
+        // If the enclosing item has a span coming from a proc macro, then we also don't want to include
+        // the example.
+        let enclosing_item_span = tcx.hir().span_with_body(tcx.hir().get_parent_item(ex.hir_id));
+        if enclosing_item_span.from_expansion() {
+            trace!("Rejecting expr ({:?}) from macro item: {:?}", span, enclosing_item_span);
+            return;
+        }
+
+        assert!(
+            enclosing_item_span.contains(span),
+            "Attempted to scrape call at [{:?}] whose enclosing item [{:?}] doesn't contain the span of the call.",
+            span,
+            enclosing_item_span
+        );
+
         // Save call site if the function resolves to a concrete definition
         if let ty::FnDef(def_id, _) = ty.kind() {
-            // Ignore functions not from the crate being documented
             if self.target_crates.iter().all(|krate| *krate != def_id.krate) {
+                trace!("Rejecting expr from crate not being documented: {:?}", span);
                 return;
             }
 
@@ -182,7 +208,8 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
                 let fn_key = tcx.def_path_hash(*def_id);
                 let fn_entries = self.calls.entry(fn_key).or_default();
 
-                let location = CallLocation::new(tcx, span, ex.hir_id, &file);
+                trace!("Including expr: {:?}", span);
+                let location = CallLocation::new(span, enclosing_item_span, &file);
                 fn_entries.entry(abs_path).or_insert_with(mk_call_data).locations.push(location);
             }
         }
@@ -224,6 +251,13 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
         let mut finder = FindCalls { calls: &mut calls, tcx, map: tcx.hir(), cx, target_crates };
         tcx.hir().visit_all_item_likes(&mut finder.as_deep_visitor());
 
+        // Sort call locations within a given file in document order
+        for fn_calls in calls.values_mut() {
+            for file_calls in fn_calls.values_mut() {
+                file_calls.locations.sort_by_key(|loc| loc.call_expr.byte_span.0);
+            }
+        }
+
         // Save output to provided path
         let mut encoder = FileEncoder::new(options.output_path).map_err(|e| e.to_string())?;
         calls.encode(&mut encoder).map_err(|e| e.to_string())?;
diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs
new file mode 100644 (file)
index 0000000..df4d155
--- /dev/null
@@ -0,0 +1,71 @@
+use crate::clean::*;
+
+crate trait DocVisitor: Sized {
+    fn visit_item(&mut self, item: &Item) {
+        self.visit_item_recur(item)
+    }
+
+    /// don't override!
+    fn visit_inner_recur(&mut self, kind: &ItemKind) {
+        match kind {
+            StrippedItem(..) => unreachable!(),
+            ModuleItem(i) => {
+                self.visit_mod(i);
+                return;
+            }
+            StructItem(i) => i.fields.iter().for_each(|x| self.visit_item(x)),
+            UnionItem(i) => i.fields.iter().for_each(|x| self.visit_item(x)),
+            EnumItem(i) => i.variants.iter().for_each(|x| self.visit_item(x)),
+            TraitItem(i) => i.items.iter().for_each(|x| self.visit_item(x)),
+            ImplItem(i) => i.items.iter().for_each(|x| self.visit_item(x)),
+            VariantItem(i) => match i {
+                Variant::Struct(j) => j.fields.iter().for_each(|x| self.visit_item(x)),
+                Variant::Tuple(fields) => fields.iter().for_each(|x| self.visit_item(x)),
+                Variant::CLike => {}
+            },
+            ExternCrateItem { src: _ }
+            | ImportItem(_)
+            | FunctionItem(_)
+            | TypedefItem(_, _)
+            | OpaqueTyItem(_)
+            | StaticItem(_)
+            | ConstantItem(_)
+            | TraitAliasItem(_)
+            | TyMethodItem(_)
+            | MethodItem(_, _)
+            | StructFieldItem(_)
+            | ForeignFunctionItem(_)
+            | ForeignStaticItem(_)
+            | ForeignTypeItem
+            | MacroItem(_)
+            | ProcMacroItem(_)
+            | PrimitiveItem(_)
+            | AssocConstItem(_, _)
+            | AssocTypeItem(_, _)
+            | KeywordItem(_) => {}
+        }
+    }
+
+    /// don't override!
+    fn visit_item_recur(&mut self, item: &Item) {
+        match &*item.kind {
+            StrippedItem(i) => self.visit_inner_recur(i),
+            _ => self.visit_inner_recur(&item.kind),
+        }
+    }
+
+    fn visit_mod(&mut self, m: &Module) {
+        m.items.iter().for_each(|i| self.visit_item(i))
+    }
+
+    fn visit_crate(&mut self, c: &Crate) {
+        self.visit_item(&c.module);
+
+        // FIXME: make this a simple by-ref for loop once external_traits is cleaned up
+        let external_traits = { std::mem::take(&mut *c.external_traits.borrow_mut()) };
+        for (k, v) in external_traits {
+            v.trait_.items.iter().for_each(|i| self.visit_item(i));
+            c.external_traits.borrow_mut().insert(k, v);
+        }
+    }
+}
index 3e853456fad77d48ee20e74dd20ab5d2ad862b0c..5d1f934240f037f0de0e2c18e8252a543f350957 100644 (file)
@@ -9,7 +9,6 @@
 use rustc_hir::CRATE_HIR_ID;
 use rustc_middle::middle::privacy::AccessLevel;
 use rustc_middle::ty::TyCtxt;
-use rustc_span;
 use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -277,7 +276,7 @@ fn visit_item(
             _ if self.inlining && !is_pub => {}
             hir::ItemKind::GlobalAsm(..) => {}
             hir::ItemKind::Use(_, hir::UseKind::ListStem) => {}
-            hir::ItemKind::Use(ref path, kind) => {
+            hir::ItemKind::Use(path, kind) => {
                 let is_glob = kind == hir::UseKind::Glob;
 
                 // Struct and variant constructors and proc macro stubs always show up alongside
index 372204dbbf703cde43bcd10c0096201ff377cf70..b5a4a3a03fdd7ac1259cfc46b1c39651cf07663e 100644 (file)
   "__comment": "Generated by `./x.py run src/tools/bump-stage0`. Run that command again to update the bootstrap compiler.",
   "dist_server": "https://static.rust-lang.org",
   "compiler": {
-    "date": "2021-09-08",
+    "date": "2021-10-22",
     "version": "beta"
   },
   "rustfmt": {
-    "date": "2021-09-08",
+    "date": "2021-10-23",
     "version": "nightly"
   },
   "checksums_sha256": {
-    "dist/2021-09-08/cargo-beta-aarch64-apple-darwin.tar.gz": "5bc2e21b10c153fd070c1a9b9af8ff68ada71f10953d8261bd8aa5f599878db3",
-    "dist/2021-09-08/cargo-beta-aarch64-apple-darwin.tar.xz": "95082b292ccf8e0fdd637f591dd3180297c48ec13ccbcb3e1a2c115feb17463f",
-    "dist/2021-09-08/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "7de49c4e1db688089dd566647c23233fb4ff21dbb4025a4be37d18b11cc82e2f",
-    "dist/2021-09-08/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "35394e3c08a3dd392958187b091b3bdc576a6bf0d2d139556df21cd3ff1d21cc",
-    "dist/2021-09-08/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "a71153dde967a7816636dce62ba4334baadad4b926b25dc54c068c5cb293df9a",
-    "dist/2021-09-08/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "d4e33616af35dd7564a73e702eb6eab7eae5da7a980f518bd3d34f4cf0d05440",
-    "dist/2021-09-08/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "f76545e48977d2ebad75d3cf745d81ca709d59ca02a6c66ee3d049d8ca145463",
-    "dist/2021-09-08/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "79cf346367022c3a1ba58fd134f8189fa7781e702871d56f60dc1fff9d318570",
-    "dist/2021-09-08/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "7884e6a177a2469f21dee177564e03490fc541e877f0a1858e17162a9037298c",
-    "dist/2021-09-08/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "6fb307038c827d4e915224bc17709929628bdc5eda625644eaa4df992de75718",
-    "dist/2021-09-08/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "a367fc19f65b07cfec4732d3bd13aa662581d9aca886d56c93bad171948c9593",
-    "dist/2021-09-08/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "161eabe9fc1a0031f9fb044da4cc4c2cf376c6a018695f9fa1f5d7ce96c742d1",
-    "dist/2021-09-08/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "35587eeb680443f759c6cc9526186d51e35b08683f9c8a112d692324b62afae4",
-    "dist/2021-09-08/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "8fea8765c22e9751379585d381ad14aa0faab811cfaf40dbb55a60c82146b91e",
-    "dist/2021-09-08/cargo-beta-i686-pc-windows-gnu.tar.gz": "9e7e075e79cfca74b1185067962e3b37118ed32c8258d6746f05891f742226cb",
-    "dist/2021-09-08/cargo-beta-i686-pc-windows-gnu.tar.xz": "50f34954765c542076e7a6d9dbaf3a8e8dbfbabfa95bbc76e95eb1fb52e1227a",
-    "dist/2021-09-08/cargo-beta-i686-pc-windows-msvc.tar.gz": "eb93a58581ff485b44013d3623d0f4afb0fc2e3a3c7ff1898b74faad6f7bf48d",
-    "dist/2021-09-08/cargo-beta-i686-pc-windows-msvc.tar.xz": "1913dd2d4b0c56a6e5ec3686fa03eafc716006cc1fcdcfd81cf1b7984b9532b1",
-    "dist/2021-09-08/cargo-beta-i686-unknown-linux-gnu.tar.gz": "04b3f5ca4f4a24a2555c186600f683730a59f807d3525248c1d8f2f674cd00a6",
-    "dist/2021-09-08/cargo-beta-i686-unknown-linux-gnu.tar.xz": "c730e3f619d69d221277f3b44a188746980eb7a0c79dab9a252cea6bc4a1e54b",
-    "dist/2021-09-08/cargo-beta-mips-unknown-linux-gnu.tar.gz": "94fc426e50671c39d7a272b9636ce43bc3242f1b6a302555914127ab73ce6c65",
-    "dist/2021-09-08/cargo-beta-mips-unknown-linux-gnu.tar.xz": "c44957519099e19edfeceed53b99674d9b98731b20ca7494621fb0dcc6488ed5",
-    "dist/2021-09-08/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "377a998bba44a16bb401bf56c4be2e38f1c40e37f71335f93ba8e54d20d7a3c3",
-    "dist/2021-09-08/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "2406c2ac61d9b494b3a6327d991a6846a18c867fc581892874a2e3e83f4d49fe",
-    "dist/2021-09-08/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "52c7d8009a6ca8701912c9e02c1278dacd2b6c2bdb218416d1e3db2c750b7536",
-    "dist/2021-09-08/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "764820946adfd6594c7c9c4f97cb06d1c639ae2621ded3059d234a0cef97b1dd",
-    "dist/2021-09-08/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "d351cbcd87d10d54bde4311d6fc902a655e8c74ffb16b2a85cfb8e5ad30faeda",
-    "dist/2021-09-08/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "ec7235af6ae25ce30c61d06f94bd398018878b741d8d94edad8e3dbaaad0cc2e",
-    "dist/2021-09-08/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "11d983f439f46a1b49d72b0e8ec1dd5f78c72c23f305476ce3b56ec20167ccc9",
-    "dist/2021-09-08/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "327fcdfcc7679178e734293e23e752d44bf1a4c44a88e5b2d89bfa7f95b7876c",
-    "dist/2021-09-08/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "52f827f09376c0f21419cbff1e56d30337d140c1c097d5a38d4541f65545d3d2",
-    "dist/2021-09-08/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "e9f956aaa4f8428b813d27c43a8602671a27f567d206f769da7b14e5029f5a1f",
-    "dist/2021-09-08/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "b59d4814b99031a9e418fd423833500a3436b65b0696974d1d6a2f7598ecce2d",
-    "dist/2021-09-08/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "5751e2453329e1fe2378cf9e7ade93c75df7a31d4dbeb0f14fde9c3cfbc5d5b1",
-    "dist/2021-09-08/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "a3d97d9efad02108166878a9a30d3485a9f6db0768bbef5c98e86540c6f4901c",
-    "dist/2021-09-08/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "e8c3bf169cdcf9192363c9ace37457a94720d36ff1b607e178796dac933f652f",
-    "dist/2021-09-08/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "51fc38135a45870bd01bbcee4b69f5e7055424b1cfa36d4c0272613baf3185c2",
-    "dist/2021-09-08/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "bc392d660368c856ab1bc96b603699d492f03b226a0d60812a1bb19ca6c05ff3",
-    "dist/2021-09-08/cargo-beta-x86_64-apple-darwin.tar.gz": "ea1804dfe7b806368f278adcb887e4aa023ff7f533bee84541415cb0862ed836",
-    "dist/2021-09-08/cargo-beta-x86_64-apple-darwin.tar.xz": "69fa3524d2bb2bbbf0c0a4e18ecbec3eeae791f9b60547d6adf0fa20123c4a41",
-    "dist/2021-09-08/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "611c3653a03ca05effb06b5857b77cb24fd87ae5f1d294df980c96a57b8a9a74",
-    "dist/2021-09-08/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "cca04b2298bea6b447daa806af2313da4797072d27ecc3202bd0633b5a1d5fb4",
-    "dist/2021-09-08/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "763d4ec911a374d348468a38d07caa8d559330c6179f5cd40b5a54ccdb355580",
-    "dist/2021-09-08/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "37d24786e764c3af201cba07ef88a27fac97d150d7711cfdbb625e957b9f0139",
-    "dist/2021-09-08/cargo-beta-x86_64-unknown-freebsd.tar.gz": "f39494da3f92c39be50579f26d7f09d8e5f985e3566f8742aacc1446ab9f92c1",
-    "dist/2021-09-08/cargo-beta-x86_64-unknown-freebsd.tar.xz": "b65f8024b47d4784ab59e4722e522e54442852bbe16906760f2708e2b0d0fe65",
-    "dist/2021-09-08/cargo-beta-x86_64-unknown-illumos.tar.gz": "072bb564f73a97bdc6d58970735191d8da0831926dcd155a946f0fde1f382a02",
-    "dist/2021-09-08/cargo-beta-x86_64-unknown-illumos.tar.xz": "fc6a9c6d4cceeac868b37e200ed193981b8d70e8408d8e4b4765e149a9075c3a",
-    "dist/2021-09-08/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "8074fc6912e4bdbae269a334f21d0ead7bb0f28344ad67d71f65487baf21cc35",
-    "dist/2021-09-08/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "32a8471b2fb91b62aeda637bdb1368c67d1b17daaeea2592517666393857af16",
-    "dist/2021-09-08/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "19dbfab31784d0615d0e84c526e98d9f47332492744bd1ab4fc7434c0762c5ad",
-    "dist/2021-09-08/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "510734acf369b92a3f1eb30921a96f393ae207af7dffe6a83df66c350bd1a510",
-    "dist/2021-09-08/cargo-beta-x86_64-unknown-netbsd.tar.gz": "85e2fb4ab2ca3eff3ce98ab1c74c996a6b9cd2c20ff3f47c8624e261ac254195",
-    "dist/2021-09-08/cargo-beta-x86_64-unknown-netbsd.tar.xz": "2b1cff0bfa9bcece19e61f4be680ebaa05663e918fc9f3a20516efd91244e1c6",
-    "dist/2021-09-08/rust-std-beta-aarch64-apple-darwin.tar.gz": "54386650675047126f2b418485a5b2ca8bf3b568231fe54914512ae09809276e",
-    "dist/2021-09-08/rust-std-beta-aarch64-apple-darwin.tar.xz": "c7613b2089562353502560a6521139dfd7fd58a96c772877cf2ea7bfd62920d4",
-    "dist/2021-09-08/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "a80e59fa3885f73973d9c3eb50628718eda015b1e62f328152ee95971acb10c2",
-    "dist/2021-09-08/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "b0b65575680186ae6c032fabad5dd4352d17ec2d29ecc22771ab9f86a54b90e8",
-    "dist/2021-09-08/rust-std-beta-aarch64-apple-ios.tar.gz": "22fdfea8abb345a32ca47ce658c601c36d7838cf22383a34470db643a14e89b3",
-    "dist/2021-09-08/rust-std-beta-aarch64-apple-ios.tar.xz": "3a145167eb7bd82e59df7bd009f69f4951efb1487cf002c584625c24be35f4c0",
-    "dist/2021-09-08/rust-std-beta-aarch64-fuchsia.tar.gz": "97d1614ad18e71a09326d65ec4bb631c9974f4d3c63c9438b180646579227f7d",
-    "dist/2021-09-08/rust-std-beta-aarch64-fuchsia.tar.xz": "aabd6f6c8548b6576986f6fa2632ced035f0ad504da05d3dfd92ab0202104ff9",
-    "dist/2021-09-08/rust-std-beta-aarch64-linux-android.tar.gz": "5e67121330fd7e095f86c5dc71bd5180ec1669ad819ccf0bb4b38b46f35bcf94",
-    "dist/2021-09-08/rust-std-beta-aarch64-linux-android.tar.xz": "b3d72ba51cca485d742117c70915a5e57404d3f8c80356c8df388eba913e136d",
-    "dist/2021-09-08/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "f3eaf16070eb770d464a844e72257cca4ccce4ee2c380f276e82d259d8781326",
-    "dist/2021-09-08/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "846480e3eaf8d21fb4d99659a68e71259da613e54cfd098470c139e38ea5a447",
-    "dist/2021-09-08/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "198be5989e4d2d479582ef2002ec3041105555cbb86488ba563fce35ae1c5c18",
-    "dist/2021-09-08/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "706148bf9e562cf61d6f882a330e0fd150eb0593136a370cf559c54b6723f4c1",
-    "dist/2021-09-08/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "8e2718c2509c3db0696599dbd93f7a9c846228374ec0e24bf9f7b876a7714d71",
-    "dist/2021-09-08/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "e44e11ca1ac94d2335c19891fc8b85394b3935a86fa51c8a2c558faf8606c7bc",
-    "dist/2021-09-08/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "9439bb56b5c11e9fab00e02e7f931c4582a6dbb3aeb7b20e5ad0fe5420dd27d0",
-    "dist/2021-09-08/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "5e3187685291d52c500aba70de657478e08b5a69ecbf381f2ae41cb78cfd82d3",
-    "dist/2021-09-08/rust-std-beta-aarch64-unknown-none.tar.gz": "69c5da7ba93aeb93f8f7a6b581f1895b427c377c8f624274cf2691cacf845acc",
-    "dist/2021-09-08/rust-std-beta-aarch64-unknown-none.tar.xz": "8d66841c5e9e20d35b3791bbd10fb97e73b7abf602fee52a939a7096e0040eb0",
-    "dist/2021-09-08/rust-std-beta-arm-linux-androideabi.tar.gz": "4901f22f057d78331d298c23b66a39b2caa39580b19adc007fa8a4780483b27c",
-    "dist/2021-09-08/rust-std-beta-arm-linux-androideabi.tar.xz": "ba5d5016a625f433dc2fdacb3a1c462a08cdf9cdfcd202a966f16386e58362cb",
-    "dist/2021-09-08/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "0ea2986826d17ea1baeecda1c73af27e41830d22aa10722ac18e1427a3c11295",
-    "dist/2021-09-08/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "11e8397c3b6cc2f0ce7c8d725e8bc8dd0a7b7c800174ca3f4da6ee4c32e338e9",
-    "dist/2021-09-08/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "019fb984e383342a3ec4069f7f62bbc33c9b9609202b571ae32fe6b0ddd2dd60",
-    "dist/2021-09-08/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "e86d5310c9181ccfd432bc93e6715d109f26608bea97fee0d9f0d2efaaa7126a",
-    "dist/2021-09-08/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "1a7c7bf25c54c9a394a671d7f23e5cb08d6501b25bbb687159a208dfa16b0d33",
-    "dist/2021-09-08/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "e8deaf7cf0031d73e93ac1f61713836a0413f644639f8f602d234bd583c660c2",
-    "dist/2021-09-08/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "0d72ae75cc1b59146dd799cb85a8c60ea9c4169f53f17b8eeb74da644bad0e21",
-    "dist/2021-09-08/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "1dd8c951a7e13e68686e9a9a3eb0ecdae83fb178454a0ace9c649b5b47fc9a50",
-    "dist/2021-09-08/rust-std-beta-armebv7r-none-eabi.tar.gz": "8b4b4163b746618c2dde450a7151ccdbfaf9732311fb959d11336bd78bfa8d25",
-    "dist/2021-09-08/rust-std-beta-armebv7r-none-eabi.tar.xz": "fa6ef79c9a3ac07c0cebe908eebab2a32f578f0838c0f939bf8f4136aed7a499",
-    "dist/2021-09-08/rust-std-beta-armebv7r-none-eabihf.tar.gz": "487c64e8251564373437f94b5e94d81bec50b61e77c39c691ce912cf95236d0d",
-    "dist/2021-09-08/rust-std-beta-armebv7r-none-eabihf.tar.xz": "2bae0e0b2383ee6182ce8df4dd26993aaa56aa4dd89e6cac1982a48414ca5d5c",
-    "dist/2021-09-08/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "bb5ca2b48383b27d181d90e4802cd387cacab9c00fca853c0deeb317270851b0",
-    "dist/2021-09-08/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "f7bf769be48434faddf3dbed8264b1ab5dbbb3657f5b71640ad9330b3340ca29",
-    "dist/2021-09-08/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "c88db813417a1263408cc3bffeaf03b45db7b2c0a89c8441b3f4e7514473a0c3",
-    "dist/2021-09-08/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "3c5a3ea4ce9a6826dd3fc1eaae8615701bf3b5c53d56fe6948432229f027ac1c",
-    "dist/2021-09-08/rust-std-beta-armv7-linux-androideabi.tar.gz": "3d45d64267149d222337421be4cd5207812125f9b2df253f507f0cc2cba37219",
-    "dist/2021-09-08/rust-std-beta-armv7-linux-androideabi.tar.xz": "ee71e74b369b42a9c2258bf5d9c8c7119ee65b8951d4655c477a4593ec2cf3fa",
-    "dist/2021-09-08/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "949bce55fc6047a37f8ea26e21cc69557ad66a45c688442f2be06a8cab503358",
-    "dist/2021-09-08/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "28ec52f486459b436c0097db2b400a202ad1280591f2612cadf4daec1ef4e4a8",
-    "dist/2021-09-08/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "0f7782f0b6874c858de7171d255f12fe309e9255ad55a6406577feae3702fbc0",
-    "dist/2021-09-08/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "cf3bc863ecd6da3fb45c3d2f5b6741d57ff778b1bb2e4f0d05480c9aab480bbf",
-    "dist/2021-09-08/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "35e3647a940d2e2e37ed3a5b7c1a789f94b7f1a256f0bd339630bb7b0342c2e0",
-    "dist/2021-09-08/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "ed1ec913fd3e821501e52be1d3cdac3fbe5a6c00acd17204b1891aa5fa3e6f93",
-    "dist/2021-09-08/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "2fc9f5791717cc876d155f4cbb672dabf9fa308ac67636e50a75a5b5ea11369f",
-    "dist/2021-09-08/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "91ac6c321d172cfb62e6772c2c7340110fb9801a8d44814b69b477f611f09c58",
-    "dist/2021-09-08/rust-std-beta-armv7a-none-eabi.tar.gz": "69661706ec6749f851d6a967f69fc8e4de8e5a58da2a771129b22202918f6ce8",
-    "dist/2021-09-08/rust-std-beta-armv7a-none-eabi.tar.xz": "45275aea14a3f4547e0e2f11ce2cf364ac2c749cf0df467a54e27b39b65a5fe2",
-    "dist/2021-09-08/rust-std-beta-armv7r-none-eabi.tar.gz": "63ea71e69e36d916baca6eb42b4b4b6f2f69870063526533a2699f66fc0cb317",
-    "dist/2021-09-08/rust-std-beta-armv7r-none-eabi.tar.xz": "2d6f4ca658991a7b426d50330371922888706944eb3c1603288d4be2fa4f5457",
-    "dist/2021-09-08/rust-std-beta-armv7r-none-eabihf.tar.gz": "3d27ea42bd3a419ccf7f28b9ff040e077f3e963948924f996aaf718abeeb1709",
-    "dist/2021-09-08/rust-std-beta-armv7r-none-eabihf.tar.xz": "8f6bc34715629354b4d9f71d7a8693171b667604d237b433f7444df1228d2a36",
-    "dist/2021-09-08/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "f83bdc7e73590beab7ec915bb7a3a7531e485d7f73cf9c65150102748207d874",
-    "dist/2021-09-08/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "1068750fb0b4a7ec35b5674a6c7fb0368b043bee6df0fbe360f521c7c2f08b94",
-    "dist/2021-09-08/rust-std-beta-i586-pc-windows-msvc.tar.gz": "506bd86d803953bb086e057c6b2ee1fd9ffa0e08a0d7162189119cd21668cc0f",
-    "dist/2021-09-08/rust-std-beta-i586-pc-windows-msvc.tar.xz": "b608aff18260165b51acbc06d551c5eb003928f2c7551f83a1ac1782442826ac",
-    "dist/2021-09-08/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "c90eca1f2326cfa916e225199e2526719fc9b6f18e2b789366a9668a52eba339",
-    "dist/2021-09-08/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "ab382cc6c67bceaf76555a2c71c5f26e46802fe7c2713e173744b14371b742a5",
-    "dist/2021-09-08/rust-std-beta-i586-unknown-linux-musl.tar.gz": "dd52e44df6cd8bbac61d484e574d363125662fef270695e962900995a05818b3",
-    "dist/2021-09-08/rust-std-beta-i586-unknown-linux-musl.tar.xz": "e9c4bba480b748625898dc047b950a142ccda9e9fe1e329365741f09f640e843",
-    "dist/2021-09-08/rust-std-beta-i686-linux-android.tar.gz": "bb2e1dea2aae2f726420d8a5cd112f1bed6e06e95053f10c6497b1be878b180e",
-    "dist/2021-09-08/rust-std-beta-i686-linux-android.tar.xz": "df15194a40cce8c574b219164b75590ad9c55c03ab811682ebe89db004c651f4",
-    "dist/2021-09-08/rust-std-beta-i686-pc-windows-gnu.tar.gz": "c7b38618dda1cd13d52c59bb9a4632458aa7b20d90b01478fb506801c3fb41eb",
-    "dist/2021-09-08/rust-std-beta-i686-pc-windows-gnu.tar.xz": "83390b595e3273f0b02e05878064429a1815f18bceb7e0d77a63c5caecaebfeb",
-    "dist/2021-09-08/rust-std-beta-i686-pc-windows-msvc.tar.gz": "e7c6c8e5ae9d02e9f3c33b174862d1d6e0caf357c7c3cd510e63cc3472db816b",
-    "dist/2021-09-08/rust-std-beta-i686-pc-windows-msvc.tar.xz": "feb49ed3fdf25d7703134afefc3c04b0ed23d87adc02945bccac4b30c425fa16",
-    "dist/2021-09-08/rust-std-beta-i686-unknown-freebsd.tar.gz": "f633cb1bd2636eceaa87d98a214aa73907502aa92d4cb1a1869870c9bc6ad23a",
-    "dist/2021-09-08/rust-std-beta-i686-unknown-freebsd.tar.xz": "cd61b7dfe7ead85a79469008717bc52cb76572fc9688f82a50f07b0c7e0fafb2",
-    "dist/2021-09-08/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "b22f1285e8d179a372060916bc2a6d609499231f805b5cec2ef8d1e5d0c70d71",
-    "dist/2021-09-08/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "24fd3c052bdec08615e54438fbccd9e43c9956d25b1bfce6f3640eb164aa6f5d",
-    "dist/2021-09-08/rust-std-beta-i686-unknown-linux-musl.tar.gz": "df63f460486eeb9a11ed53c35814495e931492aed5abe44a841cd7a43a9e3719",
-    "dist/2021-09-08/rust-std-beta-i686-unknown-linux-musl.tar.xz": "3ba2d402c01b099b89518acded3734a552f64a330a7d21732ce641cf25cd5c8d",
-    "dist/2021-09-08/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "4cc5b2cfa6747155a0e0c6a7a835abd464bc9610fd071197af1ac50ab8f2fa1c",
-    "dist/2021-09-08/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "28f70f287f4cceba042b9574b16ce0403d73785bc6261c9a6739d770d5f354f9",
-    "dist/2021-09-08/rust-std-beta-mips-unknown-linux-musl.tar.gz": "04a8dc4e8144330f326dba5182928cf91c50c4b3513df0b67d55d601d3524a7e",
-    "dist/2021-09-08/rust-std-beta-mips-unknown-linux-musl.tar.xz": "06a91efa4f8ab42c3a0f9c2ae9279da87bb2a239f1032d1faa3583febace37cc",
-    "dist/2021-09-08/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "887728123ccd4bb75f4d42bffc1d2b7f46d8bdc4554a77b12578507cb44e7fd5",
-    "dist/2021-09-08/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "987598a67a36f428fa8fb21e0239aa345e952a1e6c64fefcc2fe2feda56bb864",
-    "dist/2021-09-08/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "2110b1b7456366668e093d27013d7002e302c6ecccff63c147c0346cd9a452b7",
-    "dist/2021-09-08/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "d6f16eca6526aeeef3ec7d0a9948ff5da3b7eff6e4bb9203a9546037df1f8d55",
-    "dist/2021-09-08/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "36a510c2a8fbc751416183b88680685c232646289504d2e2422e5208cd11670b",
-    "dist/2021-09-08/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "2f2a7a533d30cdb437bf31d18fb547680d646ec1765ca6c5fe16e449dbf3b613",
-    "dist/2021-09-08/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "09472066c8403c059e9d34ac2f7a4387e61726c45dd5ff2bc03b85543d8376c0",
-    "dist/2021-09-08/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "83c4a0f9ed4fa2884d1d193b79693c3af4e9c8603b9a1f3bd6eb827ba09a5466",
-    "dist/2021-09-08/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "739998734f48c9591b7aed3452d8425e2c916d202341ff63931fa473e3eb9a25",
-    "dist/2021-09-08/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "83be5e72fc8597f51c6b2cc216d90c8dba6be509b44fa25f3d7d285e1c54c7c0",
-    "dist/2021-09-08/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "0a02455697ac62af66b359d5b73436ce7b18274abd18ffa13b7f0f9c1df72f82",
-    "dist/2021-09-08/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "1cc6fe6ecfe4c10c2957806e56c1a0aa256ef5bb3ad4ca47f24aae42cf0fc0e3",
-    "dist/2021-09-08/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "f90d70acfa78388fe8e54a62f4fd9e773bd1455b036f6af13a5feec072de11e8",
-    "dist/2021-09-08/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "d2c491b6fb62bc5279447e7f5d96fbb679a225ec13d6c96c8f80cad859b0f5f8",
-    "dist/2021-09-08/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "17e9bca285df96b3bcd48297c89c096aab6b545d783e261103f7b364c214c09d",
-    "dist/2021-09-08/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "d4a8679af46449daa4db0acc23bda23aa5c8f35fb2ca9d0e065b35e30d6fc649",
-    "dist/2021-09-08/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "845cab4436d36b6eb2a914ab7c48bd49626a04053eee918fbbb78aba1d1e0a4a",
-    "dist/2021-09-08/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "b399647f0d9e8458570e8a9ab11b30d7258fa396ab019037b5bb391dbe65ead7",
-    "dist/2021-09-08/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "6c84662ba3c210b9d7c3332473cdc95dcf3e238d9c9010581accfafa37cdf4f8",
-    "dist/2021-09-08/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "594aba2abb126a615c93bb5c7927eb5a2ccdbe4c54c22bfdfa9cacf99e268889",
-    "dist/2021-09-08/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "439f5d5f1d2ee9db18c6e3b0bb831b037234852067a91f1a15bca38ca38b7a0b",
-    "dist/2021-09-08/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "227fa2ff323d20a2a8c29e0167fac78c7b88b8db3368b009b75d4a1cd49b7b29",
-    "dist/2021-09-08/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "5055560e4dc3df90bf127bb5133c8d2d0ba662c1b1b20d63453cd60ee3e04947",
-    "dist/2021-09-08/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "df1267905fe5a23c2ddc47fc0ade249bd663e6d3e8982193cb2a2a638e747e5c",
-    "dist/2021-09-08/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "2a702d0d0a0e2cf17a42eac549bd751eadc4398182f42590e3322cc7420b4cd1",
-    "dist/2021-09-08/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "98e5d336ee07556ff0fe01f89f9059cb977fa36d5f87ee8633aebb5fa6c8762b",
-    "dist/2021-09-08/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "de64e6d171a2c11e16142b1e964c0f0e0d6e4bab2e9e9d5d8121ee77fbdb60de",
-    "dist/2021-09-08/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "1dbb24b1ed6510f098f63933a596f1f58907c22320eb79394dce341af7d7b59a",
-    "dist/2021-09-08/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "66af911664286500164db018c0aad12a85da035fc1e2d6cffbe7603ff0145624",
-    "dist/2021-09-08/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "e8abd1f9f7344842af5f6a85d75404c1589fd17efbe5a8008ab52f082b7b3772",
-    "dist/2021-09-08/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "a9f06d8862f9bb805f438b1c01464dd7a9cd07ecd04b1246727ac290891da54f",
-    "dist/2021-09-08/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "6143b4b36bbdd1c56b978e9a2afc012163610fac7b8fb9bd9f24abb4e970b21d",
-    "dist/2021-09-08/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "5cb4c0616056f36c7cfe446fa97e146fd5c525be1de8bbdb5017ad0d07a9561d",
-    "dist/2021-09-08/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "9d2397f9d70956ddd50b37f8a7dba71d3cea9df5fa128e35d92cb162d7f938d4",
-    "dist/2021-09-08/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "b7e0fe340919a37cf8daeb1a747392c53fce4dafc84331f998479c3c12572973",
-    "dist/2021-09-08/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "464b2601346e014b2f5a9cc64dd32897be915742a5c75eeacf82691277c4f8de",
-    "dist/2021-09-08/rust-std-beta-sparcv9-sun-solaris.tar.gz": "40c61118e3e85343f6ea3059e41e3d2e3108f540331d8114948447307eea9b5f",
-    "dist/2021-09-08/rust-std-beta-sparcv9-sun-solaris.tar.xz": "3dfb77e1315a8367b4a5665ae9419843a8cb953ce4726b35307e7c7199514616",
-    "dist/2021-09-08/rust-std-beta-thumbv6m-none-eabi.tar.gz": "66632c7fad29f275ccfed907e395db12e621b17909e5e026d192f0b552fd4be1",
-    "dist/2021-09-08/rust-std-beta-thumbv6m-none-eabi.tar.xz": "a308cdebc35d65d8208fe2b2dc7b45dfb1a64405478d86b82bfb28115174a129",
-    "dist/2021-09-08/rust-std-beta-thumbv7em-none-eabi.tar.gz": "c342b21b5f61dcddea74b89f60f1d0d0622c5aedc79550d316b8744b522bda6f",
-    "dist/2021-09-08/rust-std-beta-thumbv7em-none-eabi.tar.xz": "a3b00a6b9b3fb8942700f91d32077520185a7c21d25620193cbe2e730a021f64",
-    "dist/2021-09-08/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "18f15f7e2ffe97f7be99e246144e6b9ad7445b1b66382112e71e08137a36b840",
-    "dist/2021-09-08/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "16eb54bf02813d45c6ff328ec7db8f16daf0e57dedfad7247249af2ec5133d4b",
-    "dist/2021-09-08/rust-std-beta-thumbv7m-none-eabi.tar.gz": "14bdada81be2379b2ead0212cc34add3ace87bd222532ada2a00b603180db946",
-    "dist/2021-09-08/rust-std-beta-thumbv7m-none-eabi.tar.xz": "f6cfa6bdcee91a6cab748fced0d2be7642b83cbe7d5fdcdf638fc3e86277d17e",
-    "dist/2021-09-08/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "e11e35a643c0a9983fb1f1e8f60ac073a4ee48c4a9f3e757f4fb55ea8364046d",
-    "dist/2021-09-08/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "2ee5fc11fb01f84e2346a17745c935f75d400a2448ec49d9e3535c98c3d67a73",
-    "dist/2021-09-08/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "61b26681fdb6957c3acd9aa32b011605786bed196cd71334d966ad9289efbb2f",
-    "dist/2021-09-08/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "bfd3391ebdc20690ede1a8a606f59df9009a473962deb04d3a89b266d0a89949",
-    "dist/2021-09-08/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "ae8d90bdd3d2faa2623ec30935e3e93bf3af6ad036eaae72bc8a3d086f7cd054",
-    "dist/2021-09-08/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "66ce451e2a0830808aa996b4643fa6ca6d89a072467d9df659ad4e202b73d561",
-    "dist/2021-09-08/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "1afbb6a4ee9ec38b7ad1c67c3df3371d188b831ffdb58ae96227e5c9a017f5d9",
-    "dist/2021-09-08/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "8c1e0000926fb4ff370763396e69aef70ed7871c33f01bc2d429abf31ee8d211",
-    "dist/2021-09-08/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "169852e1ae03792a8f492954258d08bc1483615e7121d587476ac4fc065c79a1",
-    "dist/2021-09-08/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "1da32effe4416f0cd5448a9061d57dd2f4b541f737a7036d20d78fd44f715ddb",
-    "dist/2021-09-08/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "39d22c8ff2620d4e6569eb75c86d4135a288bba00dcc479f4371a1e7e52fee4b",
-    "dist/2021-09-08/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "c34b1abdb8e3f3f913564a472b18dc52b239d7e327a4bd89d9bd0290d0b31635",
-    "dist/2021-09-08/rust-std-beta-wasm32-unknown-unknown.tar.gz": "ae284aa5819407e8daf022fbbf1f5d279366077faf25a6653d9c518ab3fe710e",
-    "dist/2021-09-08/rust-std-beta-wasm32-unknown-unknown.tar.xz": "be7a5b763db13ab1582a5f98fe7fb9ab1facdd645a7fe4544e0cbec9d1c58e76",
-    "dist/2021-09-08/rust-std-beta-wasm32-wasi.tar.gz": "ac9f39cb7924f48fc29d666dfda3c6001b6880d6efd956acfa734389ef7b5dbe",
-    "dist/2021-09-08/rust-std-beta-wasm32-wasi.tar.xz": "04d20256cea7b2394f72f6c0895a9d249fbd641fcaf616a628ad703e79c950a2",
-    "dist/2021-09-08/rust-std-beta-x86_64-apple-darwin.tar.gz": "c304a11e2361b42f80fb9c6f239cbfbd2b7ffdcf00fe49ac94e3a6d4a9d2d2b3",
-    "dist/2021-09-08/rust-std-beta-x86_64-apple-darwin.tar.xz": "35d51256fc42481b8265a02d756bb9bd84a23240156ed1fdf84ee3adaa77b8c2",
-    "dist/2021-09-08/rust-std-beta-x86_64-apple-ios.tar.gz": "6eec11897fe08b43fece4a1cf0ecec1ca247b3d01656b4a2a159815fbe13c626",
-    "dist/2021-09-08/rust-std-beta-x86_64-apple-ios.tar.xz": "faddd6de72f17f669e38dc2e9ef5cdd4b729cdbccaae6a7711c54b173d86bfd2",
-    "dist/2021-09-08/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "6741696a588c4e723d279e388d446271b773c6029a823c5e2135a08a018c6083",
-    "dist/2021-09-08/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "a62d276ad6a4832cadd3ef4c587cc77f588774b93b2807dc1ab9e0acff037838",
-    "dist/2021-09-08/rust-std-beta-x86_64-fuchsia.tar.gz": "38a61746734681a97e84419709bd3ebc722207db656737e7be75479e0d991f9f",
-    "dist/2021-09-08/rust-std-beta-x86_64-fuchsia.tar.xz": "b85bbcd1353315e5c4eef82707912566f6a1f94f706350ae0474a29ff33b603e",
-    "dist/2021-09-08/rust-std-beta-x86_64-linux-android.tar.gz": "de32ea66a8228857a34f39d8d47e6cb32a4db9efd73100e97afe12bf58f6d520",
-    "dist/2021-09-08/rust-std-beta-x86_64-linux-android.tar.xz": "e2f89e63a379ba8182acf1b4fba33f790e0cdf4675bc46239840ecde613b1835",
-    "dist/2021-09-08/rust-std-beta-x86_64-pc-solaris.tar.gz": "6136d0607905fe49617a8171896bfada258eb84cb00e8042fd67bef29732a714",
-    "dist/2021-09-08/rust-std-beta-x86_64-pc-solaris.tar.xz": "00a98839ab7d2302feeaa0fdbedc169bfb2bd7229c27aa274954efc73b52c4f3",
-    "dist/2021-09-08/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "2f711c4a26ed3b876e64e256bf1b4040552e80a06bec352a9d3479ed8ed6aca9",
-    "dist/2021-09-08/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "e479e495292512d67414d3056c322ea368559a0d95d827f944bae7382bea4e4a",
-    "dist/2021-09-08/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "ce43642d886784242a3914b799b1a77b60df642af2a41f75eac186b7f1b6104e",
-    "dist/2021-09-08/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "a83d236d59f04f3a51a6a34ccf7b79b4b2f269dc50e147d61e1e9c4a57925835",
-    "dist/2021-09-08/rust-std-beta-x86_64-sun-solaris.tar.gz": "a8e7f979fc8ad5bdaa4ea2965c305a3296dfe88ffa235cdb7aea8234e4a46138",
-    "dist/2021-09-08/rust-std-beta-x86_64-sun-solaris.tar.xz": "72ed0fb32e53b283c6a0e1752d231915b98504164965f7e2b5f06d8550e4c338",
-    "dist/2021-09-08/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "1f5535f9d44afdacf059681587239bf4d21985f1dfbd3ace94c864c2d7616a42",
-    "dist/2021-09-08/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "5faf349a9cc231c144c52de40f2a487a935c6f6146614547e64cabb26f037a23",
-    "dist/2021-09-08/rust-std-beta-x86_64-unknown-illumos.tar.gz": "0ae64780c9a944a32bc51b5efef9f0818025a423819ef60fdc799945d52bfd73",
-    "dist/2021-09-08/rust-std-beta-x86_64-unknown-illumos.tar.xz": "b3308afe75af668878959db95b039c6e1c4416badf67ee650b07f5cf07f14ab2",
-    "dist/2021-09-08/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "f8078421bde37f74dd0ffe0ea44704778baca779e502cb760371340a6bfa15a5",
-    "dist/2021-09-08/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "cc26d8fd139b35e13cf75c2942727bba7899a874d95f865c127b0c3af15707cd",
-    "dist/2021-09-08/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "6e0ef50cb8c4ce19d7de517ad51581c4d80043fa489278c0ba984a5d408269db",
-    "dist/2021-09-08/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "5c9380fb472de93ebfe59b21f2a74b5f19a632ef6eccf77a89cf0b26ce2054a7",
-    "dist/2021-09-08/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "264c78d59e71d4fa232f6f10713ee61d94c270e493eabad7318877afa46b7327",
-    "dist/2021-09-08/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "af3e5b1883e8fa7d49e64ce8754d656d2992eba33b8ec5f92245f2a82793abf4",
-    "dist/2021-09-08/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "0797448414c3421577705e725814dbf833a44b0930875fe418aa1eed9ebf6121",
-    "dist/2021-09-08/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "bd3ec2d0fde1e11a75bfc3b684c2d564bd5068519d1c5a382ae09379337236c9",
-    "dist/2021-09-08/rust-std-beta-x86_64-unknown-redox.tar.gz": "449ea2e6ed2e1b4d656f8da8390f2e22cbbe40713e5f91cbc85971f36488402d",
-    "dist/2021-09-08/rust-std-beta-x86_64-unknown-redox.tar.xz": "5424c5b4aa5588de73734dcd43cd1ff9bf0e0ba244749a1519afc94c8f2057e2",
-    "dist/2021-09-08/rustc-beta-aarch64-apple-darwin.tar.gz": "b14f7853a9353b71d7babeeb136fbb595b5c23144ac1bd72e70b74227a1685ca",
-    "dist/2021-09-08/rustc-beta-aarch64-apple-darwin.tar.xz": "af2ab319357b3b4a2810a52c824f8f308d2c3f41ea1ed30ba9ef9ff6a4769dde",
-    "dist/2021-09-08/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "c09a6bdbe6dccbdcd366a695d54be4e0a472fa1ca5bf30bf7eaf389534e2f70c",
-    "dist/2021-09-08/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "9fad7bc10840340081cd29166aa788843a9950e293d6ced71a26e36bf0eafe9e",
-    "dist/2021-09-08/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "d20cdcc681b0506e73ccd0b484a7b7394a08615d2d195318d0f2c5af3063581b",
-    "dist/2021-09-08/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "07d0b4393149f854dca2d622a6ac8d6cb9fc62d2d24977bcf50cdc1824fe6a32",
-    "dist/2021-09-08/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "dbe81393d5253521adceda8027b103edef45a031120e92f2e9e89564e85863c2",
-    "dist/2021-09-08/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "40edabc1e00f228815c88798543f55081e3dfe352f88753f5592479de9236b4b",
-    "dist/2021-09-08/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "114dce61c5bf25be9f3cb33cd0c7500b1a60f5cbebef27547458312b8ddb8f4d",
-    "dist/2021-09-08/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "abc9130f7116badf9949f5a3ecd6820787e40bb590ebbd5c867b05cedfbdce5f",
-    "dist/2021-09-08/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "cbebd112f0dd96258ed19b25762af60c9bac30669ae229d6b8456049779c890f",
-    "dist/2021-09-08/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "cff6cbf35aba285cfb5f5d2f8a9dee5edefc7c22843ae0198e693993d556fcae",
-    "dist/2021-09-08/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "c20cf9a2e72f712f02ed867e9c4babe02d7ff22d62eb96cb127054010b6731b6",
-    "dist/2021-09-08/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "aa1b6cd4f9153fba338eb5c8a90ace06d742c97e659c3ffbca75125e5477b828",
-    "dist/2021-09-08/rustc-beta-i686-pc-windows-gnu.tar.gz": "3308d1e3ee0ae40f8db301601c73bf6eace168b570e9ab952760e28bd970a240",
-    "dist/2021-09-08/rustc-beta-i686-pc-windows-gnu.tar.xz": "0a019f66979c2542bf9fb268bad143cd55deac6f1502a4393464bb26a1e21c76",
-    "dist/2021-09-08/rustc-beta-i686-pc-windows-msvc.tar.gz": "31016537cedf38ef83e29a6125445946834a06ec2fda51ef799566baeb47211d",
-    "dist/2021-09-08/rustc-beta-i686-pc-windows-msvc.tar.xz": "a997b98b7a28358bd4ed394ddd3af62e5b19d7a33a61f55bf973b06fb9b95fe5",
-    "dist/2021-09-08/rustc-beta-i686-unknown-linux-gnu.tar.gz": "ddfba3dfb711db2ebb4cd7149172a738200b8e38a98f7ec5e5bbc81515be5453",
-    "dist/2021-09-08/rustc-beta-i686-unknown-linux-gnu.tar.xz": "5b0435f652dc749216735fc06599a3c6916a867ab82dc126d0cde872855dac83",
-    "dist/2021-09-08/rustc-beta-mips-unknown-linux-gnu.tar.gz": "6408766f8c58c13ba51347375dc5ed0fb7c247c8aee9b8a89e3369c70541c397",
-    "dist/2021-09-08/rustc-beta-mips-unknown-linux-gnu.tar.xz": "18a41553893aa8ff4c80fef252e8ba80c383d2809a57123fe89e89172a5839c5",
-    "dist/2021-09-08/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "28078984a80c4cb0e65391ae213390059a9eebff028209861d23c82b4db0a11c",
-    "dist/2021-09-08/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "277cfaafab145858ee5102a657c597abbdfa33ed2d6f1c8806f218bad91b2d8f",
-    "dist/2021-09-08/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "8c8c92719f3d299047089031cb29ce209e2954466415449d37d474e88a732d8e",
-    "dist/2021-09-08/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "d055a61cd0ec951edbc703180c190ef4dbed3391d1b2472668340642e205fecb",
-    "dist/2021-09-08/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "95433c7dc0437f61a024276c10a0654128bd0e873597932297140f82e34ad201",
-    "dist/2021-09-08/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "a3660c9909e3821537a275e37121950d6adbc87b85959e80fd7b72c6e3b7b944",
-    "dist/2021-09-08/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "07384f5fba55ad572753fc85ad6b2d231d94b31f009defb694c8632b38eeeb62",
-    "dist/2021-09-08/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "f0985ea483fbad75a9cff021db6c230c5c322eff942da667a0dd6cb3e37bb2c6",
-    "dist/2021-09-08/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "81a7ddf94bf62f45dde9199df8b28ac9971d23b1817906e119ca4ea32000b08d",
-    "dist/2021-09-08/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "7ce055fd68b1c5e3c48c9f03289cd4eb3af619cc30a7103056b20fe842a92db8",
-    "dist/2021-09-08/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "6b853d5c2fd2dc61d89c26bf5b365f48a9c535dd30aa672f28f254af8fbcc9e3",
-    "dist/2021-09-08/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "32c659ea9578759020f291099f16b1d12eebae30e07d35568e69cd0721576c24",
-    "dist/2021-09-08/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "a73a918ec89b759f19b605df527471acbbcfd2e3debcd0601d7a3956f645bcf0",
-    "dist/2021-09-08/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "eabdfdac435195844bdfaaa5f8bf6b57cf045742c6180c3ff0822bd85fac40f5",
-    "dist/2021-09-08/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "a626ed9d5ce779e7fd8ab17d4dc83130a57200669730851bc68eb01d88bade7d",
-    "dist/2021-09-08/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "67f195e60d88b3e0f1a702f7ba0cefded2dca6ffc03ede1f9b6e4fd38592eb6d",
-    "dist/2021-09-08/rustc-beta-x86_64-apple-darwin.tar.gz": "01e5b6d7153866ada9d3c1caee5c95da58296acd7007aa93338171cc349af304",
-    "dist/2021-09-08/rustc-beta-x86_64-apple-darwin.tar.xz": "a0b87b79f87e97a746ad311f2bf36ee9d5784f504f844427415e4a983ea4a0ac",
-    "dist/2021-09-08/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "54ff5dfa917a5ebbaf77185d4efff9700d248dd66746dcb3942e29917495dd3b",
-    "dist/2021-09-08/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "2d9dddd6b9a3ef6c5bb0758dbee171f08882292ba17e1f98445a9cf196f9c02c",
-    "dist/2021-09-08/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "359690df63e15260f028d6838f4f5007f828c4a977cc657513b8ab6900f1d126",
-    "dist/2021-09-08/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "6d8d2b9d5964fe690d4f6fd7ee643bce5f049d19e33c7f3b580502ba83ce5ea5",
-    "dist/2021-09-08/rustc-beta-x86_64-unknown-freebsd.tar.gz": "5e47aa933805000f806984b09222808636eddcb58ea0b95913eae6c4f0ce913c",
-    "dist/2021-09-08/rustc-beta-x86_64-unknown-freebsd.tar.xz": "4e01128800f479a96597ce7eee9d2e76a5128ae1c13a4e0e2eb52e36d43cf559",
-    "dist/2021-09-08/rustc-beta-x86_64-unknown-illumos.tar.gz": "51cdd463ec6402dac5a4b0ab3b0e303ad97ba49c2a63e1cfa2d8036d060fd67a",
-    "dist/2021-09-08/rustc-beta-x86_64-unknown-illumos.tar.xz": "498cca6f9826a9180759a0446627e2e6dba50b6bf1051044e6e09dc714d7b3e7",
-    "dist/2021-09-08/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "59314c4c868e57a76f7cb4dd80cd9a7e6230b87080784db44349420c950efddc",
-    "dist/2021-09-08/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "8b3e2cdba3ff86144029f7c7446825dff79937ed8a30df15a33a779e9f694227",
-    "dist/2021-09-08/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "56dc8f8914bbe5beaa1e369fdc22d99ef98c9d864e24f5b7d64cf6188c400b1c",
-    "dist/2021-09-08/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "66cf18df72034540d756b29d69a4148123029ff512fc831a786fe15a9641382b",
-    "dist/2021-09-08/rustc-beta-x86_64-unknown-netbsd.tar.gz": "2315fd067e858501b4df44f2a4d042cef3f70b7314ee6cfe24749849b8d386ae",
-    "dist/2021-09-08/rustc-beta-x86_64-unknown-netbsd.tar.xz": "62b429e67f24365963b0744e9b4807ae2cb7aa280a5e425882e4894a2d3225fb",
-    "dist/2021-09-08/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "691922fb32f3da37532bb9be974ad1717af521ec2b71bca4bbb5e57f3c4cc3fa",
-    "dist/2021-09-08/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "2c9667209094b7a603d50d3dc684c505b2ab855c64dcd8b23fe09248a6e13cee",
-    "dist/2021-09-08/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "daee571bf222bb7addf0d495991acf3f5001b69bb97d31bb43f0466b4e43c600",
-    "dist/2021-09-08/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "f6d31e21f798427c5483256d54b25b6dca1d61ff8c601384c62648959ebbce25",
-    "dist/2021-09-08/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "98b2eaf259a1bfdc70e40a52e891920dec7fc6132ad8d2420f91655c793ea340",
-    "dist/2021-09-08/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "a97c1c2646f9628fcc92818d21f4925568681976727686701116d0e6a71693a7",
-    "dist/2021-09-08/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "a4df0726fba466a5180471d3e63735c2b5ee9794e9f42026b1e8ae404dd43ab6",
-    "dist/2021-09-08/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "92846ab58a75bddc0270c9f42234a6585edc9a382e2018baa776aa74bb13e444",
-    "dist/2021-09-08/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "a8dbc2a00d359c95f05b0b3cf08a12b6df9f888157ba57fa9ba4a134cf271075",
-    "dist/2021-09-08/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "44b17a06b015f9701291cec7e60b0932c5ebc29244f4a6e35736e9f5ccf47c41",
-    "dist/2021-09-08/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "ee54b0a25f061c29ea22977c7d36d6fa6bf85abee3b108135b53bcb37028af0b",
-    "dist/2021-09-08/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "0a721d2526a78f7e70f9a6c49d156b1c18cd627c066bc8f09b084910864ec252",
-    "dist/2021-09-08/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "584ba68113add6e113cffb5c93a8000cfea16d621ba337dc68cd4d106f5e2759",
-    "dist/2021-09-08/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "e450429fcd37f15b6e200f62d9cb4790b39b7227e0246b667c82fa3b9ecf1b75",
-    "dist/2021-09-08/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "e0aa68b96699402e7cc09329055826f63ac9899cf22828d56cf393476a70405a",
-    "dist/2021-09-08/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "6f10f279f81c35c718446e837f5f22fb61841c45f5172abb2d0d4a035065edcd",
-    "dist/2021-09-08/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "aeb05fcb66830d395bf9a819a05a44f179cad3f35016f76fa60a4959f9e3c69e",
-    "dist/2021-09-08/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "351ee1490533ac9fa00a21c6db6087cb498b0034cb21358d29a8b944bf0f77e3",
-    "dist/2021-09-08/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "418b0481fd2b074e9a0f195b9e07f888652642aced34136044bad997f7500802",
-    "dist/2021-09-08/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "90d04308cbfc845462687206bf13182d907afebd02bdf88cca9a27eb8f1e7e28",
-    "dist/2021-09-08/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "0d2f54c9927ac9de3c00f8f703d52d8310d1b36baa84dbcddf1159759b4bff06",
-    "dist/2021-09-08/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "7f2b33077267e6ae064b12c7d0082115ea7f011f168f0d0e3ad9dc7ac9d39705",
-    "dist/2021-09-08/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "bdc9fa2cdb295e453460f1bf7b12efaa673955c27b01f22df626de989c3e1a28",
-    "dist/2021-09-08/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "bacd376fe18068010ada3e52c531de5a07dcc8232f988feb9e90be59986efb3b",
-    "dist/2021-09-08/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "fdc93a8295c563be29793d36b6b1e25f579d187b7e234ced6f17b1fe3c1fac02",
-    "dist/2021-09-08/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "289fd400d4959968c0ffccd787d613943c8534527913d0dbed69e8a7251ca32c",
-    "dist/2021-09-08/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "2e655b764843cea5f0e70e2a5b2a0f13dd5fa65c4055f42c547e36372af08296",
-    "dist/2021-09-08/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "07f6657648d1d7033030e9e2d05bfb9ea0022e63ae72320074a3d09ac9639d09",
-    "dist/2021-09-08/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "b78878ec58d6b932d3d1f8e1fefdb7871b1404c701ab0d2f8645246b458ba650",
-    "dist/2021-09-08/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "dfa79cb51708794d2c814bff6a60a63ca5358df3670179f9a9ae828811e72ad8",
-    "dist/2021-09-08/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "017de1a82a0e3988d1216771082b5d0e3e083dc51d4a0f0266f1e610bac166da",
-    "dist/2021-09-08/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "a0a46a62b9af14d2147939967e545ad812d9acebe3d1ed861321a6dfd8d554ca",
-    "dist/2021-09-08/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "54dff0daec5dd2a2ab23cf4e92bf9b2d71839c37144b52e5b5aa899ddf027bda",
-    "dist/2021-09-08/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "e743e45dc695e0bd9a1ce5fdd183f89951a329ec433bb510d37c47b435152a7b",
-    "dist/2021-09-08/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "0e04ae69e03d9e7e8d1d60a265c7ed3c3608a19aaef6ad4aa7ae2b280d3552b8",
-    "dist/2021-09-08/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "6ec865bd38b0fde2c9c823f4cb110b96c2aac4f7976cc2a6be48ffa214aa4bc7",
-    "dist/2021-09-08/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "3b833517415dee73b1e0d381df441a96856e3bac77f101545624c382aad7902c",
-    "dist/2021-09-08/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "7a8a447cc2167d0a998ad3858dfec88beb8658043655087d208affbc94aa3e62",
-    "dist/2021-09-08/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "20de8ad3aa7507dd9657c4a4b959c38cc7f732a87bb757183033f78a96288e45",
-    "dist/2021-09-08/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "99561b207ba61b455d1522d95143ca4ccc6474187be2f38f1ebff2ed63d0092e",
-    "dist/2021-09-08/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "145eb25cc3b295060c5f5a354ea2321cd39df17ea4e3a5c73c3eea105f7454a4",
-    "dist/2021-09-08/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "356ede5cd8a7d51f9e25a54c329b1be1da7d6fe418cbe86fdae9c8bcd9970ac4",
-    "dist/2021-09-08/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "0cc0f10763b73c5e4c8bdcd15a563d7e9d705b192ed6e8edc50dd6a71b874761",
-    "dist/2021-09-08/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "d734aefabe95fa03710dc75e9851c8f2e654f19cec1381ecb18281837d19db38",
-    "dist/2021-09-08/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "e1c28472a81312560ca36719f0b61b7212a07d63e85d745f97cd8e3b9ea8f191",
-    "dist/2021-09-08/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "4d6a62738f842e54666c608a466c64f896097ffa65d10d30361704e4b8496eed",
-    "dist/2021-09-08/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "75b21690480f6214ed174ca86297d9a41f37731560adf5782ccd7116b0df583a",
-    "dist/2021-09-08/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "5c08f45f557da789d39bf203dfbcf2667f4196dedad327a19dc3ad5bb783079d",
-    "dist/2021-09-08/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "a7d579672b94978e8427584f7e9d2b6534f320719252db46fc6ee85082d646ff",
-    "dist/2021-09-08/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "6ffbdb558b9d25e9d923534413b25dc99bb5b9cc92b4774d5255cf70ec20b20d",
-    "dist/2021-09-08/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "fba0e7bc1401b830223b5207b63808e28403f48d1591c7d47c1681519c1883f7",
-    "dist/2021-09-08/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "644b3acc47cd7bbbb5405683ce94e7f32a8313ad265da753026bdb6c3687b608",
-    "dist/2021-09-08/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "3f152caa88299ab8aca2c6d39a5e36af995b95e3394c7d514ed94e87f7c61fa3",
-    "dist/2021-09-08/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "5f92b4d12a9eaa50b29b81a3dff1959e59966f362b67c346b74403138fdb320d"
+    "dist/2021-10-22/cargo-beta-aarch64-apple-darwin.tar.gz": "b81ef641492ff2f03a93c8fbfbcfa78db2f6574d1998569d68dd2ba0e08ee186",
+    "dist/2021-10-22/cargo-beta-aarch64-apple-darwin.tar.xz": "925090782ad982202ca554a84e9d4a7b190f94b0b220c23e73235383d6ca367d",
+    "dist/2021-10-22/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "eba42edfebc85c744f4c6874337847748df65e430915f47238a93b1b7e96840a",
+    "dist/2021-10-22/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "fd04a8c4058ff287ea0256fd9f33a4b04b4f098d6911e8d827525cdeda6f169e",
+    "dist/2021-10-22/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "c7abbf1f265435cc9f6f0773d30321fc99353e0ddbf0004d00f47433eb3aaab1",
+    "dist/2021-10-22/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "3363dfdcd7106841edbd9029676ac339ff54c142921d71d92e308bee2ee33066",
+    "dist/2021-10-22/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "fbc5d5f70a36fc73f4d34d101aef4be78e38b5009ebf690fe46ba32eff6c1fce",
+    "dist/2021-10-22/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "220f23f50645532df4e5a4b1d6d894ce66a6ee2e5576fdf552081644a74a1c8f",
+    "dist/2021-10-22/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "94b42b8639ce541c1a355991f20d9934c72e766b6200d742d2d5b3b2f499f782",
+    "dist/2021-10-22/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "e32e9df3ab261fe20c363406d655fdaeeefc9dbb3d69da4551cdf9c22c418eb2",
+    "dist/2021-10-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "301c303ec0db0e342ecce4e259e79810e082766bac8f9907c353bdf490177863",
+    "dist/2021-10-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "d6f9409076ab4e2dac5ac5c07bac6be30e83e281df9efe2fa68386928e2e6faf",
+    "dist/2021-10-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "a4a82d48b2b1e6a49c0a765f9ee4d01e7ce4b0543128745d13cf4684c56eca8c",
+    "dist/2021-10-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "c9ca524ba0e76d9fe38f0e4af337d14b97fd97dcd83d80ebf4725b5b03bea3ac",
+    "dist/2021-10-22/cargo-beta-i686-pc-windows-gnu.tar.gz": "973eabda91963d58a9cdd1491bcea15834874fbca018287fb7f5c8bdcdf323d1",
+    "dist/2021-10-22/cargo-beta-i686-pc-windows-gnu.tar.xz": "cbbc14d1ef0e4579167fce4a5fac43b22c87882049a3d0edfbace9fc5c103ad3",
+    "dist/2021-10-22/cargo-beta-i686-pc-windows-msvc.tar.gz": "ef090943f6c90bb3327225e0256e73762ca2f73ae5d0d07b2c828709077e1132",
+    "dist/2021-10-22/cargo-beta-i686-pc-windows-msvc.tar.xz": "42708683ba5ad855880ec69d92192bd9f99ebf102beaf6c53680cb8733fba9e7",
+    "dist/2021-10-22/cargo-beta-i686-unknown-linux-gnu.tar.gz": "b6c260ba19734482439bf6d12b8e87e82f269f1bec447ec85e59372ef6489eec",
+    "dist/2021-10-22/cargo-beta-i686-unknown-linux-gnu.tar.xz": "fb6036ff910d075fb5e483000af641328e6d7d01c33255c099ed1b0302239918",
+    "dist/2021-10-22/cargo-beta-mips-unknown-linux-gnu.tar.gz": "71e4e5fcf055251089ac0d37b5ad873eaee6aa0380438cd68f140a16d3a37cd1",
+    "dist/2021-10-22/cargo-beta-mips-unknown-linux-gnu.tar.xz": "b89acabf106b10c5c3421574bea83d8baf1f29d040c40d5522f85e2e6afa6373",
+    "dist/2021-10-22/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "f544ea08d2f6086dc49c4d635116f3b4b804e5b68251e5fad433d538ae5e8226",
+    "dist/2021-10-22/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "54b0cbb4292cc4733a704017775e5cd4a9be34d53a4c666d6fc556472b508e1c",
+    "dist/2021-10-22/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "5e81253ec483f096e23ed98f939220b029814c041b4b72b93e994cead3dc4f4c",
+    "dist/2021-10-22/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "1a66beee5ccfd8b0fb4de52bccd11a0057248ac7fe8daf4f4d6fe0c0088044ea",
+    "dist/2021-10-22/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "2a6cc2e98ed575df64661595b6e1ec2814ed79fb63fe697c0201193eb52d70e0",
+    "dist/2021-10-22/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "ab3f70ea6977306c26c9cc368d64a116716f9ac6ad1a55eed23ddac894e7717b",
+    "dist/2021-10-22/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "ddd840c0c19077b4b45dc85920a2b2a37f176795b3d9390f1faccd44aa3d55e5",
+    "dist/2021-10-22/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "f5c9f1df082a7c48a63e786e5104d31e616c31d47514e9233b4a86d24700159c",
+    "dist/2021-10-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "4d39fac4d45dd73221b93b1d1351988ab4bf07ab04187a815467ab9b992f9490",
+    "dist/2021-10-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "3b6b0d38a3644028ca76347d5b82da6bac6e761a235516bf5b321d12ba909519",
+    "dist/2021-10-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "0d5992a6e66207e4ead98d5bd627c181a052775f03ebdd2a0313574092a12abc",
+    "dist/2021-10-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "217940928d5c22553f910f3abf7b56bc832ddcd36282cb85c4b8142f9411147f",
+    "dist/2021-10-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "67ce7cb12cbd06e114a2f5dedd1d94c844f091ab05a764579dccf30e6158ea46",
+    "dist/2021-10-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "2cb17c66bdfcfeb567bb021c25c33a8c2b8df1366601d09fd9332278517a2f4c",
+    "dist/2021-10-22/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "e25a7fa310019a3457b317c9e3fe052602c82a25939c2ea8c012ff6016c622d9",
+    "dist/2021-10-22/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "1722ef69ea949c365f6b64735ee31dc92082db1177b94f0086b8aca790378398",
+    "dist/2021-10-22/cargo-beta-x86_64-apple-darwin.tar.gz": "f171fb45017640db15d437198b25758c49649b64338118501905f48ce957b93f",
+    "dist/2021-10-22/cargo-beta-x86_64-apple-darwin.tar.xz": "59c5f8ce9fa9dbf3e96dd8a38a52b8bff0ff0d97c081b1d343a654257df1e500",
+    "dist/2021-10-22/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "4f219f3661a03330b33d33cebadd5eac759968e1c4c3449f0f27433e715ab55e",
+    "dist/2021-10-22/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "5aed2d9631a2aa3fe016ae5e2ee312aa5357ce470c26c01171d14a159af7750c",
+    "dist/2021-10-22/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "c9dfb9c486cedac794cab6ac524805c10d2853c15416f3037ff4a5098514427a",
+    "dist/2021-10-22/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "a1e0aca8a32700e62fbc73b17dbb0be711db4e9caf535440b08bb1465d6a9c9c",
+    "dist/2021-10-22/cargo-beta-x86_64-unknown-freebsd.tar.gz": "61c041ba51632c029d916f274ed8ff92f1f7b23b5e9641591828e6251e205f6b",
+    "dist/2021-10-22/cargo-beta-x86_64-unknown-freebsd.tar.xz": "b61464e9e1c2e820a237f1f3d91cae8b0e62cda16dea51b32a8cf695b7a5707c",
+    "dist/2021-10-22/cargo-beta-x86_64-unknown-illumos.tar.gz": "1f9b7e500b22c34fa3080e4a15397a3a3827797c237d21459841055b5cb6cbaa",
+    "dist/2021-10-22/cargo-beta-x86_64-unknown-illumos.tar.xz": "97aba07cede4a9228ff1b937b8e884b23e9e246afe39b9d68896e6b4a346d972",
+    "dist/2021-10-22/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "c82bf6a11f468ba1d865a3cdc036b03f01e63a23272512583afa9dd9bbf95824",
+    "dist/2021-10-22/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "2efde3ef57e877f7a0aaba264ec14bc94d0cf3e4451b072c004c37e3f86288a9",
+    "dist/2021-10-22/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "17df9a194a8cd80871981fbde5fc333794e36a4ab219aafa7849ffeaf07d95c1",
+    "dist/2021-10-22/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "54fd84ff5bdf3221b151945ceacd71f51e71898927fe4b57887a0eba5d3e3676",
+    "dist/2021-10-22/cargo-beta-x86_64-unknown-netbsd.tar.gz": "0bd987dd970f98b297afbb7cf4906b1d2045ad09df929e8ebd291125e3c36126",
+    "dist/2021-10-22/cargo-beta-x86_64-unknown-netbsd.tar.xz": "054af5ef3148902a8fe07c2c445ea98a526f63203c13b849ba464d17145afe07",
+    "dist/2021-10-22/rust-std-beta-aarch64-apple-darwin.tar.gz": "2228315b5b7280a7ea9b3acfdfa1a8f0921391f67d792f32f53c1b303565a20b",
+    "dist/2021-10-22/rust-std-beta-aarch64-apple-darwin.tar.xz": "777d4c1c6bd3430771280dad79aaa16a6903901875529391e4779f0c2fadb0d8",
+    "dist/2021-10-22/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "1d2a74d8ff44feae6551613c182a87d078c0d4cc8f5117c6a3763f28d0af306e",
+    "dist/2021-10-22/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "67ab7519c7182a582fbd3e477b8bbbcba143a76e442cef94a47f0a03fa36ed05",
+    "dist/2021-10-22/rust-std-beta-aarch64-apple-ios.tar.gz": "2c2a8ca955cc99e86823bf7ede5492b04ea28c182a94d0f59b0d542f10128e88",
+    "dist/2021-10-22/rust-std-beta-aarch64-apple-ios.tar.xz": "bfd421654ad72aaff2610a104d0ea2afec579803ed16ac70ab594067cac292aa",
+    "dist/2021-10-22/rust-std-beta-aarch64-fuchsia.tar.gz": "b06020ac4aa9b5236d1888a59e2dc3519ac63c760ed0ef47b706466df437d5ba",
+    "dist/2021-10-22/rust-std-beta-aarch64-fuchsia.tar.xz": "92ffbe22d8fe9474aef42cd3bbe4808c4afa212a3f65f07828b39848dc03a1f9",
+    "dist/2021-10-22/rust-std-beta-aarch64-linux-android.tar.gz": "55aa7b2b3b79aba674bfc496efba37400086e192e6c7fa8483f5501ba31e68a8",
+    "dist/2021-10-22/rust-std-beta-aarch64-linux-android.tar.xz": "6219a156e46b7056a9046ab5a58af1a5386024b2961528a54fe6b1c3ec09a91f",
+    "dist/2021-10-22/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "f43fecdf75ac81f8b18ba5ec59625ce93b0debd27c0016edd76d5058e8182118",
+    "dist/2021-10-22/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "a032b56685b2b8431068565d652e5a174dbc9febe6de96945c037b96359d5cfe",
+    "dist/2021-10-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "bdb7d197cc36c774fe4d59a1c86b46325e93d82462c1cbe87e8ab415aba78e4c",
+    "dist/2021-10-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "061cb27b6d5b8e416457137334969733cd0727afe75d63d7954ccf547b7edc51",
+    "dist/2021-10-22/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "895d936a579c9642efcfdca400662264b8ba84ab9130f88e4dcd11c968a81e4d",
+    "dist/2021-10-22/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "29f3aa4005c64fa28f99af20221956ad21aff4a37c5cab9723959ddebb3c2b9d",
+    "dist/2021-10-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "b1e326b0ab30a2f9172a55272926cfa62dca9fbc2c590579f6c7685b8b4ad789",
+    "dist/2021-10-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "616fa68272334400c9110cf5a2cbd7d5c6e462cef8d2c5bc443c3ef6e9843e3b",
+    "dist/2021-10-22/rust-std-beta-aarch64-unknown-none.tar.gz": "ec7d513787434a3cf2d523dcff7e37c28cff4b09b13be93c024729cbbbb5aa83",
+    "dist/2021-10-22/rust-std-beta-aarch64-unknown-none.tar.xz": "5a396cc0499690193879d10da333f5a3acc6586f1c216f751a1e62bf1a8b6618",
+    "dist/2021-10-22/rust-std-beta-arm-linux-androideabi.tar.gz": "f9baf9d74b094cabdab59c1eaaf5238caa175e7865c3497c34eba68be5b2d756",
+    "dist/2021-10-22/rust-std-beta-arm-linux-androideabi.tar.xz": "0c5f14f311e29233057ea466123ef9c33e3fffdc798358f0f339ce3869ffe9e4",
+    "dist/2021-10-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "e3c2ffd3d69ba9035048fad22103989ec97b892de955a94015e16578e42481e9",
+    "dist/2021-10-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "3e716d6aab270f764233f50a25a33d37a6d34c2dea23b3cd1aa5733c72c13958",
+    "dist/2021-10-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "65b74540b47fcf7fc8a88cbc5cfe54ad67c1060722c37af7e31bebe2b3c204ed",
+    "dist/2021-10-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "4bf4f75f7c4ed171ef7705764f71eb899763205a9a4727343b96cb209691a97c",
+    "dist/2021-10-22/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "be073a69a1e9de0f87511a5a8b3454b3a2d24319571c25f347f7213c872a54bf",
+    "dist/2021-10-22/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "57be5edb2c00745235dc486b4e6e6f0e6b40edf16481405abe3ac360190040e1",
+    "dist/2021-10-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "53c39c89d7b19e45e1a4f32b07eac8214a7d5d277a83e4a88d7ab8820bf2de86",
+    "dist/2021-10-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "b9f058907117e3f1921fb5ee73e04c6114154870067dc8791382f3099aeb5c0a",
+    "dist/2021-10-22/rust-std-beta-armebv7r-none-eabi.tar.gz": "bc3d93dd7381749a7d24eb904c7fa74aa6e2a575ad1af5ef7e34ffa07e91105e",
+    "dist/2021-10-22/rust-std-beta-armebv7r-none-eabi.tar.xz": "b605ced5cb597a2973417f4de55fb39cfe12b1209c4249ced9232091395d8e91",
+    "dist/2021-10-22/rust-std-beta-armebv7r-none-eabihf.tar.gz": "315432af4541ceabb14891da9ab6af6717bba88f1caaf216053f75405ff8997f",
+    "dist/2021-10-22/rust-std-beta-armebv7r-none-eabihf.tar.xz": "aa643ea7978ea7911e50ab65ba0af7bf018a4bf9ded1da8e161ee7ab13decbfa",
+    "dist/2021-10-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "3f780d36c780b1379fde18fbcd6a1f75efa766b56a4aa6933c9bb88dcd4f4ba8",
+    "dist/2021-10-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "d0c87b4127f10c85368254377013053747c10d2d7dafae2f5643a3526f938f48",
+    "dist/2021-10-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "fb4a610676f9102dd206a1762be6bf7838b3eb0fa08629df8199573246bfc38e",
+    "dist/2021-10-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "192d9bf1354737dc576bfdcc310c936e065039f39303370008dd0fe3d3e8ec65",
+    "dist/2021-10-22/rust-std-beta-armv7-linux-androideabi.tar.gz": "5dd746bb8db14ca9f968a651f3ae7e3c3c5a505800c0c3da8f6469809a81230a",
+    "dist/2021-10-22/rust-std-beta-armv7-linux-androideabi.tar.xz": "2cd651fad1f2820a2bb9b828faf292d3029ce633d24283d9a5363a726a024044",
+    "dist/2021-10-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "06f337db74903b607d09151f8a5178ce48e8b5905af407ae9b37445fe78aeed0",
+    "dist/2021-10-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "8851247487823bbee990937a1f83578d910985ed4055fe3bf339871a7aa28bce",
+    "dist/2021-10-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "5696a2c0fc2c3141d43f2d97d8e4959310032756cbdf0140dde28a5843b431e8",
+    "dist/2021-10-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "d8f9a3669d550f1c6f338d99ea74f4e48771620d4125bbd408cc750a70ee4686",
+    "dist/2021-10-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "326e4ac48ef1e1a60c434699b5fb09b9d0581e020bb745196011f2f61af41a13",
+    "dist/2021-10-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "cbd10db975412fe275d12b81cdfd5e97c0b464194639dcc439cd72a65790d601",
+    "dist/2021-10-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "977c9e94e25fa9a1db5f93ec800d529d80d874ceb2ed3a10bff63639fd24da59",
+    "dist/2021-10-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "0729470e2138e90d9140e30779d7397e58ebfc1ec243e55caf90ab12ef904da4",
+    "dist/2021-10-22/rust-std-beta-armv7a-none-eabi.tar.gz": "3115e3b7f0981dba799902b212f350608042a2beff3bc3b32e930e9c9c3cca17",
+    "dist/2021-10-22/rust-std-beta-armv7a-none-eabi.tar.xz": "75b3d8eba51877916129d8dec07bc86ec6e88076af79cc221e8543695e64da63",
+    "dist/2021-10-22/rust-std-beta-armv7r-none-eabi.tar.gz": "9787d23a7078c94b4ac33d34cdfb68da586d777f020a6284bb1540b54069f476",
+    "dist/2021-10-22/rust-std-beta-armv7r-none-eabi.tar.xz": "c8f9b933b2e9c955e6bbcb141082f6b5833f89f34de16e14f54e8d4aac02c473",
+    "dist/2021-10-22/rust-std-beta-armv7r-none-eabihf.tar.gz": "ce9ea3ade0886bf7ea40a1066981d172d915aff4c54ca325d72ed823c7e17787",
+    "dist/2021-10-22/rust-std-beta-armv7r-none-eabihf.tar.xz": "2d2442ed2ac017777d3fab1a3f69a578a9db1139fa1aa63dc87113071f08a6f8",
+    "dist/2021-10-22/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "98258ea791d398c6a29e1ebe28557aceb59ac228a0bb1332bdbd9f702c61a4bd",
+    "dist/2021-10-22/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "a4172c8c2b719d0391654968377fdba932343e444bc78482f19f731ca45806ca",
+    "dist/2021-10-22/rust-std-beta-i586-pc-windows-msvc.tar.gz": "2221360e32bdbbdbf073a4bc1fbbb98b86bd0a1df526cb8dd05dd521ea402c7a",
+    "dist/2021-10-22/rust-std-beta-i586-pc-windows-msvc.tar.xz": "03c53e31762e5ccc58d1296a8fcee123592dc6d3b88d0c81ed1f8305545faca1",
+    "dist/2021-10-22/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "612eb9bc2a06779ec05f6033f44b18f283d6cc8dccac0d5c81a6d09f515fc077",
+    "dist/2021-10-22/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "70ad4e52227ae069a9e99cf53e07470267abf1f2ae0398192ac854cfd31d50d9",
+    "dist/2021-10-22/rust-std-beta-i586-unknown-linux-musl.tar.gz": "8a5dd3dd62cb31c77aec2e00847812ba53e951fb284c74671cf3875b18a015eb",
+    "dist/2021-10-22/rust-std-beta-i586-unknown-linux-musl.tar.xz": "10650efcfda713c2a3053a9c505847dd021bed19b1e3af12d58742deb76cb421",
+    "dist/2021-10-22/rust-std-beta-i686-linux-android.tar.gz": "6fb4f4ac2b448bebade72ba2080bdcf579b6a40041b311301452ee41ea267ea1",
+    "dist/2021-10-22/rust-std-beta-i686-linux-android.tar.xz": "6e0e8feb477ad35bab1ef599f51f64b4720dc37194dd6354a7a4bfdbacbf2c82",
+    "dist/2021-10-22/rust-std-beta-i686-pc-windows-gnu.tar.gz": "0b0c0e86be0fb63dd56b419f0b8d05eb59841649120e16a8216bbe490a76db1c",
+    "dist/2021-10-22/rust-std-beta-i686-pc-windows-gnu.tar.xz": "c54a116404d31591d6a6a1a332e4bb8ee177ea7a0367b11eef6a8cae6c1c0325",
+    "dist/2021-10-22/rust-std-beta-i686-pc-windows-msvc.tar.gz": "14313eb7b20a3a3739a28406b1544cfe421c593a3198b081956a1a54387cd0b8",
+    "dist/2021-10-22/rust-std-beta-i686-pc-windows-msvc.tar.xz": "54fb4abc77fb6c97929641095ef86e559a4cb116cdac7dc4bf34a81aafa03681",
+    "dist/2021-10-22/rust-std-beta-i686-unknown-freebsd.tar.gz": "9a2a5b2d3d5cd98cb3f9a43fc34d3dd0dcdf9bd104798380f70373440edaefa4",
+    "dist/2021-10-22/rust-std-beta-i686-unknown-freebsd.tar.xz": "d0165b16890da11196a1e4cd6b48d545f44ddb996ba9515a919ecad85cddaceb",
+    "dist/2021-10-22/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "a42e125c252eed17664a50713d5e2f0c43f0f9ffe54e471500db75352d1e2147",
+    "dist/2021-10-22/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "705185a2b4b98f6ac16a9106af60f30618c24d6d93ffb0283a41cd31f992750e",
+    "dist/2021-10-22/rust-std-beta-i686-unknown-linux-musl.tar.gz": "1a01712d4b8b470548c22a24e7e9524c0ddacfcf15459b490531e68e62b8a400",
+    "dist/2021-10-22/rust-std-beta-i686-unknown-linux-musl.tar.xz": "a86f8080ea25267f7e127f23bb75538cc3032091061b1fc3ce95c917d2a1cc92",
+    "dist/2021-10-22/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "d6d06becfaa6a4b0cb7131fbadd6cc6ff58edfa11fc6d98e69d2cf5388e8bdef",
+    "dist/2021-10-22/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "65bafaa34e506e8bab15d2442742fc075dab2ea8687c69f6090acf0204b6fb06",
+    "dist/2021-10-22/rust-std-beta-mips-unknown-linux-musl.tar.gz": "53a48c17c4ed3740049d0c88b14d2a1189e7ef5fa08a926c8ca26ec5b2b298b8",
+    "dist/2021-10-22/rust-std-beta-mips-unknown-linux-musl.tar.xz": "14525b83b69fc54d4c808ffb69e06f015850ea9186837c670dcc23b5bc66d4bd",
+    "dist/2021-10-22/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "1b8f11cb2ab076f00cd601c1465ff3a2e3857cdec255c8ecc1697efa713f5626",
+    "dist/2021-10-22/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "31e824a6243a6e15ea96a2984c69711e312eefa5214ba349ef6d6a4c42fffffa",
+    "dist/2021-10-22/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "89178cf43cfbffea696390c317230d39108e529803e28ca60d37b6167e589dbd",
+    "dist/2021-10-22/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "8b9fc0f9a2297d15abc86db95ac8768e872ec1acd21461e599a1aacb80f4b182",
+    "dist/2021-10-22/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "13ec0039303d3df358ccfa4fc19924df0ce17b31e8f57b13e7367db68bb9dfe8",
+    "dist/2021-10-22/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "1266340a228c8cd657d0ee7ef257d80a33b193c4ecb742cdb82d469772311499",
+    "dist/2021-10-22/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "b100adc79e776116a267bc918ded30c4c8d27d83ed21f65f9428ed8831d101b6",
+    "dist/2021-10-22/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "6966af76ccf83f37657efc4aff88887de81642dddc3f2ef59dcaa91219d4f674",
+    "dist/2021-10-22/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "0b7a859f952741a740458609cd207d5f7291c054fc6d9a0191d3acf0f216bd17",
+    "dist/2021-10-22/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "2e6e61f68fc3772a6c3b3f0b3be6d99bca1a57b5f568e87397765cf6fe867dd1",
+    "dist/2021-10-22/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "881946b261399e50992beb3cc613ca2141736a7480103fa1fb117c1e7df2b1db",
+    "dist/2021-10-22/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "223a78a4c5055ca00a7d5b40491aef9498a204759cb388e734408e305999713b",
+    "dist/2021-10-22/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "76d81922eb6f61d33c10f2754ccc9b1394ae09feee5818b23b62f768f0e6a370",
+    "dist/2021-10-22/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "be57410669ba5a516dc935fd1eaa73b2d0d3d237a2eb184a8dadce919bf1975f",
+    "dist/2021-10-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "cebf48de57e57285c91092abc01ab1fd9bc7eb660eaad3db2ce71877bd6b9352",
+    "dist/2021-10-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "30a8fc47441c4f7b34f540f5132b3d7ff9756e8906ac6e2b9df5ea8fb622ad65",
+    "dist/2021-10-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "7deb058683792cd3fcab92b950f653a4ba0d2a2997bef508c6d1d04be319f057",
+    "dist/2021-10-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "c5d26bbe5b6c64ce9cae78465d22faa98ef956dc4d8bacc91a127a7f439f7b11",
+    "dist/2021-10-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "bf06959a991270e9e15d538e70d078a5241b6e87d62a55a655e4c2f9e8ea2964",
+    "dist/2021-10-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "d85b330532cb6743071ffa117fbe8bc26b9c6167a0ff76c0ba32fb17c0247c70",
+    "dist/2021-10-22/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "7dda5e010ddb4afd6e6efeb9f43ef17cb30af7ed9f172b59e6c737b2f9d66ef8",
+    "dist/2021-10-22/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "35d8feb28897bead99c17d952b711888f2f6f613fef767f28e3593fb4aa2dc36",
+    "dist/2021-10-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "2e7067692c10447d50df8e9871f95b4ea925a88c5792f973b3c51325afaa8457",
+    "dist/2021-10-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "4b2d3bc61727c87f7c2ba129e9147621c3e3efd542feba3acb6596ea91d10d71",
+    "dist/2021-10-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "093aa10e425beef7d66e9986b045543b3dc04c296fa3b3fdd9071fd6d61b269b",
+    "dist/2021-10-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "8f3512c368b7c44c7d8ec9e1dbdbaed344859ebe2d0dcee22118397d41b841b3",
+    "dist/2021-10-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "adab0b58b93d37949eb35d4a6f3ba9e6b43630e4a82f1d9047116f1462cd1809",
+    "dist/2021-10-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "6a0410d1194ec0c471e384c5d02aba555efbd47b36a3544c56674fc2080c51e7",
+    "dist/2021-10-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "19c8be8430ab59b92006e0bccf186687569ca172b54f934ff4763da20cebdb58",
+    "dist/2021-10-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "6cb9647a504683fa5c67e5ab2e737bf1d6004dd4a7ffbaf593dea0f9844ced6f",
+    "dist/2021-10-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "cc2d94e753035ff0b49490173b042d21f1ea58711f7c6ce5cfdfd79a76e539b1",
+    "dist/2021-10-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "de398391e577f2fa09f369fbea4114c6cc0f1412884c6f52c97d71c74920462b",
+    "dist/2021-10-22/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "feefd67b9c9dceee7ef7947753ebd990a914d7a54562b718e6704d35a1f5c75f",
+    "dist/2021-10-22/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "1b550a911a51514f8d69b9b763cc3379cd674615090652a253eeb7b585d2d97d",
+    "dist/2021-10-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "4d7d78589d6d72e5ce60d6997394c4d7ff03fd2bae471ef3334f1d5bff9f18d7",
+    "dist/2021-10-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "ec499330b2f63047eb43bf98b1e66d301d7ea7015447c83307ab528421387502",
+    "dist/2021-10-22/rust-std-beta-sparcv9-sun-solaris.tar.gz": "7e48f11954d44dade640c86cc87d5841ebd708643cd5220ae7d07127f71ff333",
+    "dist/2021-10-22/rust-std-beta-sparcv9-sun-solaris.tar.xz": "5038770dbb2dda71d32c4270653fd3ece96062b24ad55dc8def6475e464210df",
+    "dist/2021-10-22/rust-std-beta-thumbv6m-none-eabi.tar.gz": "b8b9a59bf1a9127b26aff54dde3a1da9992a99fd3d601be7cc1daa6ce3c7b6e4",
+    "dist/2021-10-22/rust-std-beta-thumbv6m-none-eabi.tar.xz": "e0a96a8b105466a3279da3d9bf589724def7326448bc6f51ae6f8e8aee2ac880",
+    "dist/2021-10-22/rust-std-beta-thumbv7em-none-eabi.tar.gz": "cc3a8d935ae2101cff8af86fb066c09672f9fd0297cd9d6b960c9f4877618e98",
+    "dist/2021-10-22/rust-std-beta-thumbv7em-none-eabi.tar.xz": "9bafbfbcb01e23f58b1adc7fab26e8ebd135c5c20589887278065f75cb5b5350",
+    "dist/2021-10-22/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "8dd7c2cbc2c24e5220ff6a7f5caffcca6605f3d76ff66f766af00ba4bb316067",
+    "dist/2021-10-22/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "963a698d49c8742ec5c7520fdefa1668db573eb01bd7774f80133496122b0517",
+    "dist/2021-10-22/rust-std-beta-thumbv7m-none-eabi.tar.gz": "3a01a35a10f0efe48cef64d45e80fccab31df8287f500bf280b5d9bd5784ea3a",
+    "dist/2021-10-22/rust-std-beta-thumbv7m-none-eabi.tar.xz": "84a5b9d9cc21a13cf1e2e1c29e7af63c75690cbb2293c63fe95e075ebf59815d",
+    "dist/2021-10-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "946e96f404b8a9f4c8139e90172ea26f3a6c509effc6e1ff16a49dc9ff6cc1e4",
+    "dist/2021-10-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "787cd874aeb33e4a4fed2726a571d39f6687da20625aa9a485a95d7167b321b5",
+    "dist/2021-10-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "70fd17c069fe4b6a318d887794c54a142275cc65f088a7bcbda5bbbd7c9d6aa7",
+    "dist/2021-10-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "15ce829bd9ea0a1ee918e7887392ce1e74e00b23509b802f5f45550176d78768",
+    "dist/2021-10-22/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "2edc66ee89c319ef7c9520c5203185a5b5203ca4ea9996e0142075273ccf84b6",
+    "dist/2021-10-22/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "3c129a2557639fad501c7f1474f45535a55c33813a889f08521f4a7d527010ab",
+    "dist/2021-10-22/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "354e644c51ad5863bb0eea09e0c5d1aa32858e7025c039d693e2e433e1c18c04",
+    "dist/2021-10-22/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "6996a329a81624537d45b2401b8dba81911e5c61d2fff6bcd63c5fb15b2fbec3",
+    "dist/2021-10-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "97d6aa47e209650860e97d442f7ec5c5da385399aa5f06bca4c7f9a08767026d",
+    "dist/2021-10-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "dac5cadd67e5d162e00861ec5d2c96166fe1a80954237068aed6072afe0f728e",
+    "dist/2021-10-22/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "e0161120cb6cefb23514c839eb2be13a54139d4f408563bd9dc1d6b9d665496a",
+    "dist/2021-10-22/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "94bcd63f3712cb3b09948ed62c8db889e2bc78b97d868c89386f912d0daa1b4d",
+    "dist/2021-10-22/rust-std-beta-wasm32-unknown-unknown.tar.gz": "00a37ebbf36bd66ab6e0b957e93c7a2e5c2d8567583c65873abc1c79b37bbabf",
+    "dist/2021-10-22/rust-std-beta-wasm32-unknown-unknown.tar.xz": "75589caa1835ee12362a2ad581828c9faf0d527f48d5a07c1d7f0b810e035def",
+    "dist/2021-10-22/rust-std-beta-wasm32-wasi.tar.gz": "2276b9ef2ff2faa665f15d3572abe0d13a5bb9ec0ad08a6a0c00d9e143464993",
+    "dist/2021-10-22/rust-std-beta-wasm32-wasi.tar.xz": "fa132a08849d7c583dbf37db97f3702c263b17de595823d87fa14e56ff21ef3c",
+    "dist/2021-10-22/rust-std-beta-x86_64-apple-darwin.tar.gz": "47454a419e6a87b057047c002932cd2f0f52a77ed4c3b4e4d9b65cc4f4ddaaf4",
+    "dist/2021-10-22/rust-std-beta-x86_64-apple-darwin.tar.xz": "f9040fa310d122651461d026f43873aa18d5f2c63a9f3bdd47f9a034e4153348",
+    "dist/2021-10-22/rust-std-beta-x86_64-apple-ios.tar.gz": "e143c4c8d394810c7734824476dbbfb2a73b3b62cb8a708f796e0c0332deede9",
+    "dist/2021-10-22/rust-std-beta-x86_64-apple-ios.tar.xz": "53c660ef68e1898574f62725c2f50fc2f26539143c0be0675327a33511142f8f",
+    "dist/2021-10-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "e419db2f8f12467335c8571902f1ed163a5407394914f55416fe948525140ec5",
+    "dist/2021-10-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "efd2b6df7dd439b0ae0312831afd4517cf19adf619916eeda1f571daf1dae723",
+    "dist/2021-10-22/rust-std-beta-x86_64-fuchsia.tar.gz": "e669378ed5da5948dbe232323ef3926f37ad430feb8c398259229fd18675de20",
+    "dist/2021-10-22/rust-std-beta-x86_64-fuchsia.tar.xz": "5a26a35164ae44467d256e6fab0e8f45731e8840204635ac9b1dd1d7d8f96810",
+    "dist/2021-10-22/rust-std-beta-x86_64-linux-android.tar.gz": "0d922ff7d7658c296246c22f4440a8975c8036f7159508e2fa964d1f2ad3aebb",
+    "dist/2021-10-22/rust-std-beta-x86_64-linux-android.tar.xz": "d775ecb6054216f0f48dbd0acb7710fc097ef6d61df9c1f59139721ada7bef8a",
+    "dist/2021-10-22/rust-std-beta-x86_64-pc-solaris.tar.gz": "1e830dc490e9b00b86c9d55c974feefdd87efc06c1bb90088b41737151987dce",
+    "dist/2021-10-22/rust-std-beta-x86_64-pc-solaris.tar.xz": "cb37a89a871d61849f9aa262bee7248813a8c7a422872aa3926f20c1adf4ec63",
+    "dist/2021-10-22/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "d83a17c374e937b9a06a364d0be980f4dc953df01efccdb3a0bf853ffd889718",
+    "dist/2021-10-22/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "94fb51d1db6482adf683b9953fcc942923fa5c85cbb63f7b05ad19c24272a21e",
+    "dist/2021-10-22/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "4b7cc0a0a6b07054bb1da0b75d5f687fb38653a7b31f7610f5a90a402839e481",
+    "dist/2021-10-22/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "267f634ec4e08d0a76a75ec0f4ae037aaba44db3ac2969ed3f34d74db43bea1a",
+    "dist/2021-10-22/rust-std-beta-x86_64-sun-solaris.tar.gz": "3648f1129895e89467a569219570061a6c50937d87bbb407e6b3b6b1f488bac3",
+    "dist/2021-10-22/rust-std-beta-x86_64-sun-solaris.tar.xz": "3a7d686102d9f2469e180a80679db52b6c8dc8ca35adf3e50a25b7bd35f4c6a5",
+    "dist/2021-10-22/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "6cb296c0d9e07e00b8561c2f39a7dad9c9d74e224658fa9a7039e34d4b5f3aa7",
+    "dist/2021-10-22/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "9e951fec5ee4a4a655693d1c9e205413aeb3120a7b2c0bb6673f4392cdf9fa6d",
+    "dist/2021-10-22/rust-std-beta-x86_64-unknown-illumos.tar.gz": "35b6775e13b79b946398a65d6cd4f15d26e160dbf44718cf177679964b2f3cec",
+    "dist/2021-10-22/rust-std-beta-x86_64-unknown-illumos.tar.xz": "84d127ce90d62f1698a948ffb247cba400bd162b9864d2ca7c0240a46b23c88b",
+    "dist/2021-10-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "53a627ff89fbfd2abe9b4354e25e02d2ae8d05fcf6f6cefe99b84aec9775acd0",
+    "dist/2021-10-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "7692b0b44eea139874fb8c6cbaca46b8f156ce392454ee4891daad532a5c6baa",
+    "dist/2021-10-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "853db076a2c469e37003fc8e52af2d0a2e31cd7f74c51147f00b04532df5721e",
+    "dist/2021-10-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "6925429b5f25d0454abbd68ee333623ccec9d706fe0ec528fb619b2688528770",
+    "dist/2021-10-22/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "13e920a779485d04952e4c402b42fac9b7570098e5e32394996cd985889682fc",
+    "dist/2021-10-22/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "158062a56de043afc4acefc8eafaa536c3018cbdc7696b6d909c757050062b42",
+    "dist/2021-10-22/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "1701a13827b3ab22fe78569704d39a2f699f463b2f6f159407a39eaf4c7fd6d8",
+    "dist/2021-10-22/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "f10ff1def90cb101179f11b4b07ceeec0ae26ee15c7a85f80e4e31c61baf846c",
+    "dist/2021-10-22/rust-std-beta-x86_64-unknown-redox.tar.gz": "20c6c718322cc341f0e1f69a9dc42f3146d10f32075d32376a241a90a2e40f48",
+    "dist/2021-10-22/rust-std-beta-x86_64-unknown-redox.tar.xz": "d0429de3b0391f063836c765ad17e2fd1940f737b69961f501eb9d2573cba6e5",
+    "dist/2021-10-22/rustc-beta-aarch64-apple-darwin.tar.gz": "31d16857f6fec033e6f79121040eb025c28a1d049014c6047fbf1057450f86d6",
+    "dist/2021-10-22/rustc-beta-aarch64-apple-darwin.tar.xz": "997a9aa6db5e23f476aefd3f4799f986a51fda3e31e2b293309fb65fa92b0370",
+    "dist/2021-10-22/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "73fb943292d50a372f2df490e47235f395ff7eceac353be74fde3adcf45d363f",
+    "dist/2021-10-22/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "30a4a4cbe3fb683b8e846052a83a3185d1b8d714251bd6ad0bfc251b49a72121",
+    "dist/2021-10-22/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "b238cffde0b9ae2305e501970cb9cff1782331f1cccbf8dff84979d1ffdf0625",
+    "dist/2021-10-22/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "5d01b8e471419036703886fc7dcceb89ffc88fa62994727109865339fbe0c92c",
+    "dist/2021-10-22/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "8b8b48fc67a2093502baf21c372870bad42840377548e250023c9f83884322b5",
+    "dist/2021-10-22/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "a9e73e67a7120968474040dbde7b12668bd6e3a6b4f9d91b8c9a66474f68e40b",
+    "dist/2021-10-22/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "4e83419922b4f02b1c1c62ca14db65863f4226cbaa61674ac792e860c026a948",
+    "dist/2021-10-22/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "20d7369422ebb89f8e1064616a9842cbc98d9056910a2d0ba46f8bcf144cb794",
+    "dist/2021-10-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "05ab3071cdb3ea4e39f53e179c754d2cf64800ca1c38ff887e45f60294d6e222",
+    "dist/2021-10-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "e8509c60955ecf4938575a7a40091ba5d7aff77c9c3e24208623882d1bb45e6f",
+    "dist/2021-10-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "185a3e399dcc67d8fb43a0174ef8e15c36a068b82aa33db8b42c948c2ee15689",
+    "dist/2021-10-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "69be7881ba1b2d4348ea06fc2d31a62fe484843e660f399349c49a17852cfaa7",
+    "dist/2021-10-22/rustc-beta-i686-pc-windows-gnu.tar.gz": "74c3a25a67b10abbefadf63bc09f6069242267a9ca8a9177e2f46e2b29869b75",
+    "dist/2021-10-22/rustc-beta-i686-pc-windows-gnu.tar.xz": "9f0d3ce0a00b33bb591d6b615f9cc80a714f3ea0d787f410da7d643ac5e1144a",
+    "dist/2021-10-22/rustc-beta-i686-pc-windows-msvc.tar.gz": "feac518beb813b2d553d6ee1ce03daf890c956918f0de69d5f59d4067f2f60d3",
+    "dist/2021-10-22/rustc-beta-i686-pc-windows-msvc.tar.xz": "aad640ae5e48f489148e1edf5e815a78b19288d916615e2af8805f0023e15686",
+    "dist/2021-10-22/rustc-beta-i686-unknown-linux-gnu.tar.gz": "c5996c458e6e1a3f3dbcb70debe562bb5d0f4a6eadd97932d8935209fbbe6809",
+    "dist/2021-10-22/rustc-beta-i686-unknown-linux-gnu.tar.xz": "d5ed640d08bcf3770b80386282c442d79af38e4c7e73be9617d0ac72d553c507",
+    "dist/2021-10-22/rustc-beta-mips-unknown-linux-gnu.tar.gz": "aa0dd3e77f92c1cc21f550c59761a437d3a8ddf31b23040e8849dd116e209835",
+    "dist/2021-10-22/rustc-beta-mips-unknown-linux-gnu.tar.xz": "3c7bfcd663507730ad3d07024e1d884dee6adb49343bef0cfb8fd07b8a56c6e4",
+    "dist/2021-10-22/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "0370337cce565e6e363e6de59aaa8c2e17db49d79496086c20f00d80198635c8",
+    "dist/2021-10-22/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "30413f65a4fcafbbb6a5302cc65bc35edc549cded8ce6a32277ae9a499adfe59",
+    "dist/2021-10-22/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "0e6ee26e237a185a26068c2c69ef095ff37f24af7984bad91196ad253dae196b",
+    "dist/2021-10-22/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "f0185e074bb0c6811d244502ce93384cd7256840fbf64025e074d97e4ccb03a9",
+    "dist/2021-10-22/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "a2c1f733c16d62300adef3ed41f9c5926f704e6b3d47e98cc615665496aa4f17",
+    "dist/2021-10-22/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "3945ad08c0b296a700bfca778994fd93bd3cbe643517ba20a60aa1f9a88eb2cf",
+    "dist/2021-10-22/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "e3871e21ac938b4bf3a1ed44fed2f05fa3a27d3eb000d98876f9f220a5fe9175",
+    "dist/2021-10-22/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "bdc7cddaf0031af1b737fd0c2510ef018d68ebed914200ae8acbfd31ad38ad06",
+    "dist/2021-10-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "9ea42f7e50864bb514293461d3622096fd7a73e8f487578ba1425a3e8d26a970",
+    "dist/2021-10-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "c39cf38c563b16d303bc2cde8c67527e7d2a74e8c5375af73744d9a9e3dc5e1e",
+    "dist/2021-10-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "dee289bd99b3b573493160446f923fb2f2b66926a5a69c0a7704eb2aaaac3ea8",
+    "dist/2021-10-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "e3c89f1baa358b6a28ae567981d5efd457d2df61f2eeee19bceeac715793510b",
+    "dist/2021-10-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "748df03717e997a01a6d222bdb6d6c0b1e206d9be55b74c14c3374a333ad8d55",
+    "dist/2021-10-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "5cbef13c038d0fe822920eabf91c152a7130e50824fd203e3fffff4a44b10bcc",
+    "dist/2021-10-22/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "dd0ec4dba66712a10c3ee5e5ef1835210d8632766c17a4afa1ba0594b6fdd35c",
+    "dist/2021-10-22/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "30d736ad6f32019435613fec04b4474795c8915e878a528c46de453a25df1bd9",
+    "dist/2021-10-22/rustc-beta-x86_64-apple-darwin.tar.gz": "14c1ba057a56a0c34f129ebae29c6a9453faa03125f1fe88b564355c186d42bb",
+    "dist/2021-10-22/rustc-beta-x86_64-apple-darwin.tar.xz": "67d1c23c910e038c6238d286af0141f0a954799dc12a6b935d47239f4d2e8bd9",
+    "dist/2021-10-22/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "7685e5b408bf70aa4c8af5ce7b5e5d5a6ac7125c75e7b10a9b3dc0e2dbd4cca1",
+    "dist/2021-10-22/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "a52b846d34cfaeddb57d00d0209b1829fb129049ef61212937c0f19fff5efc91",
+    "dist/2021-10-22/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "a5c2dce3211ec671959abb8b2f7fc34b572e3bd44362c61b98e0850c0530d1bb",
+    "dist/2021-10-22/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "ba948c4a665c349732de9f8faddc2f7e0f7be5995ad88af44f8f4f5ffd4b9387",
+    "dist/2021-10-22/rustc-beta-x86_64-unknown-freebsd.tar.gz": "edf7d1c9c9288cca973a0bc3a90bf005d25df324c592b0b8d051f0de98b85f78",
+    "dist/2021-10-22/rustc-beta-x86_64-unknown-freebsd.tar.xz": "0c01b34ed39016866e945e0f01de830a68c54f7eef2ac83c3ab85318b01debb0",
+    "dist/2021-10-22/rustc-beta-x86_64-unknown-illumos.tar.gz": "6ddf6e92653ab0c00ec524e1274be3e644868cfa867933bc383e8e3e7674945f",
+    "dist/2021-10-22/rustc-beta-x86_64-unknown-illumos.tar.xz": "14353a439a306d0803d89a3ce3da5e5c91b9236ed84759fecf8b38ebe1d8a8b1",
+    "dist/2021-10-22/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "4d7feace1b414919ba2e682c748e24b31d811d7b54d710a7cf70e0b3c9c1a591",
+    "dist/2021-10-22/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "35593657a752a66f3052752c67c380e7ebace191a0be78c5def2cc3c1fb3a18a",
+    "dist/2021-10-22/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "04e752df5371b5d3879c8514b7dab27bcb35a7b8c7eaec0ec6e3ec5f51ff84a2",
+    "dist/2021-10-22/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "b0ef02ff310386b80a9b6113a6e44a437ab78b42480b4d0a86e828d97d92a3dc",
+    "dist/2021-10-22/rustc-beta-x86_64-unknown-netbsd.tar.gz": "387040cfbb92e6b2acc52067ab2184313de2588a6af65c0af003432bc9e69c75",
+    "dist/2021-10-22/rustc-beta-x86_64-unknown-netbsd.tar.xz": "a617e0ee647908038bd1b3f233b99db1a82b0f32875c9093cb66387f3b2bf430",
+    "dist/2021-10-23/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "5ef7d34a33925b7af081f2e135a0fd20ebb18f711372d432a570f8983243c93b",
+    "dist/2021-10-23/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "6003e9f8fb4b2a581e359e2e4f1bad83b9055d5a0c60fa0b752ef1aa15957f28",
+    "dist/2021-10-23/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "838f7773a9aaec82c4323d8412a441eb3db94da8384bc1a4a50969c5beea9aa8",
+    "dist/2021-10-23/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "403a2141367854a281302f9cdcc2d1b37a2415e8aca4cd5e5308af5fa254601d",
+    "dist/2021-10-23/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "6a3b69c8352c8262a37ba0104043a66bc579fb033166434a1b9eeaf115d8d1c2",
+    "dist/2021-10-23/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "f272195798b40df211b1d2e817e91bba68a1083026159cab4414ecc88ddb06f3",
+    "dist/2021-10-23/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "5ec04606fc7196f9a5cd130dc4c98e8df58994278ab50f7ea6baf2cdca957b07",
+    "dist/2021-10-23/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "a24513ffce8f76fa3334932268aed073958f904b1988d337df7bd4277d3a139b",
+    "dist/2021-10-23/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "8f078b404db9fabd8b0a45deb5110fab32e2ffe5f604f74ef787d9baf3f857ad",
+    "dist/2021-10-23/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "3569e3ed42cd9b4dd6f8b2838329c7864c6d3f7a5242cbdbcd9a756e6f2ca5ea",
+    "dist/2021-10-23/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "afa42b42631320a68d6a99902fd48b1e72d2daeb07a5be34b833f22ba6dcb67a",
+    "dist/2021-10-23/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "839a8576012332bb2ad01d5b4ab24d46af8644e38b3019b36c0ba5a9417bfd07",
+    "dist/2021-10-23/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "aa59c2ebf3bbff46b6c09aa1e7784ebf83dccd6df60e1295935ff3cc954fa755",
+    "dist/2021-10-23/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "e7f479891368cebb99f41b59508a3904321d600e20cc2507954f78386a448601",
+    "dist/2021-10-23/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "a971a861cc76d0a2a4c5fecfc4537c8e1c14f4d43013bceeed395722e8620cbd",
+    "dist/2021-10-23/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "5879a7a9af9c6ef6397f75e4b062527fee5006d655fac5b7538915b176d9faa8",
+    "dist/2021-10-23/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "dc66ac568c709f4b580b46d567bf2d79481566688e0ae55df1edd2a5f07fe0a9",
+    "dist/2021-10-23/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "a2ea4554d52b1181c589eefdf67c60bc0831f2e26430bd6e5e7bb4094db5dfc5",
+    "dist/2021-10-23/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "8d9ef4755d32e8dc480db1b130943f47b45cc2ba69b1e9fa3dfa128d63780b70",
+    "dist/2021-10-23/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "3cac0853da192779f4edc5bc3c913e4b93a02ae98b883cfe2717cc58329d7469",
+    "dist/2021-10-23/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "14c5197f4884f418a392bccce9ac3c9a09dcd0a710a337bba5959f5570c41e98",
+    "dist/2021-10-23/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "f9b14921e3a6bd006479a01579e6601787082ecc0ec8e631b8cea6a4f1c0b967",
+    "dist/2021-10-23/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "9f4efc8229a5a8561bea614a3df0da49349dc4118d72905ecd6feb6b6e1eba9f",
+    "dist/2021-10-23/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "02d829ac6d9013f7268e505aa2b0aa99db7e25ddc3d6555ca8f9a4c5ed3f01e7",
+    "dist/2021-10-23/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "8192413e5e376bf957a2caffe8ab15b3c235c714f8214a0f3a46711a79fe33c5",
+    "dist/2021-10-23/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "be155309daae3cb39dbbc874b2ddaebd1ad303b09f40e130ea8429cc7c9c366f",
+    "dist/2021-10-23/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "318c3e8235913f64c9e90b0e7c1fb50229caf59c02f0ddc702cf0728d54dc41c",
+    "dist/2021-10-23/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "50bf71e32ae2228142ad88d67e794ab00b632147fb554ebbfcda7ec79304ae2f",
+    "dist/2021-10-23/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "80f5b76c38d7300c5aa6a71a8b3325b28290b1bb936dd59287fa87d6dee044da",
+    "dist/2021-10-23/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "30a71791c6ed0cf3e0fb955fa697549dcd13d2c0f3e357d9723fa729c3a03698",
+    "dist/2021-10-23/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "7e5dc3dc89cb21638b452eb9b5c9f008803ee5845c973f2547f59db01b7a0100",
+    "dist/2021-10-23/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "e1a949b29d249361b306af38bba7118aa1931c14061b6fa7621027e9994b519f",
+    "dist/2021-10-23/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "ae4186e4faebc9ad8a13f06a97f96c48cbb35353ad649e25f2e80e519a9d272a",
+    "dist/2021-10-23/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "ca4466d872bb050cabce20ae04eb915ac3e39e4788899db7bec5b51ed7d5b579",
+    "dist/2021-10-23/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "0f39f27e2ee437df69975578c6e32b6e293bf3129f7e63bde83091330aaa496c",
+    "dist/2021-10-23/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "55700dff4b4f3f7d9dfee3317d984afe2b44681deb7b074441b41cfd59e497ed",
+    "dist/2021-10-23/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "6273db29aa2715ffe38593802c520adafcbb2300ed2595121bff628686eae675",
+    "dist/2021-10-23/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "7a4ce848a1083c16bc17bd22345427ba4c920cb887e90d612a8c3d1ddcf802ed",
+    "dist/2021-10-23/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "12a715fca796c192514157b43b0296d688cc46e9d81416a67a0019184c1703d4",
+    "dist/2021-10-23/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "9a651e94a0cdddef7c7a56e356e25d0f35d0c592b6a54f2cbeeb3364fc5d457c",
+    "dist/2021-10-23/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "2ea52a8413a43a10165322135064692faee0d03a453c4b28ddea480b153de5c8",
+    "dist/2021-10-23/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "843b06b9b21c56fe1749e8a5bda908dcc2b6d8206faabd04d050ce83f8c32b73",
+    "dist/2021-10-23/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "69210991cca5a07c0421254a2e18a29de28ab5019b490a576f7bb94496ca10b8",
+    "dist/2021-10-23/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "3f5a59ba68e004c06cb07ce83d4a567b77179e11071a8b5b8ab6fe3a70bdb872",
+    "dist/2021-10-23/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "7225fde4655ed5b4479ff9f4e61237a16280541f44aa751c5a06d5916e8fde3f",
+    "dist/2021-10-23/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "e844e80d99418bea9e7cf96cd389056d17f3be60e9412983d91c64e107a28b92",
+    "dist/2021-10-23/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "6c1b031bc408349c5d15bf494881dd75aa68df8e7417e6c72c061c7d3270cdf8",
+    "dist/2021-10-23/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "d24b970a15dfd41cb1b0027a4a5822e8c2b0217dd1984503d60a85fc6acf7414",
+    "dist/2021-10-23/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "5b5aec4bfde07863d2d5bb71f38d3459db0659df75f53567be6fbaacec33c7b3",
+    "dist/2021-10-23/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "851b9582bd2518a3e050127c46e59f7bb6b24d354c6e89a9b0fe4d3e09cfbbb9",
+    "dist/2021-10-23/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "758a05277e99d00e21ff9d8abf96a6da71350664a1eb85adbb1ad4cfa1934255",
+    "dist/2021-10-23/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "6431dabc8ef72ca252b257683fd2f5ce3c1347b18ff1d4b7ee7758c6906ba2af",
+    "dist/2021-10-23/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "51bdea94714c0892ca7020ddcc7c55bb20ac69eaf5152a38f83925d793b90eb1",
+    "dist/2021-10-23/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "660a23d1430164b01b3e1e8b50233be07fa0988d90e9880bb9044fe661537cde"
   }
 }
index 66c39a48c6e1d5fbc1ecb2ea3207c5dedeb4af37..04b5f4aed9bb5c87ef34b0658a78c60586022d39 100644 (file)
@@ -2,7 +2,7 @@
 // compile-flags: --target aarch64-unknown-linux-gnu
 // needs-llvm-components: aarch64
 
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym)]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(asm_sub_register, non_camel_case_types)]
index c848e3284ff1f06bb1926b6ba7587e13b2bb5983..0c57b1fc4782de50a8752cb372d439e973ea18b9 100644 (file)
@@ -3,7 +3,7 @@
 // compile-flags: -C target-feature=+neon
 // needs-llvm-components: arm
 
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym)]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(asm_sub_register, non_camel_case_types)]
index 7271ef11287efcfd8c6614ffd25291adc5fb7045..3428d93fb1205d60b3e3040a76996cbbc4552c08 100644 (file)
@@ -3,7 +3,7 @@
 // compile-flags: --target bpfel-unknown-none -C target_feature=+alu32
 // needs-llvm-components: bpf
 
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(asm_sub_register, non_camel_case_types)]
index 1c981040d601474da4547213aa610003c4e16e0d..7e48c386abcde7cc978b0e5ef4653413e00a8601 100644 (file)
@@ -2,7 +2,7 @@
 // assembly-output: emit-asm
 // compile-flags: -C llvm-args=--x86-asm-syntax=intel
 
-#![feature(asm, global_asm)]
+#![feature(global_asm, asm_const)]
 #![crate_type = "rlib"]
 
 // CHECK: mov eax, eax
index 2156d77233d83888f99ed4ee9454596dfb4920e2..de310c78488d9e9fea925fb0f32644c61898cefc 100644 (file)
@@ -2,7 +2,7 @@
 // compile-flags: --target hexagon-unknown-linux-musl
 // needs-llvm-components: hexagon
 
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(asm_sub_register, non_camel_case_types)]
index eb6627639f159d5d77a02c6e9756b7cdcffa5204..04bf49a40efbcd0b816754138a36717b5e64b6f3 100644 (file)
@@ -5,7 +5,7 @@
 //[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64
 //[mips64] needs-llvm-components: mips
 
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(asm_sub_register, non_camel_case_types)]
index cc816fd78f81e2063c66a74e2740afe941b2182f..3ebd5b4b89681252dd4bc3715a03a55b408e7d02 100644 (file)
@@ -3,7 +3,7 @@
 // compile-flags: --crate-type cdylib
 // needs-llvm-components: nvptx
 
-#![feature(no_core, lang_items, rustc_attrs)]
+#![feature(no_core, lang_items, rustc_attrs, asm_sym, asm_experimental_arch)]
 #![no_core]
 
 #[rustc_builtin_macro]
index 342998245315e8be0eeb55ce1bfb4c235b218d3b..b8859c07e164fe03a38ba7654802920bf488f6bc 100644 (file)
@@ -6,7 +6,7 @@
 //[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
 //[powerpc64] needs-llvm-components: powerpc
 
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(asm_sub_register, non_camel_case_types)]
index c510689b42bff788ce2ac9626c10a10446eabf08..0f9f61bd6d916a85d4bd7c5aa908574949e2aaa1 100644 (file)
@@ -6,7 +6,7 @@
 //[riscv32] needs-llvm-components: riscv
 // compile-flags: -C target-feature=+d
 
-#![feature(no_core, lang_items, rustc_attrs)]
+#![feature(no_core, lang_items, rustc_attrs, asm_sym)]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(asm_sub_register)]
index b8a4ca08df1cc8ce2d06a39ad7513558b69ede8c..6a12902a0461f711d76f08bdfb70428b37c53c95 100644 (file)
@@ -3,7 +3,7 @@
 //[s390x] compile-flags: --target s390x-unknown-linux-gnu
 //[s390x] needs-llvm-components: systemz
 
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(asm_sub_register, non_camel_case_types)]
index 4b2e83e69b1065ba5701286557cbcbc373176632..3aa128c46ac01f8e6ef8e824a0f5fd66ff88674b 100644 (file)
@@ -3,7 +3,7 @@
 // compile-flags: --crate-type cdylib
 // needs-llvm-components: webassembly
 
-#![feature(no_core, lang_items, rustc_attrs)]
+#![feature(no_core, lang_items, rustc_attrs, asm_sym, asm_experimental_arch)]
 #![no_core]
 
 #[rustc_builtin_macro]
index 81be79cbaac18c25d8e9516bd8bb6327bdb6b92d..e871535cfdeef75a79da05884a06faa1b4c911cd 100644 (file)
@@ -7,7 +7,7 @@
 // compile-flags: -C llvm-args=--x86-asm-syntax=intel
 // compile-flags: -C target-feature=+avx512bw
 
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym)]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(asm_sub_register, non_camel_case_types)]
diff --git a/src/test/codegen-units/item-collection/implicit-panic-call.rs b/src/test/codegen-units/item-collection/implicit-panic-call.rs
new file mode 100644 (file)
index 0000000..abec7ad
--- /dev/null
@@ -0,0 +1,58 @@
+// compile-flags:-Zprint-mono-items=lazy
+
+// rust-lang/rust#90405
+// Ensure implicit panic calls are collected
+
+#![feature(lang_items)]
+#![feature(no_core)]
+#![crate_type = "lib"]
+#![no_core]
+#![no_std]
+
+#[lang = "panic_location"]
+struct Location<'a> {
+    _file: &'a str,
+    _line: u32,
+    _col: u32,
+}
+
+#[lang = "panic"]
+#[inline]
+#[track_caller]
+fn panic(_: &'static str) -> ! {
+    loop {}
+}
+
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "copy"]
+trait Copy {}
+
+#[lang = "freeze"]
+trait Freeze {}
+
+impl Copy for i32 {}
+
+#[lang = "div"]
+trait Div<Rhs = Self> {
+    type Output;
+    fn div(self, rhs: Rhs) -> Self::Output;
+}
+
+impl Div for i32 {
+    type Output = i32;
+    fn div(self, rhs: i32) -> i32 {
+        self / rhs
+    }
+}
+
+#[allow(unconditional_panic)]
+pub fn foo() {
+    // This implicitly generates a panic call.
+    let _ = 1 / 0;
+}
+
+//~ MONO_ITEM fn foo
+//~ MONO_ITEM fn <i32 as Div>::div
+//~ MONO_ITEM fn panic
index ce13a7ff938c8beb23ce18f7c230dd6ddfc4f8aa..10b20ba6beb0a614cdb53a13ceed46fc8fa97978 100644 (file)
@@ -7,7 +7,7 @@
 //[powerpc64le] needs-llvm-components: powerpc
 
 #![crate_type = "rlib"]
-#![feature(no_core, rustc_attrs, lang_items)]
+#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)]
 #![no_core]
 
 #[lang = "sized"]
diff --git a/src/test/codegen/sanitizer_cfi_add_canonical_jump_tables_flag.rs b/src/test/codegen/sanitizer_cfi_add_canonical_jump_tables_flag.rs
new file mode 100644 (file)
index 0000000..68f8180
--- /dev/null
@@ -0,0 +1,14 @@
+// Verifies that "CFI Canonical Jump Tables" module flag is added.
+//
+// ignore-windows
+// needs-sanitizer-cfi
+// only-aarch64
+// only-x86_64
+// compile-flags: -Clto -Zsanitizer=cfi
+
+#![crate_type="lib"]
+
+pub fn foo() {
+}
+
+// CHECK: !{{[0-9]+}} = !{i32 2, !"CFI Canonical Jump Tables", i32 1}
diff --git a/src/test/codegen/sanitizer_cfi_emit_type_checks.rs b/src/test/codegen/sanitizer_cfi_emit_type_checks.rs
new file mode 100644 (file)
index 0000000..9ed0422
--- /dev/null
@@ -0,0 +1,24 @@
+// Verifies that pointer type membership tests for indirect calls are emitted.
+//
+// ignore-windows
+// needs-sanitizer-cfi
+// only-aarch64
+// only-x86_64
+// compile-flags: -Clto -Cno-prepopulate-passes -Zsanitizer=cfi
+
+#![crate_type="lib"]
+
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}foo{{.*}}!type !{{[0-9]+}}
+    // CHECK:       start:
+    // CHECK-NEXT:  %0 = bitcast i32 (i32)* %f to i8*
+    // CHECK-NEXT:  %1 = call i1 @llvm.type.test(i8* %0, metadata !"{{[[:print:]]+}}")
+    // CHECK-NEXT:  br i1 %1, label %type_test.pass, label %type_test.fail
+    // CHECK:       type_test.pass:
+    // CHECK-NEXT:  %2 = call i32 %f(i32 %arg)
+    // CHECK-NEXT:  br label %bb1
+    // CHECK:       type_test.fail:
+    // CHECK-NEXT:  call void @llvm.trap()
+    // CHECK-NEXT:  unreachable
+    f(arg)
+}
diff --git a/src/test/codegen/sanitizer_cfi_emit_type_metadata.rs b/src/test/codegen/sanitizer_cfi_emit_type_metadata.rs
new file mode 100644 (file)
index 0000000..96fced4
--- /dev/null
@@ -0,0 +1,31 @@
+// Verifies that type metadata for functions are emitted.
+//
+// ignore-windows
+// needs-sanitizer-cfi
+// only-aarch64
+// only-x86_64
+// compile-flags: -Clto -Cno-prepopulate-passes -Zsanitizer=cfi
+
+#![crate_type="lib"]
+
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}foo{{.*}}!type !{{[0-9]+}}
+    // CHECK:       %1 = call i1 @llvm.type.test(i8* %0, metadata !"typeid1")
+    f(arg)
+}
+
+pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}bar{{.*}}!type !{{[0-9]+}}
+    // CHECK:       %1 = call i1 @llvm.type.test(i8* %0, metadata !"typeid2")
+    f(arg1, arg2)
+}
+
+pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}baz{{.*}}!type !{{[0-9]+}}
+    // CHECK:       %1 = call i1 @llvm.type.test(i8* %0, metadata !"typeid3")
+    f(arg1, arg2, arg3)
+}
+
+// CHECK: !{{[0-9]+}} = !{i64 0, !"typeid2"}
+// CHECK: !{{[0-9]+}} = !{i64 0, !"typeid3"}
+// CHECK: !{{[0-9]+}} = !{i64 0, !"typeid4"}
index 906d094f72b4a1b45b838babfc42698c8a3e67de..39f665402b025cf12918fba727f95bc93ecf6410 100644 (file)
@@ -1,4 +1,4 @@
-// EMIT_MIR issue_78192.f.InstCombine.diff
+// compile-flags: -Zmir-opt-level=1 -Zinline-mir
 pub fn f<T>(a: &T) -> *const T {
     let b: &*const T = &(a as *const T);
     *b
@@ -7,3 +7,5 @@ pub fn f<T>(a: &T) -> *const T {
 fn main() {
     f(&2);
 }
+
+// EMIT_MIR issue_78192.f.InstCombine.diff
index f4be3c1c63a84e5d8fda7b09ff7cf076ed3bebe6..84eda08d203bfcacfe288766a7c38bc13888e9ef 100644 (file)
@@ -12,7 +12,7 @@ fn main() {
     {
         ::std::io::_print(::core::fmt::Arguments::new_v1(&["rust\n"],
                                                          &match () {
-                                                              () => [],
+                                                              _args => [],
                                                           }));
     };
 }
index 199aee05622beed636c3966d6a00f091fae86cdd..529daab903887de6122e0cbb8eb4b0cb096d0f5b 100644 (file)
@@ -45,7 +45,7 @@ pub fn bar() ({
                                                                                                                                                                      as
                                                                                                                                                                      ())
                                                                                                                                                                {
-                                                                                                                                                               ()
+                                                                                                                                                               _args
                                                                                                                                                                =>
                                                                                                                                                                ([]
                                                                                                                                                                    as
index c279cf7e8bf10bcb77e5b150b909f00563a0149f..dd3b7c76f28675b8d0d77321f9607193fe843119 100644 (file)
@@ -2,8 +2,6 @@
 // are caught by catch_unwind. Also tests that Rust panics can unwind through
 // C++ code.
 
-// For linking libstdc++ on MinGW
-#![cfg_attr(all(windows, target_env = "gnu"), feature(static_nobundle))]
 #![feature(c_unwind)]
 
 use std::panic::{catch_unwind, AssertUnwindSafe};
index c75713c3ee53d1798915a4abfd36c4144a0669ec..de463a330149b0416afbf5b98c21a4591082a5da 100644 (file)
@@ -3,4 +3,4 @@
 all:
        touch $(TMPDIR)/lib.rmeta
        $(AR) crus $(TMPDIR)/libfoo-ffffffff-1.0.rlib $(TMPDIR)/lib.rmeta
-       $(RUSTC) foo.rs 2>&1 | $(CGREP) "can't find crate for"
+       $(RUSTC) foo.rs 2>&1 | $(CGREP) "found invalid metadata"
index a288b90d7924e96de619596b1eede797573fb423..86e6d9e756c51d9946e1828195a4de2c090699ed 100644 (file)
@@ -25,7 +25,7 @@
 use rustc_interface::interface::Compiler;
 use rustc_interface::{Config, Queries};
 use rustc_middle::ty::query::query_values::mir_borrowck;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::query::{ExternProviders, Providers};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::Session;
 use std::cell::RefCell;
@@ -87,9 +87,8 @@ fn after_analysis<'tcx>(
     }
 }
 
-fn override_queries(_session: &Session, local: &mut Providers, external: &mut Providers) {
+fn override_queries(_session: &Session, local: &mut Providers, _external: &mut ExternProviders) {
     local.mir_borrowck = mir_borrowck;
-    external.mir_borrowck = mir_borrowck;
 }
 
 // Since mir_borrowck does not have access to any other state, we need to use a
index 013bf3baca45f1d18d321ba80ea4641bbc72ecbc..5472baae3f2b0bb0d1a9de1cef1b0bf7729524ba 100644 (file)
@@ -1,3 +1,5 @@
+# needs-llvm-components: x86 arm
+
 -include ../tools.mk
 
 all: default
diff --git a/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/Makefile b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/Makefile
new file mode 100644 (file)
index 0000000..4934e87
--- /dev/null
@@ -0,0 +1,18 @@
+-include ../../run-make-fulldeps/tools.mk
+
+OUTPUT_DIR := "$(TMPDIR)/rustdoc"
+DYLIB_NAME := $(shell echo | $(RUSTC) --crate-name foobar_macro --crate-type dylib --print file-names -)
+
+all:
+       $(RUSTC) src/proc.rs --crate-name foobar_macro --edition=2021 --crate-type proc-macro --emit=dep-info,link
+
+       $(RUSTC) src/lib.rs --crate-name foobar --edition=2021 --crate-type lib --emit=dep-info,link
+
+       $(RUSTDOC) examples/ex.rs --crate-name ex --crate-type bin --output $(OUTPUT_DIR) \
+               --extern foobar=$(TMPDIR)/libfoobar.rlib --extern foobar_macro=$(TMPDIR)/$(DYLIB_NAME) \
+               -Z unstable-options --scrape-examples-output-path $(TMPDIR)/ex.calls --scrape-examples-target-crate foobar
+
+       $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --output $(OUTPUT_DIR) \
+               -Z unstable-options --with-examples $(TMPDIR)/ex.calls
+
+       $(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs
diff --git a/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/examples/ex.rs b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/examples/ex.rs
new file mode 100644 (file)
index 0000000..4d8c8b3
--- /dev/null
@@ -0,0 +1,27 @@
+extern crate foobar;
+extern crate foobar_macro;
+
+use foobar::*;
+use foobar_macro::*;
+
+a_proc_macro!(); // no
+
+#[an_attr_macro]
+fn a() {
+  f(); // no
+}
+
+#[an_attr_macro(with_span)]
+fn b() {
+  f(); // yes
+}
+
+fn c() {
+  a_rules_macro!(f()); // yes
+}
+
+fn d() {
+  a_rules_macro!(()); // no
+}
+
+fn main(){}
diff --git a/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs
new file mode 100644 (file)
index 0000000..bac3970
--- /dev/null
@@ -0,0 +1,12 @@
+// Scraped example should only include line numbers for items b and c in ex.rs
+// @!has foobar/fn.f.html '//*[@class="line-numbers"]' '14'
+// @has foobar/fn.f.html '//*[@class="line-numbers"]' '15'
+// @has foobar/fn.f.html '//*[@class="line-numbers"]' '21'
+// @!has foobar/fn.f.html '//*[@class="line-numbers"]' '22'
+
+pub fn f() {}
+
+#[macro_export]
+macro_rules! a_rules_macro {
+  ($e:expr) => { ($e, foobar::f()); }
+}
diff --git a/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/proc.rs b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/proc.rs
new file mode 100644 (file)
index 0000000..46e518f
--- /dev/null
@@ -0,0 +1,39 @@
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn a_proc_macro(_item: TokenStream) -> TokenStream {
+    "fn ex() { foobar::f(); }".parse().unwrap()
+}
+
+// inserts foobar::f() to the end of the function
+#[proc_macro_attribute]
+pub fn an_attr_macro(attr: TokenStream, item: TokenStream) -> TokenStream {
+    let new_call: TokenStream = "foobar::f();".parse().unwrap();
+
+    let mut tokens = item.into_iter();
+
+    let fn_tok = tokens.next().unwrap();
+    let ident_tok = tokens.next().unwrap();
+    let args_tok = tokens.next().unwrap();
+    let body = match tokens.next().unwrap() {
+        TokenTree::Group(g) => {
+            let new_g = Group::new(g.delimiter(), new_call);
+            let mut outer_g = Group::new(
+                g.delimiter(),
+                [TokenTree::Group(g.clone()), TokenTree::Group(new_g)].into_iter().collect(),
+            );
+
+            if attr.to_string() == "with_span" {
+                outer_g.set_span(g.span());
+            }
+
+            TokenTree::Group(outer_g)
+        }
+        _ => unreachable!(),
+    };
+
+    let tokens = vec![fn_tok, ident_tok, args_tok, body].into_iter().collect::<TokenStream>();
+
+    tokens
+}
index 3934c4725f4133a1ad86ae63e4bf469ca924c67a..9655d09df0f2a021ff78835395c411d308d1694f 100644 (file)
@@ -117,10 +117,10 @@ else
        # that it is compiled with the expectation that pthreads is dynamically
        # linked as a DLL and will fail to link with a statically linked libpthread.
        #
-       # So we end up with the following hack: we link use static-nobundle to only
+       # So we end up with the following hack: we link use static:-bundle to only
        # link the parts of libstdc++ that we actually use, which doesn't include
        # the dependency on the pthreads DLL.
-       EXTRARSCXXFLAGS := -l static-nobundle=stdc++
+       EXTRARSCXXFLAGS := -l static:-bundle=stdc++ -Z unstable-options
 endif
 else
 ifeq ($(UNAME),Darwin)
diff --git a/src/test/run-make/invalid-so/Makefile b/src/test/run-make/invalid-so/Makefile
new file mode 100644 (file)
index 0000000..5b82ecd
--- /dev/null
@@ -0,0 +1,7 @@
+include ../../run-make-fulldeps/tools.mk
+
+DYLIB_NAME := $(shell echo | $(RUSTC) --crate-name foo --crate-type dylib --print file-names -)
+
+all:
+       echo >> $(TMPDIR)/$(DYLIB_NAME)
+       $(RUSTC) --crate-type lib --extern foo=$(TMPDIR)/$(DYLIB_NAME) bar.rs 2>&1 | $(CGREP) 'invalid metadata files for crate `foo`'
diff --git a/src/test/run-make/invalid-so/bar.rs b/src/test/run-make/invalid-so/bar.rs
new file mode 100644 (file)
index 0000000..49af74e
--- /dev/null
@@ -0,0 +1 @@
+extern crate foo;
index 845844f427bdf1177edb4ceebaf7746126b2cc6d..f30a35e27c0bcc7f596fda1de1e8007e2798c109 100644 (file)
@@ -1,8 +1,5 @@
 // Tests that linking to C++ code with global destructors works.
 
-// For linking libstdc++ on MinGW
-#![cfg_attr(all(windows, target_env = "gnu"), feature(static_nobundle))]
-
 extern "C" {
     fn get() -> u32;
 }
diff --git a/src/test/run-make/rustdoc-scrape-examples-invalid-expr/Makefile b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/Makefile
new file mode 100644 (file)
index 0000000..dce8b83
--- /dev/null
@@ -0,0 +1,5 @@
+deps := ex
+
+-include ../rustdoc-scrape-examples-multiple/scrape.mk
+
+all: scrape
diff --git a/src/test/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs
new file mode 100644 (file)
index 0000000..b342b5b
--- /dev/null
@@ -0,0 +1,2 @@
+pub struct Foo([usize; foobar::f()]);
+fn main() {}
diff --git a/src/test/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs
new file mode 100644 (file)
index 0000000..c30c99d
--- /dev/null
@@ -0,0 +1 @@
+pub const fn f() -> usize { 5 }
index bd59584bbbf4fafbb70c7920d901807bb6d6064e..bdfeda92d79a0684e6adf2a5e46a27f518b61575 100644 (file)
@@ -1,4 +1,6 @@
 // @has foobar/fn.ok.html '//*[@class="docblock scraped-example-list"]//*[@class="prev"]' ''
 // @has foobar/fn.ok.html '//*[@class="more-scraped-examples"]' ''
+// @has src/ex/ex.rs.html
+// @has foobar/fn.ok.html '//a[@href="../src/ex/ex.rs.html#2"]' ''
 
 pub fn ok() {}
index d6d5982087658066359803dbda99c85143ec88fe..05c18007b0c718bfe72aadf237fc18ae89c197f2 100644 (file)
@@ -1,8 +1,10 @@
 fn main() {
-    foobar::ok();
+    foobar::ok(0);
 
     // this is a
 
+    //  ..
+
     // BIG
 
     // item
index a1133117f861e9cab46ce570c989c199b9a4aa7c..de21d9061f8dcc4c49cc76d2b1263f46d3f19acf 100644 (file)
@@ -1,4 +1,8 @@
 fn main() {
-    foobar::ok();
+    foobar::ok(1);
     // small item
 }
+
+fn f() {
+    foobar::ok(2);
+}
index f1b7686d36800f774dc718d0ff793729bdd60302..5afffffdf9976f84854352224888f49ea786889c 100644 (file)
@@ -1,4 +1,7 @@
 // @has foobar/fn.ok.html '//*[@class="docblock scraped-example-list"]' 'ex2'
 // @has foobar/fn.ok.html '//*[@class="more-scraped-examples"]' 'ex1'
+// @has foobar/fn.ok.html '//*[@class="highlight focus"]' '1'
+// @has foobar/fn.ok.html '//*[@class="highlight"]' '2'
+// @has foobar/fn.ok.html '//*[@class="highlight focus"]' '0'
 
-pub fn ok() {}
+pub fn ok(_x: i32) {}
diff --git a/src/test/rustdoc-gui/headings.goml b/src/test/rustdoc-gui/headings.goml
new file mode 100644 (file)
index 0000000..bdf17ec
--- /dev/null
@@ -0,0 +1,156 @@
+// This test check that headers (a) have the correct heading level, (b) are the right size,
+// and (c) have the correct underlining (or absence of underlining).
+// The sizes may change as design changes, but try to make sure a lower header is never bigger than
+// its parent headers. Also make sure lower headers don't have underlines when their parents lack
+// an underline.
+// Most of these sizes are set in CSS in `em` units, so here's a conversion chart based on our
+// default 16px font size:
+// 24px    1.5em
+// 22.4px  1.4em
+// 20.8px  1.3em
+// 18.4px  1.15em
+// 17.6px  1.1em
+// 16px    1em
+// 15.2px  0.95em  
+goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html
+
+assert-css: ("h1.fqn", {"font-size": "24px"})
+assert-css: ("h1.fqn", {"border-bottom-width": "1px"})
+
+assert-css: ("h2#top-doc-prose-title", {"font-size": "20.8px"})
+assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"})
+assert-css: ("h3#top-doc-prose-sub-heading", {"font-size": "18.4px"})
+assert-css: ("h3#top-doc-prose-sub-heading", {"border-bottom-width": "1px"})
+assert-css: ("h4#top-doc-prose-sub-sub-heading", {"font-size": "17.6px"})
+assert-css: ("h4#top-doc-prose-sub-sub-heading", {"border-bottom-width": "1px"})
+
+assert-css: ("h2#fields", {"font-size": "22.4px"})
+assert-css: ("h2#fields", {"border-bottom-width": "1px"})
+assert-css: ("h3#title-for-field", {"font-size": "20.8px"})
+assert-css: ("h3#title-for-field", {"border-bottom-width": "0px"})
+assert-css: ("h4#sub-heading-for-field", {"font-size": "16px"})
+assert-css: ("h4#sub-heading-for-field", {"border-bottom-width": "0px"})
+
+assert-css: ("h2#implementations", {"font-size": "22.4px"})
+assert-css: ("h2#implementations", {"border-bottom-width": "1px"})
+
+assert-css: ("#impl > h3.code-header", {"font-size": "17.6px"})
+assert-css: ("#impl > h3.code-header", {"border-bottom-width": "0px"})
+assert-css: ("#method\.do_nothing > h4.code-header", {"font-size": "16px"})
+assert-css: ("#method\.do_nothing > h4.code-header", {"border-bottom-width": "0px"})
+
+assert-css: ("h4#title-for-struct-impl-doc", {"font-size": "16px"})
+assert-css: ("h4#title-for-struct-impl-doc", {"border-bottom-width": "0px"})
+assert-css: ("h5#sub-heading-for-struct-impl-doc", {"font-size": "16px"})
+assert-css: ("h5#sub-heading-for-struct-impl-doc", {"border-bottom-width": "0px"})
+assert-css: ("h6#sub-sub-heading-for-struct-impl-doc", {"font-size": "15.2px"})
+assert-css: ("h6#sub-sub-heading-for-struct-impl-doc", {"border-bottom-width": "0px"})
+
+assert-css: ("h5#title-for-struct-impl-item-doc", {"font-size": "16px"})
+assert-css: ("h5#title-for-struct-impl-item-doc", {"border-bottom-width": "0px"})
+assert-css: ("h6#sub-heading-for-struct-impl-item-doc", {"font-size": "15.2px"})
+assert-css: ("h6#sub-heading-for-struct-impl-item-doc", {"border-bottom-width": "0px"})
+assert-css: ("h6#sub-sub-heading-for-struct-impl-item-doc", {"font-size": "15.2px"})
+
+goto: file://|DOC_PATH|/test_docs/enum.HeavilyDocumentedEnum.html
+
+assert-css: ("h1.fqn", {"font-size": "24px"})
+assert-css: ("h1.fqn", {"border-bottom-width": "1px"})
+
+assert-css: ("h2#top-doc-prose-title", {"font-size": "20.8px"})
+assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"})
+assert-css: ("h3#top-doc-prose-sub-heading", {"font-size": "18.4px"})
+assert-css: ("h3#top-doc-prose-sub-heading", {"border-bottom-width": "1px"})
+assert-css: ("h4#top-doc-prose-sub-sub-heading", {"font-size": "17.6px"})
+assert-css: ("h4#top-doc-prose-sub-sub-heading", {"border-bottom-width": "1px"})
+
+assert-css: ("h2#variants", {"font-size": "22.4px"})
+assert-css: ("h2#variants", {"border-bottom-width": "1px"})
+
+assert-css: ("h3#none-prose-title", {"font-size": "20.8px"})
+assert-css: ("h3#none-prose-title", {"border-bottom-width": "0px"})
+assert-css: ("h4#none-prose-sub-heading", {"font-size": "16px"})
+assert-css: ("h4#none-prose-sub-heading", {"border-bottom-width": "0px"})
+
+assert-css: ("h3#wrapped-prose-title", {"font-size": "20.8px"})
+assert-css: ("h3#wrapped-prose-title", {"border-bottom-width": "0px"})
+assert-css: ("h4#wrapped-prose-sub-heading", {"font-size": "16px"})
+assert-css: ("h4#wrapped-prose-sub-heading", {"border-bottom-width": "0px"})
+
+assert-css: ("h4#wrapped0-prose-title", {"font-size": "16px"})
+assert-css: ("h4#wrapped0-prose-title", {"border-bottom-width": "0px"})
+assert-css: ("h5#wrapped0-prose-sub-heading", {"font-size": "16px"})
+assert-css: ("h5#wrapped0-prose-sub-heading", {"border-bottom-width": "0px"})
+
+assert-css: ("h4#structy-prose-title", {"font-size": "16px"})
+assert-css: ("h4#structy-prose-title", {"border-bottom-width": "0px"})
+assert-css: ("h5#structy-prose-sub-heading", {"font-size": "16px"})
+assert-css: ("h5#structy-prose-sub-heading", {"border-bottom-width": "0px"})
+
+assert-css: ("h2#implementations", {"font-size": "22.4px"})
+assert-css: ("h2#implementations", {"border-bottom-width": "1px"})
+
+assert-css: ("#impl > h3.code-header", {"font-size": "17.6px"})
+assert-css: ("#impl > h3.code-header", {"border-bottom-width": "0px"})
+assert-css: ("#method\.do_nothing > h4.code-header", {"font-size": "16px"})
+assert-css: ("#method\.do_nothing > h4.code-header", {"border-bottom-width": "0px"})
+
+assert-css: ("h4#title-for-enum-impl-doc", {"font-size": "16px"})
+assert-css: ("h4#title-for-enum-impl-doc", {"border-bottom-width": "0px"})
+assert-css: ("h5#sub-heading-for-enum-impl-doc", {"font-size": "16px"})
+assert-css: ("h5#sub-heading-for-enum-impl-doc", {"border-bottom-width": "0px"})
+assert-css: ("h6#sub-sub-heading-for-enum-impl-doc", {"font-size": "15.2px"})
+assert-css: ("h6#sub-sub-heading-for-enum-impl-doc", {"border-bottom-width": "0px"})
+
+assert-css: ("h5#title-for-enum-impl-item-doc", {"font-size": "16px"})
+assert-css: ("h5#title-for-enum-impl-item-doc", {"border-bottom-width": "0px"})
+assert-css: ("h6#sub-heading-for-enum-impl-item-doc", {"font-size": "15.2px"})
+assert-css: ("h6#sub-heading-for-enum-impl-item-doc", {"border-bottom-width": "0px"})
+assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"font-size": "15.2px"})
+assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"border-bottom-width": "0px"})
+
+assert-text: (".sidebar .others h3", "Modules")
+assert-css: (".sidebar .others h3", {"border-bottom-width": "1px"}, ALL)
+
+goto: file://|DOC_PATH|/test_docs/union.HeavilyDocumentedUnion.html
+
+assert-css: ("h1.fqn", {"font-size": "24px"})
+assert-css: ("h1.fqn", {"border-bottom-width": "1px"})
+
+assert-css: ("h2#top-doc-prose-title", {"font-size": "20.8px"})
+assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"})
+assert-css: ("h3#top-doc-prose-sub-heading", {"font-size": "18.4px"})
+assert-css: ("h3#top-doc-prose-sub-heading", {"border-bottom-width": "1px"})
+
+assert-css: ("h2#fields", {"font-size": "22.4px"})
+assert-css: ("h2#fields", {"border-bottom-width": "1px"})
+
+assert-css: ("h3#title-for-union-variant", {"font-size": "20.8px"})
+assert-css: ("h3#title-for-union-variant", {"border-bottom-width": "0px"})
+assert-css: ("h4#sub-heading-for-union-variant", {"font-size": "16px"})
+assert-css: ("h4#sub-heading-for-union-variant", {"border-bottom-width": "0px"})
+
+assert-css: ("h2#implementations", {"font-size": "22.4px"})
+assert-css: ("h2#implementations", {"border-bottom-width": "1px"})
+
+assert-css: ("#impl > h3.code-header", {"font-size": "17.6px"})
+assert-css: ("#impl > h3.code-header", {"border-bottom-width": "0px"})
+assert-css: ("h4#title-for-union-impl-doc", {"font-size": "16px"})
+assert-css: ("h4#title-for-union-impl-doc", {"border-bottom-width": "0px"})
+assert-css: ("h5#sub-heading-for-union-impl-doc", {"font-size": "16px"})
+assert-css: ("h5#sub-heading-for-union-impl-doc", {"border-bottom-width": "0px"})
+
+assert-css: ("h5#title-for-union-impl-item-doc", {"font-size": "16px"})
+assert-css: ("h5#title-for-union-impl-item-doc", {"border-bottom-width": "0px"})
+assert-css: ("h6#sub-heading-for-union-impl-item-doc", {"font-size": "15.2px"})
+assert-css: ("h6#sub-heading-for-union-impl-item-doc", {"border-bottom-width": "0px"})
+
+goto: file://|DOC_PATH|/test_docs/macro.heavily_documented_macro.html
+
+assert-css: ("h1.fqn", {"font-size": "24px"})
+assert-css: ("h1.fqn", {"border-bottom-width": "1px"})
+
+assert-css: ("h2#top-doc-prose-title", {"font-size": "20.8px"})
+assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"})
+assert-css: ("h3#top-doc-prose-sub-heading", {"font-size": "18.4px"})
+assert-css: ("h3#top-doc-prose-sub-heading", {"border-bottom-width": "1px"})
diff --git a/src/test/rustdoc-gui/javascript-disabled.goml b/src/test/rustdoc-gui/javascript-disabled.goml
new file mode 100644 (file)
index 0000000..1693f7b
--- /dev/null
@@ -0,0 +1,6 @@
+// When JavaScript is disabled, we hide the search bar, because it
+// can't be used without JS.
+javascript: false
+
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+assert-css: (".sub", {"display": "none"})
index ab595d28019210bfec57a956853fb640dd11ab75..0316172ee1464663e393d4290d63f01f7491b59b 100644 (file)
@@ -1,23 +1,23 @@
 // This test checks that the correct font is used on module items (in index.html pages).
 goto: file://|DOC_PATH|/test_docs/index.html
-assert-css: (".item-table .module-item a", {"font-family": '"Fira Sans", Arial, sans-serif'}, ALL)
-assert-css: (".item-table .docblock-short", {"font-family": '"Source Serif 4", "Noto Sans KR", serif'}, ALL)
+assert-css: (".item-table .module-item a", {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'}, ALL)
+assert-css: (".item-table .docblock-short", {"font-family": '"Source Serif 4", NanumBarunGothic, serif'}, ALL)
 
 // modules
-assert-css: ("#modules + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, sans-serif'})
-assert-css: ("#modules + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", "Noto Sans KR", serif'})
+assert-css: ("#modules + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'})
+assert-css: ("#modules + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", NanumBarunGothic, serif'})
 // structs
-assert-css: ("#structs + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, sans-serif'})
-assert-css: ("#structs + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", "Noto Sans KR", serif'})
+assert-css: ("#structs + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'})
+assert-css: ("#structs + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", NanumBarunGothic, serif'})
 // enums
-assert-css: ("#enums + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, sans-serif'})
-assert-css: ("#enums + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", "Noto Sans KR", serif'})
+assert-css: ("#enums + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'})
+assert-css: ("#enums + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", NanumBarunGothic, serif'})
 // traits
-assert-css: ("#traits + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, sans-serif'})
-assert-css: ("#traits + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", "Noto Sans KR", serif'})
+assert-css: ("#traits + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'})
+assert-css: ("#traits + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", NanumBarunGothic, serif'})
 // functions
-assert-css: ("#functions + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, sans-serif'})
-assert-css: ("#functions + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", "Noto Sans KR", serif'})
+assert-css: ("#functions + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'})
+assert-css: ("#functions + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", NanumBarunGothic, serif'})
 // keywords
-assert-css: ("#keywords + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, sans-serif'})
-assert-css: ("#keywords + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", "Noto Sans KR", serif'})
+assert-css: ("#keywords + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'})
+assert-css: ("#keywords + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", NanumBarunGothic, serif'})
diff --git a/src/test/rustdoc-gui/overflow-tooltip-information.goml b/src/test/rustdoc-gui/overflow-tooltip-information.goml
new file mode 100644 (file)
index 0000000..7ef85a4
--- /dev/null
@@ -0,0 +1,8 @@
+// The goal of this test is to ensure that the tooltip `.information` class doesn't
+// have overflow and max-width CSS rules set because they create a bug in firefox on
+// mac. For more information: https://github.com/rust-lang/rust/issues/89185
+goto: file://|DOC_PATH|/test_docs/fn.foo.html
+assert-css: (".docblock > .information", {
+    "overflow-x": "visible",
+    "max-width": "none"
+}, ALL)
index 62dc76a40bcf5a315904a5f0ee031a5813caad05..f9c707f81e79c8022c510a1f183d74f2f92cd5f6 100644 (file)
@@ -4,16 +4,17 @@ assert-text: (".sidebar > .location", "Crate test_docs")
 assert-count: (".sidebar .location", 1)
 assert-text: (".sidebar-elems > #all-types", "See all test_docs's items")
 // We check that we have the crates list and that the "current" on is "test_docs".
-assert-text: (".sidebar-elems .crate > ul > li > a.current", "test_docs")
+assert-text: (".sidebar-elems .crate > ul > li > a.current", "test_docs")
 // And we're also supposed to have the list of items in the current module.
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(2)", "Macros")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(3)", "Structs")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(4)", "Enums")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(5)", "Traits")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(6)", "Functions")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(7)", "Type Definitions")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(8)", "Keywords")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(1)", "Modules")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(2)", "Macros")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(3)", "Structs")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(4)", "Enums")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(5)", "Traits")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(6)", "Functions")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(7)", "Type Definitions")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(8)", "Unions")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(9)", "Keywords")
 assert-text: ("#structs + .item-table .item-left > a", "Foo")
 click: "#structs + .item-table .item-left > a"
 
@@ -23,13 +24,13 @@ assert-count: (".sidebar .location", 2)
 assert-false: ".sidebar-elems > .crate"
 // We now go back to the crate page to click on the "lib2" crate link.
 goto: file://|DOC_PATH|/test_docs/index.html
-click: ".sidebar-elems .crate > ul > li:first-child > a"
+click: ".sidebar-elems .crate > ul > li:first-child > a"
 
 // PAGE: lib2/index.html
 goto: file://|DOC_PATH|/lib2/index.html
 assert-text: (".sidebar > .location", "Crate lib2")
 // We check that we have the crates list and that the "current" on is now "lib2".
-assert-text: (".sidebar-elems .crate > ul > li > a.current", "lib2")
+assert-text: (".sidebar-elems .crate > ul > li > a.current", "lib2")
 // We now go to the "foobar" function page.
 assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
 assert-text: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs")
@@ -56,6 +57,6 @@ assert-false: ".sidebar-elems > .crate"
 goto: ./sub_module/sub_sub_module/index.html
 assert-text: (".sidebar > .location", "Module sub_sub_module")
 // We check that we don't have the crate list.
-assert-false: ".sidebar-elems .crate"
-assert-text: (".sidebar-elems .items > ul > li:nth-child(1)", "Functions")
+assert-false: ".sidebar-elems .crate"
+assert-text: (".sidebar-elems .items > ul > li:nth-child(1)", "Functions")
 assert-text: ("#functions + .item-table .item-left > a", "foo")
index 652308a71cb8501d6deb791d9cd33c2e80408799..14d8b18613087caf1d8c311cc7e4648f17ca109a 100644 (file)
@@ -131,3 +131,129 @@ macro_rules! repro {
 }
 
 pub use crate::repro as repro2;
+
+/// # Top-doc Prose title
+///
+/// Text below title.
+///
+/// ## Top-doc Prose sub-heading
+///
+/// Text below sub-heading.
+///
+/// ### Top-doc Prose sub-sub-heading
+///
+/// Text below sub-sub-heading
+pub struct HeavilyDocumentedStruct {
+    /// # Title for field
+    /// ## Sub-heading for field
+    pub nothing: (),
+}
+
+/// # Title for struct impl doc
+///
+/// Text below heading.
+///
+/// ## Sub-heading for struct impl doc
+///
+/// Text below sub-heading.
+///
+/// ### Sub-sub-heading for struct impl doc
+///
+/// Text below sub-sub-heading.
+///
+impl HeavilyDocumentedStruct {
+    /// # Title for struct impl-item doc
+    /// Text below title.
+    /// ## Sub-heading for struct impl-item doc
+    /// Text below sub-heading.
+    /// ### Sub-sub-heading for struct impl-item doc
+    /// Text below sub-sub-heading.
+    pub fn do_nothing() {}
+}
+
+/// # Top-doc Prose title
+///
+/// Text below title.
+///
+/// ## Top-doc Prose sub-heading
+///
+/// Text below sub-heading.
+///
+/// ### Top-doc Prose sub-sub-heading
+///
+/// Text below sub-sub-heading
+pub enum HeavilyDocumentedEnum {
+    /// # None prose title
+    /// ## None prose sub-heading
+    None,
+    /// # Wrapped prose title
+    /// ## Wrapped prose sub-heading
+    Wrapped(
+        /// # Wrapped.0 prose title
+        /// ## Wrapped.0 prose sub-heading
+        String,
+        String,
+    ),
+    Structy {
+        /// # Structy prose title
+        /// ## Structy prose sub-heading
+        alpha: String,
+        beta: String,
+    },
+}
+
+/// # Title for enum impl doc
+///
+/// Text below heading.
+///
+/// ## Sub-heading for enum impl doc
+///
+/// Text below sub-heading.
+///
+/// ### Sub-sub-heading for enum impl doc
+///
+/// Text below sub-sub-heading.
+///
+impl HeavilyDocumentedEnum {
+    /// # Title for enum impl-item doc
+    /// Text below title.
+    /// ## Sub-heading for enum impl-item doc
+    /// Text below sub-heading.
+    /// ### Sub-sub-heading for enum impl-item doc
+    /// Text below sub-sub-heading.
+    pub fn do_nothing() {}
+}
+
+/// # Top-doc prose title
+///
+/// Text below heading.
+///
+/// ## Top-doc prose sub-heading
+///
+/// Text below heading.
+pub union HeavilyDocumentedUnion {
+    /// # Title for union variant
+    /// ## Sub-heading for union variant
+    pub nothing: (),
+    pub something: f32,
+}
+
+/// # Title for union impl doc
+/// ## Sub-heading for union impl doc
+impl HeavilyDocumentedUnion {
+    /// # Title for union impl-item doc
+    /// ## Sub-heading for union impl-item doc
+    pub fn do_nothing() {}
+}
+
+/// # Top-doc prose title
+///
+/// Text below heading.
+///
+/// ## Top-doc prose sub-heading
+///
+/// Text below heading.
+#[macro_export]
+macro_rules! heavily_documented_macro {
+    () => {};
+}
index 49a80ae2360f542723017c49ab17dee74c724b0d..63a9ad5381244c635e80674ea8eafc11e04bd839 100644 (file)
@@ -1,10 +1,12 @@
 // exact-check
 
 const QUERY = [
-  '"R<P>"',
-  '"P"',
-  'P',
-  '"ExtraCreditStructMulti<ExtraCreditInnerMulti, ExtraCreditInnerMulti>"',
+    '"R<P>"',
+    '"P"',
+    'P',
+    '"ExtraCreditStructMulti<ExtraCreditInnerMulti, ExtraCreditInnerMulti>"',
+    'TraitCat',
+    'TraitDog',
 ];
 
 const EXPECTED = [
@@ -30,9 +32,11 @@ const EXPECTED = [
     {
         'returned': [
             { 'path': 'generics', 'name': 'alef' },
+            { 'path': 'generics', 'name': 'bet' },
         ],
         'in_args': [
             { 'path': 'generics', 'name': 'alpha' },
+            { 'path': 'generics', 'name': 'beta' },
         ],
     },
     {
@@ -41,4 +45,14 @@ const EXPECTED = [
         ],
         'returned': [],
     },
+    {
+        'in_args': [
+            { 'path': 'generics', 'name': 'gamma' },
+        ],
+    },
+    {
+        'in_args': [
+            { 'path': 'generics', 'name': 'gamma' },
+        ],
+    },
 ];
index a0dc086e9f9cfe17b55dabf6769ed1c1aa2620f4..5e11a6d6018856f75daaa7e73cc43fe7cd03764e 100644 (file)
@@ -19,3 +19,8 @@ pub fn extracreditlabhomework(
 pub fn redherringmatchforextracredit(
     _param: ExtraCreditStructMulti<ExtraCreditInnerMulti, ()>
 ) { loop {} }
+
+pub trait TraitCat {}
+pub trait TraitDog {}
+
+pub fn gamma<T: TraitCat + TraitDog>(t: T) {}
index 595ece2ea724707527b41ec419903c8182c90b5e..55006b2087eb024f3037bbc638dfbd8f23d8131c 100644 (file)
@@ -29,7 +29,7 @@ LL | pub fn foo() {}
    |
    = 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 #82730 <https://github.com/rust-lang/rust/issues/82730>
-   = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information
+   = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline for more information
 
 error: this attribute can only be applied at the crate level
   --> $DIR/invalid-doc-attr.rs:15:12
@@ -72,7 +72,7 @@ LL |     pub fn baz() {}
    |
    = 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 #82730 <https://github.com/rust-lang/rust/issues/82730>
-   = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information
+   = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline for more information
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/rustdoc-ui/recursive-deref-ice.rs b/src/test/rustdoc-ui/recursive-deref-ice.rs
new file mode 100644 (file)
index 0000000..c44fd27
--- /dev/null
@@ -0,0 +1,19 @@
+// check-pass
+
+// ICE found in https://github.com/rust-lang/rust/issues/83123
+
+pub struct Attribute;
+
+pub struct Map<'hir> {}
+impl<'hir> Map<'hir> {
+    pub fn attrs(&self) -> &'hir [Attribute] { &[] }
+}
+
+pub struct List<T>(T);
+
+impl<T> std::ops::Deref for List<T> {
+    type Target = [T];
+    fn deref(&self) -> &[T] {
+        &[]
+    }
+}
diff --git a/src/test/rustdoc/deref-recursive-pathbuf.rs b/src/test/rustdoc/deref-recursive-pathbuf.rs
new file mode 100644 (file)
index 0000000..9ab338c
--- /dev/null
@@ -0,0 +1,25 @@
+// #26207: Show all methods reachable via Deref impls, recursing through multiple dereferencing
+// levels and across multiple crates.
+// For `Deref` on non-foreign types, look at `deref-recursive.rs`.
+
+// @has 'foo/struct.Foo.html'
+// @has '-' '//*[@id="deref-methods-PathBuf"]' 'Methods from Deref<Target = PathBuf>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.as_path"]' 'pub fn as_path(&self)'
+// @has '-' '//*[@id="deref-methods-Path"]' 'Methods from Deref<Target = Path>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.exists"]' 'pub fn exists(&self)'
+// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-PathBuf"]' 'Methods from Deref<Target=PathBuf>'
+// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.as_path"]' 'as_path'
+// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Path"]' 'Methods from Deref<Target=Path>'
+// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.exists"]' 'exists'
+
+#![crate_name = "foo"]
+
+use std::ops::Deref;
+use std::path::PathBuf;
+
+pub struct Foo(PathBuf);
+
+impl Deref for Foo {
+    type Target = PathBuf;
+    fn deref(&self) -> &PathBuf { &self.0 }
+}
diff --git a/src/test/rustdoc/deref-recursive.rs b/src/test/rustdoc/deref-recursive.rs
new file mode 100644 (file)
index 0000000..c07e048
--- /dev/null
@@ -0,0 +1,41 @@
+// #26207: Show all methods reachable via Deref impls, recursing through multiple dereferencing
+// levels if needed.
+// For `Deref` on foreign types, look at `deref-recursive-pathbuf.rs`.
+
+// @has 'foo/struct.Foo.html'
+// @has '-' '//*[@id="deref-methods-Bar"]' 'Methods from Deref<Target = Bar>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.bar"]' 'pub fn bar(&self)'
+// @has '-' '//*[@id="deref-methods-Baz"]' 'Methods from Deref<Target = Baz>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.baz"]' 'pub fn baz(&self)'
+// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Bar"]' 'Methods from Deref<Target=Bar>'
+// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.bar"]' 'bar'
+// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Baz"]' 'Methods from Deref<Target=Baz>'
+// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.baz"]' 'baz'
+
+#![crate_name = "foo"]
+
+use std::ops::Deref;
+
+pub struct Foo(Bar);
+pub struct Bar(Baz);
+pub struct Baz;
+
+impl Deref for Foo {
+    type Target = Bar;
+    fn deref(&self) -> &Bar { &self.0 }
+}
+
+impl Deref for Bar {
+    type Target = Baz;
+    fn deref(&self) -> &Baz { &self.0 }
+}
+
+impl Bar {
+    /// This appears under `Foo` methods
+    pub fn bar(&self) {}
+}
+
+impl Baz {
+    /// This should also appear in `Foo` methods when recursing
+    pub fn baz(&self) {}
+}
index d42ff384b29b83863eb9b9aa81600bb74930d634..ad7a96c5dad1fc7c6ce37cc1746c13b7387b85d7 100644 (file)
@@ -1,12 +1,12 @@
 #![crate_name = "foo"]
 
 // @has 'foo/struct.Bar.html'
-// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref<Target = FooJ>'
+// @has '-' '//*[@id="deref-methods-FooJ"]' 'Methods from Deref<Target = FooJ>'
 // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_a"]' 'pub fn foo_a(&self)'
 // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_b"]' 'pub fn foo_b(&self)'
 // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_c"]' 'pub fn foo_c(&self)'
 // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_j"]' 'pub fn foo_j(&self)'
-// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods"]' 'Methods from Deref<Target=FooJ>'
+// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-FooJ"]' 'Methods from Deref<Target=FooJ>'
 // @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_a"]' 'foo_a'
 // @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_b"]' 'foo_b'
 // @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_c"]' 'foo_c'
diff --git a/src/test/rustdoc/doc-auto-cfg.rs b/src/test/rustdoc/doc-auto-cfg.rs
new file mode 100644 (file)
index 0000000..fcdd835
--- /dev/null
@@ -0,0 +1,8 @@
+#![feature(doc_auto_cfg)]
+
+#![crate_name = "foo"]
+
+// @has foo/fn.foo.html
+// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-test'
+#[cfg(not(test))]
+pub fn foo() {}
index b9d0d32313723ddb1128b563e33237881ef7ab11..424fa6d6a911fac841884f3d302fcb7a0805ed6c 100644 (file)
@@ -1,5 +1,5 @@
 #![crate_name = "oud"]
-#![feature(doc_cfg, doc_cfg_hide)]
+#![feature(doc_auto_cfg, doc_cfg, doc_cfg_hide)]
 
 #![doc(cfg_hide(feature = "solecism"))]
 
index 36c2025785d0f87a8e76915fe7fcd3ce897b4fe8..5d17a4ede6adcb16da2a182c0abe50e36b64132f 100644 (file)
@@ -1,5 +1,5 @@
 #![crate_name = "funambulism"]
-#![feature(doc_cfg)]
+#![feature(doc_auto_cfg, doc_cfg)]
 
 // @has 'funambulism/struct.Disorbed.html'
 // @count   - '//*[@class="stab portability"]' 1
diff --git a/src/test/rustdoc/feature-gate-doc_auto_cfg.rs b/src/test/rustdoc/feature-gate-doc_auto_cfg.rs
new file mode 100644 (file)
index 0000000..da76381
--- /dev/null
@@ -0,0 +1,8 @@
+#![feature(doc_cfg)]
+
+#![crate_name = "foo"]
+
+// @has foo/fn.foo.html
+// @count - '//*[@class="item-info"]/*[@class="stab portability"]' 0
+#[cfg(not(test))]
+pub fn foo() {}
diff --git a/src/test/rustdoc/include_str_cut.rs b/src/test/rustdoc/include_str_cut.rs
new file mode 100644 (file)
index 0000000..cbc1ba8
--- /dev/null
@@ -0,0 +1,7 @@
+#![crate_name = "foo"]
+#![no_std]
+
+// @has 'foo/fn.foo.html'
+// @has - '//*[@class="docblock"]' 'inc2 x'
+#[doc = include_str!("short-line.md")]
+pub fn foo() {}
index fcb636ade8f7ad2729ae0f9786b005ba401ef6ed..65a7debc2538dd8e1804d0a302956a0e60fe5c2c 100644 (file)
@@ -15,7 +15,7 @@ impl Deref for A {
     fn deref(&self) -> &B { todo!() }
 }
 
-// @!has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_c'
+// @has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_c'
 impl Deref for B {
     type Target = C;
     fn deref(&self) -> &C { todo!() }
index 3d17bce472154e7de09411c3ab85e27b633edcf4..a7504fbccfb508f9384b13b551698a2fc59fd2cc 100644 (file)
@@ -1,9 +1,16 @@
 use std::ops::Deref;
 
+// Cyclic deref with the parent (which is not the top parent).
 pub struct A;
 pub struct B;
+pub struct C;
+
+impl C {
+    pub fn c(&self) {}
+}
 
 // @has recursive_deref/struct.A.html '//h3[@class="code-header in-band"]' 'impl Deref for A'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.c"]' 'pub fn c(&self)'
 impl Deref for A {
     type Target = B;
 
@@ -13,8 +20,99 @@ fn deref(&self) -> &Self::Target {
 }
 
 // @has recursive_deref/struct.B.html '//h3[@class="code-header in-band"]' 'impl Deref for B'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.c"]' 'pub fn c(&self)'
 impl Deref for B {
-    type Target = A;
+    type Target = C;
+
+    fn deref(&self) -> &Self::Target {
+        panic!()
+    }
+}
+
+// @has recursive_deref/struct.C.html '//h3[@class="code-header in-band"]' 'impl Deref for C'
+impl Deref for C {
+    type Target = B;
+
+    fn deref(&self) -> &Self::Target {
+        panic!()
+    }
+}
+
+// Cyclic deref with the grand-parent (which is not the top parent).
+pub struct D;
+pub struct E;
+pub struct F;
+pub struct G;
+
+impl G {
+    // There is no "self" parameter so it shouldn't be listed!
+    pub fn g() {}
+}
+
+// @has recursive_deref/struct.D.html '//h3[@class="code-header in-band"]' 'impl Deref for D'
+// We also check that `G::g` method isn't rendered because there is no `self` argument.
+// @!has '-' '//*[@id="deref-methods-G"]'
+impl Deref for D {
+    type Target = E;
+
+    fn deref(&self) -> &Self::Target {
+        panic!()
+    }
+}
+
+// @has recursive_deref/struct.E.html '//h3[@class="code-header in-band"]' 'impl Deref for E'
+// We also check that `G::g` method isn't rendered because there is no `self` argument.
+// @!has '-' '//*[@id="deref-methods-G"]'
+impl Deref for E {
+    type Target = F;
+
+    fn deref(&self) -> &Self::Target {
+        panic!()
+    }
+}
+
+// @has recursive_deref/struct.F.html '//h3[@class="code-header in-band"]' 'impl Deref for F'
+// We also check that `G::g` method isn't rendered because there is no `self` argument.
+// @!has '-' '//*[@id="deref-methods-G"]'
+impl Deref for F {
+    type Target = G;
+
+    fn deref(&self) -> &Self::Target {
+        panic!()
+    }
+}
+
+// @has recursive_deref/struct.G.html '//h3[@class="code-header in-band"]' 'impl Deref for G'
+impl Deref for G {
+    type Target = E;
+
+    fn deref(&self) -> &Self::Target {
+        panic!()
+    }
+}
+
+// Cyclic deref with top parent.
+pub struct H;
+pub struct I;
+
+impl I {
+    // There is no "self" parameter so it shouldn't be listed!
+    pub fn i() {}
+}
+
+// @has recursive_deref/struct.H.html '//h3[@class="code-header in-band"]' 'impl Deref for H'
+// @!has '-' '//*[@id="deref-methods-I"]'
+impl Deref for H {
+    type Target = I;
+
+    fn deref(&self) -> &Self::Target {
+        panic!()
+    }
+}
+
+// @has recursive_deref/struct.I.html '//h3[@class="code-header in-band"]' 'impl Deref for I'
+impl Deref for I {
+    type Target = H;
 
     fn deref(&self) -> &Self::Target {
         panic!()
diff --git a/src/test/rustdoc/short-line.md b/src/test/rustdoc/short-line.md
new file mode 100644 (file)
index 0000000..eff713b
--- /dev/null
@@ -0,0 +1,2 @@
+inc2
+x
diff --git a/src/test/ui-fulldeps/internal-lints/query_stability.rs b/src/test/ui-fulldeps/internal-lints/query_stability.rs
deleted file mode 100644 (file)
index 560675b..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// compile-flags: -Z unstable-options
-
-#![feature(rustc_private)]
-#![deny(rustc::potential_query_instability)]
-
-extern crate rustc_data_structures;
-
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-
-fn main() {
-    let mut x = FxHashMap::<u32, i32>::default();
-
-    for _ in x.drain() {}
-    //~^ ERROR using `drain` can result in unstable
-
-    for _ in x.iter() {}
-    //~^ ERROR using `iter`
-
-    for _ in Some(&mut x).unwrap().iter_mut() {}
-    //~^ ERROR using `iter_mut`
-
-    for _ in x {}
-    //~^ ERROR using `into_iter`
-}
diff --git a/src/test/ui-fulldeps/internal-lints/query_stability.stderr b/src/test/ui-fulldeps/internal-lints/query_stability.stderr
deleted file mode 100644 (file)
index 7e8b448..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-error: using `drain` can result in unstable query results
-  --> $DIR/query_stability.rs:13:16
-   |
-LL |     for _ in x.drain() {}
-   |                ^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/query_stability.rs:4:9
-   |
-LL | #![deny(rustc::potential_query_instability)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
-
-error: using `iter` can result in unstable query results
-  --> $DIR/query_stability.rs:16:16
-   |
-LL |     for _ in x.iter() {}
-   |                ^^^^
-   |
-   = note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
-
-error: using `iter_mut` can result in unstable query results
-  --> $DIR/query_stability.rs:19:36
-   |
-LL |     for _ in Some(&mut x).unwrap().iter_mut() {}
-   |                                    ^^^^^^^^
-   |
-   = note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
-
-error: using `into_iter` can result in unstable query results
-  --> $DIR/query_stability.rs:22:14
-   |
-LL |     for _ in x {}
-   |              ^
-   |
-   = note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
-
-error: aborting due to 4 previous errors
-
diff --git a/src/test/ui-fulldeps/internal-lints/query_stability_incorrect.rs b/src/test/ui-fulldeps/internal-lints/query_stability_incorrect.rs
deleted file mode 100644 (file)
index f478b73..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// compile-flags: -Z unstable-options
-
-#![feature(rustc_attrs)]
-
-#[rustc_lint_query_instability]
-//~^ ERROR attribute should be applied to a function
-struct Foo;
-
-impl Foo {
-    #[rustc_lint_query_instability(a)]
-    //~^ ERROR malformed `rustc_lint_query_instability`
-    fn bar() {}
-}
-
-fn main() {}
diff --git a/src/test/ui-fulldeps/internal-lints/query_stability_incorrect.stderr b/src/test/ui-fulldeps/internal-lints/query_stability_incorrect.stderr
deleted file mode 100644 (file)
index b5156f2..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error: malformed `rustc_lint_query_instability` attribute input
-  --> $DIR/query_stability_incorrect.rs:10:5
-   |
-LL |     #[rustc_lint_query_instability(a)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_lint_query_instability]`
-
-error: attribute should be applied to a function
-  --> $DIR/query_stability_incorrect.rs:5:1
-   |
-LL | #[rustc_lint_query_instability]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | struct Foo;
-   | ----------- not a function
-
-error: aborting due to 2 previous errors
-
index f92bcd213b844a272914c36cf2ceea10bb58ab0f..0d04eb6fcfa968be6ad6f942561531619a719bda 100644 (file)
 //~^ WARNING lint name `test_lint` is deprecated and may not have an effect in the future
 //~| WARNING lint name `test_lint` is deprecated and may not have an effect in the future
 //~| WARNING lint name `test_lint` is deprecated and may not have an effect in the future
+//~| WARNING lint name `test_lint` is deprecated and may not have an effect in the future
 #![deny(clippy_group)]
 //~^ WARNING lint name `clippy_group` is deprecated and may not have an effect in the future
 //~| WARNING lint name `clippy_group` is deprecated and may not have an effect in the future
 //~| WARNING lint name `clippy_group` is deprecated and may not have an effect in the future
+//~| WARNING lint name `clippy_group` is deprecated and may not have an effect in the future
 
 fn lintme() { } //~ ERROR item is named 'lintme'
 
@@ -30,6 +32,7 @@ fn lintmetoo() { } //~ ERROR item is named 'lintmetoo'
 //~^ WARNING lint name `test_group` is deprecated and may not have an effect in the future
 //~| WARNING lint name `test_group` is deprecated and may not have an effect in the future
 //~| WARNING lint name `test_group` is deprecated and may not have an effect in the future
+//~| WARNING lint name `test_group` is deprecated and may not have an effect in the future
 #[deny(this_lint_does_not_exist)] //~ WARNING unknown lint: `this_lint_does_not_exist`
 fn hello() {
     fn lintmetoo() { }
index 2260477a91d39a642d9d83e053c76dbf9bf4c0b5..0f76384ed5ba5001d6325ea8407e1322a53e7222 100644 (file)
@@ -7,19 +7,19 @@ LL | #![cfg_attr(foo, warn(test_lint))]
    = note: `#[warn(renamed_and_removed_lints)]` on by default
 
 warning: lint name `clippy_group` is deprecated and may not have an effect in the future.
-  --> $DIR/lint-tool-test.rs:13:9
+  --> $DIR/lint-tool-test.rs:14:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
 
 warning: lint name `test_group` is deprecated and may not have an effect in the future.
-  --> $DIR/lint-tool-test.rs:29:9
+  --> $DIR/lint-tool-test.rs:31:9
    |
 LL | #[allow(test_group)]
    |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
 
 warning: unknown lint: `this_lint_does_not_exist`
-  --> $DIR/lint-tool-test.rs:33:8
+  --> $DIR/lint-tool-test.rs:36:8
    |
 LL | #[deny(this_lint_does_not_exist)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -33,13 +33,13 @@ LL | #![cfg_attr(foo, warn(test_lint))]
    |                       ^^^^^^^^^ help: change it to: `clippy::test_lint`
 
 warning: lint name `clippy_group` is deprecated and may not have an effect in the future.
-  --> $DIR/lint-tool-test.rs:13:9
+  --> $DIR/lint-tool-test.rs:14:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
 
 warning: lint name `test_group` is deprecated and may not have an effect in the future.
-  --> $DIR/lint-tool-test.rs:29:9
+  --> $DIR/lint-tool-test.rs:31:9
    |
 LL | #[allow(test_group)]
    |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
@@ -59,42 +59,60 @@ LL | #![cfg_attr(foo, warn(test_lint))]
    |                       ^^^^^^^^^ help: change it to: `clippy::test_lint`
 
 warning: lint name `clippy_group` is deprecated and may not have an effect in the future.
-  --> $DIR/lint-tool-test.rs:13:9
+  --> $DIR/lint-tool-test.rs:14:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
 
 error: item is named 'lintme'
-  --> $DIR/lint-tool-test.rs:18:1
+  --> $DIR/lint-tool-test.rs:20:1
    |
 LL | fn lintme() { }
    | ^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/lint-tool-test.rs:13:9
+  --> $DIR/lint-tool-test.rs:14:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^
    = note: `#[deny(clippy::test_lint)]` implied by `#[deny(clippy::group)]`
 
 error: item is named 'lintmetoo'
-  --> $DIR/lint-tool-test.rs:26:5
+  --> $DIR/lint-tool-test.rs:28:5
    |
 LL |     fn lintmetoo() { }
    |     ^^^^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/lint-tool-test.rs:13:9
+  --> $DIR/lint-tool-test.rs:14:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^
    = note: `#[deny(clippy::test_group)]` implied by `#[deny(clippy::group)]`
 
 warning: lint name `test_group` is deprecated and may not have an effect in the future.
-  --> $DIR/lint-tool-test.rs:29:9
+  --> $DIR/lint-tool-test.rs:31:9
    |
 LL | #[allow(test_group)]
    |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
 
-error: aborting due to 2 previous errors; 11 warnings emitted
+warning: lint name `test_lint` is deprecated and may not have an effect in the future.
+  --> $DIR/lint-tool-test.rs:9:23
+   |
+LL | #![cfg_attr(foo, warn(test_lint))]
+   |                       ^^^^^^^^^ help: change it to: `clippy::test_lint`
+
+warning: lint name `clippy_group` is deprecated and may not have an effect in the future.
+  --> $DIR/lint-tool-test.rs:14:9
+   |
+LL | #![deny(clippy_group)]
+   |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
+
+warning: lint name `test_group` is deprecated and may not have an effect in the future.
+  --> $DIR/lint-tool-test.rs:31:9
+   |
+LL | #[allow(test_group)]
+   |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
+
+error: aborting due to 2 previous errors; 14 warnings emitted
 
index 225d49e05a3fa49fef67994992f726d6c772bbcf..a948947dbdb610df2e36d4d6193f6fc70f03d107 100644 (file)
@@ -40,25 +40,22 @@ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target
 LL | extern "x86-interrupt" fn x86() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of calling convention not supported on this target
+error[E0570]: `"thiscall"` is not a supported ABI for the current target
   --> $DIR/unsupported.rs:43:1
    |
-LL | extern "stdcall" fn stdcall() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(unsupported_calling_conventions)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
+LL | extern "thiscall" fn thiscall() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of calling convention not supported on this target
-  --> $DIR/unsupported.rs:50:1
+  --> $DIR/unsupported.rs:47:1
    |
-LL | extern "thiscall" fn thiscall() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | extern "stdcall" fn stdcall() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: `#[warn(unsupported_calling_conventions)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
 
-error: aborting due to 7 previous errors; 2 warnings emitted
+error: aborting due to 8 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0570`.
index b050ee0aa3148501b5bc94661152b5d2a07633b3..297354c28289569d064fd1e0f42fd81e4b522aab 100644 (file)
@@ -34,25 +34,22 @@ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target
 LL | extern "x86-interrupt" fn x86() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of calling convention not supported on this target
+error[E0570]: `"thiscall"` is not a supported ABI for the current target
   --> $DIR/unsupported.rs:43:1
    |
-LL | extern "stdcall" fn stdcall() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(unsupported_calling_conventions)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
+LL | extern "thiscall" fn thiscall() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of calling convention not supported on this target
-  --> $DIR/unsupported.rs:50:1
+  --> $DIR/unsupported.rs:47:1
    |
-LL | extern "thiscall" fn thiscall() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | extern "stdcall" fn stdcall() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: `#[warn(unsupported_calling_conventions)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
 
-error: aborting due to 6 previous errors; 2 warnings emitted
+error: aborting due to 7 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0570`.
index 9319eac8d30d84bd84be935d7bd7fe0ba49fe17d..6427a5695c0297c032f5d2601da51e91654b60cc 100644 (file)
@@ -40,14 +40,11 @@ extern "avr-interrupt" fn avr() {}
 extern "x86-interrupt" fn x86() {}
 //[aarch64]~^ ERROR is not a supported ABI
 //[arm]~^^ ERROR is not a supported ABI
-extern "stdcall" fn stdcall() {}
-//[x64]~^ WARN use of calling convention not supported
-//[x64]~^^ WARN this was previously accepted
-//[aarch64]~^^^ WARN use of calling convention not supported
-//[aarch64]~^^^^ WARN this was previously accepted
-//[arm]~^^^^^ WARN use of calling convention not supported
-//[arm]~^^^^^^ WARN this was previously accepted
 extern "thiscall" fn thiscall() {}
+//[x64]~^ ERROR is not a supported ABI
+//[aarch64]~^^ ERROR is not a supported ABI
+//[arm]~^^^ ERROR is not a supported ABI
+extern "stdcall" fn stdcall() {}
 //[x64]~^ WARN use of calling convention not supported
 //[x64]~^^ WARN this was previously accepted
 //[aarch64]~^^^ WARN use of calling convention not supported
index f2f52683324dba69576e9759aa00e298d88a7c3c..49b88cd3fac939c559b2bfda5d4ad4fba8024aa3 100644 (file)
@@ -34,25 +34,22 @@ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
 LL | extern "avr-interrupt" fn avr() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of calling convention not supported on this target
+error[E0570]: `"thiscall"` is not a supported ABI for the current target
   --> $DIR/unsupported.rs:43:1
    |
-LL | extern "stdcall" fn stdcall() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(unsupported_calling_conventions)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
+LL | extern "thiscall" fn thiscall() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of calling convention not supported on this target
-  --> $DIR/unsupported.rs:50:1
+  --> $DIR/unsupported.rs:47:1
    |
-LL | extern "thiscall" fn thiscall() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | extern "stdcall" fn stdcall() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: `#[warn(unsupported_calling_conventions)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
 
-error: aborting due to 6 previous errors; 2 warnings emitted
+error: aborting due to 7 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0570`.
diff --git a/src/test/ui/argument-passing.rs b/src/test/ui/argument-passing.rs
deleted file mode 100644 (file)
index 74759a4..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// run-pass
-
-struct X {
-    x: isize
-}
-
-fn f1(a: &mut X, b: &mut isize, c: isize) -> isize {
-    let r = a.x + *b + c;
-    a.x = 0;
-    *b = 10;
-    return r;
-}
-
-fn f2<F>(a: isize, f: F) -> isize where F: FnOnce(isize) { f(1); return a; }
-
-pub fn main() {
-    let mut a = X {x: 1};
-    let mut b = 2;
-    let c = 3;
-    assert_eq!(f1(&mut a, &mut b, c), 6);
-    assert_eq!(a.x, 0);
-    assert_eq!(b, 10);
-    assert_eq!(f2(a.x, |_| a.x = 50), 0);
-    assert_eq!(a.x, 50);
-}
diff --git a/src/test/ui/array-slice-vec/mut-vstore-expr.rs b/src/test/ui/array-slice-vec/mut-vstore-expr.rs
new file mode 100644 (file)
index 0000000..75b309a
--- /dev/null
@@ -0,0 +1,6 @@
+// run-pass
+// pretty-expanded FIXME #23616
+
+pub fn main() {
+    let _x: &mut [isize] = &mut [ 1, 2, 3 ];
+}
index 22d0499a1cc1d0c3cb6da58e8f82dd4d779cd385..4d7a7fd31feca7b5dacb21236ce712ffdbc20c6b 100644 (file)
@@ -1,7 +1,7 @@
 // only-aarch64
 // compile-flags: -C target-feature=+fp
 
-#![feature(asm)]
+#![feature(asm, asm_const, asm_sym)]
 
 fn main() {
     let mut foo = 0;
index 05165b2d46c0dd3eb85fccd5dd7711d57592b269..49fe48600c25c4948df632d25a2a02d82cb07338 100644 (file)
@@ -3,7 +3,7 @@
 // revisions: mirunsafeck thirunsafeck
 // [thirunsafeck]compile-flags: -Z thir-unsafeck
 
-#![feature(asm, global_asm)]
+#![feature(asm, global_asm, asm_const)]
 
 fn const_generic<const X: usize>() -> usize {
     unsafe {
index faa5e37b781ecffe1f8352304c112f472c1ce7b6..e19c5cd13d35aa545ab0565cff43989a681806d9 100644 (file)
@@ -1,6 +1,6 @@
 // only-aarch64
 
-#![feature(asm, global_asm)]
+#![feature(asm, global_asm, asm_const)]
 
 fn main() {
     let mut foo = 0;
index 526555334cb882cd1cf2c5d97ef225bab56974fc..b0dd143a0a1b6de603dae63e6dfc7e7c8422a6dc 100644 (file)
@@ -2,7 +2,7 @@
 // only-linux
 // run-pass
 
-#![feature(asm, thread_local)]
+#![feature(asm, thread_local, asm_sym)]
 
 extern "C" fn f1() -> i32 {
     111
@@ -75,5 +75,7 @@ fn main() {
     std::thread::spawn(|| {
         assert_eq!(static_addr!(S1), &S1 as *const u32);
         assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
-    }).join().unwrap();
+    })
+    .join()
+    .unwrap();
 }
index cf25dcb930c7920e0c6cb2d185a75683094b2756..e1e8a91dda6033a8087682b4d5b2c5a65d730210 100644 (file)
@@ -1,6 +1,6 @@
 // only-aarch64
 
-#![feature(asm, repr_simd, never_type)]
+#![feature(asm, repr_simd, never_type, asm_sym)]
 
 #[repr(simd)]
 #[derive(Clone, Copy)]
index d0d5954ca4aef78eb67355cb1c9497743e024419..fc1831a520a0cbc0b702c7756cf5321d29231d75 100644 (file)
@@ -1,13 +1,13 @@
 // only-aarch64
 // compile-flags: -C target-feature=+neon
 
-#![feature(asm, global_asm, repr_simd, stdsimd)]
+#![feature(asm, global_asm, repr_simd, stdsimd, asm_const)]
 
 use std::arch::aarch64::float64x2_t;
 
 #[repr(simd)]
 #[derive(Copy, Clone)]
-struct Simd256bit(f64, f64,f64, f64);
+struct Simd256bit(f64, f64, f64, f64);
 
 fn main() {
     let f64x2: float64x2_t = unsafe { std::mem::transmute(0i128) };
@@ -42,7 +42,6 @@ fn main() {
         asm!("{:b}", in(vreg) 0u64);
         asm!("{:d}", in(vreg_low16) f64x2);
 
-
         // Template modifier suggestions for sub-registers
 
         asm!("{}", in(reg) 0u8);
index c31a62ae7912a59e67303750374ae7f02520191f..ed9d3147b9ffaa52358a1fb85bd240bcb3a6e10d 100644 (file)
@@ -1,5 +1,5 @@
 warning: formatting may not be suitable for sub-register argument
-  --> $DIR/type-check-3.rs:48:15
+  --> $DIR/type-check-3.rs:47:15
    |
 LL |         asm!("{}", in(reg) 0u8);
    |               ^^           --- for this argument
@@ -9,7 +9,7 @@ LL |         asm!("{}", in(reg) 0u8);
    = help: or use the `x` modifier to keep the default formatting of `x0`
 
 warning: formatting may not be suitable for sub-register argument
-  --> $DIR/type-check-3.rs:50:15
+  --> $DIR/type-check-3.rs:49:15
    |
 LL |         asm!("{}", in(reg) 0u16);
    |               ^^           ---- for this argument
@@ -18,7 +18,7 @@ LL |         asm!("{}", in(reg) 0u16);
    = help: or use the `x` modifier to keep the default formatting of `x0`
 
 warning: formatting may not be suitable for sub-register argument
-  --> $DIR/type-check-3.rs:52:15
+  --> $DIR/type-check-3.rs:51:15
    |
 LL |         asm!("{}", in(reg) 0i32);
    |               ^^           ---- for this argument
@@ -27,7 +27,7 @@ LL |         asm!("{}", in(reg) 0i32);
    = help: or use the `x` modifier to keep the default formatting of `x0`
 
 warning: formatting may not be suitable for sub-register argument
-  --> $DIR/type-check-3.rs:54:15
+  --> $DIR/type-check-3.rs:53:15
    |
 LL |         asm!("{}", in(reg) 0f32);
    |               ^^           ---- for this argument
@@ -36,7 +36,7 @@ LL |         asm!("{}", in(reg) 0f32);
    = help: or use the `x` modifier to keep the default formatting of `x0`
 
 warning: formatting may not be suitable for sub-register argument
-  --> $DIR/type-check-3.rs:57:15
+  --> $DIR/type-check-3.rs:56:15
    |
 LL |         asm!("{}", in(vreg) 0i16);
    |               ^^            ---- for this argument
@@ -45,7 +45,7 @@ LL |         asm!("{}", in(vreg) 0i16);
    = help: or use the `v` modifier to keep the default formatting of `v0`
 
 warning: formatting may not be suitable for sub-register argument
-  --> $DIR/type-check-3.rs:59:15
+  --> $DIR/type-check-3.rs:58:15
    |
 LL |         asm!("{}", in(vreg) 0f32);
    |               ^^            ---- for this argument
@@ -54,7 +54,7 @@ LL |         asm!("{}", in(vreg) 0f32);
    = help: or use the `v` modifier to keep the default formatting of `v0`
 
 warning: formatting may not be suitable for sub-register argument
-  --> $DIR/type-check-3.rs:61:15
+  --> $DIR/type-check-3.rs:60:15
    |
 LL |         asm!("{}", in(vreg) 0f64);
    |               ^^            ---- for this argument
@@ -63,7 +63,7 @@ LL |         asm!("{}", in(vreg) 0f64);
    = help: or use the `v` modifier to keep the default formatting of `v0`
 
 warning: formatting may not be suitable for sub-register argument
-  --> $DIR/type-check-3.rs:63:15
+  --> $DIR/type-check-3.rs:62:15
    |
 LL |         asm!("{}", in(vreg_low16) 0f64);
    |               ^^                  ---- for this argument
@@ -72,7 +72,7 @@ LL |         asm!("{}", in(vreg_low16) 0f64);
    = help: or use the `v` modifier to keep the default formatting of `v0`
 
 warning: formatting may not be suitable for sub-register argument
-  --> $DIR/type-check-3.rs:66:15
+  --> $DIR/type-check-3.rs:65:15
    |
 LL |         asm!("{0} {0}", in(reg) 0i16);
    |               ^^^ ^^^           ---- for this argument
@@ -81,7 +81,7 @@ LL |         asm!("{0} {0}", in(reg) 0i16);
    = help: or use the `x` modifier to keep the default formatting of `x0`
 
 warning: formatting may not be suitable for sub-register argument
-  --> $DIR/type-check-3.rs:68:15
+  --> $DIR/type-check-3.rs:67:15
    |
 LL |         asm!("{0} {0:x}", in(reg) 0i16);
    |               ^^^                 ---- for this argument
@@ -90,7 +90,7 @@ LL |         asm!("{0} {0:x}", in(reg) 0i16);
    = help: or use the `x` modifier to keep the default formatting of `x0`
 
 error: type `i128` cannot be used with this register class
-  --> $DIR/type-check-3.rs:73:28
+  --> $DIR/type-check-3.rs:72:28
    |
 LL |         asm!("{}", in(reg) 0i128);
    |                            ^^^^^
@@ -98,7 +98,7 @@ LL |         asm!("{}", in(reg) 0i128);
    = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64
 
 error: type `float64x2_t` cannot be used with this register class
-  --> $DIR/type-check-3.rs:75:28
+  --> $DIR/type-check-3.rs:74:28
    |
 LL |         asm!("{}", in(reg) f64x2);
    |                            ^^^^^
@@ -106,7 +106,7 @@ LL |         asm!("{}", in(reg) f64x2);
    = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64
 
 error: type `Simd256bit` cannot be used with this register class
-  --> $DIR/type-check-3.rs:77:29
+  --> $DIR/type-check-3.rs:76:29
    |
 LL |         asm!("{}", in(vreg) f64x4);
    |                             ^^^^^
@@ -114,7 +114,7 @@ LL |         asm!("{}", in(vreg) f64x4);
    = note: register class `vreg` supports these types: i8, i16, i32, i64, f32, f64, i8x8, i16x4, i32x2, i64x1, f32x2, f64x1, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2
 
 error: incompatible types for asm inout argument
-  --> $DIR/type-check-3.rs:88:33
+  --> $DIR/type-check-3.rs:87:33
    |
 LL |         asm!("{:x}", inout(reg) 0u32 => val_f32);
    |                                 ^^^^    ^^^^^^^ type `f32`
@@ -124,7 +124,7 @@ LL |         asm!("{:x}", inout(reg) 0u32 => val_f32);
    = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
 
 error: incompatible types for asm inout argument
-  --> $DIR/type-check-3.rs:90:33
+  --> $DIR/type-check-3.rs:89:33
    |
 LL |         asm!("{:x}", inout(reg) 0u32 => val_ptr);
    |                                 ^^^^    ^^^^^^^ type `*mut u8`
@@ -134,7 +134,7 @@ LL |         asm!("{:x}", inout(reg) 0u32 => val_ptr);
    = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
 
 error: incompatible types for asm inout argument
-  --> $DIR/type-check-3.rs:92:33
+  --> $DIR/type-check-3.rs:91:33
    |
 LL |         asm!("{:x}", inout(reg) main => val_u32);
    |                                 ^^^^    ^^^^^^^ type `u32`
@@ -144,7 +144,7 @@ LL |         asm!("{:x}", inout(reg) main => val_u32);
    = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
 
 error[E0013]: constants cannot refer to statics
-  --> $DIR/type-check-3.rs:108:25
+  --> $DIR/type-check-3.rs:107:25
    |
 LL | global_asm!("{}", const S);
    |                         ^
@@ -152,7 +152,7 @@ LL | global_asm!("{}", const S);
    = help: consider extracting the value of the `static` to a `const`, and referring to that
 
 error[E0013]: constants cannot refer to statics
-  --> $DIR/type-check-3.rs:111:35
+  --> $DIR/type-check-3.rs:110:35
    |
 LL | global_asm!("{}", const const_foo(S));
    |                                   ^
@@ -160,7 +160,7 @@ LL | global_asm!("{}", const const_foo(S));
    = help: consider extracting the value of the `static` to a `const`, and referring to that
 
 error[E0013]: constants cannot refer to statics
-  --> $DIR/type-check-3.rs:114:35
+  --> $DIR/type-check-3.rs:113:35
    |
 LL | global_asm!("{}", const const_bar(S));
    |                                   ^
index fca77e7aa71f37d9b3841cbaf4e9a1fe31793dd7..b062c45e6ea34947b37ab09c98d49f23f6a3eec2 100644 (file)
@@ -10,7 +10,7 @@
 // [aarch64_thirunsafeck] needs-llvm-components: aarch64
 // [aarch64_mirunsafeck] needs-llvm-components: aarch64
 
-#![feature(no_core, lang_items, rustc_attrs)]
+#![feature(no_core, lang_items, rustc_attrs, asm_const)]
 #![no_core]
 
 #[rustc_builtin_macro]
index bdcf3f305ebb18cc6841ff79ad59cd70000c747c..a4b22e21028d90c52af9152915a4ccc56581469d 100644 (file)
@@ -2,6 +2,7 @@
 // as both unused and possibly-uninitialized.
 
 // check-pass
+// needs-asm-support
 
 #![feature(asm)]
 #![warn(unused)]
index 9cc127b44d008765b7a841efca42ab93d68f91f0..3fb1526183bccdbb3527ddc970947f44945398c9 100644 (file)
@@ -1,11 +1,11 @@
 warning: unused variable: `x`
-  --> $DIR/issue-89305.rs:11:13
+  --> $DIR/issue-89305.rs:12:13
    |
 LL |         let x: () = asm!("nop");
    |             ^ help: if this is intentional, prefix it with an underscore: `_x`
    |
 note: the lint level is defined here
-  --> $DIR/issue-89305.rs:7:9
+  --> $DIR/issue-89305.rs:8:9
    |
 LL | #![warn(unused)]
    |         ^^^^^^
index 803311d4235058a0a6419f2c44a5a4f94b1692da..7154ce26efcf5e3833dec4a5ec96e69fdaa597e8 100644 (file)
@@ -7,11 +7,15 @@
 #![feature(llvm_asm)]
 #![feature(naked_functions)]
 #![feature(or_patterns)]
+#![feature(asm_const, asm_sym)]
 #![crate_type = "lib"]
 #![allow(deprecated)] // llvm_asm!
 
 #[repr(C)]
-pub struct P { x: u8, y: u16 }
+pub struct P {
+    x: u8,
+    y: u16,
+}
 
 #[naked]
 pub unsafe extern "C" fn patterns(
@@ -143,21 +147,27 @@ pub unsafe fn default_abi() {
 }
 
 #[naked]
-pub unsafe extern "Rust" fn rust_abi() {
+pub unsafe fn rust_abi() {
     //~^ WARN Rust ABI is unsupported in naked functions
     asm!("", options(noreturn));
 }
 
 #[naked]
 pub extern "C" fn valid_a<T>() -> T {
-    unsafe { asm!("", options(noreturn)); }
+    unsafe {
+        asm!("", options(noreturn));
+    }
 }
 
 #[naked]
 pub extern "C" fn valid_b() {
-    unsafe { { {
-        asm!("", options(noreturn)); ; ; ;
-    } ; }  ; }
+    unsafe {
+        {
+            {
+                asm!("", options(noreturn));
+            };
+        };
+    }
 }
 
 #[naked]
index 465db634aa2f0b84bf07c4a888150231d9521be6..e4ddb97ca27467393caa956ad8af2ab87031ea7b 100644 (file)
@@ -1,35 +1,35 @@
 error: asm with the `pure` option must have at least one output
-  --> $DIR/naked-functions.rs:131:14
+  --> $DIR/naked-functions.rs:135:14
    |
 LL |     asm!("", options(readonly, nostack), options(pure));
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^
 
 error: patterns not allowed in naked function parameters
-  --> $DIR/naked-functions.rs:18:5
+  --> $DIR/naked-functions.rs:22:5
    |
 LL |     mut a: u32,
    |     ^^^^^
 
 error: patterns not allowed in naked function parameters
-  --> $DIR/naked-functions.rs:20:5
+  --> $DIR/naked-functions.rs:24:5
    |
 LL |     &b: &i32,
    |     ^^
 
 error: patterns not allowed in naked function parameters
-  --> $DIR/naked-functions.rs:22:6
+  --> $DIR/naked-functions.rs:26:6
    |
 LL |     (None | Some(_)): Option<std::ptr::NonNull<u8>>,
    |      ^^^^^^^^^^^^^^
 
 error: patterns not allowed in naked function parameters
-  --> $DIR/naked-functions.rs:24:5
+  --> $DIR/naked-functions.rs:28:5
    |
 LL |     P { x, y }: P,
    |     ^^^^^^^^^^
 
 error: referencing function parameters is not allowed in naked functions
-  --> $DIR/naked-functions.rs:34:5
+  --> $DIR/naked-functions.rs:38:5
    |
 LL |     a + 1
    |     ^
@@ -37,7 +37,7 @@ LL |     a + 1
    = help: follow the calling convention in asm block to use parameters
 
 warning: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:31:1
+  --> $DIR/naked-functions.rs:35:1
    |
 LL | / pub unsafe extern "C" fn inc(a: u32) -> u32 {
 LL | |
@@ -53,7 +53,7 @@ LL | | }
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 error: referencing function parameters is not allowed in naked functions
-  --> $DIR/naked-functions.rs:40:31
+  --> $DIR/naked-functions.rs:44:31
    |
 LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
    |                               ^
@@ -61,7 +61,7 @@ LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
    = help: follow the calling convention in asm block to use parameters
 
 warning: only `const` and `sym` operands are supported in naked functions
-  --> $DIR/naked-functions.rs:40:23
+  --> $DIR/naked-functions.rs:44:23
    |
 LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
    |                       ^^^^^^^^^
@@ -70,7 +70,7 @@ LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:47:1
+  --> $DIR/naked-functions.rs:51:1
    |
 LL | / pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
 LL | |
@@ -84,7 +84,7 @@ LL | | }
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: only `const` and `sym` operands are supported in naked functions
-  --> $DIR/naked-functions.rs:67:10
+  --> $DIR/naked-functions.rs:71:10
    |
 LL |          in(reg) a,
    |          ^^^^^^^^^
@@ -102,7 +102,7 @@ LL |          out(reg) e,
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:64:5
+  --> $DIR/naked-functions.rs:68:5
    |
 LL | /     asm!("/* {0} {1} {2} {3} {4} {5} {6} */",
 LL | |
@@ -117,7 +117,7 @@ LL | |     );
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:54:1
+  --> $DIR/naked-functions.rs:58:1
    |
 LL | / pub unsafe extern "C" fn unsupported_operands() {
 LL | |
@@ -141,7 +141,7 @@ LL | | }
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:80:1
+  --> $DIR/naked-functions.rs:84:1
    |
 LL | / pub extern "C" fn missing_assembly() {
 LL | |
@@ -153,7 +153,7 @@ LL | | }
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:89:5
+  --> $DIR/naked-functions.rs:93:5
    |
 LL |     asm!("");
    |     ^^^^^^^^
@@ -162,7 +162,7 @@ LL |     asm!("");
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:92:5
+  --> $DIR/naked-functions.rs:96:5
    |
 LL |     asm!("");
    |     ^^^^^^^^
@@ -171,7 +171,7 @@ LL |     asm!("");
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:95:5
+  --> $DIR/naked-functions.rs:99:5
    |
 LL |     asm!("");
    |     ^^^^^^^^
@@ -180,7 +180,7 @@ LL |     asm!("");
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:86:1
+  --> $DIR/naked-functions.rs:90:1
    |
 LL | / pub extern "C" fn too_many_asm_blocks() {
 LL | |
@@ -202,7 +202,7 @@ LL | | }
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 error: referencing function parameters is not allowed in naked functions
-  --> $DIR/naked-functions.rs:106:11
+  --> $DIR/naked-functions.rs:110:11
    |
 LL |         *&y
    |           ^
@@ -210,7 +210,7 @@ LL |         *&y
    = help: follow the calling convention in asm block to use parameters
 
 warning: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:103:5
+  --> $DIR/naked-functions.rs:107:5
    |
 LL | /     pub extern "C" fn inner(y: usize) -> usize {
 LL | |
@@ -225,7 +225,7 @@ LL | |     }
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: the LLVM-style inline assembly is unsupported in naked functions
-  --> $DIR/naked-functions.rs:116:5
+  --> $DIR/naked-functions.rs:120:5
    |
 LL |     llvm_asm!("");
    |     ^^^^^^^^^^^^^
@@ -236,7 +236,7 @@ LL |     llvm_asm!("");
    = note: this warning originates in the macro `llvm_asm` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 warning: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:113:1
+  --> $DIR/naked-functions.rs:117:1
    |
 LL | / unsafe extern "C" fn llvm() -> ! {
 LL | |
@@ -252,7 +252,7 @@ LL | | }
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: asm options unsupported in naked functions: `nomem`, `preserves_flags`
-  --> $DIR/naked-functions.rs:124:5
+  --> $DIR/naked-functions.rs:128:5
    |
 LL |     asm!("", options(nomem, preserves_flags, noreturn));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -261,7 +261,7 @@ LL |     asm!("", options(nomem, preserves_flags, noreturn));
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
-  --> $DIR/naked-functions.rs:131:5
+  --> $DIR/naked-functions.rs:135:5
    |
 LL |     asm!("", options(readonly, nostack), options(pure));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -270,7 +270,7 @@ LL |     asm!("", options(readonly, nostack), options(pure));
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:131:5
+  --> $DIR/naked-functions.rs:135:5
    |
 LL |     asm!("", options(readonly, nostack), options(pure));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -279,7 +279,7 @@ LL |     asm!("", options(readonly, nostack), options(pure));
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: Rust ABI is unsupported in naked functions
-  --> $DIR/naked-functions.rs:140:15
+  --> $DIR/naked-functions.rs:144:15
    |
 LL | pub unsafe fn default_abi() {
    |               ^^^^^^^^^^^
@@ -287,13 +287,13 @@ LL | pub unsafe fn default_abi() {
    = note: `#[warn(undefined_naked_function_abi)]` on by default
 
 warning: Rust ABI is unsupported in naked functions
-  --> $DIR/naked-functions.rs:146:29
+  --> $DIR/naked-functions.rs:150:15
    |
-LL | pub unsafe extern "Rust" fn rust_abi() {
-   |                             ^^^^^^^^
+LL | pub unsafe fn rust_abi() {
+   |               ^^^^^^^^
 
 warning: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:180:1
+  --> $DIR/naked-functions.rs:190:1
    |
 LL | #[inline]
    | ^^^^^^^^^
@@ -302,7 +302,7 @@ LL | #[inline]
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:188:1
+  --> $DIR/naked-functions.rs:198:1
    |
 LL | #[inline(always)]
    | ^^^^^^^^^^^^^^^^^
@@ -311,7 +311,7 @@ LL | #[inline(always)]
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:196:1
+  --> $DIR/naked-functions.rs:206:1
    |
 LL | #[inline(never)]
    | ^^^^^^^^^^^^^^^^
@@ -320,7 +320,7 @@ LL | #[inline(never)]
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:204:1
+  --> $DIR/naked-functions.rs:214:1
    |
 LL | #[inline]
    | ^^^^^^^^^
@@ -329,7 +329,7 @@ LL | #[inline]
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:207:1
+  --> $DIR/naked-functions.rs:217:1
    |
 LL | #[inline(always)]
    | ^^^^^^^^^^^^^^^^^
@@ -338,7 +338,7 @@ LL | #[inline(always)]
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:210:1
+  --> $DIR/naked-functions.rs:220:1
    |
 LL | #[inline(never)]
    | ^^^^^^^^^^^^^^^^
index 82c47945a7b302c4db11ee389e3c54877b98a46c..c87188e46a2bbedd92dcea45d37a764f86f14ba6 100644 (file)
@@ -11,7 +11,7 @@
 // which causes less readable LLVM errors and in the worst cases causes ICEs
 // or segfaults based on system dependent behavior and codegen flags.
 
-#![feature(asm, global_asm, naked_functions)]
+#![feature(asm, global_asm, naked_functions, asm_const)]
 
 #[no_mangle]
 pub static FOO: usize = 42;
index bbbe798d1557b0e095559ae2cff6fcfd19ebede2..1e463107b18bc4471f86e29aabe0ffbc360198f2 100644 (file)
@@ -3,7 +3,7 @@
 // ignore-spirv
 // ignore-wasm32
 
-#![feature(asm, global_asm)]
+#![feature(asm, global_asm, asm_const)]
 
 fn main() {
     unsafe {
index 91d0f8c33f9793c58a0d8b37e6e20f7c3a321036..ba4e95db46a2da80e97978aebe43ccf115f132a1 100644 (file)
@@ -1,7 +1,7 @@
 // only-x86_64
 // compile-flags: -C target-feature=+avx2
 
-#![feature(asm)]
+#![feature(asm, asm_const, asm_sym)]
 
 fn main() {
     let mut foo = 0;
index dbf17755720829516155af2e69b864d2952e92ec..c1e4cdbb928f4ce392e6328fcd1e6bda6bbb3d0c 100644 (file)
@@ -3,7 +3,7 @@
 // revisions: mirunsafeck thirunsafeck
 // [thirunsafeck]compile-flags: -Z thir-unsafeck
 
-#![feature(asm, global_asm)]
+#![feature(asm, global_asm, asm_const)]
 
 fn const_generic<const X: usize>() -> usize {
     unsafe {
diff --git a/src/test/ui/asm/x86_64/issue-89875.rs b/src/test/ui/asm/x86_64/issue-89875.rs
new file mode 100644 (file)
index 0000000..9b2b21b
--- /dev/null
@@ -0,0 +1,14 @@
+// build-pass
+// only-x86_64
+
+#![feature(asm, target_feature_11)]
+
+#[target_feature(enable = "avx")]
+fn main() {
+    unsafe {
+        asm!(
+            "/* {} */",
+            out(ymm_reg) _,
+        );
+    }
+}
index fa14c52cf0ad7f9fcd43549989d2bbf52d14b4e1..e7f3804c5886c24a0896b0e61fbd4381870387fa 100644 (file)
@@ -1,6 +1,6 @@
 // only-x86_64
 
-#![feature(asm, global_asm)]
+#![feature(asm, global_asm, asm_const)]
 
 fn main() {
     let mut foo = 0;
index 188d03e298e0182b734bb4dce9d5091aaef89589..958dbbdd37646acef7ce8906760ef74f7641b7f8 100644 (file)
@@ -3,7 +3,7 @@
 // only-linux
 // run-pass
 
-#![feature(asm, thread_local)]
+#![feature(asm, thread_local, asm_sym)]
 
 extern "C" fn f1() -> i32 {
     111
@@ -76,5 +76,7 @@ fn main() {
     std::thread::spawn(|| {
         assert_eq!(static_addr!(S1), &S1 as *const u32);
         assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
-    }).join().unwrap();
+    })
+    .join()
+    .unwrap();
 }
index 2311f86d340f48e4db0cc2917b407d44f8f5c216..94aadcf09f423466969d022b754e209d613215ab 100644 (file)
@@ -1,6 +1,6 @@
 // only-x86_64
 
-#![feature(asm, repr_simd, never_type)]
+#![feature(asm, repr_simd, never_type, asm_sym)]
 
 #[repr(simd)]
 struct SimdNonCopy(f32, f32, f32, f32);
index c2c1885ff166f45136a3eb891cbe2d7171387fea..83674cf8204d677f9544166fd938ddbdbc22a21e 100644 (file)
@@ -1,7 +1,7 @@
 // only-x86_64
 // compile-flags: -C target-feature=+avx512f
 
-#![feature(asm, global_asm)]
+#![feature(asm, global_asm, asm_const)]
 
 use std::arch::x86_64::{_mm256_setzero_ps, _mm_setzero_ps};
 
index 912dedfdcebbc3b220401347f2191c494eb02f5a..c993e1d27202d5a53ac33f843623d48b8bd24852 100644 (file)
@@ -28,11 +28,13 @@ pub fn f1_int_uint() {
 pub fn f1_uint_uint() {
     f1(2u32, 4u32);
     //~^ ERROR `u32: Foo` is not satisfied
+    //~| ERROR `u32: Foo` is not satisfied
 }
 
 pub fn f1_uint_int() {
     f1(2u32, 4i32);
     //~^ ERROR `u32: Foo` is not satisfied
+    //~| ERROR `u32: Foo` is not satisfied
 }
 
 pub fn f2_int() {
index 15a5245d54d9577c52a6350962400918138c6670..b3bb58f78142af7f159280f0f9e3bdb29e37dc92 100644 (file)
@@ -10,12 +10,10 @@ LL |     f1(2i32, 4u32);
    |               ~~~
 
 error[E0277]: the trait bound `u32: Foo` is not satisfied
-  --> $DIR/associated-types-path-2.rs:29:14
+  --> $DIR/associated-types-path-2.rs:29:5
    |
 LL |     f1(2u32, 4u32);
-   |     --       ^^^^ the trait `Foo` is not implemented for `u32`
-   |     |
-   |     required by a bound introduced by this call
+   |     ^^ the trait `Foo` is not implemented for `u32`
    |
 note: required by a bound in `f1`
   --> $DIR/associated-types-path-2.rs:13:14
@@ -24,10 +22,16 @@ LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
    |              ^^^ required by this bound in `f1`
 
 error[E0277]: the trait bound `u32: Foo` is not satisfied
-  --> $DIR/associated-types-path-2.rs:34:14
+  --> $DIR/associated-types-path-2.rs:29:14
+   |
+LL |     f1(2u32, 4u32);
+   |              ^^^^ the trait `Foo` is not implemented for `u32`
+
+error[E0277]: the trait bound `u32: Foo` is not satisfied
+  --> $DIR/associated-types-path-2.rs:35:8
    |
 LL |     f1(2u32, 4i32);
-   |     --       ^^^^ the trait `Foo` is not implemented for `u32`
+   |     -- ^^^^ the trait `Foo` is not implemented for `u32`
    |     |
    |     required by a bound introduced by this call
    |
@@ -37,8 +41,14 @@ note: required by a bound in `f1`
 LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
    |              ^^^ required by this bound in `f1`
 
+error[E0277]: the trait bound `u32: Foo` is not satisfied
+  --> $DIR/associated-types-path-2.rs:35:14
+   |
+LL |     f1(2u32, 4i32);
+   |              ^^^^ the trait `Foo` is not implemented for `u32`
+
 error[E0308]: mismatched types
-  --> $DIR/associated-types-path-2.rs:39:18
+  --> $DIR/associated-types-path-2.rs:41:18
    |
 LL |     let _: i32 = f2(2i32);
    |            ---   ^^^^^^^^ expected `i32`, found `u32`
@@ -50,7 +60,7 @@ help: you can convert a `u32` to an `i32` and panic if the converted value doesn
 LL |     let _: i32 = f2(2i32).try_into().unwrap();
    |                          ++++++++++++++++++++
 
-error: aborting due to 4 previous errors
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0277, E0308.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/issue-22066.rs b/src/test/ui/associated-types/issue-22066.rs
new file mode 100644 (file)
index 0000000..8e8ba5d
--- /dev/null
@@ -0,0 +1,12 @@
+// check-pass
+pub trait LineFormatter<'a> {
+    type Iter: Iterator<Item=&'a str> + 'a;
+    fn iter(&'a self, line: &'a str) -> Self::Iter;
+
+    fn dimensions(&'a self, line: &'a str) {
+        let iter: Self::Iter = self.iter(line);
+        <_ as IntoIterator>::into_iter(iter);
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-22828.rs b/src/test/ui/associated-types/issue-22828.rs
new file mode 100644 (file)
index 0000000..adf4dd6
--- /dev/null
@@ -0,0 +1,23 @@
+// run-pass
+#![allow(dead_code)]
+// Test transitive analysis for associated types. Collected types
+// should be normalized and new obligations generated.
+
+// pretty-expanded FIXME #23616
+
+trait Foo {
+    type A;
+    fn foo(&self) {}
+}
+
+impl Foo for usize {
+    type A = usize;
+}
+
+struct Bar<T: Foo> { inner: T::A }
+
+fn is_send<T: Send>() {}
+
+fn main() {
+    is_send::<Bar<usize>>();
+}
diff --git a/src/test/ui/associated-types/issue-28871.rs b/src/test/ui/associated-types/issue-28871.rs
new file mode 100644 (file)
index 0000000..210c783
--- /dev/null
@@ -0,0 +1,24 @@
+// check-pass
+// Regression test for #28871. The problem is that rustc encountered
+// two ways to project, one from a where clause and one from the where
+// clauses on the trait definition. (In fact, in this case, the where
+// clauses originated from the trait definition as well.) The true
+// cause of the error is that the trait definition where clauses are
+// not being normalized, and hence the two sources are considered in
+// conflict, and not a duplicate. Hacky solution is to prefer where
+// clauses over the data found in the trait definition.
+
+trait T {
+    type T;
+}
+
+struct S;
+impl T for S {
+    type T = S;
+}
+
+trait T2 {
+    type T: Iterator<Item=<S as T>::T>;
+}
+
+fn main() { }
diff --git a/src/test/ui/associated-types/issue-47139-1.rs b/src/test/ui/associated-types/issue-47139-1.rs
new file mode 100644 (file)
index 0000000..c55fc34
--- /dev/null
@@ -0,0 +1,78 @@
+// run-pass
+// Regression test for issue #47139:
+//
+// Coherence was encountering an (unnecessary) overflow trying to
+// decide if the two impls of dummy overlap.
+//
+// The overflow went something like:
+//
+// - `&'a ?T: Insertable` ?
+// - let ?T = Option<?U> ?
+// - `Option<?U>: Insertable` ?
+// - `Option<&'a ?U>: Insertable` ?
+// - `&'a ?U: Insertable` ?
+//
+// While somewhere in the middle, a projection would occur, which
+// broke cycle detection.
+//
+// It turned out that this cycle was being kicked off due to some
+// extended diagnostic attempts in coherence, so removing those
+// sidestepped the issue for now.
+
+#![allow(dead_code)]
+
+pub trait Insertable {
+    type Values;
+
+    fn values(self) -> Self::Values;
+}
+
+impl<T> Insertable for Option<T>
+    where
+    T: Insertable,
+    T::Values: Default,
+{
+    type Values = T::Values;
+
+    fn values(self) -> Self::Values {
+        self.map(Insertable::values).unwrap_or_default()
+    }
+}
+
+impl<'a, T> Insertable for &'a Option<T>
+    where
+    Option<&'a T>: Insertable,
+{
+    type Values = <Option<&'a T> as Insertable>::Values;
+
+    fn values(self) -> Self::Values {
+        self.as_ref().values()
+    }
+}
+
+impl<'a, T> Insertable for &'a [T]
+{
+    type Values = Self;
+
+    fn values(self) -> Self::Values {
+        self
+    }
+}
+
+trait Unimplemented { }
+
+trait Dummy { }
+
+struct Foo<T> { t: T }
+
+impl<'a, U> Dummy for Foo<&'a U>
+    where &'a U: Insertable
+{
+}
+
+impl<T> Dummy for T
+    where T: Unimplemented
+{ }
+
+fn main() {
+}
diff --git a/src/test/ui/associated-types/issue-54467.rs b/src/test/ui/associated-types/issue-54467.rs
new file mode 100644 (file)
index 0000000..734bf27
--- /dev/null
@@ -0,0 +1,46 @@
+// run-pass
+
+pub trait Stream {
+    type Item;
+    type Error;
+}
+
+pub trait ParseError<I> {
+    type Output;
+}
+
+impl ParseError<char> for u32 {
+    type Output = ();
+}
+
+impl Stream for () {
+    type Item = char;
+    type Error = u32;
+}
+
+pub struct Lex<'a, I>
+    where I: Stream,
+          I::Error: ParseError<char>,
+          <<I as Stream>::Error as ParseError<char>>::Output: 'a
+{
+    x: &'a <I::Error as ParseError<char>>::Output
+}
+
+pub struct Reserved<'a, I> where
+    I: Stream<Item=char> + 'a,
+    I::Error: ParseError<I::Item>,
+    <<I as Stream>::Error as ParseError<char>>::Output: 'a
+
+{
+    x: Lex<'a, I>
+}
+
+fn main() {
+    let r: Reserved<()> = Reserved {
+        x: Lex {
+            x: &()
+        }
+    };
+
+    let _v = r.x.x;
+}
index d509ff3598b50f4a2e9f0f7b7b75bf50206bec43..baaab7fee679dcdfed20ed7419e2adb25dd4e27c 100644 (file)
@@ -1,8 +1,8 @@
 error: future cannot be sent between threads safely
-  --> $DIR/async-fn-nonsend.rs:49:5
+  --> $DIR/async-fn-nonsend.rs:49:17
    |
 LL |     assert_send(local_dropped_before_await());
-   |     ^^^^^^^^^^^ future returned by `local_dropped_before_await` is not `Send`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `local_dropped_before_await` is not `Send`
    |
    = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>`
 note: future is not `Send` as this value is used across an await
@@ -22,10 +22,10 @@ LL | fn assert_send(_: impl Send) {}
    |                        ^^^^ required by this bound in `assert_send`
 
 error: future cannot be sent between threads safely
-  --> $DIR/async-fn-nonsend.rs:51:5
+  --> $DIR/async-fn-nonsend.rs:51:17
    |
 LL |     assert_send(non_send_temporary_in_match());
-   |     ^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send`
    |
    = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>`
 note: future is not `Send` as this value is used across an await
@@ -45,10 +45,10 @@ LL | fn assert_send(_: impl Send) {}
    |                        ^^^^ required by this bound in `assert_send`
 
 error: future cannot be sent between threads safely
-  --> $DIR/async-fn-nonsend.rs:53:5
+  --> $DIR/async-fn-nonsend.rs:53:17
    |
 LL |     assert_send(non_sync_with_method_call());
-   |     ^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send`
    |
    = help: the trait `Send` is not implemented for `dyn std::fmt::Write`
 note: future is not `Send` as this value is used across an await
index 69c7ff47456c0846dc73fca9eb1da5f02d3208db..12e4bfc3d48b66b05fb91b238270a5e4dd429b81 100644 (file)
@@ -1,8 +1,8 @@
 error: future cannot be shared between threads safely
-  --> $DIR/issue-64130-1-sync.rs:21:5
+  --> $DIR/issue-64130-1-sync.rs:21:13
    |
 LL |     is_sync(bar());
-   |     ^^^^^^^ future returned by `bar` is not `Sync`
+   |             ^^^^^ future returned by `bar` is not `Sync`
    |
    = help: within `impl Future`, the trait `Sync` is not implemented for `Foo`
 note: future is not `Sync` as this value is used across an await
index 933e9296848e942b34ebac6659d3ea21a15bc6f7..9c94b8da8929ab48b764fbd8ec11aa6a31158e94 100644 (file)
@@ -1,8 +1,8 @@
 error: future cannot be sent between threads safely
-  --> $DIR/issue-64130-2-send.rs:21:5
+  --> $DIR/issue-64130-2-send.rs:21:13
    |
 LL |     is_send(bar());
-   |     ^^^^^^^ future returned by `bar` is not `Send`
+   |             ^^^^^ future returned by `bar` is not `Send`
    |
    = help: within `impl Future`, the trait `Send` is not implemented for `Foo`
 note: future is not `Send` as this value is used across an await
index ec0fdd4a5551dd70ad9a37a015c1e22a67a5a029..3dd1239e23dbeefff5a5b81af8346c02ed6b690e 100644 (file)
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `Foo: Qux` is not satisfied in `impl Future`
-  --> $DIR/issue-64130-3-other.rs:24:5
+  --> $DIR/issue-64130-3-other.rs:24:12
    |
 LL | async fn bar() {
    |                - within this `impl Future`
 ...
 LL |     is_qux(bar());
-   |     ^^^^^^ within `impl Future`, the trait `Qux` is not implemented for `Foo`
+   |            ^^^^^ within `impl Future`, the trait `Qux` is not implemented for `Foo`
    |
 note: future does not implement `Qux` as this value is used across an await
   --> $DIR/issue-64130-3-other.rs:18:5
index 656ade67c71a7a3eb9d165cce773fcd154a98811..b652d239153302fc7fddd99b23cdc4d2be9b559b 100644 (file)
@@ -1,4 +1,6 @@
 // edition:2018
+#![feature(must_not_suspend)]
+#![allow(must_not_suspend)]
 
 // This tests the basic example case for the async-await-specific error.
 
index 472fffa61b791e5f07ef0cd97939383ac41a5188..a373ba6aa71361ea74b4bb90880874cd70cdfe4e 100644 (file)
@@ -1,12 +1,12 @@
 error: future cannot be sent between threads safely
-  --> $DIR/issue-64130-non-send-future-diags.rs:21:5
+  --> $DIR/issue-64130-non-send-future-diags.rs:23:13
    |
 LL |     is_send(foo());
-   |     ^^^^^^^ future returned by `foo` is not `Send`
+   |             ^^^^^ future returned by `foo` is not `Send`
    |
    = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, u32>`
 note: future is not `Send` as this value is used across an await
-  --> $DIR/issue-64130-non-send-future-diags.rs:15:5
+  --> $DIR/issue-64130-non-send-future-diags.rs:17:5
    |
 LL |     let g = x.lock().unwrap();
    |         - has type `MutexGuard<'_, u32>` which is not `Send`
@@ -15,7 +15,7 @@ LL |     baz().await;
 LL | }
    | - `g` is later dropped here
 note: required by a bound in `is_send`
-  --> $DIR/issue-64130-non-send-future-diags.rs:7:15
+  --> $DIR/issue-64130-non-send-future-diags.rs:9:15
    |
 LL | fn is_send<T: Send>(t: T) { }
    |               ^^^^ required by this bound in `is_send`
index ebb392a45308e85bb34c7c84ab5adc4ba8345e87..7695e0325ff31feb45ee5dc1dc990d44d08ec2af 100644 (file)
@@ -1,4 +1,6 @@
 // edition:2018
+#![feature(must_not_suspend)]
+#![allow(must_not_suspend)]
 
 use std::future::Future;
 use std::sync::Mutex;
index 8903c09c17f0dbb186105e309e33bf87f5f39856..3cc800f96c20d0ed983779fc88362c13f5bf7aa2 100644 (file)
@@ -1,12 +1,12 @@
 error: future cannot be sent between threads safely
-  --> $DIR/issue-71137.rs:20:3
+  --> $DIR/issue-71137.rs:22:14
    |
 LL |   fake_spawn(wrong_mutex());
-   |   ^^^^^^^^^^ future returned by `wrong_mutex` is not `Send`
+   |              ^^^^^^^^^^^^^ future returned by `wrong_mutex` is not `Send`
    |
    = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, i32>`
 note: future is not `Send` as this value is used across an await
-  --> $DIR/issue-71137.rs:12:5
+  --> $DIR/issue-71137.rs:14:5
    |
 LL |     let mut guard = m.lock().unwrap();
    |         --------- has type `MutexGuard<'_, i32>` which is not `Send`
@@ -16,7 +16,7 @@ LL |     *guard += 1;
 LL |   }
    |   - `mut guard` is later dropped here
 note: required by a bound in `fake_spawn`
-  --> $DIR/issue-71137.rs:6:27
+  --> $DIR/issue-71137.rs:8:27
    |
 LL | fn fake_spawn<F: Future + Send + 'static>(f: F) { }
    |                           ^^^^ required by this bound in `fake_spawn`
diff --git a/src/test/ui/async-await/issue-73541-1.rs b/src/test/ui/async-await/issue-73541-1.rs
new file mode 100644 (file)
index 0000000..7fb0d6c
--- /dev/null
@@ -0,0 +1,12 @@
+// edition:2018
+
+fn main() {
+    'a: loop {
+        async {
+            loop {
+                continue 'a
+                //~^ ERROR use of unreachable label `'a`
+            }
+        };
+    }
+}
diff --git a/src/test/ui/async-await/issue-73541-1.stderr b/src/test/ui/async-await/issue-73541-1.stderr
new file mode 100644 (file)
index 0000000..80c1fdf
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0767]: use of unreachable label `'a`
+  --> $DIR/issue-73541-1.rs:7:26
+   |
+LL |     'a: loop {
+   |     -- unreachable label defined here
+...
+LL |                 continue 'a
+   |                          ^^ unreachable label `'a`
+   |
+   = note: labels are unreachable through functions, closures, async blocks and modules
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0767`.
index f34ce8081ca02e3f967910067a9d0a840f3c360f..8b53408d758e110ef55992fc4f94c42390e4f5cd 100644 (file)
@@ -7,5 +7,5 @@ fn g(_: impl Send) {}
 
 fn main() {
     g(issue_67893::run())
-    //~^ ERROR: `MutexGuard<'_, ()>` cannot be sent between threads safely
+    //~^ ERROR generator cannot be sent between threads safely
 }
index c4b55e6ec20222e9d83bcc1fb216f71641cac5b1..ee32a1a9e4fbb4a17b22ada678d38262a0058e53 100644 (file)
@@ -1,20 +1,10 @@
-error[E0277]: `MutexGuard<'_, ()>` cannot be sent between threads safely
-  --> $DIR/issue-67893.rs:9:5
+error: generator cannot be sent between threads safely
+  --> $DIR/issue-67893.rs:9:7
    |
 LL |     g(issue_67893::run())
-   |     ^ `MutexGuard<'_, ()>` cannot be sent between threads safely
-   |
-  ::: $DIR/auxiliary/issue_67893.rs:7:20
-   |
-LL | pub async fn run() {
-   |                    - within this `impl Future`
+   |       ^^^^^^^^^^^^^^^^^^ generator is not `Send`
    |
    = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, ()>`
-   = note: required because it appears within the type `for<'r, 's, 't0, 't1, 't2, 't3> {ResumeTy, Arc<Mutex<()>>, &'r Mutex<()>, Result<MutexGuard<'s, ()>, PoisonError<MutexGuard<'t0, ()>>>, &'t1 MutexGuard<'t2, ()>, MutexGuard<'t3, ()>, (), impl Future}`
-   = note: required because it appears within the type `[static generator@run::{closure#0}]`
-   = note: required because it appears within the type `from_generator::GenFuture<[static generator@run::{closure#0}]>`
-   = note: required because it appears within the type `impl Future`
-   = note: required because it appears within the type `impl Future`
 note: required by a bound in `g`
   --> $DIR/issue-67893.rs:6:14
    |
@@ -23,4 +13,3 @@ LL | fn g(_: impl Send) {}
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0277`.
index 8c581ff2229fc00889d0b9684cd75de5b2750938..b63ea106d90262ae8a0a09e7d970d40bf9db994f 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: `PhantomPinned` cannot be unpinned
-  --> $DIR/pin-needed-to-poll-2.rs:43:9
+  --> $DIR/pin-needed-to-poll-2.rs:43:18
    |
 LL |         Pin::new(&mut self.sleep).poll(cx)
-   |         ^^^^^^^^ within `Sleep`, the trait `Unpin` is not implemented for `PhantomPinned`
+   |         -------- ^^^^^^^^^^^^^^^ within `Sleep`, the trait `Unpin` is not implemented for `PhantomPinned`
+   |         |
+   |         required by a bound introduced by this call
    |
    = note: consider using `Box::pin`
 note: required because it appears within the type `Sleep`
index 595ece2ea724707527b41ec419903c8182c90b5e..55006b2087eb024f3037bbc638dfbd8f23d8131c 100644 (file)
@@ -29,7 +29,7 @@ LL | pub fn foo() {}
    |
    = 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 #82730 <https://github.com/rust-lang/rust/issues/82730>
-   = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information
+   = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline for more information
 
 error: this attribute can only be applied at the crate level
   --> $DIR/invalid-doc-attr.rs:15:12
@@ -72,7 +72,7 @@ LL |     pub fn baz() {}
    |
    = 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 #82730 <https://github.com/rust-lang/rust/issues/82730>
-   = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information
+   = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline for more information
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/attributes/issue-40962.rs b/src/test/ui/attributes/issue-40962.rs
new file mode 100644 (file)
index 0000000..7b91c06
--- /dev/null
@@ -0,0 +1,11 @@
+// check-pass
+macro_rules! m {
+    ($i:meta) => {
+        #[derive($i)]
+        struct S;
+    }
+}
+
+m!(Clone);
+
+fn main() {}
index ef59381f5f26dba34697ef81249380f21f2632e7..e59216fe902704879d0eed6b815942532b9ed004 100644 (file)
@@ -19,8 +19,8 @@ error: unexpected token: `{
     let res =
         ::alloc::fmt::format(::core::fmt::Arguments::new_v1(&[""],
                                                             &match (&"u8",) {
-                                                                 (arg0,) =>
-                                                                 [::core::fmt::ArgumentV1::new(arg0,
+                                                                 _args =>
+                                                                 [::core::fmt::ArgumentV1::new(_args.0,
                                                                                                ::core::fmt::Display::fmt)],
                                                              }));
     res
diff --git a/src/test/ui/attributes/unrestricted-attribute-tokens.rs b/src/test/ui/attributes/unrestricted-attribute-tokens.rs
new file mode 100644 (file)
index 0000000..e31bc91
--- /dev/null
@@ -0,0 +1,8 @@
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![feature(rustc_attrs)]
+
+#[rustc_dummy(a b c d)]
+#[rustc_dummy[a b c d]]
+#[rustc_dummy{a b c d}]
+fn main() {}
diff --git a/src/test/ui/auxiliary/changing-crates-a1.rs b/src/test/ui/auxiliary/changing-crates-a1.rs
deleted file mode 100644 (file)
index bc0559b..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#![crate_name = "a"]
-
-pub fn foo<T>() {}
diff --git a/src/test/ui/auxiliary/changing-crates-a2.rs b/src/test/ui/auxiliary/changing-crates-a2.rs
deleted file mode 100644 (file)
index fafc6d5..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#![crate_name = "a"]
-
-pub fn foo<T>() { println!("hello!"); }
diff --git a/src/test/ui/auxiliary/changing-crates-b.rs b/src/test/ui/auxiliary/changing-crates-b.rs
deleted file mode 100644 (file)
index f9ce29e..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#![crate_name = "b"]
-
-extern crate a;
-
-pub fn foo() { a::foo::<isize>(); }
diff --git a/src/test/ui/auxiliary/legacy-const-generics.rs b/src/test/ui/auxiliary/legacy-const-generics.rs
deleted file mode 100644 (file)
index 67352a2..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#![feature(rustc_attrs)]
-
-#[rustc_legacy_const_generics(1)]
-pub fn foo<const Y: usize>(x: usize, z: usize) -> [usize; 3] {
-    [x, Y, z]
-}
diff --git a/src/test/ui/auxiliary/lto-duplicate-symbols1.rs b/src/test/ui/auxiliary/lto-duplicate-symbols1.rs
deleted file mode 100644 (file)
index ec6d056..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// no-prefer-dynamic
-
-#![crate_type = "rlib"]
-
-#[no_mangle]
-pub extern "C" fn foo() {}
diff --git a/src/test/ui/auxiliary/lto-duplicate-symbols2.rs b/src/test/ui/auxiliary/lto-duplicate-symbols2.rs
deleted file mode 100644 (file)
index ec6d056..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// no-prefer-dynamic
-
-#![crate_type = "rlib"]
-
-#[no_mangle]
-pub extern "C" fn foo() {}
diff --git a/src/test/ui/auxiliary/lto-rustc-loads-linker-plugin.rs b/src/test/ui/auxiliary/lto-rustc-loads-linker-plugin.rs
deleted file mode 100644 (file)
index d24375b..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// compile-flags: -Clinker-plugin-lto
-// no-prefer-dynamic
-
-#![crate_type = "rlib"]
-
-pub fn foo() {}
diff --git a/src/test/ui/auxiliary/nested_item.rs b/src/test/ui/auxiliary/nested_item.rs
deleted file mode 100644 (file)
index 9db9d19..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// original problem
-pub fn foo<T>() -> isize {
-    {
-        static foo: isize = 2;
-        foo
-    }
-}
-
-// issue 8134
-struct Foo;
-impl Foo {
-    pub fn foo<T>(&self) {
-        static X: usize = 1;
-    }
-}
-
-// issue 8134
-pub struct Parser<T>(T);
-impl<T: std::iter::Iterator<Item=char>> Parser<T> {
-    fn in_doctype(&mut self) {
-        static DOCTYPEPattern: [char; 6] = ['O', 'C', 'T', 'Y', 'P', 'E'];
-    }
-}
-
-struct Bar;
-impl Foo {
-    pub fn bar<T>(&self) {
-        static X: usize = 1;
-    }
-}
diff --git a/src/test/ui/bastion-of-the-turbofish.rs b/src/test/ui/bastion-of-the-turbofish.rs
deleted file mode 100644 (file)
index e128570..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-// check-pass
-
-// Bastion of the Turbofish
-// ------------------------
-// Beware travellers, lest you venture into waters callous and unforgiving,
-// where hope must be abandoned, ere it is cruelly torn from you. For here
-// stands the bastion of the Turbofish: an impenetrable fortress holding
-// unshaking against those who would dare suggest the supererogation of the
-// Turbofish.
-//
-// Once I was young and foolish and had the impudence to imagine that I could
-// shake free from the coils by which that creature had us tightly bound. I
-// dared to suggest that there was a better way: a brighter future, in which
-// Rustaceans both new and old could be rid of that vile beast. But alas! In
-// my foolhardiness my ignorance was unveiled and my dreams were dashed
-// unforgivingly against the rock of syntactic ambiguity.
-//
-// This humble program, small and insignificant though it might seem,
-// demonstrates that to which we had previously cast a blind eye: an ambiguity
-// in permitting generic arguments to be provided without the consent of the
-// Great Turbofish. Should you be so naïve as to try to revolt against its
-// mighty clutches, here shall its wrath be indomitably displayed. This
-// program must pass for all eternity: forever watched by the guardian angel
-// which gave this beast its name, and stands fundamentally at odds with the
-// impetuous rebellion against the Turbofish.
-//
-// My heart aches in sorrow, for I know I am defeated. Let this be a warning
-// to all those who come after: for they too must overcome the impassible
-// hurdle of defeating the great beast, championed by a resolute winged
-// guardian.
-//
-// Here stands the Bastion of the Turbofish, a memorial to Anna Harren,
-// Guardian Angel of these Hallowed Grounds. <3
-
-// See https://github.com/rust-lang/rust/pull/53562
-// and https://github.com/rust-lang/rfcs/pull/2527
-// and https://twitter.com/garblefart/status/1393236602856611843
-// for context.
-
-fn main() {
-    let (the, guardian, stands, resolute) = ("the", "Turbofish", "remains", "undefeated");
-    let _: (bool, bool) = (the<guardian, stands>(resolute));
-}
index 615193c0d02db929e18188c2603fdca40a6d501a..f36201396423adb1b7bc3fd3c995c4bd2ee3d353 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `f` is ambiguous (glob import vs glob import in the same module)
+error[E0659]: `f` is ambiguous
   --> $DIR/ambiguity-item.rs:14:13
    |
 LL |     let v = f;
    |             ^ ambiguous name
    |
+   = note: ambiguous because of multiple glob imports of a name in the same module
 note: `f` could refer to the function imported here
   --> $DIR/ambiguity-item.rs:6:5
    |
@@ -17,12 +18,13 @@ LL | use n::*; // OK, no conflict with `use m::*;`
    |     ^^^^
    = help: consider adding an explicit import of `f` to disambiguate
 
-error[E0659]: `f` is ambiguous (glob import vs glob import in the same module)
+error[E0659]: `f` is ambiguous
   --> $DIR/ambiguity-item.rs:16:9
    |
 LL |         f => {}
    |         ^ ambiguous name
    |
+   = note: ambiguous because of multiple glob imports of a name in the same module
 note: `f` could refer to the function imported here
   --> $DIR/ambiguity-item.rs:6:5
    |
diff --git a/src/test/ui/binop/structured-compare.rs b/src/test/ui/binop/structured-compare.rs
new file mode 100644 (file)
index 0000000..63d30c4
--- /dev/null
@@ -0,0 +1,30 @@
+// run-pass
+
+#![allow(non_camel_case_types)]
+
+
+#[derive(Copy, Clone, Debug)]
+enum foo { large, small, }
+
+impl PartialEq for foo {
+    fn eq(&self, other: &foo) -> bool {
+        ((*self) as usize) == ((*other) as usize)
+    }
+    fn ne(&self, other: &foo) -> bool { !(*self).eq(other) }
+}
+
+pub fn main() {
+    let a = (1, 2, 3);
+    let b = (1, 2, 3);
+    assert_eq!(a, b);
+    assert!((a != (1, 2, 4)));
+    assert!((a < (1, 2, 4)));
+    assert!((a <= (1, 2, 4)));
+    assert!(((1, 2, 4) > a));
+    assert!(((1, 2, 4) >= a));
+    let x = foo::large;
+    let y = foo::small;
+    assert!((x != y));
+    assert_eq!(x, foo::large);
+    assert!((x != foo::small));
+}
diff --git a/src/test/ui/borrowck/issue-46095.rs b/src/test/ui/borrowck/issue-46095.rs
new file mode 100644 (file)
index 0000000..59ddb60
--- /dev/null
@@ -0,0 +1,30 @@
+// run-pass
+struct A;
+
+impl A {
+    fn take_mutably(&mut self) {}
+}
+
+fn identity<T>(t: T) -> T {
+    t
+}
+
+// Issue 46095
+// Built-in indexing should be used even when the index is not
+// trivially an integer
+// Overloaded indexing would cause wrapped to be borrowed mutably
+
+fn main() {
+    let mut a1 = A;
+    let mut a2 = A;
+
+    let wrapped = [&mut a1, &mut a2];
+
+    {
+        wrapped[0 + 1 - 1].take_mutably();
+    }
+
+    {
+        wrapped[identity(0)].take_mutably();
+    }
+}
diff --git a/src/test/ui/box/new-box.rs b/src/test/ui/box/new-box.rs
new file mode 100644 (file)
index 0000000..96a3b19
--- /dev/null
@@ -0,0 +1,30 @@
+// run-pass
+
+fn f(x: Box<isize>) {
+    let y: &isize = &*x;
+    println!("{}", *x);
+    println!("{}", *y);
+}
+
+trait Trait {
+    fn printme(&self);
+}
+
+struct Struct;
+
+impl Trait for Struct {
+    fn printme(&self) {
+        println!("hello world!");
+    }
+}
+
+fn g(x: Box<dyn Trait>) {
+    x.printme();
+    let y: &dyn Trait = &*x;
+    y.printme();
+}
+
+fn main() {
+    f(Box::new(1234));
+    g(Box::new(Struct) as Box<dyn Trait>);
+}
diff --git a/src/test/ui/c-variadic/issue-32201.rs b/src/test/ui/c-variadic/issue-32201.rs
new file mode 100644 (file)
index 0000000..f27bb1c
--- /dev/null
@@ -0,0 +1,13 @@
+extern "C" {
+    fn foo(a: i32, ...);
+}
+
+fn bar(_: *const u8) {}
+
+fn main() {
+    unsafe {
+        foo(0, bar);
+        //~^ ERROR can't pass `fn(*const u8) {bar}` to variadic function
+        //~| HELP cast the value to `fn(*const u8)`
+    }
+}
diff --git a/src/test/ui/c-variadic/issue-32201.stderr b/src/test/ui/c-variadic/issue-32201.stderr
new file mode 100644 (file)
index 0000000..cedb587
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0617]: can't pass `fn(*const u8) {bar}` to variadic function
+  --> $DIR/issue-32201.rs:9:16
+   |
+LL |         foo(0, bar);
+   |                ^^^ help: cast the value to `fn(*const u8)`: `bar as fn(*const u8)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0617`.
diff --git a/src/test/ui/cast/supported-cast.rs b/src/test/ui/cast/supported-cast.rs
new file mode 100644 (file)
index 0000000..ff41ce6
--- /dev/null
@@ -0,0 +1,206 @@
+// run-pass
+
+pub fn main() {
+  let f = 1_usize as *const String;
+  println!("{:?}", f as isize);
+  println!("{:?}", f as usize);
+  println!("{:?}", f as i8);
+  println!("{:?}", f as i16);
+  println!("{:?}", f as i32);
+  println!("{:?}", f as i64);
+  println!("{:?}", f as u8);
+  println!("{:?}", f as u16);
+  println!("{:?}", f as u32);
+  println!("{:?}", f as u64);
+
+  println!("{:?}", 1 as isize);
+  println!("{:?}", 1 as usize);
+  println!("{:?}", 1 as *const String);
+  println!("{:?}", 1 as i8);
+  println!("{:?}", 1 as i16);
+  println!("{:?}", 1 as i32);
+  println!("{:?}", 1 as i64);
+  println!("{:?}", 1 as u8);
+  println!("{:?}", 1 as u16);
+  println!("{:?}", 1 as u32);
+  println!("{:?}", 1 as u64);
+  println!("{:?}", 1 as f32);
+  println!("{:?}", 1 as f64);
+
+  println!("{:?}", 1_usize as isize);
+  println!("{:?}", 1_usize as usize);
+  println!("{:?}", 1_usize as *const String);
+  println!("{:?}", 1_usize as i8);
+  println!("{:?}", 1_usize as i16);
+  println!("{:?}", 1_usize as i32);
+  println!("{:?}", 1_usize as i64);
+  println!("{:?}", 1_usize as u8);
+  println!("{:?}", 1_usize as u16);
+  println!("{:?}", 1_usize as u32);
+  println!("{:?}", 1_usize as u64);
+  println!("{:?}", 1_usize as f32);
+  println!("{:?}", 1_usize as f64);
+
+  println!("{:?}", 1i8 as isize);
+  println!("{:?}", 1i8 as usize);
+  println!("{:?}", 1i8 as *const String);
+  println!("{:?}", 1i8 as i8);
+  println!("{:?}", 1i8 as i16);
+  println!("{:?}", 1i8 as i32);
+  println!("{:?}", 1i8 as i64);
+  println!("{:?}", 1i8 as u8);
+  println!("{:?}", 1i8 as u16);
+  println!("{:?}", 1i8 as u32);
+  println!("{:?}", 1i8 as u64);
+  println!("{:?}", 1i8 as f32);
+  println!("{:?}", 1i8 as f64);
+
+  println!("{:?}", 1u8 as isize);
+  println!("{:?}", 1u8 as usize);
+  println!("{:?}", 1u8 as *const String);
+  println!("{:?}", 1u8 as i8);
+  println!("{:?}", 1u8 as i16);
+  println!("{:?}", 1u8 as i32);
+  println!("{:?}", 1u8 as i64);
+  println!("{:?}", 1u8 as u8);
+  println!("{:?}", 1u8 as u16);
+  println!("{:?}", 1u8 as u32);
+  println!("{:?}", 1u8 as u64);
+  println!("{:?}", 1u8 as f32);
+  println!("{:?}", 1u8 as f64);
+
+  println!("{:?}", 1i16 as isize);
+  println!("{:?}", 1i16 as usize);
+  println!("{:?}", 1i16 as *const String);
+  println!("{:?}", 1i16 as i8);
+  println!("{:?}", 1i16 as i16);
+  println!("{:?}", 1i16 as i32);
+  println!("{:?}", 1i16 as i64);
+  println!("{:?}", 1i16 as u8);
+  println!("{:?}", 1i16 as u16);
+  println!("{:?}", 1i16 as u32);
+  println!("{:?}", 1i16 as u64);
+  println!("{:?}", 1i16 as f32);
+  println!("{:?}", 1i16 as f64);
+
+  println!("{:?}", 1u16 as isize);
+  println!("{:?}", 1u16 as usize);
+  println!("{:?}", 1u16 as *const String);
+  println!("{:?}", 1u16 as i8);
+  println!("{:?}", 1u16 as i16);
+  println!("{:?}", 1u16 as i32);
+  println!("{:?}", 1u16 as i64);
+  println!("{:?}", 1u16 as u8);
+  println!("{:?}", 1u16 as u16);
+  println!("{:?}", 1u16 as u32);
+  println!("{:?}", 1u16 as u64);
+  println!("{:?}", 1u16 as f32);
+  println!("{:?}", 1u16 as f64);
+
+  println!("{:?}", 1i32 as isize);
+  println!("{:?}", 1i32 as usize);
+  println!("{:?}", 1i32 as *const String);
+  println!("{:?}", 1i32 as i8);
+  println!("{:?}", 1i32 as i16);
+  println!("{:?}", 1i32 as i32);
+  println!("{:?}", 1i32 as i64);
+  println!("{:?}", 1i32 as u8);
+  println!("{:?}", 1i32 as u16);
+  println!("{:?}", 1i32 as u32);
+  println!("{:?}", 1i32 as u64);
+  println!("{:?}", 1i32 as f32);
+  println!("{:?}", 1i32 as f64);
+
+  println!("{:?}", 1u32 as isize);
+  println!("{:?}", 1u32 as usize);
+  println!("{:?}", 1u32 as *const String);
+  println!("{:?}", 1u32 as i8);
+  println!("{:?}", 1u32 as i16);
+  println!("{:?}", 1u32 as i32);
+  println!("{:?}", 1u32 as i64);
+  println!("{:?}", 1u32 as u8);
+  println!("{:?}", 1u32 as u16);
+  println!("{:?}", 1u32 as u32);
+  println!("{:?}", 1u32 as u64);
+  println!("{:?}", 1u32 as f32);
+  println!("{:?}", 1u32 as f64);
+
+  println!("{:?}", 1i64 as isize);
+  println!("{:?}", 1i64 as usize);
+  println!("{:?}", 1i64 as *const String);
+  println!("{:?}", 1i64 as i8);
+  println!("{:?}", 1i64 as i16);
+  println!("{:?}", 1i64 as i32);
+  println!("{:?}", 1i64 as i64);
+  println!("{:?}", 1i64 as u8);
+  println!("{:?}", 1i64 as u16);
+  println!("{:?}", 1i64 as u32);
+  println!("{:?}", 1i64 as u64);
+  println!("{:?}", 1i64 as f32);
+  println!("{:?}", 1i64 as f64);
+
+  println!("{:?}", 1u64 as isize);
+  println!("{:?}", 1u64 as usize);
+  println!("{:?}", 1u64 as *const String);
+  println!("{:?}", 1u64 as i8);
+  println!("{:?}", 1u64 as i16);
+  println!("{:?}", 1u64 as i32);
+  println!("{:?}", 1u64 as i64);
+  println!("{:?}", 1u64 as u8);
+  println!("{:?}", 1u64 as u16);
+  println!("{:?}", 1u64 as u32);
+  println!("{:?}", 1u64 as u64);
+  println!("{:?}", 1u64 as f32);
+  println!("{:?}", 1u64 as f64);
+
+  println!("{:?}", 1u64 as isize);
+  println!("{:?}", 1u64 as usize);
+  println!("{:?}", 1u64 as *const String);
+  println!("{:?}", 1u64 as i8);
+  println!("{:?}", 1u64 as i16);
+  println!("{:?}", 1u64 as i32);
+  println!("{:?}", 1u64 as i64);
+  println!("{:?}", 1u64 as u8);
+  println!("{:?}", 1u64 as u16);
+  println!("{:?}", 1u64 as u32);
+  println!("{:?}", 1u64 as u64);
+  println!("{:?}", 1u64 as f32);
+  println!("{:?}", 1u64 as f64);
+
+  println!("{:?}", true as isize);
+  println!("{:?}", true as usize);
+  println!("{:?}", true as i8);
+  println!("{:?}", true as i16);
+  println!("{:?}", true as i32);
+  println!("{:?}", true as i64);
+  println!("{:?}", true as u8);
+  println!("{:?}", true as u16);
+  println!("{:?}", true as u32);
+  println!("{:?}", true as u64);
+
+  println!("{:?}", 1f32 as isize);
+  println!("{:?}", 1f32 as usize);
+  println!("{:?}", 1f32 as i8);
+  println!("{:?}", 1f32 as i16);
+  println!("{:?}", 1f32 as i32);
+  println!("{:?}", 1f32 as i64);
+  println!("{:?}", 1f32 as u8);
+  println!("{:?}", 1f32 as u16);
+  println!("{:?}", 1f32 as u32);
+  println!("{:?}", 1f32 as u64);
+  println!("{:?}", 1f32 as f32);
+  println!("{:?}", 1f32 as f64);
+
+  println!("{:?}", 1f64 as isize);
+  println!("{:?}", 1f64 as usize);
+  println!("{:?}", 1f64 as i8);
+  println!("{:?}", 1f64 as i16);
+  println!("{:?}", 1f64 as i32);
+  println!("{:?}", 1f64 as i64);
+  println!("{:?}", 1f64 as u8);
+  println!("{:?}", 1f64 as u16);
+  println!("{:?}", 1f64 as u32);
+  println!("{:?}", 1f64 as u64);
+  println!("{:?}", 1f64 as f32);
+  println!("{:?}", 1f64 as f64);
+}
diff --git a/src/test/ui/changing-crates.rs b/src/test/ui/changing-crates.rs
deleted file mode 100644 (file)
index 60c043b..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// ignore-msvc FIXME #31306
-
-// note that these aux-build directives must be in this order
-// aux-build:changing-crates-a1.rs
-// aux-build:changing-crates-b.rs
-// aux-build:changing-crates-a2.rs
-// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2"
-
-extern crate a;
-extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
-
-fn main() {}
diff --git a/src/test/ui/changing-crates.stderr b/src/test/ui/changing-crates.stderr
deleted file mode 100644 (file)
index cc62a4d..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0460]: found possibly newer version of crate `a` which `b` depends on
-  --> $DIR/changing-crates.rs:10:1
-   |
-LL | extern crate b;
-   | ^^^^^^^^^^^^^^^
-   |
-   = note: perhaps that crate needs to be recompiled?
-   = note: the following crate versions were found:
-           crate `a`: $PATH_a
-           crate `b`: $PATH_b
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-90465.fixed b/src/test/ui/closures/2229_closure_analysis/issue-90465.fixed
new file mode 100644 (file)
index 0000000..4e0b18e
--- /dev/null
@@ -0,0 +1,35 @@
+// run-rustfix
+
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE lint level is defined here
+
+fn main() {
+    struct Foo(u32);
+    impl Drop for Foo {
+        fn drop(&mut self) {
+            println!("dropped {}", self.0);
+        }
+    }
+
+    let f0 = Foo(0);
+    let f1 = Foo(1);
+
+    let c0 = move || {
+        let _ = &f0;
+        //~^ ERROR changes to closure capture in Rust 2021 will affect drop order
+        //~| NOTE for more information
+        let _ = f0;
+        //~^ NOTE in Rust 2018, this causes the closure to capture `f0`, but in Rust 2021, it has no effect
+    };
+
+    let c1 = move || {
+        let _ = &f1;
+    };
+
+    println!("dropping 0");
+    drop(c0);
+    println!("dropping 1");
+    drop(c1);
+    println!("dropped all");
+}
+//~^ NOTE in Rust 2018, `f0` is dropped here along with the closure, but in Rust 2021 `f0` is not part of the closure
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-90465.rs b/src/test/ui/closures/2229_closure_analysis/issue-90465.rs
new file mode 100644 (file)
index 0000000..466e6db
--- /dev/null
@@ -0,0 +1,34 @@
+// run-rustfix
+
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE lint level is defined here
+
+fn main() {
+    struct Foo(u32);
+    impl Drop for Foo {
+        fn drop(&mut self) {
+            println!("dropped {}", self.0);
+        }
+    }
+
+    let f0 = Foo(0);
+    let f1 = Foo(1);
+
+    let c0 = move || {
+        //~^ ERROR changes to closure capture in Rust 2021 will affect drop order
+        //~| NOTE for more information
+        let _ = f0;
+        //~^ NOTE in Rust 2018, this causes the closure to capture `f0`, but in Rust 2021, it has no effect
+    };
+
+    let c1 = move || {
+        let _ = &f1;
+    };
+
+    println!("dropping 0");
+    drop(c0);
+    println!("dropping 1");
+    drop(c1);
+    println!("dropped all");
+}
+//~^ NOTE in Rust 2018, `f0` is dropped here along with the closure, but in Rust 2021 `f0` is not part of the closure
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-90465.stderr b/src/test/ui/closures/2229_closure_analysis/issue-90465.stderr
new file mode 100644 (file)
index 0000000..3e921dc
--- /dev/null
@@ -0,0 +1,26 @@
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/issue-90465.rs:17:14
+   |
+LL |     let c0 = move || {
+   |              ^^^^^^^
+...
+LL |         let _ = f0;
+   |                 -- in Rust 2018, this causes the closure to capture `f0`, but in Rust 2021, it has no effect
+...
+LL | }
+   | - in Rust 2018, `f0` is dropped here along with the closure, but in Rust 2021 `f0` is not part of the closure
+   |
+note: the lint level is defined here
+  --> $DIR/issue-90465.rs:3:9
+   |
+LL | #![deny(rust_2021_incompatible_closure_captures)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+help: add a dummy let to cause `f0` to be fully captured
+   |
+LL ~     let c0 = move || {
+LL +         let _ = &f0;
+   |
+
+error: aborting due to previous error
+
index b0fc5120f08f219783461c3e3e44316ed4323b28..26703fbf81193603e2a471b5a5d055b20bcc93db 100644 (file)
@@ -20,8 +20,8 @@ fn test_send_trait() {
     let mut f = 10;
     let fptr = SendPointer(&mut f as *mut i32);
     thread::spawn(move || { let _ = &fptr; unsafe {
-        //~^ ERROR: `Send` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send`
+        //~^ ERROR: changes to closure capture
+        //~| NOTE: in Rust 2018, this closure implements `Send`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr` to be fully captured
         *fptr.0 = 20;
@@ -40,8 +40,9 @@ fn test_sync_trait() {
     let f = CustomInt(&mut f as *mut i32);
     let fptr = SyncPointer(f);
     thread::spawn(move || { let _ = &fptr; unsafe {
-        //~^ ERROR: `Sync`, `Send` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
+        //~^ ERROR: changes to closure capture
+        //~| NOTE: in Rust 2018, this closure implements `Sync`
+        //~| NOTE: in Rust 2018, this closure implements `Send`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr` to be fully captured
         *fptr.0.0 = 20;
@@ -65,8 +66,8 @@ fn test_clone_trait() {
     let f = U(S(Foo(0)), T(0));
     let c = || {
         let _ = &f;
-        //~^ ERROR: `Clone` trait implementation for closure and drop order
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone`
+        //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
+        //~| NOTE: in Rust 2018, this closure implements `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f` to be fully captured
         let f_1 = f.1;
index 2bcf9a795edbd8f9fa093efe8b216d76725d777f..932db51d437130699e7256ef92cf104542b34940 100644 (file)
@@ -20,8 +20,8 @@ fn test_send_trait() {
     let mut f = 10;
     let fptr = SendPointer(&mut f as *mut i32);
     thread::spawn(move || unsafe {
-        //~^ ERROR: `Send` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send`
+        //~^ ERROR: changes to closure capture
+        //~| NOTE: in Rust 2018, this closure implements `Send`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr` to be fully captured
         *fptr.0 = 20;
@@ -40,8 +40,9 @@ fn test_sync_trait() {
     let f = CustomInt(&mut f as *mut i32);
     let fptr = SyncPointer(f);
     thread::spawn(move || unsafe {
-        //~^ ERROR: `Sync`, `Send` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
+        //~^ ERROR: changes to closure capture
+        //~| NOTE: in Rust 2018, this closure implements `Sync`
+        //~| NOTE: in Rust 2018, this closure implements `Send`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr` to be fully captured
         *fptr.0.0 = 20;
@@ -64,8 +65,8 @@ fn clone(&self) -> Self {
 fn test_clone_trait() {
     let f = U(S(Foo(0)), T(0));
     let c = || {
-        //~^ ERROR: `Clone` trait implementation for closure and drop order
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone`
+        //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
+        //~| NOTE: in Rust 2018, this closure implements `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f` to be fully captured
         let f_1 = f.1;
index 8d2d3553d4040f2fdbb6027cbe71d5fb5c3fd700..ee4907bb755cc115005945b6af0d7fa14e964da4 100644 (file)
@@ -1,8 +1,8 @@
-error: changes to closure capture in Rust 2021 will affect `Send` trait implementation for closure
+error: changes to closure capture in Rust 2021 will affect which traits the closure implements
   --> $DIR/auto_traits.rs:22:19
    |
 LL |     thread::spawn(move || unsafe {
-   |                   ^^^^^^^^^^^^^^ in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send`
+   |                   ^^^^^^^^^^^^^^ in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr` is not fully captured and `fptr.0` does not implement `Send`
 ...
 LL |         *fptr.0 = 20;
    |         ------- in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0`
@@ -23,11 +23,14 @@ LL |
 LL |         *fptr.0 = 20;
  ...
 
-error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure
+error: changes to closure capture in Rust 2021 will affect which traits the closure implements
   --> $DIR/auto_traits.rs:42:19
    |
 LL |     thread::spawn(move || unsafe {
-   |                   ^^^^^^^^^^^^^^ in Rust 2018, this closure implements `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
+   |                   ^^^^^^^^^^^^^^
+   |                   |
+   |                   in Rust 2018, this closure implements `Sync` as `fptr` implements `Sync`, but in Rust 2021, this closure will no longer implement `Sync` because `fptr` is not fully captured and `fptr.0.0` does not implement `Sync`
+   |                   in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr` is not fully captured and `fptr.0.0` does not implement `Send`
 ...
 LL |         *fptr.0.0 = 20;
    |         --------- in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0.0`
@@ -40,14 +43,14 @@ LL |
 LL |
 LL |
 LL |
-LL |         *fptr.0.0 = 20;
+LL |
  ...
 
-error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order
-  --> $DIR/auto_traits.rs:66:13
+error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
+  --> $DIR/auto_traits.rs:67:13
    |
 LL |     let c = || {
-   |             ^^ in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone`
+   |             ^^ in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f` is not fully captured and `f.1` does not implement `Clone`
 ...
 LL |         let f_1 = f.1;
    |                   --- in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.1`
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/issue-90024-adt-correct-subst.rs b/src/test/ui/closures/2229_closure_analysis/migrations/issue-90024-adt-correct-subst.rs
new file mode 100644 (file)
index 0000000..ed8cb04
--- /dev/null
@@ -0,0 +1,37 @@
+// Test that rustc doesn't ICE as in #90024.
+// check-pass
+// edition=2018
+
+#![warn(rust_2021_incompatible_closure_captures)]
+
+// Checks there's no double-subst into the generic args, otherwise we get OOB
+// MCVE by @lqd
+pub struct Graph<N, E, Ix> {
+    _edges: E,
+    _nodes: N,
+    _ix: Vec<Ix>,
+}
+fn graph<N, E>() -> Graph<N, E, i32> {
+    todo!()
+}
+fn first_ice() {
+    let g = graph::<i32, i32>();
+    let _ = || g;
+}
+
+// Checks that there is a subst into the fields, otherwise we get normalization error
+// MCVE by @cuviper
+use std::iter::Empty;
+struct Foo<I: Iterator> {
+    data: Vec<I::Item>,
+}
+pub fn second_ice() {
+    let v = Foo::<Empty<()>> { data: vec![] };
+
+    (|| v.data[0])();
+}
+
+pub fn main() {
+    first_ice();
+    second_ice();
+}
index a5652154682c5b672da67568c79a30dbc1f1e384..7df0dd76b44564b768e8989ece9e037c962d9136 100644 (file)
@@ -19,8 +19,9 @@ where
     let f = panic::AssertUnwindSafe(f);
     let result = panic::catch_unwind(move || {
         let _ = &f;
-        //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
+        //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures]
+        //~| NOTE: in Rust 2018, this closure implements `UnwindSafe`
+        //~| NOTE: in Rust 2018, this closure implements `RefUnwindSafe`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f` to be fully captured
         f.0()
index d9acde073fc3d38fffd84202b80668764057f394..d02fac7c66952606048a19827fcd9c37050b3c23 100644 (file)
@@ -18,8 +18,9 @@ fn assert_panics<F>(f: F)
 {
     let f = panic::AssertUnwindSafe(f);
     let result = panic::catch_unwind(move || {
-        //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
+        //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures]
+        //~| NOTE: in Rust 2018, this closure implements `UnwindSafe`
+        //~| NOTE: in Rust 2018, this closure implements `RefUnwindSafe`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f` to be fully captured
         f.0()
index 10816b7bc3adf9346df3414fd7ed2105e6b6a621..74f85b6ebaac50e5f3de999ef10a17f90740d93d 100644 (file)
@@ -1,8 +1,11 @@
-error: changes to closure capture in Rust 2021 will affect `UnwindSafe`, `RefUnwindSafe` trait implementation for closure
+error: changes to closure capture in Rust 2021 will affect which traits the closure implements
   --> $DIR/mir_calls_to_shims.rs:20:38
    |
 LL |     let result = panic::catch_unwind(move || {
-   |                                      ^^^^^^^ in Rust 2018, this closure implements `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
+   |                                      ^^^^^^^
+   |                                      |
+   |                                      in Rust 2018, this closure implements `UnwindSafe` as `f` implements `UnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe` because `f` is not fully captured and `f.0` does not implement `UnwindSafe`
+   |                                      in Rust 2018, this closure implements `RefUnwindSafe` as `f` implements `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `RefUnwindSafe` because `f` is not fully captured and `f.0` does not implement `RefUnwindSafe`
 ...
 LL |         f.0()
    |         --- in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.0`
index 11218eff1337f7f63e779df6b9ec5a7a40fdc429..2b86b0ddade2367196e542f83ac91b65cfc2b2b7 100644 (file)
@@ -18,7 +18,6 @@ impl Foo {
     }
 }
 
-
 struct S(Foo);
 
 #[derive(Clone)]
@@ -37,8 +36,8 @@ fn test_multi_issues() {
     let f2 = U(S(Foo::from("bar")), T(0));
     let c = || {
         let _ = (&f1, &f2);
-        //~^ ERROR: `Clone` trait implementation for closure and drop order
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~^ ERROR: changes to closure capture in Rust 2021
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured
         let _f_1 = f1.0;
@@ -57,8 +56,8 @@ fn test_capturing_all_disjoint_fields_individually() {
     let f1 = U(S(Foo::from("foo")), T(0));
     let c = || {
         let _ = &f1;
-        //~^ ERROR: `Clone` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures]
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1` to be fully captured
         let _f_1 = f1.0;
@@ -83,9 +82,9 @@ fn test_capturing_several_disjoint_fields_individually_1() {
     let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar")));
     let c = || {
         let _ = &f1;
-        //~^ ERROR: `Clone` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.2` does not implement `Clone`
+        //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures]
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1` to be fully captured
         let _f_0 = f1.0;
@@ -103,8 +102,8 @@ fn test_capturing_several_disjoint_fields_individually_2() {
     let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar")));
     let c = || {
         let _ = &f1;
-        //~^ ERROR: `Clone` trait implementation for closure and drop order
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1` to be fully captured
         let _f_0 = f1.0;
@@ -136,9 +135,10 @@ fn test_multi_traits_issues() {
     let mut f2 = 10;
     let fptr2 = SendPointer(&mut f2 as *mut i32);
     thread::spawn(move || { let _ = (&fptr1, &fptr2); unsafe {
-        //~^ ERROR: `Sync`, `Send` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
-        //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr2.0` does not implement `Send`
+        //~^ ERROR: changes to closure capture in Rust 2021
+        //~| NOTE: in Rust 2018, this closure implements `Sync` as `fptr1` implements `Sync`
+        //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr1` implements `Send`
+        //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured
         *fptr1.0.0 = 20;
index 02f2faa2e8741615266e5f91687be7713335d207..3cac4abfad7c2a5def2e614517d6d30684481719 100644 (file)
@@ -18,7 +18,6 @@ fn from(s: &str) -> Self {
     }
 }
 
-
 struct S(Foo);
 
 #[derive(Clone)]
@@ -36,8 +35,8 @@ fn test_multi_issues() {
     let f1 = U(S(Foo::from("foo")), T(0));
     let f2 = U(S(Foo::from("bar")), T(0));
     let c = || {
-        //~^ ERROR: `Clone` trait implementation for closure and drop order
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~^ ERROR: changes to closure capture in Rust 2021
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured
         let _f_1 = f1.0;
@@ -55,8 +54,8 @@ fn test_multi_issues() {
 fn test_capturing_all_disjoint_fields_individually() {
     let f1 = U(S(Foo::from("foo")), T(0));
     let c = || {
-        //~^ ERROR: `Clone` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures]
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1` to be fully captured
         let _f_1 = f1.0;
@@ -80,9 +79,9 @@ fn clone(&self) -> Self {
 fn test_capturing_several_disjoint_fields_individually_1() {
     let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar")));
     let c = || {
-        //~^ ERROR: `Clone` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.2` does not implement `Clone`
+        //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures]
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1` to be fully captured
         let _f_0 = f1.0;
@@ -99,8 +98,8 @@ fn test_capturing_several_disjoint_fields_individually_1() {
 fn test_capturing_several_disjoint_fields_individually_2() {
     let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar")));
     let c = || {
-        //~^ ERROR: `Clone` trait implementation for closure and drop order
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1` to be fully captured
         let _f_0 = f1.0;
@@ -132,9 +131,10 @@ fn test_multi_traits_issues() {
     let mut f2 = 10;
     let fptr2 = SendPointer(&mut f2 as *mut i32);
     thread::spawn(move || unsafe {
-        //~^ ERROR: `Sync`, `Send` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
-        //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr2.0` does not implement `Send`
+        //~^ ERROR: changes to closure capture in Rust 2021
+        //~| NOTE: in Rust 2018, this closure implements `Sync` as `fptr1` implements `Sync`
+        //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr1` implements `Send`
+        //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured
         *fptr1.0.0 = 20;
index d425db5aa998c69394a674441809eef0581660b3..0008f1b2c07ed5811544fd27f9767c75c6bcfec0 100644 (file)
@@ -1,8 +1,8 @@
-error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order
-  --> $DIR/multi_diagnostics.rs:38:13
+error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
+  --> $DIR/multi_diagnostics.rs:37:13
    |
 LL |     let c = || {
-   |             ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+   |             ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.0` does not implement `Clone`
 ...
 LL |         let _f_1 = f1.0;
    |                    ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
@@ -25,11 +25,11 @@ LL ~     let c = || {
 LL +         let _ = (&f1, &f2);
    |
 
-error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure
-  --> $DIR/multi_diagnostics.rs:57:13
+error: changes to closure capture in Rust 2021 will affect which traits the closure implements
+  --> $DIR/multi_diagnostics.rs:56:13
    |
 LL |     let c = || {
-   |             ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+   |             ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.0` does not implement `Clone`
 ...
 LL |         let _f_1 = f1.0;
    |                    ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
@@ -41,14 +41,14 @@ LL ~     let c = || {
 LL +         let _ = &f1;
    |
 
-error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure
-  --> $DIR/multi_diagnostics.rs:82:13
+error: changes to closure capture in Rust 2021 will affect which traits the closure implements
+  --> $DIR/multi_diagnostics.rs:81:13
    |
 LL |     let c = || {
    |             ^^
    |             |
-   |             in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
-   |             in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.2` does not implement `Clone`
+   |             in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.0` does not implement `Clone`
+   |             in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.2` does not implement `Clone`
 ...
 LL |         let _f_0 = f1.0;
    |                    ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
@@ -63,11 +63,11 @@ LL ~     let c = || {
 LL +         let _ = &f1;
    |
 
-error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order
-  --> $DIR/multi_diagnostics.rs:101:13
+error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
+  --> $DIR/multi_diagnostics.rs:100:13
    |
 LL |     let c = || {
-   |             ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+   |             ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.0` does not implement `Clone`
 ...
 LL |         let _f_0 = f1.0;
    |                    ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
@@ -88,14 +88,15 @@ LL ~     let c = || {
 LL +         let _ = &f1;
    |
 
-error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure
-  --> $DIR/multi_diagnostics.rs:134:19
+error: changes to closure capture in Rust 2021 will affect which traits the closure implements
+  --> $DIR/multi_diagnostics.rs:133:19
    |
 LL |     thread::spawn(move || unsafe {
    |                   ^^^^^^^^^^^^^^
    |                   |
-   |                   in Rust 2018, this closure implements `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
-   |                   in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr2.0` does not implement `Send`
+   |                   in Rust 2018, this closure implements `Sync` as `fptr1` implements `Sync`, but in Rust 2021, this closure will no longer implement `Sync` because `fptr1` is not fully captured and `fptr1.0.0` does not implement `Sync`
+   |                   in Rust 2018, this closure implements `Send` as `fptr1` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr1` is not fully captured and `fptr1.0.0` does not implement `Send`
+   |                   in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr2` is not fully captured and `fptr2.0` does not implement `Send`
 ...
 LL |         *fptr1.0.0 = 20;
    |         ---------- in Rust 2018, this closure captures all of `fptr1`, but in Rust 2021, it will only capture `fptr1.0.0`
diff --git a/src/test/ui/closures/issue-10398.rs b/src/test/ui/closures/issue-10398.rs
new file mode 100644 (file)
index 0000000..0405b2d
--- /dev/null
@@ -0,0 +1,11 @@
+#![feature(box_syntax)]
+
+fn main() {
+    let x: Box<_> = box 1;
+    let f = move|| {
+        let _a = x;
+        drop(x);
+        //~^ ERROR: use of moved value: `x`
+    };
+    f();
+}
diff --git a/src/test/ui/closures/issue-10398.stderr b/src/test/ui/closures/issue-10398.stderr
new file mode 100644 (file)
index 0000000..8d9faf3
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/issue-10398.rs:7:14
+   |
+LL |         let _a = x;
+   |                  - value moved here
+LL |         drop(x);
+   |              ^ value used here after move
+   |
+   = note: move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/closures/issue-42463.rs b/src/test/ui/closures/issue-42463.rs
new file mode 100644 (file)
index 0000000..51d6ea3
--- /dev/null
@@ -0,0 +1,32 @@
+// run-pass
+use std::ops::{Deref, DerefMut};
+
+struct CheckedDeref<T, F> {
+    value: T,
+    check: F
+}
+
+impl<F: Fn(&T) -> bool, T> Deref for CheckedDeref<T, F> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        assert!((self.check)(&self.value));
+        &self.value
+    }
+}
+
+impl<F: Fn(&T) -> bool, T> DerefMut for CheckedDeref<T, F> {
+    fn deref_mut(&mut self) -> &mut T {
+        assert!((self.check)(&self.value));
+        &mut self.value
+    }
+}
+
+
+fn main() {
+    let mut v = CheckedDeref {
+        value: vec![0],
+        check: |v: &Vec<_>| !v.is_empty()
+    };
+    v.push(1);
+    assert_eq!(*v, vec![0, 1]);
+}
index d9479002b6cde31df63b1e10c5c04bb77b4504e2..ee394d64a1dc945d5c072cf2e64f7766771cf292 100644 (file)
@@ -9,7 +9,7 @@ LL |         let c1 : () = c;
    |                  expected due to this
    |
    = note: expected unit type `()`
-                found closure `[mod1::f<T>::{closure#0} closure_substs=(unavailable)]`
+                found closure `[mod1::f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#22t, extern "rust-call" fn(()), _#23t]]`
 help: use parentheses to call this closure
    |
 LL |         let c1 : () = c();
index 880e38df2d70a87586c18a20cdd111dadcbd8711..11b9fa7e40caa67f2d1a337f727b8c84a8dc60d4 100644 (file)
@@ -9,7 +9,7 @@ LL |         let c1 : () = c;
    |                  expected due to this
    |
    = note: expected unit type `()`
-                found closure `[f<T>::{closure#0} closure_substs=(unavailable)]`
+                found closure `[f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#22t, extern "rust-call" fn(()), _#23t]]`
 help: use parentheses to call this closure
    |
 LL |         let c1 : () = c();
index d19b07acbf175c3aa8ed7e88fbe87ed4e847e0b0..083717b333408e46d342f4e6a07b20d72058db87 100644 (file)
@@ -7,7 +7,7 @@ LL |     let foo: fn(u8) -> u8 = |v: u8| { a += v; a };
    |              expected due to this
    |
    = note: expected fn pointer `fn(u8) -> u8`
-                 found closure `[main::{closure#0} closure_substs=(unavailable)]`
+                 found closure `[main::{closure#0} closure_substs=(unavailable) substs=[i8, extern "rust-call" fn((u8,)) -> u8, _#6t]]`
 note: closures can only be coerced to `fn` types if they do not capture any variables
   --> $DIR/closure-print-verbose.rs:10:39
    |
diff --git a/src/test/ui/coercion/auxiliary/issue-39823.rs b/src/test/ui/coercion/auxiliary/issue-39823.rs
new file mode 100644 (file)
index 0000000..3af9c68
--- /dev/null
@@ -0,0 +1,7 @@
+#![crate_type="rlib"]
+
+#[derive(Debug, PartialEq)]
+pub struct RemoteC(pub u32);
+
+#[derive(Debug, PartialEq)]
+pub struct RemoteG<T>(pub T);
diff --git a/src/test/ui/coercion/issue-14589.rs b/src/test/ui/coercion/issue-14589.rs
new file mode 100644 (file)
index 0000000..5d8aab2
--- /dev/null
@@ -0,0 +1,24 @@
+// run-pass
+// All 3 expressions should work in that the argument gets
+// coerced to a trait object
+
+// pretty-expanded FIXME #23616
+
+fn main() {
+    send::<Box<dyn Foo>>(Box::new(Output(0)));
+    Test::<Box<dyn Foo>>::foo(Box::new(Output(0)));
+    Test::<Box<dyn Foo>>::new().send(Box::new(Output(0)));
+}
+
+fn send<T>(_: T) {}
+
+struct Test<T> { marker: std::marker::PhantomData<T> }
+impl<T> Test<T> {
+    fn new() -> Test<T> { Test { marker: ::std::marker::PhantomData } }
+    fn foo(_: T) {}
+    fn send(&self, _: T) {}
+}
+
+trait Foo { fn dummy(&self) { }}
+struct Output(isize);
+impl Foo for Output {}
diff --git a/src/test/ui/coercion/issue-39823.rs b/src/test/ui/coercion/issue-39823.rs
new file mode 100644 (file)
index 0000000..148cf52
--- /dev/null
@@ -0,0 +1,25 @@
+// run-pass
+// aux-build:issue-39823.rs
+
+extern crate issue_39823;
+use issue_39823::{RemoteC, RemoteG};
+
+#[derive(Debug, PartialEq)]
+struct LocalC(u32);
+
+#[derive(Debug, PartialEq)]
+struct LocalG<T>(T);
+
+fn main() {
+    let virtual_localc : &dyn Fn(_) -> LocalC = &LocalC;
+    assert_eq!(virtual_localc(1), LocalC(1));
+
+    let virtual_localg : &dyn Fn(_) -> LocalG<u32> = &LocalG;
+    assert_eq!(virtual_localg(1), LocalG(1));
+
+    let virtual_remotec : &dyn Fn(_) -> RemoteC = &RemoteC;
+    assert_eq!(virtual_remotec(1), RemoteC(1));
+
+    let virtual_remoteg : &dyn Fn(_) -> RemoteG<u32> = &RemoteG;
+    assert_eq!(virtual_remoteg(1), RemoteG(1));
+}
diff --git a/src/test/ui/coercion/issue-73886.rs b/src/test/ui/coercion/issue-73886.rs
new file mode 100644 (file)
index 0000000..9c0c87a
--- /dev/null
@@ -0,0 +1,6 @@
+fn main() {
+    let _ = &&[0] as &[_];
+    //~^ ERROR non-primitive cast: `&&[i32; 1]` as `&[_]`
+    let _ = 7u32 as Option<_>;
+    //~^ ERROR non-primitive cast: `u32` as `Option<_>`
+}
diff --git a/src/test/ui/coercion/issue-73886.stderr b/src/test/ui/coercion/issue-73886.stderr
new file mode 100644 (file)
index 0000000..a6f8ba6
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0605]: non-primitive cast: `&&[i32; 1]` as `&[_]`
+  --> $DIR/issue-73886.rs:2:13
+   |
+LL |     let _ = &&[0] as &[_];
+   |             ^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
+
+error[E0605]: non-primitive cast: `u32` as `Option<_>`
+  --> $DIR/issue-73886.rs:4:13
+   |
+LL |     let _ = 7u32 as Option<_>;
+   |             ^^^^^^^^^^^^^^^^^ help: consider using the `From` trait instead: `Option<_>::from(7u32)`
+   |
+   = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0605`.
diff --git a/src/test/ui/compare-method/issue-90444.rs b/src/test/ui/compare-method/issue-90444.rs
new file mode 100644 (file)
index 0000000..6c287d9
--- /dev/null
@@ -0,0 +1,17 @@
+pub struct A;
+impl From<fn((), (), &())> for A {
+    fn from(_: fn((), (), &mut ())) -> Self {
+        //~^ error: method `from` has an incompatible type for trait
+        loop {}
+    }
+}
+
+pub struct B;
+impl From<fn((), (), u32)> for B {
+    fn from(_: fn((), (), u64)) -> Self {
+        //~^ error: method `from` has an incompatible type for trait
+        loop {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/compare-method/issue-90444.stderr b/src/test/ui/compare-method/issue-90444.stderr
new file mode 100644 (file)
index 0000000..84bbec0
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0053]: method `from` has an incompatible type for trait
+  --> $DIR/issue-90444.rs:3:16
+   |
+LL |     fn from(_: fn((), (), &mut ())) -> Self {
+   |                ^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                types differ in mutability
+   |                help: change the parameter type to match the trait: `for<'r> fn((), (), &'r ())`
+   |
+   = note: expected fn pointer `fn(for<'r> fn((), (), &'r ())) -> A`
+              found fn pointer `fn(for<'r> fn((), (), &'r mut ())) -> A`
+
+error[E0053]: method `from` has an incompatible type for trait
+  --> $DIR/issue-90444.rs:11:16
+   |
+LL |     fn from(_: fn((), (), u64)) -> Self {
+   |                ^^^^^^^^^^^^^^^
+   |                |
+   |                expected `u32`, found `u64`
+   |                help: change the parameter type to match the trait: `fn((), (), u32)`
+   |
+   = note: expected fn pointer `fn(fn((), (), u32)) -> B`
+              found fn pointer `fn(fn((), (), u64)) -> B`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/conditional-compilation/issue-34028.rs b/src/test/ui/conditional-compilation/issue-34028.rs
new file mode 100644 (file)
index 0000000..d761c0c
--- /dev/null
@@ -0,0 +1,10 @@
+// check-pass
+
+macro_rules! m {
+    () => { #[cfg(any())] fn f() {} }
+}
+
+trait T {}
+impl T for () { m!(); }
+
+fn main() {}
diff --git a/src/test/ui/const-generics/auxiliary/legacy-const-generics.rs b/src/test/ui/const-generics/auxiliary/legacy-const-generics.rs
new file mode 100644 (file)
index 0000000..67352a2
--- /dev/null
@@ -0,0 +1,6 @@
+#![feature(rustc_attrs)]
+
+#[rustc_legacy_const_generics(1)]
+pub fn foo<const Y: usize>(x: usize, z: usize) -> [usize; 3] {
+    [x, Y, z]
+}
diff --git a/src/test/ui/const-generics/expose-default-substs-param-env.rs b/src/test/ui/const-generics/expose-default-substs-param-env.rs
new file mode 100644 (file)
index 0000000..e40c931
--- /dev/null
@@ -0,0 +1,9 @@
+// build-pass
+
+#![feature(generic_const_exprs)]
+#![allow(unused_braces, incomplete_features)]
+
+pub trait Foo<const N: usize> {}
+pub trait Bar: Foo<{ 1 }> { }
+
+fn main() {}
index e51db35925e4acb3d543482c8ba6269d0e8da6b4..4202cbae7eb29a46750827dd0247db2add4554c1 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `(): _Contains<&C>` is not satisfied
-  --> $DIR/issue-85848.rs:24:5
+  --> $DIR/issue-85848.rs:24:29
    |
 LL |     writes_to_specific_path(&cap);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ the trait `_Contains<&C>` is not implemented for `()`
+   |     ----------------------- ^^^^ the trait `_Contains<&C>` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required because of the requirements on the impl of `Contains<(), true>` for `&C`
   --> $DIR/issue-85848.rs:21:12
@@ -21,10 +23,12 @@ LL | fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {}
    |                               ^^^^^^^^^^^^^ required by this bound in `writes_to_specific_path`
 
 error: unconstrained generic constant
-  --> $DIR/issue-85848.rs:24:5
+  --> $DIR/issue-85848.rs:24:29
    |
 LL |     writes_to_specific_path(&cap);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |     ----------------------- ^^^^
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: try adding a `where` bound using this expression: `where [(); { contains::<T, U>() }]:`
 note: required because of the requirements on the impl of `Contains<(), true>` for `&C`
index 6268a564b06b65dafeccf91f5a895788ddf3ba7c..87e4ad500404439b6fa4c585653f292c0fee2d7c 100644 (file)
@@ -3,6 +3,9 @@ error[E0632]: cannot provide explicit generic arguments when `impl Trait` is use
    |
 LL |     assert_eq!(f::<4usize>(Usizable), 20usize);
    |                    ^^^^^^ explicit generic argument not allowed
+   |
+   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
+   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-88997.rs b/src/test/ui/const-generics/issues/issue-88997.rs
new file mode 100644 (file)
index 0000000..7666a51
--- /dev/null
@@ -0,0 +1,14 @@
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+
+struct ConstAssert<const COND: bool>;
+trait True {}
+impl True for ConstAssert<true> {}
+
+struct Range<T: PartialOrd, const MIN: T, const MAX: T>(T)
+//~^ ERROR the type of const parameters must not depend on other generic parameters
+//~| ERROR the type of const parameters must not depend on other generic parameters
+where
+    ConstAssert<{ MIN <= MAX }>: True;
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-88997.stderr b/src/test/ui/const-generics/issues/issue-88997.stderr
new file mode 100644 (file)
index 0000000..505ba0d
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/issue-88997.rs:8:40
+   |
+LL | struct Range<T: PartialOrd, const MIN: T, const MAX: T>(T)
+   |                                        ^ the type must not depend on the parameter `T`
+
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/issue-88997.rs:8:54
+   |
+LL | struct Range<T: PartialOrd, const MIN: T, const MAX: T>(T)
+   |                                                      ^ the type must not depend on the parameter `T`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0770`.
diff --git a/src/test/ui/const-generics/issues/issue-89304.rs b/src/test/ui/const-generics/issues/issue-89304.rs
new file mode 100644 (file)
index 0000000..d544d63
--- /dev/null
@@ -0,0 +1,20 @@
+// check-pass
+
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct GenericStruct<const T: usize> { val: i64 }
+
+impl<const T: usize> From<GenericStruct<T>> for GenericStruct<{T + 1}> {
+    fn from(other: GenericStruct<T>) -> Self {
+        Self { val: other.val }
+    }
+}
+
+impl<const T: usize> From<GenericStruct<{T + 1}>> for GenericStruct<T> {
+    fn from(other: GenericStruct<{T + 1}>) -> Self {
+        Self { val: other.val }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-89334.rs b/src/test/ui/const-generics/issues/issue-89334.rs
new file mode 100644 (file)
index 0000000..b15b742
--- /dev/null
@@ -0,0 +1,16 @@
+// build-pass
+
+#![feature(generic_const_exprs)]
+#![allow(unused_braces, incomplete_features)]
+
+pub trait AnotherTrait{
+    const ARRAY_SIZE: usize;
+}
+pub trait Shard<T: AnotherTrait>:
+    AsMut<[[u8; T::ARRAY_SIZE]]>
+where
+    [(); T::ARRAY_SIZE]: Sized
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-90364.rs b/src/test/ui/const-generics/issues/issue-90364.rs
new file mode 100644 (file)
index 0000000..b11b07b
--- /dev/null
@@ -0,0 +1,9 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub struct Foo<T, const H: T>(T)
+//~^ ERROR the type of const parameters must not depend on other generic parameters
+where
+    [(); 1]:;
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-90364.stderr b/src/test/ui/const-generics/issues/issue-90364.stderr
new file mode 100644 (file)
index 0000000..e85bd13
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/issue-90364.rs:4:28
+   |
+LL | pub struct Foo<T, const H: T>(T)
+   |                            ^ the type must not depend on the parameter `T`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0770`.
diff --git a/src/test/ui/const-generics/legacy-const-generics-bad.rs b/src/test/ui/const-generics/legacy-const-generics-bad.rs
new file mode 100644 (file)
index 0000000..538eee3
--- /dev/null
@@ -0,0 +1,16 @@
+// aux-build:legacy-const-generics.rs
+
+extern crate legacy_const_generics;
+
+fn foo<const N: usize>() {
+    let a = 1;
+    legacy_const_generics::foo(0, a, 2);
+    //~^ ERROR attempt to use a non-constant value in a constant
+
+    legacy_const_generics::foo(0, N, 2);
+
+    legacy_const_generics::foo(0, N + 1, 2);
+    //~^ ERROR generic parameters may not be used in const operations
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/legacy-const-generics-bad.stderr b/src/test/ui/const-generics/legacy-const-generics-bad.stderr
new file mode 100644 (file)
index 0000000..3c78dd6
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0435]: attempt to use a non-constant value in a constant
+  --> $DIR/legacy-const-generics-bad.rs:7:35
+   |
+LL |     let a = 1;
+   |     ----- help: consider using `const` instead of `let`: `const a`
+LL |     legacy_const_generics::foo(0, a, 2);
+   |                                   ^ non-constant value
+
+error: generic parameters may not be used in const operations
+  --> $DIR/legacy-const-generics-bad.rs:12:35
+   |
+LL |     legacy_const_generics::foo(0, N + 1, 2);
+   |                                   ^ cannot perform const operation using `N`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/const-generics/legacy-const-generics.rs b/src/test/ui/const-generics/legacy-const-generics.rs
new file mode 100644 (file)
index 0000000..9abc72d
--- /dev/null
@@ -0,0 +1,18 @@
+// aux-build:legacy-const-generics.rs
+// run-pass
+
+#![feature(rustc_attrs)]
+
+extern crate legacy_const_generics;
+
+#[rustc_legacy_const_generics(1)]
+pub fn bar<const Y: usize>(x: usize, z: usize) -> [usize; 3] {
+    [x, Y, z]
+}
+
+fn main() {
+    assert_eq!(legacy_const_generics::foo(0 + 0, 1 + 1, 2 + 2), [0, 2, 4]);
+    assert_eq!(legacy_const_generics::foo::<{1 + 1}>(0 + 0, 2 + 2), [0, 2, 4]);
+    // FIXME: Only works cross-crate
+    //assert_eq!(bar(0, 1, 2), [0, 1, 2]);
+}
index fa9542f93a36ce67cf62727a2385a64db846182b..b46ca6ba6df5464a5137e942b743cc5143e2b4cb 100644 (file)
@@ -1,3 +1,5 @@
+// needs-asm-support
+
 #![feature(asm)]
 
 const _: () = unsafe { asm!("nop") };
index f38044a290b631da4b46675ee0b92676a415c30e..65a828d118c0cdc70a2e487d7d4f0873fde6c47b 100644 (file)
@@ -1,5 +1,5 @@
 error[E0015]: inline assembly is not allowed in constants
-  --> $DIR/inline_asm.rs:3:24
+  --> $DIR/inline_asm.rs:5:24
    |
 LL | const _: () = unsafe { asm!("nop") };
    |                        ^^^^^^^^^^^
diff --git a/src/test/ui/consts/issue-13902.rs b/src/test/ui/consts/issue-13902.rs
new file mode 100644 (file)
index 0000000..1afde0e
--- /dev/null
@@ -0,0 +1,16 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+
+const JSVAL_TAG_CLEAR: u32 = 0xFFFFFF80;
+const JSVAL_TYPE_INT32: u8 = 0x01;
+const JSVAL_TYPE_UNDEFINED: u8 = 0x02;
+#[repr(u32)]
+enum ValueTag {
+    JSVAL_TAG_INT32 = JSVAL_TAG_CLEAR | (JSVAL_TYPE_INT32 as u32),
+    JSVAL_TAG_UNDEFINED = JSVAL_TAG_CLEAR | (JSVAL_TYPE_UNDEFINED as u32),
+}
+
+fn main() {
+    let _ = ValueTag::JSVAL_TAG_INT32;
+}
diff --git a/src/test/ui/consts/issue-17074.rs b/src/test/ui/consts/issue-17074.rs
new file mode 100644 (file)
index 0000000..0ed8113
--- /dev/null
@@ -0,0 +1,15 @@
+// run-pass
+#![allow(dead_code)]
+
+static X2: u64 = !0 as u16 as u64;
+static Y2: u64 = !0 as u32 as u64;
+const X: u64 = !0 as u16 as u64;
+const Y: u64 = !0 as u32 as u64;
+
+fn main() {
+    assert_eq!(match 1 {
+        X => unreachable!(),
+        Y => unreachable!(),
+        _ => 1
+    }, 1);
+}
diff --git a/src/test/ui/consts/issue-18294.rs b/src/test/ui/consts/issue-18294.rs
new file mode 100644 (file)
index 0000000..77355f0
--- /dev/null
@@ -0,0 +1,5 @@
+fn main() {
+    const X: u32 = 1;
+    const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR pointers cannot be cast to integers
+    println!("{}", Y);
+}
diff --git a/src/test/ui/consts/issue-18294.stderr b/src/test/ui/consts/issue-18294.stderr
new file mode 100644 (file)
index 0000000..e0cbd2a
--- /dev/null
@@ -0,0 +1,11 @@
+error: pointers cannot be cast to integers during const eval
+  --> $DIR/issue-18294.rs:3:31
+   |
+LL |     const Y: usize = unsafe { &X as *const u32 as usize };
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: at compile-time, pointers do not have an integer value
+   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/issue-23968-const-not-overflow.rs b/src/test/ui/consts/issue-23968-const-not-overflow.rs
new file mode 100644 (file)
index 0000000..b959302
--- /dev/null
@@ -0,0 +1,12 @@
+// run-pass
+const U8_MAX_HALF: u8 = !0u8 / 2;
+const U16_MAX_HALF: u16 = !0u16 / 2;
+const U32_MAX_HALF: u32 = !0u32 / 2;
+const U64_MAX_HALF: u64 = !0u64 / 2;
+
+fn main() {
+    assert_eq!(U8_MAX_HALF, 0x7f);
+    assert_eq!(U16_MAX_HALF, 0x7fff);
+    assert_eq!(U32_MAX_HALF, 0x7fff_ffff);
+    assert_eq!(U64_MAX_HALF, 0x7fff_ffff_ffff_ffff);
+}
diff --git a/src/test/ui/consts/issue-37550-1.rs b/src/test/ui/consts/issue-37550-1.rs
new file mode 100644 (file)
index 0000000..35b63bd
--- /dev/null
@@ -0,0 +1,6 @@
+const fn x() {
+    let t = true;
+    let x = || t; //~ ERROR function pointer
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/issue-37550-1.stderr b/src/test/ui/consts/issue-37550-1.stderr
new file mode 100644 (file)
index 0000000..f66d706
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0658]: function pointers cannot appear in constant functions
+  --> $DIR/issue-37550-1.rs:3:9
+   |
+LL |     let x = || t;
+   |         ^
+   |
+   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
+   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/issue-37991.rs b/src/test/ui/consts/issue-37991.rs
new file mode 100644 (file)
index 0000000..a6ac4d5
--- /dev/null
@@ -0,0 +1,17 @@
+// run-pass
+
+const fn foo() -> i64 {
+    3
+}
+
+const fn bar(x: i64) -> i64 {
+    x*2
+}
+
+fn main() {
+    let val = &(foo() % 2);
+    assert_eq!(*val, 1);
+
+    let val2 = &(bar(1+1) % 3);
+    assert_eq!(*val2, 1);
+}
index 99926532247ab1c1e5d7431feea83a4983c814be..6830b23cfa345eeb6ea83e49e8a156f107aaee53 100644 (file)
@@ -39,6 +39,8 @@ pub const fn promote_union() {
     let _val: &'static _ = &(Cell::new(1), 2).1; //~ ERROR temporary value dropped while borrowed
 };
 
+const TEST_DROP: String = String::new();
+
 fn main() {
     // We must not promote things with interior mutability. Not even if we "project it away".
     let _val: &'static _ = &(Cell::new(1), 2).0; //~ ERROR temporary value dropped while borrowed
@@ -50,4 +52,17 @@ fn main() {
     let _val: &'static _ = &(1%0); //~ ERROR temporary value dropped while borrowed
     let _val: &'static _ = &(1%(1-1)); //~ ERROR temporary value dropped while borrowed
     let _val: &'static _ = &([1,2,3][4]+1); //~ ERROR temporary value dropped while borrowed
+
+    // No promotion of temporaries that need to be dropped.
+    let _val: &'static _ = &TEST_DROP;
+    //~^ ERROR temporary value dropped while borrowed
+    let _val: &'static _ = &&TEST_DROP;
+    //~^ ERROR temporary value dropped while borrowed
+    //~| ERROR temporary value dropped while borrowed
+    let _val: &'static _ = &(&TEST_DROP,);
+    //~^ ERROR temporary value dropped while borrowed
+    //~| ERROR temporary value dropped while borrowed
+    let _val: &'static _ = &[&TEST_DROP; 1];
+    //~^ ERROR temporary value dropped while borrowed
+    //~| ERROR temporary value dropped while borrowed
 }
index 932109bd86dcfa6a957d09ef9a943ae358b5b970..0d0b0f9c689b5b6593d007015efb60d00f71fba3 100644 (file)
@@ -59,7 +59,7 @@ LL | };
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:44:29
+  --> $DIR/promote-not.rs:46:29
    |
 LL |     let _val: &'static _ = &(Cell::new(1), 2).0;
    |               ----------    ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
@@ -70,7 +70,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:45:29
+  --> $DIR/promote-not.rs:47:29
    |
 LL |     let _val: &'static _ = &(Cell::new(1), 2).1;
    |               ----------    ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
@@ -81,7 +81,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:48:29
+  --> $DIR/promote-not.rs:50:29
    |
 LL |     let _val: &'static _ = &(1/0);
    |               ----------    ^^^^^ creates a temporary which is freed while still in use
@@ -92,7 +92,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:49:29
+  --> $DIR/promote-not.rs:51:29
    |
 LL |     let _val: &'static _ = &(1/(1-1));
    |               ----------    ^^^^^^^^^ creates a temporary which is freed while still in use
@@ -103,7 +103,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:50:29
+  --> $DIR/promote-not.rs:52:29
    |
 LL |     let _val: &'static _ = &(1%0);
    |               ----------    ^^^^^ creates a temporary which is freed while still in use
@@ -114,26 +114,102 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:51:29
+  --> $DIR/promote-not.rs:53:29
    |
 LL |     let _val: &'static _ = &(1%(1-1));
    |               ----------    ^^^^^^^^^ creates a temporary which is freed while still in use
    |               |
    |               type annotation requires that borrow lasts for `'static`
-LL |     let _val: &'static _ = &([1,2,3][4]+1);
+...
 LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:52:29
+  --> $DIR/promote-not.rs:54:29
    |
 LL |     let _val: &'static _ = &([1,2,3][4]+1);
    |               ----------    ^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
    |               |
    |               type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote-not.rs:57:29
+   |
+LL |     let _val: &'static _ = &TEST_DROP;
+   |               ----------    ^^^^^^^^^ creates a temporary which is freed while still in use
+   |               |
+   |               type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote-not.rs:59:29
+   |
+LL |     let _val: &'static _ = &&TEST_DROP;
+   |               ----------    ^^^^^^^^^^ creates a temporary which is freed while still in use
+   |               |
+   |               type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote-not.rs:59:30
+   |
+LL |     let _val: &'static _ = &&TEST_DROP;
+   |               ----------     ^^^^^^^^^ creates a temporary which is freed while still in use
+   |               |
+   |               type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote-not.rs:62:29
+   |
+LL |     let _val: &'static _ = &(&TEST_DROP,);
+   |               ----------    ^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |               |
+   |               type annotation requires that borrow lasts for `'static`
+...
 LL | }
    | - temporary value is freed at the end of this statement
 
-error: aborting due to 13 previous errors
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote-not.rs:62:31
+   |
+LL |     let _val: &'static _ = &(&TEST_DROP,);
+   |               ----------      ^^^^^^^^^ creates a temporary which is freed while still in use
+   |               |
+   |               type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote-not.rs:65:29
+   |
+LL |     let _val: &'static _ = &[&TEST_DROP; 1];
+   |               ----------    ^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |               |
+   |               type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote-not.rs:65:31
+   |
+LL |     let _val: &'static _ = &[&TEST_DROP; 1];
+   |               ----------      ^^^^^^^^^    - temporary value is freed at the end of this statement
+   |               |               |
+   |               |               creates a temporary which is freed while still in use
+   |               type annotation requires that borrow lasts for `'static`
+
+error: aborting due to 20 previous errors
 
 For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/qualif-indirect-mutation-fail.rs b/src/test/ui/consts/qualif-indirect-mutation-fail.rs
new file mode 100644 (file)
index 0000000..f74a25a
--- /dev/null
@@ -0,0 +1,64 @@
+// compile-flags: --crate-type=lib
+#![feature(const_mut_refs)]
+#![feature(const_precise_live_drops)]
+#![feature(const_swap)]
+#![feature(raw_ref_op)]
+
+// Mutable borrow of a field with drop impl.
+pub const fn f() {
+    let mut a: (u32, Option<String>) = (0, None); //~ ERROR destructors cannot be evaluated
+    let _ = &mut a.1;
+}
+
+// Mutable borrow of a type with drop impl.
+pub const A1: () = {
+    let mut x = None; //~ ERROR destructors cannot be evaluated
+    let mut y = Some(String::new());
+    let a = &mut x;
+    let b = &mut y;
+    std::mem::swap(a, b);
+    std::mem::forget(y);
+};
+
+// Mutable borrow of a type with drop impl.
+pub const A2: () = {
+    let mut x = None;
+    let mut y = Some(String::new());
+    let a = &mut x;
+    let b = &mut y;
+    std::mem::swap(a, b);
+    std::mem::forget(y);
+    let _z = x; //~ ERROR destructors cannot be evaluated
+};
+
+// Shared borrow of a type that might be !Freeze and Drop.
+pub const fn g1<T>() {
+    let x: Option<T> = None; //~ ERROR destructors cannot be evaluated
+    let _ = x.is_some();
+}
+
+// Shared borrow of a type that might be !Freeze and Drop.
+pub const fn g2<T>() {
+    let x: Option<T> = None;
+    let _ = x.is_some();
+    let _y = x; //~ ERROR destructors cannot be evaluated
+}
+
+// Mutable raw reference to a Drop type.
+pub const fn address_of_mut() {
+    let mut x: Option<String> = None; //~ ERROR destructors cannot be evaluated
+    &raw mut x;
+
+    let mut y: Option<String> = None; //~ ERROR destructors cannot be evaluated
+    std::ptr::addr_of_mut!(y);
+}
+
+// Const raw reference to a Drop type. Conservatively assumed to allow mutation
+// until resolution of https://github.com/rust-lang/rust/issues/56604.
+pub const fn address_of_const() {
+    let x: Option<String> = None; //~ ERROR destructors cannot be evaluated
+    &raw const x;
+
+    let y: Option<String> = None; //~ ERROR destructors cannot be evaluated
+    std::ptr::addr_of!(y);
+}
diff --git a/src/test/ui/consts/qualif-indirect-mutation-fail.stderr b/src/test/ui/consts/qualif-indirect-mutation-fail.stderr
new file mode 100644 (file)
index 0000000..713df12
--- /dev/null
@@ -0,0 +1,57 @@
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/qualif-indirect-mutation-fail.rs:9:9
+   |
+LL |     let mut a: (u32, Option<String>) = (0, None);
+   |         ^^^^^ constant functions cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/qualif-indirect-mutation-fail.rs:15:9
+   |
+LL |     let mut x = None;
+   |         ^^^^^ constants cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/qualif-indirect-mutation-fail.rs:31:9
+   |
+LL |     let _z = x;
+   |         ^^ constants cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/qualif-indirect-mutation-fail.rs:36:9
+   |
+LL |     let x: Option<T> = None;
+   |         ^ constant functions cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/qualif-indirect-mutation-fail.rs:44:9
+   |
+LL |     let _y = x;
+   |         ^^ constant functions cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/qualif-indirect-mutation-fail.rs:52:9
+   |
+LL |     let mut y: Option<String> = None;
+   |         ^^^^^ constant functions cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/qualif-indirect-mutation-fail.rs:49:9
+   |
+LL |     let mut x: Option<String> = None;
+   |         ^^^^^ constant functions cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/qualif-indirect-mutation-fail.rs:62:9
+   |
+LL |     let y: Option<String> = None;
+   |         ^ constant functions cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/qualif-indirect-mutation-fail.rs:59:9
+   |
+LL |     let x: Option<String> = None;
+   |         ^ constant functions cannot evaluate destructors
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/qualif-indirect-mutation-pass.rs b/src/test/ui/consts/qualif-indirect-mutation-pass.rs
new file mode 100644 (file)
index 0000000..06af6a0
--- /dev/null
@@ -0,0 +1,24 @@
+// compile-flags: --crate-type=lib
+// check-pass
+#![feature(const_mut_refs)]
+#![feature(const_precise_live_drops)]
+
+// Mutable reference allows only mutation of !Drop place.
+pub const fn f() {
+    let mut x: (Option<String>, u32) = (None, 0);
+    let mut a = 10;
+    *(&mut a) = 11;
+    x.1 = a;
+}
+
+// Mutable reference allows only mutation of !Drop place.
+pub const fn g() {
+    let mut a: (u32, Option<String>) = (0, None);
+    let _ = &mut a.0;
+}
+
+// Shared reference does not allow for mutation.
+pub const fn h() {
+    let x: Option<String> = None;
+    let _ = &x;
+}
diff --git a/src/test/ui/consts/qualif-union.rs b/src/test/ui/consts/qualif-union.rs
new file mode 100644 (file)
index 0000000..2054b5b
--- /dev/null
@@ -0,0 +1,32 @@
+// Checks that unions use type based qualification. Regression test for issue #90268.
+#![feature(untagged_unions)]
+use std::cell::Cell;
+
+union U { i: u32, c: Cell<u32> }
+
+const C1: Cell<u32> = {
+    unsafe { U { c: Cell::new(0) }.c }
+};
+
+const C2: Cell<u32> = {
+    unsafe { U { i : 0 }.c }
+};
+
+const C3: Cell<u32> = {
+    let mut u = U { i: 0 };
+    u.i = 1;
+    unsafe { u.c }
+};
+
+const C4: U = U { i: 0 };
+
+const C5: [U; 1] = [U {i : 0}; 1];
+
+fn main() {
+    // Interior mutability should prevent promotion.
+    let _: &'static _ = &C1; //~ ERROR temporary value dropped while borrowed
+    let _: &'static _ = &C2; //~ ERROR temporary value dropped while borrowed
+    let _: &'static _ = &C3; //~ ERROR temporary value dropped while borrowed
+    let _: &'static _ = &C4; //~ ERROR temporary value dropped while borrowed
+    let _: &'static _ = &C5; //~ ERROR temporary value dropped while borrowed
+}
diff --git a/src/test/ui/consts/qualif-union.stderr b/src/test/ui/consts/qualif-union.stderr
new file mode 100644 (file)
index 0000000..fda8ad4
--- /dev/null
@@ -0,0 +1,57 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/qualif-union.rs:27:26
+   |
+LL |     let _: &'static _ = &C1;
+   |            ----------    ^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/qualif-union.rs:28:26
+   |
+LL |     let _: &'static _ = &C2;
+   |            ----------    ^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/qualif-union.rs:29:26
+   |
+LL |     let _: &'static _ = &C3;
+   |            ----------    ^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/qualif-union.rs:30:26
+   |
+LL |     let _: &'static _ = &C4;
+   |            ----------    ^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL |     let _: &'static _ = &C5;
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/qualif-union.rs:31:26
+   |
+LL |     let _: &'static _ = &C5;
+   |            ----------    ^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/crate-loading/auxiliary/libfoo.rlib b/src/test/ui/crate-loading/auxiliary/libfoo.rlib
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/test/ui/crate-loading/invalid-rlib.rs b/src/test/ui/crate-loading/invalid-rlib.rs
new file mode 100644 (file)
index 0000000..77c2909
--- /dev/null
@@ -0,0 +1,8 @@
+// compile-flags: --crate-type lib --extern foo={{src-base}}/crate-loading/auxiliary/libfoo.rlib
+// normalize-stderr-test: "failed to mmap file '.*auxiliary/libfoo.rlib':.*" -> "failed to mmap file 'auxiliary/libfoo.rlib'"
+// don't emit warn logging, it's basically the same as the errors and it's annoying to normalize
+// rustc-env:RUSTC_LOG=error
+// edition:2018
+#![no_std]
+use ::foo; //~ ERROR invalid metadata files for crate `foo`
+//~| NOTE failed to mmap file
diff --git a/src/test/ui/crate-loading/invalid-rlib.stderr b/src/test/ui/crate-loading/invalid-rlib.stderr
new file mode 100644 (file)
index 0000000..b2c79f7
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0786]: found invalid metadata files for crate `foo`
+  --> $DIR/invalid-rlib.rs:7:7
+   |
+LL | use ::foo;
+   |       ^^^
+   |
+   = note: failed to mmap file 'auxiliary/libfoo.rlib'
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0786`.
index 35e42a6857f320cfa429c639e4ae9d6069f538d2..9bde2ca1942e64c09a188bc4d2a58f835ffaa762 100644 (file)
@@ -278,6 +278,7 @@ fn test() {
         let _ = nested::DeprecatedStruct {
             //~^ ERROR use of deprecated struct `this_crate::nested::DeprecatedStruct`: text
             i: 0 //~ ERROR use of deprecated field `this_crate::nested::DeprecatedStruct::i`: text
+            //~| ERROR field `i` of struct `this_crate::nested::DeprecatedStruct` is private
         };
 
         let _ = nested::DeprecatedUnitStruct; //~ ERROR use of deprecated unit struct `this_crate::nested::DeprecatedUnitStruct`: text
index 20af4f62e6502cc78af28a3b2bf97afcd8878bd6..5d716fa625e5d47793dd0a2e878be4296b3a627f 100644 (file)
@@ -257,97 +257,97 @@ LL |         let _ = nested::DeprecatedStruct {
    |                         ^^^^^^^^^^^^^^^^
 
 error: use of deprecated unit struct `this_crate::nested::DeprecatedUnitStruct`: text
-  --> $DIR/deprecation-lint.rs:283:25
+  --> $DIR/deprecation-lint.rs:284:25
    |
 LL |         let _ = nested::DeprecatedUnitStruct;
    |                         ^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated unit variant `this_crate::nested::Enum::DeprecatedVariant`: text
-  --> $DIR/deprecation-lint.rs:285:31
+  --> $DIR/deprecation-lint.rs:286:31
    |
 LL | ...   let _ = nested::Enum::DeprecatedVariant;
    |                             ^^^^^^^^^^^^^^^^^
 
 error: use of deprecated tuple struct `this_crate::nested::DeprecatedTupleStruct`: text
-  --> $DIR/deprecation-lint.rs:287:25
+  --> $DIR/deprecation-lint.rs:288:25
    |
 LL | ...   let _ = nested::DeprecatedTupleStruct (1);
    |                       ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:292:16
+  --> $DIR/deprecation-lint.rs:293:16
    |
 LL |         Trait::trait_deprecated(&foo);
    |                ^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:294:25
+  --> $DIR/deprecation-lint.rs:295:25
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
    |                         ^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:296:16
+  --> $DIR/deprecation-lint.rs:297:16
    |
 LL |         Trait::trait_deprecated_text(&foo);
    |                ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:298:25
+  --> $DIR/deprecation-lint.rs:299:25
    |
 LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
    |                       ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated function `this_crate::test_fn_closure_body::{closure#0}::bar`
-  --> $DIR/deprecation-lint.rs:316:13
+  --> $DIR/deprecation-lint.rs:317:13
    |
 LL |             bar();
    |             ^^^
 
 error: use of deprecated trait `this_crate::DeprecatedTrait`: text
-  --> $DIR/deprecation-lint.rs:335:10
+  --> $DIR/deprecation-lint.rs:336:10
    |
 LL |     impl DeprecatedTrait for S { }
    |          ^^^^^^^^^^^^^^^
 
 error: use of deprecated trait `this_crate::DeprecatedTrait`: text
-  --> $DIR/deprecation-lint.rs:337:24
+  --> $DIR/deprecation-lint.rs:338:24
    |
 LL |     trait LocalTrait : DeprecatedTrait { }
    |                        ^^^^^^^^^^^^^^^
 
 error: use of deprecated struct `this_crate2::Deprecated`: text
-  --> $DIR/deprecation-lint.rs:389:17
+  --> $DIR/deprecation-lint.rs:390:17
    |
 LL |         let x = Deprecated {
    |                 ^^^^^^^^^^
 
 error: use of deprecated struct `this_crate2::Deprecated`: text
-  --> $DIR/deprecation-lint.rs:398:13
+  --> $DIR/deprecation-lint.rs:399:13
    |
 LL |         let Deprecated {
    |             ^^^^^^^^^^
 
 error: use of deprecated struct `this_crate2::Deprecated`: text
-  --> $DIR/deprecation-lint.rs:404:13
+  --> $DIR/deprecation-lint.rs:405:13
    |
 LL |         let Deprecated
    |             ^^^^^^^^^^
 
 error: use of deprecated tuple struct `this_crate2::Deprecated2`: text
-  --> $DIR/deprecation-lint.rs:409:17
+  --> $DIR/deprecation-lint.rs:410:17
    |
 LL |         let x = Deprecated2(1, 2, 3);
    |                 ^^^^^^^^^^^
 
 error: use of deprecated tuple struct `this_crate2::Deprecated2`: text
-  --> $DIR/deprecation-lint.rs:419:13
+  --> $DIR/deprecation-lint.rs:420:13
    |
 LL |         let Deprecated2
    |             ^^^^^^^^^^^
 
 error: use of deprecated tuple struct `this_crate2::Deprecated2`: text
-  --> $DIR/deprecation-lint.rs:428:13
+  --> $DIR/deprecation-lint.rs:429:13
    |
 LL |         let Deprecated2
    |             ^^^^^^^^^^^
@@ -617,124 +617,131 @@ LL |             i: 0
    |             ^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:291:13
+  --> $DIR/deprecation-lint.rs:292:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:293:16
+  --> $DIR/deprecation-lint.rs:294:16
    |
 LL |         <Foo>::trait_deprecated(&foo);
    |                ^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:295:13
+  --> $DIR/deprecation-lint.rs:296:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:297:16
+  --> $DIR/deprecation-lint.rs:298:16
    |
 LL |         <Foo>::trait_deprecated_text(&foo);
    |                ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:302:13
+  --> $DIR/deprecation-lint.rs:303:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:303:13
+  --> $DIR/deprecation-lint.rs:304:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated field `this_crate2::Stable::override2`: text
-  --> $DIR/deprecation-lint.rs:362:13
+  --> $DIR/deprecation-lint.rs:363:13
    |
 LL |             override2: 3,
    |             ^^^^^^^^^^^^
 
 error: use of deprecated field `this_crate2::Stable::override2`: text
-  --> $DIR/deprecation-lint.rs:366:17
+  --> $DIR/deprecation-lint.rs:367:17
    |
 LL |         let _ = x.override2;
    |                 ^^^^^^^^^^^
 
 error: use of deprecated field `this_crate2::Stable::override2`: text
-  --> $DIR/deprecation-lint.rs:370:13
+  --> $DIR/deprecation-lint.rs:371:13
    |
 LL |             override2: _
    |             ^^^^^^^^^^^^
 
 error: use of deprecated field `this_crate2::Stable2::2`: text
-  --> $DIR/deprecation-lint.rs:378:17
+  --> $DIR/deprecation-lint.rs:379:17
    |
 LL |         let _ = x.2;
    |                 ^^^
 
 error: use of deprecated field `this_crate2::Stable2::2`: text
-  --> $DIR/deprecation-lint.rs:383:20
+  --> $DIR/deprecation-lint.rs:384:20
    |
 LL |                    _)
    |                    ^
 
 error: use of deprecated field `this_crate2::Deprecated::inherit`: text
-  --> $DIR/deprecation-lint.rs:391:13
+  --> $DIR/deprecation-lint.rs:392:13
    |
 LL |             inherit: 1,
    |             ^^^^^^^^^^
 
 error: use of deprecated field `this_crate2::Deprecated::inherit`: text
-  --> $DIR/deprecation-lint.rs:395:17
+  --> $DIR/deprecation-lint.rs:396:17
    |
 LL |         let _ = x.inherit;
    |                 ^^^^^^^^^
 
 error: use of deprecated field `this_crate2::Deprecated::inherit`: text
-  --> $DIR/deprecation-lint.rs:400:13
+  --> $DIR/deprecation-lint.rs:401:13
    |
 LL |             inherit: _,
    |             ^^^^^^^^^^
 
 error: use of deprecated field `this_crate2::Deprecated2::0`: text
-  --> $DIR/deprecation-lint.rs:412:17
+  --> $DIR/deprecation-lint.rs:413:17
    |
 LL |         let _ = x.0;
    |                 ^^^
 
 error: use of deprecated field `this_crate2::Deprecated2::1`: text
-  --> $DIR/deprecation-lint.rs:414:17
+  --> $DIR/deprecation-lint.rs:415:17
    |
 LL |         let _ = x.1;
    |                 ^^^
 
 error: use of deprecated field `this_crate2::Deprecated2::2`: text
-  --> $DIR/deprecation-lint.rs:416:17
+  --> $DIR/deprecation-lint.rs:417:17
    |
 LL |         let _ = x.2;
    |                 ^^^
 
 error: use of deprecated field `this_crate2::Deprecated2::0`: text
-  --> $DIR/deprecation-lint.rs:421:14
+  --> $DIR/deprecation-lint.rs:422:14
    |
 LL |             (_,
    |              ^
 
 error: use of deprecated field `this_crate2::Deprecated2::1`: text
-  --> $DIR/deprecation-lint.rs:423:14
+  --> $DIR/deprecation-lint.rs:424:14
    |
 LL |              _,
    |              ^
 
 error: use of deprecated field `this_crate2::Deprecated2::2`: text
-  --> $DIR/deprecation-lint.rs:425:14
+  --> $DIR/deprecation-lint.rs:426:14
    |
 LL |              _)
    |              ^
 
-error: aborting due to 122 previous errors
+error[E0451]: field `i` of struct `this_crate::nested::DeprecatedStruct` is private
+  --> $DIR/deprecation-lint.rs:280:13
+   |
+LL |             i: 0
+   |             ^^^^ private field
+
+error: aborting due to 123 previous errors
 
+For more information about this error, try `rustc --explain E0451`.
diff --git a/src/test/ui/deprecation/try-macro-suggestion.rs b/src/test/ui/deprecation/try-macro-suggestion.rs
new file mode 100644 (file)
index 0000000..635ceac
--- /dev/null
@@ -0,0 +1,9 @@
+// compile-flags: --edition 2018
+fn foo() -> Result<(), ()> {
+    Ok(try!()); //~ ERROR use of deprecated `try` macro
+    Ok(try!(Ok(()))) //~ ERROR use of deprecated `try` macro
+}
+
+fn main() {
+    let _ = foo();
+}
diff --git a/src/test/ui/deprecation/try-macro-suggestion.stderr b/src/test/ui/deprecation/try-macro-suggestion.stderr
new file mode 100644 (file)
index 0000000..c7dde7e
--- /dev/null
@@ -0,0 +1,31 @@
+error: use of deprecated `try` macro
+  --> $DIR/try-macro-suggestion.rs:3:8
+   |
+LL |     Ok(try!());
+   |        ^^^^^^
+   |
+   = note: in the 2018 edition `try` is a reserved keyword, and the `try!()` macro is deprecated
+help: you can still access the deprecated `try!()` macro using the "raw identifier" syntax
+   |
+LL |     Ok(r#try!());
+   |        ++
+
+error: use of deprecated `try` macro
+  --> $DIR/try-macro-suggestion.rs:4:8
+   |
+LL |     Ok(try!(Ok(())))
+   |        ^^^^^^^^^^^^
+   |
+   = note: in the 2018 edition `try` is a reserved keyword, and the `try!()` macro is deprecated
+help: you can use the `?` operator instead
+   |
+LL -     Ok(try!(Ok(())))
+LL +     Ok(Ok(())?)
+   | 
+help: alternatively, you can still access the deprecated `try!()` macro using the "raw identifier" syntax
+   |
+LL |     Ok(r#try!(Ok(())))
+   |        ++
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/deriving/issue-19358.rs b/src/test/ui/deriving/issue-19358.rs
new file mode 100644 (file)
index 0000000..3970a41
--- /dev/null
@@ -0,0 +1,23 @@
+// run-pass
+
+#![allow(dead_code)]
+
+trait Trait { fn dummy(&self) { } }
+
+#[derive(Debug)]
+struct Foo<T: Trait> {
+    foo: T,
+}
+
+#[derive(Debug)]
+struct Bar<T> where T: Trait {
+    bar: T,
+}
+
+impl Trait for isize {}
+
+fn main() {
+    let a = Foo { foo: 12 };
+    let b = Bar { bar: 12 };
+    println!("{:?} {:?}", a, b);
+}
diff --git a/src/test/ui/deriving/issue-58319.rs b/src/test/ui/deriving/issue-58319.rs
new file mode 100644 (file)
index 0000000..757307d
--- /dev/null
@@ -0,0 +1,621 @@
+// run-pass
+fn main() {}
+#[derive(Clone)]
+pub struct Little;
+#[derive(Clone)]
+pub struct Big(
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+);
diff --git a/src/test/ui/diverging-tuple-parts-39485.rs b/src/test/ui/diverging-tuple-parts-39485.rs
deleted file mode 100644 (file)
index 0cde611..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// After #39485, this test used to pass, but that change was reverted
-// due to numerous inference failures like #39808, so it now fails
-// again. #39485 made it so that diverging types never propagate
-// upward; but we now do propagate such types upward in many more
-// cases.
-
-fn g() {
-    &panic!() //~ ERROR mismatched types
-}
-
-fn f() -> isize {
-    (return 1, return 2) //~ ERROR mismatched types
-}
-
-fn main() {}
diff --git a/src/test/ui/diverging-tuple-parts-39485.stderr b/src/test/ui/diverging-tuple-parts-39485.stderr
deleted file mode 100644 (file)
index 32967b3..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/diverging-tuple-parts-39485.rs:8:5
-   |
-LL |     &panic!()
-   |     ^^^^^^^^^ expected `()`, found reference
-   |
-   = note: expected unit type `()`
-              found reference `&_`
-help: try adding a return type
-   |
-LL | fn g() -> &_ {
-   |        +++++
-help: consider removing the borrow
-   |
-LL -     &panic!()
-LL +     panic!()
-   | 
-
-error[E0308]: mismatched types
-  --> $DIR/diverging-tuple-parts-39485.rs:12:5
-   |
-LL | fn f() -> isize {
-   |           ----- expected `isize` because of return type
-LL |     (return 1, return 2)
-   |     ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found tuple
-   |
-   = note: expected type `isize`
-             found tuple `(!, !)`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/drop/issue-35546.rs b/src/test/ui/drop/issue-35546.rs
new file mode 100644 (file)
index 0000000..004679a
--- /dev/null
@@ -0,0 +1,20 @@
+// build-pass
+#![allow(dead_code)]
+// Regression test for #35546. Check that we are able to codegen
+// this. Before we had problems because of the drop glue signature
+// around dropping a trait object (specifically, when dropping the
+// `value` field of `Node<Send>`).
+
+struct Node<T: ?Sized + Send> {
+    next: Option<Box<Node<dyn Send>>>,
+    value: T,
+}
+
+fn clear(head: &mut Option<Box<Node<dyn Send>>>) {
+    match head.take() {
+        Some(node) => *head = node.next,
+        None => (),
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/drop/terminate-in-initializer.rs b/src/test/ui/drop/terminate-in-initializer.rs
new file mode 100644 (file)
index 0000000..c9cb932
--- /dev/null
@@ -0,0 +1,33 @@
+// run-pass
+// ignore-emscripten no threads support
+
+// Issue #787
+// Don't try to clean up uninitialized locals
+
+
+use std::thread;
+
+fn test_break() { loop { let _x: Box<isize> = break; } }
+
+fn test_cont() { let mut i = 0; while i < 1 { i += 1; let _x: Box<isize> = continue; } }
+
+fn test_ret() { let _x: Box<isize> = return; }
+
+fn test_panic() {
+    fn f() { let _x: Box<isize> = panic!(); }
+    thread::spawn(move|| f() ).join().unwrap_err();
+}
+
+fn test_panic_indirect() {
+    fn f() -> ! { panic!(); }
+    fn g() { let _x: Box<isize> = f(); }
+    thread::spawn(move|| g() ).join().unwrap_err();
+}
+
+pub fn main() {
+    test_break();
+    test_cont();
+    test_ret();
+    test_panic();
+    test_panic_indirect();
+}
diff --git a/src/test/ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs b/src/test/ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs
new file mode 100644 (file)
index 0000000..23fd86a
--- /dev/null
@@ -0,0 +1,46 @@
+// run-pass
+
+// Demonstrate the use of the unguarded escape hatch with a type param in negative position
+// to assert that destructor will not access any dead data.
+//
+// Compare with ui/span/issue28498-reject-lifetime-param.rs
+
+// Demonstrate that a type param in negative position causes dropck to reject code
+// that might indirectly access previously dropped value.
+//
+// Compare with run-pass/issue28498-ugeh-with-passed-to-fn.rs
+
+#![feature(dropck_eyepatch)]
+
+#[derive(Debug)]
+struct ScribbleOnDrop(String);
+
+impl Drop for ScribbleOnDrop {
+    fn drop(&mut self) {
+        self.0 = format!("DROPPED");
+    }
+}
+
+struct Foo<T>(u32, T, Box<for <'r> fn(&'r T) -> String>);
+
+unsafe impl<#[may_dangle] T> Drop for Foo<T> {
+    fn drop(&mut self) {
+        // Use of `may_dangle` is sound, because destructor never passes a `self.1`
+        // to the callback (in `self.2`) despite having it available.
+        println!("Dropping Foo({}, _)", self.0);
+    }
+}
+
+fn callback(s: & &ScribbleOnDrop) -> String { format!("{:?}", s) }
+
+fn main() {
+    let (last_dropped, foo0);
+    let (foo1, first_dropped);
+
+    last_dropped = ScribbleOnDrop(format!("last"));
+    first_dropped = ScribbleOnDrop(format!("first"));
+    foo0 = Foo(0, &last_dropped, Box::new(callback));
+    foo1 = Foo(1, &first_dropped, Box::new(callback));
+
+    println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
+}
diff --git a/src/test/ui/editions-crate-root-2015.rs b/src/test/ui/editions-crate-root-2015.rs
deleted file mode 100644 (file)
index 4c890e3..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// edition:2015
-
-mod inner {
-    fn global_inner(_: ::nonexistant::Foo) {
-        //~^ ERROR failed to resolve: maybe a missing crate `nonexistant`?
-    }
-    fn crate_inner(_: crate::nonexistant::Foo) {
-        //~^ ERROR failed to resolve: maybe a missing crate `nonexistant`?
-    }
-
-    fn bare_global(_: ::nonexistant) {
-        //~^ ERROR cannot find type `nonexistant` in the crate root
-    }
-    fn bare_crate(_: crate::nonexistant) {
-        //~^ ERROR cannot find type `nonexistant` in the crate root
-    }
-}
-
-fn main() {
-
-}
diff --git a/src/test/ui/editions-crate-root-2015.stderr b/src/test/ui/editions-crate-root-2015.stderr
deleted file mode 100644 (file)
index f8d65fe..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-error[E0433]: failed to resolve: maybe a missing crate `nonexistant`?
-  --> $DIR/editions-crate-root-2015.rs:4:26
-   |
-LL |     fn global_inner(_: ::nonexistant::Foo) {
-   |                          ^^^^^^^^^^^ maybe a missing crate `nonexistant`?
-
-error[E0433]: failed to resolve: maybe a missing crate `nonexistant`?
-  --> $DIR/editions-crate-root-2015.rs:7:30
-   |
-LL |     fn crate_inner(_: crate::nonexistant::Foo) {
-   |                              ^^^^^^^^^^^ maybe a missing crate `nonexistant`?
-
-error[E0412]: cannot find type `nonexistant` in the crate root
-  --> $DIR/editions-crate-root-2015.rs:11:25
-   |
-LL |     fn bare_global(_: ::nonexistant) {
-   |                         ^^^^^^^^^^^ not found in the crate root
-
-error[E0412]: cannot find type `nonexistant` in the crate root
-  --> $DIR/editions-crate-root-2015.rs:14:29
-   |
-LL |     fn bare_crate(_: crate::nonexistant) {
-   |                             ^^^^^^^^^^^ not found in the crate root
-
-error: aborting due to 4 previous errors
-
-Some errors have detailed explanations: E0412, E0433.
-For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/editions/epoch-gate-feature.rs b/src/test/ui/editions/epoch-gate-feature.rs
new file mode 100644 (file)
index 0000000..5f7feb5
--- /dev/null
@@ -0,0 +1,15 @@
+// run-pass
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+// Checks if the correct registers are being used to pass arguments
+// when the sysv64 ABI is specified.
+
+#![feature(rust_2018_preview)]
+
+pub trait Foo {}
+
+// should compile without the dyn trait feature flag
+fn foo(x: &dyn Foo) {}
+
+pub fn main() {}
index 2839688f34240e05fa14f5d1f428b2ffd82c3b3c..e8c70b06513c28b59bd14e072ce4a2db784b7264 100644 (file)
@@ -1,5 +1,5 @@
 #![feature(imported_main)]
-//~^ ERROR `main` is ambiguous (glob import vs glob import in the same module)
+//~^ ERROR `main` is ambiguous
 mod m1 { pub(crate) fn main() {} }
 mod m2 { pub(crate) fn main() {} }
 
index 36cb98d94e69a23c898c77aa50e4fb2c78b4c726..8fadd0e19b395a83b3b0bbb98b3598843478dc80 100644 (file)
@@ -1,5 +1,6 @@
-error[E0659]: `main` is ambiguous (glob import vs glob import in the same module)
+error[E0659]: `main` is ambiguous
    |
+   = note: ambiguous because of multiple glob imports of a name in the same module
 note: `main` could refer to the function imported here
   --> $DIR/imported_main_conflict.rs:6:5
    |
diff --git a/src/test/ui/enum-discriminant/issue-51582.rs b/src/test/ui/enum-discriminant/issue-51582.rs
new file mode 100644 (file)
index 0000000..40a70c6
--- /dev/null
@@ -0,0 +1,18 @@
+// run-pass
+#![feature(core_intrinsics)]
+
+#[repr(i8)]
+pub enum Enum {
+    VariantA,
+    VariantB,
+}
+
+fn make_b() -> Enum { Enum::VariantB }
+
+fn main() {
+    assert_eq!(1, make_b() as i8);
+    assert_eq!(1, make_b() as u8);
+    assert_eq!(1, make_b() as i32);
+    assert_eq!(1, make_b() as u32);
+    assert_eq!(1, std::intrinsics::discriminant_value(&make_b()));
+}
diff --git a/src/test/ui/enum/issue-42747.rs b/src/test/ui/enum/issue-42747.rs
new file mode 100644 (file)
index 0000000..fec6587
--- /dev/null
@@ -0,0 +1,46 @@
+// run-pass
+macro_rules! fooN {
+    ($cur:ident $prev:ty) => {
+        #[allow(dead_code)]
+        enum $cur {
+            Empty,
+            First($prev),
+            Second($prev),
+            Third($prev),
+            Fourth($prev),
+        }
+    }
+}
+
+fooN!(Foo0 ());
+fooN!(Foo1 Foo0);
+fooN!(Foo2 Foo1);
+fooN!(Foo3 Foo2);
+fooN!(Foo4 Foo3);
+fooN!(Foo5 Foo4);
+fooN!(Foo6 Foo5);
+fooN!(Foo7 Foo6);
+fooN!(Foo8 Foo7);
+fooN!(Foo9 Foo8);
+fooN!(Foo10 Foo9);
+fooN!(Foo11 Foo10);
+fooN!(Foo12 Foo11);
+fooN!(Foo13 Foo12);
+fooN!(Foo14 Foo13);
+fooN!(Foo15 Foo14);
+fooN!(Foo16 Foo15);
+fooN!(Foo17 Foo16);
+fooN!(Foo18 Foo17);
+fooN!(Foo19 Foo18);
+fooN!(Foo20 Foo19);
+fooN!(Foo21 Foo20);
+fooN!(Foo22 Foo21);
+fooN!(Foo23 Foo22);
+fooN!(Foo24 Foo23);
+fooN!(Foo25 Foo24);
+fooN!(Foo26 Foo25);
+fooN!(Foo27 Foo26);
+
+fn main() {
+    let _foo = Foo27::Empty;
+}
diff --git a/src/test/ui/epoch-gate-feature.rs b/src/test/ui/epoch-gate-feature.rs
deleted file mode 100644 (file)
index 5f7feb5..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// run-pass
-
-#![allow(dead_code)]
-#![allow(unused_variables)]
-// Checks if the correct registers are being used to pass arguments
-// when the sysv64 ABI is specified.
-
-#![feature(rust_2018_preview)]
-
-pub trait Foo {}
-
-// should compile without the dyn trait feature flag
-fn foo(x: &dyn Foo) {}
-
-pub fn main() {}
index 2f01f54c2d1ce5863eae6ab8a82b92afdc219939..b0c73c636c62ffd0a95dfef75f82bdb1e3bb26dd 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `foo` is ambiguous (glob import vs glob import in the same module)
+error[E0659]: `foo` is ambiguous
   --> $DIR/E0659.rs:15:15
    |
 LL |     collider::foo();
    |               ^^^ ambiguous name
    |
+   = note: ambiguous because of multiple glob imports of a name in the same module
 note: `foo` could refer to the function imported here
   --> $DIR/E0659.rs:10:13
    |
index 3909b5301ade5ab672919e9d373c6692200b9d87..22792c11366ba3dda38e1d4102b264d8f2e661c9 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-// only-i686
+// only-x86
 
 trait A {
     extern "fastcall" fn test1(i: i32);
index 8ce94aa71aae6e9172fc0fbfd7be185e49a22e75..717df57ec48485d2b57e56a729927dca03abfb38 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-// only-i686
+// only-x86
 
 #![feature(abi_thiscall)]
 
index f625eb0890f05dc5efbd4b400f904b3038be6a0c..a283573c9fbd11afa437bf2884445766af3ecdbb 100644 (file)
@@ -1,7 +1,7 @@
 // run-pass
 // revisions: x64 x32
 // [x64]only-x86_64
-// [x32]only-i686
+// [x32]only-x86
 
 #![feature(abi_vectorcall)]
 
diff --git a/src/test/ui/extern/issue-28324.mir.stderr b/src/test/ui/extern/issue-28324.mir.stderr
new file mode 100644 (file)
index 0000000..aff8bf7
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: use of extern static is unsafe and requires unsafe function or block
+  --> $DIR/issue-28324.rs:8:24
+   |
+LL | pub static BAZ: u32 = *&error_message_count;
+   |                        ^^^^^^^^^^^^^^^^^^^^ use of extern static
+   |
+   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/extern/issue-28324.rs b/src/test/ui/extern/issue-28324.rs
new file mode 100644 (file)
index 0000000..fbe83e3
--- /dev/null
@@ -0,0 +1,11 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+extern "C" {
+    static error_message_count: u32;
+}
+
+pub static BAZ: u32 = *&error_message_count;
+//~^ ERROR use of extern static is unsafe and requires
+
+fn main() {}
diff --git a/src/test/ui/extern/issue-28324.thir.stderr b/src/test/ui/extern/issue-28324.thir.stderr
new file mode 100644 (file)
index 0000000..c696c35
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: use of extern static is unsafe and requires unsafe function or block
+  --> $DIR/issue-28324.rs:8:25
+   |
+LL | pub static BAZ: u32 = *&error_message_count;
+   |                         ^^^^^^^^^^^^^^^^^^^ use of extern static
+   |
+   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/feature-gates/feature-gate-asm_const.rs b/src/test/ui/feature-gates/feature-gate-asm_const.rs
new file mode 100644 (file)
index 0000000..c152b54
--- /dev/null
@@ -0,0 +1,10 @@
+// only-x86_64
+
+#![feature(asm)]
+
+fn main() {
+    unsafe {
+        asm!("mov eax, {}", const 123);
+        //~^ ERROR const operands for inline assembly are unstable
+    }
+}
diff --git a/src/test/ui/feature-gates/feature-gate-asm_const.stderr b/src/test/ui/feature-gates/feature-gate-asm_const.stderr
new file mode 100644 (file)
index 0000000..2851a9b
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0658]: const operands for inline assembly are unstable
+  --> $DIR/feature-gate-asm_const.rs:7:29
+   |
+LL |         asm!("mov eax, {}", const 123);
+   |                             ^^^^^^^^^
+   |
+   = note: see issue #72016 <https://github.com/rust-lang/rust/issues/72016> for more information
+   = help: add `#![feature(asm_const)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-asm_experimental_arch.rs b/src/test/ui/feature-gates/feature-gate-asm_experimental_arch.rs
new file mode 100644 (file)
index 0000000..53e2a4d
--- /dev/null
@@ -0,0 +1,21 @@
+// compile-flags: --target mips-unknown-linux-gnu
+// needs-llvm-components: mips
+
+#![feature(no_core, lang_items, rustc_attrs)]
+#![crate_type = "rlib"]
+#![no_core]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+unsafe fn main() {
+    asm!("");
+    //~^ ERROR inline assembly is not stable yet on this architecture
+}
diff --git a/src/test/ui/feature-gates/feature-gate-asm_experimental_arch.stderr b/src/test/ui/feature-gates/feature-gate-asm_experimental_arch.stderr
new file mode 100644 (file)
index 0000000..1b4188a
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0658]: inline assembly is not stable yet on this architecture
+  --> $DIR/feature-gate-asm_experimental_arch.rs:19:5
+   |
+LL |     asm!("");
+   |     ^^^^^^^^
+   |
+   = note: see issue #72016 <https://github.com/rust-lang/rust/issues/72016> for more information
+   = help: add `#![feature(asm_experimental_arch)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-asm_sym.rs b/src/test/ui/feature-gates/feature-gate-asm_sym.rs
new file mode 100644 (file)
index 0000000..d89c7dd
--- /dev/null
@@ -0,0 +1,10 @@
+// only-x86_64
+
+#![feature(asm)]
+
+fn main() {
+    unsafe {
+        asm!("mov eax, {}", sym main);
+        //~^ ERROR sym operands for inline assembly are unstable
+    }
+}
diff --git a/src/test/ui/feature-gates/feature-gate-asm_sym.stderr b/src/test/ui/feature-gates/feature-gate-asm_sym.stderr
new file mode 100644 (file)
index 0000000..99b61b8
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0658]: sym operands for inline assembly are unstable
+  --> $DIR/feature-gate-asm_sym.rs:7:29
+   |
+LL |         asm!("mov eax, {}", sym main);
+   |                             ^^^^^^^^
+   |
+   = note: see issue #72016 <https://github.com/rust-lang/rust/issues/72016> for more information
+   = help: add `#![feature(asm_sym)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.rs b/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.rs
deleted file mode 100644 (file)
index 0cfd0a0..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// Test that we allow unsizing even if there is an unchanged param in the
-// field getting unsized.
-struct A<T, U: ?Sized + 'static>(T, B<T, U>);
-struct B<T, U: ?Sized>(T, U);
-
-fn main() {
-    let x: A<[u32; 1], [u32; 1]> = A([0; 1], B([0; 1], [0; 1]));
-    let y: &A<[u32; 1], [u32]> = &x; //~ ERROR mismatched types
-    assert_eq!(y.1.1.len(), 1);
-}
diff --git a/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr b/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr
deleted file mode 100644 (file)
index f62def4..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/feature-gate-relaxed_struct_unsize.rs:8:34
-   |
-LL |     let y: &A<[u32; 1], [u32]> = &x;
-   |            -------------------   ^^ expected slice `[u32]`, found array `[u32; 1]`
-   |            |
-   |            expected due to this
-   |
-   = note: expected reference `&A<[u32; 1], [u32]>`
-              found reference `&A<[u32; 1], [u32; 1]>`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/for-loop-while/issue-51345.rs b/src/test/ui/for-loop-while/issue-51345.rs
new file mode 100644 (file)
index 0000000..15571e8
--- /dev/null
@@ -0,0 +1,8 @@
+// run-pass
+#![allow(unreachable_code)]
+
+fn main() {
+    let mut v = Vec::new();
+
+    loop { v.push(break) }
+}
diff --git a/src/test/ui/for-loop-while/long-while.rs b/src/test/ui/for-loop-while/long-while.rs
new file mode 100644 (file)
index 0000000..529cca7
--- /dev/null
@@ -0,0 +1,12 @@
+// run-pass
+// pretty-expanded FIXME #23616
+
+#![allow(unused_variables)]
+
+pub fn main() {
+    let mut i: isize = 0;
+    while i < 1000000 {
+        i += 1;
+        let x = 3;
+    }
+}
diff --git a/src/test/ui/foreign/nil-decl-in-foreign.rs b/src/test/ui/foreign/nil-decl-in-foreign.rs
new file mode 100644 (file)
index 0000000..f3be948
--- /dev/null
@@ -0,0 +1,14 @@
+// run-pass
+
+#![allow(improper_ctypes)]
+#![allow(dead_code)]
+// Issue #901
+// pretty-expanded FIXME #23616
+
+mod libc {
+    extern "C" {
+        pub fn printf(x: ());
+    }
+}
+
+pub fn main() {}
index 0944bf110c1b5211a74d70797d57535e1be0a576..5b94cdee7c9c7deea6fb73f325ec198a982ee5a4 100644 (file)
@@ -8,7 +8,7 @@
 // check that we don't normalize with trait defaults.
 
 trait Collection<T> {
-    type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter;
+    type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter, Self: 'iter;
     type Family: CollectionFamily;
     // Test associated type defaults with parameters
     type Sibling<U>: Collection<U> =
index f14c6dac1b1ed9d28436adfc09c4dd511baf5f68..b0f2fb3f567856e8d649f1c0ed7c3e0c4612081b 100644 (file)
@@ -8,7 +8,7 @@
 // run-pass
 
 trait Collection<T> {
-    type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter;
+    type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter, Self: 'iter;
     type Family: CollectionFamily;
     // Test associated type defaults with parameters
     type Sibling<U>: Collection<U> =
index 5d3a3a893527eec22a81d8e34129fc277116698e..d7c4dbda2644e68a6d31003e323d8a034d8ad1c9 100644 (file)
@@ -3,7 +3,7 @@
 #![feature(generic_associated_types)]
 
 pub trait X {
-    type Y<'a>;
+    type Y<'a> where Self: 'a;
     fn m(&self) -> Self::Y<'_>;
 }
 
index d238f53bde7bee4df9e2d9d28628c710c3478e31..568996e1a17aa4b8b199fad7414ed6c3b688ff17 100644 (file)
@@ -3,7 +3,7 @@
 #![feature(generic_associated_types)]
 
 trait Document {
-    type Cursor<'a>: DocCursor<'a>;
+    type Cursor<'a>: DocCursor<'a> where Self: 'a;
 
     fn cursor(&self) -> Self::Cursor<'_>;
 }
index 1dad856d5a370fd888f13e7b3e83cce8d46706ba..20c6924afa614d34d34858dd25de778fad604efa 100644 (file)
@@ -3,7 +3,7 @@
 pub trait SubTrait {}
 
 pub trait SuperTrait {
-    type SubType<'a>: SubTrait;
+    type SubType<'a>: SubTrait where Self: 'a;
 
     fn get_sub<'a>(&'a mut self) -> Self::SubType<'a>;
 }
index 0a7eb5dde6009838b44af2b5c6ff9bc75bdb03bb..64eeec1b2fcbe39c2dfbf92460a60dac57f4ac67 100644 (file)
@@ -7,7 +7,7 @@ LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruc
 note: associated type defined here, with 1 lifetime parameter: `'a`
   --> $DIR/issue-76535.rs:6:10
    |
-LL |     type SubType<'a>: SubTrait;
+LL |     type SubType<'a>: SubTrait where Self: 'a;
    |          ^^^^^^^ --
 help: add missing lifetime argument
    |
@@ -25,7 +25,7 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all
    |
 LL | pub trait SuperTrait {
    |           ---------- this trait cannot be made into an object...
-LL |     type SubType<'a>: SubTrait;
+LL |     type SubType<'a>: SubTrait where Self: 'a;
    |          ^^^^^^^ ...because it contains the generic associated type `SubType`
    = help: consider moving `SubType` to another trait
 
@@ -40,7 +40,7 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all
    |
 LL | pub trait SuperTrait {
    |           ---------- this trait cannot be made into an object...
-LL |     type SubType<'a>: SubTrait;
+LL |     type SubType<'a>: SubTrait where Self: 'a;
    |          ^^^^^^^ ...because it contains the generic associated type `SubType`
    = help: consider moving `SubType` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn SuperTrait<SubType = SubStruct<'_>>>>` for `Box<SuperStruct>`
index 7f0ac348358840c6bc0975e954cc1238345933e1..47ef38ff45d65beadccc13496883013c7420e21d 100644 (file)
@@ -17,12 +17,12 @@ fn t(&'a self) -> &'a T {
 }
 
 trait MapLike<K, V> {
-    type VRefCont<'a>: RefCont<'a, V>;
+    type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
     fn get<'a>(&'a self, key: &K) -> Option<Self::VRefCont<'a>>;
 }
 
 impl<K: Ord, V: 'static> MapLike<K, V> for std::collections::BTreeMap<K, V> {
-    type VRefCont<'a> = &'a V;
+    type VRefCont<'a> where Self: 'a = &'a V;
     fn get<'a>(&'a self, key: &K) -> Option<&'a V> {
         std::collections::BTreeMap::get(self, key)
     }
index b6f856a97e7257fcc8c5a9795e024846ff4159f9..8b6f9b866e5ef1559333c848e618ffbf80fbdb32 100644 (file)
@@ -7,7 +7,7 @@ LL |         as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
 note: associated type defined here, with 1 lifetime parameter: `'a`
   --> $DIR/issue-79422.rs:20:10
    |
-LL |     type VRefCont<'a>: RefCont<'a, V>;
+LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
    |          ^^^^^^^^ --
 help: add missing lifetime argument
    |
@@ -25,7 +25,7 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all
    |
 LL | trait MapLike<K, V> {
    |       ------- this trait cannot be made into an object...
-LL |     type VRefCont<'a>: RefCont<'a, V>;
+LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
    |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
    = help: consider moving `VRefCont` to another trait
 
@@ -40,7 +40,7 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all
    |
 LL | trait MapLike<K, V> {
    |       ------- this trait cannot be made into an object...
-LL |     type VRefCont<'a>: RefCont<'a, V>;
+LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
    |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
    = help: consider moving `VRefCont` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>>` for `Box<BTreeMap<u8, u8>>`
index f1f05ea6627e8f9282564e85d5732af2eea4488e..0f62f83e2563b15935bce74fc968ec97c56941f7 100644 (file)
@@ -9,6 +9,7 @@ enum Either<L, R> {
 pub trait HasChildrenOf {
     type T;
     type TRef<'a>;
+    //~^ Missing required bounds
 
     fn ref_children<'a>(&'a self) -> Vec<Self::TRef<'a>>;
     fn take_children(self) -> Vec<Self::T>;
@@ -20,9 +21,9 @@ impl<Left, Right> HasChildrenOf for Either<Left, Right>
     Right: HasChildrenOf,
 {
     type T = Either<Left::T, Right::T>;
+    // We used to error below because the where clause doesn't match the trait.
+    // Now, we error early on the trait itself.
     type TRef<'a>
-    //~^ `impl` associated type signature
-    //~^^ `impl` associated type signature
     where
     <Left as HasChildrenOf>::T: 'a,
     <Right as HasChildrenOf>::T: 'a
index 648eff77d73bb876abde0e156833a300d6db1494..87dcd875de703b589d4be1477ed8446f9233eb1b 100644 (file)
@@ -1,32 +1,10 @@
-error: `impl` associated type signature for `TRef` doesn't match `trait` associated type signature
-  --> $DIR/issue-86787.rs:23:5
+error: Missing required bounds on TRef
+  --> $DIR/issue-86787.rs:11:5
    |
-LL |       type TRef<'a>;
-   |       -------------- expected
-...
-LL | /     type TRef<'a>
-LL | |
-LL | |
-LL | |     where
-LL | |     <Left as HasChildrenOf>::T: 'a,
-LL | |     <Right as HasChildrenOf>::T: 'a
-LL | |     = Either<&'a Left::T, &'a Right::T>;
-   | |________________________________________^ found
+LL |     type TRef<'a>;
+   |     ^^^^^^^^^^^^^-
+   |                  |
+   |                  help: add the required where clauses: `where Self: 'a`
 
-error: `impl` associated type signature for `TRef` doesn't match `trait` associated type signature
-  --> $DIR/issue-86787.rs:23:5
-   |
-LL |       type TRef<'a>;
-   |       -------------- expected
-...
-LL | /     type TRef<'a>
-LL | |
-LL | |
-LL | |     where
-LL | |     <Left as HasChildrenOf>::T: 'a,
-LL | |     <Right as HasChildrenOf>::T: 'a
-LL | |     = Either<&'a Left::T, &'a Right::T>;
-   | |________________________________________^ found
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/generic-associated-types/issue-87258_a.rs b/src/test/ui/generic-associated-types/issue-87258_a.rs
new file mode 100644 (file)
index 0000000..d9d1775
--- /dev/null
@@ -0,0 +1,24 @@
+#![feature(type_alias_impl_trait)]
+#![feature(generic_associated_types)]
+
+// See https://github.com/rust-lang/rust/issues/87258#issuecomment-883293367
+
+trait Trait1 {}
+
+struct Struct<'b>(&'b ());
+
+impl<'d> Trait1 for Struct<'d> {}
+
+pub trait Trait2 {
+    type FooFuture<'a>: Trait1;
+    fn foo<'a>() -> Self::FooFuture<'a>;
+}
+
+impl<'c, S: Trait2> Trait2 for &'c mut S {
+    type FooFuture<'a> = impl Trait1;
+    fn foo<'a>() -> Self::FooFuture<'a> { //~ ERROR
+        Struct(unimplemented!())
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-87258_a.stderr b/src/test/ui/generic-associated-types/issue-87258_a.stderr
new file mode 100644 (file)
index 0000000..93513a4
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/issue-87258_a.rs:19:21
+   |
+LL |     fn foo<'a>() -> Self::FooFuture<'a> {
+   |                     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: hidden type `Struct<'_>` captures lifetime '_#7r
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/generic-associated-types/issue-87258_b.rs b/src/test/ui/generic-associated-types/issue-87258_b.rs
new file mode 100644 (file)
index 0000000..b29a978
--- /dev/null
@@ -0,0 +1,26 @@
+#![feature(type_alias_impl_trait)]
+#![feature(generic_associated_types)]
+
+// See https://github.com/rust-lang/rust/issues/87258#issuecomment-883293367
+
+trait Trait1 {}
+
+struct Struct<'b>(&'b ());
+
+impl<'d> Trait1 for Struct<'d> {}
+
+pub trait Trait2 {
+    type FooFuture<'a>: Trait1;
+    fn foo<'a>() -> Self::FooFuture<'a>;
+}
+
+type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1;
+
+impl<'c, S: Trait2> Trait2 for &'c mut S {
+    type FooFuture<'a> = Helper<'c, 'a, S>;
+    fn foo<'a>() -> Self::FooFuture<'a> { //~ ERROR
+        Struct(unimplemented!())
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-87258_b.stderr b/src/test/ui/generic-associated-types/issue-87258_b.stderr
new file mode 100644 (file)
index 0000000..e077a42
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/issue-87258_b.rs:21:21
+   |
+LL |     fn foo<'a>() -> Self::FooFuture<'a> {
+   |                     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: hidden type `Struct<'_>` captures lifetime '_#7r
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0700`.
index 2e65af594a6bd545cfbe1cd066e4844625f1f4d3..df5586ed422f84f0491c3330ccc6e492b33f194c 100644 (file)
@@ -13,7 +13,8 @@ trait SearchableResource<Criteria> {
 trait SearchableResourceExt<Criteria>: SearchableResource<Criteria> {
     type Future<'f, A: 'f + ?Sized, B: 'f>: Future<Output = Result<Vec<A::SearchResult>, ()>> + 'f
     where
-        A: SearchableResource<B>;
+        A: SearchableResource<B>,
+        Self: 'f;
 
     fn search<'c>(&'c self, client: &'c ()) -> Self::Future<'c, Self, Criteria>;
 }
@@ -29,6 +30,7 @@ impl<T, Criteria> SearchableResourceExt<Criteria> for T
     type Future<'f, A, B: 'f>
     where
         A: SearchableResource<B> + ?Sized + 'f,
+        Self: 'f,
     = SearchFutureTy<'f, A, B>;
 
     fn search<'c>(&'c self, _client: &'c ()) -> Self::Future<'c, Self, Criteria> {
index 06af3f5ec96d65f2d7f5c3c6c9480bc30726c62a..8ee98201aba7a79ec6624e8aa626025e403d032d 100644 (file)
@@ -1,13 +1,14 @@
 #![feature(generic_associated_types)]
 
 trait GatTrait {
-    type Gat<'a>;
+    type Gat<'a> where Self: 'a;
 
     fn test(&self) -> Self::Gat<'_>;
 }
 
 trait SuperTrait<T>
 where
+    Self: 'static,
     for<'a> Self: GatTrait<Gat<'a> = &'a T>,
 {
     fn copy(&self) -> Self::Gat<'_> where T: Copy {
index cfbf3aaa4e65d556a156915c43e7c87aa74c32ea..5f769d799faa16ab547dfd1d80a3abf54fbd11b5 100644 (file)
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-88360.rs:14:9
+  --> $DIR/issue-88360.rs:15:9
    |
 LL | trait SuperTrait<T>
    |                  - this type parameter
diff --git a/src/test/ui/generic-associated-types/issue-88459.rs b/src/test/ui/generic-associated-types/issue-88459.rs
new file mode 100644 (file)
index 0000000..3b26a18
--- /dev/null
@@ -0,0 +1,19 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+
+trait Trait {
+    type Assoc<'a>;
+}
+
+fn f<T: Trait>(_: T, _: impl Fn(T::Assoc<'_>)) {}
+
+struct Type;
+
+impl Trait for Type {
+    type Assoc<'a> = ();
+}
+
+fn main() {
+    f(Type, |_|());
+}
diff --git a/src/test/ui/generic-associated-types/issue-88595.rs b/src/test/ui/generic-associated-types/issue-88595.rs
new file mode 100644 (file)
index 0000000..e397390
--- /dev/null
@@ -0,0 +1,24 @@
+#![feature(generic_associated_types)]
+#![feature(type_alias_impl_trait)]
+
+fn main() {}
+
+trait A<'a> {
+    type B<'b>: Clone
+    // FIXME(generic_associated_types): Remove one of the below bounds
+    // https://github.com/rust-lang/rust/pull/90678#discussion_r744976085
+    where
+        'a: 'b, Self: 'a, Self: 'b;
+
+    fn a(&'a self) -> Self::B<'a>;
+}
+
+struct C;
+
+impl<'a> A<'a> for C {
+    type B<'b> = impl Clone;
+    //~^ ERROR: lifetime bound not satisfied
+    //~| ERROR: could not find defining uses
+
+    fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope
+}
diff --git a/src/test/ui/generic-associated-types/issue-88595.stderr b/src/test/ui/generic-associated-types/issue-88595.stderr
new file mode 100644 (file)
index 0000000..1948f82
--- /dev/null
@@ -0,0 +1,40 @@
+error[E0478]: lifetime bound not satisfied
+  --> $DIR/issue-88595.rs:19:5
+   |
+LL |     type B<'b> = impl Clone;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lifetime parameter instantiated with the lifetime `'a` as defined here
+  --> $DIR/issue-88595.rs:18:6
+   |
+LL | impl<'a> A<'a> for C {
+   |      ^^
+note: but lifetime parameter must outlive the lifetime `'b` as defined here
+  --> $DIR/issue-88595.rs:19:12
+   |
+LL |     type B<'b> = impl Clone;
+   |            ^^
+
+error: non-defining opaque type use in defining scope
+  --> $DIR/issue-88595.rs:23:23
+   |
+LL |     fn a(&'a self) -> Self::B<'a> {}
+   |                       ^^^^^^^^^^^
+   |
+note: lifetime used multiple times
+  --> $DIR/issue-88595.rs:18:6
+   |
+LL | impl<'a> A<'a> for C {
+   |      ^^
+LL |     type B<'b> = impl Clone;
+   |            ^^
+
+error: could not find defining uses
+  --> $DIR/issue-88595.rs:19:18
+   |
+LL |     type B<'b> = impl Clone;
+   |                  ^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0478`.
diff --git a/src/test/ui/generic-associated-types/issue-90014.rs b/src/test/ui/generic-associated-types/issue-90014.rs
new file mode 100644 (file)
index 0000000..f110b06
--- /dev/null
@@ -0,0 +1,22 @@
+// edition:2018
+
+#![feature(generic_associated_types)]
+#![feature(type_alias_impl_trait)]
+
+use std::future::Future;
+
+trait MakeFut {
+    type Fut<'a> where Self: 'a;
+    fn make_fut<'a>(&'a self) -> Self::Fut<'a>;
+}
+
+impl MakeFut for &'_ mut () {
+    type Fut<'a> = impl Future<Output = ()>;
+    //~^ ERROR: the type `&mut ()` does not fulfill the required lifetime
+
+    fn make_fut<'a>(&'a self) -> Self::Fut<'a> {
+        async { () }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-90014.stderr b/src/test/ui/generic-associated-types/issue-90014.stderr
new file mode 100644 (file)
index 0000000..125d817
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0477]: the type `&mut ()` does not fulfill the required lifetime
+  --> $DIR/issue-90014.rs:14:5
+   |
+LL |     type Fut<'a> = impl Future<Output = ()>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: type must outlive the lifetime `'a` as defined here
+  --> $DIR/issue-90014.rs:14:14
+   |
+LL |     type Fut<'a> = impl Future<Output = ()>;
+   |              ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0477`.
index b976ee3261fcc7f9569d9fc2758dd50da656a0aa..bcbcfc18996375a47fe0dd4c6024512530ce2e18 100644 (file)
@@ -1,7 +1,7 @@
 #![feature(generic_associated_types)]
 
 pub trait X {
-    type Y<'a>;
+    type Y<'a> where Self: 'a;
     fn m(&self) -> Self::Y<'_>;
 }
 
diff --git a/src/test/ui/generic-associated-types/self-outlives-lint.rs b/src/test/ui/generic-associated-types/self-outlives-lint.rs
new file mode 100644 (file)
index 0000000..af90d15
--- /dev/null
@@ -0,0 +1,173 @@
+#![feature(generic_associated_types)]
+
+// check-fail
+
+use std::fmt::Debug;
+
+// We have a `&'a self`, so we need a `Self: 'a`
+trait Iterable {
+    type Item<'x>;
+    //~^ Missing required bounds
+    fn iter<'a>(&'a self) -> Self::Item<'a>;
+}
+
+/*
+impl<T> Iterable for T {
+    type Item<'a> = &'a T;
+    fn iter<'a>(&'a self) -> Self::Item<'a> {
+        self
+    }
+}
+*/
+
+// We have a `&'a T`, so we need a `T: 'x`
+trait Deserializer<T> {
+    type Out<'x>;
+    //~^ Missing required bounds
+    fn deserialize<'a>(&self, input: &'a T) -> Self::Out<'a>;
+}
+
+/*
+impl<T> Deserializer<T> for () {
+    type Out<'a> = &'a T;
+    fn deserialize<'a>(&self, input: &'a T) -> Self::Out<'a> { input }
+}
+*/
+
+// We have a `&'b T` and a `'b: 'a`, so it is implied that `T: 'a`. Therefore, we need a `T: 'x`
+trait Deserializer2<T> {
+    type Out<'x>;
+    //~^ Missing required bounds
+    fn deserialize2<'a, 'b: 'a>(&self, input1: &'b T) -> Self::Out<'a>;
+}
+
+// We have a `&'a T` and a `&'b U`, so we need a `T: 'x` and a `U: 'y`
+trait Deserializer3<T, U> {
+    type Out<'x, 'y>;
+    //~^ Missing required bounds
+    fn deserialize2<'a, 'b>(&self, input: &'a T, input2: &'b U) -> Self::Out<'a, 'b>;
+}
+
+// `T` is a param on the function, so it can't be named by the associated type
+trait Deserializer4 {
+    type Out<'x>;
+    fn deserialize<'a, T>(&self, input: &'a T) -> Self::Out<'a>;
+}
+
+struct Wrap<T>(T);
+
+// We pass `Wrap<T>` and we see `&'z Wrap<T>`, so we require `D: 'x`
+trait Des {
+    type Out<'x, D>;
+    //~^ Missing required bounds
+    fn des<'z, T>(&self, data: &'z Wrap<T>) -> Self::Out<'z, Wrap<T>>;
+}
+/*
+impl Des for () {
+    type Out<'x, D> = &'x D; // Not okay
+    fn des<'a, T>(&self, data: &'a Wrap<T>) -> Self::Out<'a, Wrap<T>> {
+        data
+    }
+}
+*/
+
+// We have `T` and `'z` as GAT substs. Because of `&'z Wrap<T>`, there is an
+// implied bound that `T: 'z`, so we require `D: 'x`
+trait Des2 {
+    type Out<'x, D>;
+    //~^ Missing required bounds
+    fn des<'z, T>(&self, data: &'z Wrap<T>) -> Self::Out<'z, T>;
+}
+/*
+impl Des2 for () {
+    type Out<'x, D> = &'x D;
+    fn des<'a, T>(&self, data: &'a Wrap<T>) -> Self::Out<'a, T> {
+        &data.0
+    }
+}
+*/
+
+// We see `&'z T`, so we require `D: 'x`
+trait Des3 {
+    type Out<'x, D>;
+    //~^ Missing required bounds
+    fn des<'z, T>(&self, data: &'z T) -> Self::Out<'z, T>;
+}
+/*
+impl Des3 for () {
+    type Out<'x, D> = &'x D;
+    fn des<'a, T>(&self, data: &'a T) -> Self::Out<'a, T> {
+          data
+    }
+}
+*/
+
+// Similar case to before, except with GAT.
+trait NoGat<'a> {
+    type Bar;
+    fn method(&'a self) -> Self::Bar;
+}
+
+// Lifetime is not on function; except `Self: 'a`
+// FIXME: we require two bounds (`where Self: 'a, Self: 'b`) when we should only require one
+trait TraitLifetime<'a> {
+    type Bar<'b>;
+    //~^ Missing required bounds
+    fn method(&'a self) -> Self::Bar<'a>;
+}
+
+// Like above, but we have a where clause that can prove what we want
+// FIXME: we require two bounds (`where Self: 'a, Self: 'b`) when we should only require one
+trait TraitLifetimeWhere<'a> where Self: 'a {
+    type Bar<'b>;
+    //~^ Missing required bounds
+    fn method(&'a self) -> Self::Bar<'a>;
+}
+
+// Explicit bound instead of implicit; we want to still error
+trait ExplicitBound {
+    type Bar<'b>;
+    //~^ Missing required bounds
+    fn method<'b>(&self, token: &'b ()) -> Self::Bar<'b> where Self: 'b;
+}
+
+// The use of the GAT here is not in the return, we don't want to error
+trait NotInReturn {
+    type Bar<'b>;
+    fn method<'b>(&'b self) where Self::Bar<'b>: Debug;
+}
+
+// We obviously error for `Iterator`, but we should also error for `Item`
+trait IterableTwo {
+    type Item<'a>;
+    type Iterator<'a>: Iterator<Item = Self::Item<'a>>;
+    //~^ Missing required bounds
+    fn iter<'a>(&'a self) -> Self::Iterator<'a>;
+}
+
+// We also should report region outlives clauses
+trait RegionOutlives {
+    type Bar<'a, 'b>;
+    //~^ Missing required bounds
+    fn foo<'x, 'y>(&self, input: &'x &'y ()) -> Self::Bar<'x, 'y>;
+}
+
+/*
+impl Foo for () {
+    type Bar<'a, 'b> = &'a &'b ();
+    fn foo<'x, 'y>(&self, input: &'x &'y ()) -> Self::Bar<'x, 'y> {
+        input
+    }
+}
+*/
+
+// If there are multiple methods that return the GAT, require a set of clauses
+// that can be satisfied by *all* methods
+trait MultipleMethods {
+    type Bar<'me>;
+
+    fn gimme<'a>(&'a self) -> Self::Bar<'a>;
+    fn gimme_default(&self) -> Self::Bar<'static>;
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/self-outlives-lint.stderr b/src/test/ui/generic-associated-types/self-outlives-lint.stderr
new file mode 100644 (file)
index 0000000..bf85780
--- /dev/null
@@ -0,0 +1,98 @@
+error: Missing required bounds on Item
+  --> $DIR/self-outlives-lint.rs:9:5
+   |
+LL |     type Item<'x>;
+   |     ^^^^^^^^^^^^^-
+   |                  |
+   |                  help: add the required where clauses: `where Self: 'x`
+
+error: Missing required bounds on Out
+  --> $DIR/self-outlives-lint.rs:25:5
+   |
+LL |     type Out<'x>;
+   |     ^^^^^^^^^^^^-
+   |                 |
+   |                 help: add the required where clauses: `where T: 'x`
+
+error: Missing required bounds on Out
+  --> $DIR/self-outlives-lint.rs:39:5
+   |
+LL |     type Out<'x>;
+   |     ^^^^^^^^^^^^-
+   |                 |
+   |                 help: add the required where clauses: `where T: 'x`
+
+error: Missing required bounds on Out
+  --> $DIR/self-outlives-lint.rs:46:5
+   |
+LL |     type Out<'x, 'y>;
+   |     ^^^^^^^^^^^^^^^^-
+   |                     |
+   |                     help: add the required where clauses: `where T: 'x, U: 'y`
+
+error: Missing required bounds on Out
+  --> $DIR/self-outlives-lint.rs:61:5
+   |
+LL |     type Out<'x, D>;
+   |     ^^^^^^^^^^^^^^^-
+   |                    |
+   |                    help: add the required where clauses: `where D: 'x`
+
+error: Missing required bounds on Out
+  --> $DIR/self-outlives-lint.rs:77:5
+   |
+LL |     type Out<'x, D>;
+   |     ^^^^^^^^^^^^^^^-
+   |                    |
+   |                    help: add the required where clauses: `where D: 'x`
+
+error: Missing required bounds on Out
+  --> $DIR/self-outlives-lint.rs:92:5
+   |
+LL |     type Out<'x, D>;
+   |     ^^^^^^^^^^^^^^^-
+   |                    |
+   |                    help: add the required where clauses: `where D: 'x`
+
+error: Missing required bounds on Bar
+  --> $DIR/self-outlives-lint.rs:114:5
+   |
+LL |     type Bar<'b>;
+   |     ^^^^^^^^^^^^-
+   |                 |
+   |                 help: add the required where clauses: `where Self: 'a, Self: 'b`
+
+error: Missing required bounds on Bar
+  --> $DIR/self-outlives-lint.rs:122:5
+   |
+LL |     type Bar<'b>;
+   |     ^^^^^^^^^^^^-
+   |                 |
+   |                 help: add the required where clauses: `where Self: 'a, Self: 'b`
+
+error: Missing required bounds on Bar
+  --> $DIR/self-outlives-lint.rs:129:5
+   |
+LL |     type Bar<'b>;
+   |     ^^^^^^^^^^^^-
+   |                 |
+   |                 help: add the required where clauses: `where Self: 'b`
+
+error: Missing required bounds on Iterator
+  --> $DIR/self-outlives-lint.rs:143:5
+   |
+LL |     type Iterator<'a>: Iterator<Item = Self::Item<'a>>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                                       |
+   |                                                       help: add the required where clauses: `where Self: 'a`
+
+error: Missing required bounds on Bar
+  --> $DIR/self-outlives-lint.rs:150:5
+   |
+LL |     type Bar<'a, 'b>;
+   |     ^^^^^^^^^^^^^^^^-
+   |                     |
+   |                     help: add the required where clauses: `where 'a: 'b`
+
+error: aborting due to 12 previous errors
+
index 2feff9f4c6f2ff3f64e191e5ac148064fd68018a..f83d4d7b68e48ae155a5db86ae28bf2f6486654a 100644 (file)
@@ -5,12 +5,12 @@
 use std::fmt::Display;
 
 trait StreamingIterator {
-    type Item<'a>;
+    type Item<'a> where Self: 'a;
     // Applying the lifetime parameter `'a` to `Self::Item` inside the trait.
     fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>;
 }
 
-struct Foo<T: StreamingIterator> {
+struct Foo<T: StreamingIterator + 'static> {
     // Applying a concrete lifetime to the constructor outside the trait.
     bar: <T as StreamingIterator>::Item<'static>,
 }
@@ -30,7 +30,7 @@ struct StreamEnumerate<I> {
 }
 
 impl<I: StreamingIterator> StreamingIterator for StreamEnumerate<I> {
-    type Item<'a> = (usize, I::Item<'a>);
+    type Item<'a> where Self: 'a = (usize, I::Item<'a>);
     fn next<'a>(&'a mut self) -> Option<Self::Item<'a>> {
         match self.iter.next() {
             None => None,
@@ -44,7 +44,7 @@ fn next<'a>(&'a mut self) -> Option<Self::Item<'a>> {
 }
 
 impl<I: Iterator> StreamingIterator for I {
-    type Item<'a> = <I as Iterator>::Item;
+    type Item<'a> where Self: 'a = <I as Iterator>::Item;
     fn next(&mut self) -> Option<<I as StreamingIterator>::Item<'_>> {
         Iterator::next(self)
     }
index 7bc250ee87b944dc50cf4f0714923f5ce893bb4f..7d0f7638ac89dc008a5f43305440cff3c2299bb7 100644 (file)
@@ -3,7 +3,7 @@
 #![feature(generic_associated_types)]
 
 trait A {
-    type B<'a>;
+    type B<'a> where Self: 'a;
 
     fn make_b<'a>(&'a self) -> Self::B<'a>;
 }
diff --git a/src/test/ui/generics/issue-1112.rs b/src/test/ui/generics/issue-1112.rs
new file mode 100644 (file)
index 0000000..3ba7bb2
--- /dev/null
@@ -0,0 +1,37 @@
+// run-pass
+#![allow(dead_code)]
+// Issue #1112
+// Alignment of interior pointers to dynamic-size types
+
+
+struct X<T> {
+    a: T,
+    b: u8,
+    c: bool,
+    d: u8,
+    e: u16,
+    f: u8,
+    g: u8
+}
+
+pub fn main() {
+    let x: X<isize> = X {
+        a: 12345678,
+        b: 9,
+        c: true,
+        d: 10,
+        e: 11,
+        f: 12,
+        g: 13
+    };
+    bar(x);
+}
+
+fn bar<T>(x: X<T>) {
+    assert_eq!(x.b, 9);
+    assert_eq!(x.c, true);
+    assert_eq!(x.d, 10);
+    assert_eq!(x.e, 11);
+    assert_eq!(x.f, 12);
+    assert_eq!(x.g, 13);
+}
diff --git a/src/test/ui/generics/issue-333.rs b/src/test/ui/generics/issue-333.rs
new file mode 100644 (file)
index 0000000..0753aaa
--- /dev/null
@@ -0,0 +1,7 @@
+// run-pass
+
+fn quux<T>(x: T) -> T { let f = id::<T>; return f(x); }
+
+fn id<T>(x: T) -> T { return x; }
+
+pub fn main() { assert_eq!(quux(10), 10); }
diff --git a/src/test/ui/generics/issue-59508-1.rs b/src/test/ui/generics/issue-59508-1.rs
new file mode 100644 (file)
index 0000000..6376c42
--- /dev/null
@@ -0,0 +1,17 @@
+#![allow(dead_code)]
+#![feature(const_generics_defaults)]
+
+// This test checks that generic parameter re-ordering diagnostic suggestions mention that
+// consts come after types and lifetimes when the `const_generics_defaults` feature is enabled.
+// We cannot run rustfix on this test because of the above const generics warning.
+
+struct A;
+
+impl A {
+    pub fn do_things<T, 'a, 'b: 'a>() {
+    //~^ ERROR lifetime parameters must be declared prior to type parameters
+        println!("panic");
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/generics/issue-59508-1.stderr b/src/test/ui/generics/issue-59508-1.stderr
new file mode 100644 (file)
index 0000000..df244f0
--- /dev/null
@@ -0,0 +1,8 @@
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/issue-59508-1.rs:11:25
+   |
+LL |     pub fn do_things<T, 'a, 'b: 'a>() {
+   |                     ----^^--^^----- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b: 'a, T>`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/generics/issue-59508.fixed b/src/test/ui/generics/issue-59508.fixed
new file mode 100644 (file)
index 0000000..b5c60a1
--- /dev/null
@@ -0,0 +1,16 @@
+// run-rustfix
+
+#![allow(dead_code)]
+
+// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds.
+
+struct A;
+
+impl A {
+    pub fn do_things<'a, 'b: 'a, T>() {
+    //~^ ERROR lifetime parameters must be declared prior to type parameters
+        println!("panic");
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/generics/issue-59508.rs b/src/test/ui/generics/issue-59508.rs
new file mode 100644 (file)
index 0000000..0b39c5d
--- /dev/null
@@ -0,0 +1,16 @@
+// run-rustfix
+
+#![allow(dead_code)]
+
+// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds.
+
+struct A;
+
+impl A {
+    pub fn do_things<T, 'a, 'b: 'a>() {
+    //~^ ERROR lifetime parameters must be declared prior to type parameters
+        println!("panic");
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/generics/issue-59508.stderr b/src/test/ui/generics/issue-59508.stderr
new file mode 100644 (file)
index 0000000..33e967c
--- /dev/null
@@ -0,0 +1,8 @@
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/issue-59508.rs:10:25
+   |
+LL |     pub fn do_things<T, 'a, 'b: 'a>() {
+   |                     ----^^--^^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b: 'a, T>`
+
+error: aborting due to previous error
+
index 738f151b0f60b17c8aee1845f5123bb30114a8b2..134d8af5bfb8aba42320695460111a4b87ca45cf 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 // edition:2021
-// compile-flags: -Zunstable-options
 
 fn main() {
     println!("hello, 2021");
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-60283.rs b/src/test/ui/higher-rank-trait-bounds/issue-60283.rs
new file mode 100644 (file)
index 0000000..c63b154
--- /dev/null
@@ -0,0 +1,20 @@
+pub trait Trait<'a> {
+    type Item;
+}
+
+impl<'a> Trait<'a> for () {
+    type Item = ();
+}
+
+pub fn foo<T, F>(_: T, _: F)
+where
+    T: for<'a> Trait<'a>,
+    F: for<'a> FnMut(<T as Trait<'a>>::Item),
+{
+}
+
+fn main() {
+    foo((), drop)
+    //~^ ERROR type mismatch in function arguments
+    //~| ERROR size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-60283.stderr b/src/test/ui/higher-rank-trait-bounds/issue-60283.stderr
new file mode 100644 (file)
index 0000000..34893cd
--- /dev/null
@@ -0,0 +1,42 @@
+error[E0631]: type mismatch in function arguments
+  --> $DIR/issue-60283.rs:17:13
+   |
+LL |     foo((), drop)
+   |     ---     ^^^^
+   |     |       |
+   |     |       expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _`
+   |     |       found signature of `fn(()) -> _`
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `foo`
+  --> $DIR/issue-60283.rs:12:16
+   |
+LL | pub fn foo<T, F>(_: T, _: F)
+   |        --- required by a bound in this
+...
+LL |     F: for<'a> FnMut(<T as Trait<'a>>::Item),
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`
+
+error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time
+  --> $DIR/issue-60283.rs:17:13
+   |
+LL |     foo((), drop)
+   |     ---     ^^^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Sized` is not implemented for `<() as Trait<'_>>::Item`
+note: required by a bound in `std::mem::drop`
+  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+   |
+LL | pub fn drop<T>(_x: T) {}
+   |             ^ required by this bound in `std::mem::drop`
+help: consider further restricting the associated type
+   |
+LL | fn main() where <() as Trait<'_>>::Item: Sized {
+   |           ++++++++++++++++++++++++++++++++++++
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0631.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs
new file mode 100644 (file)
index 0000000..f255eac
--- /dev/null
@@ -0,0 +1,31 @@
+// check-pass
+
+pub trait Foo<'a> {
+    type Bar;
+    fn foo(&'a self) -> Self::Bar;
+}
+
+impl<'a, 'b, T: 'a> Foo<'a> for &'b T {
+    type Bar = &'a T;
+    fn foo(&'a self) -> &'a T {
+        self
+    }
+}
+
+pub fn uncallable<T, F>(x: T, f: F)
+where
+    T: for<'a> Foo<'a>,
+    F: for<'a> Fn(<T as Foo<'a>>::Bar),
+{
+    f(x.foo());
+}
+
+pub fn catalyst(x: &i32) {
+    broken(x, |_| {})
+}
+
+pub fn broken<F: Fn(&i32)>(x: &i32, f: F) {
+    uncallable(x, |y| f(y));
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs
new file mode 100644 (file)
index 0000000..768d1c3
--- /dev/null
@@ -0,0 +1,13 @@
+// check-pass
+
+fn foo<T>(t: T) -> usize
+where
+    for<'a> &'a T: IntoIterator,
+    for<'a> <&'a T as IntoIterator>::IntoIter: ExactSizeIterator,
+{
+    t.into_iter().len()
+}
+
+fn main() {
+    foo::<Vec<u32>>(vec![]);
+}
index 24ac566f9df0c646061a912dbc1ad503a560f096..7c3c72e04cb781d32091328e33310422e858e473 100644 (file)
@@ -77,7 +77,7 @@ fn task<P>(processor: P) -> Task
 }
 
 fn main() {
-    task(annotate( //~ type mismatch
+    task(annotate(
         //~^ the size
         //~^^ the trait bound
         Annotate::<RefMutFamily<usize>>::new(),
index b13226fef6e76fe7ada4ad5948fa3f7428d26faa..01b14660b6531aa98a6f17f289e90aba6d632ebb 100644 (file)
@@ -1,29 +1,3 @@
-error[E0631]: type mismatch in closure arguments
-  --> $DIR/issue-62529-1.rs:80:10
-   |
-LL |       task(annotate(
-   |  _____----_^
-   | |     |
-   | |     required by a bound introduced by this call
-LL | |
-LL | |
-LL | |         Annotate::<RefMutFamily<usize>>::new(),
-LL | |         |value: &mut usize| {
-   | |         ------------------- found signature of `for<'r> fn(&'r mut usize) -> _`
-LL | |             *value = 2;
-LL | |         }
-LL | |     ));
-   | |_____^ expected signature of `for<'r> fn(<RefMutFamily<usize> as FamilyLt<'r>>::Out) -> _`
-   |
-note: required by a bound in `annotate`
-  --> $DIR/issue-62529-1.rs:44:8
-   |
-LL | fn annotate<F, Q>(_q: Annotate<Q>, func: F) -> impl Execute + 'static
-   |    -------- required by a bound in this
-LL | where
-LL |     F: for<'r> FnOnce(<<Q as Inject>::I as FamilyLt<'r>>::Out) + 'static,
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `annotate`
-
 error[E0277]: the size for values of type `impl Execute` cannot be known at compilation time
   --> $DIR/issue-62529-1.rs:80:10
    |
@@ -73,7 +47,6 @@ LL | fn task<P>(processor: P) -> Task
 LL | where P: Execute + 'static {
    |          ^^^^^^^ required by this bound in `task`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0277, E0631.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0277`.
index 87d1a250f7ae6dd3b47729605b0ae210272f65e2..3ced40230f012033de6307c24ac43f1001144b1a 100644 (file)
@@ -1,3 +1,5 @@
+// check-pass
+
 pub trait MyTrait<'a> {
     type Output: 'a;
     fn gimme_value(&self) -> Self::Output;
@@ -23,7 +25,7 @@ fn meow<T, F>(t: T, f: F)
 
 fn main() {
     let struc = MyStruct;
-    meow(struc, |foo| { //~ type mismatch
+    meow(struc, |foo| {
         println!("{:?}", foo);
     })
 }
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr
deleted file mode 100644 (file)
index efc9568..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0631]: type mismatch in closure arguments
-  --> $DIR/issue-70120.rs:26:5
-   |
-LL |     meow(struc, |foo| {
-   |     ^^^^        ----- found signature of `for<'r> fn(&'r usize) -> _`
-   |     |
-   |     expected signature of `for<'any2> fn(<MyStruct as MyTrait<'any2>>::Output) -> _`
-   |
-note: required by a bound in `meow`
-  --> $DIR/issue-70120.rs:18:8
-   |
-LL | fn meow<T, F>(t: T, f: F)
-   |    ---- required by a bound in this
-...
-LL |     F: for<'any2> Fn(<T as MyTrait<'any2>>::Output),
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `meow`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr
new file mode 100644 (file)
index 0000000..119cec1
--- /dev/null
@@ -0,0 +1,92 @@
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:52:5
+   |
+LL |     foo(bar, "string", |s| s.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:52:5
+   |
+LL |     foo(bar, "string", |s| s.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:52:5
+   |
+LL |     foo(bar, "string", |s| s.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:52:5
+   |
+LL |     foo(bar, "string", |s| s.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:52:5
+   |
+LL |     foo(bar, "string", |s| s.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:58:5
+   |
+LL |     foo(baz, "string", |s| s.0.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:58:5
+   |
+LL |     foo(baz, "string", |s| s.0.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:58:5
+   |
+LL |     foo(baz, "string", |s| s.0.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:58:5
+   |
+LL |     foo(baz, "string", |s| s.0.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:58:5
+   |
+LL |     foo(baz, "string", |s| s.0.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.nll.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.nll.stderr
new file mode 100644 (file)
index 0000000..69ab446
--- /dev/null
@@ -0,0 +1,8 @@
+error: fatal error triggered by #[rustc_error]
+  --> $DIR/issue-71955.rs:42:1
+   |
+LL | fn main() {
+   | ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs
new file mode 100644 (file)
index 0000000..95e3b3d
--- /dev/null
@@ -0,0 +1,64 @@
+// ignore-compare-mode-nll
+// revisions: migrate nll
+// [nll]compile-flags: -Zborrowck=mir
+// check-fail
+
+#![feature(rustc_attrs)]
+
+trait Parser<'s> {
+    type Output;
+
+    fn call(&self, input: &'s str) -> (&'s str, Self::Output);
+}
+
+impl<'s, F, T> Parser<'s> for F
+where F: Fn(&'s str) -> (&'s str, T) {
+    type Output = T;
+    fn call(&self, input: &'s str) -> (&'s str, T) {
+        self(input)
+    }
+}
+
+fn foo<F1, F2>(
+    f1: F1,
+    base: &'static str,
+    f2: F2
+)
+where
+    F1: for<'a> Parser<'a>,
+    F2: FnOnce(&<F1 as Parser>::Output) -> bool
+{
+    let s: String = base.to_owned();
+    let str_ref = s.as_ref();
+    let (remaining, produced) = f1.call(str_ref);
+    assert!(f2(&produced));
+    assert_eq!(remaining.len(), 0);
+}
+
+struct Wrapper<'a>(&'a str);
+
+// Because nll currently succeeds and migrate doesn't
+#[rustc_error]
+fn main() {
+    //[nll]~^ fatal
+    fn bar<'a>(s: &'a str) -> (&'a str, &'a str) {
+        (&s[..1], &s[..])
+    }
+
+    fn baz<'a>(s: &'a str) -> (&'a str, Wrapper<'a>) {
+        (&s[..1], Wrapper(&s[..]))
+    }
+
+    foo(bar, "string", |s| s.len() == 5);
+    //[migrate]~^ ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    foo(baz, "string", |s| s.0.len() == 5);
+    //[migrate]~^ ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs
new file mode 100644 (file)
index 0000000..93ccb42
--- /dev/null
@@ -0,0 +1,30 @@
+// check-pass
+
+use std::marker::PhantomData;
+
+trait A<'a> {
+    type B;
+    fn b(self) -> Self::B;
+}
+
+struct T;
+struct S<'a>(PhantomData<&'a ()>);
+
+impl<'a> A<'a> for T {
+    type B = S<'a>;
+    fn b(self) -> Self::B {
+        S(PhantomData)
+    }
+}
+
+fn s<TT, F>(t: TT, f: F)
+where
+    TT: for<'a> A<'a>,
+    F: for<'a> FnOnce(<TT as A<'a>>::B)
+{
+    f(t.b());
+}
+
+fn main() {
+    s(T, |_| {});
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-76956.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-76956.rs
new file mode 100644 (file)
index 0000000..5834700
--- /dev/null
@@ -0,0 +1,15 @@
+// check-pass
+
+use std::ops::Deref;
+
+struct Data {
+    boxed: Box<&'static i32>
+}
+
+impl Data {
+    fn use_data(&self, user: impl for <'a> FnOnce(<Box<&'a i32> as Deref>::Target)) {
+        user(*self.boxed)
+    }
+}
+
+fn main() {}
index 454d7e5e9cdea8c97c43968bcb2ff226ed3bb8ae..80f099ce3c80210324aa02e897c43382779c0182 100644 (file)
@@ -37,8 +37,8 @@ trait Ty<'a> {
 fn main() {
     let v = Unit2.m(
         //~^ ERROR type mismatch
-        //~| ERROR type mismatch
         L {
+        //~^ ERROR type mismatch
             f : |x| { drop(x); Unit4 }
         });
 }
index 97f53bc70e44eeef6feea6ca9d9afd13fd83aa10..4c5c59c22099ae2abbfec71ff4d2900719a22e9e 100644 (file)
@@ -10,10 +10,16 @@ LL |     let v = Unit2.m(
    = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 
 error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39] as FnOnce<((&'r u8,),)>>::Output == Unit3`
-  --> $DIR/issue-62203-hrtb-ice.rs:38:19
+  --> $DIR/issue-62203-hrtb-ice.rs:40:9
    |
-LL |     let v = Unit2.m(
-   |                   ^ expected struct `Unit4`, found struct `Unit3`
+LL |       let v = Unit2.m(
+   |                     - required by a bound introduced by this call
+LL |
+LL | /         L {
+LL | |
+LL | |             f : |x| { drop(x); Unit4 }
+LL | |         });
+   | |_________^ expected struct `Unit4`, found struct `Unit3`
    |
 note: required because of the requirements on the impl of `for<'r> T0<'r, (&'r u8,)>` for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39]>`
   --> $DIR/issue-62203-hrtb-ice.rs:17:16
diff --git a/src/test/ui/hrtb/issue-90177.rs b/src/test/ui/hrtb/issue-90177.rs
new file mode 100644 (file)
index 0000000..b151a9d
--- /dev/null
@@ -0,0 +1,32 @@
+// check-pass
+
+trait Base<'f> {
+    type Assoc;
+
+    fn do_something(&self);
+}
+
+trait ForAnyLifetime: for<'f> Base<'f> {}
+
+impl<T> ForAnyLifetime for T where T: for<'f> Base<'f> {}
+
+trait CanBeDynamic: ForAnyLifetime + for<'f> Base<'f, Assoc = ()> {}
+
+fn foo(a: &dyn CanBeDynamic) {
+    a.do_something();
+}
+
+struct S;
+
+impl<'a> Base<'a> for S {
+    type Assoc = ();
+
+    fn do_something(&self) {}
+}
+
+impl CanBeDynamic for S {}
+
+fn main() {
+    let s = S;
+    foo(&s);
+}
diff --git a/src/test/ui/hygiene/auxiliary/fields.rs b/src/test/ui/hygiene/auxiliary/fields.rs
new file mode 100644 (file)
index 0000000..733d11a
--- /dev/null
@@ -0,0 +1,73 @@
+#![feature(decl_macro)]
+
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub enum Field {
+    RootCtxt,
+    MacroCtxt,
+}
+
+#[rustfmt::skip]
+macro x(
+    $macro_name:ident,
+    $macro2_name:ident,
+    $type_name:ident,
+    $field_name:ident,
+    $const_name:ident
+) {
+    #[derive(Copy, Clone)]
+    pub struct $type_name {
+        pub field: Field,
+        pub $field_name: Field,
+    }
+
+    pub const $const_name: $type_name =
+        $type_name { field: Field::MacroCtxt, $field_name: Field::RootCtxt };
+
+    #[macro_export]
+    macro_rules! $macro_name {
+        (check_fields_of $e:expr) => {{
+            let e = $e;
+            assert_eq!(e.field, Field::MacroCtxt);
+            assert_eq!(e.$field_name, Field::RootCtxt);
+        }};
+        (check_fields) => {{
+            assert_eq!($const_name.field, Field::MacroCtxt);
+            assert_eq!($const_name.$field_name, Field::RootCtxt);
+        }};
+        (construct) => {
+            $type_name { field: Field::MacroCtxt, $field_name: Field::RootCtxt }
+        };
+    }
+
+    pub macro $macro2_name {
+        (check_fields_of $e:expr) => {{
+            let e = $e;
+            assert_eq!(e.field, Field::MacroCtxt);
+            assert_eq!(e.$field_name, Field::RootCtxt);
+        }},
+        (check_fields) => {{
+            assert_eq!($const_name.field, Field::MacroCtxt);
+            assert_eq!($const_name.$field_name, Field::RootCtxt);
+        }},
+        (construct) => {
+            $type_name { field: Field::MacroCtxt, $field_name: Field::RootCtxt }
+        }
+    }
+}
+
+x!(test_fields, test_fields2, MyStruct, field, MY_CONST);
+
+pub fn check_fields(s: MyStruct) {
+    test_fields!(check_fields_of s);
+}
+
+pub fn check_fields_local() {
+    test_fields!(check_fields);
+    test_fields2!(check_fields);
+
+    let s1 = test_fields!(construct);
+    test_fields!(check_fields_of s1);
+
+    let s2 = test_fields2!(construct);
+    test_fields2!(check_fields_of s2);
+}
diff --git a/src/test/ui/hygiene/auxiliary/methods.rs b/src/test/ui/hygiene/auxiliary/methods.rs
new file mode 100644 (file)
index 0000000..23b9c61
--- /dev/null
@@ -0,0 +1,160 @@
+#![feature(decl_macro)]
+
+#[derive(PartialEq, Eq, Debug)]
+pub enum Method {
+    DefaultMacroCtxt,
+    DefaultRootCtxt,
+    OverrideMacroCtxt,
+    OverrideRootCtxt,
+}
+
+#[rustfmt::skip]
+macro x($macro_name:ident, $macro2_name:ident, $trait_name:ident, $method_name:ident) {
+    pub trait $trait_name {
+        fn method(&self) -> Method {
+            Method::DefaultMacroCtxt
+        }
+
+        fn $method_name(&self) -> Method {
+            Method::DefaultRootCtxt
+        }
+    }
+
+    impl $trait_name for () {}
+    impl $trait_name for bool {
+        fn method(&self) -> Method {
+            Method::OverrideMacroCtxt
+        }
+
+        fn $method_name(&self) -> Method {
+            Method::OverrideRootCtxt
+        }
+    }
+
+    #[macro_export]
+    macro_rules! $macro_name {
+        (check_resolutions) => {
+            assert_eq!(().method(), Method::DefaultMacroCtxt);
+            assert_eq!($trait_name::method(&()), Method::DefaultMacroCtxt);
+            assert_eq!(().$method_name(), Method::DefaultRootCtxt);
+            assert_eq!($trait_name::$method_name(&()), Method::DefaultRootCtxt);
+
+            assert_eq!(false.method(), Method::OverrideMacroCtxt);
+            assert_eq!($trait_name::method(&false), Method::OverrideMacroCtxt);
+            assert_eq!(false.$method_name(), Method::OverrideRootCtxt);
+            assert_eq!($trait_name::$method_name(&false), Method::OverrideRootCtxt);
+
+            assert_eq!('a'.method(), Method::DefaultMacroCtxt);
+            assert_eq!($trait_name::method(&'a'), Method::DefaultMacroCtxt);
+            assert_eq!('a'.$method_name(), Method::DefaultRootCtxt);
+            assert_eq!($trait_name::$method_name(&'a'), Method::DefaultRootCtxt);
+
+            assert_eq!(1i32.method(), Method::OverrideMacroCtxt);
+            assert_eq!($trait_name::method(&1i32), Method::OverrideMacroCtxt);
+            assert_eq!(1i32.$method_name(), Method::OverrideRootCtxt);
+            assert_eq!($trait_name::$method_name(&1i32), Method::OverrideRootCtxt);
+
+            assert_eq!(1i64.method(), Method::OverrideMacroCtxt);
+            assert_eq!($trait_name::method(&1i64), Method::OverrideMacroCtxt);
+            assert_eq!(1i64.$method_name(), Method::OverrideRootCtxt);
+            assert_eq!($trait_name::$method_name(&1i64), Method::OverrideRootCtxt);
+        };
+        (assert_no_override $v:expr) => {
+            assert_eq!($v.method(), Method::DefaultMacroCtxt);
+            assert_eq!($trait_name::method(&$v), Method::DefaultMacroCtxt);
+            assert_eq!($v.$method_name(), Method::DefaultRootCtxt);
+            assert_eq!($trait_name::$method_name(&$v), Method::DefaultRootCtxt);
+        };
+        (assert_override $v:expr) => {
+            assert_eq!($v.method(), Method::OverrideMacroCtxt);
+            assert_eq!($trait_name::method(&$v), Method::OverrideMacroCtxt);
+            assert_eq!($v.$method_name(), Method::OverrideRootCtxt);
+            assert_eq!($trait_name::$method_name(&$v), Method::OverrideRootCtxt);
+        };
+        (impl for $t:ty) => {
+            impl $trait_name for $t {
+                fn method(&self) -> Method {
+                    Method::OverrideMacroCtxt
+                }
+
+                fn $method_name(&self) -> Method {
+                    Method::OverrideRootCtxt
+                }
+            }
+        };
+    }
+
+    pub macro $macro2_name {
+        (check_resolutions) => {
+            assert_eq!(().method(), Method::DefaultMacroCtxt);
+            assert_eq!($trait_name::method(&()), Method::DefaultMacroCtxt);
+            assert_eq!(().$method_name(), Method::DefaultRootCtxt);
+            assert_eq!($trait_name::$method_name(&()), Method::DefaultRootCtxt);
+
+            assert_eq!(false.method(), Method::OverrideMacroCtxt);
+            assert_eq!($trait_name::method(&false), Method::OverrideMacroCtxt);
+            assert_eq!(false.$method_name(), Method::OverrideRootCtxt);
+            assert_eq!($trait_name::$method_name(&false), Method::OverrideRootCtxt);
+
+            assert_eq!('a'.method(), Method::DefaultMacroCtxt);
+            assert_eq!($trait_name::method(&'a'), Method::DefaultMacroCtxt);
+            assert_eq!('a'.$method_name(), Method::DefaultRootCtxt);
+            assert_eq!($trait_name::$method_name(&'a'), Method::DefaultRootCtxt);
+
+            assert_eq!(1i32.method(), Method::OverrideMacroCtxt);
+            assert_eq!($trait_name::method(&1i32), Method::OverrideMacroCtxt);
+            assert_eq!(1i32.$method_name(), Method::OverrideRootCtxt);
+            assert_eq!($trait_name::$method_name(&1i32), Method::OverrideRootCtxt);
+
+            assert_eq!(1i64.method(), Method::OverrideMacroCtxt);
+            assert_eq!($trait_name::method(&1i64), Method::OverrideMacroCtxt);
+            assert_eq!(1i64.$method_name(), Method::OverrideRootCtxt);
+            assert_eq!($trait_name::$method_name(&1i64), Method::OverrideRootCtxt);
+        },
+        (assert_no_override $v:expr) => {
+            assert_eq!($v.method(), Method::DefaultMacroCtxt);
+            assert_eq!($trait_name::method(&$v), Method::DefaultMacroCtxt);
+            assert_eq!($v.$method_name(), Method::DefaultRootCtxt);
+            assert_eq!($trait_name::$method_name(&$v), Method::DefaultRootCtxt);
+        },
+        (assert_override $v:expr) => {
+            assert_eq!($v.method(), Method::OverrideMacroCtxt);
+            assert_eq!($trait_name::method(&$v), Method::OverrideMacroCtxt);
+            assert_eq!($v.$method_name(), Method::OverrideRootCtxt);
+            assert_eq!($trait_name::$method_name(&$v), Method::OverrideRootCtxt);
+        },
+        (impl for $t:ty) => {
+            impl $trait_name for $t {
+                fn method(&self) -> Method {
+                    Method::OverrideMacroCtxt
+                }
+
+                fn $method_name(&self) -> Method {
+                    Method::OverrideRootCtxt
+                }
+            }
+        }
+    }
+}
+
+x!(test_trait, test_trait2, MyTrait, method);
+
+impl MyTrait for char {}
+test_trait!(impl for i32);
+test_trait2!(impl for i64);
+
+pub fn check_crate_local() {
+    test_trait!(check_resolutions);
+    test_trait2!(check_resolutions);
+}
+
+// Check that any comparison of idents at monomorphization time is correct
+pub fn check_crate_local_generic<T: MyTrait, U: MyTrait>(t: T, u: U) {
+    test_trait!(check_resolutions);
+    test_trait2!(check_resolutions);
+
+    test_trait!(assert_no_override t);
+    test_trait2!(assert_no_override t);
+    test_trait!(assert_override u);
+    test_trait2!(assert_override u);
+}
diff --git a/src/test/ui/hygiene/auxiliary/pub_hygiene.rs b/src/test/ui/hygiene/auxiliary/pub_hygiene.rs
new file mode 100644 (file)
index 0000000..47e76a6
--- /dev/null
@@ -0,0 +1,7 @@
+#![feature(decl_macro)]
+
+macro x() {
+    pub struct MyStruct;
+}
+
+x!();
diff --git a/src/test/ui/hygiene/auxiliary/use_by_macro.rs b/src/test/ui/hygiene/auxiliary/use_by_macro.rs
new file mode 100644 (file)
index 0000000..791cf03
--- /dev/null
@@ -0,0 +1,15 @@
+#![feature(decl_macro)]
+
+macro x($macro_name:ident) {
+    #[macro_export]
+    macro_rules! $macro_name {
+        (define) => {
+            pub struct MyStruct;
+        };
+        (create) => {
+            MyStruct {}
+        };
+    }
+}
+
+x!(my_struct);
diff --git a/src/test/ui/hygiene/auxiliary/variants.rs b/src/test/ui/hygiene/auxiliary/variants.rs
new file mode 100644 (file)
index 0000000..dbfcce1
--- /dev/null
@@ -0,0 +1,36 @@
+#![feature(decl_macro)]
+
+#[rustfmt::skip]
+macro x($macro_name:ident, $macro2_name:ident, $type_name:ident, $variant_name:ident) {
+    #[repr(u8)]
+    pub enum $type_name {
+        Variant = 0,
+        $variant_name = 1,
+    }
+
+    #[macro_export]
+    macro_rules! $macro_name {
+        () => {{
+            assert_eq!($type_name::Variant as u8, 0);
+            assert_eq!($type_name::$variant_name as u8, 1);
+            assert_eq!(<$type_name>::Variant as u8, 0);
+            assert_eq!(<$type_name>::$variant_name as u8, 1);
+        }};
+    }
+
+    pub macro $macro2_name {
+        () => {{
+            assert_eq!($type_name::Variant as u8, 0);
+            assert_eq!($type_name::$variant_name as u8, 1);
+            assert_eq!(<$type_name>::Variant as u8, 0);
+            assert_eq!(<$type_name>::$variant_name as u8, 1);
+        }},
+    }
+}
+
+x!(test_variants, test_variants2, MyEnum, Variant);
+
+pub fn check_variants() {
+    test_variants!();
+    test_variants2!();
+}
diff --git a/src/test/ui/hygiene/cross-crate-define-and-use.rs b/src/test/ui/hygiene/cross-crate-define-and-use.rs
new file mode 100644 (file)
index 0000000..94f1adf
--- /dev/null
@@ -0,0 +1,19 @@
+// Check that a marco from another crate can define an item in one expansion
+// and use it from another, without it being visible to everyone.
+// This requires that the definition of `my_struct` preserves the hygiene
+// information for the tokens in its definition.
+
+// check-pass
+// aux-build:use_by_macro.rs
+
+#![feature(type_name_of_val)]
+extern crate use_by_macro;
+
+use use_by_macro::*;
+
+enum MyStruct {}
+my_struct!(define);
+
+fn main() {
+    let x = my_struct!(create);
+}
diff --git a/src/test/ui/hygiene/cross-crate-fields.rs b/src/test/ui/hygiene/cross-crate-fields.rs
new file mode 100644 (file)
index 0000000..1bcd645
--- /dev/null
@@ -0,0 +1,24 @@
+// Test that fields on a struct defined in another crate are resolved correctly
+// their names differ only in `SyntaxContext`.
+
+// run-pass
+// aux-build:fields.rs
+
+extern crate fields;
+
+use fields::*;
+
+fn main() {
+    check_fields_local();
+
+    test_fields!(check_fields);
+    test_fields2!(check_fields);
+
+    let s1 = test_fields!(construct);
+    check_fields(s1);
+    test_fields!(check_fields_of s1);
+
+    let s2 = test_fields2!(construct);
+    check_fields(s2);
+    test_fields2!(check_fields_of s2);
+}
diff --git a/src/test/ui/hygiene/cross-crate-glob-hygiene.rs b/src/test/ui/hygiene/cross-crate-glob-hygiene.rs
new file mode 100644 (file)
index 0000000..de55766
--- /dev/null
@@ -0,0 +1,23 @@
+// Check that globs cannot import hygienic identifiers from a macro expansion
+// in another crate. `my_struct` is a `macro_rules` macro, so the struct it
+// defines is only not imported because `my_struct` is defined by a macros 2.0
+// macro.
+
+// aux-build:use_by_macro.rs
+
+extern crate use_by_macro;
+
+use use_by_macro::*;
+
+mod m {
+    use use_by_macro::*;
+
+    my_struct!(define);
+}
+
+use m::*;
+
+fn main() {
+    let x = my_struct!(create);
+    //~^ ERROR cannot find struct, variant or union type `MyStruct` in this scope
+}
diff --git a/src/test/ui/hygiene/cross-crate-glob-hygiene.stderr b/src/test/ui/hygiene/cross-crate-glob-hygiene.stderr
new file mode 100644 (file)
index 0000000..7369e77
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0422]: cannot find struct, variant or union type `MyStruct` in this scope
+  --> $DIR/cross-crate-glob-hygiene.rs:21:13
+   |
+LL |     let x = my_struct!(create);
+   |             ^^^^^^^^^^^^^^^^^^ not found in this scope
+   |
+   = note: this error originates in the macro `my_struct` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0422`.
diff --git a/src/test/ui/hygiene/cross-crate-methods.rs b/src/test/ui/hygiene/cross-crate-methods.rs
new file mode 100644 (file)
index 0000000..0e6f57c
--- /dev/null
@@ -0,0 +1,33 @@
+// Test that methods defined in another crate are resolved correctly their
+// names differ only in `SyntaxContext`. This also checks that any name
+// resolution done when monomorphizing is correct.
+
+// run-pass
+// aux-build:methods.rs
+
+extern crate methods;
+
+use methods::*;
+
+struct A;
+struct B;
+struct C;
+
+impl MyTrait for A {}
+test_trait!(impl for B);
+test_trait2!(impl for C);
+
+fn main() {
+    check_crate_local();
+    check_crate_local_generic(A, B);
+    check_crate_local_generic(A, C);
+
+    test_trait!(check_resolutions);
+    test_trait2!(check_resolutions);
+    test_trait!(assert_no_override A);
+    test_trait2!(assert_no_override A);
+    test_trait!(assert_override B);
+    test_trait2!(assert_override B);
+    test_trait!(assert_override C);
+    test_trait2!(assert_override C);
+}
diff --git a/src/test/ui/hygiene/cross-crate-name-collision.rs b/src/test/ui/hygiene/cross-crate-name-collision.rs
new file mode 100644 (file)
index 0000000..8f11878
--- /dev/null
@@ -0,0 +1,12 @@
+// Check that two items defined in another crate that have identifiers that
+// only differ by `SyntaxContext` do not cause name collisions when imported
+// in another crate.
+
+// check-pass
+// aux-build:needs_hygiene.rs
+
+extern crate needs_hygiene;
+
+use needs_hygiene::*;
+
+fn main() {}
diff --git a/src/test/ui/hygiene/cross-crate-name-hiding-2.rs b/src/test/ui/hygiene/cross-crate-name-hiding-2.rs
new file mode 100644 (file)
index 0000000..3eacd77
--- /dev/null
@@ -0,0 +1,15 @@
+// Check that an identifier from a 2.0 macro in another crate cannot be
+// resolved with an identifier that's not from a macro expansion.
+
+// aux-build:use_by_macro.rs
+
+extern crate use_by_macro;
+
+use use_by_macro::*;
+
+my_struct!(define);
+
+fn main() {
+    let x = MyStruct {};
+    //~^ ERROR cannot find struct, variant or union type `MyStruct` in this scope
+}
diff --git a/src/test/ui/hygiene/cross-crate-name-hiding-2.stderr b/src/test/ui/hygiene/cross-crate-name-hiding-2.stderr
new file mode 100644 (file)
index 0000000..46314cd
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0422]: cannot find struct, variant or union type `MyStruct` in this scope
+  --> $DIR/cross-crate-name-hiding-2.rs:13:13
+   |
+LL |     let x = MyStruct {};
+   |             ^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0422`.
diff --git a/src/test/ui/hygiene/cross-crate-name-hiding.rs b/src/test/ui/hygiene/cross-crate-name-hiding.rs
new file mode 100644 (file)
index 0000000..dd76ecc
--- /dev/null
@@ -0,0 +1,13 @@
+// Check that an item defined by a 2.0 macro in another crate cannot be used in
+// another crate.
+
+// aux-build:pub_hygiene.rs
+
+extern crate pub_hygiene;
+
+use pub_hygiene::*;
+
+fn main() {
+    let x = MyStruct {};
+    //~^ ERROR cannot find struct, variant or union type `MyStruct` in this scope
+}
diff --git a/src/test/ui/hygiene/cross-crate-name-hiding.stderr b/src/test/ui/hygiene/cross-crate-name-hiding.stderr
new file mode 100644 (file)
index 0000000..f8840c8
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0422]: cannot find struct, variant or union type `MyStruct` in this scope
+  --> $DIR/cross-crate-name-hiding.rs:11:13
+   |
+LL |     let x = MyStruct {};
+   |             ^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0422`.
diff --git a/src/test/ui/hygiene/cross-crate-redefine.rs b/src/test/ui/hygiene/cross-crate-redefine.rs
new file mode 100644 (file)
index 0000000..3cb06b4
--- /dev/null
@@ -0,0 +1,14 @@
+// Check that items with identical `SyntaxContext` conflict even when that
+// context involves a mark from another crate.
+
+// aux-build:use_by_macro.rs
+
+extern crate use_by_macro;
+
+use use_by_macro::*;
+
+my_struct!(define);
+//~^ ERROR the name `MyStruct` is defined multiple times
+my_struct!(define);
+
+fn main() {}
diff --git a/src/test/ui/hygiene/cross-crate-redefine.stderr b/src/test/ui/hygiene/cross-crate-redefine.stderr
new file mode 100644 (file)
index 0000000..4f1419d
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0428]: the name `MyStruct` is defined multiple times
+  --> $DIR/cross-crate-redefine.rs:10:1
+   |
+LL | my_struct!(define);
+   | ^^^^^^^^^^^^^^^^^^ `MyStruct` redefined here
+LL |
+LL | my_struct!(define);
+   | ------------------ previous definition of the type `MyStruct` here
+   |
+   = note: `MyStruct` must be defined only once in the type namespace of this module
+   = note: this error originates in the macro `my_struct` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/hygiene/cross-crate-variants.rs b/src/test/ui/hygiene/cross-crate-variants.rs
new file mode 100644 (file)
index 0000000..efc73a2
--- /dev/null
@@ -0,0 +1,18 @@
+// Test that variants of an enum defined in another crate are resolved
+// correctly when their names differ only in `SyntaxContext`.
+
+// run-pass
+// aux-build:variants.rs
+
+extern crate variants;
+
+use variants::*;
+
+fn main() {
+    check_variants();
+
+    test_variants!();
+    test_variants2!();
+
+    assert_eq!(MyEnum::Variant as u8, 1);
+}
diff --git a/src/test/ui/hygiene/cross_crate_hygiene.rs b/src/test/ui/hygiene/cross_crate_hygiene.rs
deleted file mode 100644 (file)
index 7574296..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// check-pass
-// aux-build:needs_hygiene.rs
-
-extern crate needs_hygiene;
-
-use needs_hygiene::*;
-
-fn main() {}
diff --git a/src/test/ui/hygiene/lambda-var-hygiene.rs b/src/test/ui/hygiene/lambda-var-hygiene.rs
new file mode 100644 (file)
index 0000000..bf06765
--- /dev/null
@@ -0,0 +1,12 @@
+// run-pass
+// shouldn't affect evaluation of $ex:
+macro_rules! bad_macro {
+    ($ex:expr) => ({(|_x| { $ex }) (9) })
+}
+
+fn takes_x(_x : isize) {
+    assert_eq!(bad_macro!(_x),8);
+}
+fn main() {
+    takes_x(8);
+}
index 5a8e503601468992260526c53d546e1fbb2bb51e..8c53b4105bb8b838bedc96bcce33eed565c5d1bf 100644 (file)
@@ -1,11 +1,13 @@
 error[E0277]: `Rc<Cell<i32>>` cannot be sent between threads safely
-  --> $DIR/auto-trait-leak2.rs:13:5
+  --> $DIR/auto-trait-leak2.rs:13:10
    |
 LL | fn before() -> impl Fn(i32) {
    |                ------------ within this `impl Fn<(i32,)>`
 ...
 LL |     send(before());
-   |     ^^^^ `Rc<Cell<i32>>` cannot be sent between threads safely
+   |     ---- ^^^^^^^^ `Rc<Cell<i32>>` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: within `impl Fn<(i32,)>`, the trait `Send` is not implemented for `Rc<Cell<i32>>`
    = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:7:5: 7:22]`
@@ -17,10 +19,12 @@ LL | fn send<T: Send>(_: T) {}
    |            ^^^^ required by this bound in `send`
 
 error[E0277]: `Rc<Cell<i32>>` cannot be sent between threads safely
-  --> $DIR/auto-trait-leak2.rs:16:5
+  --> $DIR/auto-trait-leak2.rs:16:10
    |
 LL |     send(after());
-   |     ^^^^ `Rc<Cell<i32>>` cannot be sent between threads safely
+   |     ---- ^^^^^^^ `Rc<Cell<i32>>` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
 ...
 LL | fn after() -> impl Fn(i32) {
    |               ------------ within this `impl Fn<(i32,)>`
index 6adc4e6b23968ed57e04443005c220aed915727d..a25c85faf4e352c86d5ef7584fbbb81899aaa999 100644 (file)
@@ -3,6 +3,9 @@ error[E0632]: cannot provide explicit generic arguments when `impl Trait` is use
    |
 LL |     foo::<str>("".to_string());
    |           ^^^ explicit generic argument not allowed
+   |
+   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
+   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/issue-49579.rs b/src/test/ui/impl-trait/issue-49579.rs
new file mode 100644 (file)
index 0000000..98de014
--- /dev/null
@@ -0,0 +1,14 @@
+// check-pass
+
+fn fibs(n: u32) -> impl Iterator<Item=u128> {
+    (0 .. n)
+    .scan((0, 1), |st, _| {
+        *st = (st.1, st.0 + st.1);
+        Some(*st)
+    })
+    .map(&|(f, _)| f)
+}
+
+fn main() {
+    println!("{:?}", fibs(10).collect::<Vec<_>>());
+}
diff --git a/src/test/ui/impl-trait/issue-49685.rs b/src/test/ui/impl-trait/issue-49685.rs
new file mode 100644 (file)
index 0000000..fb328d6
--- /dev/null
@@ -0,0 +1,13 @@
+// run-pass
+// Regression test for #49685: drop elaboration was not revealing the
+// value of `impl Trait` returns, leading to an ICE.
+
+fn main() {
+    let _ = Some(())
+        .into_iter()
+        .flat_map(|_| Some(()).into_iter().flat_map(func));
+}
+
+fn func(_: ()) -> impl Iterator<Item = ()> {
+    Some(()).into_iter().flat_map(|_| vec![])
+}
diff --git a/src/test/ui/impl-trait/issue-51185.rs b/src/test/ui/impl-trait/issue-51185.rs
new file mode 100644 (file)
index 0000000..52a2b25
--- /dev/null
@@ -0,0 +1,8 @@
+// run-pass
+fn foo() -> impl Into<for<'a> fn(&'a ())> {
+    (|_| {}) as for<'a> fn(&'a ())
+}
+
+fn main() {
+    foo().into()(&());
+}
index 6800b37b5b175aaaee409116c67c9acefa9a4848..90c252537ef82b1b72f94e5fbc0a3fa3f3f9ec05 100644 (file)
@@ -3,6 +3,9 @@ error[E0632]: cannot provide explicit generic arguments when `impl Trait` is use
    |
 LL |     foo::<String>('a');
    |           ^^^^^^ explicit generic argument not allowed
+   |
+   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
+   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
index db66d461095993f8fb9f5b3ad9a5c711dcadb30f..84b98f71f4f0caefea1347220c2dec8ea761d96b 100644 (file)
@@ -5,6 +5,9 @@ LL |     evt.handle_event::<TestEvent, fn(TestEvent)>(|_evt| {
    |                        ^^^^^^^^^  ^^^^^^^^^^^^^ explicit generic argument not allowed
    |                        |
    |                        explicit generic argument not allowed
+   |
+   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
+   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
index 4605e76ac96d28a44cb50f3563daee0b2be0d873..35fb42d6213226918f687979944f6812db7d6278 100644 (file)
@@ -235,6 +235,7 @@ impl <T = impl Debug> T {}
 //~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
 //~| WARNING this was previously accepted by the compiler but is being phased out
 //~| ERROR `impl Trait` not allowed outside of function and method return types
+//~| ERROR no nominal type found
 
 // Disallowed
 fn in_method_generic_param_default<T = impl Debug>(_: T) {}
index 7f11d30dbaa5faafe272cfcbf75da31e42a04b37..236cf449e85fa5050893e64709a4a507ec310fc0 100644 (file)
@@ -272,19 +272,19 @@ LL | impl <T = impl Debug> T {}
    |           ^^^^^^^^^^
 
 error[E0562]: `impl Trait` not allowed outside of function and method return types
-  --> $DIR/where-allowed.rs:240:40
+  --> $DIR/where-allowed.rs:241:40
    |
 LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
    |                                        ^^^^^^^^^^
 
 error[E0562]: `impl Trait` not allowed outside of function and method return types
-  --> $DIR/where-allowed.rs:246:29
+  --> $DIR/where-allowed.rs:247:29
    |
 LL |     let _in_local_variable: impl Fn() = || {};
    |                             ^^^^^^^^^
 
 error[E0562]: `impl Trait` not allowed outside of function and method return types
-  --> $DIR/where-allowed.rs:248:46
+  --> $DIR/where-allowed.rs:249:46
    |
 LL |     let _in_return_in_local_variable = || -> impl Fn() { || {} };
    |                                              ^^^^^^^^^
@@ -300,7 +300,7 @@ LL | impl <T = impl Debug> T {}
    = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
 
 error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
-  --> $DIR/where-allowed.rs:240:36
+  --> $DIR/where-allowed.rs:241:36
    |
 LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
    |                                    ^
@@ -308,7 +308,15 @@ LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
    = 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 #36887 <https://github.com/rust-lang/rust/issues/36887>
 
-error: aborting due to 48 previous errors
+error[E0118]: no nominal type found for inherent implementation
+  --> $DIR/where-allowed.rs:234:23
+   |
+LL | impl <T = impl Debug> T {}
+   |                       ^ impl requires a nominal type
+   |
+   = note: either implement a trait on it or create a newtype to wrap it instead
+
+error: aborting due to 49 previous errors
 
-Some errors have detailed explanations: E0562, E0658, E0666.
-For more information about an error, try `rustc --explain E0562`.
+Some errors have detailed explanations: E0118, E0562, E0658, E0666.
+For more information about an error, try `rustc --explain E0118`.
index 0dbcb5f1de3f9b17c5856ae297261b56443244ea..997a2741b382c8de1a7cc4efb1ffe58acda53681 100644 (file)
@@ -8,12 +8,13 @@ LL |     use a::foo;
    |
    = note: `foo` must be defined only once in the value namespace of this module
 
-error[E0659]: `foo` is ambiguous (glob import vs glob import in the same module)
+error[E0659]: `foo` is ambiguous
   --> $DIR/duplicate.rs:46:15
    |
 LL |     use self::foo::bar;
    |               ^^^ ambiguous name
    |
+   = note: ambiguous because of multiple glob imports of a name in the same module
 note: `foo` could refer to the module imported here
   --> $DIR/duplicate.rs:43:9
    |
@@ -27,12 +28,13 @@ LL |     use self::m2::*;
    |         ^^^^^^^^^^^
    = help: consider adding an explicit import of `foo` to disambiguate
 
-error[E0659]: `foo` is ambiguous (glob import vs glob import in the same module)
+error[E0659]: `foo` is ambiguous
   --> $DIR/duplicate.rs:35:8
    |
 LL |     f::foo();
    |        ^^^ ambiguous name
    |
+   = note: ambiguous because of multiple glob imports of a name in the same module
 note: `foo` could refer to the function imported here
   --> $DIR/duplicate.rs:24:13
    |
@@ -46,12 +48,13 @@ LL |     pub use b::*;
    |             ^^^^
    = help: consider adding an explicit import of `foo` to disambiguate
 
-error[E0659]: `foo` is ambiguous (glob import vs glob import in the same module)
+error[E0659]: `foo` is ambiguous
   --> $DIR/duplicate.rs:49:9
    |
 LL |         foo::bar();
    |         ^^^ ambiguous name
    |
+   = note: ambiguous because of multiple glob imports of a name in the same module
 note: `foo` could refer to the module imported here
   --> $DIR/duplicate.rs:43:9
    |
index 472824b84f4a1eda80ced77eee008946e0368fa3..c31c8840381537217a3ac5273b2561718a1da352 100644 (file)
@@ -9,12 +9,13 @@ LL | define_other_core!();
    |
    = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0659]: `Vec` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `Vec` is ambiguous
   --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:13:9
    |
 LL |         Vec::panic!();
    |         ^^^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
 note: `Vec` could refer to the crate imported here
   --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:5:9
    |
index 4ef446f93c860c39430a96685bcef26e4d6b9a47..aff2eff68ac86d708015eefa2019c87b024d9d1c 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `env` is ambiguous (glob import vs any other name from outer scope during import/macro resolution)
+error[E0659]: `env` is ambiguous
   --> $DIR/glob-shadowing.rs:11:17
    |
 LL |         let x = env!("PATH");
    |                 ^^^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution
    = note: `env` could refer to a macro from prelude
 note: `env` could also refer to the macro imported here
   --> $DIR/glob-shadowing.rs:9:9
@@ -13,12 +14,13 @@ LL |     use m::*;
    = help: consider adding an explicit import of `env` to disambiguate
    = help: or use `self::env` to refer to this macro unambiguously
 
-error[E0659]: `env` is ambiguous (glob import vs any other name from outer scope during import/macro resolution)
+error[E0659]: `env` is ambiguous
   --> $DIR/glob-shadowing.rs:19:21
    |
 LL |             let x = env!("PATH");
    |                     ^^^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution
    = note: `env` could refer to a macro from prelude
 note: `env` could also refer to the macro imported here
   --> $DIR/glob-shadowing.rs:17:13
@@ -27,12 +29,13 @@ LL |         use m::*;
    |             ^^^^
    = help: consider adding an explicit import of `env` to disambiguate
 
-error[E0659]: `fenv` is ambiguous (glob import vs any other name from outer scope during import/macro resolution)
+error[E0659]: `fenv` is ambiguous
   --> $DIR/glob-shadowing.rs:29:21
    |
 LL |             let x = fenv!();
    |                     ^^^^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution
 note: `fenv` could refer to the macro imported here
   --> $DIR/glob-shadowing.rs:27:13
    |
index bbec2aae825928ea4ef8e7ac3176c421efcf0aa3..a0e7bf8b61f6e4ceb79617cb9528b59be35952ee 100644 (file)
@@ -4,12 +4,13 @@ error[E0432]: unresolved import `nonexistent_module`
 LL |     use nonexistent_module::mac;
    |         ^^^^^^^^^^^^^^^^^^ maybe a missing crate `nonexistent_module`?
 
-error[E0659]: `mac` is ambiguous (`macro_rules` vs non-`macro_rules` from other module)
+error[E0659]: `mac` is ambiguous
   --> $DIR/issue-53269.rs:8:5
    |
 LL |     mac!();
    |     ^^^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a `macro_rules` name and a non-`macro_rules` name from another module
 note: `mac` could refer to the macro defined here
   --> $DIR/issue-53269.rs:3:1
    |
index a7a7cc8879e652716ab6c220b972fc4b1512274b..c38166ddea6aaf4e4d6358828fdcbb30303be6b2 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `S` is ambiguous (glob import vs glob import in the same module)
+error[E0659]: `S` is ambiguous
   --> $DIR/issue-55884-1.rs:19:12
    |
 LL |     use m::S;
    |            ^ ambiguous name
    |
+   = note: ambiguous because of multiple glob imports of a name in the same module
 note: `S` could refer to the struct imported here
   --> $DIR/issue-55884-1.rs:14:13
    |
index d78cc5230367d4932676fe4f27d1e06723eeff4a..2e4ba86237676090cb292469ee0b4b908317a816 100644 (file)
@@ -4,12 +4,13 @@ error[E0432]: unresolved import `empty::issue_56125`
 LL |     use empty::issue_56125;
    |         ^^^^^^^^^^^^^^^^^^ no `issue_56125` in `m3::empty`
 
-error[E0659]: `issue_56125` is ambiguous (name vs any other name during import resolution)
+error[E0659]: `issue_56125` is ambiguous
   --> $DIR/issue-56125.rs:6:9
    |
 LL |     use issue_56125::last_segment::*;
    |         ^^^^^^^^^^^ ambiguous name
    |
+   = note: ambiguous because of multiple potential import sources
    = note: `issue_56125` could refer to a crate passed with `--extern`
    = help: use `::issue_56125` to refer to this crate unambiguously
 note: `issue_56125` could also refer to the module imported here
@@ -19,12 +20,13 @@ LL |     use issue_56125::last_segment::*;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: use `self::issue_56125` to refer to this module unambiguously
 
-error[E0659]: `issue_56125` is ambiguous (name vs any other name during import resolution)
+error[E0659]: `issue_56125` is ambiguous
   --> $DIR/issue-56125.rs:11:9
    |
 LL |     use issue_56125::non_last_segment::non_last_segment::*;
    |         ^^^^^^^^^^^ ambiguous name
    |
+   = note: ambiguous because of multiple potential import sources
    = note: `issue_56125` could refer to a crate passed with `--extern`
    = help: use `::issue_56125` to refer to this crate unambiguously
 note: `issue_56125` could also refer to the module imported here
@@ -34,12 +36,13 @@ LL |     use issue_56125::non_last_segment::non_last_segment::*;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: use `self::issue_56125` to refer to this module unambiguously
 
-error[E0659]: `issue_56125` is ambiguous (name vs any other name during import resolution)
+error[E0659]: `issue_56125` is ambiguous
   --> $DIR/issue-56125.rs:18:9
    |
 LL |     use issue_56125::*;
    |         ^^^^^^^^^^^ ambiguous name
    |
+   = note: ambiguous because of multiple potential import sources
    = note: `issue_56125` could refer to a crate passed with `--extern`
    = help: use `::issue_56125` to refer to this crate unambiguously
 note: `issue_56125` could also refer to the module imported here
index 174088e8f6c1197fb5f17a00b1f41cfc585fb928..1a3ca4edaca9be106d3cb5d12d22e8b6d6984d05 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `core` is ambiguous (name vs any other name during import resolution)
+error[E0659]: `core` is ambiguous
   --> $DIR/issue-57539.rs:4:9
    |
 LL |     use core;
    |         ^^^^ ambiguous name
    |
+   = note: ambiguous because of multiple potential import sources
    = note: `core` could refer to a built-in crate
    = help: use `::core` to refer to this crate unambiguously
 note: `core` could also refer to the module imported here
index f809698fe1d4d725f0ffea3baa3065aa3a4fb06a..c048d2ea204202904d94bea1d31df44c42bcfaae 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `exported` is ambiguous (glob import vs macro-expanded name in the same module during import/macro resolution)
+error[E0659]: `exported` is ambiguous
   --> $DIR/local-modularized-tricky-fail-1.rs:28:1
    |
 LL | exported!();
    | ^^^^^^^^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution
 note: `exported` could refer to the macro defined here
   --> $DIR/local-modularized-tricky-fail-1.rs:5:5
    |
@@ -22,12 +23,13 @@ LL | use inner1::*;
    = help: consider adding an explicit import of `exported` to disambiguate
    = note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0659]: `exported` is ambiguous (glob import vs macro-expanded name in the same module during import/macro resolution)
+error[E0659]: `exported` is ambiguous
   --> $DIR/local-modularized-tricky-fail-1.rs:28:1
    |
 LL | exported!();
    | ^^^^^^^^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution
 note: `exported` could refer to the macro defined here
   --> $DIR/local-modularized-tricky-fail-1.rs:5:5
    |
@@ -46,12 +48,13 @@ LL | use inner1::*;
    = help: consider adding an explicit import of `exported` to disambiguate
    = note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `panic` is ambiguous
   --> $DIR/local-modularized-tricky-fail-1.rs:36:5
    |
 LL |     panic!();
    |     ^^^^^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
    = note: `panic` could refer to a macro from prelude
 note: `panic` could also refer to the macro defined here
   --> $DIR/local-modularized-tricky-fail-1.rs:11:5
@@ -66,12 +69,13 @@ LL |       define_panic!();
    = help: use `crate::panic` to refer to this macro unambiguously
    = note: this error originates in the macro `define_panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0659]: `include` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `include` is ambiguous
   --> $DIR/local-modularized-tricky-fail-1.rs:47:1
    |
 LL | include!();
    | ^^^^^^^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
    = note: `include` could refer to a macro from prelude
 note: `include` could also refer to the macro defined here
   --> $DIR/local-modularized-tricky-fail-1.rs:17:5
index a5b90008272cf3494f1b49bd338758147a7aaf12..5f113ce2bee5df8045f87d635c07fa083796b5bf 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `bar` is ambiguous (glob import vs macro-expanded name in the same module during import/macro resolution)
+error[E0659]: `bar` is ambiguous
   --> $DIR/macro-paths.rs:13:5
    |
 LL |     bar::m! {
    |     ^^^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution
 note: `bar` could refer to the module defined here
   --> $DIR/macro-paths.rs:14:9
    |
@@ -16,12 +17,13 @@ LL |     use foo::*;
    |         ^^^^^^
    = help: consider adding an explicit import of `bar` to disambiguate
 
-error[E0659]: `baz` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `baz` is ambiguous
   --> $DIR/macro-paths.rs:23:5
    |
 LL |     baz::m! {
    |     ^^^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
 note: `baz` could refer to the module defined here
   --> $DIR/macro-paths.rs:24:9
    |
index 27b34fe0c01fa8ab4ca548bb4f25e373ad09e088..110548d1d6ae1604784e8f4768d875ea3da40639 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `m` is ambiguous (glob import vs macro-expanded name in the same module during import/macro resolution)
+error[E0659]: `m` is ambiguous
   --> $DIR/macros.rs:16:5
    |
 LL |     m! {
    |     ^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution
 note: `m` could refer to the macro imported here
   --> $DIR/macros.rs:18:13
    |
@@ -16,12 +17,13 @@ LL |     use two_macros::*;
    |         ^^^^^^^^^^^^^
    = help: consider adding an explicit import of `m` to disambiguate
 
-error[E0659]: `m` is ambiguous (glob import vs macro-expanded name in the same module during import/macro resolution)
+error[E0659]: `m` is ambiguous
   --> $DIR/macros.rs:16:5
    |
 LL |     m! {
    |     ^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution
 note: `m` could refer to the macro imported here
   --> $DIR/macros.rs:18:13
    |
@@ -34,12 +36,13 @@ LL |     use two_macros::*;
    |         ^^^^^^^^^^^^^
    = help: consider adding an explicit import of `m` to disambiguate
 
-error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `m` is ambiguous
   --> $DIR/macros.rs:30:9
    |
 LL |         m! {
    |         ^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
 note: `m` could refer to the macro imported here
   --> $DIR/macros.rs:31:17
    |
index d79c719d826472d2f1668fc7171ec783e07c31c8..fd7e99165b551c40ad824042d33913e402e2454b 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `Foo` is ambiguous (glob import vs glob import in the same module)
+error[E0659]: `Foo` is ambiguous
   --> $DIR/rfc-1560-warning-cycle.rs:9:17
    |
 LL |         fn f(_: Foo) {}
    |                 ^^^ ambiguous name
    |
+   = note: ambiguous because of multiple glob imports of a name in the same module
 note: `Foo` could refer to the struct imported here
   --> $DIR/rfc-1560-warning-cycle.rs:7:13
    |
index 2fcbb2a045cb32edd31d37913c0c923d71d7ae0b..6ffb31c20e60a21e894468c603cdd18bbb6217e4 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `panic` is ambiguous (glob import vs any other name from outer scope during import/macro resolution)
+error[E0659]: `panic` is ambiguous
   --> $DIR/shadow_builtin_macros.rs:15:14
    |
 LL |     fn f() { panic!(); }
    |              ^^^^^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution
    = note: `panic` could refer to a macro from prelude
 note: `panic` could also refer to the macro imported here
   --> $DIR/shadow_builtin_macros.rs:14:9
@@ -13,12 +14,13 @@ LL |     use foo::*;
    = help: consider adding an explicit import of `panic` to disambiguate
    = help: or use `self::panic` to refer to this macro unambiguously
 
-error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `panic` is ambiguous
   --> $DIR/shadow_builtin_macros.rs:33:5
    |
 LL |     panic!();
    |     ^^^^^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
    = note: `panic` could refer to a macro from prelude
 note: `panic` could also refer to the macro defined here
   --> $DIR/shadow_builtin_macros.rs:30:9
@@ -30,12 +32,13 @@ LL |     m!();
    |     ---- in this macro invocation
    = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0659]: `n` is ambiguous (glob import vs any other name from outer scope during import/macro resolution)
+error[E0659]: `n` is ambiguous
   --> $DIR/shadow_builtin_macros.rs:49:5
    |
 LL |     n!();
    |     ^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution
 note: `n` could refer to the macro imported here
   --> $DIR/shadow_builtin_macros.rs:48:9
    |
@@ -49,12 +52,13 @@ note: `n` could also refer to the macro imported here
 LL | #[macro_use(n)]
    |             ^
 
-error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `panic` is ambiguous
   --> $DIR/shadow_builtin_macros.rs:20:14
    |
 LL |     fn f() { panic!(); }
    |              ^^^^^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
    = note: `panic` could refer to a macro from prelude
 note: `panic` could also refer to the macro imported here
   --> $DIR/shadow_builtin_macros.rs:19:26
diff --git a/src/test/ui/in-band-lifetimes.rs b/src/test/ui/in-band-lifetimes.rs
deleted file mode 100644 (file)
index 9b2e1fe..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-// run-pass
-
-#![allow(warnings)]
-#![feature(in_band_lifetimes)]
-
-fn foo(x: &'x u8) -> &'x u8 { x }
-fn foo2(x: &'a u8, y: &u8) -> &'a u8 { x }
-
-fn check_in_band_can_be_late_bound() {
-    let _: for<'x> fn(&'x u8, &u8) -> &'x u8 = foo2;
-}
-
-struct ForInherentNoParams;
-
-impl ForInherentNoParams {
-    fn foo(x: &'a u32, y: &u32) -> &'a u32 { x }
-}
-
-struct X<'a>(&'a u8);
-
-impl<'a> X<'a> {
-    fn inner(&self) -> &'a u8 {
-        self.0
-    }
-
-    fn same_lifetime_as_parameter(&mut self, x: &'a u8) {
-        self.0 = x;
-    }
-}
-
-impl X<'b> {
-    fn inner_2(&self) -> &'b u8 {
-        self.0
-    }
-
-    fn reference_already_introduced_in_band_from_method_with_explicit_binders<'a>(
-        &'b self, x: &'a u32
-    ) {}
-}
-
-struct Y<T>(T);
-
-impl Y<&'a u8> {
-    fn inner(&self) -> &'a u8 {
-        self.0
-    }
-}
-
-trait MyTrait<'a> {
-    fn my_lifetime(&self) -> &'a u8;
-    fn any_lifetime() -> &'b u8;
-    fn borrowed_lifetime(&'b self) -> &'b u8;
-    fn default_impl(&self, x: &'b u32, y: &u32) -> &'b u32 { x }
-    fn in_band_def_explicit_impl(&self, x: &'b u8);
-}
-
-impl MyTrait<'a> for Y<&'a u8> {
-    fn my_lifetime(&self) -> &'a u8 { self.0 }
-    fn any_lifetime() -> &'b u8 { &0 }
-    fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
-    fn in_band_def_explicit_impl<'b>(&self, x: &'b u8) {}
-}
-
-fn test_hrtb_defined_lifetime_where<F>(_: F) where for<'a> F: Fn(&'a u8) {}
-fn test_hrtb_defined_lifetime_polytraitref<F>(_: F) where F: for<'a> Fn(&'a u8) {}
-
-fn reference_in_band_from_locals(x: &'test u32) -> &'test u32 {
-    let y: &'test u32 = x;
-    y
-}
-
-fn in_generics_in_band<T: MyTrait<'a>>(x: &T) {}
-fn where_clause_in_band<T>(x: &T) where T: MyTrait<'a> {}
-fn impl_trait_in_band(x: &impl MyTrait<'a>) {}
-
-// Tests around using in-band lifetimes within existential traits.
-
-trait FunkyTrait<'a> { }
-impl<'a, T> FunkyTrait<'a> for T { }
-fn ret_pos_impl_trait_in_band_outlives(x: &'a u32) -> impl ::std::fmt::Debug + 'a {
-    x
-}
-fn ret_pos_impl_trait_in_band_param(x: &'a u32) -> impl FunkyTrait<'a> {
-    x
-}
-fn ret_pos_impl_trait_in_band_param_static(x: &'a u32) -> impl FunkyTrait<'static> + 'a {
-    x
-}
-fn ret_pos_impl_trait_in_band_param_outlives(x: &'a u32) -> impl FunkyTrait<'a> + 'a {
-    x
-}
-fn ret_pos_impl_trait_in_band_higher_ranked(x: &'a u32) -> impl for<'b> FunkyTrait<'b> + 'a {
-    x
-}
-
-fn main() {}
diff --git a/src/test/ui/in-band-lifetimes/in-band-lifetimes.rs b/src/test/ui/in-band-lifetimes/in-band-lifetimes.rs
new file mode 100644 (file)
index 0000000..9b2e1fe
--- /dev/null
@@ -0,0 +1,96 @@
+// run-pass
+
+#![allow(warnings)]
+#![feature(in_band_lifetimes)]
+
+fn foo(x: &'x u8) -> &'x u8 { x }
+fn foo2(x: &'a u8, y: &u8) -> &'a u8 { x }
+
+fn check_in_band_can_be_late_bound() {
+    let _: for<'x> fn(&'x u8, &u8) -> &'x u8 = foo2;
+}
+
+struct ForInherentNoParams;
+
+impl ForInherentNoParams {
+    fn foo(x: &'a u32, y: &u32) -> &'a u32 { x }
+}
+
+struct X<'a>(&'a u8);
+
+impl<'a> X<'a> {
+    fn inner(&self) -> &'a u8 {
+        self.0
+    }
+
+    fn same_lifetime_as_parameter(&mut self, x: &'a u8) {
+        self.0 = x;
+    }
+}
+
+impl X<'b> {
+    fn inner_2(&self) -> &'b u8 {
+        self.0
+    }
+
+    fn reference_already_introduced_in_band_from_method_with_explicit_binders<'a>(
+        &'b self, x: &'a u32
+    ) {}
+}
+
+struct Y<T>(T);
+
+impl Y<&'a u8> {
+    fn inner(&self) -> &'a u8 {
+        self.0
+    }
+}
+
+trait MyTrait<'a> {
+    fn my_lifetime(&self) -> &'a u8;
+    fn any_lifetime() -> &'b u8;
+    fn borrowed_lifetime(&'b self) -> &'b u8;
+    fn default_impl(&self, x: &'b u32, y: &u32) -> &'b u32 { x }
+    fn in_band_def_explicit_impl(&self, x: &'b u8);
+}
+
+impl MyTrait<'a> for Y<&'a u8> {
+    fn my_lifetime(&self) -> &'a u8 { self.0 }
+    fn any_lifetime() -> &'b u8 { &0 }
+    fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
+    fn in_band_def_explicit_impl<'b>(&self, x: &'b u8) {}
+}
+
+fn test_hrtb_defined_lifetime_where<F>(_: F) where for<'a> F: Fn(&'a u8) {}
+fn test_hrtb_defined_lifetime_polytraitref<F>(_: F) where F: for<'a> Fn(&'a u8) {}
+
+fn reference_in_band_from_locals(x: &'test u32) -> &'test u32 {
+    let y: &'test u32 = x;
+    y
+}
+
+fn in_generics_in_band<T: MyTrait<'a>>(x: &T) {}
+fn where_clause_in_band<T>(x: &T) where T: MyTrait<'a> {}
+fn impl_trait_in_band(x: &impl MyTrait<'a>) {}
+
+// Tests around using in-band lifetimes within existential traits.
+
+trait FunkyTrait<'a> { }
+impl<'a, T> FunkyTrait<'a> for T { }
+fn ret_pos_impl_trait_in_band_outlives(x: &'a u32) -> impl ::std::fmt::Debug + 'a {
+    x
+}
+fn ret_pos_impl_trait_in_band_param(x: &'a u32) -> impl FunkyTrait<'a> {
+    x
+}
+fn ret_pos_impl_trait_in_band_param_static(x: &'a u32) -> impl FunkyTrait<'static> + 'a {
+    x
+}
+fn ret_pos_impl_trait_in_band_param_outlives(x: &'a u32) -> impl FunkyTrait<'a> + 'a {
+    x
+}
+fn ret_pos_impl_trait_in_band_higher_ranked(x: &'a u32) -> impl for<'b> FunkyTrait<'b> + 'a {
+    x
+}
+
+fn main() {}
diff --git a/src/test/ui/inference/lub-glb-with-unbound-infer-var.rs b/src/test/ui/inference/lub-glb-with-unbound-infer-var.rs
new file mode 100644 (file)
index 0000000..c9e1170
--- /dev/null
@@ -0,0 +1,15 @@
+// run-pass
+// Test for a specific corner case: when we compute the LUB of two fn
+// types and their parameters have unbound variables. In that case, we
+// wind up relating those two variables. This was causing an ICE in an
+// in-progress PR.
+
+fn main() {
+    let a_f: fn(_) = |_| ();
+    let b_f: fn(_) = |_| ();
+    let c_f = match 22 {
+        0 => a_f,
+        _ => b_f,
+    };
+    c_f(4);
+}
diff --git a/src/test/ui/inline-const/const-expr-inference.rs b/src/test/ui/inline-const/const-expr-inference.rs
new file mode 100644 (file)
index 0000000..6aa2a2f
--- /dev/null
@@ -0,0 +1,12 @@
+// check-pass
+
+#![feature(inline_const)]
+#![allow(incomplete_features)]
+
+pub fn todo<T>() -> T {
+    const { todo!() }
+}
+
+fn main() {
+    let _: usize = const { 0 };
+}
diff --git a/src/test/ui/inline-const/const-expr-lifetime-err.rs b/src/test/ui/inline-const/const-expr-lifetime-err.rs
new file mode 100644 (file)
index 0000000..e56cbc9
--- /dev/null
@@ -0,0 +1,30 @@
+#![allow(incomplete_features)]
+#![feature(const_mut_refs)]
+#![feature(inline_const)]
+
+use std::marker::PhantomData;
+
+#[derive(PartialEq, Eq)]
+pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
+
+impl<'a, T: ?Sized> InvariantRef<'a, T> {
+    pub const fn new(r: &'a T) -> Self {
+        InvariantRef(r, PhantomData)
+    }
+}
+
+impl<'a> InvariantRef<'a, ()> {
+    pub const NEW: Self = InvariantRef::new(&());
+}
+
+fn equate<T>(x: T, y: T){}
+
+fn foo<'a>() {
+    let y = ();
+    equate(InvariantRef::new(&y), const { InvariantRef::<'a>::NEW });
+    //~^ ERROR `y` does not live long enough [E0597]
+}
+
+fn main() {
+    foo();
+}
diff --git a/src/test/ui/inline-const/const-expr-lifetime-err.stderr b/src/test/ui/inline-const/const-expr-lifetime-err.stderr
new file mode 100644 (file)
index 0000000..30ecd33
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/const-expr-lifetime-err.rs:24:30
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+LL |     let y = ();
+LL |     equate(InvariantRef::new(&y), const { InvariantRef::<'a>::NEW });
+   |            ------------------^^-
+   |            |                 |
+   |            |                 borrowed value does not live long enough
+   |            argument requires that `y` is borrowed for `'a`
+LL |
+LL | }
+   | - `y` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/inline-const/const-expr-lifetime.rs b/src/test/ui/inline-const/const-expr-lifetime.rs
new file mode 100644 (file)
index 0000000..f622f2c
--- /dev/null
@@ -0,0 +1,36 @@
+// run-pass
+
+#![allow(incomplete_features)]
+#![feature(const_mut_refs)]
+#![feature(inline_const)]
+
+use std::marker::PhantomData;
+
+// rust-lang/rust#78174: ICE: "cannot convert ReErased to a region vid"
+fn issue_78174() {
+    let foo = const { "foo" };
+    assert_eq!(foo, "foo");
+}
+
+pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
+
+impl<'a, T: ?Sized> InvariantRef<'a, T> {
+    pub const fn new(r: &'a T) -> Self {
+        InvariantRef(r, PhantomData)
+    }
+}
+
+fn get_invariant_ref<'a>() -> InvariantRef<'a, ()> {
+    const { InvariantRef::<'a, ()>::new(&()) }
+}
+
+fn get_invariant_ref2<'a>() -> InvariantRef<'a, ()> {
+    // Try some type inference
+    const { InvariantRef::new(&()) }
+}
+
+fn main() {
+    issue_78174();
+    get_invariant_ref();
+    get_invariant_ref2();
+}
diff --git a/src/test/ui/inline-const/const-match-pat-inference.rs b/src/test/ui/inline-const/const-match-pat-inference.rs
new file mode 100644 (file)
index 0000000..61188ed
--- /dev/null
@@ -0,0 +1,12 @@
+// check-pass
+
+#![feature(inline_const)]
+#![allow(incomplete_features)]
+
+fn main() {
+    match 1u64 {
+        0 => (),
+        const { 0 + 1 } => (),
+        const { 2 - 1 } ..= const { u64::MAX } => (),
+    }
+}
diff --git a/src/test/ui/inline-const/const-match-pat-lifetime-err.rs b/src/test/ui/inline-const/const-match-pat-lifetime-err.rs
new file mode 100644 (file)
index 0000000..bc5aa24
--- /dev/null
@@ -0,0 +1,34 @@
+// ignore-test
+
+#![allow(incomplete_features)]
+#![feature(const_mut_refs)]
+#![feature(inline_const)]
+
+use std::marker::PhantomData;
+
+#[derive(PartialEq, Eq)]
+pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
+
+impl<'a, T: ?Sized> InvariantRef<'a, T> {
+    pub const fn new(r: &'a T) -> Self {
+        InvariantRef(r, PhantomData)
+    }
+}
+
+impl<'a> InvariantRef<'a, ()> {
+    pub const NEW: Self = InvariantRef::new(&());
+}
+
+fn match_invariant_ref<'a>() {
+    let y = ();
+    match InvariantRef::new(&y) {
+    //~^ ERROR `y` does not live long enough [E0597]
+        // FIXME(nbdd0121): This should give the same error as `InvariantRef::<'a>::NEW` (without
+        // const block)
+        const { InvariantRef::<'a>::NEW } => (),
+    }
+}
+
+fn main() {
+    match_invariant_ref();
+}
diff --git a/src/test/ui/inline-const/const-match-pat-lifetime.rs b/src/test/ui/inline-const/const-match-pat-lifetime.rs
new file mode 100644 (file)
index 0000000..3d986f0
--- /dev/null
@@ -0,0 +1,36 @@
+// run-pass
+
+#![allow(incomplete_features)]
+#![feature(const_mut_refs)]
+#![feature(inline_const)]
+
+use std::marker::PhantomData;
+
+// rust-lang/rust#78174: ICE: "cannot convert ReErased to a region vid"
+fn issue_78174() {
+    match "foo" {
+        const { concat!("fo", "o") } => (),
+        _ => unreachable!(),
+    }
+}
+
+#[derive(PartialEq, Eq)]
+pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
+
+impl<'a, T: ?Sized> InvariantRef<'a, T> {
+    pub const fn new(r: &'a T) -> Self {
+        InvariantRef(r, PhantomData)
+    }
+}
+
+fn match_invariant_ref<'a>() {
+    match const { InvariantRef::<'a, _>::new(&()) } {
+        const { InvariantRef::<'a, ()>::new(&()) } => {
+        }
+    }
+}
+
+fn main() {
+    issue_78174();
+    match_invariant_ref();
+}
index 8fbdc0c39c6aa38edce10d2f98470a2b06533879..a3171187e69e58d236a68abd471f9512f073bccf 100644 (file)
@@ -7,6 +7,7 @@ const fn not_fn_items() {
     //~^ ERROR expected a `FnOnce<()>` closure
     const_eval_select((), 42, 0xDEADBEEF);
     //~^ ERROR expected a `FnOnce<()>` closure
+    //~| ERROR expected a `FnOnce<()>` closure
 }
 
 const fn foo(n: i32) -> i32 {
index 78647e92138c2ccaa8dd3cd29001265654afea8b..5e1ab584d80cf2f9fa75b3bbc8af88489d3b315c 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: expected a `FnOnce<()>` closure, found `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]`
-  --> $DIR/const-eval-select-bad.rs:6:34
+  --> $DIR/const-eval-select-bad.rs:6:27
    |
 LL |     const_eval_select((), || {}, || {});
-   |     -----------------            ^^^^^ expected an `FnOnce<()>` closure, found `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]`
+   |     -----------------     ^^^^^ expected an `FnOnce<()>` closure, found `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]`
    |     |
    |     required by a bound introduced by this call
    |
@@ -15,10 +15,10 @@ LL |     F: ~const FnOnce<ARG, Output = RET>,
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
 
 error[E0277]: expected a `FnOnce<()>` closure, found `{integer}`
-  --> $DIR/const-eval-select-bad.rs:8:31
+  --> $DIR/const-eval-select-bad.rs:8:27
    |
 LL |     const_eval_select((), 42, 0xDEADBEEF);
-   |     -----------------         ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `{integer}`
+   |     -----------------     ^^ expected an `FnOnce<()>` closure, found `{integer}`
    |     |
    |     required by a bound introduced by this call
    |
@@ -30,8 +30,24 @@ note: required by a bound in `const_eval_select`
 LL |     F: ~const FnOnce<ARG, Output = RET>,
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
 
+error[E0277]: expected a `FnOnce<()>` closure, found `{integer}`
+  --> $DIR/const-eval-select-bad.rs:8:31
+   |
+LL |     const_eval_select((), 42, 0xDEADBEEF);
+   |     -----------------         ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `{integer}`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `FnOnce<()>` is not implemented for `{integer}`
+   = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
+note: required by a bound in `const_eval_select`
+  --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
+   |
+LL |     G: FnOnce<ARG, Output = RET> + ~const Drop,
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
+
 error[E0271]: type mismatch resolving `<fn(i32) -> bool {bar} as FnOnce<(i32,)>>::Output == i32`
-  --> $DIR/const-eval-select-bad.rs:27:5
+  --> $DIR/const-eval-select-bad.rs:28:5
    |
 LL |     const_eval_select((1,), foo, bar);
    |     ^^^^^^^^^^^^^^^^^ expected `i32`, found `bool`
@@ -43,13 +59,13 @@ LL |     G: FnOnce<ARG, Output = RET> + ~const Drop,
    |                    ^^^^^^^^^^^^ required by this bound in `const_eval_select`
 
 error[E0631]: type mismatch in function arguments
-  --> $DIR/const-eval-select-bad.rs:32:37
+  --> $DIR/const-eval-select-bad.rs:33:32
    |
 LL | const fn foo(n: i32) -> i32 {
    | --------------------------- found signature of `fn(i32) -> _`
 ...
 LL |     const_eval_select((true,), foo, baz);
-   |     -----------------               ^^^ expected signature of `fn(bool) -> _`
+   |     -----------------          ^^^ expected signature of `fn(bool) -> _`
    |     |
    |     required by a bound introduced by this call
    |
@@ -59,7 +75,7 @@ note: required by a bound in `const_eval_select`
 LL |     F: ~const FnOnce<ARG, Output = RET>,
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
 
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0271, E0277, E0631.
 For more information about an error, try `rustc --explain E0271`.
index 5a27ea8783a2f3b149f23057929ff84c75b8d8cc..6007eba8c0906a2f9307ee7887ad7cbaab0f3e90 100644 (file)
@@ -15,6 +15,7 @@ mod rusti {
           target_os = "emscripten",
           target_os = "freebsd",
           target_os = "fuchsia",
+          target_os = "illumos",
           target_os = "linux",
           target_os = "macos",
           target_os = "netbsd",
diff --git a/src/test/ui/issues/auxiliary/issue-19163.rs b/src/test/ui/issues/auxiliary/issue-19163.rs
deleted file mode 100644 (file)
index 0c0d9e4..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#![crate_type = "lib"]
-
-#[macro_export]
-macro_rules! mywrite {
-    ($dst:expr, $($arg:tt)*) => ($dst.write_fmt(format_args!($($arg)*)))
-}
diff --git a/src/test/ui/issues/auxiliary/issue-39823.rs b/src/test/ui/issues/auxiliary/issue-39823.rs
deleted file mode 100644 (file)
index 3af9c68..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#![crate_type="rlib"]
-
-#[derive(Debug, PartialEq)]
-pub struct RemoteC(pub u32);
-
-#[derive(Debug, PartialEq)]
-pub struct RemoteG<T>(pub T);
diff --git a/src/test/ui/issues/auxiliary/xcrate-issue-43189-a.rs b/src/test/ui/issues/auxiliary/xcrate-issue-43189-a.rs
deleted file mode 100644 (file)
index 9ab570f..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#![crate_type="lib"]
-
-
-pub trait A {
-    fn a(&self) {}
-}
-impl A for () {}
diff --git a/src/test/ui/issues/auxiliary/xcrate-issue-43189-b.rs b/src/test/ui/issues/auxiliary/xcrate-issue-43189-b.rs
deleted file mode 100644 (file)
index 31dfb05..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#![crate_type="lib"]
-
-pub extern crate xcrate_issue_43189_a;
diff --git a/src/test/ui/issues/auxiliary/xcrate-issue-46112-rexport-core.rs b/src/test/ui/issues/auxiliary/xcrate-issue-46112-rexport-core.rs
deleted file mode 100644 (file)
index 2b517b5..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#![crate_type="lib"]
-
-pub extern crate core;
diff --git a/src/test/ui/issues/auxiliary/xcrate-issue-61711-b.rs b/src/test/ui/issues/auxiliary/xcrate-issue-61711-b.rs
deleted file mode 100644 (file)
index 88a0405..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-// edition:2018
-#![crate_type="lib"]
-#![crate_name="xcrate_issue_61711_b"]
-pub struct Struct;
-pub use crate as alias;
diff --git a/src/test/ui/issues/issue-10398.rs b/src/test/ui/issues/issue-10398.rs
deleted file mode 100644 (file)
index 0405b2d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#![feature(box_syntax)]
-
-fn main() {
-    let x: Box<_> = box 1;
-    let f = move|| {
-        let _a = x;
-        drop(x);
-        //~^ ERROR: use of moved value: `x`
-    };
-    f();
-}
diff --git a/src/test/ui/issues/issue-10398.stderr b/src/test/ui/issues/issue-10398.stderr
deleted file mode 100644 (file)
index 8d9faf3..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0382]: use of moved value: `x`
-  --> $DIR/issue-10398.rs:7:14
-   |
-LL |         let _a = x;
-   |                  - value moved here
-LL |         drop(x);
-   |              ^ value used here after move
-   |
-   = note: move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/issues/issue-1112.rs b/src/test/ui/issues/issue-1112.rs
deleted file mode 100644 (file)
index 3ba7bb2..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-// Issue #1112
-// Alignment of interior pointers to dynamic-size types
-
-
-struct X<T> {
-    a: T,
-    b: u8,
-    c: bool,
-    d: u8,
-    e: u16,
-    f: u8,
-    g: u8
-}
-
-pub fn main() {
-    let x: X<isize> = X {
-        a: 12345678,
-        b: 9,
-        c: true,
-        d: 10,
-        e: 11,
-        f: 12,
-        g: 13
-    };
-    bar(x);
-}
-
-fn bar<T>(x: X<T>) {
-    assert_eq!(x.b, 9);
-    assert_eq!(x.c, true);
-    assert_eq!(x.d, 10);
-    assert_eq!(x.e, 11);
-    assert_eq!(x.f, 12);
-    assert_eq!(x.g, 13);
-}
diff --git a/src/test/ui/issues/issue-11577.rs b/src/test/ui/issues/issue-11577.rs
deleted file mode 100644 (file)
index 70177c5..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// run-pass
-// Destructuring struct variants would ICE where regular structs wouldn't
-
-enum Foo {
-    VBar { num: isize }
-}
-
-struct SBar { num: isize }
-
-pub fn main() {
-    let vbar = Foo::VBar { num: 1 };
-    let Foo::VBar { num } = vbar;
-    assert_eq!(num, 1);
-
-    let sbar = SBar { num: 2 };
-    let SBar { num } = sbar;
-    assert_eq!(num, 2);
-}
diff --git a/src/test/ui/issues/issue-11940.rs b/src/test/ui/issues/issue-11940.rs
deleted file mode 100644 (file)
index 6815c87..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// run-pass
-
-const TEST_STR: &'static str = "abcd";
-
-fn main() {
-    let s = "abcd";
-    match s {
-        TEST_STR => (),
-        _ => unreachable!()
-    }
-}
diff --git a/src/test/ui/issues/issue-12796.rs b/src/test/ui/issues/issue-12796.rs
deleted file mode 100644 (file)
index 942d6b9..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-trait Trait {
-    fn outer(&self) {
-        fn inner(_: &Self) {
-            //~^ ERROR can't use generic parameters from outer function
-        }
-    }
-}
-
-fn main() { }
diff --git a/src/test/ui/issues/issue-12796.stderr b/src/test/ui/issues/issue-12796.stderr
deleted file mode 100644 (file)
index a01fd2d..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0401]: can't use generic parameters from outer function
-  --> $DIR/issue-12796.rs:3:22
-   |
-LL |         fn inner(_: &Self) {
-   |                      ^^^^
-   |                      |
-   |                      use of generic parameter from outer function
-   |                      can't use `Self` here
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/issues/issue-13483.rs b/src/test/ui/issues/issue-13483.rs
deleted file mode 100644 (file)
index a2fd926..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-fn main() {
-    if true {
-    } else if { //~ ERROR missing condition
-    //~^ ERROR mismatched types
-    } else {
-    }
-}
-
-fn foo() {
-    if true {
-    } else if { //~ ERROR missing condition
-    //~^ ERROR mismatched types
-    }
-    bar();
-}
-
-fn bar() {}
diff --git a/src/test/ui/issues/issue-13483.stderr b/src/test/ui/issues/issue-13483.stderr
deleted file mode 100644 (file)
index 5fd05b1..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-error: missing condition for `if` expression
-  --> $DIR/issue-13483.rs:3:14
-   |
-LL |     } else if {
-   |              ^ expected if condition here
-
-error: missing condition for `if` expression
-  --> $DIR/issue-13483.rs:11:14
-   |
-LL |     } else if {
-   |              ^ expected if condition here
-
-error[E0308]: mismatched types
-  --> $DIR/issue-13483.rs:3:15
-   |
-LL |       } else if {
-   |  _______________^
-LL | |
-LL | |     } else {
-   | |_____^ expected `bool`, found `()`
-
-error[E0308]: mismatched types
-  --> $DIR/issue-13483.rs:11:15
-   |
-LL |       } else if {
-   |  _______________^
-LL | |
-LL | |     }
-   | |_____^ expected `bool`, found `()`
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-13902.rs b/src/test/ui/issues/issue-13902.rs
deleted file mode 100644 (file)
index 1afde0e..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-#![allow(non_camel_case_types)]
-
-const JSVAL_TAG_CLEAR: u32 = 0xFFFFFF80;
-const JSVAL_TYPE_INT32: u8 = 0x01;
-const JSVAL_TYPE_UNDEFINED: u8 = 0x02;
-#[repr(u32)]
-enum ValueTag {
-    JSVAL_TAG_INT32 = JSVAL_TAG_CLEAR | (JSVAL_TYPE_INT32 as u32),
-    JSVAL_TAG_UNDEFINED = JSVAL_TAG_CLEAR | (JSVAL_TYPE_UNDEFINED as u32),
-}
-
-fn main() {
-    let _ = ValueTag::JSVAL_TAG_INT32;
-}
diff --git a/src/test/ui/issues/issue-14227.mir.stderr b/src/test/ui/issues/issue-14227.mir.stderr
deleted file mode 100644 (file)
index 8e7a251..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0133]: use of extern static is unsafe and requires unsafe function or block
-  --> $DIR/issue-14227.rs:7:21
-   |
-LL | static CRASH: u32 = symbol;
-   |                     ^^^^^^ use of extern static
-   |
-   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/issues/issue-14227.rs b/src/test/ui/issues/issue-14227.rs
deleted file mode 100644 (file)
index 5f866ec..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// revisions: mir thir
-// [thir]compile-flags: -Z thir-unsafeck
-
-extern "C" {
-    pub static symbol: u32;
-}
-static CRASH: u32 = symbol;
-//~^ ERROR use of extern static is unsafe and requires
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-14227.thir.stderr b/src/test/ui/issues/issue-14227.thir.stderr
deleted file mode 100644 (file)
index 8e7a251..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0133]: use of extern static is unsafe and requires unsafe function or block
-  --> $DIR/issue-14227.rs:7:21
-   |
-LL | static CRASH: u32 = symbol;
-   |                     ^^^^^^ use of extern static
-   |
-   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/issues/issue-14456.rs b/src/test/ui/issues/issue-14456.rs
deleted file mode 100644 (file)
index 52a56eb..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// run-pass
-#![allow(unused_mut)]
-// ignore-emscripten no processes
-// ignore-sgx no processes
-
-use std::env;
-use std::io::prelude::*;
-use std::io;
-use std::process::{Command, Stdio};
-
-fn main() {
-    let args: Vec<String> = env::args().collect();
-    if args.len() > 1 && args[1] == "child" {
-        return child()
-    }
-
-    test();
-}
-
-fn child() {
-    writeln!(&mut io::stdout(), "foo").unwrap();
-    writeln!(&mut io::stderr(), "bar").unwrap();
-    let mut stdin = io::stdin();
-    let mut s = String::new();
-    stdin.lock().read_line(&mut s).unwrap();
-    assert_eq!(s.len(), 0);
-}
-
-fn test() {
-    let args: Vec<String> = env::args().collect();
-    let mut p = Command::new(&args[0]).arg("child")
-                                     .stdin(Stdio::piped())
-                                     .stdout(Stdio::piped())
-                                     .stderr(Stdio::piped())
-                                     .spawn().unwrap();
-    assert!(p.wait().unwrap().success());
-}
diff --git a/src/test/ui/issues/issue-14589.rs b/src/test/ui/issues/issue-14589.rs
deleted file mode 100644 (file)
index 5d8aab2..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// run-pass
-// All 3 expressions should work in that the argument gets
-// coerced to a trait object
-
-// pretty-expanded FIXME #23616
-
-fn main() {
-    send::<Box<dyn Foo>>(Box::new(Output(0)));
-    Test::<Box<dyn Foo>>::foo(Box::new(Output(0)));
-    Test::<Box<dyn Foo>>::new().send(Box::new(Output(0)));
-}
-
-fn send<T>(_: T) {}
-
-struct Test<T> { marker: std::marker::PhantomData<T> }
-impl<T> Test<T> {
-    fn new() -> Test<T> { Test { marker: ::std::marker::PhantomData } }
-    fn foo(_: T) {}
-    fn send(&self, _: T) {}
-}
-
-trait Foo { fn dummy(&self) { }}
-struct Output(isize);
-impl Foo for Output {}
diff --git a/src/test/ui/issues/issue-14837.rs b/src/test/ui/issues/issue-14837.rs
deleted file mode 100644 (file)
index a83bc41..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// check-pass
-// pretty-expanded FIXME #23616
-
-#[deny(dead_code)]
-pub enum Foo {
-    Bar {
-        baz: isize
-    }
-}
-
-fn main() { }
diff --git a/src/test/ui/issues/issue-15080.rs b/src/test/ui/issues/issue-15080.rs
deleted file mode 100644 (file)
index 4dd6981..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// run-pass
-
-fn main() {
-    let mut x: &[_] = &[1, 2, 3, 4];
-
-    let mut result = vec![];
-    loop {
-        x = match *x {
-            [1, n, 3, ref rest @ ..] => {
-                result.push(n);
-                rest
-            }
-            [n, ref rest @ ..] => {
-                result.push(n);
-                rest
-            }
-            [] =>
-                break
-        }
-    }
-    assert_eq!(result, [2, 4]);
-}
diff --git a/src/test/ui/issues/issue-16098.rs b/src/test/ui/issues/issue-16098.rs
deleted file mode 100644 (file)
index 00acc20..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-macro_rules! prob1 {
-    (0) => {
-        0
-    };
-    ($n:expr) => {
-        if ($n % 3 == 0) || ($n % 5 == 0) {
-            $n + prob1!($n - 1); //~ ERROR recursion limit reached while expanding `prob1!`
-        } else {
-            prob1!($n - 1);
-        }
-    };
-}
-
-fn main() {
-    println!("Problem 1: {}", prob1!(1000));
-}
diff --git a/src/test/ui/issues/issue-16098.stderr b/src/test/ui/issues/issue-16098.stderr
deleted file mode 100644 (file)
index 6428021..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: recursion limit reached while expanding `prob1!`
-  --> $DIR/issue-16098.rs:7:18
-   |
-LL |             $n + prob1!($n - 1);
-   |                  ^^^^^^^^^^^^^^
-...
-LL |     println!("Problem 1: {}", prob1!(1000));
-   |                               ------------ in this macro invocation
-   |
-   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_16098`)
-   = note: this error originates in the macro `prob1` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-16272.rs b/src/test/ui/issues/issue-16272.rs
deleted file mode 100644 (file)
index 5cf3fd9..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// run-pass
-// ignore-emscripten no processes
-// ignore-sgx no processes
-
-use std::process::Command;
-use std::env;
-
-fn main() {
-    let len = env::args().len();
-
-    if len == 1 {
-        test();
-    } else {
-        assert_eq!(len, 3);
-    }
-}
-
-fn test() {
-    let status = Command::new(&env::current_exe().unwrap())
-                         .arg("foo").arg("")
-                         .status().unwrap();
-    assert!(status.success());
-}
diff --git a/src/test/ui/issues/issue-17074.rs b/src/test/ui/issues/issue-17074.rs
deleted file mode 100644 (file)
index 0ed8113..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-
-static X2: u64 = !0 as u16 as u64;
-static Y2: u64 = !0 as u32 as u64;
-const X: u64 = !0 as u16 as u64;
-const Y: u64 = !0 as u32 as u64;
-
-fn main() {
-    assert_eq!(match 1 {
-        X => unreachable!(),
-        Y => unreachable!(),
-        _ => 1
-    }, 1);
-}
diff --git a/src/test/ui/issues/issue-18060.rs b/src/test/ui/issues/issue-18060.rs
deleted file mode 100644 (file)
index b5f3d0f..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-pass
-// Regression test for #18060: match arms were matching in the wrong order.
-
-fn main() {
-    assert_eq!(2, match (1, 3) { (0, 2..=5) => 1, (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 });
-    assert_eq!(2, match (1, 3) {                  (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 });
-    assert_eq!(2, match (1, 7) { (0, 2..=5) => 1, (1, 7) => 2, (_, 2..=5) => 3, (_, _) => 4 });
-}
diff --git a/src/test/ui/issues/issue-18294.rs b/src/test/ui/issues/issue-18294.rs
deleted file mode 100644 (file)
index 77355f0..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-fn main() {
-    const X: u32 = 1;
-    const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR pointers cannot be cast to integers
-    println!("{}", Y);
-}
diff --git a/src/test/ui/issues/issue-18294.stderr b/src/test/ui/issues/issue-18294.stderr
deleted file mode 100644 (file)
index e0cbd2a..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error: pointers cannot be cast to integers during const eval
-  --> $DIR/issue-18294.rs:3:31
-   |
-LL |     const Y: usize = unsafe { &X as *const u32 as usize };
-   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: at compile-time, pointers do not have an integer value
-   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-18652.rs b/src/test/ui/issues/issue-18652.rs
deleted file mode 100644 (file)
index 59aa015..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// run-pass
-// Tests multiple free variables being passed by value into an unboxed
-// once closure as an optimization by codegen.  This used to hit an
-// incorrect assert.
-
-fn main() {
-    let x = 2u8;
-    let y = 3u8;
-    assert_eq!((move || x + y)(), 5);
-}
diff --git a/src/test/ui/issues/issue-19163.rs b/src/test/ui/issues/issue-19163.rs
deleted file mode 100644 (file)
index d98c591..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// aux-build:issue-19163.rs
-
-#[macro_use] extern crate issue_19163;
-
-use std::io::Write;
-
-fn main() {
-    let mut v = vec![];
-    mywrite!(&v, "Hello world");
-    //~^ ERROR cannot borrow data in a `&` reference as mutable
-}
diff --git a/src/test/ui/issues/issue-19163.stderr b/src/test/ui/issues/issue-19163.stderr
deleted file mode 100644 (file)
index ae1ae14..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/issue-19163.rs:9:5
-   |
-LL |     mywrite!(&v, "Hello world");
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
-   |
-   = note: this error originates in the macro `mywrite` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/issues/issue-19358.rs b/src/test/ui/issues/issue-19358.rs
deleted file mode 100644 (file)
index 3970a41..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// run-pass
-
-#![allow(dead_code)]
-
-trait Trait { fn dummy(&self) { } }
-
-#[derive(Debug)]
-struct Foo<T: Trait> {
-    foo: T,
-}
-
-#[derive(Debug)]
-struct Bar<T> where T: Trait {
-    bar: T,
-}
-
-impl Trait for isize {}
-
-fn main() {
-    let a = Foo { foo: 12 };
-    let b = Bar { bar: 12 };
-    println!("{:?} {:?}", a, b);
-}
diff --git a/src/test/ui/issues/issue-19660.rs b/src/test/ui/issues/issue-19660.rs
deleted file mode 100644 (file)
index 400ac31..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// error-pattern: requires `copy` lang_item
-
-#![feature(lang_items, start, no_core)]
-#![no_core]
-
-#[lang = "sized"]
-trait Sized { }
-
-struct S;
-
-#[start]
-fn main(_: isize, _: *const *const u8) -> isize {
-    let _ = S;
-    0
-}
diff --git a/src/test/ui/issues/issue-19660.stderr b/src/test/ui/issues/issue-19660.stderr
deleted file mode 100644 (file)
index f5d903f..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-error: requires `copy` lang_item
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-20091.rs b/src/test/ui/issues/issue-20091.rs
deleted file mode 100644 (file)
index 86cc79d..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// run-pass
-#![allow(stable_features)]
-
-// ignore-emscripten no processes
-// ignore-sgx no processes
-
-#![feature(os)]
-
-#[cfg(unix)]
-fn main() {
-    use std::process::Command;
-    use std::env;
-    use std::os::unix::prelude::*;
-    use std::ffi::OsStr;
-
-    if env::args().len() == 1 {
-        assert!(Command::new(&env::current_exe().unwrap())
-                        .arg(<OsStr as OsStrExt>::from_bytes(b"\xff"))
-                        .status().unwrap().success())
-    }
-}
-
-#[cfg(windows)]
-fn main() {}
diff --git a/src/test/ui/issues/issue-20616-4.rs b/src/test/ui/issues/issue-20616-4.rs
deleted file mode 100644 (file)
index a71f47c..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// We need all these 9 issue-20616-N.rs files
-// because we can only catch one parsing error at a time
-
-type Type_1_<'a, T> = &'a T;
-
-
-//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
-
-
-//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
-
-
-//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
-
-
-type Type_4<T> = Type_1_<'static,, T>;
-//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
-
-
-type Type_5_<'a> = Type_1_<'a, ()>;
-
-
-//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
-
-
-//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
-
-
-//type Type_7 = Box<(),,>; // error: expected type, found `,`
-
-
-//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
-
-
-//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/issues/issue-20616-4.stderr b/src/test/ui/issues/issue-20616-4.stderr
deleted file mode 100644 (file)
index 2b3b75f..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: expected one of `>`, a const expression, lifetime, or type, found `,`
-  --> $DIR/issue-20616-4.rs:16:34
-   |
-LL | type Type_4<T> = Type_1_<'static,, T>;
-   |                                  ^ expected one of `>`, a const expression, lifetime, or type
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-20616-5.rs b/src/test/ui/issues/issue-20616-5.rs
deleted file mode 100644 (file)
index b96d09d..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// We need all these 9 issue-20616-N.rs files
-// because we can only catch one parsing error at a time
-
-type Type_1_<'a, T> = &'a T;
-
-
-//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
-
-
-//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
-
-
-//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
-
-
-//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
-
-
-type Type_5_<'a> = Type_1_<'a, ()>;
-
-
-type Type_5<'a> = Type_1_<'a, (),,>;
-//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
-
-
-//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
-
-
-//type Type_7 = Box<(),,>; // error: expected type, found `,`
-
-
-//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
-
-
-//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/issues/issue-20616-5.stderr b/src/test/ui/issues/issue-20616-5.stderr
deleted file mode 100644 (file)
index 1ec1dbd..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: expected one of `>`, a const expression, lifetime, or type, found `,`
-  --> $DIR/issue-20616-5.rs:22:34
-   |
-LL | type Type_5<'a> = Type_1_<'a, (),,>;
-   |                                  ^ expected one of `>`, a const expression, lifetime, or type
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-20616-6.rs b/src/test/ui/issues/issue-20616-6.rs
deleted file mode 100644 (file)
index a2c45ec..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// We need all these 9 issue-20616-N.rs files
-// because we can only catch one parsing error at a time
-
-type Type_1_<'a, T> = &'a T;
-
-
-//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
-
-
-//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
-
-
-//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
-
-
-//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
-
-
-type Type_5_<'a> = Type_1_<'a, ()>;
-
-
-//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
-
-
-type Type_6 = Type_5_<'a,,>;
-//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
-
-
-//type Type_7 = Box<(),,>; // error: expected type, found `,`
-
-
-//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
-
-
-//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/issues/issue-20616-6.stderr b/src/test/ui/issues/issue-20616-6.stderr
deleted file mode 100644 (file)
index 7401abd..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: expected one of `>`, a const expression, lifetime, or type, found `,`
-  --> $DIR/issue-20616-6.rs:25:26
-   |
-LL | type Type_6 = Type_5_<'a,,>;
-   |                          ^ expected one of `>`, a const expression, lifetime, or type
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-20616-7.rs b/src/test/ui/issues/issue-20616-7.rs
deleted file mode 100644 (file)
index 67209c0..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// We need all these 9 issue-20616-N.rs files
-// because we can only catch one parsing error at a time
-
-type Type_1_<'a, T> = &'a T;
-
-
-//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
-
-
-//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
-
-
-//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
-
-
-//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
-
-
-type Type_5_<'a> = Type_1_<'a, ()>;
-
-
-//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
-
-
-//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
-
-
-type Type_7 = Box<(),,>;
-//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
-
-
-//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
-
-
-//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/issues/issue-20616-7.stderr b/src/test/ui/issues/issue-20616-7.stderr
deleted file mode 100644 (file)
index e2c3efe..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: expected one of `>`, a const expression, lifetime, or type, found `,`
-  --> $DIR/issue-20616-7.rs:28:22
-   |
-LL | type Type_7 = Box<(),,>;
-   |                      ^ expected one of `>`, a const expression, lifetime, or type
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-20823.rs b/src/test/ui/issues/issue-20823.rs
deleted file mode 100644 (file)
index 9e209d5..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-// run-pass
-// compile-flags: --test
-
-#[test]
-pub fn foo() {}
diff --git a/src/test/ui/issues/issue-21356.rs b/src/test/ui/issues/issue-21356.rs
deleted file mode 100644 (file)
index ae62392..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#![allow(unused_macros)]
-
-macro_rules! test { ($wrong:t_ty ..) => () }
-                  //~^ ERROR: invalid fragment specifier `t_ty`
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-21356.stderr b/src/test/ui/issues/issue-21356.stderr
deleted file mode 100644 (file)
index 17014c6..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-error: invalid fragment specifier `t_ty`
-  --> $DIR/issue-21356.rs:3:22
-   |
-LL | macro_rules! test { ($wrong:t_ty ..) => () }
-   |                      ^^^^^^^^^^^
-   |
-   = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-21475.rs b/src/test/ui/issues/issue-21475.rs
deleted file mode 100644 (file)
index b028fca..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// run-pass
-#![allow(unused_imports, overlapping_range_endpoints)]
-// pretty-expanded FIXME #23616
-
-use m::{START, END};
-
-fn main() {
-    match 42 {
-        m::START..=m::END => {},
-        0..=m::END => {},
-        m::START..=59 => {},
-        _  => {},
-    }
-}
-
-mod m {
-  pub const START: u32 = 4;
-  pub const END:   u32 = 14;
-}
diff --git a/src/test/ui/issues/issue-21520.rs b/src/test/ui/issues/issue-21520.rs
deleted file mode 100644 (file)
index ab4ac72..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// check-pass
-#![allow(dead_code)]
-// Test that the requirement (in `Bar`) that `T::Bar : 'static` does
-// not wind up propagating to `T`.
-
-// pretty-expanded FIXME #23616
-
-pub trait Foo {
-    type Bar;
-
-    fn foo(&self) -> Self;
-}
-
-pub struct Static<T:'static>(T);
-
-struct Bar<T:Foo>
-    where T::Bar : 'static
-{
-    x: Static<Option<T::Bar>>
-}
-
-fn main() { }
diff --git a/src/test/ui/issues/issue-22066.rs b/src/test/ui/issues/issue-22066.rs
deleted file mode 100644 (file)
index 8e8ba5d..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// check-pass
-pub trait LineFormatter<'a> {
-    type Iter: Iterator<Item=&'a str> + 'a;
-    fn iter(&'a self, line: &'a str) -> Self::Iter;
-
-    fn dimensions(&'a self, line: &'a str) {
-        let iter: Self::Iter = self.iter(line);
-        <_ as IntoIterator>::into_iter(iter);
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-22463.rs b/src/test/ui/issues/issue-22463.rs
deleted file mode 100644 (file)
index fdf5a2f..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// run-pass
-macro_rules! items {
-    () => {
-        type A = ();
-        fn a() {}
-    }
-}
-
-trait Foo {
-    type A;
-    fn a();
-}
-
-impl Foo for () {
-    items!();
-}
-
-fn main() {
-
-}
diff --git a/src/test/ui/issues/issue-22828.rs b/src/test/ui/issues/issue-22828.rs
deleted file mode 100644 (file)
index adf4dd6..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-// Test transitive analysis for associated types. Collected types
-// should be normalized and new obligations generated.
-
-// pretty-expanded FIXME #23616
-
-trait Foo {
-    type A;
-    fn foo(&self) {}
-}
-
-impl Foo for usize {
-    type A = usize;
-}
-
-struct Bar<T: Foo> { inner: T::A }
-
-fn is_send<T: Send>() {}
-
-fn main() {
-    is_send::<Bar<usize>>();
-}
diff --git a/src/test/ui/issues/issue-23458.rs b/src/test/ui/issues/issue-23458.rs
deleted file mode 100644 (file)
index d640828..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#![feature(llvm_asm)]
-#![allow(deprecated)] // llvm_asm!
-// compile-flags: -Ccodegen-units=1
-// build-fail
-// only-x86_64
-
-fn main() {
-    unsafe {
-        llvm_asm!("int $3"); //~ ERROR too few operands for instruction
-                             //~| ERROR invalid operand in inline asm
-    }
-}
diff --git a/src/test/ui/issues/issue-23458.stderr b/src/test/ui/issues/issue-23458.stderr
deleted file mode 100644 (file)
index 69e458f..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error: invalid operand in inline asm: 'int $3'
-  --> $DIR/issue-23458.rs:9:9
-   |
-LL |         llvm_asm!("int $3");
-   |         ^
-
-error: too few operands for instruction
-  --> $DIR/issue-23458.rs:9:9
-   |
-LL |         llvm_asm!("int $3");
-   |         ^
-   |
-note: instantiated into assembly here
-  --> <inline asm>:1:2
-   |
-LL |     int 
-   |     ^
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/issues/issue-23716.rs b/src/test/ui/issues/issue-23716.rs
deleted file mode 100644 (file)
index e9139c0..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-static foo: i32 = 0;
-
-fn bar(foo: i32) {}
-//~^ ERROR function parameters cannot shadow statics
-//~| cannot be named the same as a static
-
-mod submod {
-    pub static answer: i32 = 42;
-}
-
-use self::submod::answer;
-
-fn question(answer: i32) {}
-//~^ ERROR function parameters cannot shadow statics
-//~| cannot be named the same as a static
-fn main() {
-}
diff --git a/src/test/ui/issues/issue-23716.stderr b/src/test/ui/issues/issue-23716.stderr
deleted file mode 100644 (file)
index e7bebfb..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0530]: function parameters cannot shadow statics
-  --> $DIR/issue-23716.rs:3:8
-   |
-LL | static foo: i32 = 0;
-   | -------------------- the static `foo` is defined here
-LL | 
-LL | fn bar(foo: i32) {}
-   |        ^^^ cannot be named the same as a static
-
-error[E0530]: function parameters cannot shadow statics
-  --> $DIR/issue-23716.rs:13:13
-   |
-LL | use self::submod::answer;
-   |     -------------------- the static `answer` is imported here
-LL | 
-LL | fn question(answer: i32) {}
-   |             ^^^^^^ cannot be named the same as a static
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0530`.
diff --git a/src/test/ui/issues/issue-23968-const-not-overflow.rs b/src/test/ui/issues/issue-23968-const-not-overflow.rs
deleted file mode 100644 (file)
index b959302..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// run-pass
-const U8_MAX_HALF: u8 = !0u8 / 2;
-const U16_MAX_HALF: u16 = !0u16 / 2;
-const U32_MAX_HALF: u32 = !0u32 / 2;
-const U64_MAX_HALF: u64 = !0u64 / 2;
-
-fn main() {
-    assert_eq!(U8_MAX_HALF, 0x7f);
-    assert_eq!(U16_MAX_HALF, 0x7fff);
-    assert_eq!(U32_MAX_HALF, 0x7fff_ffff);
-    assert_eq!(U64_MAX_HALF, 0x7fff_ffff_ffff_ffff);
-}
diff --git a/src/test/ui/issues/issue-24010.rs b/src/test/ui/issues/issue-24010.rs
deleted file mode 100644 (file)
index f181853..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// run-pass
-
-trait Foo: Fn(i32) -> i32 + Send {}
-
-impl<T: ?Sized + Fn(i32) -> i32 + Send> Foo for T {}
-
-fn wants_foo(f: Box<dyn Foo>) -> i32 {
-    f(42)
-}
-
-fn main() {
-    let f = Box::new(|x| x);
-    assert_eq!(wants_foo(f), 42);
-}
diff --git a/src/test/ui/issues/issue-24313.rs b/src/test/ui/issues/issue-24313.rs
deleted file mode 100644 (file)
index c28b4ca..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// run-pass
-// ignore-emscripten no threads
-// ignore-sgx no processes
-
-use std::thread;
-use std::env;
-use std::process::Command;
-
-struct Handle(i32);
-
-impl Drop for Handle {
-    fn drop(&mut self) { panic!(); }
-}
-
-thread_local!(static HANDLE: Handle = Handle(0));
-
-fn main() {
-    let args = env::args().collect::<Vec<_>>();
-    if args.len() == 1 {
-        let out = Command::new(&args[0]).arg("test").output().unwrap();
-        let stderr = std::str::from_utf8(&out.stderr).unwrap();
-        assert!(stderr.contains("panicked at 'explicit panic'"),
-                "bad failure message:\n{}\n", stderr);
-    } else {
-        // TLS dtors are not always run on process exit
-        thread::spawn(|| {
-            HANDLE.with(|h| {
-                println!("{}", h.0);
-            });
-        }).join().unwrap();
-    }
-}
diff --git a/src/test/ui/issues/issue-2444.rs b/src/test/ui/issues/issue-2444.rs
deleted file mode 100644 (file)
index ac0d050..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// run-fail
-// error-pattern:explicit panic
-// ignore-emscripten no processes
-
-use std::sync::Arc;
-
-enum Err<T> {
-    Errr(Arc<T>),
-}
-
-fn foo() -> Err<isize> {
-    panic!();
-}
-
-fn main() {
-    let _f = foo();
-}
diff --git a/src/test/ui/issues/issue-26251.rs b/src/test/ui/issues/issue-26251.rs
deleted file mode 100644 (file)
index a3e26a4..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// run-pass
-#![allow(overlapping_range_endpoints)]
-
-fn main() {
-    let x = 'a';
-
-    let y = match x {
-        'a'..='b' if false => "one",
-        'a' => "two",
-        'a'..='b' => "three",
-        _ => panic!("what?"),
-    };
-
-    assert_eq!(y, "two");
-}
diff --git a/src/test/ui/issues/issue-26448-1.rs b/src/test/ui/issues/issue-26448-1.rs
deleted file mode 100644 (file)
index 7d2d75b..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// run-pass
-
-pub trait Foo<T> {
-    fn foo(self) -> T;
-}
-
-impl<'a, T> Foo<T> for &'a str where &'a str: Into<T> {
-    fn foo(self) -> T {
-        panic!();
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-26448-2.rs b/src/test/ui/issues/issue-26448-2.rs
deleted file mode 100644 (file)
index c60e06c..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// check-pass
-
-pub struct Bar<T> {
-    items: Vec<&'static str>,
-    inner: T,
-}
-
-pub trait IntoBar<T> {
-    fn into_bar(self) -> Bar<T>;
-}
-
-impl<'a, T> IntoBar<T> for &'a str where &'a str: Into<T> {
-    fn into_bar(self) -> Bar<T> {
-        Bar {
-            items: Vec::new(),
-            inner: self.into(),
-        }
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-26448-3.rs b/src/test/ui/issues/issue-26448-3.rs
deleted file mode 100644 (file)
index d48022c..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// check-pass
-
-pub struct Item {
-    _inner: &'static str,
-}
-
-pub struct Bar<T> {
-    items: Vec<Item>,
-    inner: T,
-}
-
-pub trait IntoBar<T> {
-    fn into_bar(self) -> Bar<T>;
-}
-
-impl<'a, T> IntoBar<T> for &'a str where &'a str: Into<T> {
-    fn into_bar(self) -> Bar<T> {
-        Bar {
-            items: Vec::new(),
-            inner: self.into(),
-        }
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-26638.rs b/src/test/ui/issues/issue-26638.rs
deleted file mode 100644 (file)
index 72fe428..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() }
-//~^ ERROR missing lifetime specifier [E0106]
-
-fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
-//~^ ERROR missing lifetime specifier [E0106]
-
-fn parse_type_3() -> &str { unimplemented!() }
-//~^ ERROR missing lifetime specifier [E0106]
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-26638.stderr b/src/test/ui/issues/issue-26638.stderr
deleted file mode 100644 (file)
index bb7cdcb..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-error[E0106]: missing lifetime specifier
-  --> $DIR/issue-26638.rs:1:62
-   |
-LL | fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() }
-   |                     ------------------------------------     ^ expected named lifetime parameter
-   |
-   = help: this function's return type contains a borrowed value, but the signature does not say which one of `iter`'s 2 lifetimes it is borrowed from
-help: consider introducing a named lifetime parameter
-   |
-LL | fn parse_type<'a>(iter: Box<dyn Iterator<Item=&str>+'static>) -> &'a str { iter.next() }
-   |              ++++                                                 ++
-
-error[E0106]: missing lifetime specifier
-  --> $DIR/issue-26638.rs:4:40
-   |
-LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
-   |                                        ^ expected named lifetime parameter
-   |
-   = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
-help: consider using the `'static` lifetime
-   |
-LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &'static str { iter() }
-   |                                        ~~~~~~~~
-
-error[E0106]: missing lifetime specifier
-  --> $DIR/issue-26638.rs:7:22
-   |
-LL | fn parse_type_3() -> &str { unimplemented!() }
-   |                      ^ expected named lifetime parameter
-   |
-   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
-help: consider using the `'static` lifetime
-   |
-LL | fn parse_type_3() -> &'static str { unimplemented!() }
-   |                      ~~~~~~~~
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/issues/issue-26996.rs b/src/test/ui/issues/issue-26996.rs
deleted file mode 100644 (file)
index 84037b7..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// run-pass
-
-// This test is bogus (i.e., should be check-fail) during the period
-// where #54986 is implemented and #54987 is *not* implemented. For
-// now: just ignore it
-//
-// ignore-test
-
-// This test is checking that the write to `c.0` (which has been moved out of)
-// won't overwrite the state in `c2`.
-//
-// That's a fine thing to test when this code is accepted by the
-// compiler, and this code is being transcribed accordingly into
-// the ui test issue-21232-partial-init-and-use.rs
-
-fn main() {
-    let mut c = (1, "".to_owned());
-    match c {
-        c2 => {
-            c.0 = 2;
-            assert_eq!(c2.0, 1);
-        }
-    }
-}
diff --git a/src/test/ui/issues/issue-2748-b.rs b/src/test/ui/issues/issue-2748-b.rs
deleted file mode 100644 (file)
index 8df735a..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// run-pass
-
-fn thing<'r>(x: &'r [isize]) -> &'r [isize] { x }
-
-pub fn main() {
-    let x = &[1,2,3];
-    let y = x;
-    let z = thing(x);
-    assert_eq!(z[2], x[2]);
-    assert_eq!(z[1], y[1]);
-}
diff --git a/src/test/ui/issues/issue-28324.mir.stderr b/src/test/ui/issues/issue-28324.mir.stderr
deleted file mode 100644 (file)
index aff8bf7..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0133]: use of extern static is unsafe and requires unsafe function or block
-  --> $DIR/issue-28324.rs:8:24
-   |
-LL | pub static BAZ: u32 = *&error_message_count;
-   |                        ^^^^^^^^^^^^^^^^^^^^ use of extern static
-   |
-   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/issues/issue-28324.rs b/src/test/ui/issues/issue-28324.rs
deleted file mode 100644 (file)
index fbe83e3..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// revisions: mir thir
-// [thir]compile-flags: -Z thir-unsafeck
-
-extern "C" {
-    static error_message_count: u32;
-}
-
-pub static BAZ: u32 = *&error_message_count;
-//~^ ERROR use of extern static is unsafe and requires
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-28324.thir.stderr b/src/test/ui/issues/issue-28324.thir.stderr
deleted file mode 100644 (file)
index c696c35..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0133]: use of extern static is unsafe and requires unsafe function or block
-  --> $DIR/issue-28324.rs:8:25
-   |
-LL | pub static BAZ: u32 = *&error_message_count;
-   |                         ^^^^^^^^^^^^^^^^^^^ use of extern static
-   |
-   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/issues/issue-28498-ugeh-with-passed-to-fn.rs b/src/test/ui/issues/issue-28498-ugeh-with-passed-to-fn.rs
deleted file mode 100644 (file)
index 23fd86a..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-// run-pass
-
-// Demonstrate the use of the unguarded escape hatch with a type param in negative position
-// to assert that destructor will not access any dead data.
-//
-// Compare with ui/span/issue28498-reject-lifetime-param.rs
-
-// Demonstrate that a type param in negative position causes dropck to reject code
-// that might indirectly access previously dropped value.
-//
-// Compare with run-pass/issue28498-ugeh-with-passed-to-fn.rs
-
-#![feature(dropck_eyepatch)]
-
-#[derive(Debug)]
-struct ScribbleOnDrop(String);
-
-impl Drop for ScribbleOnDrop {
-    fn drop(&mut self) {
-        self.0 = format!("DROPPED");
-    }
-}
-
-struct Foo<T>(u32, T, Box<for <'r> fn(&'r T) -> String>);
-
-unsafe impl<#[may_dangle] T> Drop for Foo<T> {
-    fn drop(&mut self) {
-        // Use of `may_dangle` is sound, because destructor never passes a `self.1`
-        // to the callback (in `self.2`) despite having it available.
-        println!("Dropping Foo({}, _)", self.0);
-    }
-}
-
-fn callback(s: & &ScribbleOnDrop) -> String { format!("{:?}", s) }
-
-fn main() {
-    let (last_dropped, foo0);
-    let (foo1, first_dropped);
-
-    last_dropped = ScribbleOnDrop(format!("last"));
-    first_dropped = ScribbleOnDrop(format!("first"));
-    foo0 = Foo(0, &last_dropped, Box::new(callback));
-    foo1 = Foo(1, &first_dropped, Box::new(callback));
-
-    println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
-}
diff --git a/src/test/ui/issues/issue-28871.rs b/src/test/ui/issues/issue-28871.rs
deleted file mode 100644 (file)
index 210c783..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// check-pass
-// Regression test for #28871. The problem is that rustc encountered
-// two ways to project, one from a where clause and one from the where
-// clauses on the trait definition. (In fact, in this case, the where
-// clauses originated from the trait definition as well.) The true
-// cause of the error is that the trait definition where clauses are
-// not being normalized, and hence the two sources are considered in
-// conflict, and not a duplicate. Hacky solution is to prefer where
-// clauses over the data found in the trait definition.
-
-trait T {
-    type T;
-}
-
-struct S;
-impl T for S {
-    type T = S;
-}
-
-trait T2 {
-    type T: Iterator<Item=<S as T>::T>;
-}
-
-fn main() { }
diff --git a/src/test/ui/issues/issue-29084.rs b/src/test/ui/issues/issue-29084.rs
deleted file mode 100644 (file)
index d162526..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-macro_rules! foo {
-    ($d:expr) => {{
-        fn bar(d: u8) { }
-        bar(&mut $d);
-        //~^ ERROR mismatched types
-        //~| expected `u8`, found `&mut u8`
-    }}
-}
-
-fn main() {
-    foo!(0u8);
-    //~^ in this expansion of foo!
-}
diff --git a/src/test/ui/issues/issue-29084.stderr b/src/test/ui/issues/issue-29084.stderr
deleted file mode 100644 (file)
index a973e23..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-29084.rs:4:13
-   |
-LL |         bar(&mut $d);
-   |             ^^^^^^^ expected `u8`, found `&mut u8`
-...
-LL |     foo!(0u8);
-   |     --------- in this macro invocation
-   |
-   = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-3021-c.rs b/src/test/ui/issues/issue-3021-c.rs
deleted file mode 100644 (file)
index 94ed1fd..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-fn siphash<T>() {
-
-    trait U {
-        fn g(&self, x: T) -> T;  //~ ERROR can't use generic parameters from outer function
-        //~^ ERROR can't use generic parameters from outer function
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-3021-c.stderr b/src/test/ui/issues/issue-3021-c.stderr
deleted file mode 100644 (file)
index 8764ac8..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-error[E0401]: can't use generic parameters from outer function
-  --> $DIR/issue-3021-c.rs:4:24
-   |
-LL | fn siphash<T>() {
-   |            - type parameter from outer function
-...
-LL |         fn g(&self, x: T) -> T;
-   |            -           ^ use of generic parameter from outer function
-   |            |
-   |            help: try using a local generic parameter instead: `g<T>`
-
-error[E0401]: can't use generic parameters from outer function
-  --> $DIR/issue-3021-c.rs:4:30
-   |
-LL | fn siphash<T>() {
-   |            - type parameter from outer function
-...
-LL |         fn g(&self, x: T) -> T;
-   |            -                 ^ use of generic parameter from outer function
-   |            |
-   |            help: try using a local generic parameter instead: `g<T>`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/issues/issue-3021.rs b/src/test/ui/issues/issue-3021.rs
deleted file mode 100644 (file)
index a672261..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-trait SipHash {
-    fn reset(&self);
-}
-
-fn siphash(k0 : u64) {
-    struct SipState {
-        v0: u64,
-    }
-
-    impl SipHash for SipState {
-        fn reset(&self) {
-           self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR can't capture dynamic environment
-        }
-    }
-    panic!();
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-3021.stderr b/src/test/ui/issues/issue-3021.stderr
deleted file mode 100644 (file)
index d5b015e..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0434]: can't capture dynamic environment in a fn item
-  --> $DIR/issue-3021.rs:12:22
-   |
-LL |            self.v0 = k0 ^ 0x736f6d6570736575;
-   |                      ^^
-   |
-   = help: use the `|| { ... }` closure form instead
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0434`.
diff --git a/src/test/ui/issues/issue-30225.rs b/src/test/ui/issues/issue-30225.rs
deleted file mode 100644 (file)
index 4231533..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-// Regression test for #30225, which was an ICE that would trigger as
-// a result of a poor interaction between trait result caching and
-// type inference. Specifically, at that time, unification could cause
-// unrelated type variables to become instantiated, if subtyping
-// relationships existed. These relationships are now propagated
-// through obligations and hence everything works out fine.
-
-trait Foo<U,V> : Sized {
-    fn foo(self, u: Option<U>, v: Option<V>) {}
-}
-
-struct A;
-struct B;
-
-impl Foo<A, B> for () {}      // impl A
-impl Foo<u32, u32> for u32 {} // impl B, creating ambiguity
-
-fn toxic() {
-    // cache the resolution <() as Foo<$0,$1>> = impl A
-    let u = None;
-    let v = None;
-    Foo::foo((), u, v);
-}
-
-fn bomb() {
-    let mut u = None; // type is Option<$0>
-    let mut v = None; // type is Option<$1>
-    let mut x = None; // type is Option<$2>
-
-    Foo::foo(x.unwrap(),u,v); // register <$2 as Foo<$0, $1>>
-    u = v; // mark $0 and $1 in a subtype relationship
-    //~^ ERROR mismatched types
-    x = Some(()); // set $2 = (), allowing impl selection
-                  // to proceed for <() as Foo<$0, $1>> = impl A.
-                  // kaboom, this *used* to trigge an ICE
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-30225.stderr b/src/test/ui/issues/issue-30225.stderr
deleted file mode 100644 (file)
index ccd05fa..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-30225.rs:31:9
-   |
-LL |     u = v; // mark $0 and $1 in a subtype relationship
-   |         ^ expected struct `A`, found struct `B`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-30355.rs b/src/test/ui/issues/issue-30355.rs
deleted file mode 100644 (file)
index 6ff5b37..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-pub struct X([u8]);
-
-pub static Y: &'static X = {
-    const Y: &'static [u8] = b"";
-    &X(*Y)
-    //~^ ERROR E0277
-};
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-30355.stderr b/src/test/ui/issues/issue-30355.stderr
deleted file mode 100644 (file)
index 71bbdf5..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/issue-30355.rs:5:8
-   |
-LL |     &X(*Y)
-   |        ^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `[u8]`
-   = note: all function arguments must have a statically known size
-   = help: unsized fn params are gated as an unstable feature
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-31076.rs b/src/test/ui/issues/issue-31076.rs
deleted file mode 100644 (file)
index cdb196d..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#![feature(no_core, lang_items)]
-#![no_core]
-
-#[lang="sized"]
-trait Sized {}
-
-#[lang="add"]
-trait Add<T> {}
-
-impl Add<i32> for i32 {}
-
-fn main() {
-    let x = 5 + 6;
-    //~^ ERROR cannot add `i32` to `{integer}`
-    let y = 5i32 + 6i32;
-    //~^ ERROR cannot add `i32` to `i32`
-}
diff --git a/src/test/ui/issues/issue-31076.stderr b/src/test/ui/issues/issue-31076.stderr
deleted file mode 100644 (file)
index ac0d9dc..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0369]: cannot add `i32` to `{integer}`
-  --> $DIR/issue-31076.rs:13:15
-   |
-LL |     let x = 5 + 6;
-   |             - ^ - i32
-   |             |
-   |             {integer}
-
-error[E0369]: cannot add `i32` to `i32`
-  --> $DIR/issue-31076.rs:15:18
-   |
-LL |     let y = 5i32 + 6i32;
-   |             ---- ^ ---- i32
-   |             |
-   |             i32
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0369`.
index abed18d81f8d31d27882ad7ba2d74bb01c7e65b0..d93ffcb2262eb362edb6e0cd773599847741b139 100644 (file)
@@ -29,6 +29,7 @@ impl<T> Front for Vec<T> {
 
 struct M(PtrBack<Vec<M>>);
 
+#[allow(unused_must_use)]
 fn main() {
     std::mem::size_of::<M>();
 }
diff --git a/src/test/ui/issues/issue-31804.rs b/src/test/ui/issues/issue-31804.rs
deleted file mode 100644 (file)
index d056b77..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// Test that error recovery in the parser to an EOF does not give an infinite
-// spew of errors.
-
-fn main() {
-    let
-} //~ ERROR expected pattern, found `}`
diff --git a/src/test/ui/issues/issue-31804.stderr b/src/test/ui/issues/issue-31804.stderr
deleted file mode 100644 (file)
index 76e68b0..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: expected pattern, found `}`
-  --> $DIR/issue-31804.rs:6:1
-   |
-LL | }
-   | ^ expected pattern
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-31845.rs b/src/test/ui/issues/issue-31845.rs
deleted file mode 100644 (file)
index f6dc115..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// Checks lexical scopes cannot see through normal module boundaries
-
-fn f() {
-    fn g() {}
-    mod foo {
-        fn h() {
-           g(); //~ ERROR cannot find function `g` in this scope
-        }
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-31845.stderr b/src/test/ui/issues/issue-31845.stderr
deleted file mode 100644 (file)
index 5628193..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0425]: cannot find function `g` in this scope
-  --> $DIR/issue-31845.rs:7:12
-   |
-LL |            g();
-   |            ^ not found in this scope
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-3211.rs b/src/test/ui/issues/issue-3211.rs
deleted file mode 100644 (file)
index 49dd4fa..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// run-pass
-pub fn main() {
-    let mut x = 0;
-    for _ in 0..4096 { x += 1; }
-    assert_eq!(x, 4096);
-    println!("x = {}", x);
-}
diff --git a/src/test/ui/issues/issue-32201.rs b/src/test/ui/issues/issue-32201.rs
deleted file mode 100644 (file)
index f27bb1c..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-extern "C" {
-    fn foo(a: i32, ...);
-}
-
-fn bar(_: *const u8) {}
-
-fn main() {
-    unsafe {
-        foo(0, bar);
-        //~^ ERROR can't pass `fn(*const u8) {bar}` to variadic function
-        //~| HELP cast the value to `fn(*const u8)`
-    }
-}
diff --git a/src/test/ui/issues/issue-32201.stderr b/src/test/ui/issues/issue-32201.stderr
deleted file mode 100644 (file)
index cedb587..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0617]: can't pass `fn(*const u8) {bar}` to variadic function
-  --> $DIR/issue-32201.rs:9:16
-   |
-LL |         foo(0, bar);
-   |                ^^^ help: cast the value to `fn(*const u8)`: `bar as fn(*const u8)`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0617`.
diff --git a/src/test/ui/issues/issue-333.rs b/src/test/ui/issues/issue-333.rs
deleted file mode 100644 (file)
index 0753aaa..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// run-pass
-
-fn quux<T>(x: T) -> T { let f = id::<T>; return f(x); }
-
-fn id<T>(x: T) -> T { return x; }
-
-pub fn main() { assert_eq!(quux(10), 10); }
diff --git a/src/test/ui/issues/issue-34028.rs b/src/test/ui/issues/issue-34028.rs
deleted file mode 100644 (file)
index d761c0c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// check-pass
-
-macro_rules! m {
-    () => { #[cfg(any())] fn f() {} }
-}
-
-trait T {}
-impl T for () { m!(); }
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-34171.rs b/src/test/ui/issues/issue-34171.rs
deleted file mode 100644 (file)
index 157c58c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// check-pass
-
-macro_rules! null { ($i:tt) => {} }
-macro_rules! apply_null {
-    ($i:item) => { null! { $i } }
-}
-
-fn main() {
-    apply_null!(#[cfg(all())] fn f() {});
-}
diff --git a/src/test/ui/issues/issue-34255-1.rs b/src/test/ui/issues/issue-34255-1.rs
deleted file mode 100644 (file)
index c70cd8b..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-enum Test {
-    Drill {
-        field: i32,
-    }
-}
-
-fn main() {
-    Test::Drill(field: 42);
-    //~^ ERROR invalid `struct` delimiters or `fn` call arguments
-}
diff --git a/src/test/ui/issues/issue-34255-1.stderr b/src/test/ui/issues/issue-34255-1.stderr
deleted file mode 100644 (file)
index fbff75e..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error: invalid `struct` delimiters or `fn` call arguments
-  --> $DIR/issue-34255-1.rs:8:5
-   |
-LL |     Test::Drill(field: 42);
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: if `Test::Drill` is a struct, use braces as delimiters
-   |
-LL |     Test::Drill { field: 42 };
-   |                 ~           ~
-help: if `Test::Drill` is a function, use the arguments directly
-   |
-LL -     Test::Drill(field: 42);
-LL +     Test::Drill(42);
-   | 
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-35546.rs b/src/test/ui/issues/issue-35546.rs
deleted file mode 100644 (file)
index 004679a..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// build-pass
-#![allow(dead_code)]
-// Regression test for #35546. Check that we are able to codegen
-// this. Before we had problems because of the drop glue signature
-// around dropping a trait object (specifically, when dropping the
-// `value` field of `Node<Send>`).
-
-struct Node<T: ?Sized + Send> {
-    next: Option<Box<Node<dyn Send>>>,
-    value: T,
-}
-
-fn clear(head: &mut Option<Box<Node<dyn Send>>>) {
-    match head.take() {
-        Some(node) => *head = node.next,
-        None => (),
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-37175.rs b/src/test/ui/issues/issue-37175.rs
deleted file mode 100644 (file)
index 9ec9d48..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-// run-pass
-macro_rules! m { (<$t:ty>) => { stringify!($t) } }
-fn main() {
-    println!("{}", m!(<Vec<i32>>));
-}
diff --git a/src/test/ui/issues/issue-37366.rs b/src/test/ui/issues/issue-37366.rs
deleted file mode 100644 (file)
index acc2f3e..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// check-pass
-// ignore-emscripten
-
-#![feature(llvm_asm)]
-#![allow(deprecated)] // llvm_asm!
-
-macro_rules! interrupt_handler {
-    () => {
-        unsafe fn _interrupt_handler() {
-            llvm_asm!("pop  eax" :::: "intel");
-        }
-    }
-}
-interrupt_handler!{}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-37550.rs b/src/test/ui/issues/issue-37550.rs
deleted file mode 100644 (file)
index 35b63bd..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-const fn x() {
-    let t = true;
-    let x = || t; //~ ERROR function pointer
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-37550.stderr b/src/test/ui/issues/issue-37550.stderr
deleted file mode 100644 (file)
index 54b60df..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: function pointers cannot appear in constant functions
-  --> $DIR/issue-37550.rs:3:9
-   |
-LL |     let x = || t;
-   |         ^
-   |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-37991.rs b/src/test/ui/issues/issue-37991.rs
deleted file mode 100644 (file)
index a6ac4d5..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// run-pass
-
-const fn foo() -> i64 {
-    3
-}
-
-const fn bar(x: i64) -> i64 {
-    x*2
-}
-
-fn main() {
-    let val = &(foo() % 2);
-    assert_eq!(*val, 1);
-
-    let val2 = &(bar(1+1) % 3);
-    assert_eq!(*val2, 1);
-}
diff --git a/src/test/ui/issues/issue-38604.rs b/src/test/ui/issues/issue-38604.rs
deleted file mode 100644 (file)
index 002a3c4..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-trait Q<T:?Sized> {}
-trait Foo where u32: Q<Self> {
-    fn foo(&self);
-}
-
-impl Q<()> for u32 {}
-impl Foo for () {
-    fn foo(&self) {
-        println!("foo!");
-    }
-}
-
-fn main() {
-    let _f: Box<dyn Foo> = //~ ERROR `Foo` cannot be made into an object
-        Box::new(()); //~ ERROR `Foo` cannot be made into an object
-}
diff --git a/src/test/ui/issues/issue-38604.stderr b/src/test/ui/issues/issue-38604.stderr
deleted file mode 100644 (file)
index d41488c..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/issue-38604.rs:14:13
-   |
-LL |     let _f: Box<dyn Foo> =
-   |             ^^^^^^^^^^^^ `Foo` cannot be made into an object
-   |
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/issue-38604.rs:2:22
-   |
-LL | trait Foo where u32: Q<Self> {
-   |       ---            ^^^^^^^ ...because it uses `Self` as a type parameter
-   |       |
-   |       this trait cannot be made into an object...
-
-error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/issue-38604.rs:15:9
-   |
-LL |         Box::new(());
-   |         ^^^^^^^^^^^^ `Foo` cannot be made into an object
-   |
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/issue-38604.rs:2:22
-   |
-LL | trait Foo where u32: Q<Self> {
-   |       ---            ^^^^^^^ ...because it uses `Self` as a type parameter
-   |       |
-   |       this trait cannot be made into an object...
-   = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn Foo>>` for `Box<()>`
-   = note: required by cast to type `Box<dyn Foo>`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/issues/issue-39388.rs b/src/test/ui/issues/issue-39388.rs
deleted file mode 100644 (file)
index a8e31a6..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#![allow(unused_macros)]
-
-macro_rules! assign {
-    (($($a:tt)*) = ($($b:tt))*) => { //~ ERROR expected one of: `*`, `+`, or `?`
-        $($a)* = $($b)*
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-39388.stderr b/src/test/ui/issues/issue-39388.stderr
deleted file mode 100644 (file)
index 62e7dff..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: expected one of: `*`, `+`, or `?`
-  --> $DIR/issue-39388.rs:4:22
-   |
-LL |     (($($a:tt)*) = ($($b:tt))*) => {
-   |                      ^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-3973.rs b/src/test/ui/issues/issue-3973.rs
deleted file mode 100644 (file)
index a5ed5b8..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-struct Point {
-    x: f64,
-    y: f64,
-}
-
-trait ToString_ {
-    fn to_string(&self) -> String;
-}
-
-impl ToString_ for Point {
-    fn new(x: f64, y: f64) -> Point {
-    //~^ ERROR method `new` is not a member of trait `ToString_`
-        Point { x: x, y: y }
-    }
-
-    fn to_string(&self) -> String {
-        format!("({}, {})", self.x, self.y)
-    }
-}
-
-fn main() {
-    let p = Point::new(0.0, 0.0);
-    //~^ ERROR no function or associated item named `new` found for struct `Point`
-    println!("{}", p.to_string());
-}
diff --git a/src/test/ui/issues/issue-3973.stderr b/src/test/ui/issues/issue-3973.stderr
deleted file mode 100644 (file)
index 63282e8..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-error[E0407]: method `new` is not a member of trait `ToString_`
-  --> $DIR/issue-3973.rs:11:5
-   |
-LL | /     fn new(x: f64, y: f64) -> Point {
-LL | |
-LL | |         Point { x: x, y: y }
-LL | |     }
-   | |_____^ not a member of trait `ToString_`
-
-error[E0599]: no function or associated item named `new` found for struct `Point` in the current scope
-  --> $DIR/issue-3973.rs:22:20
-   |
-LL | struct Point {
-   | ------------ function or associated item `new` not found for this
-...
-LL |     let p = Point::new(0.0, 0.0);
-   |                    ^^^ function or associated item not found in `Point`
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0407, E0599.
-For more information about an error, try `rustc --explain E0407`.
diff --git a/src/test/ui/issues/issue-39823.rs b/src/test/ui/issues/issue-39823.rs
deleted file mode 100644 (file)
index 148cf52..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// run-pass
-// aux-build:issue-39823.rs
-
-extern crate issue_39823;
-use issue_39823::{RemoteC, RemoteG};
-
-#[derive(Debug, PartialEq)]
-struct LocalC(u32);
-
-#[derive(Debug, PartialEq)]
-struct LocalG<T>(T);
-
-fn main() {
-    let virtual_localc : &dyn Fn(_) -> LocalC = &LocalC;
-    assert_eq!(virtual_localc(1), LocalC(1));
-
-    let virtual_localg : &dyn Fn(_) -> LocalG<u32> = &LocalG;
-    assert_eq!(virtual_localg(1), LocalG(1));
-
-    let virtual_remotec : &dyn Fn(_) -> RemoteC = &RemoteC;
-    assert_eq!(virtual_remotec(1), RemoteC(1));
-
-    let virtual_remoteg : &dyn Fn(_) -> RemoteG<u32> = &RemoteG;
-    assert_eq!(virtual_remoteg(1), RemoteG(1));
-}
diff --git a/src/test/ui/issues/issue-40770.rs b/src/test/ui/issues/issue-40770.rs
deleted file mode 100644 (file)
index c9713c1..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// run-pass
-#![allow(unused_macros)]
-macro_rules! m {
-    ($e:expr) => {
-        macro_rules! n { () => { $e } }
-    }
-}
-
-fn main() {
-    m!(foo!());
-}
index 3b2d232e61f7e5c8c559c8835ca8e949df59d52a..11c23e5b659b7af06385f33dd0f0bd4ab1c9cf00 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: `Rc<Foo>` cannot be shared between threads safely
-  --> $DIR/issue-40827.rs:14:5
+  --> $DIR/issue-40827.rs:14:7
    |
 LL |     f(Foo(Arc::new(Bar::B(None))));
-   |     ^ `Rc<Foo>` cannot be shared between threads safely
+   |     - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Rc<Foo>` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: within `Bar`, the trait `Sync` is not implemented for `Rc<Foo>`
 note: required because it appears within the type `Bar`
@@ -23,10 +25,12 @@ LL | fn f<T: Send>(_: T) {}
    |         ^^^^ required by this bound in `f`
 
 error[E0277]: `Rc<Foo>` cannot be sent between threads safely
-  --> $DIR/issue-40827.rs:14:5
+  --> $DIR/issue-40827.rs:14:7
    |
 LL |     f(Foo(Arc::new(Bar::B(None))));
-   |     ^ `Rc<Foo>` cannot be sent between threads safely
+   |     - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Rc<Foo>` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: within `Bar`, the trait `Send` is not implemented for `Rc<Foo>`
 note: required because it appears within the type `Bar`
diff --git a/src/test/ui/issues/issue-40962.rs b/src/test/ui/issues/issue-40962.rs
deleted file mode 100644 (file)
index 7b91c06..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// check-pass
-macro_rules! m {
-    ($i:meta) => {
-        #[derive($i)]
-        struct S;
-    }
-}
-
-m!(Clone);
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-42463.rs b/src/test/ui/issues/issue-42463.rs
deleted file mode 100644 (file)
index 51d6ea3..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// run-pass
-use std::ops::{Deref, DerefMut};
-
-struct CheckedDeref<T, F> {
-    value: T,
-    check: F
-}
-
-impl<F: Fn(&T) -> bool, T> Deref for CheckedDeref<T, F> {
-    type Target = T;
-    fn deref(&self) -> &T {
-        assert!((self.check)(&self.value));
-        &self.value
-    }
-}
-
-impl<F: Fn(&T) -> bool, T> DerefMut for CheckedDeref<T, F> {
-    fn deref_mut(&mut self) -> &mut T {
-        assert!((self.check)(&self.value));
-        &mut self.value
-    }
-}
-
-
-fn main() {
-    let mut v = CheckedDeref {
-        value: vec![0],
-        check: |v: &Vec<_>| !v.is_empty()
-    };
-    v.push(1);
-    assert_eq!(*v, vec![0, 1]);
-}
diff --git a/src/test/ui/issues/issue-42679.rs b/src/test/ui/issues/issue-42679.rs
deleted file mode 100644 (file)
index 596309f..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// run-pass
-#![feature(box_syntax)]
-#![feature(box_patterns)]
-
-#[derive(Debug, PartialEq)]
-enum Test {
-    Foo(usize),
-    Bar(isize),
-}
-
-fn main() {
-    let a = box Test::Foo(10);
-    let b = box Test::Bar(-20);
-    match (a, b) {
-        (_, box Test::Foo(_)) => unreachable!(),
-        (box Test::Foo(x), b) => {
-            assert_eq!(x, 10);
-            assert_eq!(b, box Test::Bar(-20));
-        },
-        _ => unreachable!(),
-    }
-}
diff --git a/src/test/ui/issues/issue-42747.rs b/src/test/ui/issues/issue-42747.rs
deleted file mode 100644 (file)
index fec6587..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-// run-pass
-macro_rules! fooN {
-    ($cur:ident $prev:ty) => {
-        #[allow(dead_code)]
-        enum $cur {
-            Empty,
-            First($prev),
-            Second($prev),
-            Third($prev),
-            Fourth($prev),
-        }
-    }
-}
-
-fooN!(Foo0 ());
-fooN!(Foo1 Foo0);
-fooN!(Foo2 Foo1);
-fooN!(Foo3 Foo2);
-fooN!(Foo4 Foo3);
-fooN!(Foo5 Foo4);
-fooN!(Foo6 Foo5);
-fooN!(Foo7 Foo6);
-fooN!(Foo8 Foo7);
-fooN!(Foo9 Foo8);
-fooN!(Foo10 Foo9);
-fooN!(Foo11 Foo10);
-fooN!(Foo12 Foo11);
-fooN!(Foo13 Foo12);
-fooN!(Foo14 Foo13);
-fooN!(Foo15 Foo14);
-fooN!(Foo16 Foo15);
-fooN!(Foo17 Foo16);
-fooN!(Foo18 Foo17);
-fooN!(Foo19 Foo18);
-fooN!(Foo20 Foo19);
-fooN!(Foo21 Foo20);
-fooN!(Foo22 Foo21);
-fooN!(Foo23 Foo22);
-fooN!(Foo24 Foo23);
-fooN!(Foo25 Foo24);
-fooN!(Foo26 Foo25);
-fooN!(Foo27 Foo26);
-
-fn main() {
-    let _foo = Foo27::Empty;
-}
diff --git a/src/test/ui/issues/issue-43189.rs b/src/test/ui/issues/issue-43189.rs
deleted file mode 100644 (file)
index ce667a5..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// Issue 46112: An extern crate pub re-exporting libcore was causing
-// paths rooted from `std` to be misrendered in the diagnostic output.
-
-// ignore-windows
-// aux-build:xcrate-issue-43189-a.rs
-// aux-build:xcrate-issue-43189-b.rs
-
-extern crate xcrate_issue_43189_b;
-fn main() {
-    ().a();
-    //~^ ERROR no method named `a` found
-}
diff --git a/src/test/ui/issues/issue-43189.stderr b/src/test/ui/issues/issue-43189.stderr
deleted file mode 100644 (file)
index caf7530..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0599]: no method named `a` found for unit type `()` in the current scope
-  --> $DIR/issue-43189.rs:10:8
-   |
-LL |     ().a();
-   |        ^ method not found in `()`
-   |
-  ::: $DIR/auxiliary/xcrate-issue-43189-a.rs:5:8
-   |
-LL |     fn a(&self) {}
-   |        - the method is available for `()` here
-   |
-   = help: items from traits can only be used if the trait is in scope
-help: the following trait is implemented but not in scope; perhaps add a `use` for it:
-   |
-LL | use xcrate_issue_43189_b::xcrate_issue_43189_a::A;
-   |
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-44005.rs b/src/test/ui/issues/issue-44005.rs
deleted file mode 100644 (file)
index ab3b921..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-pub trait Foo<'a> {
-    type Bar;
-    fn foo(&'a self) -> Self::Bar;
-}
-
-impl<'a, 'b, T: 'a> Foo<'a> for &'b T {
-    type Bar = &'a T;
-    fn foo(&'a self) -> &'a T {
-        self
-    }
-}
-
-pub fn uncallable<T, F>(x: T, f: F)
-where
-    T: for<'a> Foo<'a>,
-    F: for<'a> Fn(<T as Foo<'a>>::Bar),
-{
-    f(x.foo());
-}
-
-pub fn catalyst(x: &i32) {
-    broken(x, |_| {})
-}
-
-pub fn broken<F: Fn(&i32)>(x: &i32, f: F) {
-    uncallable(x, |y| f(y));
-    //~^ type mismatch
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-44005.stderr b/src/test/ui/issues/issue-44005.stderr
deleted file mode 100644 (file)
index 307e444..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0631]: type mismatch in closure arguments
-  --> $DIR/issue-44005.rs:26:5
-   |
-LL |     uncallable(x, |y| f(y));
-   |     ^^^^^^^^^^    -------- found signature of `for<'r> fn(&'r i32) -> _`
-   |     |
-   |     expected signature of `for<'a> fn(<&i32 as Foo<'a>>::Bar) -> _`
-   |
-note: required by a bound in `uncallable`
-  --> $DIR/issue-44005.rs:16:8
-   |
-LL | pub fn uncallable<T, F>(x: T, f: F)
-   |        ---------- required by a bound in this
-...
-LL |     F: for<'a> Fn(<T as Foo<'a>>::Bar),
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `uncallable`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/issues/issue-4401.rs b/src/test/ui/issues/issue-4401.rs
deleted file mode 100644 (file)
index fef73fb..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// run-pass
-pub fn main() {
-    let mut count = 0;
-    for _ in 0..999_999 { count += 1; }
-    assert_eq!(count, 999_999);
-    println!("{}", count);
-}
diff --git a/src/test/ui/issues/issue-4448.rs b/src/test/ui/issues/issue-4448.rs
deleted file mode 100644 (file)
index 27d0326..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// run-pass
-// ignore-emscripten no threads support
-
-use std::sync::mpsc::channel;
-use std::thread;
-
-pub fn main() {
-    let (tx, rx) = channel::<&'static str>();
-
-    let t = thread::spawn(move|| {
-        assert_eq!(rx.recv().unwrap(), "hello, world");
-    });
-
-    tx.send("hello, world").unwrap();
-    t.join().ok().unwrap();
-}
diff --git a/src/test/ui/issues/issue-45124.rs b/src/test/ui/issues/issue-45124.rs
deleted file mode 100644 (file)
index 942014c..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// run-pass
-#![allow(unreachable_code)]
-// compile-flags: --edition 2018
-
-#![feature(try_blocks)]
-
-fn main() {
-    let mut a = 0;
-    let () = {
-        let _: Result<(), ()> = try {
-            let _ = Err(())?;
-            return
-        };
-        a += 1;
-    };
-    a += 2;
-    assert_eq!(a, 3);
-}
diff --git a/src/test/ui/issues/issue-45152.rs b/src/test/ui/issues/issue-45152.rs
deleted file mode 100644 (file)
index fb1c9fb..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-#![allow(unused_variables)]
-#![feature(unsize, coerce_unsized)]
-
-#[repr(packed)]
-struct UnalignedPtr<'a, T: ?Sized>
-    where T: 'a,
-{
-    data: &'a T,
-}
-
-fn main() {
-
-    impl<'a, T, U> std::ops::CoerceUnsized<UnalignedPtr<'a, U>> for UnalignedPtr<'a, T>
-        where
-        T: std::marker::Unsize<U> + ?Sized,
-        U: ?Sized,
-    { }
-
-    let arr = [1, 2, 3];
-    let arr_unaligned: UnalignedPtr<[i32; 3]> = UnalignedPtr { data: &arr };
-    let arr_unaligned: UnalignedPtr<[i32]> = arr_unaligned;
-}
diff --git a/src/test/ui/issues/issue-46095.rs b/src/test/ui/issues/issue-46095.rs
deleted file mode 100644 (file)
index 59ddb60..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// run-pass
-struct A;
-
-impl A {
-    fn take_mutably(&mut self) {}
-}
-
-fn identity<T>(t: T) -> T {
-    t
-}
-
-// Issue 46095
-// Built-in indexing should be used even when the index is not
-// trivially an integer
-// Overloaded indexing would cause wrapped to be borrowed mutably
-
-fn main() {
-    let mut a1 = A;
-    let mut a2 = A;
-
-    let wrapped = [&mut a1, &mut a2];
-
-    {
-        wrapped[0 + 1 - 1].take_mutably();
-    }
-
-    {
-        wrapped[identity(0)].take_mutably();
-    }
-}
diff --git a/src/test/ui/issues/issue-46112.rs b/src/test/ui/issues/issue-46112.rs
deleted file mode 100644 (file)
index 0cdd2c2..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// Issue 46112: An extern crate pub re-exporting libcore was causing
-// paths rooted from `std` to be misrendered in the diagnostic output.
-
-// ignore-windows
-// aux-build:xcrate-issue-46112-rexport-core.rs
-
-extern crate xcrate_issue_46112_rexport_core;
-fn test(r: Result<Option<()>, &'static str>) { }
-fn main() { test(Ok(())); }
-//~^ mismatched types
diff --git a/src/test/ui/issues/issue-46112.stderr b/src/test/ui/issues/issue-46112.stderr
deleted file mode 100644 (file)
index ec05fbe..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-46112.rs:9:21
-   |
-LL | fn main() { test(Ok(())); }
-   |                     ^^
-   |                     |
-   |                     expected enum `Option`, found `()`
-   |                     help: try using a variant of the expected enum: `Some(())`
-   |
-   = note:   expected enum `Option<()>`
-           found unit type `()`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-47139-1.rs b/src/test/ui/issues/issue-47139-1.rs
deleted file mode 100644 (file)
index c55fc34..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-// run-pass
-// Regression test for issue #47139:
-//
-// Coherence was encountering an (unnecessary) overflow trying to
-// decide if the two impls of dummy overlap.
-//
-// The overflow went something like:
-//
-// - `&'a ?T: Insertable` ?
-// - let ?T = Option<?U> ?
-// - `Option<?U>: Insertable` ?
-// - `Option<&'a ?U>: Insertable` ?
-// - `&'a ?U: Insertable` ?
-//
-// While somewhere in the middle, a projection would occur, which
-// broke cycle detection.
-//
-// It turned out that this cycle was being kicked off due to some
-// extended diagnostic attempts in coherence, so removing those
-// sidestepped the issue for now.
-
-#![allow(dead_code)]
-
-pub trait Insertable {
-    type Values;
-
-    fn values(self) -> Self::Values;
-}
-
-impl<T> Insertable for Option<T>
-    where
-    T: Insertable,
-    T::Values: Default,
-{
-    type Values = T::Values;
-
-    fn values(self) -> Self::Values {
-        self.map(Insertable::values).unwrap_or_default()
-    }
-}
-
-impl<'a, T> Insertable for &'a Option<T>
-    where
-    Option<&'a T>: Insertable,
-{
-    type Values = <Option<&'a T> as Insertable>::Values;
-
-    fn values(self) -> Self::Values {
-        self.as_ref().values()
-    }
-}
-
-impl<'a, T> Insertable for &'a [T]
-{
-    type Values = Self;
-
-    fn values(self) -> Self::Values {
-        self
-    }
-}
-
-trait Unimplemented { }
-
-trait Dummy { }
-
-struct Foo<T> { t: T }
-
-impl<'a, U> Dummy for Foo<&'a U>
-    where &'a U: Insertable
-{
-}
-
-impl<T> Dummy for T
-    where T: Unimplemented
-{ }
-
-fn main() {
-}
diff --git a/src/test/ui/issues/issue-49040.rs b/src/test/ui/issues/issue-49040.rs
deleted file mode 100644 (file)
index b7a541d..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#![allow(unused_variables)]; //~ ERROR expected item, found `;`
-//~^ ERROR `main` function
-fn foo() {}
diff --git a/src/test/ui/issues/issue-49040.stderr b/src/test/ui/issues/issue-49040.stderr
deleted file mode 100644 (file)
index 56befe3..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error: expected item, found `;`
-  --> $DIR/issue-49040.rs:1:28
-   |
-LL | #![allow(unused_variables)];
-   |                            ^ help: remove this semicolon
-
-error[E0601]: `main` function not found in crate `issue_49040`
-  --> $DIR/issue-49040.rs:1:1
-   |
-LL | #![allow(unused_variables)];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ consider adding a `main` function to `$DIR/issue-49040.rs`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/issues/issue-49579.rs b/src/test/ui/issues/issue-49579.rs
deleted file mode 100644 (file)
index 98de014..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// check-pass
-
-fn fibs(n: u32) -> impl Iterator<Item=u128> {
-    (0 .. n)
-    .scan((0, 1), |st, _| {
-        *st = (st.1, st.0 + st.1);
-        Some(*st)
-    })
-    .map(&|(f, _)| f)
-}
-
-fn main() {
-    println!("{:?}", fibs(10).collect::<Vec<_>>());
-}
diff --git a/src/test/ui/issues/issue-49685.rs b/src/test/ui/issues/issue-49685.rs
deleted file mode 100644 (file)
index fb328d6..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// run-pass
-// Regression test for #49685: drop elaboration was not revealing the
-// value of `impl Trait` returns, leading to an ICE.
-
-fn main() {
-    let _ = Some(())
-        .into_iter()
-        .flat_map(|_| Some(()).into_iter().flat_map(func));
-}
-
-fn func(_: ()) -> impl Iterator<Item = ()> {
-    Some(()).into_iter().flat_map(|_| vec![])
-}
diff --git a/src/test/ui/issues/issue-50731.rs b/src/test/ui/issues/issue-50731.rs
deleted file mode 100644 (file)
index 209c1e1..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// run-pass
-enum Void {}
-fn foo(_: Result<(Void, u32), (Void, String)>) {}
-fn main() {
-    let _: fn(_) = foo;
-}
diff --git a/src/test/ui/issues/issue-5099.rs b/src/test/ui/issues/issue-5099.rs
deleted file mode 100644 (file)
index b5abccb..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-trait B <A> {
-    fn a() -> A {
-        this.a //~ ERROR cannot find value `this` in this scope
-    }
-    fn b(x: i32) {
-        this.b(x); //~ ERROR cannot find value `this` in this scope
-    }
-    fn c() {
-        let _ = || this.a; //~ ERROR cannot find value `this` in this scope
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-5099.stderr b/src/test/ui/issues/issue-5099.stderr
deleted file mode 100644 (file)
index e9b2a9c..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-error[E0425]: cannot find value `this` in this scope
-  --> $DIR/issue-5099.rs:3:9
-   |
-LL |         this.a
-   |         ^^^^ not found in this scope
-   |
-help: you might have meant to use `self` here instead
-   |
-LL |         self.a
-   |         ~~~~
-help: if you meant to use `self`, you are also missing a `self` receiver argument
-   |
-LL |     fn a(&self) -> A {
-   |          +++++
-
-error[E0425]: cannot find value `this` in this scope
-  --> $DIR/issue-5099.rs:6:9
-   |
-LL |         this.b(x);
-   |         ^^^^ not found in this scope
-   |
-help: you might have meant to use `self` here instead
-   |
-LL |         self.b(x);
-   |         ~~~~
-help: if you meant to use `self`, you are also missing a `self` receiver argument
-   |
-LL |     fn b(&self, x: i32) {
-   |          ++++++
-
-error[E0425]: cannot find value `this` in this scope
-  --> $DIR/issue-5099.rs:9:20
-   |
-LL |         let _ = || this.a;
-   |                    ^^^^ not found in this scope
-   |
-help: you might have meant to use `self` here instead
-   |
-LL |         let _ = || self.a;
-   |                    ~~~~
-help: if you meant to use `self`, you are also missing a `self` receiver argument
-   |
-LL |     fn c(&self) {
-   |          +++++
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-50993.rs b/src/test/ui/issues/issue-50993.rs
deleted file mode 100644 (file)
index e6a9451..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// compile-flags: --crate-type dylib --target thumbv7em-none-eabihf
-// needs-llvm-components: arm
-// build-pass
-// error-pattern: dropping unsupported crate type `dylib` for target `thumbv7em-none-eabihf`
-
-#![feature(no_core)]
-
-#![no_std]
-#![no_core]
diff --git a/src/test/ui/issues/issue-50993.stderr b/src/test/ui/issues/issue-50993.stderr
deleted file mode 100644 (file)
index 45cbfef..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-warning: dropping unsupported crate type `dylib` for target `thumbv7em-none-eabihf`
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/issues/issue-51185.rs b/src/test/ui/issues/issue-51185.rs
deleted file mode 100644 (file)
index 52a2b25..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-pass
-fn foo() -> impl Into<for<'a> fn(&'a ())> {
-    (|_| {}) as for<'a> fn(&'a ())
-}
-
-fn main() {
-    foo().into()(&());
-}
diff --git a/src/test/ui/issues/issue-51345.rs b/src/test/ui/issues/issue-51345.rs
deleted file mode 100644 (file)
index 15571e8..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-pass
-#![allow(unreachable_code)]
-
-fn main() {
-    let mut v = Vec::new();
-
-    loop { v.push(break) }
-}
diff --git a/src/test/ui/issues/issue-51582.rs b/src/test/ui/issues/issue-51582.rs
deleted file mode 100644 (file)
index 40a70c6..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// run-pass
-#![feature(core_intrinsics)]
-
-#[repr(i8)]
-pub enum Enum {
-    VariantA,
-    VariantB,
-}
-
-fn make_b() -> Enum { Enum::VariantB }
-
-fn main() {
-    assert_eq!(1, make_b() as i8);
-    assert_eq!(1, make_b() as u8);
-    assert_eq!(1, make_b() as i32);
-    assert_eq!(1, make_b() as u32);
-    assert_eq!(1, std::intrinsics::discriminant_value(&make_b()));
-}
diff --git a/src/test/ui/issues/issue-53787-inline-assembler-macro.rs b/src/test/ui/issues/issue-53787-inline-assembler-macro.rs
deleted file mode 100644 (file)
index d9fe7ca..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-// Regression test for Issue #53787: Fix ICE when creating a label in inline assembler with macros.
-
-// build-fail
-// ignore-emscripten
-
-#![feature(llvm_asm)]
-#![allow(deprecated)] // llvm_asm!
-
-macro_rules! fake_jump {
-    ($id:expr) => {
-        unsafe {
-            llvm_asm!(
-            "
-            jmp $0
-            lea eax, [ebx]
-            xor eax, 0xDEADBEEF
-            retn
-            $0:
-            "::"0"($id)::"volatile", "intel");
-        }
-    };
-}
-
-fn main() {
-    fake_jump!("FirstFunc"); //~ ERROR invalid value for constraint in inline assembly
-    println!("Hello, world!");
-}
diff --git a/src/test/ui/issues/issue-53787-inline-assembler-macro.stderr b/src/test/ui/issues/issue-53787-inline-assembler-macro.stderr
deleted file mode 100644 (file)
index fd755e3..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0669]: invalid value for constraint in inline assembly
-  --> $DIR/issue-53787-inline-assembler-macro.rs:25:16
-   |
-LL |     fake_jump!("FirstFunc");
-   |                ^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0669`.
diff --git a/src/test/ui/issues/issue-54467.rs b/src/test/ui/issues/issue-54467.rs
deleted file mode 100644 (file)
index 734bf27..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-// run-pass
-
-pub trait Stream {
-    type Item;
-    type Error;
-}
-
-pub trait ParseError<I> {
-    type Output;
-}
-
-impl ParseError<char> for u32 {
-    type Output = ();
-}
-
-impl Stream for () {
-    type Item = char;
-    type Error = u32;
-}
-
-pub struct Lex<'a, I>
-    where I: Stream,
-          I::Error: ParseError<char>,
-          <<I as Stream>::Error as ParseError<char>>::Output: 'a
-{
-    x: &'a <I::Error as ParseError<char>>::Output
-}
-
-pub struct Reserved<'a, I> where
-    I: Stream<Item=char> + 'a,
-    I::Error: ParseError<I::Item>,
-    <<I as Stream>::Error as ParseError<char>>::Output: 'a
-
-{
-    x: Lex<'a, I>
-}
-
-fn main() {
-    let r: Reserved<()> = Reserved {
-        x: Lex {
-            x: &()
-        }
-    };
-
-    let _v = r.x.x;
-}
diff --git a/src/test/ui/issues/issue-56031.rs b/src/test/ui/issues/issue-56031.rs
deleted file mode 100644 (file)
index b68f568..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-struct T;
-
-impl for T {}
-//~^ ERROR missing trait in a trait impl
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-56031.stderr b/src/test/ui/issues/issue-56031.stderr
deleted file mode 100644 (file)
index 7ee5bc6..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error: missing trait in a trait impl
-  --> $DIR/issue-56031.rs:3:5
-   |
-LL | impl for T {}
-   |     ^
-   |
-help: add a trait here
-   |
-LL | impl Trait for T {}
-   |      +++++
-help: for an inherent impl, drop this `for`
-   |
-LL - impl for T {}
-LL + impl T {}
-   | 
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-57410-1.rs b/src/test/ui/issues/issue-57410-1.rs
deleted file mode 100644 (file)
index d825cb1..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// check-pass
-
-// Originally from #53925.
-// Tests that the `unreachable_pub` lint doesn't fire for `pub self::bar::Bar`.
-
-#![deny(unreachable_pub)]
-
-mod foo {
-    mod bar {
-        pub struct Bar;
-    }
-
-    pub use self::bar::Bar;
-}
-
-pub use foo::Bar;
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-57597.rs b/src/test/ui/issues/issue-57597.rs
deleted file mode 100644 (file)
index ebeb3fe..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-// Regression test for #57597.
-//
-// Make sure that nested matchers work correctly rather than causing an infinite loop or crash.
-
-// edition:2018
-
-macro_rules! foo1 {
-    ($($($i:ident)?)+) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo2 {
-    ($($($i:ident)?)*) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo3 {
-    ($($($i:ident)?)?) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo4 {
-    ($($($($i:ident)?)?)?) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo5 {
-    ($($($($i:ident)*)?)?) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo6 {
-    ($($($($i:ident)?)*)?) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo7 {
-    ($($($($i:ident)?)?)*) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo8 {
-    ($($($($i:ident)*)*)?) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo9 {
-    ($($($($i:ident)?)*)*) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo10 {
-    ($($($($i:ident)?)*)+) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo11 {
-    ($($($($i:ident)+)?)*) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo12 {
-    ($($($($i:ident)+)*)?) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-fn main() {
-    foo1!();
-    foo2!();
-    foo3!();
-    foo4!();
-    foo5!();
-    foo6!();
-    foo7!();
-    foo8!();
-    foo9!();
-    foo10!();
-    foo11!();
-    foo12!();
-}
diff --git a/src/test/ui/issues/issue-57597.stderr b/src/test/ui/issues/issue-57597.stderr
deleted file mode 100644 (file)
index 0a02ac8..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:8:7
-   |
-LL |     ($($($i:ident)?)+) => {};
-   |       ^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:13:7
-   |
-LL |     ($($($i:ident)?)*) => {};
-   |       ^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:18:7
-   |
-LL |     ($($($i:ident)?)?) => {};
-   |       ^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:23:7
-   |
-LL |     ($($($($i:ident)?)?)?) => {};
-   |       ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:28:7
-   |
-LL |     ($($($($i:ident)*)?)?) => {};
-   |       ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:33:7
-   |
-LL |     ($($($($i:ident)?)*)?) => {};
-   |       ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:38:7
-   |
-LL |     ($($($($i:ident)?)?)*) => {};
-   |       ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:43:7
-   |
-LL |     ($($($($i:ident)*)*)?) => {};
-   |       ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:48:7
-   |
-LL |     ($($($($i:ident)?)*)*) => {};
-   |       ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:53:7
-   |
-LL |     ($($($($i:ident)?)*)+) => {};
-   |       ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:58:7
-   |
-LL |     ($($($($i:ident)+)?)*) => {};
-   |       ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:63:7
-   |
-LL |     ($($($($i:ident)+)*)?) => {};
-   |       ^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 12 previous errors
-
diff --git a/src/test/ui/issues/issue-58319.rs b/src/test/ui/issues/issue-58319.rs
deleted file mode 100644 (file)
index 757307d..0000000
+++ /dev/null
@@ -1,621 +0,0 @@
-// run-pass
-fn main() {}
-#[derive(Clone)]
-pub struct Little;
-#[derive(Clone)]
-pub struct Big(
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-);
diff --git a/src/test/ui/issues/issue-59029-1.rs b/src/test/ui/issues/issue-59029-1.rs
deleted file mode 100644 (file)
index 8ab47a4..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#![feature(trait_alias)]
-
-trait Svc<Req> { type Res; }
-
-trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
-//~^ ERROR associated type `Res` not found for `Self`
-//~| ERROR associated type `Res` not found for `Self`
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-59029-1.stderr b/src/test/ui/issues/issue-59029-1.stderr
deleted file mode 100644 (file)
index 53cdb8b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0220]: associated type `Res` not found for `Self`
-  --> $DIR/issue-59029-1.rs:5:52
-   |
-LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
-   |                                                    ^^^ associated type `Res` not found
-
-error[E0220]: associated type `Res` not found for `Self`
-  --> $DIR/issue-59029-1.rs:5:52
-   |
-LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
-   |                                                    ^^^ associated type `Res` not found
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0220`.
diff --git a/src/test/ui/issues/issue-59508-1.rs b/src/test/ui/issues/issue-59508-1.rs
deleted file mode 100644 (file)
index 6376c42..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#![allow(dead_code)]
-#![feature(const_generics_defaults)]
-
-// This test checks that generic parameter re-ordering diagnostic suggestions mention that
-// consts come after types and lifetimes when the `const_generics_defaults` feature is enabled.
-// We cannot run rustfix on this test because of the above const generics warning.
-
-struct A;
-
-impl A {
-    pub fn do_things<T, 'a, 'b: 'a>() {
-    //~^ ERROR lifetime parameters must be declared prior to type parameters
-        println!("panic");
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-59508-1.stderr b/src/test/ui/issues/issue-59508-1.stderr
deleted file mode 100644 (file)
index df244f0..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: lifetime parameters must be declared prior to type parameters
-  --> $DIR/issue-59508-1.rs:11:25
-   |
-LL |     pub fn do_things<T, 'a, 'b: 'a>() {
-   |                     ----^^--^^----- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b: 'a, T>`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-59508.fixed b/src/test/ui/issues/issue-59508.fixed
deleted file mode 100644 (file)
index b5c60a1..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// run-rustfix
-
-#![allow(dead_code)]
-
-// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds.
-
-struct A;
-
-impl A {
-    pub fn do_things<'a, 'b: 'a, T>() {
-    //~^ ERROR lifetime parameters must be declared prior to type parameters
-        println!("panic");
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-59508.rs b/src/test/ui/issues/issue-59508.rs
deleted file mode 100644 (file)
index 0b39c5d..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// run-rustfix
-
-#![allow(dead_code)]
-
-// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds.
-
-struct A;
-
-impl A {
-    pub fn do_things<T, 'a, 'b: 'a>() {
-    //~^ ERROR lifetime parameters must be declared prior to type parameters
-        println!("panic");
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-59508.stderr b/src/test/ui/issues/issue-59508.stderr
deleted file mode 100644 (file)
index 33e967c..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: lifetime parameters must be declared prior to type parameters
-  --> $DIR/issue-59508.rs:10:25
-   |
-LL |     pub fn do_things<T, 'a, 'b: 'a>() {
-   |                     ----^^--^^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b: 'a, T>`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-60283.rs b/src/test/ui/issues/issue-60283.rs
deleted file mode 100644 (file)
index c63b154..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-pub trait Trait<'a> {
-    type Item;
-}
-
-impl<'a> Trait<'a> for () {
-    type Item = ();
-}
-
-pub fn foo<T, F>(_: T, _: F)
-where
-    T: for<'a> Trait<'a>,
-    F: for<'a> FnMut(<T as Trait<'a>>::Item),
-{
-}
-
-fn main() {
-    foo((), drop)
-    //~^ ERROR type mismatch in function arguments
-    //~| ERROR size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time
-}
diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/issues/issue-60283.stderr
deleted file mode 100644 (file)
index 34893cd..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-error[E0631]: type mismatch in function arguments
-  --> $DIR/issue-60283.rs:17:13
-   |
-LL |     foo((), drop)
-   |     ---     ^^^^
-   |     |       |
-   |     |       expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _`
-   |     |       found signature of `fn(()) -> _`
-   |     required by a bound introduced by this call
-   |
-note: required by a bound in `foo`
-  --> $DIR/issue-60283.rs:12:16
-   |
-LL | pub fn foo<T, F>(_: T, _: F)
-   |        --- required by a bound in this
-...
-LL |     F: for<'a> FnMut(<T as Trait<'a>>::Item),
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`
-
-error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time
-  --> $DIR/issue-60283.rs:17:13
-   |
-LL |     foo((), drop)
-   |     ---     ^^^^ doesn't have a size known at compile-time
-   |     |
-   |     required by a bound introduced by this call
-   |
-   = help: the trait `Sized` is not implemented for `<() as Trait<'_>>::Item`
-note: required by a bound in `std::mem::drop`
-  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub fn drop<T>(_x: T) {}
-   |             ^ required by this bound in `std::mem::drop`
-help: consider further restricting the associated type
-   |
-LL | fn main() where <() as Trait<'_>>::Item: Sized {
-   |           ++++++++++++++++++++++++++++++++++++
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0277, E0631.
-For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-60662.rs b/src/test/ui/issues/issue-60662.rs
deleted file mode 100644 (file)
index b9faa66..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// check-pass
-// compile-flags: -Z unpretty=hir
-
-#![feature(type_alias_impl_trait)]
-
-trait Animal {}
-
-fn main() {
-    pub type ServeFut = impl Animal;
-}
diff --git a/src/test/ui/issues/issue-60662.stdout b/src/test/ui/issues/issue-60662.stdout
deleted file mode 100644 (file)
index 14a49f2..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// check-pass
-// compile-flags: -Z unpretty=hir
-
-#![feature(type_alias_impl_trait)]
-#[prelude_import]
-use ::std::prelude::rust_2015::*;
-#[macro_use]
-extern crate std;
-
-trait Animal { }
-
-fn main() {
-              pub type ServeFut = /*impl Trait*/;
-          }
diff --git a/src/test/ui/issues/issue-61711-once-caused-rustc-inf-loop.rs b/src/test/ui/issues/issue-61711-once-caused-rustc-inf-loop.rs
deleted file mode 100644 (file)
index de7d6a0..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// Issue 61711: A crate pub re-exporting `crate` was causing an
-// infinite loop.
-
-// edition:2018
-// aux-build:xcrate-issue-61711-b.rs
-// compile-flags:--extern xcrate_issue_61711_b
-
-// build-pass
-
-fn f<F: Fn(xcrate_issue_61711_b::Struct)>(_: F) { }
-fn main() { }
diff --git a/src/test/ui/issues/issue-61882-2.rs b/src/test/ui/issues/issue-61882-2.rs
deleted file mode 100644 (file)
index 1209b54..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-struct A<T>(T);
-
-impl A<&'static u8> {
-    fn f() {
-        let x = 0;
-        Self(&x);
-        //~^ ERROR `x` does not live long enough
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-61882-2.stderr b/src/test/ui/issues/issue-61882-2.stderr
deleted file mode 100644 (file)
index 0b8e134..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0597]: `x` does not live long enough
-  --> $DIR/issue-61882-2.rs:6:14
-   |
-LL |         Self(&x);
-   |              ^^
-   |              |
-   |              borrowed value does not live long enough
-   |              this usage requires that `x` is borrowed for `'static`
-LL |
-LL |     }
-   |     - `x` dropped here while still borrowed
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-61882.rs b/src/test/ui/issues/issue-61882.rs
deleted file mode 100644 (file)
index 013398b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-struct A<T>(T);
-
-impl A<bool> {
-    const B: A<u8> = Self(0);
-    //~^ ERROR mismatched types
-    //~| ERROR mismatched types
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-61882.stderr b/src/test/ui/issues/issue-61882.stderr
deleted file mode 100644 (file)
index 09ffe8e..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-61882.rs:4:27
-   |
-LL |     const B: A<u8> = Self(0);
-   |                           ^ expected `bool`, found integer
-
-error[E0308]: mismatched types
-  --> $DIR/issue-61882.rs:4:22
-   |
-LL |     const B: A<u8> = Self(0);
-   |                      ^^^^^^^ expected `u8`, found `bool`
-   |
-   = note: expected struct `A<u8>`
-              found struct `A<bool>`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-63364.rs b/src/test/ui/issues/issue-63364.rs
deleted file mode 100644 (file)
index 5223267..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-fn part(_: u16) -> u32 {
-    1
-}
-
-fn main() {
-    for n in 100_000.. {
-    //~^ ERROR: literal out of range for `u16`
-        let _ = part(n);
-    }
-}
diff --git a/src/test/ui/issues/issue-63364.stderr b/src/test/ui/issues/issue-63364.stderr
deleted file mode 100644 (file)
index 0375359..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error: literal out of range for `u16`
-  --> $DIR/issue-63364.rs:6:14
-   |
-LL |     for n in 100_000.. {
-   |              ^^^^^^^
-   |
-   = note: `#[deny(overflowing_literals)]` on by default
-   = note: the literal `100_000` does not fit into the type `u16` whose range is `0..=65535`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-6596-1.rs b/src/test/ui/issues/issue-6596-1.rs
deleted file mode 100644 (file)
index 25f1d65..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-macro_rules! e {
-    ($inp:ident) => (
-        $nonexistent
-        //~^ ERROR expected expression, found `$`
-    );
-}
-
-fn main() {
-    e!(foo);
-}
diff --git a/src/test/ui/issues/issue-6596-1.stderr b/src/test/ui/issues/issue-6596-1.stderr
deleted file mode 100644 (file)
index 7ab3685..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error: expected expression, found `$`
-  --> $DIR/issue-6596-1.rs:3:9
-   |
-LL |         $nonexistent
-   |         ^^^^^^^^^^^^ expected expression
-...
-LL |     e!(foo);
-   |     ------- in this macro invocation
-   |
-   = note: this error originates in the macro `e` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-6804.rs b/src/test/ui/issues/issue-6804.rs
deleted file mode 100644 (file)
index 0260caa..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// Matching against NaN should result in a warning
-
-#![allow(unused)]
-#![deny(illegal_floating_point_literal_pattern)]
-
-const NAN: f64 = f64::NAN;
-
-fn main() {
-    let x = NAN;
-    match x {
-        NAN => {}, //~ ERROR floating-point types cannot be used
-        //~| WARN this was previously accepted by the compiler but is being phased out
-        _ => {},
-    };
-
-    match [x, 1.0] {
-        [NAN, _] => {}, //~ ERROR floating-point types cannot be used
-        //~| WARN this was previously accepted by the compiler but is being phased out
-        _ => {},
-    };
-}
diff --git a/src/test/ui/issues/issue-6804.stderr b/src/test/ui/issues/issue-6804.stderr
deleted file mode 100644 (file)
index 4e2961e..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-6804.rs:11:9
-   |
-LL |         NAN => {},
-   |         ^^^
-   |
-note: the lint level is defined here
-  --> $DIR/issue-6804.rs:4:9
-   |
-LL | #![deny(illegal_floating_point_literal_pattern)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-6804.rs:17:10
-   |
-LL |         [NAN, _] => {},
-   |          ^^^
-   |
-   = 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 2 previous errors
-
diff --git a/src/test/ui/issues/issue-72455.rs b/src/test/ui/issues/issue-72455.rs
deleted file mode 100644 (file)
index b6c3bb2..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-// check-pass
-
-pub trait ResultExt {
-    type Ok;
-    fn err_eprint_and_ignore(self) -> Option<Self::Ok>;
-}
-
-impl<O, E> ResultExt for std::result::Result<O, E>
-where
-    E: std::error::Error,
-{
-    type Ok = O;
-    fn err_eprint_and_ignore(self) -> Option<O>
-    where
-        Self: ,
-    {
-        match self {
-            Err(e) => {
-                eprintln!("{}", e);
-                None
-            }
-            Ok(o) => Some(o),
-        }
-    }
-}
-
-fn main() {}
index bf2794eb632b6281358710aa53b372a0ac762481..7b16fa024f8e44122040c497c86e44b921d76ea7 100644 (file)
@@ -5,6 +5,7 @@
 pub unsafe fn g() {
     return;
     if *ptr::null() {}; //~ ERROR unreachable
+    //~| WARNING dereferencing a null pointer
 }
 
 pub fn main() {}
index bb0221ecb86b448342489a288294386ebd84008f..a9bf2bf763d575b09f91b88f3bd30b0ff026a6b7 100644 (file)
@@ -12,5 +12,13 @@ note: the lint level is defined here
 LL | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+warning: dereferencing a null pointer
+  --> $DIR/issue-7246.rs:7:8
+   |
+LL |     if *ptr::null() {};
+   |        ^^^^^^^^^^^^ this code causes undefined behavior when executed
+   |
+   = note: `#[warn(deref_nullptr)]` on by default
+
+error: aborting due to previous error; 1 warning emitted
 
diff --git a/src/test/ui/issues/issue-72574-2.rs b/src/test/ui/issues/issue-72574-2.rs
deleted file mode 100644 (file)
index 0ad2db8..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-struct Binder(i32, i32, i32);
-
-fn main() {
-    let x = Binder(1, 2, 3);
-    match x {
-        Binder(_a, _x @ ..) => {}
-        _ => {}
-    }
-}
-//~^^^^ ERROR `_x @` is not allowed in a tuple struct
-//~| ERROR: `..` patterns are not allowed here
-//~| ERROR: this pattern has 2 fields, but the corresponding tuple struct has 3 fields
diff --git a/src/test/ui/issues/issue-72574-2.stderr b/src/test/ui/issues/issue-72574-2.stderr
deleted file mode 100644 (file)
index 05650f0..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-error: `_x @` is not allowed in a tuple struct
-  --> $DIR/issue-72574-2.rs:6:20
-   |
-LL |         Binder(_a, _x @ ..) => {}
-   |                    ^^^^^^^ this is only allowed in slice patterns
-   |
-   = help: remove this and bind each tuple field independently
-help: if you don't need to use the contents of _x, discard the tuple's remaining fields
-   |
-LL |         Binder(_a, ..) => {}
-   |                    ~~
-
-error: `..` patterns are not allowed here
-  --> $DIR/issue-72574-2.rs:6:25
-   |
-LL |         Binder(_a, _x @ ..) => {}
-   |                         ^^
-   |
-   = note: only allowed in tuple, tuple struct, and slice patterns
-
-error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 3 fields
-  --> $DIR/issue-72574-2.rs:6:16
-   |
-LL | struct Binder(i32, i32, i32);
-   |               ---  ---  --- tuple struct has 3 fields
-...
-LL |         Binder(_a, _x @ ..) => {}
-   |                ^^  ^^^^^^^ expected 3 fields, found 2
-   |
-help: use `_` to explicitly ignore each field
-   |
-LL |         Binder(_a, _x @ .., _) => {}
-   |                           +++
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0023`.
diff --git a/src/test/ui/issues/issue-73541-1.rs b/src/test/ui/issues/issue-73541-1.rs
deleted file mode 100644 (file)
index 7fb0d6c..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// edition:2018
-
-fn main() {
-    'a: loop {
-        async {
-            loop {
-                continue 'a
-                //~^ ERROR use of unreachable label `'a`
-            }
-        };
-    }
-}
diff --git a/src/test/ui/issues/issue-73541-1.stderr b/src/test/ui/issues/issue-73541-1.stderr
deleted file mode 100644 (file)
index 80c1fdf..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0767]: use of unreachable label `'a`
-  --> $DIR/issue-73541-1.rs:7:26
-   |
-LL |     'a: loop {
-   |     -- unreachable label defined here
-...
-LL |                 continue 'a
-   |                          ^^ unreachable label `'a`
-   |
-   = note: labels are unreachable through functions, closures, async blocks and modules
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0767`.
diff --git a/src/test/ui/issues/issue-73886.rs b/src/test/ui/issues/issue-73886.rs
deleted file mode 100644 (file)
index 9c0c87a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-fn main() {
-    let _ = &&[0] as &[_];
-    //~^ ERROR non-primitive cast: `&&[i32; 1]` as `&[_]`
-    let _ = 7u32 as Option<_>;
-    //~^ ERROR non-primitive cast: `u32` as `Option<_>`
-}
diff --git a/src/test/ui/issues/issue-73886.stderr b/src/test/ui/issues/issue-73886.stderr
deleted file mode 100644 (file)
index a6f8ba6..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0605]: non-primitive cast: `&&[i32; 1]` as `&[_]`
-  --> $DIR/issue-73886.rs:2:13
-   |
-LL |     let _ = &&[0] as &[_];
-   |             ^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
-
-error[E0605]: non-primitive cast: `u32` as `Option<_>`
-  --> $DIR/issue-73886.rs:4:13
-   |
-LL |     let _ = 7u32 as Option<_>;
-   |             ^^^^^^^^^^^^^^^^^ help: consider using the `From` trait instead: `Option<_>::from(7u32)`
-   |
-   = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0605`.
diff --git a/src/test/ui/issues/issue-74739.rs b/src/test/ui/issues/issue-74739.rs
deleted file mode 100644 (file)
index 0362235..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// compile-flags: -O
-// run-pass
-
-struct Foo {
-    x: i32,
-}
-
-pub fn main() {
-    let mut foo = Foo { x: 42 };
-    let x = &mut foo.x;
-    *x = 13;
-    let y = foo;
-    assert_eq!(y.x, 13); // used to print 42 due to mir-opt bug
-}
diff --git a/src/test/ui/issues/issue-811.rs b/src/test/ui/issues/issue-811.rs
deleted file mode 100644 (file)
index f929d38..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// run-fail
-// error-pattern:quux
-// ignore-emscripten no processes
-
-use std::marker::PhantomData;
-
-fn test00_start(ch: Chan<isize>, message: isize) {
-    send(ch, message);
-}
-
-type TaskId = isize;
-type PortId = isize;
-
-struct Chan<T> {
-    task: TaskId,
-    port: PortId,
-    marker: PhantomData<*mut T>,
-}
-
-fn send<T: Send>(_ch: Chan<T>, _data: T) {
-    panic!();
-}
-
-fn main() {
-    panic!("quux");
-}
diff --git a/src/test/ui/issues/issue-8351-1.rs b/src/test/ui/issues/issue-8351-1.rs
deleted file mode 100644 (file)
index 139f027..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-
-enum E {
-    Foo{f: isize},
-    Bar,
-}
-
-pub fn main() {
-    let e = E::Foo{f: 0};
-    match e {
-        E::Foo{f: 1} => panic!(),
-        E::Foo{..} => (),
-        _ => panic!(),
-    }
-}
diff --git a/src/test/ui/issues/issue-8351-2.rs b/src/test/ui/issues/issue-8351-2.rs
deleted file mode 100644 (file)
index bc66cbb..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-
-enum E {
-    Foo{f: isize, b: bool},
-    Bar,
-}
-
-pub fn main() {
-    let e = E::Foo{f: 0, b: false};
-    match e {
-        E::Foo{f: 1, b: true} => panic!(),
-        E::Foo{b: false, f: 0} => (),
-        _ => panic!(),
-    }
-}
diff --git a/src/test/ui/issues/issue-86865.rs b/src/test/ui/issues/issue-86865.rs
deleted file mode 100644 (file)
index 01e0a20..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-use std::fmt::Write;
-
-fn main() {
-    println!(b"foo");
-    //~^ ERROR format argument must be a string literal
-    //~| HELP consider removing the leading `b`
-    let mut s = String::new();
-    write!(s, b"foo{}", "bar");
-    //~^ ERROR format argument must be a string literal
-    //~| HELP consider removing the leading `b`
-}
diff --git a/src/test/ui/issues/issue-86865.stderr b/src/test/ui/issues/issue-86865.stderr
deleted file mode 100644 (file)
index eed7553..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error: format argument must be a string literal
-  --> $DIR/issue-86865.rs:4:14
-   |
-LL |     println!(b"foo");
-   |              -^^^^^
-   |              |
-   |              help: consider removing the leading `b`
-
-error: format argument must be a string literal
-  --> $DIR/issue-86865.rs:8:15
-   |
-LL |     write!(s, b"foo{}", "bar");
-   |               -^^^^^^^
-   |               |
-   |               help: consider removing the leading `b`
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/issues/issue-8827.rs b/src/test/ui/issues/issue-8827.rs
deleted file mode 100644 (file)
index 95be761..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-// run-pass
-// ignore-emscripten no threads support
-
-use std::thread;
-use std::sync::mpsc::{channel, Receiver};
-
-fn periodical(n: isize) -> Receiver<bool> {
-    let (chan, port) = channel();
-    thread::spawn(move|| {
-        loop {
-            for _ in 1..n {
-                match chan.send(false) {
-                    Ok(()) => {}
-                    Err(..) => break,
-                }
-            }
-            match chan.send(true) {
-                Ok(()) => {}
-                Err(..) => break
-            }
-        }
-    });
-    return port;
-}
-
-fn integers() -> Receiver<isize> {
-    let (chan, port) = channel();
-    thread::spawn(move|| {
-        let mut i = 1;
-        loop {
-            match chan.send(i) {
-                Ok(()) => {}
-                Err(..) => break,
-            }
-            i = i + 1;
-        }
-    });
-    return port;
-}
-
-fn main() {
-    let ints = integers();
-    let threes = periodical(3);
-    let fives = periodical(5);
-    for _ in 1..100 {
-        match (ints.recv().unwrap(), threes.recv().unwrap(), fives.recv().unwrap()) {
-            (_, true, true) => println!("FizzBuzz"),
-            (_, true, false) => println!("Fizz"),
-            (_, false, true) => println!("Buzz"),
-            (i, false, false) => println!("{}", i)
-        }
-    }
-}
diff --git a/src/test/ui/issues/issue-9396.rs b/src/test/ui/issues/issue-9396.rs
deleted file mode 100644 (file)
index 3e7e9a5..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// run-pass
-#![allow(unused_must_use)]
-#![allow(deprecated)]
-// ignore-emscripten no threads support
-
-use std::sync::mpsc::{TryRecvError, channel};
-use std::thread;
-
-pub fn main() {
-    let (tx, rx) = channel();
-    let t = thread::spawn(move||{
-        thread::sleep_ms(10);
-        tx.send(()).unwrap();
-    });
-    loop {
-        match rx.try_recv() {
-            Ok(()) => break,
-            Err(TryRecvError::Empty) => {}
-            Err(TryRecvError::Disconnected) => unreachable!()
-        }
-    }
-    t.join();
-}
index ec54ed005173b148fc37bbe146e4e7736caad086..158317efe4782c9b1e23014e26503f5c76a304d3 100644 (file)
@@ -1,6 +1,5 @@
 // check-pass
 // edition:2021
-// compile-flags: -Zunstable-options
 
 use std::array::IntoIter;
 use std::ops::Deref;
diff --git a/src/test/ui/lambda-var-hygiene.rs b/src/test/ui/lambda-var-hygiene.rs
deleted file mode 100644 (file)
index bf06765..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// run-pass
-// shouldn't affect evaluation of $ex:
-macro_rules! bad_macro {
-    ($ex:expr) => ({(|_x| { $ex }) (9) })
-}
-
-fn takes_x(_x : isize) {
-    assert_eq!(bad_macro!(_x),8);
-}
-fn main() {
-    takes_x(8);
-}
diff --git a/src/test/ui/lang-items/issue-19660.rs b/src/test/ui/lang-items/issue-19660.rs
new file mode 100644 (file)
index 0000000..400ac31
--- /dev/null
@@ -0,0 +1,15 @@
+// error-pattern: requires `copy` lang_item
+
+#![feature(lang_items, start, no_core)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized { }
+
+struct S;
+
+#[start]
+fn main(_: isize, _: *const *const u8) -> isize {
+    let _ = S;
+    0
+}
diff --git a/src/test/ui/lang-items/issue-19660.stderr b/src/test/ui/lang-items/issue-19660.stderr
new file mode 100644 (file)
index 0000000..f5d903f
--- /dev/null
@@ -0,0 +1,4 @@
+error: requires `copy` lang_item
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lang-items/issue-31076.rs b/src/test/ui/lang-items/issue-31076.rs
new file mode 100644 (file)
index 0000000..cdb196d
--- /dev/null
@@ -0,0 +1,17 @@
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized {}
+
+#[lang="add"]
+trait Add<T> {}
+
+impl Add<i32> for i32 {}
+
+fn main() {
+    let x = 5 + 6;
+    //~^ ERROR cannot add `i32` to `{integer}`
+    let y = 5i32 + 6i32;
+    //~^ ERROR cannot add `i32` to `i32`
+}
diff --git a/src/test/ui/lang-items/issue-31076.stderr b/src/test/ui/lang-items/issue-31076.stderr
new file mode 100644 (file)
index 0000000..ac0d9dc
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0369]: cannot add `i32` to `{integer}`
+  --> $DIR/issue-31076.rs:13:15
+   |
+LL |     let x = 5 + 6;
+   |             - ^ - i32
+   |             |
+   |             {integer}
+
+error[E0369]: cannot add `i32` to `i32`
+  --> $DIR/issue-31076.rs:15:18
+   |
+LL |     let y = 5i32 + 6i32;
+   |             ---- ^ ---- i32
+   |             |
+   |             i32
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/lang-items/required-lang-item.rs b/src/test/ui/lang-items/required-lang-item.rs
new file mode 100644 (file)
index 0000000..3b17c5b
--- /dev/null
@@ -0,0 +1,11 @@
+// build-fail
+
+#![feature(lang_items, no_core)]
+#![no_core]
+
+#[lang="copy"] pub trait Copy { }
+#[lang="sized"] pub trait Sized { }
+
+// error-pattern:requires `start` lang_item
+
+fn main() {}
diff --git a/src/test/ui/lang-items/required-lang-item.stderr b/src/test/ui/lang-items/required-lang-item.stderr
new file mode 100644 (file)
index 0000000..83764a9
--- /dev/null
@@ -0,0 +1,4 @@
+error: requires `start` lang_item
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/legacy-const-generics-bad.rs b/src/test/ui/legacy-const-generics-bad.rs
deleted file mode 100644 (file)
index 538eee3..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// aux-build:legacy-const-generics.rs
-
-extern crate legacy_const_generics;
-
-fn foo<const N: usize>() {
-    let a = 1;
-    legacy_const_generics::foo(0, a, 2);
-    //~^ ERROR attempt to use a non-constant value in a constant
-
-    legacy_const_generics::foo(0, N, 2);
-
-    legacy_const_generics::foo(0, N + 1, 2);
-    //~^ ERROR generic parameters may not be used in const operations
-}
-
-fn main() {}
diff --git a/src/test/ui/legacy-const-generics-bad.stderr b/src/test/ui/legacy-const-generics-bad.stderr
deleted file mode 100644 (file)
index 3c78dd6..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/legacy-const-generics-bad.rs:7:35
-   |
-LL |     let a = 1;
-   |     ----- help: consider using `const` instead of `let`: `const a`
-LL |     legacy_const_generics::foo(0, a, 2);
-   |                                   ^ non-constant value
-
-error: generic parameters may not be used in const operations
-  --> $DIR/legacy-const-generics-bad.rs:12:35
-   |
-LL |     legacy_const_generics::foo(0, N + 1, 2);
-   |                                   ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/legacy-const-generics.rs b/src/test/ui/legacy-const-generics.rs
deleted file mode 100644 (file)
index 9abc72d..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// aux-build:legacy-const-generics.rs
-// run-pass
-
-#![feature(rustc_attrs)]
-
-extern crate legacy_const_generics;
-
-#[rustc_legacy_const_generics(1)]
-pub fn bar<const Y: usize>(x: usize, z: usize) -> [usize; 3] {
-    [x, Y, z]
-}
-
-fn main() {
-    assert_eq!(legacy_const_generics::foo(0 + 0, 1 + 1, 2 + 2), [0, 2, 4]);
-    assert_eq!(legacy_const_generics::foo::<{1 + 1}>(0 + 0, 2 + 2), [0, 2, 4]);
-    // FIXME: Only works cross-crate
-    //assert_eq!(bar(0, 1, 2), [0, 1, 2]);
-}
diff --git a/src/test/ui/lifetimes/issue-26638.rs b/src/test/ui/lifetimes/issue-26638.rs
new file mode 100644 (file)
index 0000000..72fe428
--- /dev/null
@@ -0,0 +1,10 @@
+fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() }
+//~^ ERROR missing lifetime specifier [E0106]
+
+fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
+//~^ ERROR missing lifetime specifier [E0106]
+
+fn parse_type_3() -> &str { unimplemented!() }
+//~^ ERROR missing lifetime specifier [E0106]
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/issue-26638.stderr b/src/test/ui/lifetimes/issue-26638.stderr
new file mode 100644 (file)
index 0000000..bb7cdcb
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-26638.rs:1:62
+   |
+LL | fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() }
+   |                     ------------------------------------     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of `iter`'s 2 lifetimes it is borrowed from
+help: consider introducing a named lifetime parameter
+   |
+LL | fn parse_type<'a>(iter: Box<dyn Iterator<Item=&str>+'static>) -> &'a str { iter.next() }
+   |              ++++                                                 ++
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-26638.rs:4:40
+   |
+LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
+   |                                        ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
+help: consider using the `'static` lifetime
+   |
+LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &'static str { iter() }
+   |                                        ~~~~~~~~
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-26638.rs:7:22
+   |
+LL | fn parse_type_3() -> &str { unimplemented!() }
+   |                      ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+   |
+LL | fn parse_type_3() -> &'static str { unimplemented!() }
+   |                      ~~~~~~~~
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.fixed b/src/test/ui/lifetimes/issue-90170-elision-mismatch.fixed
new file mode 100644 (file)
index 0000000..0bc889e
--- /dev/null
@@ -0,0 +1,9 @@
+// run-rustfix
+
+pub fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime mismatch
+
+pub fn foo2<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime mismatch
+
+pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime mismatch
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.nll.stderr b/src/test/ui/lifetimes/issue-90170-elision-mismatch.nll.stderr
new file mode 100644 (file)
index 0000000..a5bc745
--- /dev/null
@@ -0,0 +1,29 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-90170-elision-mismatch.rs:3:40
+   |
+LL | pub fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); }
+   |                        -        -      ^^^^^^^^^ argument requires that `'1` must outlive `'2`
+   |                        |        |
+   |                        |        let's call the lifetime of this reference `'1`
+   |                        let's call the lifetime of this reference `'2`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-90170-elision-mismatch.rs:5:44
+   |
+LL | pub fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); }
+   |                         -           -      ^^^^^^^^^ argument requires that `'1` must outlive `'2`
+   |                         |           |
+   |                         |           let's call the lifetime of this reference `'1`
+   |                         let's call the lifetime of this reference `'2`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-90170-elision-mismatch.rs:7:63
+   |
+LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); }
+   |                                               -        -      ^^^^^^^^^ argument requires that `'1` must outlive `'2`
+   |                                               |        |
+   |                                               |        let's call the lifetime of this reference `'1`
+   |                                               let's call the lifetime of this reference `'2`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.rs b/src/test/ui/lifetimes/issue-90170-elision-mismatch.rs
new file mode 100644 (file)
index 0000000..1d6573c
--- /dev/null
@@ -0,0 +1,9 @@
+// run-rustfix
+
+pub fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); } //~ ERROR lifetime mismatch
+
+pub fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); } //~ ERROR lifetime mismatch
+
+pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); } //~ ERROR lifetime mismatch
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr b/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr
new file mode 100644 (file)
index 0000000..7fa092c
--- /dev/null
@@ -0,0 +1,45 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/issue-90170-elision-mismatch.rs:3:47
+   |
+LL | pub fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); }
+   |                        ---      ---           ^ ...but data from `y` flows into `x` here
+   |                                 |
+   |                                 these two types are declared with different lifetimes...
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | pub fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }
+   |           ++++              ++          ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/issue-90170-elision-mismatch.rs:5:51
+   |
+LL | pub fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); }
+   |                         ------      ---           ^ ...but data from `y` flows into `x` here
+   |                                     |
+   |                                     these two types are declared with different lifetimes...
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | pub fn foo2<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }
+   |            ++++              ~~          ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/issue-90170-elision-mismatch.rs:7:70
+   |
+LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); }
+   |                                               ---      ---           ^ ...but data from `y` flows into `x` here
+   |                                                        |
+   |                                                        these two types are declared with different lifetimes...
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }
+   |                                                ++          ++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
index 0aff80c6fbdd3c3fb3f316c75ea0f8a940e7a597..5c793636778ea2c9505bcb81e5f4416c5e7bf838 100644 (file)
@@ -5,6 +5,12 @@ LL | fn foo(&mut (ref mut v, w): &mut (&u8, &u8), x: &u8) {
    |                                   ---           --- these two types are declared with different lifetimes...
 LL |     *v = x;
    |          ^ ...but data from `x` flows here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'a>(&mut (ref mut v, w): &mut (&'a u8, &u8), x: &'a u8) {
+   |       ++++                             ++               ++
 
 error: aborting due to previous error
 
index 2e5ff6782d3b65ac0f617879e7cb025caa750893..1a7b4fca1ba7846729a02f714d3d06597142675f 100644 (file)
@@ -5,6 +5,12 @@ LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
    |                     ---                 --- these two types are declared with different lifetimes...
 LL |     z.push((x,y));
    |             ^ ...but data flows into `z` here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'a>(z: &mut Vec<(&'a u8,&u8)>, (x, y): (&'a u8, &u8)) {
+   |       ++++               ++                     ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ex3-both-anon-regions-3.rs:2:15
@@ -13,6 +19,12 @@ LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
    |                         ---                  --- these two types are declared with different lifetimes...
 LL |     z.push((x,y));
    |               ^ ...but data flows into `z` here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'a>(z: &mut Vec<(&u8,&'a u8)>, (x, y): (&u8, &'a u8)) {
+   |       ++++                   ++                      ++
 
 error: aborting due to 2 previous errors
 
index d2cc3dba6a4336cce5781dd19a8b6249d50f26f8..6ed3528bb9faac790382bea6d763496425066ea0 100644 (file)
@@ -5,6 +5,12 @@ LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) {
    |                               ---      --- these two types are declared with different lifetimes...
 LL |   y.push(z);
    |          ^ ...but data from `z` flows into `y` here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'a>(x:fn(&u8, &u8), y: Vec<&'a u8>, z: &'a u8) {
+   |       ++++                         ++          ++
 
 error: aborting due to previous error
 
index 2acc4eaf60f557dc1510588e1e5c794dc0b0fb0a..ede1631db271c46593a8f68186fabb5a7a988984 100644 (file)
@@ -5,6 +5,12 @@ LL | fn foo(x:Box<dyn Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) {
    |                     ---  --- these two types are declared with different lifetimes...
 LL |   y.push(z);
    |          ^ ...but data from `z` flows into `y` here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'a>(x:Box<dyn Fn(&'a u8, &'a u8)> , y: Vec<&u8>, z: &u8) {
+   |       ++++               ++      ++
 
 error: aborting due to previous error
 
index b2784827672b8fb165d45c6b5f286673d7cc1589..cf405c0de3f0b40924f451f4cc424696217ec7de 100644 (file)
@@ -5,6 +5,12 @@ LL | fn foo(x: &mut Vec<&u8>, y: &u8) {
    |                    ---      --- these two types are declared with different lifetimes...
 LL |     x.push(y);
    |            ^ ...but data from `y` flows into `x` here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) {
+   |       ++++              ++          ++
 
 error: aborting due to previous error
 
index 38c5487183ca1bfa494fdf22ba7e96bebeea0d68..d9673faa2142e4c5a226143f38a3308f67475ee1 100644 (file)
@@ -4,10 +4,12 @@ mod foo {
 #![allow(uncommon_codepoints)]
 //~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
 //~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
+//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
 
 #[allow(uncommon_codepoints)]
 //~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
 //~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
+//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
 const BAR: f64 = 0.000001;
 
 }
@@ -15,5 +17,6 @@ mod foo {
 #[allow(uncommon_codepoints)]
 //~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
 //~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
+//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
 fn main() {
 }
index 83bea0412ffd52e794962ff65be131f61c820bfe..8fb06df2a481a68297e4b9ff65639fdd632f09e7 100644 (file)
@@ -11,13 +11,13 @@ LL | #![deny(uncommon_codepoints, unused_attributes)]
    |                              ^^^^^^^^^^^^^^^^^
 
 error: allow(uncommon_codepoints) is ignored unless specified at crate level
-  --> $DIR/crate_level_only_lint.rs:8:9
+  --> $DIR/crate_level_only_lint.rs:9:9
    |
 LL | #[allow(uncommon_codepoints)]
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: allow(uncommon_codepoints) is ignored unless specified at crate level
-  --> $DIR/crate_level_only_lint.rs:15:9
+  --> $DIR/crate_level_only_lint.rs:17:9
    |
 LL | #[allow(uncommon_codepoints)]
    |         ^^^^^^^^^^^^^^^^^^^
@@ -29,16 +29,34 @@ LL | #![allow(uncommon_codepoints)]
    |          ^^^^^^^^^^^^^^^^^^^
 
 error: allow(uncommon_codepoints) is ignored unless specified at crate level
-  --> $DIR/crate_level_only_lint.rs:8:9
+  --> $DIR/crate_level_only_lint.rs:9:9
    |
 LL | #[allow(uncommon_codepoints)]
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: allow(uncommon_codepoints) is ignored unless specified at crate level
-  --> $DIR/crate_level_only_lint.rs:15:9
+  --> $DIR/crate_level_only_lint.rs:17:9
    |
 LL | #[allow(uncommon_codepoints)]
    |         ^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors
+error: allow(uncommon_codepoints) is ignored unless specified at crate level
+  --> $DIR/crate_level_only_lint.rs:4:10
+   |
+LL | #![allow(uncommon_codepoints)]
+   |          ^^^^^^^^^^^^^^^^^^^
+
+error: allow(uncommon_codepoints) is ignored unless specified at crate level
+  --> $DIR/crate_level_only_lint.rs:9:9
+   |
+LL | #[allow(uncommon_codepoints)]
+   |         ^^^^^^^^^^^^^^^^^^^
+
+error: allow(uncommon_codepoints) is ignored unless specified at crate level
+  --> $DIR/crate_level_only_lint.rs:17:9
+   |
+LL | #[allow(uncommon_codepoints)]
+   |         ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 9 previous errors
 
index 7d8a398181493b16e1edebef0a3e2739985a38bb..b12fd72da74946bc5355159eb03887cf8ae4339b 100644 (file)
 //~| WARNING previously accepted by the compiler
 //~| ERROR incompatible with previous
 //~| WARNING previously accepted by the compiler
+//~| ERROR incompatible with previous
+//~| WARNING previously accepted by the compiler
+//~| ERROR incompatible with previous
+//~| WARNING previously accepted by the compiler
+//~| ERROR incompatible with previous
+//~| WARNING previously accepted by the compiler
 fn main() {}
index d8c09e6526a2d6f340b6114792230a7556670730..214e949c11a748990d8b906b48c2b82414d1f3a4 100644 (file)
@@ -75,5 +75,41 @@ LL | #[allow(nonstandard_style)]
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
 
-error: aborting due to 6 previous errors
+error: allow(nonstandard_style) incompatible with previous forbid
+  --> $DIR/forbid-group-group-2.rs:7:9
+   |
+LL | #![forbid(warnings)]
+   |           -------- `forbid` level set here
+...
+LL | #[allow(nonstandard_style)]
+   |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
+
+error: allow(nonstandard_style) incompatible with previous forbid
+  --> $DIR/forbid-group-group-2.rs:7:9
+   |
+LL | #![forbid(warnings)]
+   |           -------- `forbid` level set here
+...
+LL | #[allow(nonstandard_style)]
+   |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
+
+error: allow(nonstandard_style) incompatible with previous forbid
+  --> $DIR/forbid-group-group-2.rs:7:9
+   |
+LL | #![forbid(warnings)]
+   |           -------- `forbid` level set here
+...
+LL | #[allow(nonstandard_style)]
+   |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
+
+error: aborting due to 9 previous errors
 
index 3fab9148392beae16e234badeeae7c8bfcf367ee..3a3d81176d691363bd6488e7bc2d8fb7f78ee668 100644 (file)
@@ -1,6 +1,6 @@
 // --force-warn $LINT causes $LINT (which is deny-by-default) to warn
 // despite $LINT being allowed on command line
-// compile-flags: -A const_err --force-warn const_err -Zunstable-options
+// compile-flags: -A const_err --force-warn const_err
 // check-pass
 
 const C: i32 = 1 / 0;
index 4eb05b538b0baea63e6e4c9c9bdc75272e98d7e1..9736027452a8df0811863d80ea2d3c1cceaa7e9f 100644 (file)
@@ -1,6 +1,6 @@
 // --force-warn $LINT_GROUP causes $LINT (which is warn-by-default) to warn
 // despite $LINT being allowed on command line
-// compile-flags: -A bare-trait-objects --force-warn rust-2018-idioms -Zunstable-options
+// compile-flags: -A bare-trait-objects --force-warn rust-2018-idioms
 // check-pass
 
 pub trait SomeTrait {}
index d2cb3417be68a272c412622ac06afdc40994f8c1..267e7b45f0c2137c3666950640ffc551332c68c2 100644 (file)
@@ -1,6 +1,6 @@
 // --force-warn $LINT causes $LINT (which is warn-by-default) to warn
 // despite being allowed in one submodule (but not the other)
-// compile-flags: --force-warn dead_code -Zunstable-options
+// compile-flags: --force-warn dead_code
 // check-pass
 
 mod one {
index fa25a1f8a842a906fd9c140e61aae4c253c8a77f..d1d4f5602f271eeb0bb1034c5279667cc55f0659 100644 (file)
@@ -1,5 +1,5 @@
 // --force-warn warnings is an error
-// compile-flags: --force-warn warnings -Zunstable-options
+// compile-flags: --force-warn warnings
 // error-pattern: `warnings` lint group is not supported
 
 fn main() {}
index 03f5788b527d3fabfd50bfcfddd9f1325a0874a9..1faeed33704511d900175c73dfe6577a2b283179 100644 (file)
@@ -2,8 +2,6 @@ error[E0602]: `warnings` lint group is not supported with ´--force-warn´
 
 error[E0602]: `warnings` lint group is not supported with ´--force-warn´
 
-error[E0602]: `warnings` lint group is not supported with ´--force-warn´
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0602`.
diff --git a/src/test/ui/lint/issue-14837.rs b/src/test/ui/lint/issue-14837.rs
new file mode 100644 (file)
index 0000000..a83bc41
--- /dev/null
@@ -0,0 +1,11 @@
+// check-pass
+// pretty-expanded FIXME #23616
+
+#[deny(dead_code)]
+pub enum Foo {
+    Bar {
+        baz: isize
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/lint/issue-57410-1.rs b/src/test/ui/lint/issue-57410-1.rs
new file mode 100644 (file)
index 0000000..d825cb1
--- /dev/null
@@ -0,0 +1,18 @@
+// check-pass
+
+// Originally from #53925.
+// Tests that the `unreachable_pub` lint doesn't fire for `pub self::bar::Bar`.
+
+#![deny(unreachable_pub)]
+
+mod foo {
+    mod bar {
+        pub struct Bar;
+    }
+
+    pub use self::bar::Bar;
+}
+
+pub use foo::Bar;
+
+fn main() {}
diff --git a/src/test/ui/lint/issue-63364.rs b/src/test/ui/lint/issue-63364.rs
new file mode 100644 (file)
index 0000000..5223267
--- /dev/null
@@ -0,0 +1,10 @@
+fn part(_: u16) -> u32 {
+    1
+}
+
+fn main() {
+    for n in 100_000.. {
+    //~^ ERROR: literal out of range for `u16`
+        let _ = part(n);
+    }
+}
diff --git a/src/test/ui/lint/issue-63364.stderr b/src/test/ui/lint/issue-63364.stderr
new file mode 100644 (file)
index 0000000..0375359
--- /dev/null
@@ -0,0 +1,11 @@
+error: literal out of range for `u16`
+  --> $DIR/issue-63364.rs:6:14
+   |
+LL |     for n in 100_000.. {
+   |              ^^^^^^^
+   |
+   = note: `#[deny(overflowing_literals)]` on by default
+   = note: the literal `100_000` does not fit into the type `u16` whose range is `0..=65535`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs b/src/test/ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs
new file mode 100644 (file)
index 0000000..425e270
--- /dev/null
@@ -0,0 +1,9 @@
+// check-pass
+// Allowing the code lint should work without warning and
+// the text flow char in the comment should be ignored.
+
+#![allow(text_direction_codepoint_in_comment)]
+
+fn main() {
+    // U+2066 LEFT-TO-RIGHT ISOLATE follows:⁦⁦
+}
index b08fbf6f845f88d2b30656db5b132104e9e0c3cd..3ee55ba96b1378746cd26726d543a88b08108b40 100644 (file)
@@ -13,4 +13,5 @@ macro_rules! evil {
 
 fn main() {
     println!("{}", evil!(*(0 as *const u8)));
+    //~^ WARNING dereferencing a null pointer
 }
index e31c003985ed8e606082245760b56fd0a07650a7..ba425ceb442b216c988b165e2f5e8755651cffcc 100644 (file)
@@ -10,5 +10,13 @@ note: the lint level is defined here
 LL | #![forbid(unsafe_code)]
    |           ^^^^^^^^^^^
 
-error: aborting due to previous error
+warning: dereferencing a null pointer
+  --> $DIR/lint-forbid-internal-unsafe.rs:15:26
+   |
+LL |     println!("{}", evil!(*(0 as *const u8)));
+   |                          ^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
+   |
+   = note: `#[warn(deref_nullptr)]` on by default
+
+error: aborting due to previous error; 1 warning emitted
 
diff --git a/src/test/ui/lint/must_not_suspend/gated.rs b/src/test/ui/lint/must_not_suspend/gated.rs
new file mode 100644 (file)
index 0000000..acb81b0
--- /dev/null
@@ -0,0 +1,14 @@
+// edition:2018
+#![deny(must_not_suspend)]  //~ ERROR the `must_not_suspend`
+//~| ERROR the `must_not_suspend`
+//~| ERROR the `must_not_suspend`
+
+async fn other() {}
+
+pub async fn uhoh(m: std::sync::Mutex<()>) {
+    let _guard = m.lock().unwrap(); //~ ERROR `MutexGuard` held across
+    other().await;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/lint/must_not_suspend/gated.stderr b/src/test/ui/lint/must_not_suspend/gated.stderr
new file mode 100644 (file)
index 0000000..be077de
--- /dev/null
@@ -0,0 +1,54 @@
+error[E0658]: the `must_not_suspend` lint is unstable
+  --> $DIR/gated.rs:2:1
+   |
+LL | #![deny(must_not_suspend)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information
+   = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable
+
+error[E0658]: the `must_not_suspend` lint is unstable
+  --> $DIR/gated.rs:2:1
+   |
+LL | #![deny(must_not_suspend)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information
+   = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable
+
+error[E0658]: the `must_not_suspend` lint is unstable
+  --> $DIR/gated.rs:2:1
+   |
+LL | #![deny(must_not_suspend)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information
+   = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable
+
+error: `MutexGuard` held across a suspend point, but should not be
+  --> $DIR/gated.rs:9:9
+   |
+LL |     let _guard = m.lock().unwrap();
+   |         ^^^^^^
+LL |     other().await;
+   |     ------------- the value is held across this suspend point
+   |
+note: the lint level is defined here
+  --> $DIR/gated.rs:2:9
+   |
+LL | #![deny(must_not_suspend)]
+   |         ^^^^^^^^^^^^^^^^
+note: holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Futures to not implement `Send`
+  --> $DIR/gated.rs:9:9
+   |
+LL |     let _guard = m.lock().unwrap();
+   |         ^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+  --> $DIR/gated.rs:9:9
+   |
+LL |     let _guard = m.lock().unwrap();
+   |         ^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/lint/must_not_suspend/issue-89562.rs b/src/test/ui/lint/must_not_suspend/issue-89562.rs
new file mode 100644 (file)
index 0000000..acdb36f
--- /dev/null
@@ -0,0 +1,19 @@
+// edition:2018
+// run-pass
+
+use std::sync::Mutex;
+
+// Copied from the issue. Allow-by-default for now, so run-pass
+pub async fn foo() {
+    let foo = Mutex::new(1);
+    let lock = foo.lock().unwrap();
+
+    // Prevent mutex lock being held across `.await` point.
+    drop(lock);
+
+    bar().await;
+}
+
+async fn bar() {}
+
+fn main() {}
index 596249b2e4e4fa8efd4eebb4b7bea11a3b6359c9..7bb895e7d36438f143181273f304f4d2c017f374 100644 (file)
@@ -1,4 +1,5 @@
 // edition:2018
+#![feature(must_not_suspend)]
 #![deny(must_not_suspend)]
 
 async fn other() {}
index 093f581264f36c3eea29df0367f2453293618c60..dde506c19e72501b9bb7fdce98902506890c2e08 100644 (file)
@@ -1,5 +1,5 @@
 error: `MutexGuard` held across a suspend point, but should not be
-  --> $DIR/mutex.rs:7:9
+  --> $DIR/mutex.rs:8:9
    |
 LL |     let _guard = m.lock().unwrap();
    |         ^^^^^^
@@ -7,17 +7,17 @@ LL |     other().await;
    |     ------------- the value is held across this suspend point
    |
 note: the lint level is defined here
-  --> $DIR/mutex.rs:2:9
+  --> $DIR/mutex.rs:3:9
    |
 LL | #![deny(must_not_suspend)]
    |         ^^^^^^^^^^^^^^^^
 note: holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Futures to not implement `Send`
-  --> $DIR/mutex.rs:7:9
+  --> $DIR/mutex.rs:8:9
    |
 LL |     let _guard = m.lock().unwrap();
    |         ^^^^^^
 help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
-  --> $DIR/mutex.rs:7:9
+  --> $DIR/mutex.rs:8:9
    |
 LL |     let _guard = m.lock().unwrap();
    |         ^^^^^^
index 50a696ba52322adb11dab5942328ae665f85fb2d..7fdea66a23517d5967e4241685820d499471f4e9 100644 (file)
@@ -1,6 +1,7 @@
 // edition:2018
 // run-pass
 #![feature(must_not_suspend)]
+#![warn(must_not_suspend)]
 
 #[must_not_suspend = "You gotta use Umm's, ya know?"]
 struct Umm {
index 24f52275b430afe1114bc69926318f92970e8335..42374d4acac275f304fab03cccada0f7f85734e9 100644 (file)
@@ -1,19 +1,23 @@
 warning: `Umm` held across a suspend point, but should not be
-  --> $DIR/warn.rs:20:9
+  --> $DIR/warn.rs:21:9
    |
 LL |     let _guard = bar();
    |         ^^^^^^
 LL |     other().await;
    |     ------------- the value is held across this suspend point
    |
-   = note: `#[warn(must_not_suspend)]` on by default
+note: the lint level is defined here
+  --> $DIR/warn.rs:4:9
+   |
+LL | #![warn(must_not_suspend)]
+   |         ^^^^^^^^^^^^^^^^
 note: You gotta use Umm's, ya know?
-  --> $DIR/warn.rs:20:9
+  --> $DIR/warn.rs:21:9
    |
 LL |     let _guard = bar();
    |         ^^^^^^
 help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
-  --> $DIR/warn.rs:20:9
+  --> $DIR/warn.rs:21:9
    |
 LL |     let _guard = bar();
    |         ^^^^^^
index 81a3427a10274b223cd68fe389c6bd2c74696821..ed8e7ddddc5977f370f343b0555b534727db2e18 100644 (file)
@@ -1,6 +1,7 @@
 #![deny(uncommon_codepoints)]
 
 const µ: f64 = 0.000001; //~ ERROR identifier contains uncommon Unicode codepoints
+//~| WARNING should have an upper case name
 
 fn dijkstra() {} //~ ERROR identifier contains uncommon Unicode codepoints
 
index d435282a6e855cca8c9b571bb9d59113da71e33d..0533da03068ae040d1802b1f8a0d4f6b64ad88dc 100644 (file)
@@ -11,16 +11,24 @@ LL | #![deny(uncommon_codepoints)]
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: identifier contains uncommon Unicode codepoints
-  --> $DIR/lint-uncommon-codepoints.rs:5:4
+  --> $DIR/lint-uncommon-codepoints.rs:6:4
    |
 LL | fn dijkstra() {}
    |    ^^^^^^^
 
 error: identifier contains uncommon Unicode codepoints
-  --> $DIR/lint-uncommon-codepoints.rs:8:9
+  --> $DIR/lint-uncommon-codepoints.rs:9:9
    |
 LL |     let ㇻㇲㇳ = "rust";
    |         ^^^^^^
 
-error: aborting due to 3 previous errors
+warning: constant `µ` should have an upper case name
+  --> $DIR/lint-uncommon-codepoints.rs:3:7
+   |
+LL | const µ: f64 = 0.000001;
+   |       ^ help: convert the identifier to upper case: `Μ`
+   |
+   = note: `#[warn(non_upper_case_globals)]` on by default
+
+error: aborting due to 3 previous errors; 1 warning emitted
 
diff --git a/src/test/ui/lint/unnecessary-extern-crate.rs b/src/test/ui/lint/unnecessary-extern-crate.rs
new file mode 100644 (file)
index 0000000..67eaaf4
--- /dev/null
@@ -0,0 +1,71 @@
+// edition:2018
+
+#![deny(unused_extern_crates)]
+#![feature(test, rustc_private, crate_visibility_modifier)]
+
+extern crate libc;
+//~^ ERROR unused extern crate
+//~| HELP remove
+extern crate libc as x;
+//~^ ERROR unused extern crate
+//~| HELP remove
+
+extern crate proc_macro;
+
+#[macro_use]
+extern crate test;
+
+pub extern crate test as y;
+
+pub extern crate alloc;
+
+pub(crate) extern crate alloc as a;
+
+crate extern crate alloc as b;
+
+mod foo {
+    pub(in crate::foo) extern crate alloc as c;
+
+    pub(super) extern crate alloc as d;
+
+    extern crate libc;
+    //~^ ERROR unused extern crate
+    //~| HELP remove
+
+    extern crate libc as x;
+    //~^ ERROR unused extern crate
+    //~| HELP remove
+
+    pub extern crate test;
+
+    pub extern crate test as y;
+
+    mod bar {
+        extern crate libc;
+        //~^ ERROR unused extern crate
+        //~| HELP remove
+
+        extern crate libc as x;
+        //~^ ERROR unused extern crate
+        //~| HELP remove
+
+        pub(in crate::foo::bar) extern crate alloc as e;
+
+        fn dummy() {
+            e::string::String::new();
+        }
+    }
+
+    fn dummy() {
+        c::string::String::new();
+        d::string::String::new();
+    }
+}
+
+
+fn main() {
+    a::string::String::new();
+    b::string::String::new();
+
+    proc_macro::TokenStream::new();
+}
diff --git a/src/test/ui/lint/unnecessary-extern-crate.stderr b/src/test/ui/lint/unnecessary-extern-crate.stderr
new file mode 100644 (file)
index 0000000..14ba9d0
--- /dev/null
@@ -0,0 +1,44 @@
+error: unused extern crate
+  --> $DIR/unnecessary-extern-crate.rs:6:1
+   |
+LL | extern crate libc;
+   | ^^^^^^^^^^^^^^^^^^ help: remove it
+   |
+note: the lint level is defined here
+  --> $DIR/unnecessary-extern-crate.rs:3:9
+   |
+LL | #![deny(unused_extern_crates)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unused extern crate
+  --> $DIR/unnecessary-extern-crate.rs:9:1
+   |
+LL | extern crate libc as x;
+   | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: unused extern crate
+  --> $DIR/unnecessary-extern-crate.rs:31:5
+   |
+LL |     extern crate libc;
+   |     ^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: unused extern crate
+  --> $DIR/unnecessary-extern-crate.rs:35:5
+   |
+LL |     extern crate libc as x;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: unused extern crate
+  --> $DIR/unnecessary-extern-crate.rs:44:9
+   |
+LL |         extern crate libc;
+   |         ^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: unused extern crate
+  --> $DIR/unnecessary-extern-crate.rs:48:9
+   |
+LL |         extern crate libc as x;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: aborting due to 6 previous errors
+
index 15ee19755bffc504ab84086542be1f91912eb7f3..c4004540467488bc5319d45436bc5153b6750e72 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --error-format json -Zunstable-options
+// compile-flags: --error-format json
 // run-rustfix
 
 // The output for humans should just highlight the whole span without showing
index d72df21e09ae264c8a253850b77f15b65401bdba..962c8bdd7d78957dcf7c837f8f1685cdbffe8734 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --error-format json -Zunstable-options
+// compile-flags: --error-format json
 // run-rustfix
 
 // The output for humans should just highlight the whole span without showing
index 498c25d2e1c44ed4a2318ef21f6170e9861a2b0c..169fb824021ed6e4eea48bb74b0ce135a10fdfdf 100644 (file)
@@ -1,4 +1,4 @@
-{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":596,"byte_end":597,"line_start":16,"line_end":16,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3));
+{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":577,"byte_end":578,"line_start":16,"line_end":16,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3));
   --> $DIR/unused_parens_json_suggestion.rs:16:14
    |
 LL |     let _a = (1 / (2 + 3));
index 1d891d328dd5ab3123026c7a3c5e4154c9c9066d..8a57cd57385f31238c90f3327b72924dc5852b48 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --error-format json -Zunstable-options
+// compile-flags: --error-format json
 // run-rustfix
 
 // The output for humans should just highlight the whole span without showing
index 494cd1845063012aa507356732dab1e076c23786..952332d54e9c10f0e94f2a644551502c90b2a37f 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --error-format json -Zunstable-options
+// compile-flags: --error-format json
 // run-rustfix
 
 // The output for humans should just highlight the whole span without showing
index 08291b10fcc204f284fe3347f193846bc10c1b51..43367aaa9113b67fbe28c01104edb6dbb8953dc9 100644 (file)
@@ -1,4 +1,4 @@
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":500,"byte_end":501,"line_start":17,"line_end":17,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":"    if (_b) {
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":481,"byte_end":482,"line_start":17,"line_end":17,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":"    if (_b) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:17:8
    |
 LL |     if (_b) {
@@ -16,7 +16,7 @@ LL +     if _b {
    | 
 
 "}
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":631,"byte_end":632,"line_start":28,"line_end":28,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":"    if(c) {
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":612,"byte_end":613,"line_start":28,"line_end":28,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":"    if(c) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:28:7
    |
 LL |     if(c) {
@@ -29,7 +29,7 @@ LL +     if c {
    | 
 
 "}
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":711,"byte_end":712,"line_start":32,"line_end":32,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":"    if (c){
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":692,"byte_end":693,"line_start":32,"line_end":32,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":"    if (c){
   --> $DIR/unused_parens_remove_json_suggestion.rs:32:8
    |
 LL |     if (c){
@@ -42,7 +42,7 @@ LL +     if c {
    | 
 
 "}
-{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":794,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":807,"byte_end":808,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":794,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":807,"byte_end":808,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition
+{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":774,"byte_end":775,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":788,"byte_end":789,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":774,"byte_end":775,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":788,"byte_end":789,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition
   --> $DIR/unused_parens_remove_json_suggestion.rs:36:11
    |
 LL |     while (false && true){
@@ -55,7 +55,7 @@ LL +     while false && true {
    | 
 
 "}
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":821,"byte_end":822,"line_start":37,"line_end":37,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":"        if (c) {
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":802,"byte_end":803,"line_start":37,"line_end":37,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":"        if (c) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:37:12
    |
 LL |         if (c) {
@@ -68,7 +68,7 @@ LL +         if c {
    | 
 
 "}
-{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":918,"byte_end":919,"line_start":43,"line_end":43,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":"    while(true && false) {
+{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":899,"byte_end":900,"line_start":43,"line_end":43,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":"    while(true && false) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:43:10
    |
 LL |     while(true && false) {
@@ -81,7 +81,7 @@ LL +     while true && false {
    | 
 
 "}
-{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":987,"byte_end":988,"line_start":44,"line_end":44,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":"        for _ in (0 .. 3){
+{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":968,"byte_end":969,"line_start":44,"line_end":44,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":"        for _ in (0 .. 3){
   --> $DIR/unused_parens_remove_json_suggestion.rs:44:18
    |
 LL |         for _ in (0 .. 3){
@@ -94,7 +94,7 @@ LL +         for _ in 0 .. 3 {
    | 
 
 "}
-{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1088,"byte_end":1089,"line_start":49,"line_end":49,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":"    for _ in (0 .. 3) {
+{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1069,"byte_end":1070,"line_start":49,"line_end":49,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":"    for _ in (0 .. 3) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:49:14
    |
 LL |     for _ in (0 .. 3) {
@@ -107,7 +107,7 @@ LL +     for _ in 0 .. 3 {
    | 
 
 "}
-{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1147,"byte_end":1148,"line_start":50,"line_end":50,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":"        while (true && false) {
+{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1128,"byte_end":1129,"line_start":50,"line_end":50,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":"        while (true && false) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:50:15
    |
 LL |         while (true && false) {
diff --git a/src/test/ui/lint/warn-ctypes-inhibit.rs b/src/test/ui/lint/warn-ctypes-inhibit.rs
new file mode 100644 (file)
index 0000000..15d8b09
--- /dev/null
@@ -0,0 +1,15 @@
+// run-pass
+
+#![allow(dead_code)]
+// compile-flags:-D improper-ctypes
+
+// pretty-expanded FIXME #23616
+#![allow(improper_ctypes)]
+
+mod libc {
+    extern "C" {
+        pub fn malloc(size: isize) -> *const u8;
+    }
+}
+
+pub fn main() {}
diff --git a/src/test/ui/llvm-asm/issue-23458.rs b/src/test/ui/llvm-asm/issue-23458.rs
new file mode 100644 (file)
index 0000000..d640828
--- /dev/null
@@ -0,0 +1,12 @@
+#![feature(llvm_asm)]
+#![allow(deprecated)] // llvm_asm!
+// compile-flags: -Ccodegen-units=1
+// build-fail
+// only-x86_64
+
+fn main() {
+    unsafe {
+        llvm_asm!("int $3"); //~ ERROR too few operands for instruction
+                             //~| ERROR invalid operand in inline asm
+    }
+}
diff --git a/src/test/ui/llvm-asm/issue-23458.stderr b/src/test/ui/llvm-asm/issue-23458.stderr
new file mode 100644 (file)
index 0000000..69e458f
--- /dev/null
@@ -0,0 +1,20 @@
+error: invalid operand in inline asm: 'int $3'
+  --> $DIR/issue-23458.rs:9:9
+   |
+LL |         llvm_asm!("int $3");
+   |         ^
+
+error: too few operands for instruction
+  --> $DIR/issue-23458.rs:9:9
+   |
+LL |         llvm_asm!("int $3");
+   |         ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     int 
+   |     ^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/llvm-asm/issue-37366.rs b/src/test/ui/llvm-asm/issue-37366.rs
new file mode 100644 (file)
index 0000000..acc2f3e
--- /dev/null
@@ -0,0 +1,16 @@
+// check-pass
+// ignore-emscripten
+
+#![feature(llvm_asm)]
+#![allow(deprecated)] // llvm_asm!
+
+macro_rules! interrupt_handler {
+    () => {
+        unsafe fn _interrupt_handler() {
+            llvm_asm!("pop  eax" :::: "intel");
+        }
+    }
+}
+interrupt_handler!{}
+
+fn main() {}
diff --git a/src/test/ui/llvm-asm/issue-53787-inline-assembler-macro.rs b/src/test/ui/llvm-asm/issue-53787-inline-assembler-macro.rs
new file mode 100644 (file)
index 0000000..d9fe7ca
--- /dev/null
@@ -0,0 +1,27 @@
+// Regression test for Issue #53787: Fix ICE when creating a label in inline assembler with macros.
+
+// build-fail
+// ignore-emscripten
+
+#![feature(llvm_asm)]
+#![allow(deprecated)] // llvm_asm!
+
+macro_rules! fake_jump {
+    ($id:expr) => {
+        unsafe {
+            llvm_asm!(
+            "
+            jmp $0
+            lea eax, [ebx]
+            xor eax, 0xDEADBEEF
+            retn
+            $0:
+            "::"0"($id)::"volatile", "intel");
+        }
+    };
+}
+
+fn main() {
+    fake_jump!("FirstFunc"); //~ ERROR invalid value for constraint in inline assembly
+    println!("Hello, world!");
+}
diff --git a/src/test/ui/llvm-asm/issue-53787-inline-assembler-macro.stderr b/src/test/ui/llvm-asm/issue-53787-inline-assembler-macro.stderr
new file mode 100644 (file)
index 0000000..fd755e3
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0669]: invalid value for constraint in inline assembly
+  --> $DIR/issue-53787-inline-assembler-macro.rs:25:16
+   |
+LL |     fake_jump!("FirstFunc");
+   |                ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0669`.
diff --git a/src/test/ui/long-while.rs b/src/test/ui/long-while.rs
deleted file mode 100644 (file)
index 529cca7..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// run-pass
-// pretty-expanded FIXME #23616
-
-#![allow(unused_variables)]
-
-pub fn main() {
-    let mut i: isize = 0;
-    while i < 1000000 {
-        i += 1;
-        let x = 3;
-    }
-}
diff --git a/src/test/ui/lto-and-no-bitcode-in-rlib.rs b/src/test/ui/lto-and-no-bitcode-in-rlib.rs
deleted file mode 100644 (file)
index f381240..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-// compile-flags: -C lto -C embed-bitcode=no
-
-fn main() {}
diff --git a/src/test/ui/lto-and-no-bitcode-in-rlib.stderr b/src/test/ui/lto-and-no-bitcode-in-rlib.stderr
deleted file mode 100644 (file)
index 11e370e..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-error: options `-C embed-bitcode=no` and `-C lto` are incompatible
-
diff --git a/src/test/ui/lto-duplicate-symbols.rs b/src/test/ui/lto-duplicate-symbols.rs
deleted file mode 100644 (file)
index 268cf26..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// build-fail
-// aux-build:lto-duplicate-symbols1.rs
-// aux-build:lto-duplicate-symbols2.rs
-// error-pattern:Linking globals named 'foo': symbol multiply defined!
-// compile-flags: -C lto
-// no-prefer-dynamic
-
-extern crate lto_duplicate_symbols1;
-extern crate lto_duplicate_symbols2;
-
-fn main() {}
diff --git a/src/test/ui/lto-duplicate-symbols.stderr b/src/test/ui/lto-duplicate-symbols.stderr
deleted file mode 100644 (file)
index e4de04e..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-warning: Linking globals named 'foo': symbol multiply defined!
-
-error: failed to load bc of "lto-duplicate-symbols2.lto_duplicate_symbols2.693a75b4-cgu.0.rcgu.o": 
-
-error: aborting due to previous error; 1 warning emitted
-
diff --git a/src/test/ui/lto-many-codegen-units.rs b/src/test/ui/lto-many-codegen-units.rs
deleted file mode 100644 (file)
index f0f461f..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// run-pass
-// compile-flags: -C lto -C codegen-units=8
-// no-prefer-dynamic
-
-fn main() {
-}
diff --git a/src/test/ui/lto-opt-level-s.rs b/src/test/ui/lto-opt-level-s.rs
deleted file mode 100644 (file)
index a7d9d50..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// compile-flags: -Clinker-plugin-lto -Copt-level=s
-// build-pass
-// no-prefer-dynamic
-
-#![crate_type = "rlib"]
-
-pub fn foo() {}
diff --git a/src/test/ui/lto-opt-level-z.rs b/src/test/ui/lto-opt-level-z.rs
deleted file mode 100644 (file)
index bf1f5e2..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// compile-flags: -Clinker-plugin-lto -Copt-level=z
-// build-pass
-// no-prefer-dynamic
-
-#![crate_type = "rlib"]
-
-pub fn foo() {}
diff --git a/src/test/ui/lto-rustc-loads-linker-plugin.rs b/src/test/ui/lto-rustc-loads-linker-plugin.rs
deleted file mode 100644 (file)
index 6ef1d45..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// compile-flags: -C lto
-// aux-build:lto-rustc-loads-linker-plugin.rs
-// run-pass
-// no-prefer-dynamic
-
-// This test ensures that if a dependency was compiled with
-// `-Clinker-plugin-lto` then we can compile with `-Clto` and still link against
-// that upstream rlib. This should work because LTO implies we're not actually
-// linking against upstream rlibs since we're generating the object code
-// locally. This test will fail if rustc can't find bytecode in rlibs compiled
-// with `-Clinker-plugin-lto`.
-
-extern crate lto_rustc_loads_linker_plugin;
-
-fn main() {
-    lto_rustc_loads_linker_plugin::foo();
-}
diff --git a/src/test/ui/lto-still-runs-thread-dtors.rs b/src/test/ui/lto-still-runs-thread-dtors.rs
deleted file mode 100644 (file)
index 1c7368b..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-// run-pass
-// compile-flags: -C lto
-// no-prefer-dynamic
-// ignore-emscripten no threads support
-// revisions: mir thir
-// [thir]compile-flags: -Zthir-unsafeck
-
-use std::thread;
-
-static mut HIT: usize = 0;
-
-thread_local!(static A: Foo = Foo);
-
-struct Foo;
-
-impl Drop for Foo {
-    fn drop(&mut self) {
-        unsafe {
-            HIT += 1;
-        }
-    }
-}
-
-fn main() {
-    unsafe {
-        assert_eq!(HIT, 0);
-        thread::spawn(|| {
-            assert_eq!(HIT, 0);
-            A.with(|_| ());
-            assert_eq!(HIT, 0);
-        }).join().unwrap();
-        assert_eq!(HIT, 1);
-    }
-}
diff --git a/src/test/ui/lto-thin-rustc-loads-linker-plugin.rs b/src/test/ui/lto-thin-rustc-loads-linker-plugin.rs
deleted file mode 100644 (file)
index 4d54ce3..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// compile-flags: -C lto=thin
-// aux-build:lto-rustc-loads-linker-plugin.rs
-// run-pass
-// no-prefer-dynamic
-
-// Same as the adjacent `lto-thin-rustc-loads-linker-plugin.rs` test, only with
-// ThinLTO.
-
-extern crate lto_rustc_loads_linker_plugin;
-
-fn main() {
-    lto_rustc_loads_linker_plugin::foo();
-}
diff --git a/src/test/ui/lto/all-crates.rs b/src/test/ui/lto/all-crates.rs
new file mode 100644 (file)
index 0000000..e910b2a
--- /dev/null
@@ -0,0 +1,8 @@
+// run-pass
+
+// compile-flags: -Clto=thin
+// no-prefer-dynamic
+
+fn main() {
+    println!("hello!");
+}
diff --git a/src/test/ui/lto/auxiliary/dylib.rs b/src/test/ui/lto/auxiliary/dylib.rs
new file mode 100644 (file)
index 0000000..e8b7f8f
--- /dev/null
@@ -0,0 +1,6 @@
+// compile-flags: -Z thinlto -C codegen-units=8
+
+#[inline]
+pub fn foo(b: u8) {
+    b.to_string();
+}
diff --git a/src/test/ui/lto/auxiliary/lto-duplicate-symbols1.rs b/src/test/ui/lto/auxiliary/lto-duplicate-symbols1.rs
new file mode 100644 (file)
index 0000000..ec6d056
--- /dev/null
@@ -0,0 +1,6 @@
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+#[no_mangle]
+pub extern "C" fn foo() {}
diff --git a/src/test/ui/lto/auxiliary/lto-duplicate-symbols2.rs b/src/test/ui/lto/auxiliary/lto-duplicate-symbols2.rs
new file mode 100644 (file)
index 0000000..ec6d056
--- /dev/null
@@ -0,0 +1,6 @@
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+#[no_mangle]
+pub extern "C" fn foo() {}
diff --git a/src/test/ui/lto/auxiliary/lto-rustc-loads-linker-plugin.rs b/src/test/ui/lto/auxiliary/lto-rustc-loads-linker-plugin.rs
new file mode 100644 (file)
index 0000000..d24375b
--- /dev/null
@@ -0,0 +1,6 @@
+// compile-flags: -Clinker-plugin-lto
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+pub fn foo() {}
diff --git a/src/test/ui/lto/auxiliary/msvc-imp-present.rs b/src/test/ui/lto/auxiliary/msvc-imp-present.rs
new file mode 100644 (file)
index 0000000..933af05
--- /dev/null
@@ -0,0 +1,11 @@
+// no-prefer-dynamic
+// compile-flags: -Z thinlto -C codegen-units=8 -C prefer-dynamic
+
+#![crate_type = "rlib"]
+#![crate_type = "dylib"]
+
+pub static A: u32 = 43;
+
+pub mod a {
+    pub static A: u32 = 43;
+}
diff --git a/src/test/ui/lto/auxiliary/thin-lto-inlines-aux.rs b/src/test/ui/lto/auxiliary/thin-lto-inlines-aux.rs
new file mode 100644 (file)
index 0000000..5fd3f19
--- /dev/null
@@ -0,0 +1,7 @@
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+pub fn bar() -> u32 {
+    3
+}
diff --git a/src/test/ui/lto/dylib-works.rs b/src/test/ui/lto/dylib-works.rs
new file mode 100644 (file)
index 0000000..9e0782b
--- /dev/null
@@ -0,0 +1,9 @@
+// run-pass
+
+// aux-build:dylib.rs
+
+extern crate dylib;
+
+fn main() {
+    dylib::foo(1);
+}
diff --git a/src/test/ui/lto/lto-and-no-bitcode-in-rlib.rs b/src/test/ui/lto/lto-and-no-bitcode-in-rlib.rs
new file mode 100644 (file)
index 0000000..f381240
--- /dev/null
@@ -0,0 +1,3 @@
+// compile-flags: -C lto -C embed-bitcode=no
+
+fn main() {}
diff --git a/src/test/ui/lto/lto-and-no-bitcode-in-rlib.stderr b/src/test/ui/lto/lto-and-no-bitcode-in-rlib.stderr
new file mode 100644 (file)
index 0000000..11e370e
--- /dev/null
@@ -0,0 +1,2 @@
+error: options `-C embed-bitcode=no` and `-C lto` are incompatible
+
diff --git a/src/test/ui/lto/lto-duplicate-symbols.rs b/src/test/ui/lto/lto-duplicate-symbols.rs
new file mode 100644 (file)
index 0000000..268cf26
--- /dev/null
@@ -0,0 +1,11 @@
+// build-fail
+// aux-build:lto-duplicate-symbols1.rs
+// aux-build:lto-duplicate-symbols2.rs
+// error-pattern:Linking globals named 'foo': symbol multiply defined!
+// compile-flags: -C lto
+// no-prefer-dynamic
+
+extern crate lto_duplicate_symbols1;
+extern crate lto_duplicate_symbols2;
+
+fn main() {}
diff --git a/src/test/ui/lto/lto-duplicate-symbols.stderr b/src/test/ui/lto/lto-duplicate-symbols.stderr
new file mode 100644 (file)
index 0000000..e4de04e
--- /dev/null
@@ -0,0 +1,6 @@
+warning: Linking globals named 'foo': symbol multiply defined!
+
+error: failed to load bc of "lto-duplicate-symbols2.lto_duplicate_symbols2.693a75b4-cgu.0.rcgu.o": 
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/src/test/ui/lto/lto-many-codegen-units.rs b/src/test/ui/lto/lto-many-codegen-units.rs
new file mode 100644 (file)
index 0000000..f0f461f
--- /dev/null
@@ -0,0 +1,6 @@
+// run-pass
+// compile-flags: -C lto -C codegen-units=8
+// no-prefer-dynamic
+
+fn main() {
+}
diff --git a/src/test/ui/lto/lto-opt-level-s.rs b/src/test/ui/lto/lto-opt-level-s.rs
new file mode 100644 (file)
index 0000000..a7d9d50
--- /dev/null
@@ -0,0 +1,7 @@
+// compile-flags: -Clinker-plugin-lto -Copt-level=s
+// build-pass
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+pub fn foo() {}
diff --git a/src/test/ui/lto/lto-opt-level-z.rs b/src/test/ui/lto/lto-opt-level-z.rs
new file mode 100644 (file)
index 0000000..bf1f5e2
--- /dev/null
@@ -0,0 +1,7 @@
+// compile-flags: -Clinker-plugin-lto -Copt-level=z
+// build-pass
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+pub fn foo() {}
diff --git a/src/test/ui/lto/lto-rustc-loads-linker-plugin.rs b/src/test/ui/lto/lto-rustc-loads-linker-plugin.rs
new file mode 100644 (file)
index 0000000..6ef1d45
--- /dev/null
@@ -0,0 +1,17 @@
+// compile-flags: -C lto
+// aux-build:lto-rustc-loads-linker-plugin.rs
+// run-pass
+// no-prefer-dynamic
+
+// This test ensures that if a dependency was compiled with
+// `-Clinker-plugin-lto` then we can compile with `-Clto` and still link against
+// that upstream rlib. This should work because LTO implies we're not actually
+// linking against upstream rlibs since we're generating the object code
+// locally. This test will fail if rustc can't find bytecode in rlibs compiled
+// with `-Clinker-plugin-lto`.
+
+extern crate lto_rustc_loads_linker_plugin;
+
+fn main() {
+    lto_rustc_loads_linker_plugin::foo();
+}
diff --git a/src/test/ui/lto/lto-still-runs-thread-dtors.rs b/src/test/ui/lto/lto-still-runs-thread-dtors.rs
new file mode 100644 (file)
index 0000000..1c7368b
--- /dev/null
@@ -0,0 +1,34 @@
+// run-pass
+// compile-flags: -C lto
+// no-prefer-dynamic
+// ignore-emscripten no threads support
+// revisions: mir thir
+// [thir]compile-flags: -Zthir-unsafeck
+
+use std::thread;
+
+static mut HIT: usize = 0;
+
+thread_local!(static A: Foo = Foo);
+
+struct Foo;
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        unsafe {
+            HIT += 1;
+        }
+    }
+}
+
+fn main() {
+    unsafe {
+        assert_eq!(HIT, 0);
+        thread::spawn(|| {
+            assert_eq!(HIT, 0);
+            A.with(|_| ());
+            assert_eq!(HIT, 0);
+        }).join().unwrap();
+        assert_eq!(HIT, 1);
+    }
+}
diff --git a/src/test/ui/lto/lto-thin-rustc-loads-linker-plugin.rs b/src/test/ui/lto/lto-thin-rustc-loads-linker-plugin.rs
new file mode 100644 (file)
index 0000000..4d54ce3
--- /dev/null
@@ -0,0 +1,13 @@
+// compile-flags: -C lto=thin
+// aux-build:lto-rustc-loads-linker-plugin.rs
+// run-pass
+// no-prefer-dynamic
+
+// Same as the adjacent `lto-thin-rustc-loads-linker-plugin.rs` test, only with
+// ThinLTO.
+
+extern crate lto_rustc_loads_linker_plugin;
+
+fn main() {
+    lto_rustc_loads_linker_plugin::foo();
+}
diff --git a/src/test/ui/lto/msvc-imp-present.rs b/src/test/ui/lto/msvc-imp-present.rs
new file mode 100644 (file)
index 0000000..5498afb
--- /dev/null
@@ -0,0 +1,22 @@
+// run-pass
+
+// aux-build:msvc-imp-present.rs
+// compile-flags: -Z thinlto -C codegen-units=8
+// no-prefer-dynamic
+
+// On MSVC we have a "hack" where we emit symbols that look like `_imp_$name`
+// for all exported statics. This is done because we apply `dllimport` to all
+// imported constants and this allows everything to actually link correctly.
+//
+// The ThinLTO passes aggressively remove symbols if they can, and this test
+// asserts that the ThinLTO passes don't remove these compiler-generated
+// `_imp_*` symbols. The external library that we link in here is compiled with
+// ThinLTO and multiple codegen units and has a few exported constants. Note
+// that we also namely compile the library as both a dylib and an rlib, but we
+// link the rlib to ensure that we assert those generated symbols exist.
+
+extern crate msvc_imp_present as bar;
+
+fn main() {
+    println!("{}", bar::A);
+}
diff --git a/src/test/ui/lto/thin-lto-global-allocator.rs b/src/test/ui/lto/thin-lto-global-allocator.rs
new file mode 100644 (file)
index 0000000..e00c5ca
--- /dev/null
@@ -0,0 +1,7 @@
+// run-pass
+// compile-flags: -Z thinlto -C codegen-units=2
+
+#[global_allocator]
+static A: std::alloc::System = std::alloc::System;
+
+fn main() {}
diff --git a/src/test/ui/lto/thin-lto-inlines.rs b/src/test/ui/lto/thin-lto-inlines.rs
new file mode 100644 (file)
index 0000000..dca7918
--- /dev/null
@@ -0,0 +1,30 @@
+// run-pass
+
+// compile-flags: -Z thinlto -C codegen-units=8 -O
+// ignore-emscripten can't inspect instructions on emscripten
+
+// We want to assert here that ThinLTO will inline across codegen units. There's
+// not really a great way to do that in general so we sort of hack around it by
+// praying two functions go into separate codegen units and then assuming that
+// if inlining *doesn't* happen the first byte of the functions will differ.
+
+pub fn foo() -> u32 {
+    bar::bar()
+}
+
+mod bar {
+    pub fn bar() -> u32 {
+        3
+    }
+}
+
+fn main() {
+    println!("{} {}", foo(), bar::bar());
+
+    unsafe {
+        let foo = foo as usize as *const u8;
+        let bar = bar::bar as usize as *const u8;
+
+        assert_eq!(*foo, *bar);
+    }
+}
diff --git a/src/test/ui/lto/thin-lto-inlines2.rs b/src/test/ui/lto/thin-lto-inlines2.rs
new file mode 100644 (file)
index 0000000..1eb2965
--- /dev/null
@@ -0,0 +1,28 @@
+// run-pass
+
+// compile-flags: -C codegen-units=8 -O -C lto=thin
+// aux-build:thin-lto-inlines-aux.rs
+// no-prefer-dynamic
+// ignore-emscripten can't inspect instructions on emscripten
+
+// We want to assert here that ThinLTO will inline across codegen units. There's
+// not really a great way to do that in general so we sort of hack around it by
+// praying two functions go into separate codegen units and then assuming that
+// if inlining *doesn't* happen the first byte of the functions will differ.
+
+extern crate thin_lto_inlines_aux as bar;
+
+pub fn foo() -> u32 {
+    bar::bar()
+}
+
+fn main() {
+    println!("{} {}", foo(), bar::bar());
+
+    unsafe {
+        let foo = foo as usize as *const u8;
+        let bar = bar::bar as usize as *const u8;
+
+        assert_eq!(*foo, *bar);
+    }
+}
diff --git a/src/test/ui/lto/weak-works.rs b/src/test/ui/lto/weak-works.rs
new file mode 100644 (file)
index 0000000..163a387
--- /dev/null
@@ -0,0 +1,28 @@
+// run-pass
+
+// compile-flags: -C codegen-units=8 -Z thinlto
+// ignore-windows
+
+#![feature(linkage)]
+
+pub mod foo {
+    #[linkage = "weak"]
+    #[no_mangle]
+    pub extern "C" fn FOO() -> i32 {
+        0
+    }
+}
+
+mod bar {
+    extern "C" {
+        fn FOO() -> i32;
+    }
+
+    pub fn bar() -> i32 {
+        unsafe { FOO() }
+    }
+}
+
+fn main() {
+    bar::bar();
+}
diff --git a/src/test/ui/lub-glb-with-unbound-infer-var.rs b/src/test/ui/lub-glb-with-unbound-infer-var.rs
deleted file mode 100644 (file)
index c9e1170..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// run-pass
-// Test for a specific corner case: when we compute the LUB of two fn
-// types and their parameters have unbound variables. In that case, we
-// wind up relating those two variables. This was causing an ICE in an
-// in-progress PR.
-
-fn main() {
-    let a_f: fn(_) = |_| ();
-    let b_f: fn(_) = |_| ();
-    let c_f = match 22 {
-        0 => a_f,
-        _ => b_f,
-    };
-    c_f(4);
-}
index d9a0a9f005432be49f75f161b5e94b6f125eb3eb..330aa6acf3550295a56b83e341b7fe861fc1bee0 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `m` is ambiguous (`macro_rules` vs non-`macro_rules` from other module)
+error[E0659]: `m` is ambiguous
   --> $DIR/ambiguity-legacy-vs-modern.rs:31:9
    |
 LL |         m!()
    |         ^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a `macro_rules` name and a non-`macro_rules` name from another module
 note: `m` could refer to the macro defined here
   --> $DIR/ambiguity-legacy-vs-modern.rs:26:5
    |
@@ -15,12 +16,13 @@ note: `m` could also refer to the macro defined here
 LL |         macro m() { 0 }
    |         ^^^^^^^^^^^^^^^
 
-error[E0659]: `m` is ambiguous (`macro_rules` vs non-`macro_rules` from other module)
+error[E0659]: `m` is ambiguous
   --> $DIR/ambiguity-legacy-vs-modern.rs:43:5
    |
 LL |     m!()
    |     ^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a `macro_rules` name and a non-`macro_rules` name from another module
 note: `m` could refer to the macro defined here
   --> $DIR/ambiguity-legacy-vs-modern.rs:40:9
    |
diff --git a/src/test/ui/macros/auxiliary/issue-19163.rs b/src/test/ui/macros/auxiliary/issue-19163.rs
new file mode 100644 (file)
index 0000000..0c0d9e4
--- /dev/null
@@ -0,0 +1,6 @@
+#![crate_type = "lib"]
+
+#[macro_export]
+macro_rules! mywrite {
+    ($dst:expr, $($arg:tt)*) => ($dst.write_fmt(format_args!($($arg)*)))
+}
diff --git a/src/test/ui/macros/issue-16098.rs b/src/test/ui/macros/issue-16098.rs
new file mode 100644 (file)
index 0000000..00acc20
--- /dev/null
@@ -0,0 +1,16 @@
+macro_rules! prob1 {
+    (0) => {
+        0
+    };
+    ($n:expr) => {
+        if ($n % 3 == 0) || ($n % 5 == 0) {
+            $n + prob1!($n - 1); //~ ERROR recursion limit reached while expanding `prob1!`
+        } else {
+            prob1!($n - 1);
+        }
+    };
+}
+
+fn main() {
+    println!("Problem 1: {}", prob1!(1000));
+}
diff --git a/src/test/ui/macros/issue-16098.stderr b/src/test/ui/macros/issue-16098.stderr
new file mode 100644 (file)
index 0000000..6428021
--- /dev/null
@@ -0,0 +1,14 @@
+error: recursion limit reached while expanding `prob1!`
+  --> $DIR/issue-16098.rs:7:18
+   |
+LL |             $n + prob1!($n - 1);
+   |                  ^^^^^^^^^^^^^^
+...
+LL |     println!("Problem 1: {}", prob1!(1000));
+   |                               ------------ in this macro invocation
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_16098`)
+   = note: this error originates in the macro `prob1` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/issue-19163.rs b/src/test/ui/macros/issue-19163.rs
new file mode 100644 (file)
index 0000000..d98c591
--- /dev/null
@@ -0,0 +1,11 @@
+// aux-build:issue-19163.rs
+
+#[macro_use] extern crate issue_19163;
+
+use std::io::Write;
+
+fn main() {
+    let mut v = vec![];
+    mywrite!(&v, "Hello world");
+    //~^ ERROR cannot borrow data in a `&` reference as mutable
+}
diff --git a/src/test/ui/macros/issue-19163.stderr b/src/test/ui/macros/issue-19163.stderr
new file mode 100644 (file)
index 0000000..ae1ae14
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/issue-19163.rs:9:5
+   |
+LL |     mywrite!(&v, "Hello world");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = note: this error originates in the macro `mywrite` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/macros/issue-21356.rs b/src/test/ui/macros/issue-21356.rs
new file mode 100644 (file)
index 0000000..ae62392
--- /dev/null
@@ -0,0 +1,6 @@
+#![allow(unused_macros)]
+
+macro_rules! test { ($wrong:t_ty ..) => () }
+                  //~^ ERROR: invalid fragment specifier `t_ty`
+
+fn main() {}
diff --git a/src/test/ui/macros/issue-21356.stderr b/src/test/ui/macros/issue-21356.stderr
new file mode 100644 (file)
index 0000000..17014c6
--- /dev/null
@@ -0,0 +1,10 @@
+error: invalid fragment specifier `t_ty`
+  --> $DIR/issue-21356.rs:3:22
+   |
+LL | macro_rules! test { ($wrong:t_ty ..) => () }
+   |                      ^^^^^^^^^^^
+   |
+   = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/issue-22463.rs b/src/test/ui/macros/issue-22463.rs
new file mode 100644 (file)
index 0000000..fdf5a2f
--- /dev/null
@@ -0,0 +1,20 @@
+// run-pass
+macro_rules! items {
+    () => {
+        type A = ();
+        fn a() {}
+    }
+}
+
+trait Foo {
+    type A;
+    fn a();
+}
+
+impl Foo for () {
+    items!();
+}
+
+fn main() {
+
+}
diff --git a/src/test/ui/macros/issue-29084.rs b/src/test/ui/macros/issue-29084.rs
new file mode 100644 (file)
index 0000000..d162526
--- /dev/null
@@ -0,0 +1,13 @@
+macro_rules! foo {
+    ($d:expr) => {{
+        fn bar(d: u8) { }
+        bar(&mut $d);
+        //~^ ERROR mismatched types
+        //~| expected `u8`, found `&mut u8`
+    }}
+}
+
+fn main() {
+    foo!(0u8);
+    //~^ in this expansion of foo!
+}
diff --git a/src/test/ui/macros/issue-29084.stderr b/src/test/ui/macros/issue-29084.stderr
new file mode 100644 (file)
index 0000000..a973e23
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-29084.rs:4:13
+   |
+LL |         bar(&mut $d);
+   |             ^^^^^^^ expected `u8`, found `&mut u8`
+...
+LL |     foo!(0u8);
+   |     --------- in this macro invocation
+   |
+   = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/macros/issue-34171.rs b/src/test/ui/macros/issue-34171.rs
new file mode 100644 (file)
index 0000000..157c58c
--- /dev/null
@@ -0,0 +1,10 @@
+// check-pass
+
+macro_rules! null { ($i:tt) => {} }
+macro_rules! apply_null {
+    ($i:item) => { null! { $i } }
+}
+
+fn main() {
+    apply_null!(#[cfg(all())] fn f() {});
+}
diff --git a/src/test/ui/macros/issue-37175.rs b/src/test/ui/macros/issue-37175.rs
new file mode 100644 (file)
index 0000000..9ec9d48
--- /dev/null
@@ -0,0 +1,5 @@
+// run-pass
+macro_rules! m { (<$t:ty>) => { stringify!($t) } }
+fn main() {
+    println!("{}", m!(<Vec<i32>>));
+}
diff --git a/src/test/ui/macros/issue-39388.rs b/src/test/ui/macros/issue-39388.rs
new file mode 100644 (file)
index 0000000..a8e31a6
--- /dev/null
@@ -0,0 +1,9 @@
+#![allow(unused_macros)]
+
+macro_rules! assign {
+    (($($a:tt)*) = ($($b:tt))*) => { //~ ERROR expected one of: `*`, `+`, or `?`
+        $($a)* = $($b)*
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/macros/issue-39388.stderr b/src/test/ui/macros/issue-39388.stderr
new file mode 100644 (file)
index 0000000..62e7dff
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected one of: `*`, `+`, or `?`
+  --> $DIR/issue-39388.rs:4:22
+   |
+LL |     (($($a:tt)*) = ($($b:tt))*) => {
+   |                      ^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/issue-40770.rs b/src/test/ui/macros/issue-40770.rs
new file mode 100644 (file)
index 0000000..c9713c1
--- /dev/null
@@ -0,0 +1,11 @@
+// run-pass
+#![allow(unused_macros)]
+macro_rules! m {
+    ($e:expr) => {
+        macro_rules! n { () => { $e } }
+    }
+}
+
+fn main() {
+    m!(foo!());
+}
diff --git a/src/test/ui/macros/issue-57597.rs b/src/test/ui/macros/issue-57597.rs
new file mode 100644 (file)
index 0000000..ebeb3fe
--- /dev/null
@@ -0,0 +1,80 @@
+// Regression test for #57597.
+//
+// Make sure that nested matchers work correctly rather than causing an infinite loop or crash.
+
+// edition:2018
+
+macro_rules! foo1 {
+    ($($($i:ident)?)+) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo2 {
+    ($($($i:ident)?)*) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo3 {
+    ($($($i:ident)?)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo4 {
+    ($($($($i:ident)?)?)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo5 {
+    ($($($($i:ident)*)?)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo6 {
+    ($($($($i:ident)?)*)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo7 {
+    ($($($($i:ident)?)?)*) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo8 {
+    ($($($($i:ident)*)*)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo9 {
+    ($($($($i:ident)?)*)*) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo10 {
+    ($($($($i:ident)?)*)+) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo11 {
+    ($($($($i:ident)+)?)*) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo12 {
+    ($($($($i:ident)+)*)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+fn main() {
+    foo1!();
+    foo2!();
+    foo3!();
+    foo4!();
+    foo5!();
+    foo6!();
+    foo7!();
+    foo8!();
+    foo9!();
+    foo10!();
+    foo11!();
+    foo12!();
+}
diff --git a/src/test/ui/macros/issue-57597.stderr b/src/test/ui/macros/issue-57597.stderr
new file mode 100644 (file)
index 0000000..0a02ac8
--- /dev/null
@@ -0,0 +1,74 @@
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:8:7
+   |
+LL |     ($($($i:ident)?)+) => {};
+   |       ^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:13:7
+   |
+LL |     ($($($i:ident)?)*) => {};
+   |       ^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:18:7
+   |
+LL |     ($($($i:ident)?)?) => {};
+   |       ^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:23:7
+   |
+LL |     ($($($($i:ident)?)?)?) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:28:7
+   |
+LL |     ($($($($i:ident)*)?)?) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:33:7
+   |
+LL |     ($($($($i:ident)?)*)?) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:38:7
+   |
+LL |     ($($($($i:ident)?)?)*) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:43:7
+   |
+LL |     ($($($($i:ident)*)*)?) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:48:7
+   |
+LL |     ($($($($i:ident)?)*)*) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:53:7
+   |
+LL |     ($($($($i:ident)?)*)+) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:58:7
+   |
+LL |     ($($($($i:ident)+)?)*) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:63:7
+   |
+LL |     ($($($($i:ident)+)*)?) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
+
diff --git a/src/test/ui/macros/issue-6596-1.rs b/src/test/ui/macros/issue-6596-1.rs
new file mode 100644 (file)
index 0000000..25f1d65
--- /dev/null
@@ -0,0 +1,10 @@
+macro_rules! e {
+    ($inp:ident) => (
+        $nonexistent
+        //~^ ERROR expected expression, found `$`
+    );
+}
+
+fn main() {
+    e!(foo);
+}
diff --git a/src/test/ui/macros/issue-6596-1.stderr b/src/test/ui/macros/issue-6596-1.stderr
new file mode 100644 (file)
index 0000000..7ab3685
--- /dev/null
@@ -0,0 +1,13 @@
+error: expected expression, found `$`
+  --> $DIR/issue-6596-1.rs:3:9
+   |
+LL |         $nonexistent
+   |         ^^^^^^^^^^^^ expected expression
+...
+LL |     e!(foo);
+   |     ------- in this macro invocation
+   |
+   = note: this error originates in the macro `e` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/issue-86865.rs b/src/test/ui/macros/issue-86865.rs
new file mode 100644 (file)
index 0000000..01e0a20
--- /dev/null
@@ -0,0 +1,11 @@
+use std::fmt::Write;
+
+fn main() {
+    println!(b"foo");
+    //~^ ERROR format argument must be a string literal
+    //~| HELP consider removing the leading `b`
+    let mut s = String::new();
+    write!(s, b"foo{}", "bar");
+    //~^ ERROR format argument must be a string literal
+    //~| HELP consider removing the leading `b`
+}
diff --git a/src/test/ui/macros/issue-86865.stderr b/src/test/ui/macros/issue-86865.stderr
new file mode 100644 (file)
index 0000000..eed7553
--- /dev/null
@@ -0,0 +1,18 @@
+error: format argument must be a string literal
+  --> $DIR/issue-86865.rs:4:14
+   |
+LL |     println!(b"foo");
+   |              -^^^^^
+   |              |
+   |              help: consider removing the leading `b`
+
+error: format argument must be a string literal
+  --> $DIR/issue-86865.rs:8:15
+   |
+LL |     write!(s, b"foo{}", "bar");
+   |               -^^^^^^^
+   |               |
+   |               help: consider removing the leading `b`
+
+error: aborting due to 2 previous errors
+
index 7bbb8eddb7137317917e78845071ad06c6e0e9ba..4a864c2e92718f08d89d93b0ca943ebdb14b8bdb 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `std` is ambiguous (glob import vs any other name from outer scope during import/macro resolution)
+error[E0659]: `std` is ambiguous
   --> $DIR/macro-path-prelude-shadowing.rs:29:9
    |
 LL |         std::panic!();
    |         ^^^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution
    = note: `std` could refer to a built-in crate
 note: `std` could also refer to the module imported here
   --> $DIR/macro-path-prelude-shadowing.rs:27:9
index 58224b70734dac193642ad01c833409bf1e74bd6..a052b43ac10e408ca40ab019064aa744642a61e1 100644 (file)
@@ -10,12 +10,13 @@ LL | m1!();
    = note: macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)
    = note: this error originates in the macro `m1` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0659]: `foo` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `foo` is ambiguous
   --> $DIR/macro-shadowing.rs:17:1
    |
 LL | foo!();
    | ^^^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
 note: `foo` could refer to the macro defined here
   --> $DIR/macro-shadowing.rs:10:5
    |
index 6b1191670743382fe3725361d42b29fb5c75ae8c..dedefac5c464c9a842d1454b5f9d60dfe2be3f42 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `bar` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `bar` is ambiguous
   --> $DIR/out-of-order-shadowing.rs:5:1
    |
 LL | bar!();
    | ^^^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
 note: `bar` could refer to the macro defined here
   --> $DIR/out-of-order-shadowing.rs:4:1
    |
index 4912166883260164dd2d54705f4bb6d003b802f1..99b27a5cab123088cdd80a6c4f1ead1bb3d02da0 100644 (file)
@@ -1,4 +1,4 @@
-error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `m` is ambiguous
   --> $DIR/restricted-shadowing-legacy.rs:101:13
    |
 LL |             m!();
@@ -7,6 +7,7 @@ LL |             m!();
 LL | include!();
    | ---------- in this macro invocation
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-legacy.rs:88:9
    |
@@ -25,7 +26,7 @@ LL | include!();
    | ---------- in this macro invocation
    = note: this error originates in the macro `gen_gen_inner_invoc` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `m` is ambiguous
   --> $DIR/restricted-shadowing-legacy.rs:139:42
    |
 LL |         macro_rules! gen_invoc { () => { m!() } }
@@ -34,6 +35,7 @@ LL |         macro_rules! gen_invoc { () => { m!() } }
 LL | include!();
    | ---------- in this macro invocation
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-legacy.rs:88:9
    |
@@ -52,7 +54,7 @@ LL | include!();
    | ---------- in this macro invocation
    = note: this error originates in the macro `gen_invoc` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `m` is ambiguous
   --> $DIR/restricted-shadowing-legacy.rs:148:9
    |
 LL |         m!();
@@ -61,6 +63,7 @@ LL |         m!();
 LL | include!();
    | ---------- in this macro invocation
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-legacy.rs:88:9
    |
@@ -79,7 +82,7 @@ LL | include!();
    | ---------- in this macro invocation
    = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `m` is ambiguous
   --> $DIR/restricted-shadowing-legacy.rs:164:9
    |
 LL |         m!();
@@ -88,6 +91,7 @@ LL |         m!();
 LL | include!();
    | ---------- in this macro invocation
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-legacy.rs:88:9
    |
@@ -106,7 +110,7 @@ LL | include!();
    | ---------- in this macro invocation
    = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `m` is ambiguous
   --> $DIR/restricted-shadowing-legacy.rs:180:13
    |
 LL |             m!();
@@ -115,6 +119,7 @@ LL |             m!();
 LL | include!();
    | ---------- in this macro invocation
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-legacy.rs:88:9
    |
@@ -133,7 +138,7 @@ LL | include!();
    | ---------- in this macro invocation
    = note: this error originates in the macro `gen_gen_inner_invoc` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `m` is ambiguous
   --> $DIR/restricted-shadowing-legacy.rs:218:42
    |
 LL |         macro_rules! gen_invoc { () => { m!() } }
@@ -142,6 +147,7 @@ LL |         macro_rules! gen_invoc { () => { m!() } }
 LL | include!();
    | ---------- in this macro invocation
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-legacy.rs:88:9
    |
@@ -160,7 +166,7 @@ LL | include!();
    | ---------- in this macro invocation
    = note: this error originates in the macro `gen_invoc` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `m` is ambiguous
   --> $DIR/restricted-shadowing-legacy.rs:232:9
    |
 LL |         m!();
@@ -169,6 +175,7 @@ LL |         m!();
 LL | include!();
    | ---------- in this macro invocation
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-legacy.rs:88:9
    |
@@ -187,7 +194,7 @@ LL | include!();
    | ---------- in this macro invocation
    = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `m` is ambiguous
   --> $DIR/restricted-shadowing-legacy.rs:262:42
    |
 LL |         macro_rules! gen_invoc { () => { m!() } }
@@ -196,6 +203,7 @@ LL |         macro_rules! gen_invoc { () => { m!() } }
 LL | include!();
    | ---------- in this macro invocation
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-legacy.rs:88:9
    |
index 62639eeb1192a9a256babd3f71241d3551ae1c5e..b169e63132e450eafef64bc0ba7e3c60c69a7909 100644 (file)
@@ -1,4 +1,4 @@
-error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `m` is ambiguous
   --> $DIR/restricted-shadowing-modern.rs:104:17
    |
 LL |                 m!();
@@ -7,6 +7,7 @@ LL |                 m!();
 LL | include!();
    | ---------- in this macro invocation
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-modern.rs:91:9
    |
@@ -25,7 +26,7 @@ LL | include!();
    | ---------- in this macro invocation
    = note: this error originates in the macro `gen_gen_inner_invoc` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `m` is ambiguous
   --> $DIR/restricted-shadowing-modern.rs:147:33
    |
 LL |             macro gen_invoc() { m!() }
@@ -34,6 +35,7 @@ LL |             macro gen_invoc() { m!() }
 LL | include!();
    | ---------- in this macro invocation
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-modern.rs:91:9
    |
@@ -52,7 +54,7 @@ LL | include!();
    | ---------- in this macro invocation
    = note: this error originates in the macro `gen_invoc` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `m` is ambiguous
   --> $DIR/restricted-shadowing-modern.rs:156:13
    |
 LL |             m!();
@@ -61,6 +63,7 @@ LL |             m!();
 LL | include!();
    | ---------- in this macro invocation
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-modern.rs:91:9
    |
@@ -79,7 +82,7 @@ LL | include!();
    | ---------- in this macro invocation
    = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `m` is ambiguous
   --> $DIR/restricted-shadowing-modern.rs:172:13
    |
 LL |             m!();
@@ -88,6 +91,7 @@ LL |             m!();
 LL | include!();
    | ---------- in this macro invocation
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-modern.rs:91:9
    |
@@ -106,7 +110,7 @@ LL | include!();
    | ---------- in this macro invocation
    = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `m` is ambiguous
   --> $DIR/restricted-shadowing-modern.rs:190:17
    |
 LL |                 m!();
@@ -115,6 +119,7 @@ LL |                 m!();
 LL | include!();
    | ---------- in this macro invocation
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-modern.rs:91:9
    |
@@ -133,7 +138,7 @@ LL | include!();
    | ---------- in this macro invocation
    = note: this error originates in the macro `gen_gen_inner_invoc` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `m` is ambiguous
   --> $DIR/restricted-shadowing-modern.rs:233:33
    |
 LL |             macro gen_invoc() { m!() }
@@ -142,6 +147,7 @@ LL |             macro gen_invoc() { m!() }
 LL | include!();
    | ---------- in this macro invocation
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-modern.rs:91:9
    |
diff --git a/src/test/ui/macros/trace_macros-format.rs b/src/test/ui/macros/trace_macros-format.rs
new file mode 100644 (file)
index 0000000..afca45c
--- /dev/null
@@ -0,0 +1,18 @@
+#![feature(trace_macros)]
+
+fn main() {
+    trace_macros!(); //~ ERROR trace_macros! accepts only `true` or `false`
+    trace_macros!(1); //~ ERROR trace_macros! accepts only `true` or `false`
+    trace_macros!(ident); //~ ERROR trace_macros! accepts only `true` or `false`
+    trace_macros!(for); //~ ERROR trace_macros! accepts only `true` or `false`
+    trace_macros!(true,); //~ ERROR trace_macros! accepts only `true` or `false`
+    trace_macros!(false 1); //~ ERROR trace_macros! accepts only `true` or `false`
+
+
+    // should be fine:
+    macro_rules! expando {
+        ($x: ident) => { trace_macros!($x) }
+    }
+
+    expando!(true);
+}
diff --git a/src/test/ui/macros/trace_macros-format.stderr b/src/test/ui/macros/trace_macros-format.stderr
new file mode 100644 (file)
index 0000000..c320270
--- /dev/null
@@ -0,0 +1,38 @@
+error: trace_macros! accepts only `true` or `false`
+  --> $DIR/trace_macros-format.rs:4:5
+   |
+LL |     trace_macros!();
+   |     ^^^^^^^^^^^^^^^
+
+error: trace_macros! accepts only `true` or `false`
+  --> $DIR/trace_macros-format.rs:5:5
+   |
+LL |     trace_macros!(1);
+   |     ^^^^^^^^^^^^^^^^
+
+error: trace_macros! accepts only `true` or `false`
+  --> $DIR/trace_macros-format.rs:6:5
+   |
+LL |     trace_macros!(ident);
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: trace_macros! accepts only `true` or `false`
+  --> $DIR/trace_macros-format.rs:7:5
+   |
+LL |     trace_macros!(for);
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: trace_macros! accepts only `true` or `false`
+  --> $DIR/trace_macros-format.rs:8:5
+   |
+LL |     trace_macros!(true,);
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: trace_macros! accepts only `true` or `false`
+  --> $DIR/trace_macros-format.rs:9:5
+   |
+LL |     trace_macros!(false 1);
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.rs b/src/test/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.rs
new file mode 100644 (file)
index 0000000..1e41312
--- /dev/null
@@ -0,0 +1,20 @@
+// run-pass
+
+#![feature(marker_trait_attr)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+#[marker]
+trait MyMarker {}
+
+impl<T> MyMarker for T {}
+impl<T> MyMarker for Vec<T> {}
+
+fn foo<T: MyMarker>(t: T) -> T {
+    t
+}
+
+fn main() {
+    assert_eq!(1, foo(1));
+    assert_eq!(2.0, foo(2.0));
+    assert_eq!(vec![1], foo(vec![1]));
+}
diff --git a/src/test/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.stderr b/src/test/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.stderr
new file mode 100644 (file)
index 0000000..fca9866
--- /dev/null
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/overlap-doesnt-conflict-with-specialization.rs:4:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/marker_trait_attr/overlap-permitted-for-annotated-marker-traits.rs b/src/test/ui/marker_trait_attr/overlap-permitted-for-annotated-marker-traits.rs
new file mode 100644 (file)
index 0000000..3833139
--- /dev/null
@@ -0,0 +1,26 @@
+// run-pass
+// Tests for RFC 1268: we allow overlapping impls of marker traits,
+// that is, traits with #[marker]. In this case, a type `T` is
+// `MyMarker` if it is either `Debug` or `Display`.
+
+#![feature(marker_trait_attr)]
+
+use std::fmt::{Debug, Display};
+
+#[marker] trait MyMarker {}
+
+impl<T: Debug> MyMarker for T {}
+impl<T: Display> MyMarker for T {}
+
+fn foo<T: MyMarker>(t: T) -> T {
+    t
+}
+
+fn main() {
+    // Debug && Display:
+    assert_eq!(1, foo(1));
+    assert_eq!(2.0, foo(2.0));
+
+    // Debug && !Display:
+    assert_eq!(vec![1], foo(vec![1]));
+}
diff --git a/src/test/ui/match/issue-11940.rs b/src/test/ui/match/issue-11940.rs
new file mode 100644 (file)
index 0000000..6815c87
--- /dev/null
@@ -0,0 +1,11 @@
+// run-pass
+
+const TEST_STR: &'static str = "abcd";
+
+fn main() {
+    let s = "abcd";
+    match s {
+        TEST_STR => (),
+        _ => unreachable!()
+    }
+}
diff --git a/src/test/ui/match/issue-18060.rs b/src/test/ui/match/issue-18060.rs
new file mode 100644 (file)
index 0000000..b5f3d0f
--- /dev/null
@@ -0,0 +1,8 @@
+// run-pass
+// Regression test for #18060: match arms were matching in the wrong order.
+
+fn main() {
+    assert_eq!(2, match (1, 3) { (0, 2..=5) => 1, (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 });
+    assert_eq!(2, match (1, 3) {                  (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 });
+    assert_eq!(2, match (1, 7) { (0, 2..=5) => 1, (1, 7) => 2, (_, 2..=5) => 3, (_, _) => 4 });
+}
diff --git a/src/test/ui/match/issue-26251.rs b/src/test/ui/match/issue-26251.rs
new file mode 100644 (file)
index 0000000..a3e26a4
--- /dev/null
@@ -0,0 +1,15 @@
+// run-pass
+#![allow(overlapping_range_endpoints)]
+
+fn main() {
+    let x = 'a';
+
+    let y = match x {
+        'a'..='b' if false => "one",
+        'a' => "two",
+        'a'..='b' => "three",
+        _ => panic!("what?"),
+    };
+
+    assert_eq!(y, "two");
+}
diff --git a/src/test/ui/match/issue-26996.rs b/src/test/ui/match/issue-26996.rs
new file mode 100644 (file)
index 0000000..84037b7
--- /dev/null
@@ -0,0 +1,24 @@
+// run-pass
+
+// This test is bogus (i.e., should be check-fail) during the period
+// where #54986 is implemented and #54987 is *not* implemented. For
+// now: just ignore it
+//
+// ignore-test
+
+// This test is checking that the write to `c.0` (which has been moved out of)
+// won't overwrite the state in `c2`.
+//
+// That's a fine thing to test when this code is accepted by the
+// compiler, and this code is being transcribed accordingly into
+// the ui test issue-21232-partial-init-and-use.rs
+
+fn main() {
+    let mut c = (1, "".to_owned());
+    match c {
+        c2 => {
+            c.0 = 2;
+            assert_eq!(c2.0, 1);
+        }
+    }
+}
diff --git a/src/test/ui/match/issue-42679.rs b/src/test/ui/match/issue-42679.rs
new file mode 100644 (file)
index 0000000..596309f
--- /dev/null
@@ -0,0 +1,22 @@
+// run-pass
+#![feature(box_syntax)]
+#![feature(box_patterns)]
+
+#[derive(Debug, PartialEq)]
+enum Test {
+    Foo(usize),
+    Bar(isize),
+}
+
+fn main() {
+    let a = box Test::Foo(10);
+    let b = box Test::Bar(-20);
+    match (a, b) {
+        (_, box Test::Foo(_)) => unreachable!(),
+        (box Test::Foo(x), b) => {
+            assert_eq!(x, 10);
+            assert_eq!(b, box Test::Bar(-20));
+        },
+        _ => unreachable!(),
+    }
+}
index f5497c1d16de61257a39b1df56029f20477a283d..9143a8cdd59bc915e1daff145d699adcb6fa5cd6 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 // edition:2021
-// compile-flags: -Zunstable-options
 
 // regression test for https://github.com/rust-lang/rust/pull/85678
 
diff --git a/src/test/ui/mir-dataflow/indirect-mutation-offset.rs b/src/test/ui/mir-dataflow/indirect-mutation-offset.rs
deleted file mode 100644 (file)
index 374a9f7..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-// compile-flags: -Zunleash-the-miri-inside-of-you
-
-// This test demonstrates a shortcoming of the `MaybeMutBorrowedLocals` analysis. It does not
-// handle code that takes a reference to one field of a struct, then use pointer arithmetic to
-// transform it to another field of that same struct that may have interior mutability. For now,
-// this is UB, but this may change in the future. See [rust-lang/unsafe-code-guidelines#134].
-//
-// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134
-
-#![feature(core_intrinsics, rustc_attrs, const_raw_ptr_deref)]
-
-use std::cell::UnsafeCell;
-use std::intrinsics::rustc_peek;
-
-#[repr(C)]
-struct PartialInteriorMut {
-    zst: [i32; 0],
-    cell: UnsafeCell<i32>,
-}
-
-#[rustc_mir(rustc_peek_indirectly_mutable,stop_after_dataflow)]
-const BOO: i32 = {
-    let x = PartialInteriorMut {
-        zst: [],
-        cell: UnsafeCell::new(0),
-    };
-
-    let p_zst: *const _ = &x.zst ; // Doesn't cause `x` to get marked as indirectly mutable.
-
-    let rmut_cell = unsafe {
-        // Take advantage of the fact that `zst` and `cell` are at the same location in memory.
-        // This trick would work with any size type if miri implemented `ptr::offset`.
-        let p_cell = p_zst as *const UnsafeCell<i32>;
-
-        let pmut_cell = (*p_cell).get();
-        &mut *pmut_cell
-    };
-
-    *rmut_cell = 42;  // Mutates `x` indirectly even though `x` is not marked indirectly mutable!!!
-    let val = *rmut_cell;
-    rustc_peek(x); //~ ERROR rustc_peek: bit not set
-
-    val
-};
-
-fn main() {
-    println!("{}", BOO);
-}
diff --git a/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr b/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr
deleted file mode 100644 (file)
index 1d5287c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-error: rustc_peek: bit not set
-  --> $DIR/indirect-mutation-offset.rs:41:5
-   |
-LL |     rustc_peek(x);
-   |     ^^^^^^^^^^^^^
-
-error: stop_after_dataflow ended compilation
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/mir/issue-74739.rs b/src/test/ui/mir/issue-74739.rs
new file mode 100644 (file)
index 0000000..0362235
--- /dev/null
@@ -0,0 +1,14 @@
+// compile-flags: -O
+// run-pass
+
+struct Foo {
+    x: i32,
+}
+
+pub fn main() {
+    let mut foo = Foo { x: 42 };
+    let x = &mut foo.x;
+    *x = 13;
+    let y = foo;
+    assert_eq!(y.x, 13); // used to print 42 due to mir-opt bug
+}
diff --git a/src/test/ui/mut-vstore-expr.rs b/src/test/ui/mut-vstore-expr.rs
deleted file mode 100644 (file)
index 75b309a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// run-pass
-// pretty-expanded FIXME #23616
-
-pub fn main() {
-    let _x: &mut [isize] = &mut [ 1, 2, 3 ];
-}
index 8ec478cd63fa1264db5eb40e35920258f4ea846e..9e1f4e1fe4ea9b12496a64fc6193d2769bf10e55 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: `NoSync` cannot be shared between threads safely
-  --> $DIR/mutable-enum-indirect.rs:17:5
+  --> $DIR/mutable-enum-indirect.rs:17:9
    |
 LL |     bar(&x);
-   |     ^^^ `NoSync` cannot be shared between threads safely
+   |     --- ^^ `NoSync` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: within `&Foo`, the trait `Sync` is not implemented for `NoSync`
 note: required because it appears within the type `Foo`
diff --git a/src/test/ui/negative.rs b/src/test/ui/negative.rs
deleted file mode 100644 (file)
index 9601e91..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-pass
-
-pub fn main() {
-    match -5 {
-      -5 => {}
-      _ => { panic!() }
-    }
-}
diff --git a/src/test/ui/nested_item_main.rs b/src/test/ui/nested_item_main.rs
deleted file mode 100644 (file)
index 2fe00ae..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// run-pass
-// aux-build:nested_item.rs
-
-
-extern crate nested_item;
-
-pub fn main() {
-    assert_eq!(2, nested_item::foo::<()>());
-    assert_eq!(2, nested_item::foo::<isize>());
-}
diff --git a/src/test/ui/never_type/diverging-tuple-parts-39485.rs b/src/test/ui/never_type/diverging-tuple-parts-39485.rs
new file mode 100644 (file)
index 0000000..0cde611
--- /dev/null
@@ -0,0 +1,15 @@
+// After #39485, this test used to pass, but that change was reverted
+// due to numerous inference failures like #39808, so it now fails
+// again. #39485 made it so that diverging types never propagate
+// upward; but we now do propagate such types upward in many more
+// cases.
+
+fn g() {
+    &panic!() //~ ERROR mismatched types
+}
+
+fn f() -> isize {
+    (return 1, return 2) //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/never_type/diverging-tuple-parts-39485.stderr b/src/test/ui/never_type/diverging-tuple-parts-39485.stderr
new file mode 100644 (file)
index 0000000..32967b3
--- /dev/null
@@ -0,0 +1,32 @@
+error[E0308]: mismatched types
+  --> $DIR/diverging-tuple-parts-39485.rs:8:5
+   |
+LL |     &panic!()
+   |     ^^^^^^^^^ expected `()`, found reference
+   |
+   = note: expected unit type `()`
+              found reference `&_`
+help: try adding a return type
+   |
+LL | fn g() -> &_ {
+   |        +++++
+help: consider removing the borrow
+   |
+LL -     &panic!()
+LL +     panic!()
+   | 
+
+error[E0308]: mismatched types
+  --> $DIR/diverging-tuple-parts-39485.rs:12:5
+   |
+LL | fn f() -> isize {
+   |           ----- expected `isize` because of return type
+LL |     (return 1, return 2)
+   |     ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found tuple
+   |
+   = note: expected type `isize`
+             found tuple `(!, !)`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/new-box.rs b/src/test/ui/new-box.rs
deleted file mode 100644 (file)
index 96a3b19..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// run-pass
-
-fn f(x: Box<isize>) {
-    let y: &isize = &*x;
-    println!("{}", *x);
-    println!("{}", *y);
-}
-
-trait Trait {
-    fn printme(&self);
-}
-
-struct Struct;
-
-impl Trait for Struct {
-    fn printme(&self) {
-        println!("hello world!");
-    }
-}
-
-fn g(x: Box<dyn Trait>) {
-    x.printme();
-    let y: &dyn Trait = &*x;
-    y.printme();
-}
-
-fn main() {
-    f(Box::new(1234));
-    g(Box::new(Struct) as Box<dyn Trait>);
-}
diff --git a/src/test/ui/nil-decl-in-foreign.rs b/src/test/ui/nil-decl-in-foreign.rs
deleted file mode 100644 (file)
index f3be948..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// run-pass
-
-#![allow(improper_ctypes)]
-#![allow(dead_code)]
-// Issue #901
-// pretty-expanded FIXME #23616
-
-mod libc {
-    extern "C" {
-        pub fn printf(x: ());
-    }
-}
-
-pub fn main() {}
index 814f3473828e3bd406ee2af575b7735b31c8dafa..b5a14b551dc2d799b7200c39cbf6408000b45678 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: `NoSend` cannot be sent between threads safely
-  --> $DIR/no_send-enum.rs:16:5
+  --> $DIR/no_send-enum.rs:16:9
    |
 LL |     bar(x);
-   |     ^^^ `NoSend` cannot be sent between threads safely
+   |     --- ^ `NoSend` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: within `Foo`, the trait `Send` is not implemented for `NoSend`
 note: required because it appears within the type `Foo`
index ad837863be9ed428659cb133594e770251508d5a..5b453e0da3bbdff1452cb73cbc7b29cd24bbf3af 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: `NoSync` cannot be shared between threads safely
-  --> $DIR/no_share-enum.rs:14:5
+  --> $DIR/no_share-enum.rs:14:9
    |
 LL |     bar(x);
-   |     ^^^ `NoSync` cannot be shared between threads safely
+   |     --- ^ `NoSync` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: within `Foo`, the trait `Sync` is not implemented for `NoSync`
 note: required because it appears within the type `Foo`
diff --git a/src/test/ui/numbers-arithmetic/unary-minus-suffix-inference.rs b/src/test/ui/numbers-arithmetic/unary-minus-suffix-inference.rs
new file mode 100644 (file)
index 0000000..a4d0a84
--- /dev/null
@@ -0,0 +1,23 @@
+// run-pass
+
+pub fn main() {
+    let a = 1;
+    let a_neg: i8 = -a;
+    println!("{}", a_neg);
+
+    let b = 1;
+    let b_neg: i16 = -b;
+    println!("{}", b_neg);
+
+    let c = 1;
+    let c_neg: i32 = -c;
+    println!("{}", c_neg);
+
+    let d = 1;
+    let d_neg: i64 = -d;
+    println!("{}", d_neg);
+
+    let e = 1;
+    let e_neg: isize = -e;
+    println!("{}", e_neg);
+}
diff --git a/src/test/ui/object-does-not-impl-trait.rs b/src/test/ui/object-does-not-impl-trait.rs
deleted file mode 100644 (file)
index b3b6798..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// Test that an object type `Box<Foo>` is not considered to implement the
-// trait `Foo`. Issue #5087.
-
-trait Foo {}
-fn take_foo<F:Foo>(f: F) {}
-fn take_object(f: Box<dyn Foo>) { take_foo(f); }
-//~^ ERROR `Box<dyn Foo>: Foo` is not satisfied
-fn main() {}
diff --git a/src/test/ui/object-does-not-impl-trait.stderr b/src/test/ui/object-does-not-impl-trait.stderr
deleted file mode 100644 (file)
index f1dd508..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0277]: the trait bound `Box<dyn Foo>: Foo` is not satisfied
-  --> $DIR/object-does-not-impl-trait.rs:6:44
-   |
-LL | fn take_object(f: Box<dyn Foo>) { take_foo(f); }
-   |                                   -------- ^ the trait `Foo` is not implemented for `Box<dyn Foo>`
-   |                                   |
-   |                                   required by a bound introduced by this call
-   |
-note: required by a bound in `take_foo`
-  --> $DIR/object-does-not-impl-trait.rs:5:15
-   |
-LL | fn take_foo<F:Foo>(f: F) {}
-   |               ^^^ required by this bound in `take_foo`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/overlap-doesnt-conflict-with-specialization.rs b/src/test/ui/overlap-doesnt-conflict-with-specialization.rs
deleted file mode 100644 (file)
index 1e41312..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// run-pass
-
-#![feature(marker_trait_attr)]
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
-
-#[marker]
-trait MyMarker {}
-
-impl<T> MyMarker for T {}
-impl<T> MyMarker for Vec<T> {}
-
-fn foo<T: MyMarker>(t: T) -> T {
-    t
-}
-
-fn main() {
-    assert_eq!(1, foo(1));
-    assert_eq!(2.0, foo(2.0));
-    assert_eq!(vec![1], foo(vec![1]));
-}
diff --git a/src/test/ui/overlap-doesnt-conflict-with-specialization.stderr b/src/test/ui/overlap-doesnt-conflict-with-specialization.stderr
deleted file mode 100644 (file)
index fca9866..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/overlap-doesnt-conflict-with-specialization.rs:4:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/overlap-permitted-for-annotated-marker-traits.rs b/src/test/ui/overlap-permitted-for-annotated-marker-traits.rs
deleted file mode 100644 (file)
index 3833139..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// run-pass
-// Tests for RFC 1268: we allow overlapping impls of marker traits,
-// that is, traits with #[marker]. In this case, a type `T` is
-// `MyMarker` if it is either `Debug` or `Display`.
-
-#![feature(marker_trait_attr)]
-
-use std::fmt::{Debug, Display};
-
-#[marker] trait MyMarker {}
-
-impl<T: Debug> MyMarker for T {}
-impl<T: Display> MyMarker for T {}
-
-fn foo<T: MyMarker>(t: T) -> T {
-    t
-}
-
-fn main() {
-    // Debug && Display:
-    assert_eq!(1, foo(1));
-    assert_eq!(2.0, foo(2.0));
-
-    // Debug && !Display:
-    assert_eq!(vec![1], foo(vec![1]));
-}
diff --git a/src/test/ui/packed/issue-46152.rs b/src/test/ui/packed/issue-46152.rs
new file mode 100644 (file)
index 0000000..fb1c9fb
--- /dev/null
@@ -0,0 +1,24 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![feature(unsize, coerce_unsized)]
+
+#[repr(packed)]
+struct UnalignedPtr<'a, T: ?Sized>
+    where T: 'a,
+{
+    data: &'a T,
+}
+
+fn main() {
+
+    impl<'a, T, U> std::ops::CoerceUnsized<UnalignedPtr<'a, U>> for UnalignedPtr<'a, T>
+        where
+        T: std::marker::Unsize<U> + ?Sized,
+        U: ?Sized,
+    { }
+
+    let arr = [1, 2, 3];
+    let arr_unaligned: UnalignedPtr<[i32; 3]> = UnalignedPtr { data: &arr };
+    let arr_unaligned: UnalignedPtr<[i32]> = arr_unaligned;
+}
diff --git a/src/test/ui/parser/auxiliary/issue-89971-outer-attr-following-inner-attr-ice.rs b/src/test/ui/parser/auxiliary/issue-89971-outer-attr-following-inner-attr-ice.rs
new file mode 100644 (file)
index 0000000..e5604b8
--- /dev/null
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(ICE)]
+pub fn derive(_: TokenStream) -> TokenStream {
+    r#"#[allow(missing_docs)] struct X { }"#.parse().unwrap()
+}
diff --git a/src/test/ui/parser/bastion-of-the-turbofish.rs b/src/test/ui/parser/bastion-of-the-turbofish.rs
new file mode 100644 (file)
index 0000000..e128570
--- /dev/null
@@ -0,0 +1,43 @@
+// check-pass
+
+// Bastion of the Turbofish
+// ------------------------
+// Beware travellers, lest you venture into waters callous and unforgiving,
+// where hope must be abandoned, ere it is cruelly torn from you. For here
+// stands the bastion of the Turbofish: an impenetrable fortress holding
+// unshaking against those who would dare suggest the supererogation of the
+// Turbofish.
+//
+// Once I was young and foolish and had the impudence to imagine that I could
+// shake free from the coils by which that creature had us tightly bound. I
+// dared to suggest that there was a better way: a brighter future, in which
+// Rustaceans both new and old could be rid of that vile beast. But alas! In
+// my foolhardiness my ignorance was unveiled and my dreams were dashed
+// unforgivingly against the rock of syntactic ambiguity.
+//
+// This humble program, small and insignificant though it might seem,
+// demonstrates that to which we had previously cast a blind eye: an ambiguity
+// in permitting generic arguments to be provided without the consent of the
+// Great Turbofish. Should you be so naïve as to try to revolt against its
+// mighty clutches, here shall its wrath be indomitably displayed. This
+// program must pass for all eternity: forever watched by the guardian angel
+// which gave this beast its name, and stands fundamentally at odds with the
+// impetuous rebellion against the Turbofish.
+//
+// My heart aches in sorrow, for I know I am defeated. Let this be a warning
+// to all those who come after: for they too must overcome the impassible
+// hurdle of defeating the great beast, championed by a resolute winged
+// guardian.
+//
+// Here stands the Bastion of the Turbofish, a memorial to Anna Harren,
+// Guardian Angel of these Hallowed Grounds. <3
+
+// See https://github.com/rust-lang/rust/pull/53562
+// and https://github.com/rust-lang/rfcs/pull/2527
+// and https://twitter.com/garblefart/status/1393236602856611843
+// for context.
+
+fn main() {
+    let (the, guardian, stands, resolute) = ("the", "Turbofish", "remains", "undefeated");
+    let _: (bool, bool) = (the<guardian, stands>(resolute));
+}
diff --git a/src/test/ui/parser/issue-13483.rs b/src/test/ui/parser/issue-13483.rs
new file mode 100644 (file)
index 0000000..a2fd926
--- /dev/null
@@ -0,0 +1,17 @@
+fn main() {
+    if true {
+    } else if { //~ ERROR missing condition
+    //~^ ERROR mismatched types
+    } else {
+    }
+}
+
+fn foo() {
+    if true {
+    } else if { //~ ERROR missing condition
+    //~^ ERROR mismatched types
+    }
+    bar();
+}
+
+fn bar() {}
diff --git a/src/test/ui/parser/issue-13483.stderr b/src/test/ui/parser/issue-13483.stderr
new file mode 100644 (file)
index 0000000..5fd05b1
--- /dev/null
@@ -0,0 +1,33 @@
+error: missing condition for `if` expression
+  --> $DIR/issue-13483.rs:3:14
+   |
+LL |     } else if {
+   |              ^ expected if condition here
+
+error: missing condition for `if` expression
+  --> $DIR/issue-13483.rs:11:14
+   |
+LL |     } else if {
+   |              ^ expected if condition here
+
+error[E0308]: mismatched types
+  --> $DIR/issue-13483.rs:3:15
+   |
+LL |       } else if {
+   |  _______________^
+LL | |
+LL | |     } else {
+   | |_____^ expected `bool`, found `()`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-13483.rs:11:15
+   |
+LL |       } else if {
+   |  _______________^
+LL | |
+LL | |     }
+   | |_____^ expected `bool`, found `()`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/issue-20616-4.rs b/src/test/ui/parser/issue-20616-4.rs
new file mode 100644 (file)
index 0000000..a71f47c
--- /dev/null
@@ -0,0 +1,35 @@
+// We need all these 9 issue-20616-N.rs files
+// because we can only catch one parsing error at a time
+
+type Type_1_<'a, T> = &'a T;
+
+
+//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
+
+
+//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
+
+
+//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
+
+
+type Type_4<T> = Type_1_<'static,, T>;
+//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
+
+
+type Type_5_<'a> = Type_1_<'a, ()>;
+
+
+//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
+
+
+//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
+
+
+//type Type_7 = Box<(),,>; // error: expected type, found `,`
+
+
+//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
+
+
+//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/parser/issue-20616-4.stderr b/src/test/ui/parser/issue-20616-4.stderr
new file mode 100644 (file)
index 0000000..2b3b75f
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected one of `>`, a const expression, lifetime, or type, found `,`
+  --> $DIR/issue-20616-4.rs:16:34
+   |
+LL | type Type_4<T> = Type_1_<'static,, T>;
+   |                                  ^ expected one of `>`, a const expression, lifetime, or type
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-20616-5.rs b/src/test/ui/parser/issue-20616-5.rs
new file mode 100644 (file)
index 0000000..b96d09d
--- /dev/null
@@ -0,0 +1,35 @@
+// We need all these 9 issue-20616-N.rs files
+// because we can only catch one parsing error at a time
+
+type Type_1_<'a, T> = &'a T;
+
+
+//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
+
+
+//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
+
+
+//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
+
+
+//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
+
+
+type Type_5_<'a> = Type_1_<'a, ()>;
+
+
+type Type_5<'a> = Type_1_<'a, (),,>;
+//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
+
+
+//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
+
+
+//type Type_7 = Box<(),,>; // error: expected type, found `,`
+
+
+//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
+
+
+//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/parser/issue-20616-5.stderr b/src/test/ui/parser/issue-20616-5.stderr
new file mode 100644 (file)
index 0000000..1ec1dbd
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected one of `>`, a const expression, lifetime, or type, found `,`
+  --> $DIR/issue-20616-5.rs:22:34
+   |
+LL | type Type_5<'a> = Type_1_<'a, (),,>;
+   |                                  ^ expected one of `>`, a const expression, lifetime, or type
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-20616-6.rs b/src/test/ui/parser/issue-20616-6.rs
new file mode 100644 (file)
index 0000000..a2c45ec
--- /dev/null
@@ -0,0 +1,35 @@
+// We need all these 9 issue-20616-N.rs files
+// because we can only catch one parsing error at a time
+
+type Type_1_<'a, T> = &'a T;
+
+
+//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
+
+
+//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
+
+
+//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
+
+
+//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
+
+
+type Type_5_<'a> = Type_1_<'a, ()>;
+
+
+//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
+
+
+type Type_6 = Type_5_<'a,,>;
+//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
+
+
+//type Type_7 = Box<(),,>; // error: expected type, found `,`
+
+
+//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
+
+
+//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/parser/issue-20616-6.stderr b/src/test/ui/parser/issue-20616-6.stderr
new file mode 100644 (file)
index 0000000..7401abd
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected one of `>`, a const expression, lifetime, or type, found `,`
+  --> $DIR/issue-20616-6.rs:25:26
+   |
+LL | type Type_6 = Type_5_<'a,,>;
+   |                          ^ expected one of `>`, a const expression, lifetime, or type
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-20616-7.rs b/src/test/ui/parser/issue-20616-7.rs
new file mode 100644 (file)
index 0000000..67209c0
--- /dev/null
@@ -0,0 +1,35 @@
+// We need all these 9 issue-20616-N.rs files
+// because we can only catch one parsing error at a time
+
+type Type_1_<'a, T> = &'a T;
+
+
+//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
+
+
+//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
+
+
+//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
+
+
+//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
+
+
+type Type_5_<'a> = Type_1_<'a, ()>;
+
+
+//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
+
+
+//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
+
+
+type Type_7 = Box<(),,>;
+//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
+
+
+//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
+
+
+//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/parser/issue-20616-7.stderr b/src/test/ui/parser/issue-20616-7.stderr
new file mode 100644 (file)
index 0000000..e2c3efe
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected one of `>`, a const expression, lifetime, or type, found `,`
+  --> $DIR/issue-20616-7.rs:28:22
+   |
+LL | type Type_7 = Box<(),,>;
+   |                      ^ expected one of `>`, a const expression, lifetime, or type
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-21475.rs b/src/test/ui/parser/issue-21475.rs
new file mode 100644 (file)
index 0000000..b028fca
--- /dev/null
@@ -0,0 +1,19 @@
+// run-pass
+#![allow(unused_imports, overlapping_range_endpoints)]
+// pretty-expanded FIXME #23616
+
+use m::{START, END};
+
+fn main() {
+    match 42 {
+        m::START..=m::END => {},
+        0..=m::END => {},
+        m::START..=59 => {},
+        _  => {},
+    }
+}
+
+mod m {
+  pub const START: u32 = 4;
+  pub const END:   u32 = 14;
+}
diff --git a/src/test/ui/parser/issue-31804.rs b/src/test/ui/parser/issue-31804.rs
new file mode 100644 (file)
index 0000000..d056b77
--- /dev/null
@@ -0,0 +1,6 @@
+// Test that error recovery in the parser to an EOF does not give an infinite
+// spew of errors.
+
+fn main() {
+    let
+} //~ ERROR expected pattern, found `}`
diff --git a/src/test/ui/parser/issue-31804.stderr b/src/test/ui/parser/issue-31804.stderr
new file mode 100644 (file)
index 0000000..76e68b0
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected pattern, found `}`
+  --> $DIR/issue-31804.rs:6:1
+   |
+LL | }
+   | ^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-34255-1.rs b/src/test/ui/parser/issue-34255-1.rs
new file mode 100644 (file)
index 0000000..c70cd8b
--- /dev/null
@@ -0,0 +1,10 @@
+enum Test {
+    Drill {
+        field: i32,
+    }
+}
+
+fn main() {
+    Test::Drill(field: 42);
+    //~^ ERROR invalid `struct` delimiters or `fn` call arguments
+}
diff --git a/src/test/ui/parser/issue-34255-1.stderr b/src/test/ui/parser/issue-34255-1.stderr
new file mode 100644 (file)
index 0000000..fbff75e
--- /dev/null
@@ -0,0 +1,18 @@
+error: invalid `struct` delimiters or `fn` call arguments
+  --> $DIR/issue-34255-1.rs:8:5
+   |
+LL |     Test::Drill(field: 42);
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: if `Test::Drill` is a struct, use braces as delimiters
+   |
+LL |     Test::Drill { field: 42 };
+   |                 ~           ~
+help: if `Test::Drill` is a function, use the arguments directly
+   |
+LL -     Test::Drill(field: 42);
+LL +     Test::Drill(42);
+   | 
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-49040.rs b/src/test/ui/parser/issue-49040.rs
new file mode 100644 (file)
index 0000000..b7a541d
--- /dev/null
@@ -0,0 +1,3 @@
+#![allow(unused_variables)]; //~ ERROR expected item, found `;`
+//~^ ERROR `main` function
+fn foo() {}
diff --git a/src/test/ui/parser/issue-49040.stderr b/src/test/ui/parser/issue-49040.stderr
new file mode 100644 (file)
index 0000000..56befe3
--- /dev/null
@@ -0,0 +1,15 @@
+error: expected item, found `;`
+  --> $DIR/issue-49040.rs:1:28
+   |
+LL | #![allow(unused_variables)];
+   |                            ^ help: remove this semicolon
+
+error[E0601]: `main` function not found in crate `issue_49040`
+  --> $DIR/issue-49040.rs:1:1
+   |
+LL | #![allow(unused_variables)];
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ consider adding a `main` function to `$DIR/issue-49040.rs`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/parser/issue-56031.rs b/src/test/ui/parser/issue-56031.rs
new file mode 100644 (file)
index 0000000..b68f568
--- /dev/null
@@ -0,0 +1,6 @@
+struct T;
+
+impl for T {}
+//~^ ERROR missing trait in a trait impl
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-56031.stderr b/src/test/ui/parser/issue-56031.stderr
new file mode 100644 (file)
index 0000000..7ee5bc6
--- /dev/null
@@ -0,0 +1,18 @@
+error: missing trait in a trait impl
+  --> $DIR/issue-56031.rs:3:5
+   |
+LL | impl for T {}
+   |     ^
+   |
+help: add a trait here
+   |
+LL | impl Trait for T {}
+   |      +++++
+help: for an inherent impl, drop this `for`
+   |
+LL - impl for T {}
+LL + impl T {}
+   | 
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-89971-outer-attr-following-inner-attr-ice.rs b/src/test/ui/parser/issue-89971-outer-attr-following-inner-attr-ice.rs
new file mode 100644 (file)
index 0000000..fe67d98
--- /dev/null
@@ -0,0 +1,15 @@
+// aux-build:issue-89971-outer-attr-following-inner-attr-ice.rs
+
+#[macro_use]
+extern crate issue_89971_outer_attr_following_inner_attr_ice;
+
+fn main() {
+    Mew();
+    X {};
+}
+
+#![deny(missing_docs)]
+//~^ ERROR an inner attribute is not permitted in this context
+#[derive(ICE)]
+#[deny(missing_docs)]
+struct Mew();
diff --git a/src/test/ui/parser/issue-89971-outer-attr-following-inner-attr-ice.stderr b/src/test/ui/parser/issue-89971-outer-attr-following-inner-attr-ice.stderr
new file mode 100644 (file)
index 0000000..34a6ab0
--- /dev/null
@@ -0,0 +1,18 @@
+error: an inner attribute is not permitted in this context
+  --> $DIR/issue-89971-outer-attr-following-inner-attr-ice.rs:11:1
+   |
+LL | #![deny(missing_docs)]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | struct Mew();
+   | ------------- the inner attribute doesn't annotate this struct
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+help: to annotate the struct, change the attribute from inner to outer style
+   |
+LL - #![deny(missing_docs)]
+LL + #[deny(missing_docs)]
+   | 
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/unicode-control-codepoints.rs b/src/test/ui/parser/unicode-control-codepoints.rs
new file mode 100644 (file)
index 0000000..5af0b58
--- /dev/null
@@ -0,0 +1,39 @@
+fn main() {
+    // if access_level != "us‫e‪r" { // Check if admin
+    //~^ ERROR unicode codepoint changing visible direction of text present in comment
+    println!("us\u{202B}e\u{202A}r");
+    println!("{:?}", r#"us\u{202B}e\u{202A}r"#);
+    println!("{:?}", b"us\u{202B}e\u{202A}r");
+    //~^ ERROR unicode escape in byte string
+    //~| ERROR unicode escape in byte string
+    println!("{:?}", br##"us\u{202B}e\u{202A}r"##);
+
+    println!("{:?}", "/*‮ } ⁦if isAdmin⁩ ⁦ begin admins only ");
+    //~^ ERROR unicode codepoint changing visible direction of text present in literal
+
+    println!("{:?}", r##"/*‮ } ⁦if isAdmin⁩ ⁦ begin admins only "##);
+    //~^ ERROR unicode codepoint changing visible direction of text present in literal
+    println!("{:?}", b"/*‮ } ⁦if isAdmin⁩ ⁦ begin admins only ");
+    //~^ ERROR non-ASCII character in byte constant
+    //~| ERROR non-ASCII character in byte constant
+    //~| ERROR non-ASCII character in byte constant
+    //~| ERROR non-ASCII character in byte constant
+    println!("{:?}", br##"/*‮ } ⁦if isAdmin⁩ ⁦ begin admins only "##);
+    //~^ ERROR raw byte string must be ASCII
+    //~| ERROR raw byte string must be ASCII
+    //~| ERROR raw byte string must be ASCII
+    //~| ERROR raw byte string must be ASCII
+    println!("{:?}", '‮');
+    //~^ ERROR unicode codepoint changing visible direction of text present in literal
+}
+
+//"/*‮ } ⁦if isAdmin⁩ ⁦ begin admins only */"
+//~^ ERROR unicode codepoint changing visible direction of text present in comment
+
+/**  '‮'); */fn foo() {}
+//~^ ERROR unicode codepoint changing visible direction of text present in doc comment
+
+/**
+ *
+ *  '‮'); */fn bar() {}
+//~^^^ ERROR unicode codepoint changing visible direction of text present in doc comment
diff --git a/src/test/ui/parser/unicode-control-codepoints.stderr b/src/test/ui/parser/unicode-control-codepoints.stderr
new file mode 100644 (file)
index 0000000..71509fe
--- /dev/null
@@ -0,0 +1,192 @@
+error: unicode escape in byte string
+  --> $DIR/unicode-control-codepoints.rs:6:26
+   |
+LL |     println!("{:?}", b"us\u{202B}e\u{202A}r");
+   |                          ^^^^^^^^ unicode escape in byte string
+   |
+   = help: unicode escape sequences cannot be used as a byte or in a byte string
+
+error: unicode escape in byte string
+  --> $DIR/unicode-control-codepoints.rs:6:35
+   |
+LL |     println!("{:?}", b"us\u{202B}e\u{202A}r");
+   |                                   ^^^^^^^^ unicode escape in byte string
+   |
+   = help: unicode escape sequences cannot be used as a byte or in a byte string
+
+error: non-ASCII character in byte constant
+  --> $DIR/unicode-control-codepoints.rs:16:26
+   |
+LL |     println!("{:?}", b"/* } if isAdmin  begin admins only ");
+   |                          ^ byte constant must be ASCII but is '\u{202e}'
+   |
+help: if you meant to use the UTF-8 encoding of '\u{202e}', use \xHH escapes
+   |
+LL |     println!("{:?}", b"/*\xE2\x80\xAE } if isAdmin  begin admins only ");
+   |                          ~~~~~~~~~~~~
+
+error: non-ASCII character in byte constant
+  --> $DIR/unicode-control-codepoints.rs:16:30
+   |
+LL |     println!("{:?}", b"/* } if isAdmin  begin admins only ");
+   |                             ^ byte constant must be ASCII but is '\u{2066}'
+   |
+help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes
+   |
+LL |     println!("{:?}", b"/* } \xE2\x81\xA6if isAdmin  begin admins only ");
+   |                             ~~~~~~~~~~~~
+
+error: non-ASCII character in byte constant
+  --> $DIR/unicode-control-codepoints.rs:16:41
+   |
+LL |     println!("{:?}", b"/* } if isAdmin  begin admins only ");
+   |                                       ^ byte constant must be ASCII but is '\u{2069}'
+   |
+help: if you meant to use the UTF-8 encoding of '\u{2069}', use \xHH escapes
+   |
+LL |     println!("{:?}", b"/* } if isAdmin\xE2\x81\xA9  begin admins only ");
+   |                                       ~~~~~~~~~~~~
+
+error: non-ASCII character in byte constant
+  --> $DIR/unicode-control-codepoints.rs:16:43
+   |
+LL |     println!("{:?}", b"/* } if isAdmin  begin admins only ");
+   |                                        ^ byte constant must be ASCII but is '\u{2066}'
+   |
+help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes
+   |
+LL |     println!("{:?}", b"/* } if isAdmin \xE2\x81\xA6 begin admins only ");
+   |                                        ~~~~~~~~~~~~
+
+error: raw byte string must be ASCII
+  --> $DIR/unicode-control-codepoints.rs:21:29
+   |
+LL |     println!("{:?}", br##"/* } if isAdmin  begin admins only "##);
+   |                             ^ must be ASCII but is '\u{202e}'
+
+error: raw byte string must be ASCII
+  --> $DIR/unicode-control-codepoints.rs:21:33
+   |
+LL |     println!("{:?}", br##"/* } if isAdmin  begin admins only "##);
+   |                                ^ must be ASCII but is '\u{2066}'
+
+error: raw byte string must be ASCII
+  --> $DIR/unicode-control-codepoints.rs:21:44
+   |
+LL |     println!("{:?}", br##"/* } if isAdmin  begin admins only "##);
+   |                                          ^ must be ASCII but is '\u{2069}'
+
+error: raw byte string must be ASCII
+  --> $DIR/unicode-control-codepoints.rs:21:46
+   |
+LL |     println!("{:?}", br##"/* } if isAdmin  begin admins only "##);
+   |                                           ^ must be ASCII but is '\u{2066}'
+
+error: unicode codepoint changing visible direction of text present in comment
+  --> $DIR/unicode-control-codepoints.rs:2:5
+   |
+LL |     // if access_level != "user" { // Check if admin
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^
+   |     |                        ||
+   |     |                        |'\u{202a}'
+   |     |                        '\u{202b}'
+   |     this comment contains invisible unicode text flow control codepoints
+   |
+   = note: `#[deny(text_direction_codepoint_in_comment)]` on by default
+   = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+   = help: if their presence wasn't intentional, you can remove them
+
+error: unicode codepoint changing visible direction of text present in comment
+  --> $DIR/unicode-control-codepoints.rs:30:1
+   |
+LL | //"/* } if isAdmin  begin admins only */"
+   | ^^^^^-^^-^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^
+   | |    |  |         ||
+   | |    |  |         |'\u{2066}'
+   | |    |  |         '\u{2069}'
+   | |    |  '\u{2066}'
+   | |    '\u{202e}'
+   | this comment contains invisible unicode text flow control codepoints
+   |
+   = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+   = help: if their presence wasn't intentional, you can remove them
+
+error: unicode codepoint changing visible direction of text present in literal
+  --> $DIR/unicode-control-codepoints.rs:11:22
+   |
+LL |     println!("{:?}", "/* } if isAdmin  begin admins only ");
+   |                      ^^^-^^-^^^^^^^^^--^^^^^^^^^^^^^^^^^^^
+   |                      |  |  |         ||
+   |                      |  |  |         |'\u{2066}'
+   |                      |  |  |         '\u{2069}'
+   |                      |  |  '\u{2066}'
+   |                      |  '\u{202e}'
+   |                      this literal contains invisible unicode text flow control codepoints
+   |
+   = note: `#[deny(text_direction_codepoint_in_literal)]` on by default
+   = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+   = help: if their presence wasn't intentional, you can remove them
+help: if you want to keep them but make them visible in your source code, you can escape them
+   |
+LL |     println!("{:?}", "/*\u{202e} } \u{2066}if isAdmin\u{2069} \u{2066} begin admins only ");
+   |                         ~~~~~~~~   ~~~~~~~~          ~~~~~~~~ ~~~~~~~~
+
+error: unicode codepoint changing visible direction of text present in literal
+  --> $DIR/unicode-control-codepoints.rs:14:22
+   |
+LL |     println!("{:?}", r##"/* } if isAdmin  begin admins only "##);
+   |                      ^^^^^^-^^-^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^
+   |                      |     |  |         ||
+   |                      |     |  |         |'\u{2066}'
+   |                      |     |  |         '\u{2069}'
+   |                      |     |  '\u{2066}'
+   |                      |     '\u{202e}'
+   |                      this literal contains invisible unicode text flow control codepoints
+   |
+   = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+   = help: if their presence wasn't intentional, you can remove them
+help: if you want to keep them but make them visible in your source code, you can escape them
+   |
+LL |     println!("{:?}", r##"/*\u{202e} } \u{2066}if isAdmin\u{2069} \u{2066} begin admins only "##);
+   |                            ~~~~~~~~   ~~~~~~~~          ~~~~~~~~ ~~~~~~~~
+
+error: unicode codepoint changing visible direction of text present in literal
+  --> $DIR/unicode-control-codepoints.rs:26:22
+   |
+LL |     println!("{:?}", '');
+   |                      ^-
+   |                      ||
+   |                      |'\u{202e}'
+   |                      this literal contains an invisible unicode text flow control codepoint
+   |
+   = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+   = help: if their presence wasn't intentional, you can remove them
+help: if you want to keep them but make them visible in your source code, you can escape them
+   |
+LL |     println!("{:?}", '\u{202e}');
+   |                       ~~~~~~~~
+
+error: unicode codepoint changing visible direction of text present in doc comment
+  --> $DIR/unicode-control-codepoints.rs:33:1
+   |
+LL | /**  ''); */fn foo() {}
+   | ^^^^^^^^^^^^ this doc comment contains an invisible unicode text flow control codepoint
+   |
+   = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+   = note: if their presence wasn't intentional, you can remove them
+   = note: if you want to keep them but make them visible in your source code, you can escape them: '\u{202e}'
+
+error: unicode codepoint changing visible direction of text present in doc comment
+  --> $DIR/unicode-control-codepoints.rs:36:1
+   |
+LL | / /**
+LL | |  *
+LL | |  *  ''); */fn bar() {}
+   | |___________^ this doc comment contains an invisible unicode text flow control codepoint
+   |
+   = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+   = note: if their presence wasn't intentional, you can remove them
+   = note: if you want to keep them but make them visible in your source code, you can escape them: '\u{202e}'
+
+error: aborting due to 17 previous errors
+
diff --git a/src/test/ui/pattern/issue-11577.rs b/src/test/ui/pattern/issue-11577.rs
new file mode 100644 (file)
index 0000000..70177c5
--- /dev/null
@@ -0,0 +1,18 @@
+// run-pass
+// Destructuring struct variants would ICE where regular structs wouldn't
+
+enum Foo {
+    VBar { num: isize }
+}
+
+struct SBar { num: isize }
+
+pub fn main() {
+    let vbar = Foo::VBar { num: 1 };
+    let Foo::VBar { num } = vbar;
+    assert_eq!(num, 1);
+
+    let sbar = SBar { num: 2 };
+    let SBar { num } = sbar;
+    assert_eq!(num, 2);
+}
diff --git a/src/test/ui/pattern/issue-15080.rs b/src/test/ui/pattern/issue-15080.rs
new file mode 100644 (file)
index 0000000..4dd6981
--- /dev/null
@@ -0,0 +1,22 @@
+// run-pass
+
+fn main() {
+    let mut x: &[_] = &[1, 2, 3, 4];
+
+    let mut result = vec![];
+    loop {
+        x = match *x {
+            [1, n, 3, ref rest @ ..] => {
+                result.push(n);
+                rest
+            }
+            [n, ref rest @ ..] => {
+                result.push(n);
+                rest
+            }
+            [] =>
+                break
+        }
+    }
+    assert_eq!(result, [2, 4]);
+}
diff --git a/src/test/ui/pattern/issue-72574-2.rs b/src/test/ui/pattern/issue-72574-2.rs
new file mode 100644 (file)
index 0000000..0ad2db8
--- /dev/null
@@ -0,0 +1,12 @@
+struct Binder(i32, i32, i32);
+
+fn main() {
+    let x = Binder(1, 2, 3);
+    match x {
+        Binder(_a, _x @ ..) => {}
+        _ => {}
+    }
+}
+//~^^^^ ERROR `_x @` is not allowed in a tuple struct
+//~| ERROR: `..` patterns are not allowed here
+//~| ERROR: this pattern has 2 fields, but the corresponding tuple struct has 3 fields
diff --git a/src/test/ui/pattern/issue-72574-2.stderr b/src/test/ui/pattern/issue-72574-2.stderr
new file mode 100644 (file)
index 0000000..05650f0
--- /dev/null
@@ -0,0 +1,37 @@
+error: `_x @` is not allowed in a tuple struct
+  --> $DIR/issue-72574-2.rs:6:20
+   |
+LL |         Binder(_a, _x @ ..) => {}
+   |                    ^^^^^^^ this is only allowed in slice patterns
+   |
+   = help: remove this and bind each tuple field independently
+help: if you don't need to use the contents of _x, discard the tuple's remaining fields
+   |
+LL |         Binder(_a, ..) => {}
+   |                    ~~
+
+error: `..` patterns are not allowed here
+  --> $DIR/issue-72574-2.rs:6:25
+   |
+LL |         Binder(_a, _x @ ..) => {}
+   |                         ^^
+   |
+   = note: only allowed in tuple, tuple struct, and slice patterns
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 3 fields
+  --> $DIR/issue-72574-2.rs:6:16
+   |
+LL | struct Binder(i32, i32, i32);
+   |               ---  ---  --- tuple struct has 3 fields
+...
+LL |         Binder(_a, _x @ ..) => {}
+   |                ^^  ^^^^^^^ expected 3 fields, found 2
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         Binder(_a, _x @ .., _) => {}
+   |                           +++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0023`.
diff --git a/src/test/ui/pattern/issue-8351-1.rs b/src/test/ui/pattern/issue-8351-1.rs
new file mode 100644 (file)
index 0000000..139f027
--- /dev/null
@@ -0,0 +1,16 @@
+// run-pass
+#![allow(dead_code)]
+
+enum E {
+    Foo{f: isize},
+    Bar,
+}
+
+pub fn main() {
+    let e = E::Foo{f: 0};
+    match e {
+        E::Foo{f: 1} => panic!(),
+        E::Foo{..} => (),
+        _ => panic!(),
+    }
+}
diff --git a/src/test/ui/pattern/issue-8351-2.rs b/src/test/ui/pattern/issue-8351-2.rs
new file mode 100644 (file)
index 0000000..bc66cbb
--- /dev/null
@@ -0,0 +1,16 @@
+// run-pass
+#![allow(dead_code)]
+
+enum E {
+    Foo{f: isize, b: bool},
+    Bar,
+}
+
+pub fn main() {
+    let e = E::Foo{f: 0, b: false};
+    match e {
+        E::Foo{f: 1, b: true} => panic!(),
+        E::Foo{b: false, f: 0} => (),
+        _ => panic!(),
+    }
+}
index f926eee9d92b282deddff6f52ff1437bc6edb05e..ec8666f93f096392d13343e876983af073e7bba8 100644 (file)
@@ -1,5 +1,6 @@
 // aux-crate:priv:priv_dep=priv_dep.rs
 // aux-build:pub_dep.rs
+// compile-flags: -Zunstable-options
 #![deny(exported_private_dependencies)]
 
 // This crate is a private dependency
index e6b4d33f10316e4ee36e8644e0de76f4f9a2a819..f64b8569015d8fc881c2c50dd5d44cdd20a21b04 100644 (file)
@@ -1,23 +1,23 @@
 error: type `OtherType` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:20:5
+  --> $DIR/pub-priv1.rs:21:5
    |
 LL |     pub field: OtherType,
    |     ^^^^^^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/pub-priv1.rs:3:9
+  --> $DIR/pub-priv1.rs:4:9
    |
 LL | #![deny(exported_private_dependencies)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: type `OtherType` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:27:5
+  --> $DIR/pub-priv1.rs:28:5
    |
 LL |     pub fn pub_fn(param: OtherType) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: trait `OtherTrait` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:34:5
+  --> $DIR/pub-priv1.rs:35:5
    |
 LL |     type Foo: OtherTrait;
    |     ^^^^^^^^^^^^^^^^^^^^^
index 65d8bcd9972e65bf82b6c1b9ecbcccaf34379d24..695ea69c8e65284bd80c7e77d9bf2b3382e5eab2 100644 (file)
@@ -35,5 +35,5 @@ fn main() {
 }
 
 use deny as allow;
-#[allow(unused)] //~ ERROR `allow` is ambiguous (built-in attribute vs any other name)
+#[allow(unused)] //~ ERROR `allow` is ambiguous
 fn builtin_renamed() {}
index 1ad991db3be4450e6861de7ae4dadd516871d27d..0f4ddc065a7420cd384a6cbae36611de6e7e0f30 100644 (file)
@@ -4,12 +4,13 @@ error[E0425]: cannot find value `NonExistent` in this scope
 LL |     NonExistent;
    |     ^^^^^^^^^^^ not found in this scope
 
-error[E0659]: `repr` is ambiguous (built-in attribute vs any other name)
+error[E0659]: `repr` is ambiguous
   --> $DIR/ambiguous-builtin-attrs.rs:9:3
    |
 LL | #[repr(C)]
    |   ^^^^ ambiguous name
    |
+   = note: ambiguous because of a name conflict with a builtin attribute
    = note: `repr` could refer to a built-in attribute
 note: `repr` could also refer to the attribute macro imported here
   --> $DIR/ambiguous-builtin-attrs.rs:6:5
@@ -18,12 +19,13 @@ LL | use builtin_attrs::*;
    |     ^^^^^^^^^^^^^^^^
    = help: use `crate::repr` to refer to this attribute macro unambiguously
 
-error[E0659]: `repr` is ambiguous (built-in attribute vs any other name)
+error[E0659]: `repr` is ambiguous
   --> $DIR/ambiguous-builtin-attrs.rs:11:19
    |
 LL | #[cfg_attr(all(), repr(C))]
    |                   ^^^^ ambiguous name
    |
+   = note: ambiguous because of a name conflict with a builtin attribute
    = note: `repr` could refer to a built-in attribute
 note: `repr` could also refer to the attribute macro imported here
   --> $DIR/ambiguous-builtin-attrs.rs:6:5
@@ -32,12 +34,13 @@ LL | use builtin_attrs::*;
    |     ^^^^^^^^^^^^^^^^
    = help: use `crate::repr` to refer to this attribute macro unambiguously
 
-error[E0659]: `repr` is ambiguous (built-in attribute vs any other name)
+error[E0659]: `repr` is ambiguous
   --> $DIR/ambiguous-builtin-attrs.rs:20:34
    |
 LL | fn non_macro_expanded_location<#[repr(C)] T>() {
    |                                  ^^^^ ambiguous name
    |
+   = note: ambiguous because of a name conflict with a builtin attribute
    = note: `repr` could refer to a built-in attribute
 note: `repr` could also refer to the attribute macro imported here
   --> $DIR/ambiguous-builtin-attrs.rs:6:5
@@ -46,12 +49,13 @@ LL | use builtin_attrs::*;
    |     ^^^^^^^^^^^^^^^^
    = help: use `crate::repr` to refer to this attribute macro unambiguously
 
-error[E0659]: `repr` is ambiguous (built-in attribute vs any other name)
+error[E0659]: `repr` is ambiguous
   --> $DIR/ambiguous-builtin-attrs.rs:24:11
    |
 LL |         #[repr(C)]
    |           ^^^^ ambiguous name
    |
+   = note: ambiguous because of a name conflict with a builtin attribute
    = note: `repr` could refer to a built-in attribute
 note: `repr` could also refer to the attribute macro imported here
   --> $DIR/ambiguous-builtin-attrs.rs:6:5
@@ -60,12 +64,13 @@ LL | use builtin_attrs::*;
    |     ^^^^^^^^^^^^^^^^
    = help: use `crate::repr` to refer to this attribute macro unambiguously
 
-error[E0659]: `allow` is ambiguous (built-in attribute vs any other name)
+error[E0659]: `allow` is ambiguous
   --> $DIR/ambiguous-builtin-attrs.rs:38:3
    |
 LL | #[allow(unused)]
    |   ^^^^^ ambiguous name
    |
+   = note: ambiguous because of a name conflict with a builtin attribute
    = note: `allow` could refer to a built-in attribute
 note: `allow` could also refer to the built-in attribute imported here
   --> $DIR/ambiguous-builtin-attrs.rs:37:5
@@ -74,12 +79,13 @@ LL | use deny as allow;
    |     ^^^^^^^^^^^^^
    = help: use `crate::allow` to refer to this built-in attribute unambiguously
 
-error[E0659]: `feature` is ambiguous (built-in attribute vs any other name)
+error[E0659]: `feature` is ambiguous
   --> $DIR/ambiguous-builtin-attrs.rs:3:4
    |
 LL | #![feature(decl_macro)]
    |    ^^^^^^^ ambiguous name
    |
+   = note: ambiguous because of a name conflict with a builtin attribute
    = note: `feature` could refer to a built-in attribute
 note: `feature` could also refer to the attribute macro imported here
   --> $DIR/ambiguous-builtin-attrs.rs:6:5
index 93551ebaf82d598416d68dcc58bfea5953f904d2..6186b941ef69f6c6f5fee030212c203c3aa6ed8e 100644 (file)
@@ -1,3 +1,5 @@
+// ignore-tidy-linelength
+
 use proc_macro::Literal;
 
 pub fn test() {
@@ -8,6 +10,14 @@ pub fn test() {
 fn test_display_literal() {
     assert_eq!(Literal::isize_unsuffixed(-10).to_string(), "-10");
     assert_eq!(Literal::isize_suffixed(-10).to_string(), "-10isize");
+    assert_eq!(Literal::f32_unsuffixed(-10.0).to_string(), "-10.0");
+    assert_eq!(Literal::f32_suffixed(-10.0).to_string(), "-10f32");
+    assert_eq!(Literal::f64_unsuffixed(-10.0).to_string(), "-10.0");
+    assert_eq!(Literal::f64_suffixed(-10.0).to_string(), "-10f64");
+    assert_eq!(
+        Literal::f64_unsuffixed(1e100).to_string(),
+        "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0",
+    );
 }
 
 fn test_parse_literal() {
index df462903fc077609c8889277b92ce90be7e6aa46..d8287eb73db01ae4958f7f94927b6ff016b78b3a 100644 (file)
@@ -33,12 +33,13 @@ LL |             gen_helper_use!();
            crate::empty_helper
    = note: this error originates in the macro `gen_helper_use` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0659]: `empty_helper` is ambiguous (name vs any other name during import resolution)
+error[E0659]: `empty_helper` is ambiguous
   --> $DIR/derive-helper-shadowing.rs:26:13
    |
 LL |         use empty_helper;
    |             ^^^^^^^^^^^^ ambiguous name
    |
+   = note: ambiguous because of multiple potential import sources
 note: `empty_helper` could refer to the derive helper attribute defined here
   --> $DIR/derive-helper-shadowing.rs:22:10
    |
@@ -51,12 +52,13 @@ LL | use test_macros::empty_attr as empty_helper;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: use `crate::empty_helper` to refer to this attribute macro unambiguously
 
-error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name)
+error[E0659]: `empty_helper` is ambiguous
   --> $DIR/derive-helper-shadowing.rs:19:3
    |
 LL | #[empty_helper]
    |   ^^^^^^^^^^^^ ambiguous name
    |
+   = note: ambiguous because of a name conflict with a derive helper attribute
 note: `empty_helper` could refer to the derive helper attribute defined here
   --> $DIR/derive-helper-shadowing.rs:22:10
    |
index ceb6d789785cc1b39548266c2407c9f4d8cdd51d..45b014c4b69fa161d2e4e4bc645c0a917a3133ee 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name)
+error[E0659]: `empty_helper` is ambiguous
   --> $DIR/helper-attr-blocked-by-import-ambig.rs:7:3
    |
 LL | #[empty_helper]
    |   ^^^^^^^^^^^^ ambiguous name
    |
+   = note: ambiguous because of a name conflict with a derive helper attribute
 note: `empty_helper` could refer to the derive helper attribute defined here
   --> $DIR/helper-attr-blocked-by-import-ambig.rs:10:10
    |
index 22ad4aa147b66132be92f110bca81294deacfe91..60cd36a9cceb92d3c4d3ff5617238a8e4eb197a9 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `identity_attr` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+error[E0659]: `identity_attr` is ambiguous
   --> $DIR/issue-41211.rs:11:4
    |
 LL | #![identity_attr]
    |    ^^^^^^^^^^^^^ ambiguous name
    |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
 note: `identity_attr` could refer to the attribute macro imported here
   --> $DIR/issue-41211.rs:14:5
    |
index 7f7a1009c909a6a751d846e4c5ef5bed08d9c704..5d04fe1e3de5f5cd08f9ead0fb563fdfd8d05eca 100644 (file)
@@ -49,6 +49,8 @@ crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt:
 crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "produce_it")
 crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "meta_macro::print_def_site")
 crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "$crate::dummy")
+crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive")
+crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive")
 crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "include")
 crate2::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
 
index 078038638137327b44fa10c59ecf8ff5262c31af..709b2a2169e08d8f9033ba28e706f17f06756acc 100644 (file)
@@ -73,6 +73,8 @@ crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt:
 crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer")
 crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #4, def_site_ctxt: #4, kind: Macro(Bang, "inner")
 crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #6, def_site_ctxt: #0, kind: Macro(Bang, "print_bang")
+crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive")
+crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive")
 crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "include")
 crate2::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
 
index 1ba04258df0d53c942a78c1e33d5d6f073897c8d..b66e4575e11af6720abf96cc9472e2a5895bbddf 100644 (file)
@@ -4,12 +4,13 @@ error: cannot find attribute `C` in this scope
 LL | #[C]
    |   ^ help: a derive helper attribute with a similar name exists: `B`
 
-error[E0659]: `B` is ambiguous (derive helper attribute vs any other name)
+error[E0659]: `B` is ambiguous
   --> $DIR/proc-macro-attributes.rs:6:3
    |
 LL | #[B]
    |   ^ ambiguous name
    |
+   = note: ambiguous because of a name conflict with a derive helper attribute
 note: `B` could refer to the derive helper attribute defined here
   --> $DIR/proc-macro-attributes.rs:19:10
    |
@@ -21,12 +22,13 @@ note: `B` could also refer to the derive macro imported here
 LL | #[macro_use]
    | ^^^^^^^^^^^^
 
-error[E0659]: `B` is ambiguous (derive helper attribute vs any other name)
+error[E0659]: `B` is ambiguous
   --> $DIR/proc-macro-attributes.rs:10:3
    |
 LL | #[B(D)]
    |   ^ ambiguous name
    |
+   = note: ambiguous because of a name conflict with a derive helper attribute
 note: `B` could refer to the derive helper attribute defined here
   --> $DIR/proc-macro-attributes.rs:19:10
    |
@@ -38,12 +40,13 @@ note: `B` could also refer to the derive macro imported here
 LL | #[macro_use]
    | ^^^^^^^^^^^^
 
-error[E0659]: `B` is ambiguous (derive helper attribute vs any other name)
+error[E0659]: `B` is ambiguous
   --> $DIR/proc-macro-attributes.rs:13:3
    |
 LL | #[B(E = "foo")]
    |   ^ ambiguous name
    |
+   = note: ambiguous because of a name conflict with a derive helper attribute
 note: `B` could refer to the derive helper attribute defined here
   --> $DIR/proc-macro-attributes.rs:19:10
    |
@@ -55,12 +58,13 @@ note: `B` could also refer to the derive macro imported here
 LL | #[macro_use]
    | ^^^^^^^^^^^^
 
-error[E0659]: `B` is ambiguous (derive helper attribute vs any other name)
+error[E0659]: `B` is ambiguous
   --> $DIR/proc-macro-attributes.rs:16:3
    |
 LL | #[B(arbitrary tokens)]
    |   ^ ambiguous name
    |
+   = note: ambiguous because of a name conflict with a derive helper attribute
 note: `B` could refer to the derive helper attribute defined here
   --> $DIR/proc-macro-attributes.rs:19:10
    |
diff --git a/src/test/ui/process/issue-14456.rs b/src/test/ui/process/issue-14456.rs
new file mode 100644 (file)
index 0000000..52a56eb
--- /dev/null
@@ -0,0 +1,37 @@
+// run-pass
+#![allow(unused_mut)]
+// ignore-emscripten no processes
+// ignore-sgx no processes
+
+use std::env;
+use std::io::prelude::*;
+use std::io;
+use std::process::{Command, Stdio};
+
+fn main() {
+    let args: Vec<String> = env::args().collect();
+    if args.len() > 1 && args[1] == "child" {
+        return child()
+    }
+
+    test();
+}
+
+fn child() {
+    writeln!(&mut io::stdout(), "foo").unwrap();
+    writeln!(&mut io::stderr(), "bar").unwrap();
+    let mut stdin = io::stdin();
+    let mut s = String::new();
+    stdin.lock().read_line(&mut s).unwrap();
+    assert_eq!(s.len(), 0);
+}
+
+fn test() {
+    let args: Vec<String> = env::args().collect();
+    let mut p = Command::new(&args[0]).arg("child")
+                                     .stdin(Stdio::piped())
+                                     .stdout(Stdio::piped())
+                                     .stderr(Stdio::piped())
+                                     .spawn().unwrap();
+    assert!(p.wait().unwrap().success());
+}
diff --git a/src/test/ui/process/issue-16272.rs b/src/test/ui/process/issue-16272.rs
new file mode 100644 (file)
index 0000000..5cf3fd9
--- /dev/null
@@ -0,0 +1,23 @@
+// run-pass
+// ignore-emscripten no processes
+// ignore-sgx no processes
+
+use std::process::Command;
+use std::env;
+
+fn main() {
+    let len = env::args().len();
+
+    if len == 1 {
+        test();
+    } else {
+        assert_eq!(len, 3);
+    }
+}
+
+fn test() {
+    let status = Command::new(&env::current_exe().unwrap())
+                         .arg("foo").arg("")
+                         .status().unwrap();
+    assert!(status.success());
+}
diff --git a/src/test/ui/process/issue-20091.rs b/src/test/ui/process/issue-20091.rs
new file mode 100644 (file)
index 0000000..86cc79d
--- /dev/null
@@ -0,0 +1,24 @@
+// run-pass
+#![allow(stable_features)]
+
+// ignore-emscripten no processes
+// ignore-sgx no processes
+
+#![feature(os)]
+
+#[cfg(unix)]
+fn main() {
+    use std::process::Command;
+    use std::env;
+    use std::os::unix::prelude::*;
+    use std::ffi::OsStr;
+
+    if env::args().len() == 1 {
+        assert!(Command::new(&env::current_exe().unwrap())
+                        .arg(<OsStr as OsStrExt>::from_bytes(b"\xff"))
+                        .status().unwrap().success())
+    }
+}
+
+#[cfg(windows)]
+fn main() {}
diff --git a/src/test/ui/process/signal-exit-status.rs b/src/test/ui/process/signal-exit-status.rs
new file mode 100644 (file)
index 0000000..0963dcc
--- /dev/null
@@ -0,0 +1,18 @@
+// run-pass
+// ignore-emscripten no processes
+// ignore-sgx no processes
+// ignore-windows
+
+use std::env;
+use std::process::Command;
+
+pub fn main() {
+    let args: Vec<String> = env::args().collect();
+    if args.len() >= 2 && args[1] == "signal" {
+        // Raise a segfault.
+        unsafe { *(1 as *mut isize) = 0; }
+    } else {
+        let status = Command::new(&args[0]).arg("signal").status().unwrap();
+        assert!(status.code().is_none());
+    }
+}
index f53bcb97e69723ad748e710a63deae7916f00876..e8e477ea4f6849aec68d7c03fc9ba2085393a8cb 100644 (file)
@@ -7,6 +7,7 @@
 fn a() {
     // the cast is unreachable:
     let x = {return} as !; //~ ERROR unreachable
+    //~| ERROR non-primitive cast
 }
 
 fn main() { }
index 3aa15bde9956b57bcb1fbf3a9e2e6239b7537264..6643f1784a1744916b10721961130ab320fdc881 100644 (file)
@@ -13,5 +13,12 @@ note: the lint level is defined here
 LL | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error[E0605]: non-primitive cast: `()` as `!`
+  --> $DIR/expr_cast.rs:9:13
+   |
+LL |     let x = {return} as !;
+   |             ^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0605`.
diff --git a/src/test/ui/regions/issue-21520.rs b/src/test/ui/regions/issue-21520.rs
new file mode 100644 (file)
index 0000000..ab4ac72
--- /dev/null
@@ -0,0 +1,22 @@
+// check-pass
+#![allow(dead_code)]
+// Test that the requirement (in `Bar`) that `T::Bar : 'static` does
+// not wind up propagating to `T`.
+
+// pretty-expanded FIXME #23616
+
+pub trait Foo {
+    type Bar;
+
+    fn foo(&self) -> Self;
+}
+
+pub struct Static<T:'static>(T);
+
+struct Bar<T:Foo>
+    where T::Bar : 'static
+{
+    x: Static<Option<T::Bar>>
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/issue-26448-1.rs b/src/test/ui/regions/issue-26448-1.rs
new file mode 100644 (file)
index 0000000..7d2d75b
--- /dev/null
@@ -0,0 +1,13 @@
+// run-pass
+
+pub trait Foo<T> {
+    fn foo(self) -> T;
+}
+
+impl<'a, T> Foo<T> for &'a str where &'a str: Into<T> {
+    fn foo(self) -> T {
+        panic!();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/issue-26448-2.rs b/src/test/ui/regions/issue-26448-2.rs
new file mode 100644 (file)
index 0000000..c60e06c
--- /dev/null
@@ -0,0 +1,21 @@
+// check-pass
+
+pub struct Bar<T> {
+    items: Vec<&'static str>,
+    inner: T,
+}
+
+pub trait IntoBar<T> {
+    fn into_bar(self) -> Bar<T>;
+}
+
+impl<'a, T> IntoBar<T> for &'a str where &'a str: Into<T> {
+    fn into_bar(self) -> Bar<T> {
+        Bar {
+            items: Vec::new(),
+            inner: self.into(),
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/issue-26448-3.rs b/src/test/ui/regions/issue-26448-3.rs
new file mode 100644 (file)
index 0000000..d48022c
--- /dev/null
@@ -0,0 +1,25 @@
+// check-pass
+
+pub struct Item {
+    _inner: &'static str,
+}
+
+pub struct Bar<T> {
+    items: Vec<Item>,
+    inner: T,
+}
+
+pub trait IntoBar<T> {
+    fn into_bar(self) -> Bar<T>;
+}
+
+impl<'a, T> IntoBar<T> for &'a str where &'a str: Into<T> {
+    fn into_bar(self) -> Bar<T> {
+        Bar {
+            items: Vec::new(),
+            inner: self.into(),
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/required-lang-item.rs b/src/test/ui/required-lang-item.rs
deleted file mode 100644 (file)
index 3b17c5b..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// build-fail
-
-#![feature(lang_items, no_core)]
-#![no_core]
-
-#[lang="copy"] pub trait Copy { }
-#[lang="sized"] pub trait Sized { }
-
-// error-pattern:requires `start` lang_item
-
-fn main() {}
diff --git a/src/test/ui/required-lang-item.stderr b/src/test/ui/required-lang-item.stderr
deleted file mode 100644 (file)
index 83764a9..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-error: requires `start` lang_item
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/resolve/editions-crate-root-2015.rs b/src/test/ui/resolve/editions-crate-root-2015.rs
new file mode 100644 (file)
index 0000000..4c890e3
--- /dev/null
@@ -0,0 +1,21 @@
+// edition:2015
+
+mod inner {
+    fn global_inner(_: ::nonexistant::Foo) {
+        //~^ ERROR failed to resolve: maybe a missing crate `nonexistant`?
+    }
+    fn crate_inner(_: crate::nonexistant::Foo) {
+        //~^ ERROR failed to resolve: maybe a missing crate `nonexistant`?
+    }
+
+    fn bare_global(_: ::nonexistant) {
+        //~^ ERROR cannot find type `nonexistant` in the crate root
+    }
+    fn bare_crate(_: crate::nonexistant) {
+        //~^ ERROR cannot find type `nonexistant` in the crate root
+    }
+}
+
+fn main() {
+
+}
diff --git a/src/test/ui/resolve/editions-crate-root-2015.stderr b/src/test/ui/resolve/editions-crate-root-2015.stderr
new file mode 100644 (file)
index 0000000..f8d65fe
--- /dev/null
@@ -0,0 +1,28 @@
+error[E0433]: failed to resolve: maybe a missing crate `nonexistant`?
+  --> $DIR/editions-crate-root-2015.rs:4:26
+   |
+LL |     fn global_inner(_: ::nonexistant::Foo) {
+   |                          ^^^^^^^^^^^ maybe a missing crate `nonexistant`?
+
+error[E0433]: failed to resolve: maybe a missing crate `nonexistant`?
+  --> $DIR/editions-crate-root-2015.rs:7:30
+   |
+LL |     fn crate_inner(_: crate::nonexistant::Foo) {
+   |                              ^^^^^^^^^^^ maybe a missing crate `nonexistant`?
+
+error[E0412]: cannot find type `nonexistant` in the crate root
+  --> $DIR/editions-crate-root-2015.rs:11:25
+   |
+LL |     fn bare_global(_: ::nonexistant) {
+   |                         ^^^^^^^^^^^ not found in the crate root
+
+error[E0412]: cannot find type `nonexistant` in the crate root
+  --> $DIR/editions-crate-root-2015.rs:14:29
+   |
+LL |     fn bare_crate(_: crate::nonexistant) {
+   |                             ^^^^^^^^^^^ not found in the crate root
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0412, E0433.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/resolve/issue-12796.rs b/src/test/ui/resolve/issue-12796.rs
new file mode 100644 (file)
index 0000000..942d6b9
--- /dev/null
@@ -0,0 +1,9 @@
+trait Trait {
+    fn outer(&self) {
+        fn inner(_: &Self) {
+            //~^ ERROR can't use generic parameters from outer function
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/resolve/issue-12796.stderr b/src/test/ui/resolve/issue-12796.stderr
new file mode 100644 (file)
index 0000000..a01fd2d
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/issue-12796.rs:3:22
+   |
+LL |         fn inner(_: &Self) {
+   |                      ^^^^
+   |                      |
+   |                      use of generic parameter from outer function
+   |                      can't use `Self` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/resolve/issue-23716.rs b/src/test/ui/resolve/issue-23716.rs
new file mode 100644 (file)
index 0000000..e9139c0
--- /dev/null
@@ -0,0 +1,17 @@
+static foo: i32 = 0;
+
+fn bar(foo: i32) {}
+//~^ ERROR function parameters cannot shadow statics
+//~| cannot be named the same as a static
+
+mod submod {
+    pub static answer: i32 = 42;
+}
+
+use self::submod::answer;
+
+fn question(answer: i32) {}
+//~^ ERROR function parameters cannot shadow statics
+//~| cannot be named the same as a static
+fn main() {
+}
diff --git a/src/test/ui/resolve/issue-23716.stderr b/src/test/ui/resolve/issue-23716.stderr
new file mode 100644 (file)
index 0000000..e7bebfb
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0530]: function parameters cannot shadow statics
+  --> $DIR/issue-23716.rs:3:8
+   |
+LL | static foo: i32 = 0;
+   | -------------------- the static `foo` is defined here
+LL | 
+LL | fn bar(foo: i32) {}
+   |        ^^^ cannot be named the same as a static
+
+error[E0530]: function parameters cannot shadow statics
+  --> $DIR/issue-23716.rs:13:13
+   |
+LL | use self::submod::answer;
+   |     -------------------- the static `answer` is imported here
+LL | 
+LL | fn question(answer: i32) {}
+   |             ^^^^^^ cannot be named the same as a static
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0530`.
diff --git a/src/test/ui/resolve/issue-3021-c.rs b/src/test/ui/resolve/issue-3021-c.rs
new file mode 100644 (file)
index 0000000..94ed1fd
--- /dev/null
@@ -0,0 +1,9 @@
+fn siphash<T>() {
+
+    trait U {
+        fn g(&self, x: T) -> T;  //~ ERROR can't use generic parameters from outer function
+        //~^ ERROR can't use generic parameters from outer function
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-3021-c.stderr b/src/test/ui/resolve/issue-3021-c.stderr
new file mode 100644 (file)
index 0000000..8764ac8
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/issue-3021-c.rs:4:24
+   |
+LL | fn siphash<T>() {
+   |            - type parameter from outer function
+...
+LL |         fn g(&self, x: T) -> T;
+   |            -           ^ use of generic parameter from outer function
+   |            |
+   |            help: try using a local generic parameter instead: `g<T>`
+
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/issue-3021-c.rs:4:30
+   |
+LL | fn siphash<T>() {
+   |            - type parameter from outer function
+...
+LL |         fn g(&self, x: T) -> T;
+   |            -                 ^ use of generic parameter from outer function
+   |            |
+   |            help: try using a local generic parameter instead: `g<T>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/resolve/issue-3021.rs b/src/test/ui/resolve/issue-3021.rs
new file mode 100644 (file)
index 0000000..a672261
--- /dev/null
@@ -0,0 +1,18 @@
+trait SipHash {
+    fn reset(&self);
+}
+
+fn siphash(k0 : u64) {
+    struct SipState {
+        v0: u64,
+    }
+
+    impl SipHash for SipState {
+        fn reset(&self) {
+           self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR can't capture dynamic environment
+        }
+    }
+    panic!();
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-3021.stderr b/src/test/ui/resolve/issue-3021.stderr
new file mode 100644 (file)
index 0000000..d5b015e
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0434]: can't capture dynamic environment in a fn item
+  --> $DIR/issue-3021.rs:12:22
+   |
+LL |            self.v0 = k0 ^ 0x736f6d6570736575;
+   |                      ^^
+   |
+   = help: use the `|| { ... }` closure form instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0434`.
diff --git a/src/test/ui/resolve/issue-31845.rs b/src/test/ui/resolve/issue-31845.rs
new file mode 100644 (file)
index 0000000..f6dc115
--- /dev/null
@@ -0,0 +1,12 @@
+// Checks lexical scopes cannot see through normal module boundaries
+
+fn f() {
+    fn g() {}
+    mod foo {
+        fn h() {
+           g(); //~ ERROR cannot find function `g` in this scope
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-31845.stderr b/src/test/ui/resolve/issue-31845.stderr
new file mode 100644 (file)
index 0000000..5628193
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0425]: cannot find function `g` in this scope
+  --> $DIR/issue-31845.rs:7:12
+   |
+LL |            g();
+   |            ^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/resolve/issue-5099.rs b/src/test/ui/resolve/issue-5099.rs
new file mode 100644 (file)
index 0000000..b5abccb
--- /dev/null
@@ -0,0 +1,13 @@
+trait B <A> {
+    fn a() -> A {
+        this.a //~ ERROR cannot find value `this` in this scope
+    }
+    fn b(x: i32) {
+        this.b(x); //~ ERROR cannot find value `this` in this scope
+    }
+    fn c() {
+        let _ = || this.a; //~ ERROR cannot find value `this` in this scope
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-5099.stderr b/src/test/ui/resolve/issue-5099.stderr
new file mode 100644 (file)
index 0000000..e9b2a9c
--- /dev/null
@@ -0,0 +1,48 @@
+error[E0425]: cannot find value `this` in this scope
+  --> $DIR/issue-5099.rs:3:9
+   |
+LL |         this.a
+   |         ^^^^ not found in this scope
+   |
+help: you might have meant to use `self` here instead
+   |
+LL |         self.a
+   |         ~~~~
+help: if you meant to use `self`, you are also missing a `self` receiver argument
+   |
+LL |     fn a(&self) -> A {
+   |          +++++
+
+error[E0425]: cannot find value `this` in this scope
+  --> $DIR/issue-5099.rs:6:9
+   |
+LL |         this.b(x);
+   |         ^^^^ not found in this scope
+   |
+help: you might have meant to use `self` here instead
+   |
+LL |         self.b(x);
+   |         ~~~~
+help: if you meant to use `self`, you are also missing a `self` receiver argument
+   |
+LL |     fn b(&self, x: i32) {
+   |          ++++++
+
+error[E0425]: cannot find value `this` in this scope
+  --> $DIR/issue-5099.rs:9:20
+   |
+LL |         let _ = || this.a;
+   |                    ^^^^ not found in this scope
+   |
+help: you might have meant to use `self` here instead
+   |
+LL |         let _ = || self.a;
+   |                    ~~~~
+help: if you meant to use `self`, you are also missing a `self` receiver argument
+   |
+LL |     fn c(&self) {
+   |          +++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/resolve/issue-90113.rs b/src/test/ui/resolve/issue-90113.rs
new file mode 100644 (file)
index 0000000..f6658b4
--- /dev/null
@@ -0,0 +1,21 @@
+mod list {
+    pub use self::List::Cons;
+
+    pub enum List<T> {
+        Cons(T, Box<List<T>>),
+    }
+}
+
+mod alias {
+    use crate::list::List;
+
+    pub type Foo = List<String>;
+}
+
+fn foo(l: crate::alias::Foo) {
+    match l {
+        Cons(..) => {} //~ ERROR: cannot find tuple struct or tuple variant `Cons` in this scope
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-90113.stderr b/src/test/ui/resolve/issue-90113.stderr
new file mode 100644 (file)
index 0000000..1b78720
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0531]: cannot find tuple struct or tuple variant `Cons` in this scope
+  --> $DIR/issue-90113.rs:17:9
+   |
+LL |         Cons(..) => {}
+   |         ^^^^ not found in this scope
+   |
+help: consider importing this tuple variant
+   |
+LL | use list::List::Cons;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0531`.
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.rs b/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.rs
new file mode 100644 (file)
index 0000000..0260caa
--- /dev/null
@@ -0,0 +1,21 @@
+// Matching against NaN should result in a warning
+
+#![allow(unused)]
+#![deny(illegal_floating_point_literal_pattern)]
+
+const NAN: f64 = f64::NAN;
+
+fn main() {
+    let x = NAN;
+    match x {
+        NAN => {}, //~ ERROR floating-point types cannot be used
+        //~| WARN this was previously accepted by the compiler but is being phased out
+        _ => {},
+    };
+
+    match [x, 1.0] {
+        [NAN, _] => {}, //~ ERROR floating-point types cannot be used
+        //~| WARN this was previously accepted by the compiler but is being phased out
+        _ => {},
+    };
+}
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr b/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr
new file mode 100644 (file)
index 0000000..4e2961e
--- /dev/null
@@ -0,0 +1,25 @@
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-6804.rs:11:9
+   |
+LL |         NAN => {},
+   |         ^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-6804.rs:4:9
+   |
+LL | #![deny(illegal_floating_point_literal_pattern)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-6804.rs:17:10
+   |
+LL |         [NAN, _] => {},
+   |          ^^^
+   |
+   = 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 2 previous errors
+
index 34cd1d2b1074d837610e08bca6d5e547da91debb..efe46d7e81d3de1ea8759a1acd7aead7f7c1948f 100644 (file)
@@ -51,9 +51,6 @@ LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
 error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied
   --> $DIR/const-drop-fail.rs:49:5
    |
-LL |         const _: () = check($exp);
-   |                       ----- required by a bound introduced by this call
-...
 LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop`
    |
index 34cd1d2b1074d837610e08bca6d5e547da91debb..efe46d7e81d3de1ea8759a1acd7aead7f7c1948f 100644 (file)
@@ -51,9 +51,6 @@ LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
 error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied
   --> $DIR/const-drop-fail.rs:49:5
    |
-LL |         const _: () = check($exp);
-   |                       ----- required by a bound introduced by this call
-...
 LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop`
    |
index 1d3a2ff82845ef74b6769045d765fc5e02b1c5e1..dc193582c6a50bec8fe0184eb0a6a5bcc6fecc52 100644 (file)
@@ -25,6 +25,6 @@ fn main() {
     println!("{:#?}", output);
     let stderr = std::str::from_utf8(&output.stderr);
     assert!(stderr.map(|v| {
-        v.ends_with("drop of the panic payload panicked")
+        v.ends_with("fatal runtime error: drop of the panic payload panicked\n")
     }).unwrap_or(false));
 }
index 2545231a1712c2f75b59900fc8e64afaaf25d913..7e008d46574c644af2de80239f86cfb985d424cd 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
+error[E0659]: `std` is ambiguous
   --> $DIR/ambiguity-macros-nested.rs:8:13
    |
 LL |     pub use std::io;
    |             ^^^ ambiguous name
    |
+   = note: ambiguous because of multiple potential import sources
    = note: `std` could refer to a built-in crate
    = help: use `::std` to refer to this crate unambiguously
 note: `std` could also refer to the module defined here
index af45cd81a3b106a684e114c196cfe674f0449b55..771d2c10c1da2fbe3ddbb63193d22302bce54264 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
+error[E0659]: `std` is ambiguous
   --> $DIR/ambiguity-macros.rs:7:5
    |
 LL | use std::io;
    |     ^^^ ambiguous name
    |
+   = note: ambiguous because of multiple potential import sources
    = note: `std` could refer to a built-in crate
    = help: use `::std` to refer to this crate unambiguously
 note: `std` could also refer to the module defined here
index 4129930bdb0fdaa233475080f104b7a8d77e86ac..defb16f79703848400134bada7f2aa1d43f7efe4 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
+error[E0659]: `std` is ambiguous
   --> $DIR/ambiguity-nested.rs:8:13
    |
 LL |     pub use std::io;
    |             ^^^ ambiguous name
    |
+   = note: ambiguous because of multiple potential import sources
    = note: `std` could refer to a built-in crate
    = help: use `::std` to refer to this crate unambiguously
 note: `std` could also refer to the module defined here
index e123b323e7c574fad59b6a07c4cc34787be779fd..2d735c7e3fdfe25c0edf6c732d38e238c696aeb4 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
+error[E0659]: `std` is ambiguous
   --> $DIR/ambiguity.rs:5:5
    |
 LL | use std::io;
    |     ^^^ ambiguous name
    |
+   = note: ambiguous because of multiple potential import sources
    = note: `std` could refer to a built-in crate
    = help: use `::std` to refer to this crate unambiguously
 note: `std` could also refer to the module defined here
index db176876382d6fab84f2509cac68e79d6f1251cc..3d45a81402940a2d9a1d7bf76f4802e002e01569 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `sub` is ambiguous (name vs any other name during import resolution)
+error[E0659]: `sub` is ambiguous
   --> $DIR/block-scoped-shadow-nested.rs:16:13
    |
 LL |         use sub::bar;
    |             ^^^ ambiguous name
    |
+   = note: ambiguous because of multiple potential import sources
 note: `sub` could refer to the module imported here
   --> $DIR/block-scoped-shadow-nested.rs:14:9
    |
index 2767d9ee77e4293fd6a99f814a3ab23a6c1af24a..b068312cedd6fc9871b2e3d0a7c7bdd500e072d0 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `Foo` is ambiguous (name vs any other name during import resolution)
+error[E0659]: `Foo` is ambiguous
   --> $DIR/block-scoped-shadow.rs:11:9
    |
 LL |     use Foo::*;
    |         ^^^ ambiguous name
    |
+   = note: ambiguous because of multiple potential import sources
 note: `Foo` could refer to the enum defined here
   --> $DIR/block-scoped-shadow.rs:10:5
    |
@@ -16,12 +17,13 @@ LL | enum Foo {}
    | ^^^^^^^^^^^
    = help: use `crate::Foo` to refer to this enum unambiguously
 
-error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
+error[E0659]: `std` is ambiguous
   --> $DIR/block-scoped-shadow.rs:18:9
    |
 LL |     use std as foo;
    |         ^^^ ambiguous name
    |
+   = note: ambiguous because of multiple potential import sources
 note: `std` could refer to the enum defined here
   --> $DIR/block-scoped-shadow.rs:17:5
    |
@@ -34,12 +36,13 @@ LL | struct std;
    | ^^^^^^^^^^^
    = help: use `crate::std` to refer to this struct unambiguously
 
-error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
+error[E0659]: `std` is ambiguous
   --> $DIR/block-scoped-shadow.rs:18:9
    |
 LL |     use std as foo;
    |         ^^^ ambiguous name
    |
+   = note: ambiguous because of multiple potential import sources
 note: `std` could refer to the function defined here
   --> $DIR/block-scoped-shadow.rs:16:5
    |
index e39840d34d9f70c7651e9bf470b54fdb2c0f308a..d2297385f33deb8f007027f16460f011a4e6fd8d 100644 (file)
@@ -1,9 +1,10 @@
-error[E0659]: `issue_56596` is ambiguous (name vs any other name during import resolution)
+error[E0659]: `issue_56596` is ambiguous
   --> $DIR/issue-56596.rs:12:5
    |
 LL | use issue_56596;
    |     ^^^^^^^^^^^ ambiguous name
    |
+   = note: ambiguous because of multiple potential import sources
    = note: `issue_56596` could refer to a crate passed with `--extern`
    = help: use `::issue_56596` to refer to this crate unambiguously
 note: `issue_56596` could also refer to the module imported here
index f1b5e0c5efaac3a441f8e900d42530ec420fff9a..622595bfa0328cba4f449f5448db1373bcd6f130 100644 (file)
@@ -10,12 +10,13 @@ note: consider marking `legacy_macro` as `pub` in the imported module
 LL |     pub use legacy_macro as _;
    |             ^^^^^^^^^^^^^^^^^
 
-error[E0659]: `legacy_macro` is ambiguous (name vs any other name during import resolution)
+error[E0659]: `legacy_macro` is ambiguous
   --> $DIR/macro-rules.rs:31:13
    |
 LL |         use legacy_macro as _;
    |             ^^^^^^^^^^^^ ambiguous name
    |
+   = note: ambiguous because of multiple potential import sources
 note: `legacy_macro` could refer to the macro defined here
   --> $DIR/macro-rules.rs:28:9
    |
index 2d306eb920cc157a60c29e3f996980447617d839..fd7fc7fbd41b774dfc6ba266d2edd8f1d3825284 100644 (file)
@@ -13,8 +13,8 @@ mod bar {
 }
 
 fn main() {
-    io::stdout();
-    self::std::io::stdout();
-    foo::my_std::io::stdout();
-    bar::std::io::stdout();
+    let _ = io::stdout();
+    let _ = self::std::io::stdout();
+    let _ = foo::my_std::io::stdout();
+    let _ = bar::std::io::stdout();
 }
index e4662b430dccc7bdd9131fc4996955c95b5fde11..d945b4c94ca2f128d6d628484b6d24bd519b11bc 100644 (file)
@@ -15,6 +15,7 @@ LL |     fn try_into(self) -> Result<T, Self::Error>;
    |        the method is available for `Rc<u8>` here
    |
    = help: items from traits can only be used if the trait is in scope
+   = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021
 help: consider wrapping the receiver expression with the appropriate type
    |
 LL |         let _: u32 = Box::new(3u8).try_into().unwrap();
index 3a9fd69322869518567d41a2e18f556ac1cdbc88..a63b6fcf2627ab8294f0a0e050b63a466c3bdf16 100644 (file)
@@ -1,6 +1,5 @@
 // check-pass
 // edition:2021
-// compile-flags: -Zunstable-options
 
 fn main() {
     let _: u16 = 123i32.try_into().unwrap();
index e026f01e93fb038027d0b773c7a4ff53f709e42e..eed2f313abe6ec70ced488c3246db67e05f4dab7 100644 (file)
@@ -1,6 +1,6 @@
 // check-pass
 // run-rustfix
-// compile-flags: -Z unstable-options --edition 2018
+// edition:2018
 
 #![warn(rust_2021_prefixes_incompatible_syntax)]
 
index d24f29634806d9d70cee029979f0a6258a7b8869..0565db793df66accbff7d51319f204b0fb307197 100644 (file)
@@ -1,6 +1,6 @@
 // check-pass
 // run-rustfix
-// compile-flags: -Z unstable-options --edition 2018
+// edition:2018
 
 #![warn(rust_2021_prefixes_incompatible_syntax)]
 
diff --git a/src/test/ui/self/issue-61882-2.rs b/src/test/ui/self/issue-61882-2.rs
new file mode 100644 (file)
index 0000000..1209b54
--- /dev/null
@@ -0,0 +1,11 @@
+struct A<T>(T);
+
+impl A<&'static u8> {
+    fn f() {
+        let x = 0;
+        Self(&x);
+        //~^ ERROR `x` does not live long enough
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/self/issue-61882-2.stderr b/src/test/ui/self/issue-61882-2.stderr
new file mode 100644 (file)
index 0000000..0b8e134
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/issue-61882-2.rs:6:14
+   |
+LL |         Self(&x);
+   |              ^^
+   |              |
+   |              borrowed value does not live long enough
+   |              this usage requires that `x` is borrowed for `'static`
+LL |
+LL |     }
+   |     - `x` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/self/issue-61882.rs b/src/test/ui/self/issue-61882.rs
new file mode 100644 (file)
index 0000000..013398b
--- /dev/null
@@ -0,0 +1,9 @@
+struct A<T>(T);
+
+impl A<bool> {
+    const B: A<u8> = Self(0);
+    //~^ ERROR mismatched types
+    //~| ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/self/issue-61882.stderr b/src/test/ui/self/issue-61882.stderr
new file mode 100644 (file)
index 0000000..09ffe8e
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-61882.rs:4:27
+   |
+LL |     const B: A<u8> = Self(0);
+   |                           ^ expected `bool`, found integer
+
+error[E0308]: mismatched types
+  --> $DIR/issue-61882.rs:4:22
+   |
+LL |     const B: A<u8> = Self(0);
+   |                      ^^^^^^^ expected `u8`, found `bool`
+   |
+   = note: expected struct `A<u8>`
+              found struct `A<bool>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/signal-exit-status.rs b/src/test/ui/signal-exit-status.rs
deleted file mode 100644 (file)
index 0963dcc..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// run-pass
-// ignore-emscripten no processes
-// ignore-sgx no processes
-// ignore-windows
-
-use std::env;
-use std::process::Command;
-
-pub fn main() {
-    let args: Vec<String> = env::args().collect();
-    if args.len() >= 2 && args[1] == "signal" {
-        // Raise a segfault.
-        unsafe { *(1 as *mut isize) = 0; }
-    } else {
-        let status = Command::new(&args[0]).arg("signal").status().unwrap();
-        assert!(status.code().is_none());
-    }
-}
diff --git a/src/test/ui/specialization/transmute-specialization.rs b/src/test/ui/specialization/transmute-specialization.rs
new file mode 100644 (file)
index 0000000..499334d
--- /dev/null
@@ -0,0 +1,15 @@
+// run-pass
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Specializable { type Output; }
+
+impl<T> Specializable for T {
+    default type Output = u16;
+}
+
+fn main() {
+    unsafe {
+        std::mem::transmute::<u16, <() as Specializable>::Output>(0);
+    }
+}
diff --git a/src/test/ui/specialization/transmute-specialization.stderr b/src/test/ui/specialization/transmute-specialization.stderr
new file mode 100644 (file)
index 0000000..a0ea724
--- /dev/null
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/transmute-specialization.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+
+warning: 1 warning emitted
+
index 656564fc9e3f8240d66f64182bd4f4e955a47499..ce2726ffde48737c93ce3f6e36804c3d2e8f3d0b 100644 (file)
@@ -1,27 +1,28 @@
 #![feature(staged_api)]
+//~^ ERROR module has missing stability attribute
 
-#[stable(feature = "x", since = "1")]
+#[stable(feature = "a", since = "1")]
 struct StableType;
 
-#[unstable(feature = "x", issue = "none")]
+#[unstable(feature = "b", issue = "none")]
 struct UnstableType;
 
-#[stable(feature = "x", since = "1")]
+#[stable(feature = "c", since = "1")]
 trait StableTrait {}
 
-#[unstable(feature = "x", issue = "none")]
+#[unstable(feature = "d", issue = "none")]
 trait UnstableTrait {}
 
-#[unstable(feature = "x", issue = "none")]
+#[unstable(feature = "e", issue = "none")]
 impl UnstableTrait for UnstableType {}
 
-#[unstable(feature = "x", issue = "none")]
+#[unstable(feature = "f", issue = "none")]
 impl StableTrait for UnstableType {}
 
-#[unstable(feature = "x", issue = "none")]
+#[unstable(feature = "g", issue = "none")]
 impl UnstableTrait for StableType {}
 
-#[unstable(feature = "x", issue = "none")]
+#[unstable(feature = "h", issue = "none")]
 //~^ ERROR an `#[unstable]` annotation here has no effect [ineffective_unstable_trait_impl]
 impl StableTrait for StableType {}
 
index a11479cc8f45cdba0c33c82bbdb8c74776c8ed9d..310f02024ca0a02b6f1a5e0e2eb5841fa9d3ed15 100644 (file)
@@ -1,11 +1,23 @@
 error: an `#[unstable]` annotation here has no effect
-  --> $DIR/stability-attribute-trait-impl.rs:24:1
+  --> $DIR/stability-attribute-trait-impl.rs:25:1
    |
-LL | #[unstable(feature = "x", issue = "none")]
+LL | #[unstable(feature = "h", issue = "none")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[deny(ineffective_unstable_trait_impl)]` on by default
    = note: see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information
 
-error: aborting due to previous error
+error: module has missing stability attribute
+  --> $DIR/stability-attribute-trait-impl.rs:1:1
+   |
+LL | / #![feature(staged_api)]
+LL | |
+LL | |
+LL | | #[stable(feature = "a", since = "1")]
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/static/auxiliary/nested_item.rs b/src/test/ui/static/auxiliary/nested_item.rs
new file mode 100644 (file)
index 0000000..9db9d19
--- /dev/null
@@ -0,0 +1,30 @@
+// original problem
+pub fn foo<T>() -> isize {
+    {
+        static foo: isize = 2;
+        foo
+    }
+}
+
+// issue 8134
+struct Foo;
+impl Foo {
+    pub fn foo<T>(&self) {
+        static X: usize = 1;
+    }
+}
+
+// issue 8134
+pub struct Parser<T>(T);
+impl<T: std::iter::Iterator<Item=char>> Parser<T> {
+    fn in_doctype(&mut self) {
+        static DOCTYPEPattern: [char; 6] = ['O', 'C', 'T', 'Y', 'P', 'E'];
+    }
+}
+
+struct Bar;
+impl Foo {
+    pub fn bar<T>(&self) {
+        static X: usize = 1;
+    }
+}
diff --git a/src/test/ui/static/nested_item_main.rs b/src/test/ui/static/nested_item_main.rs
new file mode 100644 (file)
index 0000000..2fe00ae
--- /dev/null
@@ -0,0 +1,10 @@
+// run-pass
+// aux-build:nested_item.rs
+
+
+extern crate nested_item;
+
+pub fn main() {
+    assert_eq!(2, nested_item::foo::<()>());
+    assert_eq!(2, nested_item::foo::<isize>());
+}
diff --git a/src/test/ui/statics/issue-14227.mir.stderr b/src/test/ui/statics/issue-14227.mir.stderr
new file mode 100644 (file)
index 0000000..8e7a251
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: use of extern static is unsafe and requires unsafe function or block
+  --> $DIR/issue-14227.rs:7:21
+   |
+LL | static CRASH: u32 = symbol;
+   |                     ^^^^^^ use of extern static
+   |
+   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/statics/issue-14227.rs b/src/test/ui/statics/issue-14227.rs
new file mode 100644 (file)
index 0000000..5f866ec
--- /dev/null
@@ -0,0 +1,10 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+extern "C" {
+    pub static symbol: u32;
+}
+static CRASH: u32 = symbol;
+//~^ ERROR use of extern static is unsafe and requires
+
+fn main() {}
diff --git a/src/test/ui/statics/issue-14227.thir.stderr b/src/test/ui/statics/issue-14227.thir.stderr
new file mode 100644 (file)
index 0000000..8e7a251
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: use of extern static is unsafe and requires unsafe function or block
+  --> $DIR/issue-14227.rs:7:21
+   |
+LL | static CRASH: u32 = symbol;
+   |                     ^^^^^^ use of extern static
+   |
+   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
index cc78f6cfa53f7127282038e0aaf1990424e8812f..d5645474891062e2a43bddacdcf8fbe0ab450e7f 100644 (file)
@@ -11,7 +11,11 @@ enum Void {}
 
 static VOID2: Void = unsafe { std::mem::transmute(()) }; //~ ERROR static of uninhabited type
 //~| WARN: previously accepted
+//~| ERROR undefined behavior to use this value
+//~| WARN: type `Void` does not permit zero-initialization
 static NEVER2: Void = unsafe { std::mem::transmute(()) }; //~ ERROR static of uninhabited type
 //~| WARN: previously accepted
+//~| ERROR undefined behavior to use this value
+//~| WARN: type `Void` does not permit zero-initialization
 
 fn main() {}
index 5d95b29993827ff6b005f528373bafb9b35dc452..c38cf10d6e648bfad53cb16009a3d2c4c5759329 100644 (file)
@@ -34,7 +34,7 @@ LL | static VOID2: Void = unsafe { std::mem::transmute(()) };
    = note: uninhabited statics cannot be initialized, and any access would be an immediate error
 
 error: static of uninhabited type
-  --> $DIR/uninhabited-static.rs:14:1
+  --> $DIR/uninhabited-static.rs:16:1
    |
 LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -43,5 +43,47 @@ LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
    = note: for more information, see issue #74840 <https://github.com/rust-lang/rust/issues/74840>
    = note: uninhabited statics cannot be initialized, and any access would be an immediate error
 
-error: aborting due to 4 previous errors
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/uninhabited-static.rs:12:1
+   |
+LL | static VOID2: Void = unsafe { std::mem::transmute(()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Void
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+   = note: the raw bytes of the constant (size: 0, align: 1) {}
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/uninhabited-static.rs:16:1
+   |
+LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Void
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+   = note: the raw bytes of the constant (size: 0, align: 1) {}
+
+warning: the type `Void` does not permit zero-initialization
+  --> $DIR/uninhabited-static.rs:12:31
+   |
+LL | static VOID2: Void = unsafe { std::mem::transmute(()) };
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^
+   |                               |
+   |                               this code causes undefined behavior when executed
+   |                               help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+   |
+   = note: `#[warn(invalid_value)]` on by default
+   = note: enums with no variants have no valid value
+
+warning: the type `Void` does not permit zero-initialization
+  --> $DIR/uninhabited-static.rs:16:32
+   |
+LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^
+   |                                |
+   |                                this code causes undefined behavior when executed
+   |                                help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+   |
+   = note: enums with no variants have no valid value
+
+error: aborting due to 6 previous errors; 2 warnings emitted
 
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/structs-enums/issue-50731.rs b/src/test/ui/structs-enums/issue-50731.rs
new file mode 100644 (file)
index 0000000..209c1e1
--- /dev/null
@@ -0,0 +1,6 @@
+// run-pass
+enum Void {}
+fn foo(_: Result<(Void, u32), (Void, String)>) {}
+fn main() {
+    let _: fn(_) = foo;
+}
index cc6412e271a132825e6498267211a4e0235d1468..3bc2d16cf9df2a3c09b7a9f3bd3b0c44d90390b2 100644 (file)
@@ -36,6 +36,7 @@ struct Outer {
           target_os = "emscripten",
           target_os = "freebsd",
           target_os = "fuchsia",
+          target_os = "illumos",
           target_os = "linux",
           target_os = "macos",
           target_os = "netbsd",
diff --git a/src/test/ui/structured-compare.rs b/src/test/ui/structured-compare.rs
deleted file mode 100644 (file)
index 63d30c4..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// run-pass
-
-#![allow(non_camel_case_types)]
-
-
-#[derive(Copy, Clone, Debug)]
-enum foo { large, small, }
-
-impl PartialEq for foo {
-    fn eq(&self, other: &foo) -> bool {
-        ((*self) as usize) == ((*other) as usize)
-    }
-    fn ne(&self, other: &foo) -> bool { !(*self).eq(other) }
-}
-
-pub fn main() {
-    let a = (1, 2, 3);
-    let b = (1, 2, 3);
-    assert_eq!(a, b);
-    assert!((a != (1, 2, 4)));
-    assert!((a < (1, 2, 4)));
-    assert!((a <= (1, 2, 4)));
-    assert!(((1, 2, 4) > a));
-    assert!(((1, 2, 4) >= a));
-    let x = foo::large;
-    let y = foo::small;
-    assert!((x != y));
-    assert_eq!(x, foo::large);
-    assert!((x != foo::small));
-}
diff --git a/src/test/ui/suggestions/boxed-variant-field.rs b/src/test/ui/suggestions/boxed-variant-field.rs
new file mode 100644 (file)
index 0000000..d8f7fac
--- /dev/null
@@ -0,0 +1,16 @@
+enum Ty {
+    Unit,
+    List(Box<Ty>),
+}
+
+fn foo(x: Ty) -> Ty {
+    match x {
+        Ty::Unit => Ty::Unit,
+        Ty::List(elem) => foo(elem),
+        //~^ ERROR mismatched types
+        //~| HELP try dereferencing the `Box`
+        //~| HELP try using a variant of the expected enum
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/boxed-variant-field.stderr b/src/test/ui/suggestions/boxed-variant-field.stderr
new file mode 100644 (file)
index 0000000..d4ccb2c
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+  --> $DIR/boxed-variant-field.rs:9:31
+   |
+LL |         Ty::List(elem) => foo(elem),
+   |                               ^^^^ expected enum `Ty`, found struct `Box`
+   |
+   = note: expected enum `Ty`
+            found struct `Box<Ty>`
+help: try dereferencing the `Box`
+   |
+LL |         Ty::List(elem) => foo(*elem),
+   |                               +
+help: try using a variant of the expected enum
+   |
+LL |         Ty::List(elem) => foo(Ty::List(elem)),
+   |                               ~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
index 263d509075af8058f258103ee9ef2f0caeb7bea1..0d9ecc32e08cdd6c75b47cf425955da9ffed7ddc 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `&str: From<String>` is not satisfied
-  --> $DIR/into-str.rs:4:5
+  --> $DIR/into-str.rs:4:9
    |
 LL |     foo(String::new());
-   |     ^^^ the trait `From<String>` is not implemented for `&str`
+   |     --- ^^^^^^^^^^^^^ the trait `From<String>` is not implemented for `&str`
+   |     |
+   |     required by a bound introduced by this call
    |
    = note: to coerce a `String` into a `&str`, use `&*` as a prefix
    = note: required because of the requirements on the impl of `Into<&str>` for `String`
diff --git a/src/test/ui/suggestions/suggest-tryinto-edition-change.rs b/src/test/ui/suggestions/suggest-tryinto-edition-change.rs
new file mode 100644 (file)
index 0000000..f03b42b
--- /dev/null
@@ -0,0 +1,31 @@
+// Make sure that trying to access `TryInto`, `TryFrom`, `FromIterator` in pre-2021 mentions
+// Edition 2021 change
+// edition:2018
+
+fn test() {
+    let _i: i16 = 0_i32.try_into().unwrap();
+    //~^ ERROR no method named `try_into` found for type `i32` in the current scope
+    //~| NOTE method not found in `i32`
+    //~| NOTE 'std::convert::TryInto' is included in the prelude starting in Edition 2021
+
+    let _i: i16 = TryFrom::try_from(0_i32).unwrap();
+    //~^ ERROR failed to resolve: use of undeclared type
+    //~| NOTE not found in this scope
+    //~| NOTE 'std::convert::TryFrom' is included in the prelude starting in Edition 2021
+    //~| NOTE 'core::convert::TryFrom' is included in the prelude starting in Edition 2021
+
+    let _i: i16 = TryInto::try_into(0_i32).unwrap();
+    //~^ ERROR failed to resolve: use of undeclared type
+    //~| NOTE not found in this scope
+    //~| NOTE 'std::convert::TryInto' is included in the prelude starting in Edition 2021
+    //~| NOTE 'core::convert::TryInto' is included in the prelude starting in Edition 2021
+
+    let _v: Vec<_> = FromIterator::from_iter(&[1]);
+    //~^ ERROR failed to resolve: use of undeclared type
+    //~| NOTE 'std::iter::FromIterator' is included in the prelude starting in Edition 2021
+    //~| NOTE 'core::iter::FromIterator' is included in the prelude starting in Edition 2021
+}
+
+fn main() {
+    test();
+}
diff --git a/src/test/ui/suggestions/suggest-tryinto-edition-change.stderr b/src/test/ui/suggestions/suggest-tryinto-edition-change.stderr
new file mode 100644 (file)
index 0000000..86f4871
--- /dev/null
@@ -0,0 +1,76 @@
+error[E0433]: failed to resolve: use of undeclared type `TryFrom`
+  --> $DIR/suggest-tryinto-edition-change.rs:11:19
+   |
+LL |     let _i: i16 = TryFrom::try_from(0_i32).unwrap();
+   |                   ^^^^^^^ not found in this scope
+   |
+   = note: 'std::convert::TryFrom' is included in the prelude starting in Edition 2021
+   = note: 'core::convert::TryFrom' is included in the prelude starting in Edition 2021
+help: consider importing one of these items
+   |
+LL | use core::convert::TryFrom;
+   |
+LL | use std::convert::TryFrom;
+   |
+
+error[E0433]: failed to resolve: use of undeclared type `TryInto`
+  --> $DIR/suggest-tryinto-edition-change.rs:17:19
+   |
+LL |     let _i: i16 = TryInto::try_into(0_i32).unwrap();
+   |                   ^^^^^^^ not found in this scope
+   |
+   = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021
+   = note: 'core::convert::TryInto' is included in the prelude starting in Edition 2021
+help: consider importing one of these items
+   |
+LL | use core::convert::TryInto;
+   |
+LL | use std::convert::TryInto;
+   |
+
+error[E0433]: failed to resolve: use of undeclared type `FromIterator`
+  --> $DIR/suggest-tryinto-edition-change.rs:23:22
+   |
+LL |     let _v: Vec<_> = FromIterator::from_iter(&[1]);
+   |                      ^^^^^^^^^^^^
+   |
+  ::: $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL | pub trait IntoIterator {
+   | ---------------------- similarly named trait `IntoIterator` defined here
+   |
+   = note: 'std::iter::FromIterator' is included in the prelude starting in Edition 2021
+   = note: 'core::iter::FromIterator' is included in the prelude starting in Edition 2021
+help: a trait with a similar name exists
+   |
+LL |     let _v: Vec<_> = IntoIterator::from_iter(&[1]);
+   |                      ~~~~~~~~~~~~
+help: consider importing one of these items
+   |
+LL | use core::iter::FromIterator;
+   |
+LL | use std::iter::FromIterator;
+   |
+
+error[E0599]: no method named `try_into` found for type `i32` in the current scope
+  --> $DIR/suggest-tryinto-edition-change.rs:6:25
+   |
+LL |     let _i: i16 = 0_i32.try_into().unwrap();
+   |                         ^^^^^^^^ method not found in `i32`
+   |
+  ::: $SRC_DIR/core/src/convert/mod.rs:LL:COL
+   |
+LL |     fn try_into(self) -> Result<T, Self::Error>;
+   |        -------- the method is available for `i32` here
+   |
+   = help: items from traits can only be used if the trait is in scope
+   = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+   |
+LL | use std::convert::TryInto;
+   |
+
+error: aborting due to 4 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/suggestions/undeclared-module-alloc.rs b/src/test/ui/suggestions/undeclared-module-alloc.rs
new file mode 100644 (file)
index 0000000..1defa1c
--- /dev/null
@@ -0,0 +1,5 @@
+// edition:2018
+
+use alloc::rc::Rc; //~ ERROR failed to resolve: use of undeclared crate or module `alloc`
+
+fn main() {}
diff --git a/src/test/ui/suggestions/undeclared-module-alloc.stderr b/src/test/ui/suggestions/undeclared-module-alloc.stderr
new file mode 100644 (file)
index 0000000..39169df
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0433]: failed to resolve: use of undeclared crate or module `alloc`
+  --> $DIR/undeclared-module-alloc.rs:3:5
+   |
+LL | use alloc::rc::Rc;
+   |     ^^^^^ use of undeclared crate or module `alloc`
+   |
+   = help: add `extern crate alloc` to use the `alloc` crate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/supported-cast.rs b/src/test/ui/supported-cast.rs
deleted file mode 100644 (file)
index ff41ce6..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-// run-pass
-
-pub fn main() {
-  let f = 1_usize as *const String;
-  println!("{:?}", f as isize);
-  println!("{:?}", f as usize);
-  println!("{:?}", f as i8);
-  println!("{:?}", f as i16);
-  println!("{:?}", f as i32);
-  println!("{:?}", f as i64);
-  println!("{:?}", f as u8);
-  println!("{:?}", f as u16);
-  println!("{:?}", f as u32);
-  println!("{:?}", f as u64);
-
-  println!("{:?}", 1 as isize);
-  println!("{:?}", 1 as usize);
-  println!("{:?}", 1 as *const String);
-  println!("{:?}", 1 as i8);
-  println!("{:?}", 1 as i16);
-  println!("{:?}", 1 as i32);
-  println!("{:?}", 1 as i64);
-  println!("{:?}", 1 as u8);
-  println!("{:?}", 1 as u16);
-  println!("{:?}", 1 as u32);
-  println!("{:?}", 1 as u64);
-  println!("{:?}", 1 as f32);
-  println!("{:?}", 1 as f64);
-
-  println!("{:?}", 1_usize as isize);
-  println!("{:?}", 1_usize as usize);
-  println!("{:?}", 1_usize as *const String);
-  println!("{:?}", 1_usize as i8);
-  println!("{:?}", 1_usize as i16);
-  println!("{:?}", 1_usize as i32);
-  println!("{:?}", 1_usize as i64);
-  println!("{:?}", 1_usize as u8);
-  println!("{:?}", 1_usize as u16);
-  println!("{:?}", 1_usize as u32);
-  println!("{:?}", 1_usize as u64);
-  println!("{:?}", 1_usize as f32);
-  println!("{:?}", 1_usize as f64);
-
-  println!("{:?}", 1i8 as isize);
-  println!("{:?}", 1i8 as usize);
-  println!("{:?}", 1i8 as *const String);
-  println!("{:?}", 1i8 as i8);
-  println!("{:?}", 1i8 as i16);
-  println!("{:?}", 1i8 as i32);
-  println!("{:?}", 1i8 as i64);
-  println!("{:?}", 1i8 as u8);
-  println!("{:?}", 1i8 as u16);
-  println!("{:?}", 1i8 as u32);
-  println!("{:?}", 1i8 as u64);
-  println!("{:?}", 1i8 as f32);
-  println!("{:?}", 1i8 as f64);
-
-  println!("{:?}", 1u8 as isize);
-  println!("{:?}", 1u8 as usize);
-  println!("{:?}", 1u8 as *const String);
-  println!("{:?}", 1u8 as i8);
-  println!("{:?}", 1u8 as i16);
-  println!("{:?}", 1u8 as i32);
-  println!("{:?}", 1u8 as i64);
-  println!("{:?}", 1u8 as u8);
-  println!("{:?}", 1u8 as u16);
-  println!("{:?}", 1u8 as u32);
-  println!("{:?}", 1u8 as u64);
-  println!("{:?}", 1u8 as f32);
-  println!("{:?}", 1u8 as f64);
-
-  println!("{:?}", 1i16 as isize);
-  println!("{:?}", 1i16 as usize);
-  println!("{:?}", 1i16 as *const String);
-  println!("{:?}", 1i16 as i8);
-  println!("{:?}", 1i16 as i16);
-  println!("{:?}", 1i16 as i32);
-  println!("{:?}", 1i16 as i64);
-  println!("{:?}", 1i16 as u8);
-  println!("{:?}", 1i16 as u16);
-  println!("{:?}", 1i16 as u32);
-  println!("{:?}", 1i16 as u64);
-  println!("{:?}", 1i16 as f32);
-  println!("{:?}", 1i16 as f64);
-
-  println!("{:?}", 1u16 as isize);
-  println!("{:?}", 1u16 as usize);
-  println!("{:?}", 1u16 as *const String);
-  println!("{:?}", 1u16 as i8);
-  println!("{:?}", 1u16 as i16);
-  println!("{:?}", 1u16 as i32);
-  println!("{:?}", 1u16 as i64);
-  println!("{:?}", 1u16 as u8);
-  println!("{:?}", 1u16 as u16);
-  println!("{:?}", 1u16 as u32);
-  println!("{:?}", 1u16 as u64);
-  println!("{:?}", 1u16 as f32);
-  println!("{:?}", 1u16 as f64);
-
-  println!("{:?}", 1i32 as isize);
-  println!("{:?}", 1i32 as usize);
-  println!("{:?}", 1i32 as *const String);
-  println!("{:?}", 1i32 as i8);
-  println!("{:?}", 1i32 as i16);
-  println!("{:?}", 1i32 as i32);
-  println!("{:?}", 1i32 as i64);
-  println!("{:?}", 1i32 as u8);
-  println!("{:?}", 1i32 as u16);
-  println!("{:?}", 1i32 as u32);
-  println!("{:?}", 1i32 as u64);
-  println!("{:?}", 1i32 as f32);
-  println!("{:?}", 1i32 as f64);
-
-  println!("{:?}", 1u32 as isize);
-  println!("{:?}", 1u32 as usize);
-  println!("{:?}", 1u32 as *const String);
-  println!("{:?}", 1u32 as i8);
-  println!("{:?}", 1u32 as i16);
-  println!("{:?}", 1u32 as i32);
-  println!("{:?}", 1u32 as i64);
-  println!("{:?}", 1u32 as u8);
-  println!("{:?}", 1u32 as u16);
-  println!("{:?}", 1u32 as u32);
-  println!("{:?}", 1u32 as u64);
-  println!("{:?}", 1u32 as f32);
-  println!("{:?}", 1u32 as f64);
-
-  println!("{:?}", 1i64 as isize);
-  println!("{:?}", 1i64 as usize);
-  println!("{:?}", 1i64 as *const String);
-  println!("{:?}", 1i64 as i8);
-  println!("{:?}", 1i64 as i16);
-  println!("{:?}", 1i64 as i32);
-  println!("{:?}", 1i64 as i64);
-  println!("{:?}", 1i64 as u8);
-  println!("{:?}", 1i64 as u16);
-  println!("{:?}", 1i64 as u32);
-  println!("{:?}", 1i64 as u64);
-  println!("{:?}", 1i64 as f32);
-  println!("{:?}", 1i64 as f64);
-
-  println!("{:?}", 1u64 as isize);
-  println!("{:?}", 1u64 as usize);
-  println!("{:?}", 1u64 as *const String);
-  println!("{:?}", 1u64 as i8);
-  println!("{:?}", 1u64 as i16);
-  println!("{:?}", 1u64 as i32);
-  println!("{:?}", 1u64 as i64);
-  println!("{:?}", 1u64 as u8);
-  println!("{:?}", 1u64 as u16);
-  println!("{:?}", 1u64 as u32);
-  println!("{:?}", 1u64 as u64);
-  println!("{:?}", 1u64 as f32);
-  println!("{:?}", 1u64 as f64);
-
-  println!("{:?}", 1u64 as isize);
-  println!("{:?}", 1u64 as usize);
-  println!("{:?}", 1u64 as *const String);
-  println!("{:?}", 1u64 as i8);
-  println!("{:?}", 1u64 as i16);
-  println!("{:?}", 1u64 as i32);
-  println!("{:?}", 1u64 as i64);
-  println!("{:?}", 1u64 as u8);
-  println!("{:?}", 1u64 as u16);
-  println!("{:?}", 1u64 as u32);
-  println!("{:?}", 1u64 as u64);
-  println!("{:?}", 1u64 as f32);
-  println!("{:?}", 1u64 as f64);
-
-  println!("{:?}", true as isize);
-  println!("{:?}", true as usize);
-  println!("{:?}", true as i8);
-  println!("{:?}", true as i16);
-  println!("{:?}", true as i32);
-  println!("{:?}", true as i64);
-  println!("{:?}", true as u8);
-  println!("{:?}", true as u16);
-  println!("{:?}", true as u32);
-  println!("{:?}", true as u64);
-
-  println!("{:?}", 1f32 as isize);
-  println!("{:?}", 1f32 as usize);
-  println!("{:?}", 1f32 as i8);
-  println!("{:?}", 1f32 as i16);
-  println!("{:?}", 1f32 as i32);
-  println!("{:?}", 1f32 as i64);
-  println!("{:?}", 1f32 as u8);
-  println!("{:?}", 1f32 as u16);
-  println!("{:?}", 1f32 as u32);
-  println!("{:?}", 1f32 as u64);
-  println!("{:?}", 1f32 as f32);
-  println!("{:?}", 1f32 as f64);
-
-  println!("{:?}", 1f64 as isize);
-  println!("{:?}", 1f64 as usize);
-  println!("{:?}", 1f64 as i8);
-  println!("{:?}", 1f64 as i16);
-  println!("{:?}", 1f64 as i32);
-  println!("{:?}", 1f64 as i64);
-  println!("{:?}", 1f64 as u8);
-  println!("{:?}", 1f64 as u16);
-  println!("{:?}", 1f64 as u32);
-  println!("{:?}", 1f64 as u64);
-  println!("{:?}", 1f64 as f32);
-  println!("{:?}", 1f64 as f64);
-}
diff --git a/src/test/ui/svh/auxiliary/changing-crates-a1.rs b/src/test/ui/svh/auxiliary/changing-crates-a1.rs
new file mode 100644 (file)
index 0000000..bc0559b
--- /dev/null
@@ -0,0 +1,3 @@
+#![crate_name = "a"]
+
+pub fn foo<T>() {}
diff --git a/src/test/ui/svh/auxiliary/changing-crates-a2.rs b/src/test/ui/svh/auxiliary/changing-crates-a2.rs
new file mode 100644 (file)
index 0000000..fafc6d5
--- /dev/null
@@ -0,0 +1,3 @@
+#![crate_name = "a"]
+
+pub fn foo<T>() { println!("hello!"); }
diff --git a/src/test/ui/svh/auxiliary/changing-crates-b.rs b/src/test/ui/svh/auxiliary/changing-crates-b.rs
new file mode 100644 (file)
index 0000000..f9ce29e
--- /dev/null
@@ -0,0 +1,5 @@
+#![crate_name = "b"]
+
+extern crate a;
+
+pub fn foo() { a::foo::<isize>(); }
diff --git a/src/test/ui/svh/changing-crates.rs b/src/test/ui/svh/changing-crates.rs
new file mode 100644 (file)
index 0000000..60c043b
--- /dev/null
@@ -0,0 +1,12 @@
+// ignore-msvc FIXME #31306
+
+// note that these aux-build directives must be in this order
+// aux-build:changing-crates-a1.rs
+// aux-build:changing-crates-b.rs
+// aux-build:changing-crates-a2.rs
+// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2"
+
+extern crate a;
+extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
+
+fn main() {}
diff --git a/src/test/ui/svh/changing-crates.stderr b/src/test/ui/svh/changing-crates.stderr
new file mode 100644 (file)
index 0000000..cc62a4d
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0460]: found possibly newer version of crate `a` which `b` depends on
+  --> $DIR/changing-crates.rs:10:1
+   |
+LL | extern crate b;
+   | ^^^^^^^^^^^^^^^
+   |
+   = note: perhaps that crate needs to be recompiled?
+   = note: the following crate versions were found:
+           crate `a`: $PATH_a
+           crate `b`: $PATH_b
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/syntax-trait-polarity.rs b/src/test/ui/syntax-trait-polarity.rs
deleted file mode 100644 (file)
index ed29474..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#![feature(negative_impls)]
-
-use std::marker::Send;
-
-struct TestType;
-
-impl !TestType {}
-//~^ ERROR inherent impls cannot be negative
-
-trait TestTrait {}
-
-unsafe impl !Send for TestType {}
-//~^ ERROR negative impls cannot be unsafe
-impl !TestTrait for TestType {}
-
-struct TestType2<T>(T);
-
-impl<T> !TestType2<T> {}
-//~^ ERROR inherent impls cannot be negative
-
-unsafe impl<T> !Send for TestType2<T> {}
-//~^ ERROR negative impls cannot be unsafe
-impl<T> !TestTrait for TestType2<T> {}
-
-fn main() {}
diff --git a/src/test/ui/syntax-trait-polarity.stderr b/src/test/ui/syntax-trait-polarity.stderr
deleted file mode 100644 (file)
index 1fd40fb..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-error: inherent impls cannot be negative
-  --> $DIR/syntax-trait-polarity.rs:7:7
-   |
-LL | impl !TestType {}
-   |      -^^^^^^^^ inherent impl for this type
-   |      |
-   |      negative because of this
-
-error[E0198]: negative impls cannot be unsafe
-  --> $DIR/syntax-trait-polarity.rs:12:13
-   |
-LL | unsafe impl !Send for TestType {}
-   | ------      -^^^^
-   | |           |
-   | |           negative because of this
-   | unsafe because of this
-
-error: inherent impls cannot be negative
-  --> $DIR/syntax-trait-polarity.rs:18:10
-   |
-LL | impl<T> !TestType2<T> {}
-   |         -^^^^^^^^^^^^ inherent impl for this type
-   |         |
-   |         negative because of this
-
-error[E0198]: negative impls cannot be unsafe
-  --> $DIR/syntax-trait-polarity.rs:21:16
-   |
-LL | unsafe impl<T> !Send for TestType2<T> {}
-   | ------         -^^^^
-   | |              |
-   | |              negative because of this
-   | unsafe because of this
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0198`.
index 101132d05fa0eb98f6a5d0f05e45d20800f5a2b4..5cb9ad31fbfcc0a2ac95366084206839702fa26d 100644 (file)
@@ -3,18 +3,27 @@ error[E0632]: cannot provide explicit generic arguments when `impl Trait` is use
    |
 LL |     func::<u8>(42);
    |            ^^ explicit generic argument not allowed
+   |
+   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
+   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
 
 error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
   --> $DIR/synthetic-param.rs:23:17
    |
 LL |     Foo::func::<u8>(42);
    |                 ^^ explicit generic argument not allowed
+   |
+   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
+   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
 
 error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
   --> $DIR/synthetic-param.rs:26:23
    |
 LL |     Bar::<i8>::func::<u8>(42);
    |                       ^^ explicit generic argument not allowed
+   |
+   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
+   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/terminate-in-initializer.rs b/src/test/ui/terminate-in-initializer.rs
deleted file mode 100644 (file)
index c9cb932..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-// run-pass
-// ignore-emscripten no threads support
-
-// Issue #787
-// Don't try to clean up uninitialized locals
-
-
-use std::thread;
-
-fn test_break() { loop { let _x: Box<isize> = break; } }
-
-fn test_cont() { let mut i = 0; while i < 1 { i += 1; let _x: Box<isize> = continue; } }
-
-fn test_ret() { let _x: Box<isize> = return; }
-
-fn test_panic() {
-    fn f() { let _x: Box<isize> = panic!(); }
-    thread::spawn(move|| f() ).join().unwrap_err();
-}
-
-fn test_panic_indirect() {
-    fn f() -> ! { panic!(); }
-    fn g() { let _x: Box<isize> = f(); }
-    thread::spawn(move|| g() ).join().unwrap_err();
-}
-
-pub fn main() {
-    test_break();
-    test_cont();
-    test_ret();
-    test_panic();
-    test_panic_indirect();
-}
index 869b372965966ffaebb6b17d83db3dbed5cb2e13..65d90678040d5ff094278cde42b3bb483ad2d067 100644 (file)
@@ -6,6 +6,10 @@ LL |     want_foo(b);
    |
    = note: expected struct `Foo`
               found struct `Box<Foo>`
+help: try dereferencing the `Box`
+   |
+LL |     want_foo(*b);
+   |              +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/test-attrs/issue-20823.rs b/src/test/ui/test-attrs/issue-20823.rs
new file mode 100644 (file)
index 0000000..9e209d5
--- /dev/null
@@ -0,0 +1,5 @@
+// run-pass
+// compile-flags: --test
+
+#[test]
+pub fn foo() {}
diff --git a/src/test/ui/thin-lto-global-allocator.rs b/src/test/ui/thin-lto-global-allocator.rs
deleted file mode 100644 (file)
index e00c5ca..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// run-pass
-// compile-flags: -Z thinlto -C codegen-units=2
-
-#[global_allocator]
-static A: std::alloc::System = std::alloc::System;
-
-fn main() {}
diff --git a/src/test/ui/thinlto/all-crates.rs b/src/test/ui/thinlto/all-crates.rs
deleted file mode 100644 (file)
index e910b2a..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-pass
-
-// compile-flags: -Clto=thin
-// no-prefer-dynamic
-
-fn main() {
-    println!("hello!");
-}
diff --git a/src/test/ui/thinlto/auxiliary/dylib.rs b/src/test/ui/thinlto/auxiliary/dylib.rs
deleted file mode 100644 (file)
index e8b7f8f..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// compile-flags: -Z thinlto -C codegen-units=8
-
-#[inline]
-pub fn foo(b: u8) {
-    b.to_string();
-}
diff --git a/src/test/ui/thinlto/auxiliary/msvc-imp-present.rs b/src/test/ui/thinlto/auxiliary/msvc-imp-present.rs
deleted file mode 100644 (file)
index 933af05..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// no-prefer-dynamic
-// compile-flags: -Z thinlto -C codegen-units=8 -C prefer-dynamic
-
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
-
-pub static A: u32 = 43;
-
-pub mod a {
-    pub static A: u32 = 43;
-}
diff --git a/src/test/ui/thinlto/auxiliary/thin-lto-inlines-aux.rs b/src/test/ui/thinlto/auxiliary/thin-lto-inlines-aux.rs
deleted file mode 100644 (file)
index 5fd3f19..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// no-prefer-dynamic
-
-#![crate_type = "rlib"]
-
-pub fn bar() -> u32 {
-    3
-}
diff --git a/src/test/ui/thinlto/dylib-works.rs b/src/test/ui/thinlto/dylib-works.rs
deleted file mode 100644 (file)
index 9e0782b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// run-pass
-
-// aux-build:dylib.rs
-
-extern crate dylib;
-
-fn main() {
-    dylib::foo(1);
-}
diff --git a/src/test/ui/thinlto/msvc-imp-present.rs b/src/test/ui/thinlto/msvc-imp-present.rs
deleted file mode 100644 (file)
index 5498afb..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// run-pass
-
-// aux-build:msvc-imp-present.rs
-// compile-flags: -Z thinlto -C codegen-units=8
-// no-prefer-dynamic
-
-// On MSVC we have a "hack" where we emit symbols that look like `_imp_$name`
-// for all exported statics. This is done because we apply `dllimport` to all
-// imported constants and this allows everything to actually link correctly.
-//
-// The ThinLTO passes aggressively remove symbols if they can, and this test
-// asserts that the ThinLTO passes don't remove these compiler-generated
-// `_imp_*` symbols. The external library that we link in here is compiled with
-// ThinLTO and multiple codegen units and has a few exported constants. Note
-// that we also namely compile the library as both a dylib and an rlib, but we
-// link the rlib to ensure that we assert those generated symbols exist.
-
-extern crate msvc_imp_present as bar;
-
-fn main() {
-    println!("{}", bar::A);
-}
diff --git a/src/test/ui/thinlto/thin-lto-inlines.rs b/src/test/ui/thinlto/thin-lto-inlines.rs
deleted file mode 100644 (file)
index dca7918..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// run-pass
-
-// compile-flags: -Z thinlto -C codegen-units=8 -O
-// ignore-emscripten can't inspect instructions on emscripten
-
-// We want to assert here that ThinLTO will inline across codegen units. There's
-// not really a great way to do that in general so we sort of hack around it by
-// praying two functions go into separate codegen units and then assuming that
-// if inlining *doesn't* happen the first byte of the functions will differ.
-
-pub fn foo() -> u32 {
-    bar::bar()
-}
-
-mod bar {
-    pub fn bar() -> u32 {
-        3
-    }
-}
-
-fn main() {
-    println!("{} {}", foo(), bar::bar());
-
-    unsafe {
-        let foo = foo as usize as *const u8;
-        let bar = bar::bar as usize as *const u8;
-
-        assert_eq!(*foo, *bar);
-    }
-}
diff --git a/src/test/ui/thinlto/thin-lto-inlines2.rs b/src/test/ui/thinlto/thin-lto-inlines2.rs
deleted file mode 100644 (file)
index 1eb2965..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// run-pass
-
-// compile-flags: -C codegen-units=8 -O -C lto=thin
-// aux-build:thin-lto-inlines-aux.rs
-// no-prefer-dynamic
-// ignore-emscripten can't inspect instructions on emscripten
-
-// We want to assert here that ThinLTO will inline across codegen units. There's
-// not really a great way to do that in general so we sort of hack around it by
-// praying two functions go into separate codegen units and then assuming that
-// if inlining *doesn't* happen the first byte of the functions will differ.
-
-extern crate thin_lto_inlines_aux as bar;
-
-pub fn foo() -> u32 {
-    bar::bar()
-}
-
-fn main() {
-    println!("{} {}", foo(), bar::bar());
-
-    unsafe {
-        let foo = foo as usize as *const u8;
-        let bar = bar::bar as usize as *const u8;
-
-        assert_eq!(*foo, *bar);
-    }
-}
diff --git a/src/test/ui/thinlto/weak-works.rs b/src/test/ui/thinlto/weak-works.rs
deleted file mode 100644 (file)
index 163a387..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// run-pass
-
-// compile-flags: -C codegen-units=8 -Z thinlto
-// ignore-windows
-
-#![feature(linkage)]
-
-pub mod foo {
-    #[linkage = "weak"]
-    #[no_mangle]
-    pub extern "C" fn FOO() -> i32 {
-        0
-    }
-}
-
-mod bar {
-    extern "C" {
-        fn FOO() -> i32;
-    }
-
-    pub fn bar() -> i32 {
-        unsafe { FOO() }
-    }
-}
-
-fn main() {
-    bar::bar();
-}
diff --git a/src/test/ui/threads-sendsync/issue-24313.rs b/src/test/ui/threads-sendsync/issue-24313.rs
new file mode 100644 (file)
index 0000000..c28b4ca
--- /dev/null
@@ -0,0 +1,32 @@
+// run-pass
+// ignore-emscripten no threads
+// ignore-sgx no processes
+
+use std::thread;
+use std::env;
+use std::process::Command;
+
+struct Handle(i32);
+
+impl Drop for Handle {
+    fn drop(&mut self) { panic!(); }
+}
+
+thread_local!(static HANDLE: Handle = Handle(0));
+
+fn main() {
+    let args = env::args().collect::<Vec<_>>();
+    if args.len() == 1 {
+        let out = Command::new(&args[0]).arg("test").output().unwrap();
+        let stderr = std::str::from_utf8(&out.stderr).unwrap();
+        assert!(stderr.contains("panicked at 'explicit panic'"),
+                "bad failure message:\n{}\n", stderr);
+    } else {
+        // TLS dtors are not always run on process exit
+        thread::spawn(|| {
+            HANDLE.with(|h| {
+                println!("{}", h.0);
+            });
+        }).join().unwrap();
+    }
+}
diff --git a/src/test/ui/threads-sendsync/issue-4448.rs b/src/test/ui/threads-sendsync/issue-4448.rs
new file mode 100644 (file)
index 0000000..27d0326
--- /dev/null
@@ -0,0 +1,16 @@
+// run-pass
+// ignore-emscripten no threads support
+
+use std::sync::mpsc::channel;
+use std::thread;
+
+pub fn main() {
+    let (tx, rx) = channel::<&'static str>();
+
+    let t = thread::spawn(move|| {
+        assert_eq!(rx.recv().unwrap(), "hello, world");
+    });
+
+    tx.send("hello, world").unwrap();
+    t.join().ok().unwrap();
+}
diff --git a/src/test/ui/threads-sendsync/issue-8827.rs b/src/test/ui/threads-sendsync/issue-8827.rs
new file mode 100644 (file)
index 0000000..95be761
--- /dev/null
@@ -0,0 +1,53 @@
+// run-pass
+// ignore-emscripten no threads support
+
+use std::thread;
+use std::sync::mpsc::{channel, Receiver};
+
+fn periodical(n: isize) -> Receiver<bool> {
+    let (chan, port) = channel();
+    thread::spawn(move|| {
+        loop {
+            for _ in 1..n {
+                match chan.send(false) {
+                    Ok(()) => {}
+                    Err(..) => break,
+                }
+            }
+            match chan.send(true) {
+                Ok(()) => {}
+                Err(..) => break
+            }
+        }
+    });
+    return port;
+}
+
+fn integers() -> Receiver<isize> {
+    let (chan, port) = channel();
+    thread::spawn(move|| {
+        let mut i = 1;
+        loop {
+            match chan.send(i) {
+                Ok(()) => {}
+                Err(..) => break,
+            }
+            i = i + 1;
+        }
+    });
+    return port;
+}
+
+fn main() {
+    let ints = integers();
+    let threes = periodical(3);
+    let fives = periodical(5);
+    for _ in 1..100 {
+        match (ints.recv().unwrap(), threes.recv().unwrap(), fives.recv().unwrap()) {
+            (_, true, true) => println!("FizzBuzz"),
+            (_, true, false) => println!("Fizz"),
+            (_, false, true) => println!("Buzz"),
+            (i, false, false) => println!("{}", i)
+        }
+    }
+}
diff --git a/src/test/ui/threads-sendsync/issue-9396.rs b/src/test/ui/threads-sendsync/issue-9396.rs
new file mode 100644 (file)
index 0000000..3e7e9a5
--- /dev/null
@@ -0,0 +1,23 @@
+// run-pass
+#![allow(unused_must_use)]
+#![allow(deprecated)]
+// ignore-emscripten no threads support
+
+use std::sync::mpsc::{TryRecvError, channel};
+use std::thread;
+
+pub fn main() {
+    let (tx, rx) = channel();
+    let t = thread::spawn(move||{
+        thread::sleep_ms(10);
+        tx.send(()).unwrap();
+    });
+    loop {
+        match rx.try_recv() {
+            Ok(()) => break,
+            Err(TryRecvError::Empty) => {}
+            Err(TryRecvError::Disconnected) => unreachable!()
+        }
+    }
+    t.join();
+}
diff --git a/src/test/ui/threads-sendsync/trivial-message.rs b/src/test/ui/threads-sendsync/trivial-message.rs
new file mode 100644 (file)
index 0000000..5831e86
--- /dev/null
@@ -0,0 +1,16 @@
+// run-pass
+
+#![allow(unused_must_use)]
+/*
+  This is about the simplest program that can successfully send a
+  message.
+ */
+
+use std::sync::mpsc::channel;
+
+pub fn main() {
+    let (tx, rx) = channel();
+    tx.send(42);
+    let r = rx.recv();
+    println!("{:?}", r);
+}
diff --git a/src/test/ui/threads-sendsync/yield2.rs b/src/test/ui/threads-sendsync/yield2.rs
new file mode 100644 (file)
index 0000000..376faab
--- /dev/null
@@ -0,0 +1,8 @@
+// run-pass
+
+use std::thread;
+
+pub fn main() {
+    let mut i: isize = 0;
+    while i < 100 { i = i + 1; println!("{}", i); thread::yield_now(); }
+}
diff --git a/src/test/ui/trace_macros-format.rs b/src/test/ui/trace_macros-format.rs
deleted file mode 100644 (file)
index afca45c..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#![feature(trace_macros)]
-
-fn main() {
-    trace_macros!(); //~ ERROR trace_macros! accepts only `true` or `false`
-    trace_macros!(1); //~ ERROR trace_macros! accepts only `true` or `false`
-    trace_macros!(ident); //~ ERROR trace_macros! accepts only `true` or `false`
-    trace_macros!(for); //~ ERROR trace_macros! accepts only `true` or `false`
-    trace_macros!(true,); //~ ERROR trace_macros! accepts only `true` or `false`
-    trace_macros!(false 1); //~ ERROR trace_macros! accepts only `true` or `false`
-
-
-    // should be fine:
-    macro_rules! expando {
-        ($x: ident) => { trace_macros!($x) }
-    }
-
-    expando!(true);
-}
diff --git a/src/test/ui/trace_macros-format.stderr b/src/test/ui/trace_macros-format.stderr
deleted file mode 100644 (file)
index c320270..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-error: trace_macros! accepts only `true` or `false`
-  --> $DIR/trace_macros-format.rs:4:5
-   |
-LL |     trace_macros!();
-   |     ^^^^^^^^^^^^^^^
-
-error: trace_macros! accepts only `true` or `false`
-  --> $DIR/trace_macros-format.rs:5:5
-   |
-LL |     trace_macros!(1);
-   |     ^^^^^^^^^^^^^^^^
-
-error: trace_macros! accepts only `true` or `false`
-  --> $DIR/trace_macros-format.rs:6:5
-   |
-LL |     trace_macros!(ident);
-   |     ^^^^^^^^^^^^^^^^^^^^
-
-error: trace_macros! accepts only `true` or `false`
-  --> $DIR/trace_macros-format.rs:7:5
-   |
-LL |     trace_macros!(for);
-   |     ^^^^^^^^^^^^^^^^^^
-
-error: trace_macros! accepts only `true` or `false`
-  --> $DIR/trace_macros-format.rs:8:5
-   |
-LL |     trace_macros!(true,);
-   |     ^^^^^^^^^^^^^^^^^^^^
-
-error: trace_macros! accepts only `true` or `false`
-  --> $DIR/trace_macros-format.rs:9:5
-   |
-LL |     trace_macros!(false 1);
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 6 previous errors
-
diff --git a/src/test/ui/trait-bounds/issue-75961.rs b/src/test/ui/trait-bounds/issue-75961.rs
new file mode 100644 (file)
index 0000000..367eac7
--- /dev/null
@@ -0,0 +1,7 @@
+// check-pass
+
+pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone {
+    <&mut () as Clone>::clone(&s);
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/issue-24010.rs b/src/test/ui/traits/issue-24010.rs
new file mode 100644 (file)
index 0000000..f181853
--- /dev/null
@@ -0,0 +1,14 @@
+// run-pass
+
+trait Foo: Fn(i32) -> i32 + Send {}
+
+impl<T: ?Sized + Fn(i32) -> i32 + Send> Foo for T {}
+
+fn wants_foo(f: Box<dyn Foo>) -> i32 {
+    f(42)
+}
+
+fn main() {
+    let f = Box::new(|x| x);
+    assert_eq!(wants_foo(f), 42);
+}
diff --git a/src/test/ui/traits/issue-38604.rs b/src/test/ui/traits/issue-38604.rs
new file mode 100644 (file)
index 0000000..002a3c4
--- /dev/null
@@ -0,0 +1,16 @@
+trait Q<T:?Sized> {}
+trait Foo where u32: Q<Self> {
+    fn foo(&self);
+}
+
+impl Q<()> for u32 {}
+impl Foo for () {
+    fn foo(&self) {
+        println!("foo!");
+    }
+}
+
+fn main() {
+    let _f: Box<dyn Foo> = //~ ERROR `Foo` cannot be made into an object
+        Box::new(()); //~ ERROR `Foo` cannot be made into an object
+}
diff --git a/src/test/ui/traits/issue-38604.stderr b/src/test/ui/traits/issue-38604.stderr
new file mode 100644 (file)
index 0000000..d41488c
--- /dev/null
@@ -0,0 +1,33 @@
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/issue-38604.rs:14:13
+   |
+LL |     let _f: Box<dyn Foo> =
+   |             ^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-38604.rs:2:22
+   |
+LL | trait Foo where u32: Q<Self> {
+   |       ---            ^^^^^^^ ...because it uses `Self` as a type parameter
+   |       |
+   |       this trait cannot be made into an object...
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/issue-38604.rs:15:9
+   |
+LL |         Box::new(());
+   |         ^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-38604.rs:2:22
+   |
+LL | trait Foo where u32: Q<Self> {
+   |       ---            ^^^^^^^ ...because it uses `Self` as a type parameter
+   |       |
+   |       this trait cannot be made into an object...
+   = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn Foo>>` for `Box<()>`
+   = note: required by cast to type `Box<dyn Foo>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/traits/issue-3973.rs b/src/test/ui/traits/issue-3973.rs
new file mode 100644 (file)
index 0000000..a5ed5b8
--- /dev/null
@@ -0,0 +1,25 @@
+struct Point {
+    x: f64,
+    y: f64,
+}
+
+trait ToString_ {
+    fn to_string(&self) -> String;
+}
+
+impl ToString_ for Point {
+    fn new(x: f64, y: f64) -> Point {
+    //~^ ERROR method `new` is not a member of trait `ToString_`
+        Point { x: x, y: y }
+    }
+
+    fn to_string(&self) -> String {
+        format!("({}, {})", self.x, self.y)
+    }
+}
+
+fn main() {
+    let p = Point::new(0.0, 0.0);
+    //~^ ERROR no function or associated item named `new` found for struct `Point`
+    println!("{}", p.to_string());
+}
diff --git a/src/test/ui/traits/issue-3973.stderr b/src/test/ui/traits/issue-3973.stderr
new file mode 100644 (file)
index 0000000..63282e8
--- /dev/null
@@ -0,0 +1,22 @@
+error[E0407]: method `new` is not a member of trait `ToString_`
+  --> $DIR/issue-3973.rs:11:5
+   |
+LL | /     fn new(x: f64, y: f64) -> Point {
+LL | |
+LL | |         Point { x: x, y: y }
+LL | |     }
+   | |_____^ not a member of trait `ToString_`
+
+error[E0599]: no function or associated item named `new` found for struct `Point` in the current scope
+  --> $DIR/issue-3973.rs:22:20
+   |
+LL | struct Point {
+   | ------------ function or associated item `new` not found for this
+...
+LL |     let p = Point::new(0.0, 0.0);
+   |                    ^^^ function or associated item not found in `Point`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0407, E0599.
+For more information about an error, try `rustc --explain E0407`.
diff --git a/src/test/ui/traits/issue-59029-1.rs b/src/test/ui/traits/issue-59029-1.rs
new file mode 100644 (file)
index 0000000..8ab47a4
--- /dev/null
@@ -0,0 +1,9 @@
+#![feature(trait_alias)]
+
+trait Svc<Req> { type Res; }
+
+trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
+//~^ ERROR associated type `Res` not found for `Self`
+//~| ERROR associated type `Res` not found for `Self`
+
+fn main() {}
diff --git a/src/test/ui/traits/issue-59029-1.stderr b/src/test/ui/traits/issue-59029-1.stderr
new file mode 100644 (file)
index 0000000..53cdb8b
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0220]: associated type `Res` not found for `Self`
+  --> $DIR/issue-59029-1.rs:5:52
+   |
+LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
+   |                                                    ^^^ associated type `Res` not found
+
+error[E0220]: associated type `Res` not found for `Self`
+  --> $DIR/issue-59029-1.rs:5:52
+   |
+LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
+   |                                                    ^^^ associated type `Res` not found
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0220`.
index 23b78d023b600dc8f3665e3a5b6a6ea97eca3599..d1e8affd065f9356e9179a7053bb1670fbb9dfcc 100644 (file)
@@ -5,7 +5,7 @@ LL | #[derive(Clone)]
    |          ----- in this derive macro expansion
 LL | struct FooHolster {
 LL |     the_foos: Vec<Foo>,
-   |     ^^^^^^^^^^^^^^^^^^ expected an implementor of trait `Clone`
+   |     ^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Foo`
    |
    = note: required because of the requirements on the impl of `Clone` for `Vec<Foo>`
 note: required by `clone`
diff --git a/src/test/ui/traits/issue-72455.rs b/src/test/ui/traits/issue-72455.rs
new file mode 100644 (file)
index 0000000..b6c3bb2
--- /dev/null
@@ -0,0 +1,27 @@
+// check-pass
+
+pub trait ResultExt {
+    type Ok;
+    fn err_eprint_and_ignore(self) -> Option<Self::Ok>;
+}
+
+impl<O, E> ResultExt for std::result::Result<O, E>
+where
+    E: std::error::Error,
+{
+    type Ok = O;
+    fn err_eprint_and_ignore(self) -> Option<O>
+    where
+        Self: ,
+    {
+        match self {
+            Err(e) => {
+                eprintln!("{}", e);
+                None
+            }
+            Ok(o) => Some(o),
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/issue-90195-2.rs b/src/test/ui/traits/issue-90195-2.rs
new file mode 100644 (file)
index 0000000..b739dc4
--- /dev/null
@@ -0,0 +1,20 @@
+// check-pass
+pub trait Archive {
+    type Archived;
+}
+
+impl<T> Archive for Option<T> {
+    type Archived = ();
+}
+pub type Archived<T> = <T as Archive>::Archived;
+
+pub trait Deserialize<D> {}
+
+const ARRAY_SIZE: usize = 32;
+impl<__D> Deserialize<__D> for ()
+where
+    Option<[u8; ARRAY_SIZE]>: Archive,
+    Archived<Option<[u8; ARRAY_SIZE]>>: Deserialize<__D>,
+{
+}
+fn main() {}
diff --git a/src/test/ui/traits/issue-90195.rs b/src/test/ui/traits/issue-90195.rs
new file mode 100644 (file)
index 0000000..543c9f1
--- /dev/null
@@ -0,0 +1,21 @@
+// check-pass
+pub trait Archive {
+    type Archived;
+}
+
+impl<T> Archive for Option<T> {
+    type Archived = ();
+}
+pub type Archived<T> = <T as Archive>::Archived;
+
+pub trait Deserialize<D> {}
+
+const ARRAY_SIZE: usize = 32;
+impl<__D> Deserialize<__D> for ()
+where
+    Option<[u8; ARRAY_SIZE]>: Archive,
+    Option<[u8; ARRAY_SIZE]>: Archive,
+    Archived<Option<[u8; ARRAY_SIZE]>>: Deserialize<__D>,
+{
+}
+fn main() {}
index 8059a8ca71e43b0697eda08692317a7f2c6564f2..1cf73fcdebd0b9985a05dd07f3dfab5bff602d5a 100644 (file)
@@ -49,7 +49,7 @@ LL |     is_send((8, TestType));
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Send` is not implemented for `dummy1c::TestType`
+   = help: within `({integer}, dummy1c::TestType)`, the trait `Send` is not implemented for `dummy1c::TestType`
    = note: required because it appears within the type `({integer}, dummy1c::TestType)`
 note: required by a bound in `is_send`
   --> $DIR/negated-auto-traits-error.rs:16:15
@@ -86,7 +86,7 @@ LL |     is_send(Box::new(Outer2(TestType)));
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Send` is not implemented for `dummy3::TestType`
+   = help: within `Outer2<dummy3::TestType>`, the trait `Send` is not implemented for `dummy3::TestType`
 note: required because it appears within the type `Outer2<dummy3::TestType>`
   --> $DIR/negated-auto-traits-error.rs:12:8
    |
diff --git a/src/test/ui/traits/object-does-not-impl-trait.rs b/src/test/ui/traits/object-does-not-impl-trait.rs
new file mode 100644 (file)
index 0000000..b3b6798
--- /dev/null
@@ -0,0 +1,8 @@
+// Test that an object type `Box<Foo>` is not considered to implement the
+// trait `Foo`. Issue #5087.
+
+trait Foo {}
+fn take_foo<F:Foo>(f: F) {}
+fn take_object(f: Box<dyn Foo>) { take_foo(f); }
+//~^ ERROR `Box<dyn Foo>: Foo` is not satisfied
+fn main() {}
diff --git a/src/test/ui/traits/object-does-not-impl-trait.stderr b/src/test/ui/traits/object-does-not-impl-trait.stderr
new file mode 100644 (file)
index 0000000..f1dd508
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `Box<dyn Foo>: Foo` is not satisfied
+  --> $DIR/object-does-not-impl-trait.rs:6:44
+   |
+LL | fn take_object(f: Box<dyn Foo>) { take_foo(f); }
+   |                                   -------- ^ the trait `Foo` is not implemented for `Box<dyn Foo>`
+   |                                   |
+   |                                   required by a bound introduced by this call
+   |
+note: required by a bound in `take_foo`
+  --> $DIR/object-does-not-impl-trait.rs:5:15
+   |
+LL | fn take_foo<F:Foo>(f: F) {}
+   |               ^^^ required by this bound in `take_foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/syntax-trait-polarity.rs b/src/test/ui/traits/syntax-trait-polarity.rs
new file mode 100644 (file)
index 0000000..ed29474
--- /dev/null
@@ -0,0 +1,25 @@
+#![feature(negative_impls)]
+
+use std::marker::Send;
+
+struct TestType;
+
+impl !TestType {}
+//~^ ERROR inherent impls cannot be negative
+
+trait TestTrait {}
+
+unsafe impl !Send for TestType {}
+//~^ ERROR negative impls cannot be unsafe
+impl !TestTrait for TestType {}
+
+struct TestType2<T>(T);
+
+impl<T> !TestType2<T> {}
+//~^ ERROR inherent impls cannot be negative
+
+unsafe impl<T> !Send for TestType2<T> {}
+//~^ ERROR negative impls cannot be unsafe
+impl<T> !TestTrait for TestType2<T> {}
+
+fn main() {}
diff --git a/src/test/ui/traits/syntax-trait-polarity.stderr b/src/test/ui/traits/syntax-trait-polarity.stderr
new file mode 100644 (file)
index 0000000..1fd40fb
--- /dev/null
@@ -0,0 +1,37 @@
+error: inherent impls cannot be negative
+  --> $DIR/syntax-trait-polarity.rs:7:7
+   |
+LL | impl !TestType {}
+   |      -^^^^^^^^ inherent impl for this type
+   |      |
+   |      negative because of this
+
+error[E0198]: negative impls cannot be unsafe
+  --> $DIR/syntax-trait-polarity.rs:12:13
+   |
+LL | unsafe impl !Send for TestType {}
+   | ------      -^^^^
+   | |           |
+   | |           negative because of this
+   | unsafe because of this
+
+error: inherent impls cannot be negative
+  --> $DIR/syntax-trait-polarity.rs:18:10
+   |
+LL | impl<T> !TestType2<T> {}
+   |         -^^^^^^^^^^^^ inherent impl for this type
+   |         |
+   |         negative because of this
+
+error[E0198]: negative impls cannot be unsafe
+  --> $DIR/syntax-trait-polarity.rs:21:16
+   |
+LL | unsafe impl<T> !Send for TestType2<T> {}
+   | ------         -^^^^
+   | |              |
+   | |              negative because of this
+   | unsafe because of this
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0198`.
diff --git a/src/test/ui/transmute-specialization.rs b/src/test/ui/transmute-specialization.rs
deleted file mode 100644 (file)
index 499334d..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// run-pass
-
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
-
-trait Specializable { type Output; }
-
-impl<T> Specializable for T {
-    default type Output = u16;
-}
-
-fn main() {
-    unsafe {
-        std::mem::transmute::<u16, <() as Specializable>::Output>(0);
-    }
-}
diff --git a/src/test/ui/transmute-specialization.stderr b/src/test/ui/transmute-specialization.stderr
deleted file mode 100644 (file)
index a0ea724..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/transmute-specialization.rs:3:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/trivial-message.rs b/src/test/ui/trivial-message.rs
deleted file mode 100644 (file)
index 5831e86..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// run-pass
-
-#![allow(unused_must_use)]
-/*
-  This is about the simplest program that can successfully send a
-  message.
- */
-
-use std::sync::mpsc::channel;
-
-pub fn main() {
-    let (tx, rx) = channel();
-    tx.send(42);
-    let r = rx.recv();
-    println!("{:?}", r);
-}
diff --git a/src/test/ui/try-block/issue-45124.rs b/src/test/ui/try-block/issue-45124.rs
new file mode 100644 (file)
index 0000000..942014c
--- /dev/null
@@ -0,0 +1,18 @@
+// run-pass
+#![allow(unreachable_code)]
+// compile-flags: --edition 2018
+
+#![feature(try_blocks)]
+
+fn main() {
+    let mut a = 0;
+    let () = {
+        let _: Result<(), ()> = try {
+            let _ = Err(())?;
+            return
+        };
+        a += 1;
+    };
+    a += 2;
+    assert_eq!(a, 3);
+}
diff --git a/src/test/ui/try-macro-suggestion.rs b/src/test/ui/try-macro-suggestion.rs
deleted file mode 100644 (file)
index 635ceac..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// compile-flags: --edition 2018
-fn foo() -> Result<(), ()> {
-    Ok(try!()); //~ ERROR use of deprecated `try` macro
-    Ok(try!(Ok(()))) //~ ERROR use of deprecated `try` macro
-}
-
-fn main() {
-    let _ = foo();
-}
diff --git a/src/test/ui/try-macro-suggestion.stderr b/src/test/ui/try-macro-suggestion.stderr
deleted file mode 100644 (file)
index c7dde7e..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-error: use of deprecated `try` macro
-  --> $DIR/try-macro-suggestion.rs:3:8
-   |
-LL |     Ok(try!());
-   |        ^^^^^^
-   |
-   = note: in the 2018 edition `try` is a reserved keyword, and the `try!()` macro is deprecated
-help: you can still access the deprecated `try!()` macro using the "raw identifier" syntax
-   |
-LL |     Ok(r#try!());
-   |        ++
-
-error: use of deprecated `try` macro
-  --> $DIR/try-macro-suggestion.rs:4:8
-   |
-LL |     Ok(try!(Ok(())))
-   |        ^^^^^^^^^^^^
-   |
-   = note: in the 2018 edition `try` is a reserved keyword, and the `try!()` macro is deprecated
-help: you can use the `?` operator instead
-   |
-LL -     Ok(try!(Ok(())))
-LL +     Ok(Ok(())?)
-   | 
-help: alternatively, you can still access the deprecated `try!()` macro using the "raw identifier" syntax
-   |
-LL |     Ok(r#try!(Ok(())))
-   |        ++
-
-error: aborting due to 2 previous errors
-
index 5f3b711b31aa91bac473564d7e63ac574a05d3b5..acbf15dcb6c6a937d5f49b0e3948b0b470bbb587 100644 (file)
@@ -31,7 +31,10 @@ impl Tr for E {
     type V = u8;
     fn f() -> Self::V { 0 }
     //~^ ERROR ambiguous associated item
+    //~| ERROR ambiguous associated item
     //~| WARN this was previously accepted
+    //~| WARN this was previously accepted
+    //~| HELP use fully-qualified syntax
     //~| HELP use fully-qualified syntax
 }
 
index 870b1eec48c0c8a476f386153d72d6264319f10f..f007f71a73c4532323fdaf2324211e1f290d9c9b 100644 (file)
@@ -18,5 +18,24 @@ note: `V` could also refer to the associated type defined here
 LL |     type V;
    |     ^^^^^^^
 
-error: aborting due to previous error
+error: ambiguous associated item
+  --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:32:15
+   |
+LL |     fn f() -> Self::V { 0 }
+   |               ^^^^^^^ help: use fully-qualified syntax: `<E as Tr>::V`
+   |
+   = 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 #57644 <https://github.com/rust-lang/rust/issues/57644>
+note: `V` could refer to the variant defined here
+  --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:22:5
+   |
+LL |     V
+   |     ^
+note: `V` could also refer to the associated type defined here
+  --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:26:5
+   |
+LL |     type V;
+   |     ^^^^^^^
+
+error: aborting due to 2 previous errors
 
index d60be4b1ccf9ca04289899c22b46222d5484dde4..4a49d6e4ab8fd7aaac23229cdcfea5e659138662 100644 (file)
@@ -1,11 +1,13 @@
 error[E0277]: `Rc<u32>` cannot be sent between threads safely
-  --> $DIR/auto-trait-leakage2.rs:17:5
+  --> $DIR/auto-trait-leakage2.rs:17:13
    |
 LL |     type Foo = impl std::fmt::Debug;
    |                -------------------- within this `impl Debug`
 ...
 LL |     is_send(m::foo());
-   |     ^^^^^^^ `Rc<u32>` cannot be sent between threads safely
+   |     ------- ^^^^^^^^ `Rc<u32>` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: within `impl Debug`, the trait `Send` is not implemented for `Rc<u32>`
    = note: required because it appears within the type `impl Debug`
diff --git a/src/test/ui/type-alias-impl-trait/issue-60662.rs b/src/test/ui/type-alias-impl-trait/issue-60662.rs
new file mode 100644 (file)
index 0000000..b9faa66
--- /dev/null
@@ -0,0 +1,10 @@
+// check-pass
+// compile-flags: -Z unpretty=hir
+
+#![feature(type_alias_impl_trait)]
+
+trait Animal {}
+
+fn main() {
+    pub type ServeFut = impl Animal;
+}
diff --git a/src/test/ui/type-alias-impl-trait/issue-60662.stdout b/src/test/ui/type-alias-impl-trait/issue-60662.stdout
new file mode 100644 (file)
index 0000000..14a49f2
--- /dev/null
@@ -0,0 +1,14 @@
+// check-pass
+// compile-flags: -Z unpretty=hir
+
+#![feature(type_alias_impl_trait)]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+
+trait Animal { }
+
+fn main() {
+              pub type ServeFut = /*impl Trait*/;
+          }
diff --git a/src/test/ui/type-inference/issue-30225.rs b/src/test/ui/type-inference/issue-30225.rs
new file mode 100644 (file)
index 0000000..4231533
--- /dev/null
@@ -0,0 +1,38 @@
+// Regression test for #30225, which was an ICE that would trigger as
+// a result of a poor interaction between trait result caching and
+// type inference. Specifically, at that time, unification could cause
+// unrelated type variables to become instantiated, if subtyping
+// relationships existed. These relationships are now propagated
+// through obligations and hence everything works out fine.
+
+trait Foo<U,V> : Sized {
+    fn foo(self, u: Option<U>, v: Option<V>) {}
+}
+
+struct A;
+struct B;
+
+impl Foo<A, B> for () {}      // impl A
+impl Foo<u32, u32> for u32 {} // impl B, creating ambiguity
+
+fn toxic() {
+    // cache the resolution <() as Foo<$0,$1>> = impl A
+    let u = None;
+    let v = None;
+    Foo::foo((), u, v);
+}
+
+fn bomb() {
+    let mut u = None; // type is Option<$0>
+    let mut v = None; // type is Option<$1>
+    let mut x = None; // type is Option<$2>
+
+    Foo::foo(x.unwrap(),u,v); // register <$2 as Foo<$0, $1>>
+    u = v; // mark $0 and $1 in a subtype relationship
+    //~^ ERROR mismatched types
+    x = Some(()); // set $2 = (), allowing impl selection
+                  // to proceed for <() as Foo<$0, $1>> = impl A.
+                  // kaboom, this *used* to trigge an ICE
+}
+
+fn main() {}
diff --git a/src/test/ui/type-inference/issue-30225.stderr b/src/test/ui/type-inference/issue-30225.stderr
new file mode 100644 (file)
index 0000000..ccd05fa
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-30225.rs:31:9
+   |
+LL |     u = v; // mark $0 and $1 in a subtype relationship
+   |         ^ expected struct `A`, found struct `B`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/typeck/auxiliary/xcrate-issue-43189-a.rs b/src/test/ui/typeck/auxiliary/xcrate-issue-43189-a.rs
new file mode 100644 (file)
index 0000000..9ab570f
--- /dev/null
@@ -0,0 +1,7 @@
+#![crate_type="lib"]
+
+
+pub trait A {
+    fn a(&self) {}
+}
+impl A for () {}
diff --git a/src/test/ui/typeck/auxiliary/xcrate-issue-43189-b.rs b/src/test/ui/typeck/auxiliary/xcrate-issue-43189-b.rs
new file mode 100644 (file)
index 0000000..31dfb05
--- /dev/null
@@ -0,0 +1,3 @@
+#![crate_type="lib"]
+
+pub extern crate xcrate_issue_43189_a;
diff --git a/src/test/ui/typeck/auxiliary/xcrate-issue-46112-rexport-core.rs b/src/test/ui/typeck/auxiliary/xcrate-issue-46112-rexport-core.rs
new file mode 100644 (file)
index 0000000..2b517b5
--- /dev/null
@@ -0,0 +1,3 @@
+#![crate_type="lib"]
+
+pub extern crate core;
diff --git a/src/test/ui/typeck/auxiliary/xcrate-issue-61711-b.rs b/src/test/ui/typeck/auxiliary/xcrate-issue-61711-b.rs
new file mode 100644 (file)
index 0000000..88a0405
--- /dev/null
@@ -0,0 +1,5 @@
+// edition:2018
+#![crate_type="lib"]
+#![crate_name="xcrate_issue_61711_b"]
+pub struct Struct;
+pub use crate as alias;
diff --git a/src/test/ui/typeck/issue-43189.rs b/src/test/ui/typeck/issue-43189.rs
new file mode 100644 (file)
index 0000000..ce667a5
--- /dev/null
@@ -0,0 +1,12 @@
+// Issue 46112: An extern crate pub re-exporting libcore was causing
+// paths rooted from `std` to be misrendered in the diagnostic output.
+
+// ignore-windows
+// aux-build:xcrate-issue-43189-a.rs
+// aux-build:xcrate-issue-43189-b.rs
+
+extern crate xcrate_issue_43189_b;
+fn main() {
+    ().a();
+    //~^ ERROR no method named `a` found
+}
diff --git a/src/test/ui/typeck/issue-43189.stderr b/src/test/ui/typeck/issue-43189.stderr
new file mode 100644 (file)
index 0000000..caf7530
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0599]: no method named `a` found for unit type `()` in the current scope
+  --> $DIR/issue-43189.rs:10:8
+   |
+LL |     ().a();
+   |        ^ method not found in `()`
+   |
+  ::: $DIR/auxiliary/xcrate-issue-43189-a.rs:5:8
+   |
+LL |     fn a(&self) {}
+   |        - the method is available for `()` here
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+   |
+LL | use xcrate_issue_43189_b::xcrate_issue_43189_a::A;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/typeck/issue-46112.rs b/src/test/ui/typeck/issue-46112.rs
new file mode 100644 (file)
index 0000000..0cdd2c2
--- /dev/null
@@ -0,0 +1,10 @@
+// Issue 46112: An extern crate pub re-exporting libcore was causing
+// paths rooted from `std` to be misrendered in the diagnostic output.
+
+// ignore-windows
+// aux-build:xcrate-issue-46112-rexport-core.rs
+
+extern crate xcrate_issue_46112_rexport_core;
+fn test(r: Result<Option<()>, &'static str>) { }
+fn main() { test(Ok(())); }
+//~^ mismatched types
diff --git a/src/test/ui/typeck/issue-46112.stderr b/src/test/ui/typeck/issue-46112.stderr
new file mode 100644 (file)
index 0000000..ec05fbe
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-46112.rs:9:21
+   |
+LL | fn main() { test(Ok(())); }
+   |                     ^^
+   |                     |
+   |                     expected enum `Option`, found `()`
+   |                     help: try using a variant of the expected enum: `Some(())`
+   |
+   = note:   expected enum `Option<()>`
+           found unit type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/typeck/issue-61711-once-caused-rustc-inf-loop.rs b/src/test/ui/typeck/issue-61711-once-caused-rustc-inf-loop.rs
new file mode 100644 (file)
index 0000000..de7d6a0
--- /dev/null
@@ -0,0 +1,11 @@
+// Issue 61711: A crate pub re-exporting `crate` was causing an
+// infinite loop.
+
+// edition:2018
+// aux-build:xcrate-issue-61711-b.rs
+// compile-flags:--extern xcrate_issue_61711_b
+
+// build-pass
+
+fn f<F: Fn(xcrate_issue_61711_b::Struct)>(_: F) { }
+fn main() { }
diff --git a/src/test/ui/typeck/issue-89806.rs b/src/test/ui/typeck/issue-89806.rs
new file mode 100644 (file)
index 0000000..69cec08
--- /dev/null
@@ -0,0 +1,3 @@
+fn main() {
+    0u8.as_ref(); //~ ERROR no method named `as_ref` found for type `u8` in the current scope
+}
diff --git a/src/test/ui/typeck/issue-89806.stderr b/src/test/ui/typeck/issue-89806.stderr
new file mode 100644 (file)
index 0000000..c36b496
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0599]: no method named `as_ref` found for type `u8` in the current scope
+  --> $DIR/issue-89806.rs:2:9
+   |
+LL |     0u8.as_ref();
+   |         ^^^^^^ method not found in `u8`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/typeck/issue-90101.rs b/src/test/ui/typeck/issue-90101.rs
new file mode 100644 (file)
index 0000000..1954ee6
--- /dev/null
@@ -0,0 +1,8 @@
+use std::path::{Path, PathBuf};
+
+fn func(path: impl Into<PathBuf>, code: impl Into<String>) {}
+
+fn main() {
+    func(Path::new("hello").to_path_buf().to_string_lossy(), "world")
+    //~^ ERROR [E0277]
+}
diff --git a/src/test/ui/typeck/issue-90101.stderr b/src/test/ui/typeck/issue-90101.stderr
new file mode 100644 (file)
index 0000000..998b636
--- /dev/null
@@ -0,0 +1,24 @@
+error[E0277]: the trait bound `PathBuf: From<Cow<'_, str>>` is not satisfied
+  --> $DIR/issue-90101.rs:6:10
+   |
+LL |     func(Path::new("hello").to_path_buf().to_string_lossy(), "world")
+   |     ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<Cow<'_, str>>` is not implemented for `PathBuf`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the following implementations were found:
+             <PathBuf as From<&T>>
+             <PathBuf as From<Box<Path>>>
+             <PathBuf as From<Cow<'a, Path>>>
+             <PathBuf as From<OsString>>
+             <PathBuf as From<String>>
+   = note: required because of the requirements on the impl of `Into<PathBuf>` for `Cow<'_, str>`
+note: required by a bound in `func`
+  --> $DIR/issue-90101.rs:3:20
+   |
+LL | fn func(path: impl Into<PathBuf>, code: impl Into<String>) {}
+   |                    ^^^^^^^^^^^^^ required by this bound in `func`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/typeck/issue-90164.rs b/src/test/ui/typeck/issue-90164.rs
new file mode 100644 (file)
index 0000000..6335043
--- /dev/null
@@ -0,0 +1,9 @@
+fn copy<R: Unpin, W>(_: R, _: W) {}
+
+fn f<T>(r: T) {
+    let w = ();
+    copy(r, w);
+    //~^ ERROR [E0277]
+}
+
+fn main() {}
diff --git a/src/test/ui/typeck/issue-90164.stderr b/src/test/ui/typeck/issue-90164.stderr
new file mode 100644 (file)
index 0000000..1e2f1ba
--- /dev/null
@@ -0,0 +1,22 @@
+error[E0277]: `T` cannot be unpinned
+  --> $DIR/issue-90164.rs:5:10
+   |
+LL |     copy(r, w);
+   |     ---- ^ the trait `Unpin` is not implemented for `T`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = note: consider using `Box::pin`
+note: required by a bound in `copy`
+  --> $DIR/issue-90164.rs:1:12
+   |
+LL | fn copy<R: Unpin, W>(_: R, _: W) {}
+   |            ^^^^^ required by this bound in `copy`
+help: consider restricting type parameter `T`
+   |
+LL | fn f<T: std::marker::Unpin>(r: T) {
+   |       ++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.rs b/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.rs
new file mode 100644 (file)
index 0000000..74e50d4
--- /dev/null
@@ -0,0 +1,14 @@
+// edition:2021
+
+mod m {
+  pub struct S { foo: i32 }
+  impl S {
+    pub fn foo(&self) -> i32 { 42 }
+  }
+}
+
+fn bar(s: &m::S) {
+  || s.foo() + s.foo; //~ ERROR E0616
+}
+
+fn main() {}
diff --git a/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr b/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr
new file mode 100644 (file)
index 0000000..02cdc10
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0616]: field `foo` of struct `S` is private
+  --> $DIR/issue-90483-inaccessible-field-adjustment.rs:11:18
+   |
+LL |   || s.foo() + s.foo;
+   |                  ^^^ private field
+   |
+help: a method `foo` also exists, call it with parentheses
+   |
+LL |   || s.foo() + s.foo();
+   |                     ++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0616`.
index 4b5804253b23b7efa555e35ce0ff0601eab5bc97..154e504996bc4001d441b668cebd388fd3e03f48 100644 (file)
@@ -29,10 +29,12 @@ LL | fn test<T: Sync>(s: T) {}
    |            ^^^^ required by this bound in `test`
 
 error[E0277]: `UnsafeCell<NoSync>` cannot be shared between threads safely
-  --> $DIR/typeck-unsafe-always-share.rs:27:5
+  --> $DIR/typeck-unsafe-always-share.rs:27:10
    |
 LL |     test(ms);
-   |     ^^^^ `UnsafeCell<NoSync>` cannot be shared between threads safely
+   |     ---- ^^ `UnsafeCell<NoSync>` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: within `MySync<NoSync>`, the trait `Sync` is not implemented for `UnsafeCell<NoSync>`
 note: required because it appears within the type `MySync<NoSync>`
diff --git a/src/test/ui/unary-minus-suffix-inference.rs b/src/test/ui/unary-minus-suffix-inference.rs
deleted file mode 100644 (file)
index a4d0a84..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// run-pass
-
-pub fn main() {
-    let a = 1;
-    let a_neg: i8 = -a;
-    println!("{}", a_neg);
-
-    let b = 1;
-    let b_neg: i16 = -b;
-    println!("{}", b_neg);
-
-    let c = 1;
-    let c_neg: i32 = -c;
-    println!("{}", c_neg);
-
-    let d = 1;
-    let d_neg: i64 = -d;
-    println!("{}", d_neg);
-
-    let e = 1;
-    let e_neg: isize = -e;
-    println!("{}", e_neg);
-}
diff --git a/src/test/ui/unboxed-closures/issue-18652.rs b/src/test/ui/unboxed-closures/issue-18652.rs
new file mode 100644 (file)
index 0000000..59aa015
--- /dev/null
@@ -0,0 +1,10 @@
+// run-pass
+// Tests multiple free variables being passed by value into an unboxed
+// once closure as an optimization by codegen.  This used to hit an
+// incorrect assert.
+
+fn main() {
+    let x = 2u8;
+    let y = 3u8;
+    assert_eq!((move || x + y)(), 5);
+}
index 76c14ccc14b4522906c1821bb06a5ec6c26b9572..8976da01e739beba94204208bf2482f6543e3b42 100644 (file)
@@ -5,6 +5,12 @@ LL | fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); }
    |                    ------      ------           ^ ...but data from `y` flows into `x` here
    |                                |
    |                                these two types are declared with different lifetimes...
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }
+   |       ++++              ~~          ~~
 
 error: aborting due to previous error
 
index e4e8b32c70ee9a1d6907d9d45adfb223861375a4..dcf0eb646f3b0591a1df8b2cbb9dac1cfc46faa0 100644 (file)
@@ -44,10 +44,10 @@ pub fn std() {}
 
 fn main() {
     foo::Foo(());
-    foo::std_io::stdout();
+    let _ = foo::std_io::stdout();
     foo::local_io(());
-    io::stdout();
-    bar::io::stdout();
+    let _ = io::stdout();
+    let _ = bar::io::stdout();
     bar::std();
     bar::std!();
 
@@ -56,6 +56,6 @@ fn main() {
         // scope is allowed, when both resolve to the same definition.
         use std::io;
         use io::stdout;
-        stdout();
+        let _ = stdout();
     }
 }
index 4e2e2dedef67924c9bb265bbba87d59500b691f1..ce611a7cacf38b887614240e2cfea8e076f86c5a 100644 (file)
@@ -20,7 +20,7 @@ mod std {
 
 fn main() {
     Foo(());
-    std_io::stdout();
+    let _ = std_io::stdout();
     local_io(());
 
     {
@@ -28,6 +28,6 @@ fn main() {
         // scope is allowed, when both resolve to the same definition.
         use ::std::io as std_io;
         use std_io::stdout;
-        stdout();
+        let _ = stdout();
     }
 }
index a62a28bb94d12681bf90d7ff97bfd750b914cfa4..175ccd34e98d92116d433f23bc2e15ab2720b269 100644 (file)
@@ -46,8 +46,8 @@ mod bar {
 
 fn main() {
     foo::Foo(());
-    foo::std_io::stdout();
+    let _ = foo::std_io::stdout();
     foo::local_io(());
-    io::stdout();
-    bar::io::stdout();
+    let _ = io::stdout();
+    let _ = bar::io::stdout();
 }
index 31b809f0cfdc5f2a5ad39ad08a64ca302017e2b9..bf512b30560eb7ebd8cb1b2c1d99800d47a4325d 100644 (file)
@@ -31,6 +31,6 @@ mod std {
 
 fn main() {
     Foo(());
-    std_io::stdout();
+    let _ = std_io::stdout();
     local_io(());
 }
diff --git a/src/test/ui/unnecessary-extern-crate.rs b/src/test/ui/unnecessary-extern-crate.rs
deleted file mode 100644 (file)
index 67eaaf4..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-// edition:2018
-
-#![deny(unused_extern_crates)]
-#![feature(test, rustc_private, crate_visibility_modifier)]
-
-extern crate libc;
-//~^ ERROR unused extern crate
-//~| HELP remove
-extern crate libc as x;
-//~^ ERROR unused extern crate
-//~| HELP remove
-
-extern crate proc_macro;
-
-#[macro_use]
-extern crate test;
-
-pub extern crate test as y;
-
-pub extern crate alloc;
-
-pub(crate) extern crate alloc as a;
-
-crate extern crate alloc as b;
-
-mod foo {
-    pub(in crate::foo) extern crate alloc as c;
-
-    pub(super) extern crate alloc as d;
-
-    extern crate libc;
-    //~^ ERROR unused extern crate
-    //~| HELP remove
-
-    extern crate libc as x;
-    //~^ ERROR unused extern crate
-    //~| HELP remove
-
-    pub extern crate test;
-
-    pub extern crate test as y;
-
-    mod bar {
-        extern crate libc;
-        //~^ ERROR unused extern crate
-        //~| HELP remove
-
-        extern crate libc as x;
-        //~^ ERROR unused extern crate
-        //~| HELP remove
-
-        pub(in crate::foo::bar) extern crate alloc as e;
-
-        fn dummy() {
-            e::string::String::new();
-        }
-    }
-
-    fn dummy() {
-        c::string::String::new();
-        d::string::String::new();
-    }
-}
-
-
-fn main() {
-    a::string::String::new();
-    b::string::String::new();
-
-    proc_macro::TokenStream::new();
-}
diff --git a/src/test/ui/unnecessary-extern-crate.stderr b/src/test/ui/unnecessary-extern-crate.stderr
deleted file mode 100644 (file)
index 14ba9d0..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-error: unused extern crate
-  --> $DIR/unnecessary-extern-crate.rs:6:1
-   |
-LL | extern crate libc;
-   | ^^^^^^^^^^^^^^^^^^ help: remove it
-   |
-note: the lint level is defined here
-  --> $DIR/unnecessary-extern-crate.rs:3:9
-   |
-LL | #![deny(unused_extern_crates)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error: unused extern crate
-  --> $DIR/unnecessary-extern-crate.rs:9:1
-   |
-LL | extern crate libc as x;
-   | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
-
-error: unused extern crate
-  --> $DIR/unnecessary-extern-crate.rs:31:5
-   |
-LL |     extern crate libc;
-   |     ^^^^^^^^^^^^^^^^^^ help: remove it
-
-error: unused extern crate
-  --> $DIR/unnecessary-extern-crate.rs:35:5
-   |
-LL |     extern crate libc as x;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
-
-error: unused extern crate
-  --> $DIR/unnecessary-extern-crate.rs:44:9
-   |
-LL |         extern crate libc;
-   |         ^^^^^^^^^^^^^^^^^^ help: remove it
-
-error: unused extern crate
-  --> $DIR/unnecessary-extern-crate.rs:48:9
-   |
-LL |         extern crate libc as x;
-   |         ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
-
-error: aborting due to 6 previous errors
-
diff --git a/src/test/ui/unrestricted-attribute-tokens.rs b/src/test/ui/unrestricted-attribute-tokens.rs
deleted file mode 100644 (file)
index e31bc91..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// build-pass (FIXME(62277): could be check-pass?)
-
-#![feature(rustc_attrs)]
-
-#[rustc_dummy(a b c d)]
-#[rustc_dummy[a b c d]]
-#[rustc_dummy{a b c d}]
-fn main() {}
index 6686e55130fb453579d774d736238a9282612281..6960255d98797492815899c0bebc915e1feedd59 100644 (file)
@@ -16,7 +16,7 @@ LL |     udrop::<A<[u8]>>(A { 0: *foo() });
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Sized` is not implemented for `[u8]`
+   = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]`
 note: required because it appears within the type `A<[u8]>`
   --> $DIR/unsized-exprs.rs:3:8
    |
diff --git a/src/test/ui/unsized/issue-30355.rs b/src/test/ui/unsized/issue-30355.rs
new file mode 100644 (file)
index 0000000..6ff5b37
--- /dev/null
@@ -0,0 +1,9 @@
+pub struct X([u8]);
+
+pub static Y: &'static X = {
+    const Y: &'static [u8] = b"";
+    &X(*Y)
+    //~^ ERROR E0277
+};
+
+fn main() {}
diff --git a/src/test/ui/unsized/issue-30355.stderr b/src/test/ui/unsized/issue-30355.stderr
new file mode 100644 (file)
index 0000000..71bbdf5
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/issue-30355.rs:5:8
+   |
+LL |     &X(*Y)
+   |        ^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+   = note: all function arguments must have a statically known size
+   = help: unsized fn params are gated as an unstable feature
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index 83199e8112e71d2ad12245d61793e49d91e142bc..93c7af68ac388e145714fe11c473d29eb0b5b16b 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(relaxed_struct_unsize)]
 // run-pass
 // Test that we allow unsizing even if there is an unchanged param in the
 // field getting unsized.
index 9339a004d3b742bf138b79f0c3014e08737d72c5..6ac558974d0c5476e6a606ffe3006a0b050607ac 100644 (file)
@@ -1,7 +1,7 @@
 // --extern-location with a raw reference
 
 // aux-crate:bar=bar.rs
-// compile-flags:--extern-location bar
+// compile-flags:--extern-location bar -Zunstable-options
 
 #![warn(unused_crate_dependencies)]
 
index 5fe85954dc8e98f3266d56a11a086e1c39b757bd..ca6b8ba94d1cab407a85482ac1695aebbe843f4f 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(use_nested_groups)]
 #![allow(dead_code)]
 #![deny(unused_imports)]
 
index 987d1dcf5f00de3e1b85d0b6e40f149945dcdd88..6610f8ecd4a28d5ee6290fa368335466b984f6d3 100644 (file)
@@ -1,23 +1,23 @@
 error: unused imports: `*`, `Foo`, `baz::{}`, `foobar::*`
-  --> $DIR/use-nested-groups-unused-imports.rs:16:11
+  --> $DIR/use-nested-groups-unused-imports.rs:15:11
    |
 LL | use foo::{Foo, bar::{baz::{}, foobar::*}, *};
    |           ^^^        ^^^^^^^  ^^^^^^^^^   ^
    |
 note: the lint level is defined here
-  --> $DIR/use-nested-groups-unused-imports.rs:3:9
+  --> $DIR/use-nested-groups-unused-imports.rs:2:9
    |
 LL | #![deny(unused_imports)]
    |         ^^^^^^^^^^^^^^
 
 error: unused import: `*`
-  --> $DIR/use-nested-groups-unused-imports.rs:18:24
+  --> $DIR/use-nested-groups-unused-imports.rs:17:24
    |
 LL | use foo::bar::baz::{*, *};
    |                        ^
 
 error: unused import: `foo::{}`
-  --> $DIR/use-nested-groups-unused-imports.rs:20:5
+  --> $DIR/use-nested-groups-unused-imports.rs:19:5
    |
 LL | use foo::{};
    |     ^^^^^^^
diff --git a/src/test/ui/warn-ctypes-inhibit.rs b/src/test/ui/warn-ctypes-inhibit.rs
deleted file mode 100644 (file)
index 15d8b09..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// run-pass
-
-#![allow(dead_code)]
-// compile-flags:-D improper-ctypes
-
-// pretty-expanded FIXME #23616
-#![allow(improper_ctypes)]
-
-mod libc {
-    extern "C" {
-        pub fn malloc(size: isize) -> *const u8;
-    }
-}
-
-pub fn main() {}
index 2bf4cfc50032049e780b88db39ab6fe47ca0dfd8..868923e5932438bf8b8c5d48c0093090e5a01acb 100644 (file)
@@ -28,10 +28,11 @@ pub fn main() {
           target_os = "emscripten",
           target_os = "freebsd",
           target_os = "fuchsia",
+          target_os = "illumos",
           target_os = "linux",
           target_os = "macos",
           target_os = "netbsd",
           target_os = "openbsd",
-          target_os = "vxworks",
-          target_os = "solaris"))]
+          target_os = "solaris",
+          target_os = "vxworks"))]
 pub fn main() { }
diff --git a/src/test/ui/yield2.rs b/src/test/ui/yield2.rs
deleted file mode 100644 (file)
index 376faab..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-pass
-
-use std::thread;
-
-pub fn main() {
-    let mut i: isize = 0;
-    while i < 100 { i = i + 1; println!("{}", i); thread::yield_now(); }
-}
index 96d3c873843318e3bff6d9d60ccd1a69c92c7166..d6364e28fef97f2394694d80e550419ea16f25b2 100644 (file)
@@ -196,7 +196,6 @@ struct ManifestPackage {
 
 #[derive(Debug, serde::Deserialize)]
 struct ManifestTargetPackage {
-    available: bool,
     url: Option<String>,
     hash: Option<String>,
     xz_url: Option<String>,
index 7fbbf4e8f23e3c24b8afff541dcb17e53eb5ff88..2e2a16e983f597da62bc132eb191bc3276d4b1bb 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 7fbbf4e8f23e3c24b8afff541dcb17e53eb5ff88
+Subproject commit 2e2a16e983f597da62bc132eb191bc3276d4b1bb
diff --git a/src/tools/clippy/.cargo/config b/src/tools/clippy/.cargo/config
deleted file mode 100644 (file)
index 688473f..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-[alias]
-uitest = "test --test compile-test"
-dev = "run --package clippy_dev --bin clippy_dev --manifest-path clippy_dev/Cargo.toml --"
-lintcheck = "run --package lintcheck --bin lintcheck --manifest-path lintcheck/Cargo.toml  -- "
-collect-metadata = "test --test dogfood --features metadata-collector-lint -- run_metadata_collection_lint --ignored"
-
-[build]
-# -Zbinary-dep-depinfo allows us to track which rlib files to use for compiling UI tests
-rustflags = ["-Zunstable-options", "-Zbinary-dep-depinfo"]
-target-dir = "target"
diff --git a/src/tools/clippy/.cargo/config.toml b/src/tools/clippy/.cargo/config.toml
new file mode 100644 (file)
index 0000000..688473f
--- /dev/null
@@ -0,0 +1,10 @@
+[alias]
+uitest = "test --test compile-test"
+dev = "run --package clippy_dev --bin clippy_dev --manifest-path clippy_dev/Cargo.toml --"
+lintcheck = "run --package lintcheck --bin lintcheck --manifest-path lintcheck/Cargo.toml  -- "
+collect-metadata = "test --test dogfood --features metadata-collector-lint -- run_metadata_collection_lint --ignored"
+
+[build]
+# -Zbinary-dep-depinfo allows us to track which rlib files to use for compiling UI tests
+rustflags = ["-Zunstable-options", "-Zbinary-dep-depinfo"]
+target-dir = "target"
index a3c57232f557c4b774cb53ecc7e10299db1bd8e6..34225a5402904084617e9f19adaaa762d0aa5336 100644 (file)
@@ -13,7 +13,8 @@ cp util/gh-pages/lints.json out/master
 if [[ -n $TAG_NAME ]]; then
   echo "Save the doc for the current tag ($TAG_NAME) and point stable/ to it"
   cp -Tr out/master "out/$TAG_NAME"
-  ln -sf "$TAG_NAME" out/stable
+  rm -f out/stable
+  ln -s "$TAG_NAME" out/stable
 fi
 
 if [[ $BETA = "true" ]]; then
index 3b4c687209e11dfa8ebb9454ad8c4af571a9677f..85a6a6be8b7f2618d9b515afc201e54f27781e13 100644 (file)
@@ -6,11 +6,162 @@ document.
 
 ## Unreleased / In Rust Nightly
 
-[7bfc26e...master](https://github.com/rust-lang/rust-clippy/compare/7bfc26e...master)
+[b7f3f7f...master](https://github.com/rust-lang/rust-clippy/compare/b7f3f7f...master)
+
+## Rust 1.57
+
+Current beta, release 2021-12-02
+
+[7bfc26e...b7f3f7f](https://github.com/rust-lang/rust-clippy/compare/7bfc26e...b7f3f7f)
+
+### New Lints
+
+* [`negative_feature_names`]
+  [#7539](https://github.com/rust-lang/rust-clippy/pull/7539)
+* [`redundant_feature_names`]
+  [#7539](https://github.com/rust-lang/rust-clippy/pull/7539)
+* [`mod_module_files`]
+  [#7543](https://github.com/rust-lang/rust-clippy/pull/7543)
+* [`self_named_module_files`]
+  [#7543](https://github.com/rust-lang/rust-clippy/pull/7543)
+* [`manual_split_once`]
+  [#7565](https://github.com/rust-lang/rust-clippy/pull/7565)
+* [`derivable_impls`]
+  [#7570](https://github.com/rust-lang/rust-clippy/pull/7570)
+* [`needless_option_as_deref`]
+  [#7596](https://github.com/rust-lang/rust-clippy/pull/7596)
+* [`iter_not_returning_iterator`]
+  [#7610](https://github.com/rust-lang/rust-clippy/pull/7610)
+* [`same_name_method`]
+  [#7653](https://github.com/rust-lang/rust-clippy/pull/7653)
+* [`manual_assert`] [#7669](https://github.com/rust-lang/rust-clippy/pull/7669)
+* [`non_send_fields_in_send_ty`]
+  [#7709](https://github.com/rust-lang/rust-clippy/pull/7709)
+* [`equatable_if_let`]
+  [#7762](https://github.com/rust-lang/rust-clippy/pull/7762)
+
+### Moves and Deprecations
+
+* Move [`shadow_unrelated`] to `restriction`
+  [#7338](https://github.com/rust-lang/rust-clippy/pull/7338)
+* Move [`option_if_let_else`] to `nursery`
+  [#7568](https://github.com/rust-lang/rust-clippy/pull/7568)
+* Move [`branches_sharing_code`] to `nursery`
+  [#7595](https://github.com/rust-lang/rust-clippy/pull/7595)
+* Rename `if_let_some_result` to [`match_result_ok`] which now also handles
+  `while let` cases [#7608](https://github.com/rust-lang/rust-clippy/pull/7608)
+* Move [`many_single_char_names`] to `pedantic`
+  [#7671](https://github.com/rust-lang/rust-clippy/pull/7671)
+* Move [`float_cmp`] to `pedantic`
+  [#7692](https://github.com/rust-lang/rust-clippy/pull/7692)
+* Rename `box_vec` to [`box_collection`] and lint on more general cases
+  [#7693](https://github.com/rust-lang/rust-clippy/pull/7693)
+* Uplift `invalid_atomic_ordering` to rustc
+  [rust-lang/rust#84039](https://github.com/rust-lang/rust/pull/84039)
+
+### Enhancements
+
+* Rewrite the `shadow*` lints, so that they find a lot more shadows and are not
+  limited to certain patterns
+  [#7338](https://github.com/rust-lang/rust-clippy/pull/7338)
+* The `avoid-breaking-exported-api` configuration now also works for
+  [`box_collection`], [`redundant_allocation`], [`rc_buffer`], [`vec_box`],
+  [`option_option`], [`linkedlist`], [`rc_mutex`]
+  [#7560](https://github.com/rust-lang/rust-clippy/pull/7560)
+* [`unnecessary_unwrap`]: Now also checks for `expect`s
+  [#7584](https://github.com/rust-lang/rust-clippy/pull/7584)
+* [`disallowed_method`]: Allow adding a reason that will be displayed with the
+  lint message
+  [#7621](https://github.com/rust-lang/rust-clippy/pull/7621)
+* [`approx_constant`]: Now checks the MSRV for `LOG10_2` and `LOG2_10`
+  [#7629](https://github.com/rust-lang/rust-clippy/pull/7629)
+* [`approx_constant`]: Add `TAU`
+  [#7642](https://github.com/rust-lang/rust-clippy/pull/7642)
+* [`needless_borrow`]: Now also lints on needless mutable borrows
+  [#7657](https://github.com/rust-lang/rust-clippy/pull/7657)
+* [`missing_safety_doc`]: Now also lints on unsafe traits
+  [#7734](https://github.com/rust-lang/rust-clippy/pull/7734)
+
+### False Positive Fixes
+
+* [`manual_map`]: No longer lints when the option is borrowed in the match and
+  also consumed in the arm
+  [#7531](https://github.com/rust-lang/rust-clippy/pull/7531)
+* [`filter_next`]: No longer lints if `filter` method is not the
+  `Iterator::filter` method
+  [#7562](https://github.com/rust-lang/rust-clippy/pull/7562)
+* [`manual_flatten`]: No longer lints if expression is used after `if let`
+  [#7566](https://github.com/rust-lang/rust-clippy/pull/7566)
+* [`option_if_let_else`]: Multiple fixes
+  [#7573](https://github.com/rust-lang/rust-clippy/pull/7573)
+    * `break` and `continue` statements local to the would-be closure are
+      allowed
+    * Don't lint in const contexts
+    * Don't lint when yield expressions are used
+    * Don't lint when the captures made by the would-be closure conflict with
+      the other branch
+    * Don't lint when a field of a local is used when the type could be
+      potentially moved from
+    * In some cases, don't lint when scrutinee expression conflicts with the
+      captures of the would-be closure
+* [`redundant_allocation`]: No longer lints on `Box<Box<dyn T>>` which replaces
+  wide pointers with thin pointers
+  [#7592](https://github.com/rust-lang/rust-clippy/pull/7592)
+* [`bool_assert_comparison`]: No longer lints on types that do not implement the
+  `Not` trait with `Output = bool`
+  [#7605](https://github.com/rust-lang/rust-clippy/pull/7605)
+* [`mut_range_bound`]: No longer lints on range bound mutations, that are
+  immediately followed by a `break;`
+  [#7607](https://github.com/rust-lang/rust-clippy/pull/7607)
+* [`mutable_key_type`]: Improve accuracy and document remaining false positives
+  and false negatives
+  [#7640](https://github.com/rust-lang/rust-clippy/pull/7640)
+* [`redundant_closure`]: Rewrite the lint to fix various false positives and
+  false negatives [#7661](https://github.com/rust-lang/rust-clippy/pull/7661)
+* [`large_enum_variant`]: No longer wrongly identifies the second largest
+  variant [#7677](https://github.com/rust-lang/rust-clippy/pull/7677)
+* [`needless_return`]: No longer lints on let-else expressions
+  [#7685](https://github.com/rust-lang/rust-clippy/pull/7685)
+* [`suspicious_else_formatting`]: No longer lints in proc-macros
+  [#7707](https://github.com/rust-lang/rust-clippy/pull/7707)
+* [`excessive_precision`]: No longer lints when in some cases the float was
+  already written in the shortest form
+  [#7722](https://github.com/rust-lang/rust-clippy/pull/7722)
+* [`doc_markdown`]: No longer lints on intra-doc links
+  [#7772](https://github.com/rust-lang/rust-clippy/pull/7772)
+
+### Suggestion Fixes/Improvements
+
+* [`unnecessary_operation`]: Recommend using an `assert!` instead of using a
+  function call in an indexing operation
+  [#7453](https://github.com/rust-lang/rust-clippy/pull/7453)
+* [`manual_split_once`]: Produce semantically equivalent suggestion when
+  `rsplitn` is used [#7663](https://github.com/rust-lang/rust-clippy/pull/7663)
+* [`while_let_on_iterator`]: Produce correct suggestion when using `&mut`
+  [#7690](https://github.com/rust-lang/rust-clippy/pull/7690)
+* [`manual_assert`]: No better handles complex conditions
+  [#7741](https://github.com/rust-lang/rust-clippy/pull/7741)
+* Correctly handle signs in exponents in numeric literals lints
+  [#7747](https://github.com/rust-lang/rust-clippy/pull/7747)
+* [`suspicious_map`]: Now also suggests to use `inspect` as an alternative
+  [#7770](https://github.com/rust-lang/rust-clippy/pull/7770)
+* Drop exponent from suggestion if it is 0 in numeric literals lints
+  [#7774](https://github.com/rust-lang/rust-clippy/pull/7774)
+
+### ICE Fixes
+
+* [`implicit_hasher`]
+  [#7761](https://github.com/rust-lang/rust-clippy/pull/7761)
+
+### Others
+
+* Clippy now uses the 2021
+  [Edition!](https://www.youtube.com/watch?v=q0aNduqb2Ro)
+  [#7664](https://github.com/rust-lang/rust-clippy/pull/7664)
 
 ## Rust 1.56
 
-Current beta, release 2021-10-21
+Current stable, released 2021-10-21
 
 [74d1561...7bfc26e](https://github.com/rust-lang/rust-clippy/compare/74d1561...7bfc26e)
 
@@ -74,13 +225,9 @@ Current beta, release 2021-10-21
 * [`unnested_or_patterns`]: Removed `or_patterns` feature gate in the code
   example [#7507](https://github.com/rust-lang/rust-clippy/pull/7507)
 
-### New Lints
-
-* Renamed Lint: `if_let_some_result` is now called [`match_result_ok`]. Now also handles `while let` case.
-
 ## Rust 1.55
 
-Current stable, released 2021-09-09
+Released 2021-09-09
 
 [3ae8faf...74d1561](https://github.com/rust-lang/rust-clippy/compare/3ae8faf...74d1561)
 
@@ -2748,7 +2895,6 @@ Released 2018-09-13
 [`if_let_redundant_pattern_matching`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_redundant_pattern_matching
 [`if_not_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_not_else
 [`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else
-[`if_then_panic`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_panic
 [`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none
 [`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
 [`implicit_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_clone
@@ -2806,6 +2952,7 @@ Released 2018-09-13
 [`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal
 [`macro_use_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_imports
 [`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion
+[`manual_assert`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_assert
 [`manual_async_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn
 [`manual_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter_map
 [`manual_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find_map
@@ -2976,6 +3123,7 @@ Released 2018-09-13
 [`self_named_constructors`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_constructors
 [`self_named_module_files`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_module_files
 [`semicolon_if_nothing_returned`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
+[`separated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/master/index.html#separated_literal_suffix
 [`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse
 [`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse
 [`shadow_same`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_same
@@ -3000,6 +3148,7 @@ Released 2018-09-13
 [`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_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_slice
 [`string_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_to_string
 [`strlen_on_c_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#strlen_on_c_strings
 [`struct_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools
@@ -3046,6 +3195,7 @@ Released 2018-09-13
 [`uninit_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#uninit_vec
 [`unit_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_arg
 [`unit_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_cmp
+[`unit_hash`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_hash
 [`unit_return_expecting_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_return_expecting_ord
 [`unnecessary_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast
 [`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map
index 4273fda4e640d5d9356a5d63f166db26224fc603..97ff31b4bc5a3181727c5d8230ea463a6c1c170a 100644 (file)
@@ -262,7 +262,9 @@ to be run inside the `rust` directory):
 2. Checkout the commit from the latest available nightly. You can get it using `rustup check`.
 3. Sync the changes to the rust-copy of Clippy to your Clippy fork:
     ```bash
-    # Make sure to change `your-github-name` to your github name in the following command
+    # Make sure to change `your-github-name` to your github name in the following command. Also be
+    # sure to either use a net-new branch, e.g. `sync-from-rust`, or delete the branch beforehand
+    # because changes cannot be fast forwarded
     git subtree push -P src/tools/clippy git@github.com:your-github-name/rust-clippy sync-from-rust
     ```
 
index ed7fb1440139f7d199f5632cb54525633c0d48a1..602877bb9d6831dfd824f6d0e8a4fdf143e96b59 100644 (file)
@@ -22,13 +22,13 @@ path = "src/driver.rs"
 
 [dependencies]
 clippy_lints = { version = "0.1", path = "clippy_lints" }
-semver = "0.11"
+semver = "1.0"
 rustc_tools_util = { version = "0.2", path = "rustc_tools_util" }
 tempfile = { version = "3.2", optional = true }
 
 [dev-dependencies]
-cargo_metadata = "0.12"
-compiletest_rs = { version = "0.7", features = ["tmp"] }
+cargo_metadata = "0.14"
+compiletest_rs = { version = "0.7.1", features = ["tmp"] }
 tester = "0.9"
 regex = "1.5"
 # This is used by the `collect-metadata` alias.
index 25320907bb492767f36da58f48e97d0b2d366477..43a478ee77db826975fcbda09202af1381a2981b 100644 (file)
@@ -42,7 +42,8 @@ pub fn create(pass: Option<&str>, lint_name: Option<&str>, category: Option<&str
     };
 
     create_lint(&lint, msrv).context("Unable to create lint implementation")?;
-    create_test(&lint).context("Unable to create a test for the new lint")
+    create_test(&lint).context("Unable to create a test for the new lint")?;
+    add_lint(&lint, msrv).context("Unable to add lint to clippy_lints/src/lib.rs")
 }
 
 fn create_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> {
@@ -80,6 +81,33 @@ fn create_project_layout<P: Into<PathBuf>>(lint_name: &str, location: P, case: &
     }
 }
 
+fn add_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> {
+    let path = "clippy_lints/src/lib.rs";
+    let mut lib_rs = fs::read_to_string(path).context("reading")?;
+
+    let comment_start = lib_rs.find("// add lints here,").expect("Couldn't find comment");
+
+    let new_lint = if enable_msrv {
+        format!(
+            "store.register_{lint_pass}_pass(move || Box::new({module_name}::{camel_name}::new(msrv)));\n    ",
+            lint_pass = lint.pass,
+            module_name = lint.name,
+            camel_name = to_camel_case(lint.name),
+        )
+    } else {
+        format!(
+            "store.register_{lint_pass}_pass(|| Box::new({module_name}::{camel_name}));\n    ",
+            lint_pass = lint.pass,
+            module_name = lint.name,
+            camel_name = to_camel_case(lint.name),
+        )
+    };
+
+    lib_rs.insert_str(comment_start, &new_lint);
+
+    fs::write(path, lib_rs).context("writing")
+}
+
 fn write_file<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> {
     fn inner(path: &Path, contents: &[u8]) -> io::Result<()> {
         OpenOptions::new()
@@ -151,7 +179,6 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
     };
 
     let lint_name = lint.name;
-    let pass_name = lint.pass;
     let category = lint.category;
     let name_camel = to_camel_case(lint.name);
     let name_upper = lint_name.to_uppercase();
@@ -228,18 +255,14 @@ impl {pass_type}{pass_lifetimes} for {name_camel} {{
                     extract_msrv_attr!({context_import});
                 }}
 
-                // TODO: Register the lint pass in `clippy_lints/src/lib.rs`,
-                //       e.g. store.register_{pass_name}_pass(move || Box::new({module_name}::{name_camel}::new(msrv)));
                 // TODO: Add MSRV level to `clippy_utils/src/msrvs.rs` if needed.
                 // TODO: Add MSRV test to `tests/ui/min_rust_version_attr.rs`.
                 // TODO: Update msrv config comment in `clippy_lints/src/utils/conf.rs`
             "},
             pass_type = pass_type,
             pass_lifetimes = pass_lifetimes,
-            pass_name = pass_name,
             name_upper = name_upper,
             name_camel = name_camel,
-            module_name = lint_name,
             context_import = context_import,
         )
     } else {
@@ -248,16 +271,11 @@ impl {pass_type}{pass_lifetimes} for {name_camel} {{
                 declare_lint_pass!({name_camel} => [{name_upper}]);
 
                 impl {pass_type}{pass_lifetimes} for {name_camel} {{}}
-                //
-                // TODO: Register the lint pass in `clippy_lints/src/lib.rs`,
-                //       e.g. store.register_{pass_name}_pass(|| Box::new({module_name}::{name_camel}));
             "},
             pass_type = pass_type,
             pass_lifetimes = pass_lifetimes,
-            pass_name = pass_name,
             name_upper = name_upper,
             name_camel = name_camel,
-            module_name = lint_name,
         )
     });
 
index aaf9ac83d49005dad0df8a05de2dc7818dcedd06..281480b8d94914c2d1835a1fb7d2d1fb62620b18 100644 (file)
@@ -9,7 +9,7 @@ keywords = ["clippy", "lint", "plugin"]
 edition = "2021"
 
 [dependencies]
-cargo_metadata = "0.12"
+cargo_metadata = "0.14"
 clippy_utils = { path = "../clippy_utils" }
 if_chain = "1.0"
 itertools = "0.10"
@@ -21,7 +21,7 @@ serde_json = { version = "1.0", optional = true }
 toml = "0.5"
 unicode-normalization = "0.1"
 unicode-script = { version = "0.5", default-features = false }
-semver = "0.11"
+semver = "1.0"
 rustc-semver = "1.1"
 # NOTE: cargo requires serde feat in its url dep
 # see <https://github.com/rust-lang/rust/pull/63587#issuecomment-522343864>
index 833ad122e0d4e20c46ae07f32c94157a4120f218..4af412ccaf35d7d0946429c5b997f9ae7081792e 100644 (file)
@@ -1,15 +1,88 @@
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint;
+use clippy_utils::expr_or_init;
 use clippy_utils::ty::is_isize_or_usize;
-use rustc_hir::Expr;
+use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, FloatTy, Ty};
 
 use super::{utils, CAST_POSSIBLE_TRUNCATION};
 
-pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
+fn constant_int(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u128> {
+    if let Some((Constant::Int(c), _)) = constant(cx, cx.typeck_results(), expr) {
+        Some(c)
+    } else {
+        None
+    }
+}
+
+fn get_constant_bits(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u64> {
+    constant_int(cx, expr).map(|c| u64::from(128 - c.leading_zeros()))
+}
+
+fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: bool) -> u64 {
+    match expr_or_init(cx, expr).kind {
+        ExprKind::Cast(inner, _) => apply_reductions(cx, nbits, inner, signed),
+        ExprKind::Block(block, _) => block.expr.map_or(nbits, |e| apply_reductions(cx, nbits, e, signed)),
+        ExprKind::Binary(op, left, right) => match op.node {
+            BinOpKind::Div => {
+                apply_reductions(cx, nbits, left, signed)
+                    - (if signed {
+                        0 // let's be conservative here
+                    } else {
+                        // by dividing by 1, we remove 0 bits, etc.
+                        get_constant_bits(cx, right).map_or(0, |b| b.saturating_sub(1))
+                    })
+            },
+            BinOpKind::Rem | BinOpKind::BitAnd => get_constant_bits(cx, right)
+                .unwrap_or(u64::max_value())
+                .min(apply_reductions(cx, nbits, left, signed)),
+            BinOpKind::Shr => {
+                apply_reductions(cx, nbits, left, signed)
+                    - constant_int(cx, right).map_or(0, |s| u64::try_from(s).expect("shift too high"))
+            },
+            _ => nbits,
+        },
+        ExprKind::MethodCall(method, _, [left, right], _) => {
+            if signed {
+                return nbits;
+            }
+            let max_bits = if method.ident.as_str() == "min" {
+                get_constant_bits(cx, right)
+            } else {
+                None
+            };
+            apply_reductions(cx, nbits, left, signed).min(max_bits.unwrap_or(u64::max_value()))
+        },
+        ExprKind::MethodCall(method, _, [_, lo, hi], _) => {
+            if method.ident.as_str() == "clamp" {
+                //FIXME: make this a diagnostic item
+                if let (Some(lo_bits), Some(hi_bits)) = (get_constant_bits(cx, lo), get_constant_bits(cx, hi)) {
+                    return lo_bits.max(hi_bits);
+                }
+            }
+            nbits
+        },
+        ExprKind::MethodCall(method, _, [_value], _) => {
+            if method.ident.name.as_str() == "signum" {
+                0 // do not lint if cast comes from a `signum` function
+            } else {
+                nbits
+            }
+        },
+        _ => nbits,
+    }
+}
+
+pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
     let msg = match (cast_from.is_integral(), cast_to.is_integral()) {
         (true, true) => {
-            let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx);
+            let from_nbits = apply_reductions(
+                cx,
+                utils::int_ty_to_nbits(cast_from, cx.tcx),
+                cast_expr,
+                cast_from.is_signed(),
+            );
             let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx);
 
             let (should_lint, suffix) = match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) {
index f0800c6a6f18f788bbb2804b20aaba1b8b362fc6..233abd178943e9bc20b2685c68fd55f03d46a9c3 100644 (file)
@@ -427,7 +427,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
             fn_to_numeric_cast::check(cx, expr, cast_expr, cast_from, cast_to);
             fn_to_numeric_cast_with_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
             if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx.sess(), expr.span) {
-                cast_possible_truncation::check(cx, expr, cast_from, cast_to);
+                cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
                 cast_possible_wrap::check(cx, expr, cast_from, cast_to);
                 cast_precision_loss::check(cx, expr, cast_from, cast_to);
                 cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to);
index c604516742ce5a1a510862792bc48cb7fdb1b01e..9d8524ec91cc6e08f7c2ea056aabb58f3103e02e 100644 (file)
@@ -1,3 +1,6 @@
+// NOTE: if you add a deprecated lint in this file, please add a corresponding test in
+// tests/ui/deprecated.rs
+
 /// This struct fakes the `Lint` declaration that is usually created by `declare_lint!`. This
 /// enables the simple extraction of the metadata without changing the current deprecation
 /// declaration.
index 7825e5f6ed52e45f9f715c0cb2b93fd55a4fc9ca..ce59311c4aa96acac5154ce00f02e3d0a746fa99 100644 (file)
@@ -126,7 +126,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                                 target_mut,
                             },
                         ));
-                    }
+                    },
                     _ => (),
                 }
             },
index 5511c3ea9b6889701a2dbdfaf015fdec0fa5b987..d4ba072807f8f891adb1de3f37b3327d5b9ea0eb 100644 (file)
@@ -1,16 +1,16 @@
 use clippy_utils::attrs::is_doc_hidden;
-use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_note};
-use clippy_utils::source::first_line_of_span;
+use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_note, span_lint_and_sugg};
+use clippy_utils::source::{first_line_of_span, snippet_with_applicability};
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
 use clippy_utils::{is_entrypoint_fn, is_expn_of, match_panic_def_id, method_chain_args, return_ty};
 use if_chain::if_chain;
 use itertools::Itertools;
-use rustc_ast::ast::{Async, AttrKind, Attribute, FnKind, FnRetTy, ItemKind};
+use rustc_ast::ast::{Async, AttrKind, Attribute, Fn, FnRetTy, ItemKind};
 use rustc_ast::token::CommentKind;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::emitter::EmitterWriter;
-use rustc_errors::Handler;
+use rustc_errors::{Applicability, Handler};
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{AnonConst, Expr, ExprKind, QPath};
@@ -48,7 +48,7 @@
     /// content are not linted.
     ///
     /// In addition, when writing documentation comments, including `[]` brackets
-    /// inside a link text would trip the parser. Therfore, documenting link with
+    /// inside a link text would trip the parser. Therefore, documenting link with
     /// `[`SmallVec<[T; INLINE_CAPACITY]>`]` and then [`SmallVec<[T; INLINE_CAPACITY]>`]: SmallVec
     /// would fail.
     ///
@@ -578,9 +578,12 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                     // text "http://example.com" by pulldown-cmark
                     continue;
                 }
-                headers.safety |= in_heading && text.trim() == "Safety";
-                headers.errors |= in_heading && text.trim() == "Errors";
-                headers.panics |= in_heading && text.trim() == "Panics";
+                let trimmed_text = text.trim();
+                headers.safety |= in_heading && trimmed_text == "Safety";
+                headers.safety |= in_heading && trimmed_text == "Implementation safety";
+                headers.safety |= in_heading && trimmed_text == "Implementation Safety";
+                headers.errors |= in_heading && trimmed_text == "Errors";
+                headers.panics |= in_heading && trimmed_text == "Panics";
                 if in_code {
                     if is_rust {
                         let edition = edition.unwrap_or_else(|| cx.tcx.sess.edition());
@@ -636,7 +639,7 @@ fn has_needless_main(code: String, edition: Edition) -> bool {
                             | ItemKind::ExternCrate(..)
                             | ItemKind::ForeignMod(..) => return false,
                             // We found a main function ...
-                            ItemKind::Fn(box FnKind(_, sig, _, Some(block))) if item.ident.name == sym::main => {
+                            ItemKind::Fn(box Fn { sig, body: Some(block), .. }) if item.ident.name == sym::main => {
                                 let is_async = matches!(sig.header.asyncness, Async::Yes { .. });
                                 let returns_nothing = match &sig.decl.output {
                                     FnRetTy::Default(..) => true,
@@ -686,10 +689,18 @@ fn check_text(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, text: &str
     for word in text.split(|c: char| c.is_whitespace() || c == '\'') {
         // Trim punctuation as in `some comment (see foo::bar).`
         //                                                   ^^
-        // Or even as in `_foo bar_` which is emphasized.
-        let word = word.trim_matches(|c: char| !c.is_alphanumeric());
+        // Or even as in `_foo bar_` which is emphasized. Also preserve `::` as a prefix/suffix.
+        let mut word = word.trim_matches(|c: char| !c.is_alphanumeric() && c != ':');
 
-        if valid_idents.contains(word) {
+        // Remove leading or trailing single `:` which may be part of a sentence.
+        if word.starts_with(':') && !word.starts_with("::") {
+            word = word.trim_start_matches(':');
+        }
+        if word.ends_with(':') && !word.ends_with("::") {
+            word = word.trim_end_matches(':');
+        }
+
+        if valid_idents.contains(word) || word.chars().all(|c| c == ':') {
             continue;
         }
 
@@ -744,17 +755,22 @@ fn has_hyphen(s: &str) -> bool {
         }
     }
 
-    // We assume that mixed-case words are not meant to be put inside bacticks. (Issue #2343)
+    // We assume that mixed-case words are not meant to be put inside backticks. (Issue #2343)
     if has_underscore(word) && has_hyphen(word) {
         return;
     }
 
     if has_underscore(word) || word.contains("::") || is_camel_case(word) {
-        span_lint(
+        let mut applicability = Applicability::MachineApplicable;
+
+        span_lint_and_sugg(
             cx,
             DOC_MARKDOWN,
             span,
-            &format!("you should put `{}` between ticks in the documentation", word),
+            "item in documentation is missing backticks",
+            "try",
+            format!("`{}`", snippet_with_applicability(cx, span, "..", &mut applicability)),
+            applicability,
         );
     }
 }
@@ -793,9 +809,9 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
 
         // check for `unwrap`
         if let Some(arglists) = method_chain_args(expr, &["unwrap"]) {
-            let reciever_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs();
-            if is_type_diagnostic_item(self.cx, reciever_ty, sym::Option)
-                || is_type_diagnostic_item(self.cx, reciever_ty, sym::Result)
+            let receiver_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs();
+            if is_type_diagnostic_item(self.cx, receiver_ty, sym::Option)
+                || is_type_diagnostic_item(self.cx, receiver_ty, sym::Result)
             {
                 self.panic_span = Some(expr.span);
             }
index ac6824672f66cbf90c13b7f7d9e6dfab2d009d4d..57fd24bd4f04d81ca9263a905b84b258a100ae59 100644 (file)
@@ -245,11 +245,14 @@ fn try_parse_contains(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Option<(Map
         ExprKind::MethodCall(
             _,
             _,
-            [map, Expr {
-                kind: ExprKind::AddrOf(_, _, key),
-                span: key_span,
-                ..
-            }],
+            [
+                map,
+                Expr {
+                    kind: ExprKind::AddrOf(_, _, key),
+                    span: key_span,
+                    ..
+                },
+            ],
             _,
         ) if key_span.ctxt() == expr.span.ctxt() => {
             let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?;
index 174260fabd228688c47943efa52d9cae07f84481..404b67c8f29f2817a9e6f58c3fc55d3b588075e4 100644 (file)
@@ -1,8 +1,8 @@
 //! lint on enum variants that are prefixed or suffixed by the same characters
 
-use clippy_utils::camel_case;
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
 use clippy_utils::source::is_present_in_source;
+use clippy_utils::str_utils::{self, count_match_end, count_match_start};
 use rustc_hir::{EnumDef, Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -117,26 +117,6 @@ pub fn new(threshold: u64, avoid_breaking_exported_api: bool) -> Self {
     MODULE_INCEPTION
 ]);
 
-/// Returns the number of chars that match from the start
-#[must_use]
-fn partial_match(pre: &str, name: &str) -> usize {
-    let mut name_iter = name.chars();
-    let _ = name_iter.next_back(); // make sure the name is never fully matched
-    pre.chars().zip(name_iter).take_while(|&(l, r)| l == r).count()
-}
-
-/// Returns the number of chars that match from the end
-#[must_use]
-fn partial_rmatch(post: &str, name: &str) -> usize {
-    let mut name_iter = name.chars();
-    let _ = name_iter.next(); // make sure the name is never fully matched
-    post.chars()
-        .rev()
-        .zip(name_iter.rev())
-        .take_while(|&(l, r)| l == r)
-        .count()
-}
-
 fn check_variant(
     cx: &LateContext<'_>,
     threshold: u64,
@@ -150,7 +130,7 @@ fn check_variant(
     }
     for var in def.variants {
         let name = var.ident.name.as_str();
-        if partial_match(item_name, &name) == item_name_chars
+        if count_match_start(item_name, &name).char_count == item_name_chars
             && name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase())
             && name.chars().nth(item_name_chars + 1).map_or(false, |c| !c.is_numeric())
         {
@@ -161,7 +141,7 @@ fn check_variant(
                 "variant name starts with the enum's name",
             );
         }
-        if partial_rmatch(item_name, &name) == item_name_chars {
+        if count_match_end(item_name, &name).char_count == item_name_chars {
             span_lint(
                 cx,
                 ENUM_VARIANT_NAMES,
@@ -171,14 +151,14 @@ fn check_variant(
         }
     }
     let first = &def.variants[0].ident.name.as_str();
-    let mut pre = &first[..camel_case::until(&*first)];
-    let mut post = &first[camel_case::from(&*first)..];
+    let mut pre = &first[..str_utils::camel_case_until(&*first).byte_index];
+    let mut post = &first[str_utils::camel_case_start(&*first).byte_index..];
     for var in def.variants {
         let name = var.ident.name.as_str();
 
-        let pre_match = partial_match(pre, &name);
+        let pre_match = count_match_start(pre, &name).byte_count;
         pre = &pre[..pre_match];
-        let pre_camel = camel_case::until(pre);
+        let pre_camel = str_utils::camel_case_until(pre).byte_index;
         pre = &pre[..pre_camel];
         while let Some((next, last)) = name[pre.len()..].chars().zip(pre.chars().rev()).next() {
             if next.is_numeric() {
@@ -186,18 +166,18 @@ fn check_variant(
             }
             if next.is_lowercase() {
                 let last = pre.len() - last.len_utf8();
-                let last_camel = camel_case::until(&pre[..last]);
-                pre = &pre[..last_camel];
+                let last_camel = str_utils::camel_case_until(&pre[..last]);
+                pre = &pre[..last_camel.byte_index];
             } else {
                 break;
             }
         }
 
-        let post_match = partial_rmatch(post, &name);
-        let post_end = post.len() - post_match;
+        let post_match = count_match_end(post, &name);
+        let post_end = post.len() - post_match.byte_count;
         post = &post[post_end..];
-        let post_camel = camel_case::from(post);
-        post = &post[post_camel..];
+        let post_camel = str_utils::camel_case_start(post);
+        post = &post[post_camel.byte_index..];
     }
     let (what, value) = match (pre.is_empty(), post.is_empty()) {
         (true, true) => return,
@@ -266,14 +246,16 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
                             );
                         }
                     }
-                    if item.vis.node.is_pub() {
-                        let matching = partial_match(mod_camel, &item_camel);
-                        let rmatching = partial_rmatch(mod_camel, &item_camel);
+                    // The `module_name_repetitions` lint should only trigger if the item has the module in its
+                    // name. Having the same name is accepted.
+                    if item.vis.node.is_pub() && item_camel.len() > mod_camel.len() {
+                        let matching = count_match_start(mod_camel, &item_camel);
+                        let rmatching = count_match_end(mod_camel, &item_camel);
                         let nchars = mod_camel.chars().count();
 
                         let is_word_beginning = |c: char| c == '_' || c.is_uppercase() || c.is_numeric();
 
-                        if matching == nchars {
+                        if matching.char_count == nchars {
                             match item_camel.chars().nth(nchars) {
                                 Some(c) if is_word_beginning(c) => span_lint(
                                     cx,
@@ -284,7 +266,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
                                 _ => (),
                             }
                         }
-                        if rmatching == nchars {
+                        if rmatching.char_count == nchars {
                             span_lint(
                                 cx,
                                 MODULE_NAME_REPETITIONS,
index 765a6c7585a20a6ee3b5f4d09bd6f5b0319396ab..9247343b52a5322f8c7ee09eec77de8b655ffcff 100644 (file)
@@ -169,13 +169,16 @@ fn check_inputs(cx: &LateContext<'_>, params: &[Param<'_>], call_args: &[Expr<'_
         }
         match *cx.typeck_results().expr_adjustments(arg) {
             [] => true,
-            [Adjustment {
-                kind: Adjust::Deref(None),
-                ..
-            }, Adjustment {
-                kind: Adjust::Borrow(AutoBorrow::Ref(_, mu2)),
-                ..
-            }] => {
+            [
+                Adjustment {
+                    kind: Adjust::Deref(None),
+                    ..
+                },
+                Adjustment {
+                    kind: Adjust::Borrow(AutoBorrow::Ref(_, mu2)),
+                    ..
+                },
+            ] => {
                 // re-borrow with the same mutability is allowed
                 let ty = cx.typeck_results().expr_ty(arg);
                 matches!(*ty.kind(), ty::Ref(.., mu1) if mu1 == mu2.into())
index 476e6d23f12151e869270de3c8265bc647993d25..09b6e20083889e863ac884636ad2c3b20f08db50 100644 (file)
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::in_macro;
-use rustc_ast::ast::{AssocItemKind, Extern, FnKind, FnSig, ImplKind, Item, ItemKind, TraitKind, Ty, TyKind};
+use rustc_ast::ast::{AssocItemKind, Extern, Fn, FnSig, Impl, Item, ItemKind, Trait, Ty, TyKind};
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{sym, Span};
@@ -162,17 +162,17 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
                     );
                 }
             },
-            ItemKind::Impl(box ImplKind {
+            ItemKind::Impl(box Impl {
                 of_trait: None, items, ..
             })
-            | ItemKind::Trait(box TraitKind(.., items)) => {
+            | ItemKind::Trait(box Trait { items, .. }) => {
                 for item in items {
-                    if let AssocItemKind::Fn(box FnKind(_, fn_sig, _, _)) = &item.kind {
-                        self.check_fn_sig(cx, fn_sig, item.span);
+                    if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
+                        self.check_fn_sig(cx, sig, item.span);
                     }
                 }
             },
-            ItemKind::Fn(box FnKind(_, fn_sig, _, _)) => self.check_fn_sig(cx, fn_sig, item.span),
+            ItemKind::Fn(box Fn { sig, .. }) => self.check_fn_sig(cx, sig, item.span),
             _ => (),
         }
     }
index c22f9d0e170326c79fbdd0df8cc2228b27822aaf..7169ac9ad6c5a50ce98062c8d1dcdaa465adea46 100644 (file)
@@ -49,15 +49,19 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
 
         let mut applicability = Applicability::MachineApplicable;
         if format_args.value_args.is_empty() {
-            if_chain! {
-                if let [e] = &*format_args.format_string_parts;
-                if let ExprKind::Lit(lit) = &e.kind;
-                if let Some(s_src) = snippet_opt(cx, lit.span);
-                then {
-                    // Simulate macro expansion, converting {{ and }} to { and }.
-                    let s_expand = s_src.replace("{{", "{").replace("}}", "}");
-                    let sugg = format!("{}.to_string()", s_expand);
-                    span_useless_format(cx, call_site, sugg, applicability);
+            if format_args.format_string_parts.is_empty() {
+                span_useless_format_empty(cx, call_site, "String::new()".to_owned(), applicability);
+            } else {
+                if_chain! {
+                    if let [e] = &*format_args.format_string_parts;
+                    if let ExprKind::Lit(lit) = &e.kind;
+                    if let Some(s_src) = snippet_opt(cx, lit.span);
+                    then {
+                        // Simulate macro expansion, converting {{ and }} to { and }.
+                        let s_expand = s_src.replace("{{", "{").replace("}}", "}");
+                        let sugg = format!("{}.to_string()", s_expand);
+                        span_useless_format(cx, call_site, sugg, applicability);
+                    }
                 }
             }
         } else if let [value] = *format_args.value_args {
@@ -89,6 +93,18 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
     }
 }
 
+fn span_useless_format_empty(cx: &LateContext<'_>, span: Span, sugg: String, applicability: Applicability) {
+    span_lint_and_sugg(
+        cx,
+        USELESS_FORMAT,
+        span,
+        "useless use of `format!`",
+        "consider using `String::new()`",
+        sugg,
+        applicability,
+    );
+}
+
 fn span_useless_format(cx: &LateContext<'_>, span: Span, sugg: String, applicability: Applicability) {
     span_lint_and_sugg(
         cx,
index e18442515b8fc4ffaf10e5a2c6534e387fbc7551..6b2ac985555dc59fc7014b3c0afeb4267ffd9420 100644 (file)
@@ -77,13 +77,13 @@ fn check_fn(
             if is_future {
                 let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap();
                 let span = decl.output.span();
-                let send_result = cx.tcx.infer_ctxt().enter(|infcx| {
+                let send_errors = cx.tcx.infer_ctxt().enter(|infcx| {
                     let cause = traits::ObligationCause::misc(span, hir_id);
                     let mut fulfillment_cx = traits::FulfillmentContext::new();
                     fulfillment_cx.register_bound(&infcx, cx.param_env, ret_ty, send_trait, cause);
                     fulfillment_cx.select_all_or_error(&infcx)
                 });
-                if let Err(send_errors) = send_result {
+                if !send_errors.is_empty() {
                     span_lint_and_then(
                         cx,
                         FUTURE_NOT_SEND,
index 3ce91d421baca8bc9efe4b9ae760c522c7f288ca..ac938156237bf8f090feb281558f6301b685e6b0 100644 (file)
@@ -2,9 +2,9 @@
 //! on the condition
 
 use clippy_utils::diagnostics::span_lint_and_help;
-use rustc_ast::ast::{BinOpKind, Expr, ExprKind, UnOp};
-use rustc_lint::{EarlyContext, EarlyLintPass};
-use rustc_middle::lint::in_external_macro;
+use clippy_utils::is_else_clause;
+use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
 declare_clippy_lint! {
 
 declare_lint_pass!(IfNotElse => [IF_NOT_ELSE]);
 
-impl EarlyLintPass for IfNotElse {
-    fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) {
-        if in_external_macro(cx.sess, item.span) {
+impl LateLintPass<'_> for IfNotElse {
+    fn check_expr(&mut self, cx: &LateContext<'_>, item: &Expr<'_>) {
+        // While loops will be desugared to ExprKind::If. This will cause the lint to fire.
+        // To fix this, return early if this span comes from a macro or desugaring.
+        if item.span.from_expansion() {
             return;
         }
-        if let ExprKind::If(ref cond, _, Some(ref els)) = item.kind {
+        if let ExprKind::If(cond, _, Some(els)) = item.kind {
             if let ExprKind::Block(..) = els.kind {
-                match cond.kind {
+                // Disable firing the lint in "else if" expressions.
+                if is_else_clause(cx.tcx, item) {
+                    return;
+                }
+
+                match cond.peel_drop_temps().kind {
                     ExprKind::Unary(UnOp::Not, _) => {
                         span_lint_and_help(
                             cx,
diff --git a/src/tools/clippy/clippy_lints/src/if_then_panic.rs b/src/tools/clippy/clippy_lints/src/if_then_panic.rs
deleted file mode 100644 (file)
index e8cea55..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::higher::PanicExpn;
-use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{is_expn_of, sugg};
-use rustc_errors::Applicability;
-use rustc_hir::{Block, Expr, ExprKind, StmtKind, UnOp};
-use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Detects `if`-then-`panic!` that can be replaced with `assert!`.
-    ///
-    /// ### Why is this bad?
-    /// `assert!` is simpler than `if`-then-`panic!`.
-    ///
-    /// ### Example
-    /// ```rust
-    /// let sad_people: Vec<&str> = vec![];
-    /// if !sad_people.is_empty() {
-    ///     panic!("there are sad people: {:?}", sad_people);
-    /// }
-    /// ```
-    /// Use instead:
-    /// ```rust
-    /// let sad_people: Vec<&str> = vec![];
-    /// assert!(sad_people.is_empty(), "there are sad people: {:?}", sad_people);
-    /// ```
-    pub IF_THEN_PANIC,
-    style,
-    "`panic!` and only a `panic!` in `if`-then statement"
-}
-
-declare_lint_pass!(IfThenPanic => [IF_THEN_PANIC]);
-
-impl LateLintPass<'_> for IfThenPanic {
-    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
-        if_chain! {
-            if let Expr {
-                kind: ExprKind:: If(cond, Expr {
-                    kind: ExprKind::Block(
-                        Block {
-                            stmts: [stmt],
-                            ..
-                        },
-                        _),
-                    ..
-                }, None),
-                ..
-            } = &expr;
-            if is_expn_of(stmt.span, "panic").is_some();
-            if !matches!(cond.kind, ExprKind::Let(_, _, _));
-            if let StmtKind::Semi(semi) = stmt.kind;
-            if !cx.tcx.sess.source_map().is_multiline(cond.span);
-
-            then {
-                let span = if let Some(panic_expn) = PanicExpn::parse(semi) {
-                    match *panic_expn.format_args.value_args {
-                        [] => panic_expn.format_args.format_string_span,
-                        [.., last] => panic_expn.format_args.format_string_span.to(last.span),
-                    }
-                } else {
-                    if_chain! {
-                        if let ExprKind::Block(block, _) = semi.kind;
-                        if let Some(init) = block.expr;
-                        if let ExprKind::Call(_, [format_args]) = init.kind;
-
-                        then {
-                            format_args.span
-                        } else {
-                            return
-                        }
-                    }
-                };
-                let mut applicability = Applicability::MachineApplicable;
-                let sugg = snippet_with_applicability(cx, span, "..", &mut applicability);
-                let cond_sugg = if let ExprKind::DropTemps(e, ..) = cond.kind {
-                    if let Expr{kind: ExprKind::Unary(UnOp::Not, not_expr), ..} = e {
-                         sugg::Sugg::hir_with_applicability(cx, not_expr, "..", &mut applicability).maybe_par().to_string()
-                    } else {
-                       format!("!{}", sugg::Sugg::hir_with_applicability(cx, e, "..", &mut applicability).maybe_par())
-                    }
-                } else {
-                   format!("!{}", sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par())
-                };
-
-                span_lint_and_sugg(
-                    cx,
-                    IF_THEN_PANIC,
-                    expr.span,
-                    "only a `panic!` in `if`-then statement",
-                    "try",
-                    format!("assert!({}, {});", cond_sugg, sugg),
-                    Applicability::MachineApplicable,
-                );
-            }
-        }
-    }
-}
index 49b69dd072a21352da51d21d4eb1a4c0bee2778f..6850e0c34767cb0864a002b5ce498c3cc157c5a8 100644 (file)
@@ -89,7 +89,7 @@ fn check_binop(cx: &EarlyContext<'_>, binop: BinOpKind, lhs: &Expr, rhs: &Expr)
                     },
                     _ => None,
                 }
-            }
+            },
             // case where `x + 1 <= ...` or `1 + x <= ...`
             (BinOpKind::Le, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _)
                 if lhskind.node == BinOpKind::Add =>
@@ -104,7 +104,7 @@ fn check_binop(cx: &EarlyContext<'_>, binop: BinOpKind, lhs: &Expr, rhs: &Expr)
                     },
                     _ => None,
                 }
-            }
+            },
             // case where `... >= y - 1` or `... >= -1 + y`
             (BinOpKind::Le, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs)) => {
                 match (rhskind.node, &rhslhs.kind, &rhsrhs.kind) {
index b1f70b30c12cf1c1605b09ac48cf9fc9891fad3e..82438d85c7a3a353128134b0736e587c4dc9d5f1 100644 (file)
@@ -1,5 +1,3 @@
-use std::cmp::Ordering;
-
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::layout::LayoutOf;
@@ -7,11 +5,11 @@
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::Span;
 
+use clippy_utils::comparisons;
 use clippy_utils::comparisons::Rel;
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{constant_full_int, FullInt};
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::source::snippet;
-use clippy_utils::{comparisons, sext};
 
 declare_clippy_lint! {
     /// ### What it does
 
 declare_lint_pass!(InvalidUpcastComparisons => [INVALID_UPCAST_COMPARISONS]);
 
-#[derive(Copy, Clone, Debug, Eq)]
-enum FullInt {
-    S(i128),
-    U(u128),
-}
-
-impl FullInt {
-    #[allow(clippy::cast_sign_loss)]
-    #[must_use]
-    fn cmp_s_u(s: i128, u: u128) -> Ordering {
-        if s < 0 {
-            Ordering::Less
-        } else if u > (i128::MAX as u128) {
-            Ordering::Greater
-        } else {
-            (s as u128).cmp(&u)
-        }
-    }
-}
-
-impl PartialEq for FullInt {
-    #[must_use]
-    fn eq(&self, other: &Self) -> bool {
-        self.partial_cmp(other).expect("`partial_cmp` only returns `Some(_)`") == Ordering::Equal
-    }
-}
-
-impl PartialOrd for FullInt {
-    #[must_use]
-    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-        Some(match (self, other) {
-            (&Self::S(s), &Self::S(o)) => s.cmp(&o),
-            (&Self::U(s), &Self::U(o)) => s.cmp(&o),
-            (&Self::S(s), &Self::U(o)) => Self::cmp_s_u(s, o),
-            (&Self::U(s), &Self::S(o)) => Self::cmp_s_u(o, s).reverse(),
-        })
-    }
-}
-
-impl Ord for FullInt {
-    #[must_use]
-    fn cmp(&self, other: &Self) -> Ordering {
-        self.partial_cmp(other)
-            .expect("`partial_cmp` for FullInt can never return `None`")
-    }
-}
-
 fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_>, expr: &'a Expr<'_>) -> Option<(FullInt, FullInt)> {
     if let ExprKind::Cast(cast_exp, _) = expr.kind {
         let pre_cast_ty = cx.typeck_results().expr_ty(cast_exp);
@@ -118,19 +69,6 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_>, expr: &'a Expr<'_>) ->
     }
 }
 
-fn node_as_const_fullint<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<FullInt> {
-    let val = constant(cx, cx.typeck_results(), expr)?.0;
-    if let Constant::Int(const_int) = val {
-        match *cx.typeck_results().expr_ty(expr).kind() {
-            ty::Int(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))),
-            ty::Uint(_) => Some(FullInt::U(const_int)),
-            _ => None,
-        }
-    } else {
-        None
-    }
-}
-
 fn err_upcast_comparison(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, always: bool) {
     if let ExprKind::Cast(cast_val, _) = expr.kind {
         span_lint(
@@ -156,7 +94,7 @@ fn upcast_comparison_bounds_err<'tcx>(
     invert: bool,
 ) {
     if let Some((lb, ub)) = lhs_bounds {
-        if let Some(norm_rhs_val) = node_as_const_fullint(cx, rhs) {
+        if let Some(norm_rhs_val) = constant_full_int(cx, cx.typeck_results(), rhs) {
             if rel == Rel::Eq || rel == Rel::Ne {
                 if norm_rhs_val < lb || norm_rhs_val > ub {
                     err_upcast_comparison(cx, span, lhs, rel == Rel::Ne);
index c949ee23ecc7a94858ce40214e496a881c8a08fd..15edb79d36c24d613653e870f38dc66ff94ca3e3 100644 (file)
@@ -76,7 +76,6 @@
     LintId::of(get_last_with_len::GET_LAST_WITH_LEN),
     LintId::of(identity_op::IDENTITY_OP),
     LintId::of(if_let_mutex::IF_LET_MUTEX),
-    LintId::of(if_then_panic::IF_THEN_PANIC),
     LintId::of(indexing_slicing::OUT_OF_BOUNDS_INDEXING),
     LintId::of(infinite_iter::INFINITE_ITER),
     LintId::of(inherent_to_string::INHERENT_TO_STRING),
     LintId::of(non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST),
     LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS),
     LintId::of(non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS),
+    LintId::of(non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY),
     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(undropped_manually_drops::UNDROPPED_MANUALLY_DROPS),
     LintId::of(unicode::INVISIBLE_CHARACTERS),
     LintId::of(uninit_vec::UNINIT_VEC),
+    LintId::of(unit_hash::UNIT_HASH),
     LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
     LintId::of(unit_types::UNIT_ARG),
     LintId::of(unit_types::UNIT_CMP),
index ff56a6081fb57f8cbc44c08f785b2981900147f4..4217fd3a3ea72c04af802f688f39d34f1f501c7a 100644 (file)
@@ -64,6 +64,7 @@
     LintId::of(undropped_manually_drops::UNDROPPED_MANUALLY_DROPS),
     LintId::of(unicode::INVISIBLE_CHARACTERS),
     LintId::of(uninit_vec::UNINIT_VEC),
+    LintId::of(unit_hash::UNIT_HASH),
     LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
     LintId::of(unit_types::UNIT_CMP),
     LintId::of(unnamed_address::FN_ADDRESS_COMPARISONS),
index e8dd3708c8ed406dc3f92b6bff81332d49d9757e..2cb86418e3cb5df2cc946ba79a8095fe48de7be0 100644 (file)
     identity_op::IDENTITY_OP,
     if_let_mutex::IF_LET_MUTEX,
     if_not_else::IF_NOT_ELSE,
-    if_then_panic::IF_THEN_PANIC,
     if_then_some_else_none::IF_THEN_SOME_ELSE_NONE,
     implicit_hasher::IMPLICIT_HASHER,
     implicit_return::IMPLICIT_RETURN,
     loops::WHILE_LET_ON_ITERATOR,
     macro_use::MACRO_USE_IMPORTS,
     main_recursion::MAIN_RECURSION,
+    manual_assert::MANUAL_ASSERT,
     manual_async_fn::MANUAL_ASYNC_FN,
     manual_map::MANUAL_MAP,
     manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE,
     misc_early::DUPLICATE_UNDERSCORE_ARGUMENT,
     misc_early::MIXED_CASE_HEX_LITERALS,
     misc_early::REDUNDANT_PATTERN,
+    misc_early::SEPARATED_LITERAL_SUFFIX,
     misc_early::UNNEEDED_FIELD_PATTERN,
     misc_early::UNNEEDED_WILDCARD_PATTERN,
     misc_early::UNSEPARATED_LITERAL_SUFFIX,
     strings::STRING_ADD_ASSIGN,
     strings::STRING_FROM_UTF8_AS_BYTES,
     strings::STRING_LIT_AS_BYTES,
+    strings::STRING_SLICE,
     strings::STRING_TO_STRING,
     strings::STR_TO_STRING,
     strlen_on_c_strings::STRLEN_ON_C_STRINGS,
     unicode::NON_ASCII_LITERAL,
     unicode::UNICODE_NOT_NFC,
     uninit_vec::UNINIT_VEC,
+    unit_hash::UNIT_HASH,
     unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD,
     unit_types::LET_UNIT_VALUE,
     unit_types::UNIT_ARG,
index 1e54482a8dafdc7b5f73d3798f5fd5a04864cc2b..44c75a11eec08111c17db1d2ca03862a17e3a6a3 100644 (file)
@@ -17,7 +17,6 @@
     LintId::of(missing_const_for_fn::MISSING_CONST_FOR_FN),
     LintId::of(mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL),
     LintId::of(mutex_atomic::MUTEX_INTEGER),
-    LintId::of(non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY),
     LintId::of(nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES),
     LintId::of(option_if_let_else::OPTION_IF_LET_ELSE),
     LintId::of(path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE),
index 268349d28481182fdbac33fe20ba0d0312430fbf..404ca20b5abc62bf05adf9b474a19c0990048e00 100644 (file)
@@ -48,6 +48,7 @@
     LintId::of(loops::EXPLICIT_INTO_ITER_LOOP),
     LintId::of(loops::EXPLICIT_ITER_LOOP),
     LintId::of(macro_use::MACRO_USE_IMPORTS),
+    LintId::of(manual_assert::MANUAL_ASSERT),
     LintId::of(manual_ok_or::MANUAL_OK_OR),
     LintId::of(match_on_vec_items::MATCH_ON_VEC_ITEMS),
     LintId::of(matches::MATCH_BOOL),
@@ -65,7 +66,6 @@
     LintId::of(methods::MAP_UNWRAP_OR),
     LintId::of(misc::FLOAT_CMP),
     LintId::of(misc::USED_UNDERSCORE_BINDING),
-    LintId::of(misc_early::UNSEPARATED_LITERAL_SUFFIX),
     LintId::of(mut_mut::MUT_MUT),
     LintId::of(needless_bitwise_bool::NEEDLESS_BITWISE_BOOL),
     LintId::of(needless_borrow::REF_BINDING_TO_REFERENCE),
@@ -88,7 +88,6 @@
     LintId::of(transmute::TRANSMUTE_PTR_TO_PTR),
     LintId::of(types::LINKEDLIST),
     LintId::of(types::OPTION_OPTION),
-    LintId::of(unicode::NON_ASCII_LITERAL),
     LintId::of(unicode::UNICODE_NOT_NFC),
     LintId::of(unit_types::LET_UNIT_VALUE),
     LintId::of(unnecessary_wraps::UNNECESSARY_WRAPS),
index 3d68a6e900958fbcfcd886007abc15c468b5ceef..eab389a9bd892089b94a10c749b2837d3916b25c 100644 (file)
@@ -35,7 +35,9 @@
     LintId::of(methods::GET_UNWRAP),
     LintId::of(methods::UNWRAP_USED),
     LintId::of(misc::FLOAT_CMP_CONST),
+    LintId::of(misc_early::SEPARATED_LITERAL_SUFFIX),
     LintId::of(misc_early::UNNEEDED_FIELD_PATTERN),
+    LintId::of(misc_early::UNSEPARATED_LITERAL_SUFFIX),
     LintId::of(missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS),
     LintId::of(missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES),
     LintId::of(missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS),
     LintId::of(shadow::SHADOW_SAME),
     LintId::of(shadow::SHADOW_UNRELATED),
     LintId::of(strings::STRING_ADD),
+    LintId::of(strings::STRING_SLICE),
     LintId::of(strings::STRING_TO_STRING),
     LintId::of(strings::STR_TO_STRING),
     LintId::of(types::RC_BUFFER),
     LintId::of(types::RC_MUTEX),
     LintId::of(undocumented_unsafe_blocks::UNDOCUMENTED_UNSAFE_BLOCKS),
+    LintId::of(unicode::NON_ASCII_LITERAL),
     LintId::of(unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS),
     LintId::of(unwrap_in_result::UNWRAP_IN_RESULT),
     LintId::of(verbose_file_reads::VERBOSE_FILE_READS),
index a39c111c5742340d1a0d59723da29d722c8271c6..744880bda3e69c2a83763dc5d9b1a38ade7b6ec5 100644 (file)
@@ -27,7 +27,6 @@
     LintId::of(functions::DOUBLE_MUST_USE),
     LintId::of(functions::MUST_USE_UNIT),
     LintId::of(functions::RESULT_UNIT_ERR),
-    LintId::of(if_then_panic::IF_THEN_PANIC),
     LintId::of(inherent_to_string::INHERENT_TO_STRING),
     LintId::of(len_zero::COMPARISON_TO_EMPTY),
     LintId::of(len_zero::LEN_WITHOUT_IS_EMPTY),
index 8859787fbc830c97e7b34a0ee21e053d586bcdcf..a3f964d1580428f92230f26f169586fd86e25504 100644 (file)
@@ -15,6 +15,7 @@
     LintId::of(loops::MUT_RANGE_BOUND),
     LintId::of(methods::SUSPICIOUS_MAP),
     LintId::of(mut_key::MUTABLE_KEY_TYPE),
+    LintId::of(non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY),
     LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
     LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
 ])
index ed7e827702395dc72336e5f2adaf24709324e6ac..7174d0a082e0f7627f062180d10f5ef47c170a4b 100644 (file)
@@ -228,7 +228,6 @@ macro_rules! declare_clippy_lint {
 mod identity_op;
 mod if_let_mutex;
 mod if_not_else;
-mod if_then_panic;
 mod if_then_some_else_none;
 mod implicit_hasher;
 mod implicit_return;
@@ -255,6 +254,7 @@ macro_rules! declare_clippy_lint {
 mod loops;
 mod macro_use;
 mod main_recursion;
+mod manual_assert;
 mod manual_async_fn;
 mod manual_map;
 mod manual_non_exhaustive;
@@ -364,6 +364,7 @@ macro_rules! declare_clippy_lint {
 mod undropped_manually_drops;
 mod unicode;
 mod uninit_vec;
+mod unit_hash;
 mod unit_return_expecting_ord;
 mod unit_types;
 mod unnamed_address;
@@ -522,6 +523,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| Box::new(collapsible_match::CollapsibleMatch));
     store.register_late_pass(|| Box::new(unicode::Unicode));
     store.register_late_pass(|| Box::new(uninit_vec::UninitVec));
+    store.register_late_pass(|| Box::new(unit_hash::UnitHash));
     store.register_late_pass(|| Box::new(unit_return_expecting_ord::UnitReturnExpectingOrd));
     store.register_late_pass(|| Box::new(strings::StringAdd));
     store.register_late_pass(|| Box::new(implicit_return::ImplicitReturn));
@@ -666,7 +668,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_early_pass(|| Box::new(double_parens::DoubleParens));
     store.register_late_pass(|| Box::new(to_string_in_display::ToStringInDisplay::new()));
     store.register_early_pass(|| Box::new(unsafe_removed_from_name::UnsafeNameRemoval));
-    store.register_early_pass(|| Box::new(if_not_else::IfNotElse));
     store.register_early_pass(|| Box::new(else_if_without_else::ElseIfWithoutElse));
     store.register_early_pass(|| Box::new(int_plus_one::IntPlusOne));
     store.register_early_pass(|| Box::new(formatting::Formatting));
@@ -720,6 +721,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| Box::new(option_if_let_else::OptionIfLetElse));
     store.register_late_pass(|| Box::new(future_not_send::FutureNotSend));
     store.register_late_pass(|| Box::new(if_let_mutex::IfLetMutex));
+    store.register_late_pass(|| Box::new(if_not_else::IfNotElse));
     store.register_late_pass(|| Box::new(equatable_if_let::PatternEquality));
     store.register_late_pass(|| Box::new(mut_mutex_lock::MutMutexLock));
     store.register_late_pass(|| Box::new(match_on_vec_items::MatchOnVecItems));
@@ -770,14 +772,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(move || Box::new(self_named_constructors::SelfNamedConstructors));
     store.register_late_pass(move || Box::new(feature_name::FeatureName));
     store.register_late_pass(move || Box::new(iter_not_returning_iterator::IterNotReturningIterator));
-    store.register_late_pass(move || Box::new(if_then_panic::IfThenPanic));
+    store.register_late_pass(move || Box::new(manual_assert::ManualAssert));
     let enable_raw_pointer_heuristic_for_send = conf.enable_raw_pointer_heuristic_for_send;
     store.register_late_pass(move || Box::new(non_send_fields_in_send_ty::NonSendFieldInSendTy::new(enable_raw_pointer_heuristic_for_send)));
     store.register_late_pass(move || Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks::default()));
     store.register_late_pass(|| Box::new(match_str_case_mismatch::MatchStrCaseMismatch));
     store.register_late_pass(move || Box::new(format_args::FormatArgs));
     store.register_late_pass(|| Box::new(trailing_empty_array::TrailingEmptyArray));
-
+    // add lints here, do not remove this comment, it's used in `new_lint`
 }
 
 #[rustfmt::skip]
@@ -828,6 +830,7 @@ fn register_removed_non_tool_lints(store: &mut rustc_lint::LintStore) {
 ///
 /// Used in `./src/driver.rs`.
 pub fn register_renamed(ls: &mut rustc_lint::LintStore) {
+    // NOTE: when renaming a lint, add a corresponding test to tests/ui/rename.rs
     ls.register_renamed("clippy::stutter", "clippy::module_name_repetitions");
     ls.register_renamed("clippy::new_without_default_derive", "clippy::new_without_default");
     ls.register_renamed("clippy::cyclomatic_complexity", "clippy::cognitive_complexity");
index e5e6f8d25cc11143878512361a1a9d9f5672cb99..cb0b96e0652e53b1115b238a63713907c8a7fa04 100644 (file)
@@ -378,11 +378,15 @@ fn visit_poly_trait_ref(&mut self, poly_tref: &'tcx PolyTraitRef<'tcx>, tbm: Tra
 
     fn visit_ty(&mut self, ty: &'tcx Ty<'_>) {
         match ty.kind {
-            TyKind::OpaqueDef(item, _) => {
+            TyKind::OpaqueDef(item, bounds) => {
                 let map = self.cx.tcx.hir();
                 let item = map.item(item);
                 walk_item(self, item);
                 walk_ty(self, ty);
+                self.lts.extend(bounds.iter().filter_map(|bound| match bound {
+                    GenericArg::Lifetime(l) => Some(RefLt::Named(l.name.ident().name)),
+                    _ => None,
+                }));
             },
             TyKind::BareFn(&BareFnTy { decl, .. }) => {
                 let mut sub_visitor = RefVisitor::new(self.cx);
index 2f7360210ba4de7918204c49434a6cf0a5ecd8f3..f9f515cc40a0fbdd120af9de1358d4e92ba66ce7 100644 (file)
@@ -338,7 +338,7 @@ pub(super) fn make_iterator_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, applic
                     sugg::Sugg::hir_with_applicability(cx, arg_inner, "_", applic_ref).maybe_par(),
                     meth_name,
                 )
-            }
+            },
             _ => format!(
                 "{}.into_iter()",
                 sugg::Sugg::hir_with_applicability(cx, arg, "_", applic_ref).maybe_par()
diff --git a/src/tools/clippy/clippy_lints/src/manual_assert.rs b/src/tools/clippy/clippy_lints/src/manual_assert.rs
new file mode 100644 (file)
index 0000000..e55aa3f
--- /dev/null
@@ -0,0 +1,100 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::higher::PanicExpn;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::{is_expn_of, sugg};
+use rustc_errors::Applicability;
+use rustc_hir::{Block, Expr, ExprKind, StmtKind, UnOp};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Detects `if`-then-`panic!` that can be replaced with `assert!`.
+    ///
+    /// ### Why is this bad?
+    /// `assert!` is simpler than `if`-then-`panic!`.
+    ///
+    /// ### Example
+    /// ```rust
+    /// let sad_people: Vec<&str> = vec![];
+    /// if !sad_people.is_empty() {
+    ///     panic!("there are sad people: {:?}", sad_people);
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// let sad_people: Vec<&str> = vec![];
+    /// assert!(sad_people.is_empty(), "there are sad people: {:?}", sad_people);
+    /// ```
+    pub MANUAL_ASSERT,
+    pedantic,
+    "`panic!` and only a `panic!` in `if`-then statement"
+}
+
+declare_lint_pass!(ManualAssert => [MANUAL_ASSERT]);
+
+impl LateLintPass<'_> for ManualAssert {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        if_chain! {
+            if let Expr {
+                kind: ExprKind:: If(cond, Expr {
+                    kind: ExprKind::Block(
+                        Block {
+                            stmts: [stmt],
+                            ..
+                        },
+                        _),
+                    ..
+                }, None),
+                ..
+            } = &expr;
+            if is_expn_of(stmt.span, "panic").is_some();
+            if !matches!(cond.kind, ExprKind::Let(_, _, _));
+            if let StmtKind::Semi(semi) = stmt.kind;
+            if !cx.tcx.sess.source_map().is_multiline(cond.span);
+
+            then {
+                let call = if_chain! {
+                    if let ExprKind::Block(block, _) = semi.kind;
+                    if let Some(init) = block.expr;
+                    then {
+                        init
+                    } else {
+                        semi
+                    }
+                };
+                let span = if let Some(panic_expn) = PanicExpn::parse(call) {
+                    match *panic_expn.format_args.value_args {
+                        [] => panic_expn.format_args.format_string_span,
+                        [.., last] => panic_expn.format_args.format_string_span.to(last.span),
+                    }
+                } else if let ExprKind::Call(_, [format_args]) = call.kind {
+                    format_args.span
+                } else {
+                    return
+                };
+                let mut applicability = Applicability::MachineApplicable;
+                let sugg = snippet_with_applicability(cx, span, "..", &mut applicability);
+                let cond_sugg = if let ExprKind::DropTemps(e, ..) = cond.kind {
+                    if let Expr{kind: ExprKind::Unary(UnOp::Not, not_expr), ..} = e {
+                         sugg::Sugg::hir_with_applicability(cx, not_expr, "..", &mut applicability).maybe_par().to_string()
+                    } else {
+                       format!("!{}", sugg::Sugg::hir_with_applicability(cx, e, "..", &mut applicability).maybe_par())
+                    }
+                } else {
+                   format!("!{}", sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par())
+                };
+
+                span_lint_and_sugg(
+                    cx,
+                    MANUAL_ASSERT,
+                    expr.span,
+                    "only a `panic!` in `if`-then statement",
+                    "try",
+                    format!("assert!({}, {});", cond_sugg, sugg),
+                    Applicability::MachineApplicable,
+                );
+            }
+        }
+    }
+}
index a83f38e3d516e5c74c345cc2de119f57468710e2..f501593c5187e36e99b823f0a1a6919df425bc86 100644 (file)
@@ -127,10 +127,10 @@ fn get_case_method(segment_ident_str: &str) -> Option<CaseMethod> {
 
 fn verify_case<'a>(case_method: &'a CaseMethod, arms: &'a [Arm<'_>]) -> Option<(Span, SymbolStr)> {
     let case_check = match case_method {
-        CaseMethod::LowerCase => |input: &str| -> bool { input.chars().all(char::is_lowercase) },
-        CaseMethod::AsciiLowerCase => |input: &str| -> bool { input.chars().all(|c| matches!(c, 'a'..='z')) },
-        CaseMethod::UpperCase => |input: &str| -> bool { input.chars().all(char::is_uppercase) },
-        CaseMethod::AsciiUppercase => |input: &str| -> bool { input.chars().all(|c| matches!(c, 'A'..='Z')) },
+        CaseMethod::LowerCase => |input: &str| -> bool { input.chars().all(|c| c.to_lowercase().next() == Some(c)) },
+        CaseMethod::AsciiLowerCase => |input: &str| -> bool { !input.chars().any(|c| c.is_ascii_uppercase()) },
+        CaseMethod::UpperCase => |input: &str| -> bool { input.chars().all(|c| c.to_uppercase().next() == Some(c)) },
+        CaseMethod::AsciiUppercase => |input: &str| -> bool { !input.chars().any(|c| c.is_ascii_lowercase()) },
     };
 
     for arm in arms {
@@ -153,7 +153,7 @@ fn verify_case<'a>(case_method: &'a CaseMethod, arms: &'a [Arm<'_>]) -> Option<(
 
 fn lint(cx: &LateContext<'_>, case_method: &CaseMethod, bad_case_span: Span, bad_case_str: &str) {
     let (method_str, suggestion) = match case_method {
-        CaseMethod::LowerCase => ("to_lower_case", bad_case_str.to_lowercase()),
+        CaseMethod::LowerCase => ("to_lowercase", bad_case_str.to_lowercase()),
         CaseMethod::AsciiLowerCase => ("to_ascii_lowercase", bad_case_str.to_ascii_lowercase()),
         CaseMethod::UpperCase => ("to_uppercase", bad_case_str.to_uppercase()),
         CaseMethod::AsciiUppercase => ("to_ascii_uppercase", bad_case_str.to_ascii_uppercase()),
index b643fba5d328865baded5f1192cca02fa6ae979a..7142df98c3f10fde54afa98e822067dd468532f2 100644 (file)
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, miri_to_const, Constant};
+use clippy_utils::consts::{constant, constant_full_int, miri_to_const, FullInt};
 use clippy_utils::diagnostics::{
     multispan_sugg, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then,
 };
@@ -930,9 +930,8 @@ fn check_match_bool(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
 fn check_overlapping_arms<'tcx>(cx: &LateContext<'tcx>, ex: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>]) {
     if arms.len() >= 2 && cx.typeck_results().expr_ty(ex).is_integral() {
         let ranges = all_ranges(cx, arms, cx.typeck_results().expr_ty(ex));
-        let type_ranges = type_ranges(&ranges);
-        if !type_ranges.is_empty() {
-            if let Some((start, end)) = overlapping(&type_ranges) {
+        if !ranges.is_empty() {
+            if let Some((start, end)) = overlapping(&ranges) {
                 span_lint_and_note(
                     cx,
                     MATCH_OVERLAPPING_ARM,
@@ -968,8 +967,7 @@ fn check_wild_err_arm<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm
                     }
                     if_chain! {
                         if matching_wild;
-                        if let ExprKind::Block(block, _) = arm.body.kind;
-                        if is_panic_block(block);
+                        if is_panic_call(arm.body);
                         then {
                             // `Err(_)` or `Err(_e)` arm with `panic!` found
                             span_lint_and_note(cx,
@@ -1067,7 +1065,10 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
                 PatKind::Path(path) => {
                     #[allow(clippy::match_same_arms)]
                     let id = match cx.qpath_res(path, pat.hir_id) {
-                        Res::Def(DefKind::Const | DefKind::ConstParam | DefKind::AnonConst, _) => return,
+                        Res::Def(
+                            DefKind::Const | DefKind::ConstParam | DefKind::AnonConst | DefKind::InlineConst,
+                            _,
+                        ) => return,
                         Res::Def(_, id) => id,
                         _ => return,
                     };
@@ -1172,14 +1173,19 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
 }
 
 // If the block contains only a `panic!` macro (as expression or statement)
-fn is_panic_block(block: &Block<'_>) -> bool {
-    match (&block.expr, block.stmts.len(), block.stmts.first()) {
-        (&Some(exp), 0, _) => is_expn_of(exp.span, "panic").is_some() && is_expn_of(exp.span, "unreachable").is_none(),
-        (&None, 1, Some(stmt)) => {
-            is_expn_of(stmt.span, "panic").is_some() && is_expn_of(stmt.span, "unreachable").is_none()
-        },
-        _ => false,
-    }
+fn is_panic_call(expr: &Expr<'_>) -> bool {
+    // Unwrap any wrapping blocks
+    let span = if let ExprKind::Block(block, _) = expr.kind {
+        match (&block.expr, block.stmts.len(), block.stmts.first()) {
+            (&Some(exp), 0, _) => exp.span,
+            (&None, 1, Some(stmt)) => stmt.span,
+            _ => return false,
+        }
+    } else {
+        expr.span
+    };
+
+    is_expn_of(span, "panic").is_some() && is_expn_of(span, "unreachable").is_none()
 }
 
 fn check_match_ref_pats<'a, 'b, I>(cx: &LateContext<'_>, ex: &Expr<'_>, pats: I, expr: &Expr<'_>)
@@ -1601,7 +1607,7 @@ fn opt_parent_let<'a>(cx: &LateContext<'a>, ex: &Expr<'a>) -> Option<&'a Local<'
 }
 
 /// Gets all arms that are unbounded `PatRange`s.
-fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) -> Vec<SpannedRange<Constant>> {
+fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) -> Vec<SpannedRange<FullInt>> {
     arms.iter()
         .filter_map(|arm| {
             if let Arm { pat, guard: None, .. } = *arm {
@@ -1614,21 +1620,25 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
                         Some(rhs) => constant(cx, cx.typeck_results(), rhs)?.0,
                         None => miri_to_const(ty.numeric_max_val(cx.tcx)?)?,
                     };
-                    let rhs = match range_end {
-                        RangeEnd::Included => Bound::Included(rhs),
-                        RangeEnd::Excluded => Bound::Excluded(rhs),
+
+                    let lhs_val = lhs.int_value(cx, ty)?;
+                    let rhs_val = rhs.int_value(cx, ty)?;
+
+                    let rhs_bound = match range_end {
+                        RangeEnd::Included => Bound::Included(rhs_val),
+                        RangeEnd::Excluded => Bound::Excluded(rhs_val),
                     };
                     return Some(SpannedRange {
                         span: pat.span,
-                        node: (lhs, rhs),
+                        node: (lhs_val, rhs_bound),
                     });
                 }
 
                 if let PatKind::Lit(value) = pat.kind {
-                    let value = constant(cx, cx.typeck_results(), value)?.0;
+                    let value = constant_full_int(cx, cx.typeck_results(), value)?;
                     return Some(SpannedRange {
                         span: pat.span,
-                        node: (value.clone(), Bound::Included(value)),
+                        node: (value, Bound::Included(value)),
                     });
                 }
             }
@@ -1643,32 +1653,6 @@ pub struct SpannedRange<T> {
     pub node: (T, Bound<T>),
 }
 
-type TypedRanges = Vec<SpannedRange<u128>>;
-
-/// Gets all `Int` ranges or all `Uint` ranges. Mixed types are an error anyway
-/// and other types than
-/// `Uint` and `Int` probably don't make sense.
-fn type_ranges(ranges: &[SpannedRange<Constant>]) -> TypedRanges {
-    ranges
-        .iter()
-        .filter_map(|range| match range.node {
-            (Constant::Int(start), Bound::Included(Constant::Int(end))) => Some(SpannedRange {
-                span: range.span,
-                node: (start, Bound::Included(end)),
-            }),
-            (Constant::Int(start), Bound::Excluded(Constant::Int(end))) => Some(SpannedRange {
-                span: range.span,
-                node: (start, Bound::Excluded(end)),
-            }),
-            (Constant::Int(start), Bound::Unbounded) => Some(SpannedRange {
-                span: range.span,
-                node: (start, Bound::Unbounded),
-            }),
-            _ => None,
-        })
-        .collect()
-}
-
 // Checks if arm has the form `None => None`
 fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
     matches!(arm.pat.kind, PatKind::Path(ref qpath) if is_lang_ctor(cx, qpath, OptionNone))
index 1a32af5dc7a386fdd5e03c3832e8c105d6fc47f8..b4dacb2580c313fbc366aae7b251facfbdda215e 100644 (file)
@@ -85,7 +85,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol,
                     if expr.hir_id == self_arg.hir_id && ty != cx.typeck_results().expr_ty_adjusted(expr) =>
                 {
                     return;
-                }
+                },
                 ExprKind::MethodCall(_, _, [self_arg, ..], _) if expr.hir_id == self_arg.hir_id => true,
                 ExprKind::Match(_, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar)
                 | ExprKind::Field(..)
@@ -100,7 +100,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol,
                 ) =>
             {
                 return;
-            }
+            },
             _ => false,
         };
 
index b5bbbb09092af4f12d27c6fc60cc363444796019..fe9ffde0d337c1f15506e73bdca1e0f373c88da5 100644 (file)
@@ -186,7 +186,7 @@ fn check_general_case<'tcx>(
                         check_general_case(cx, name, method_span, &args[0], &args[1], expr.span, None);
                     }
                 }
-            }
+            },
             _ => (),
         }
     }
index 6f65778e1193cfc08d011e0eec606f08e683bf6a..06ba968fa4ed31da1700c3df599ff67badc51359 100644 (file)
@@ -1,4 +1,3 @@
-use super::MiscEarlyLints;
 use clippy_utils::diagnostics::span_lint;
 use rustc_ast::ast::{Expr, ExprKind, UnOp};
 use rustc_lint::EarlyContext;
@@ -6,18 +5,14 @@
 use super::DOUBLE_NEG;
 
 pub(super) fn check(cx: &EarlyContext<'_>, expr: &Expr) {
-    match expr.kind {
-        ExprKind::Unary(UnOp::Neg, ref inner) => {
-            if let ExprKind::Unary(UnOp::Neg, _) = inner.kind {
-                span_lint(
-                    cx,
-                    DOUBLE_NEG,
-                    expr.span,
-                    "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op",
-                );
-            }
-        },
-        ExprKind::Lit(ref lit) => MiscEarlyLints::check_lit(cx, lit),
-        _ => (),
+    if let ExprKind::Unary(UnOp::Neg, ref inner) = expr.kind {
+        if let ExprKind::Unary(UnOp::Neg, _) = inner.kind {
+            span_lint(
+                cx,
+                DOUBLE_NEG,
+                expr.span,
+                "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op",
+            );
+        }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs b/src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs
new file mode 100644 (file)
index 0000000..1165c19
--- /dev/null
@@ -0,0 +1,38 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use rustc_ast::ast::Lit;
+use rustc_errors::Applicability;
+use rustc_lint::EarlyContext;
+
+use super::{SEPARATED_LITERAL_SUFFIX, UNSEPARATED_LITERAL_SUFFIX};
+
+pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str, suffix: &str, sugg_type: &str) {
+    let maybe_last_sep_idx = if let Some(val) = lit_snip.len().checked_sub(suffix.len() + 1) {
+        val
+    } else {
+        return; // It's useless so shouldn't lint.
+    };
+    // Do not lint when literal is unsuffixed.
+    if !suffix.is_empty() {
+        if lit_snip.as_bytes()[maybe_last_sep_idx] == b'_' {
+            span_lint_and_sugg(
+                cx,
+                SEPARATED_LITERAL_SUFFIX,
+                lit.span,
+                &format!("{} type suffix should not be separated by an underscore", sugg_type),
+                "remove the underscore",
+                format!("{}{}", &lit_snip[..maybe_last_sep_idx], suffix),
+                Applicability::MachineApplicable,
+            );
+        } else {
+            span_lint_and_sugg(
+                cx,
+                UNSEPARATED_LITERAL_SUFFIX,
+                lit.span,
+                &format!("{} type suffix should be separated by an underscore", sugg_type),
+                "add an underscore",
+                format!("{}_{}", &lit_snip[..=maybe_last_sep_idx], suffix),
+                Applicability::MachineApplicable,
+            );
+        }
+    }
+}
index b32feab4ee3e7e5506b23875170ca01d6d4920b6..7c3f5f22ade0f9ba447d1dc583791b092f1abf80 100644 (file)
@@ -1,15 +1,15 @@
 mod builtin_type_shadow;
 mod double_neg;
+mod literal_suffix;
 mod mixed_case_hex_literals;
 mod redundant_pattern;
 mod unneeded_field_pattern;
 mod unneeded_wildcard_pattern;
-mod unseparated_literal_suffix;
 mod zero_prefixed_literal;
 
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::source::snippet_opt;
-use rustc_ast::ast::{Expr, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind};
+use rustc_ast::ast::{Expr, ExprKind, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind};
 use rustc_ast::visit::FnKind;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_lint::{EarlyContext, EarlyLintPass};
     /// ### What it does
     /// Warns if literal suffixes are not separated by an
     /// underscore.
+    /// To enforce unseparated literal suffix style,
+    /// see the `separated_literal_suffix` lint.
     ///
     /// ### Why is this bad?
-    /// It is much less readable.
+    /// Suffix style should be consistent.
     ///
     /// ### Example
     /// ```rust
     /// let y = 123832_i32;
     /// ```
     pub UNSEPARATED_LITERAL_SUFFIX,
-    pedantic,
+    restriction,
     "literals whose suffix is not separated by an underscore"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Warns if literal suffixes are separated by an underscore.
+    /// To enforce separated literal suffix style,
+    /// see the `unseparated_literal_suffix` lint.
+    ///
+    /// ### Why is this bad?
+    /// Suffix style should be consistent.
+    ///
+    /// ### Example
+    /// ```rust
+    /// // Bad
+    /// let y = 123832_i32;
+    ///
+    /// // Good
+    /// let y = 123832i32;
+    /// ```
+    pub SEPARATED_LITERAL_SUFFIX,
+    restriction,
+    "literals whose suffix is separated by an underscore"
+}
+
 declare_clippy_lint! {
     /// ### What it does
     /// Warns if an integral constant literal starts with `0`.
     DOUBLE_NEG,
     MIXED_CASE_HEX_LITERALS,
     UNSEPARATED_LITERAL_SUFFIX,
+    SEPARATED_LITERAL_SUFFIX,
     ZERO_PREFIXED_LITERAL,
     BUILTIN_TYPE_SHADOW,
     REDUNDANT_PATTERN,
@@ -310,6 +335,10 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
         if in_external_macro(cx.sess, expr.span) {
             return;
         }
+
+        if let ExprKind::Lit(ref lit) = expr.kind {
+            MiscEarlyLints::check_lit(cx, lit);
+        }
         double_neg::check(cx, expr);
     }
 }
@@ -332,7 +361,7 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit) {
                 LitIntType::Unsigned(ty) => ty.name_str(),
                 LitIntType::Unsuffixed => "",
             };
-            unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "integer");
+            literal_suffix::check(cx, lit, &lit_snip, suffix, "integer");
             if lit_snip.starts_with("0x") {
                 mixed_case_hex_literals::check(cx, lit, suffix, &lit_snip);
             } else if lit_snip.starts_with("0b") || lit_snip.starts_with("0o") {
@@ -342,7 +371,7 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit) {
             }
         } else if let LitKind::Float(_, LitFloatType::Suffixed(float_ty)) = lit.kind {
             let suffix = float_ty.name_str();
-            unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "float");
+            literal_suffix::check(cx, lit, &lit_snip, suffix, "float");
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/unseparated_literal_suffix.rs b/src/tools/clippy/clippy_lints/src/misc_early/unseparated_literal_suffix.rs
deleted file mode 100644 (file)
index 2018aa6..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use rustc_ast::ast::Lit;
-use rustc_errors::Applicability;
-use rustc_lint::EarlyContext;
-
-use super::UNSEPARATED_LITERAL_SUFFIX;
-
-pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str, suffix: &str, sugg_type: &str) {
-    let maybe_last_sep_idx = if let Some(val) = lit_snip.len().checked_sub(suffix.len() + 1) {
-        val
-    } else {
-        return; // It's useless so shouldn't lint.
-    };
-    // Do not lint when literal is unsuffixed.
-    if !suffix.is_empty() && lit_snip.as_bytes()[maybe_last_sep_idx] != b'_' {
-        span_lint_and_sugg(
-            cx,
-            UNSEPARATED_LITERAL_SUFFIX,
-            lit.span,
-            &format!("{} type suffix should be separated by an underscore", sugg_type),
-            "add an underscore",
-            format!("{}_{}", &lit_snip[..=maybe_last_sep_idx], suffix),
-            Applicability::MachineApplicable,
-        );
-    }
-}
index f351d0098b7509cf6abdddfef53c21a29cc7a663..d41b54745649958de717e61f6d395bfbce0e62e5 100644 (file)
@@ -106,7 +106,7 @@ fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
                     }
                     process_paths_for_mod_files(path, &mut folder_segments, &mut mod_folders);
                     check_self_named_mod_exists(cx, path, file);
-                }
+                },
                 _ => {},
             }
         }
index 1b2495d764d2a0c650f9f866a153252fa5288b5a..f1be90c44f98b998901e0f4b2462722466c99d69 100644 (file)
@@ -107,14 +107,18 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         if let ExprKind::AddrOf(BorrowKind::Ref, mutability, inner) = e.kind {
             if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty(inner).kind() {
                 for adj3 in cx.typeck_results().expr_adjustments(e).windows(3) {
-                    if let [Adjustment {
-                        kind: Adjust::Deref(_), ..
-                    }, Adjustment {
-                        kind: Adjust::Deref(_), ..
-                    }, Adjustment {
-                        kind: Adjust::Borrow(_),
-                        ..
-                    }] = *adj3
+                    if let [
+                        Adjustment {
+                            kind: Adjust::Deref(_), ..
+                        },
+                        Adjustment {
+                            kind: Adjust::Deref(_), ..
+                        },
+                        Adjustment {
+                            kind: Adjust::Borrow(_),
+                            ..
+                        },
+                    ] = *adj3
                     {
                         let help_msg_ty = if matches!(mutability, Mutability::Not) {
                             format!("&{}", ty)
index 5b254bc8133d2fecce4c6227b90d7c91e2206b6c..e28cc49bf2a1a0f955ac3686c132d4c201b2b6ef 100644 (file)
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use rustc_ast::ast::{
-    Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, FnKind, Item, ItemKind, Local, Pat, PatKind,
+    self, 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};
@@ -357,7 +357,7 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
             return;
         }
 
-        if let ItemKind::Fn(box FnKind(_, ref sig, _, Some(ref blk))) = item.kind {
+        if let ItemKind::Fn(box ast::Fn { ref sig, body: Some(ref blk), .. }) = item.kind {
             do_check(self, cx, &item.attrs, &sig.decl, blk);
         }
     }
@@ -367,7 +367,7 @@ fn check_impl_item(&mut self, cx: &EarlyContext<'_>, item: &AssocItem) {
             return;
         }
 
-        if let AssocItemKind::Fn(box FnKind(_, ref sig, _, Some(ref blk))) = item.kind {
+        if let AssocItemKind::Fn(box ast::Fn { ref sig, body: Some(ref blk), .. }) = item.kind {
             do_check(self, cx, &item.attrs, &sig.decl, blk);
         }
     }
index 374b7bd59649e87db0f8ffbbdb22f1ae0b015309..7ebf84d400f569c3f891bc7d417afeeb2d741167 100644 (file)
@@ -44,7 +44,7 @@
     /// Use thread-safe types like [`std::sync::Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html)
     /// or specify correct bounds on generic type parameters (`T: Send`).
     pub NON_SEND_FIELDS_IN_SEND_TY,
-    nursery,
+    suspicious,
     "there is field that does not implement `Send` in a `Send` struct"
 }
 
index a62eb0699891bf583fc94e13a6e38629b533f877..cbe1c5d44d513044d745718518c69876f69a10f3 100644 (file)
@@ -22,7 +22,7 @@
     /// expression).
     ///
     /// ### Why is this bad?
-    /// Using the dedicated functions of the Option type is clearer and
+    /// Using the dedicated functions of the `Option` type is clearer and
     /// more concise than an `if let` expression.
     ///
     /// ### Known problems
index 92a4801a8468ae3d3e592212280e8dd7959c9bc5..8a36e20fc973d678297d14718039e8913af8acc7 100644 (file)
@@ -3,16 +3,16 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::ptr::get_spans;
 use clippy_utils::source::snippet_opt;
-use clippy_utils::ty::{is_type_diagnostic_item, match_type, walk_ptrs_hir_ty};
+use clippy_utils::ty::walk_ptrs_hir_ty;
 use clippy_utils::{expr_path_res, is_lint_allowed, match_any_diagnostic_items, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
+use rustc_hir::def::Res;
 use rustc_hir::{
-    BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, HirId, Impl, ImplItem, ImplItemKind, Item,
-    ItemKind, Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitFn, TraitItem, TraitItemKind, Ty, TyKind,
+    BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, Impl, ImplItem, ImplItemKind, Item, ItemKind,
+    Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitFn, TraitItem, TraitItemKind, Ty, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
 use rustc_span::symbol::Symbol;
 impl<'tcx> LateLintPass<'tcx> for Ptr {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
         if let ItemKind::Fn(ref sig, _, body_id) = item.kind {
-            check_fn(cx, sig.decl, item.hir_id(), Some(body_id));
+            check_fn(cx, sig.decl, Some(body_id));
         }
     }
 
@@ -165,7 +165,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>)
                     return; // ignore trait impls
                 }
             }
-            check_fn(cx, sig.decl, item.hir_id(), Some(body_id));
+            check_fn(cx, sig.decl, Some(body_id));
         }
     }
 
@@ -176,7 +176,7 @@ fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>
             } else {
                 None
             };
-            check_fn(cx, sig.decl, item.hir_id(), body_id);
+            check_fn(cx, sig.decl, body_id);
         }
     }
 
@@ -244,13 +244,10 @@ fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
 }
 
 #[allow(clippy::too_many_lines)]
-fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id: Option<BodyId>) {
-    let fn_def_id = cx.tcx.hir().local_def_id(fn_id);
-    let sig = cx.tcx.fn_sig(fn_def_id);
-    let fn_ty = sig.skip_binder();
+fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, opt_body_id: Option<BodyId>) {
     let body = opt_body_id.map(|id| cx.tcx.hir().body(id));
 
-    for (idx, (arg, ty)) in decl.inputs.iter().zip(fn_ty.inputs()).enumerate() {
+    for (idx, arg) in decl.inputs.iter().enumerate() {
         // Honor the allow attribute on parameters. See issue 5644.
         if let Some(body) = &body {
             if is_lint_allowed(cx, PTR_ARG, body.params[idx].hir_id) {
@@ -258,8 +255,20 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
             }
         }
 
-        if let ty::Ref(_, ty, Mutability::Not) = ty.kind() {
-            if is_type_diagnostic_item(cx, ty, sym::Vec) {
+        let (item_name, path) = if_chain! {
+            if let TyKind::Rptr(_, MutTy { ty, mutbl: Mutability::Not }) = arg.kind;
+            if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind;
+            if let Res::Def(_, did) = path.res;
+            if let Some(item_name) = cx.tcx.get_diagnostic_name(did);
+            then {
+                (item_name, path)
+            } else {
+                continue
+            }
+        };
+
+        match item_name {
+            sym::Vec => {
                 if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_owned()")]) {
                     span_lint_and_then(
                         cx,
@@ -289,7 +298,8 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
                         },
                     );
                 }
-            } else if is_type_diagnostic_item(cx, ty, sym::String) {
+            },
+            sym::String => {
                 if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_string()"), ("as_str", "")]) {
                     span_lint_and_then(
                         cx,
@@ -311,7 +321,8 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
                         },
                     );
                 }
-            } else if is_type_diagnostic_item(cx, ty, sym::PathBuf) {
+            },
+            sym::PathBuf => {
                 if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_path_buf()"), ("as_path", "")]) {
                     span_lint_and_then(
                         cx,
@@ -338,11 +349,10 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
                         },
                     );
                 }
-            } else if match_type(cx, ty, &paths::COW) {
+            },
+            sym::Cow => {
                 if_chain! {
-                    if let TyKind::Rptr(_, MutTy { ty, ..} ) = arg.kind;
-                    if let TyKind::Path(QPath::Resolved(None, pp)) = ty.kind;
-                    if let [ref bx] = *pp.segments;
+                    if let [ref bx] = *path.segments;
                     if let Some(params) = bx.args;
                     if !params.parenthesized;
                     if let Some(inner) = params.args.iter().find_map(|arg| match arg {
@@ -363,7 +373,8 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
                         );
                     }
                 }
-            }
+            },
+            _ => {},
         }
     }
 
index 4d616e26bfc1da1dab23a26aaaf0dcbc3b009cf5..f63ef163bcbd0f1b76ddfd92fcac4d38b50a48bc 100644 (file)
@@ -172,23 +172,17 @@ fn expression_returns_none(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool
         }
     }
 
-    fn expression_returns_unmodified_err(
-        cx: &LateContext<'_>,
-        expression: &Expr<'_>,
-        origin_hir_id: &Expr<'_>,
-    ) -> bool {
-        match expression.kind {
+    fn expression_returns_unmodified_err(cx: &LateContext<'_>, expr: &Expr<'_>, cond_expr: &Expr<'_>) -> bool {
+        match expr.kind {
             ExprKind::Block(block, _) => {
                 if let Some(return_expression) = Self::return_expression(block) {
-                    return Self::expression_returns_unmodified_err(cx, return_expression, origin_hir_id);
+                    return Self::expression_returns_unmodified_err(cx, return_expression, cond_expr);
                 }
 
                 false
             },
-            ExprKind::Ret(Some(expr)) | ExprKind::Call(expr, _) => {
-                Self::expression_returns_unmodified_err(cx, expr, origin_hir_id)
-            },
-            ExprKind::Path(_) => path_to_local(expression) == path_to_local(origin_hir_id),
+            ExprKind::Ret(Some(ret_expr)) => Self::expression_returns_unmodified_err(cx, ret_expr, cond_expr),
+            ExprKind::Path(_) => path_to_local(expr) == path_to_local(cond_expr),
             _ => false,
         }
     }
index 35b6bde56964c17f64c1f711dae4ed77fe9839d0..6435107b8b4643f02f94078b7fe0c70802458d56 100644 (file)
     "calling `as_bytes` on a string literal instead of using a byte string literal"
 }
 
-declare_lint_pass!(StringAdd => [STRING_ADD, STRING_ADD_ASSIGN]);
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for slice operations on strings
+    ///
+    /// ### Why is this bad?
+    /// UTF-8 characters span multiple bytes, and it is easy to inadvertently confuse character
+    /// counts and string indices. This may lead to panics, and should warrant some test cases
+    /// containing wide UTF-8 characters. This lint is most useful in code that should avoid
+    /// panics at all costs.
+    ///
+    /// ### Known problems
+    /// Probably lots of false positives. If an index comes from a known valid position (e.g.
+    /// obtained via `char_indices` over the same string), it is totally OK.
+    ///
+    /// # Example
+    /// ```rust,should_panic
+    /// &"Ölkanne"[1..];
+    /// ```
+    pub STRING_SLICE,
+    restriction,
+    "slicing a string"
+}
+
+declare_lint_pass!(StringAdd => [STRING_ADD, STRING_ADD_ASSIGN, STRING_SLICE]);
 
 impl<'tcx> LateLintPass<'tcx> for StringAdd {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         if in_external_macro(cx.sess(), e.span) {
             return;
         }
-
-        if let ExprKind::Binary(
-            Spanned {
-                node: BinOpKind::Add, ..
-            },
-            left,
-            _,
-        ) = e.kind
-        {
-            if is_string(cx, left) {
-                if !is_lint_allowed(cx, STRING_ADD_ASSIGN, e.hir_id) {
-                    let parent = get_parent_expr(cx, e);
-                    if let Some(p) = parent {
-                        if let ExprKind::Assign(target, _, _) = p.kind {
-                            // avoid duplicate matches
-                            if SpanlessEq::new(cx).eq_expr(target, left) {
-                                return;
+        match e.kind {
+            ExprKind::Binary(
+                Spanned {
+                    node: BinOpKind::Add, ..
+                },
+                left,
+                _,
+            ) => {
+                if is_string(cx, left) {
+                    if !is_lint_allowed(cx, STRING_ADD_ASSIGN, e.hir_id) {
+                        let parent = get_parent_expr(cx, e);
+                        if let Some(p) = parent {
+                            if let ExprKind::Assign(target, _, _) = p.kind {
+                                // avoid duplicate matches
+                                if SpanlessEq::new(cx).eq_expr(target, left) {
+                                    return;
+                                }
                             }
                         }
                     }
+                    span_lint(
+                        cx,
+                        STRING_ADD,
+                        e.span,
+                        "you added something to a string. Consider using `String::push_str()` instead",
+                    );
                 }
-                span_lint(
-                    cx,
-                    STRING_ADD,
-                    e.span,
-                    "you added something to a string. Consider using `String::push_str()` instead",
-                );
-            }
-        } else if let ExprKind::Assign(target, src, _) = e.kind {
-            if is_string(cx, target) && is_add(cx, src, target) {
-                span_lint(
-                    cx,
-                    STRING_ADD_ASSIGN,
-                    e.span,
-                    "you assigned the result of adding something to this string. Consider using \
-                     `String::push_str()` instead",
-                );
-            }
+            },
+            ExprKind::Assign(target, src, _) => {
+                if is_string(cx, target) && is_add(cx, src, target) {
+                    span_lint(
+                        cx,
+                        STRING_ADD_ASSIGN,
+                        e.span,
+                        "you assigned the result of adding something to this string. Consider using \
+                         `String::push_str()` instead",
+                    );
+                }
+            },
+            ExprKind::Index(target, _idx) => {
+                let e_ty = cx.typeck_results().expr_ty(target).peel_refs();
+                if matches!(e_ty.kind(), ty::Str) || is_type_diagnostic_item(cx, e_ty, sym::String) {
+                    span_lint(
+                        cx,
+                        STRING_SLICE,
+                        e.span,
+                        "indexing into a string may panic if the index is within a UTF-8 character",
+                    );
+                }
+            },
+            _ => {},
         }
     }
 }
index e08e4d03c7efef5c651cdd46fcfb4ada153400d3..11aef50991b0a1415a12dc83077de7246fe53d03 100644 (file)
@@ -145,8 +145,9 @@ fn block_has_safety_comment(&mut self, tcx: TyCtxt<'_>, enclosing_hir_id: HirId,
         let file_name = source_map.span_to_filename(between_span);
         let source_file = source_map.get_source_file(&file_name)?;
 
-        let lex_start = (between_span.lo().0 + 1) as usize;
-        let src_str = source_file.src.as_ref()?[lex_start..between_span.hi().0 as usize].to_string();
+        let lex_start = (between_span.lo().0 - source_file.start_pos.0 + 1) as usize;
+        let lex_end = (between_span.hi().0 - source_file.start_pos.0) as usize;
+        let src_str = source_file.src.as_ref()?[lex_start..lex_end].to_string();
 
         let mut pos = 0;
         let mut comment = false;
index f337dec8f2b9663faf88299154394ba35e8c49ba..f49ce696a04b77d4832cca91d62f78b12964f72d 100644 (file)
@@ -45,7 +45,7 @@
     /// let x = String::from("\u{20ac}");
     /// ```
     pub NON_ASCII_LITERAL,
-    pedantic,
+    restriction,
     "using any literal non-ASCII chars in a string literal instead of using the `\\u` escape"
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/unit_hash.rs b/src/tools/clippy/clippy_lints/src/unit_hash.rs
new file mode 100644 (file)
index 0000000..a3a3f2d
--- /dev/null
@@ -0,0 +1,77 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Detects `().hash(_)`.
+    ///
+    /// ### Why is this bad?
+    /// Hashing a unit value doesn't do anything as the implementation of `Hash` for `()` is a no-op.
+    ///
+    /// ### Example
+    /// ```rust
+    /// # use std::hash::Hash;
+    /// # use std::collections::hash_map::DefaultHasher;
+    /// # enum Foo { Empty, WithValue(u8) }
+    /// # use Foo::*;
+    /// # let mut state = DefaultHasher::new();
+    /// # let my_enum = Foo::Empty;
+    /// match my_enum {
+    ///        Empty => ().hash(&mut state),
+    ///        WithValue(x) => x.hash(&mut state),
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// # use std::hash::Hash;
+    /// # use std::collections::hash_map::DefaultHasher;
+    /// # enum Foo { Empty, WithValue(u8) }
+    /// # use Foo::*;
+    /// # let mut state = DefaultHasher::new();
+    /// # let my_enum = Foo::Empty;
+    /// match my_enum {
+    ///        Empty => 0_u8.hash(&mut state),
+    ///        WithValue(x) => x.hash(&mut state),
+    /// }
+    /// ```
+    pub UNIT_HASH,
+    correctness,
+    "hashing a unit value, which does nothing"
+}
+declare_lint_pass!(UnitHash => [UNIT_HASH]);
+
+impl LateLintPass<'tcx> for UnitHash {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+        if_chain! {
+            if let ExprKind::MethodCall(name_ident, _, args, _) = &expr.kind;
+            if name_ident.ident.name == sym::hash;
+            if let [recv, state_param] = args;
+            if cx.typeck_results().expr_ty(recv).is_unit();
+            then {
+                span_lint_and_then(
+                    cx,
+                    UNIT_HASH,
+                    expr.span,
+                    "this call to `hash` on the unit type will do nothing",
+                    |diag| {
+                        diag.span_suggestion(
+                            expr.span,
+                            "remove the call to `hash` or consider using",
+                            format!(
+                                "0_u8.hash({})",
+                                snippet(cx, state_param.span, ".."),
+                            ),
+                            Applicability::MaybeIncorrect,
+                        );
+                        diag.note("the implementation of `Hash` for `()` is a no-op");
+                    }
+                );
+            }
+        }
+    }
+}
index a4680ae137b3254e13f3c318448194a10211c8f9..6447e3fa2ca08a85d04716b6bd1f955ba8f5b931 100644 (file)
@@ -13,7 +13,7 @@
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for functions of type Result that contain `expect()` or `unwrap()`
+    /// Checks for functions of type `Result` that contain `expect()` or `unwrap()`
     ///
     /// ### Why is this bad?
     /// These functions promote recoverable errors to non-recoverable errors which may be undesirable in code bases which wish to avoid panics.
index d05c52122d5ee518ab1d00f0349851909026151b..122a5ce3fc8f12d19fd8d0ce877ff2a672c01537 100644 (file)
@@ -288,10 +288,10 @@ pub(crate) fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
     ///
     /// The list of imports to always rename, a fully qualified path followed by the rename.
     (enforced_import_renames: Vec<crate::utils::conf::Rename> = Vec::new()),
-    /// Lint: RESTRICTED_SCRIPTS.
+    /// Lint: DISALLOWED_SCRIPT_IDENTS.
     ///
     /// The list of unicode scripts allowed to be used in the scope.
-    (allowed_scripts: Vec<String> = vec!["Latin".to_string()]),
+    (allowed_scripts: Vec<String> = ["Latin"].iter().map(ToString::to_string).collect()),
     /// Lint: NON_SEND_FIELDS_IN_SEND_TY.
     ///
     /// Whether to apply the raw pointer heuristic to determine if a type is `Send`.
index 0d27874b7affb88d7a4dc16f119469919cbf23ef..99cf4c1ed40fbcbd0a52105176f455b05f230995 100644 (file)
@@ -512,12 +512,21 @@ fn extract_attr_docs(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> {
     let mut lines = attrs.iter().filter_map(ast::Attribute::doc_str);
     let mut docs = String::from(&*lines.next()?.as_str());
     let mut in_code_block = false;
+    let mut is_code_block_rust = false;
     for line in lines {
-        docs.push('\n');
         let line = line.as_str();
         let line = &*line;
+
+        // Rustdoc hides code lines starting with `# ` and this removes them from Clippy's lint list :)
+        if is_code_block_rust && line.trim_start().starts_with("# ") {
+            continue;
+        }
+
+        // The line should be represented in the lint list, even if it's just an empty line
+        docs.push('\n');
         if let Some(info) = line.trim_start().strip_prefix("```") {
             in_code_block = !in_code_block;
+            is_code_block_rust = false;
             if in_code_block {
                 let lang = info
                     .trim()
@@ -528,6 +537,8 @@ fn extract_attr_docs(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> {
                     .unwrap_or("rust");
                 docs.push_str("```");
                 docs.push_str(lang);
+
+                is_code_block_rust = lang == "rust";
                 continue;
             }
         }
index 85d1f65c51f0911aaf1ab76ffb36ce496a759536..b412e15ae4f82c9b474f71837b84cb944ebbd23e 100644 (file)
@@ -4,7 +4,7 @@
 
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::{snippet_opt, snippet_with_applicability};
-use rustc_ast::ast::{Expr, ExprKind, ImplKind, Item, ItemKind, MacCall, Path, StrLit, StrStyle};
+use rustc_ast::ast::{Expr, ExprKind, Impl, Item, ItemKind, MacCall, Path, StrLit, StrStyle};
 use rustc_ast::token::{self, LitKind};
 use rustc_ast::tokenstream::TokenStream;
 use rustc_errors::Applicability;
@@ -243,7 +243,7 @@ pub struct Write {
 
 impl EarlyLintPass for Write {
     fn check_item(&mut self, _: &EarlyContext<'_>, item: &Item) {
-        if let ItemKind::Impl(box ImplKind {
+        if let ItemKind::Impl(box Impl {
             of_trait: Some(trait_ref),
             ..
         }) = &item.kind
index 2fa98831c7740aa31e7765ddf463cb36eba3d658..1b05a8a35046ede0d99e4a5b439f52659ab2a075 100644 (file)
@@ -250,7 +250,8 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
         (Use(l), Use(r)) => eq_use_tree(l, r),
         (Static(lt, lm, le), Static(rt, rm, re)) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re),
         (Const(ld, lt, le), Const(rd, rt, re)) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re),
-        (Fn(box FnKind(ld, lf, lg, lb)), Fn(box FnKind(rd, rf, rg, rb))) => {
+        (Fn(box ast::Fn { defaultness: ld, sig: lf, generics: lg, body: lb }),
+         Fn(box ast::Fn { defaultness: rd, sig: rf, generics: rg, body: rb })) => {
             eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r))
         },
         (Mod(lu, lmk), Mod(ru, rmk)) => {
@@ -266,7 +267,8 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
         (ForeignMod(l), ForeignMod(r)) => {
             both(&l.abi, &r.abi, eq_str_lit) && over(&l.items, &r.items, |l, r| eq_item(l, r, eq_foreign_item_kind))
         },
-        (TyAlias(box TyAliasKind(ld, lg, lb, lt)), TyAlias(box TyAliasKind(rd, rg, rb, rt))) => {
+        (TyAlias(box ast::TyAlias { defaultness: ld, generics: lg, bounds: lb, ty: lt }),
+         TyAlias(box ast::TyAlias { defaultness: rd, generics: rg, bounds: rb, ty: rt })) => {
             eq_defaultness(*ld, *rd)
                 && eq_generics(lg, rg)
                 && over(lb, rb, eq_generic_bound)
@@ -276,7 +278,8 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
         (Struct(lv, lg), Struct(rv, rg)) | (Union(lv, lg), Union(rv, rg)) => {
             eq_variant_data(lv, rv) && eq_generics(lg, rg)
         },
-        (Trait(box TraitKind(la, lu, lg, lb, li)), Trait(box TraitKind(ra, ru, rg, rb, ri))) => {
+        (Trait(box ast::Trait { is_auto: la, unsafety: lu, generics: lg, bounds: lb, items: li }),
+         Trait(box ast::Trait { is_auto: ra, unsafety: ru, generics: rg, bounds: rb, items: ri })) => {
             la == ra
                 && matches!(lu, Unsafe::No) == matches!(ru, Unsafe::No)
                 && eq_generics(lg, rg)
@@ -285,7 +288,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
         },
         (TraitAlias(lg, lb), TraitAlias(rg, rb)) => eq_generics(lg, rg) && over(lb, rb, eq_generic_bound),
         (
-            Impl(box ImplKind {
+            Impl(box ast::Impl {
                 unsafety: lu,
                 polarity: lp,
                 defaultness: ld,
@@ -295,7 +298,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
                 self_ty: lst,
                 items: li,
             }),
-            Impl(box ImplKind {
+            Impl(box ast::Impl {
                 unsafety: ru,
                 polarity: rp,
                 defaultness: rd,
@@ -325,10 +328,12 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
     use ForeignItemKind::*;
     match (l, r) {
         (Static(lt, lm, le), Static(rt, rm, re)) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re),
-        (Fn(box FnKind(ld, lf, lg, lb)), Fn(box FnKind(rd, rf, rg, rb))) => {
+        (Fn(box ast::Fn { defaultness: ld, sig: lf, generics: lg, body: lb }),
+         Fn(box ast::Fn { defaultness: rd, sig: rf, generics: rg, body: rb })) => {
             eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r))
         },
-        (TyAlias(box TyAliasKind(ld, lg, lb, lt)), TyAlias(box TyAliasKind(rd, rg, rb, rt))) => {
+        (TyAlias(box ast::TyAlias { defaultness: ld, generics: lg, bounds: lb, ty: lt }),
+         TyAlias(box ast::TyAlias { defaultness: rd, generics: rg, bounds: rb, ty: rt })) => {
             eq_defaultness(*ld, *rd)
                 && eq_generics(lg, rg)
                 && over(lb, rb, eq_generic_bound)
@@ -343,10 +348,12 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
     use AssocItemKind::*;
     match (l, r) {
         (Const(ld, lt, le), Const(rd, rt, re)) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re),
-        (Fn(box FnKind(ld, lf, lg, lb)), Fn(box FnKind(rd, rf, rg, rb))) => {
+        (Fn(box ast::Fn { defaultness: ld, sig: lf, generics: lg, body: lb }),
+         Fn(box ast::Fn { defaultness: rd, sig: rf, generics: rg, body: rb })) => {
             eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r))
         },
-        (TyAlias(box TyAliasKind(ld, lg, lb, lt)), TyAlias(box TyAliasKind(rd, rg, rb, rt))) => {
+        (TyAlias(box ast::TyAlias { defaultness: ld, generics: lg, bounds: lb, ty: lt }),
+         TyAlias(box ast::TyAlias { defaultness: rd, generics: rg, bounds: rb, ty: rt })) => {
             eq_defaultness(*ld, *rd)
                 && eq_generics(lg, rg)
                 && over(lb, rb, eq_generic_bound)
diff --git a/src/tools/clippy/clippy_utils/src/camel_case.rs b/src/tools/clippy/clippy_utils/src/camel_case.rs
deleted file mode 100644 (file)
index a6636e3..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/// Returns the index of the character after the first camel-case component of `s`.
-#[must_use]
-pub fn until(s: &str) -> usize {
-    let mut iter = s.char_indices();
-    if let Some((_, first)) = iter.next() {
-        if !first.is_uppercase() {
-            return 0;
-        }
-    } else {
-        return 0;
-    }
-    let mut up = true;
-    let mut last_i = 0;
-    for (i, c) in iter {
-        if up {
-            if c.is_lowercase() {
-                up = false;
-            } else {
-                return last_i;
-            }
-        } else if c.is_uppercase() {
-            up = true;
-            last_i = i;
-        } else if !c.is_lowercase() {
-            return i;
-        }
-    }
-    if up { last_i } else { s.len() }
-}
-
-/// Returns index of the last camel-case component of `s`.
-#[must_use]
-pub fn from(s: &str) -> usize {
-    let mut iter = s.char_indices().rev();
-    if let Some((_, first)) = iter.next() {
-        if !first.is_lowercase() {
-            return s.len();
-        }
-    } else {
-        return s.len();
-    }
-    let mut down = true;
-    let mut last_i = s.len();
-    for (i, c) in iter {
-        if down {
-            if c.is_uppercase() {
-                down = false;
-                last_i = i;
-            } else if !c.is_lowercase() {
-                return last_i;
-            }
-        } else if c.is_lowercase() {
-            down = true;
-        } else if c.is_uppercase() {
-            last_i = i;
-        } else {
-            return last_i;
-        }
-    }
-    last_i
-}
-
-#[cfg(test)]
-mod test {
-    use super::{from, until};
-
-    #[test]
-    fn from_full() {
-        assert_eq!(from("AbcDef"), 0);
-        assert_eq!(from("Abc"), 0);
-        assert_eq!(from("ABcd"), 0);
-        assert_eq!(from("ABcdEf"), 0);
-        assert_eq!(from("AabABcd"), 0);
-    }
-
-    #[test]
-    fn from_partial() {
-        assert_eq!(from("abcDef"), 3);
-        assert_eq!(from("aDbc"), 1);
-        assert_eq!(from("aabABcd"), 3);
-    }
-
-    #[test]
-    fn from_not() {
-        assert_eq!(from("AbcDef_"), 7);
-        assert_eq!(from("AbcDD"), 5);
-    }
-
-    #[test]
-    fn from_caps() {
-        assert_eq!(from("ABCD"), 4);
-    }
-
-    #[test]
-    fn until_full() {
-        assert_eq!(until("AbcDef"), 6);
-        assert_eq!(until("Abc"), 3);
-    }
-
-    #[test]
-    fn until_not() {
-        assert_eq!(until("abcDef"), 0);
-        assert_eq!(until("aDbc"), 0);
-    }
-
-    #[test]
-    fn until_partial() {
-        assert_eq!(until("AbcDef_"), 6);
-        assert_eq!(until("CallTypeC"), 8);
-        assert_eq!(until("AbcDD"), 3);
-    }
-
-    #[test]
-    fn until_caps() {
-        assert_eq!(until("ABCD"), 0);
-    }
-}
index 8bf31807d55d1441d74e503a42e29334aee365f0..04347672e0fbb35e12241580aacfeac22de28fbc 100644 (file)
@@ -155,6 +155,19 @@ pub fn partial_cmp(tcx: TyCtxt<'_>, cmp_type: Ty<'_>, left: &Self, right: &Self)
             _ => None,
         }
     }
+
+    /// Returns the integer value or `None` if `self` or `val_type` is not integer type.
+    pub fn int_value(&self, cx: &LateContext<'_>, val_type: Ty<'_>) -> Option<FullInt> {
+        if let Constant::Int(const_int) = *self {
+            match *val_type.kind() {
+                ty::Int(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))),
+                ty::Uint(_) => Some(FullInt::U(const_int)),
+                _ => None,
+            }
+        } else {
+            None
+        }
+    }
 }
 
 /// Parses a `LitKind` to a `Constant`.
@@ -202,6 +215,52 @@ pub fn constant_simple<'tcx>(
     constant(lcx, typeck_results, e).and_then(|(cst, res)| if res { None } else { Some(cst) })
 }
 
+pub fn constant_full_int(
+    lcx: &LateContext<'tcx>,
+    typeck_results: &ty::TypeckResults<'tcx>,
+    e: &Expr<'_>,
+) -> Option<FullInt> {
+    constant_simple(lcx, typeck_results, e)?.int_value(lcx, typeck_results.expr_ty(e))
+}
+
+#[derive(Copy, Clone, Debug, Eq)]
+pub enum FullInt {
+    S(i128),
+    U(u128),
+}
+
+impl PartialEq for FullInt {
+    #[must_use]
+    fn eq(&self, other: &Self) -> bool {
+        self.cmp(other) == Ordering::Equal
+    }
+}
+
+impl PartialOrd for FullInt {
+    #[must_use]
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Ord for FullInt {
+    #[must_use]
+    fn cmp(&self, other: &Self) -> Ordering {
+        use FullInt::{S, U};
+
+        fn cmp_s_u(s: i128, u: u128) -> Ordering {
+            u128::try_from(s).map_or(Ordering::Less, |x| x.cmp(&u))
+        }
+
+        match (*self, *other) {
+            (S(s), S(o)) => s.cmp(&o),
+            (U(s), U(o)) => s.cmp(&o),
+            (S(s), U(o)) => cmp_s_u(s, o),
+            (U(s), S(o)) => cmp_s_u(o, s).reverse(),
+        }
+    }
+}
+
 /// Creates a `ConstEvalLateContext` from the given `LateContext` and `TypeckResults`.
 pub fn constant_context<'a, 'tcx>(
     lcx: &'a LateContext<'tcx>,
index 9302e5c21faa4f7606d485726bcbf256aba1cfb8..d47b002ad7aca95a94336ac60e6b6f511913d3b4 100644 (file)
@@ -72,7 +72,7 @@ pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<Mult
 /// 6  |     let other_f64_nan = 0.0f64 / 0.0;
 ///    |                         ^^^^^^^^^^^^
 ///    |
-///    = help: Consider using `f64::NAN` if you would like a constant representing NaN
+///    = help: consider using `f64::NAN` if you would like a constant representing NaN
 /// ```
 pub fn span_lint_and_help<'a, T: LintContext>(
     cx: &'a T,
index 60c4cb361aa6c0dfbc2d9ff534ca2569d9e7db18..733cc97c84596546bd0005ab6608749270564f7c 100644 (file)
@@ -1,4 +1,4 @@
-//! This module contains functions that retrieves specifiec elements.
+//! This module contains functions that retrieve specific elements.
 
 #![deny(clippy::missing_docs_in_private_items)]
 
@@ -587,9 +587,13 @@ pub fn args(&self) -> Option<Vec<FormatArgsArg<'tcx>>> {
                             if let Some(position_field) = fields.iter().find(|f| f.ident.name == sym::position);
                             if let ExprKind::Lit(lit) = &position_field.expr.kind;
                             if let LitKind::Int(position, _) = lit.node;
+                            if let Ok(i) = usize::try_from(position);
+                            let arg = &self.args[i];
+                            if let ExprKind::Call(_, [arg_name, _]) = arg.kind;
+                            if let ExprKind::Field(_, j) = arg_name.kind;
+                            if let Ok(j) = j.name.as_str().parse::<usize>();
                             then {
-                                let i = usize::try_from(position).unwrap();
-                                Some(FormatArgsArg { value: self.value_args[i], arg: &self.args[i], fmt: Some(fmt) })
+                                Some(FormatArgsArg { value: self.value_args[j], arg, fmt: Some(fmt) })
                             } else {
                                 None
                             }
@@ -718,9 +722,7 @@ impl PanicExpn<'tcx> {
     /// Parses an expanded `panic!` invocation
     pub fn parse(expr: &'tcx Expr<'tcx>) -> Option<Self> {
         if_chain! {
-            if let ExprKind::Block(block, _) = expr.kind;
-            if let Some(init) = block.expr;
-            if let ExprKind::Call(_, [format_args]) = init.kind;
+            if let ExprKind::Call(_, [format_args]) = expr.kind;
             let expn_data = expr.span.ctxt().outer_expn_data();
             if let Some(format_args) = FormatArgsExpn::parse(format_args);
             then {
@@ -770,13 +772,13 @@ pub fn get_vec_init_kind<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -
                     }
                     return Some(VecInitKind::WithExprCapacity(arg.hir_id));
                 }
-            }
+            },
             ExprKind::Path(QPath::Resolved(_, path))
                 if match_def_path(cx, path.res.opt_def_id()?, &paths::DEFAULT_TRAIT_METHOD)
                     && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Vec) =>
             {
                 return Some(VecInitKind::Default);
-            }
+            },
             _ => (),
         }
     }
index 9bc380ca6caa6501c526c4edd18b2faa11df4a5c..086fbc9d3ddddcfba357846e45e897f806118814 100644 (file)
@@ -37,7 +37,6 @@
 #[allow(clippy::module_name_repetitions)]
 pub mod ast_utils;
 pub mod attrs;
-pub mod camel_case;
 pub mod comparisons;
 pub mod consts;
 pub mod diagnostics;
@@ -50,6 +49,7 @@
 pub mod ptr;
 pub mod qualify_min_const_fn;
 pub mod source;
+pub mod str_utils;
 pub mod sugg;
 pub mod ty;
 pub mod usage;
@@ -712,7 +712,7 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
 /// Checks if the top level expression can be moved into a closure as is.
 /// Currently checks for:
 /// * Break/Continue outside the given loop HIR ids.
-/// * Yield/Return statments.
+/// * Yield/Return statements.
 /// * Inline assembly.
 /// * Usages of a field of a local where the type of the local can be partially moved.
 ///
@@ -844,10 +844,13 @@ fn pat_capture_kind(cx: &LateContext<'_>, pat: &Pat<'_>) -> CaptureKind {
     let mut capture_expr_ty = e;
 
     for (parent_id, parent) in cx.tcx.hir().parent_iter(e.hir_id) {
-        if let [Adjustment {
-            kind: Adjust::Deref(_) | Adjust::Borrow(AutoBorrow::Ref(..)),
-            target,
-        }, ref adjust @ ..] = *cx
+        if let [
+            Adjustment {
+                kind: Adjust::Deref(_) | Adjust::Borrow(AutoBorrow::Ref(..)),
+                target,
+            },
+            ref adjust @ ..,
+        ] = *cx
             .typeck_results()
             .adjustments()
             .get(child_id)
@@ -1232,9 +1235,7 @@ pub fn get_enclosing_loop_or_closure(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Opti
     for (_, node) in tcx.hir().parent_iter(expr.hir_id) {
         match node {
             Node::Expr(
-                e
-                @
-                Expr {
+                e @ Expr {
                     kind: ExprKind::Loop(..) | ExprKind::Closure(..),
                     ..
                 },
@@ -1692,10 +1693,12 @@ pub fn is_async_fn(kind: FnKind<'_>) -> bool {
 pub fn get_async_fn_body(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> {
     if let ExprKind::Call(
         _,
-        &[Expr {
-            kind: ExprKind::Closure(_, _, body, _, _),
-            ..
-        }],
+        &[
+            Expr {
+                kind: ExprKind::Closure(_, _, body, _, _),
+                ..
+            },
+        ],
     ) = body.value.kind
     {
         if let ExprKind::Block(
@@ -2123,7 +2126,7 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
     vis.found
 }
 
-/// Checks whether item either has `test` attribute appelied, or
+/// Checks whether item either has `test` attribute applied, or
 /// is a module with `test` in its name.
 ///
 /// Note: If you use this function, please add a `#[test]` case in `tests/ui_test`.
diff --git a/src/tools/clippy/clippy_utils/src/str_utils.rs b/src/tools/clippy/clippy_utils/src/str_utils.rs
new file mode 100644 (file)
index 0000000..cba96e0
--- /dev/null
@@ -0,0 +1,230 @@
+/// Dealing with sting indices can be hard, this struct ensures that both the
+/// character and byte index are provided for correct indexing.
+#[derive(Debug, Default, PartialEq, Eq)]
+pub struct StrIndex {
+    pub char_index: usize,
+    pub byte_index: usize,
+}
+
+impl StrIndex {
+    pub fn new(char_index: usize, byte_index: usize) -> Self {
+        Self { char_index, byte_index }
+    }
+}
+
+/// Returns the index of the character after the first camel-case component of `s`.
+///
+/// ```
+/// assert_eq!(camel_case_until("AbcDef"), StrIndex::new(6, 6));
+/// assert_eq!(camel_case_until("ABCD"), StrIndex::new(0, 0));
+/// assert_eq!(camel_case_until("AbcDD"), StrIndex::new(3, 3));
+/// assert_eq!(camel_case_until("Abc\u{f6}\u{f6}DD"), StrIndex::new(5, 7));
+/// ```
+#[must_use]
+pub fn camel_case_until(s: &str) -> StrIndex {
+    let mut iter = s.char_indices().enumerate();
+    if let Some((_char_index, (_, first))) = iter.next() {
+        if !first.is_uppercase() {
+            return StrIndex::new(0, 0);
+        }
+    } else {
+        return StrIndex::new(0, 0);
+    }
+    let mut up = true;
+    let mut last_index = StrIndex::new(0, 0);
+    for (char_index, (byte_index, c)) in iter {
+        if up {
+            if c.is_lowercase() {
+                up = false;
+            } else {
+                return last_index;
+            }
+        } else if c.is_uppercase() {
+            up = true;
+            last_index.byte_index = byte_index;
+            last_index.char_index = char_index;
+        } else if !c.is_lowercase() {
+            return StrIndex::new(char_index, byte_index);
+        }
+    }
+
+    if up {
+        last_index
+    } else {
+        StrIndex::new(s.chars().count(), s.len())
+    }
+}
+
+/// Returns index of the last camel-case component of `s`.
+///
+/// ```
+/// assert_eq!(camel_case_start("AbcDef"), StrIndex::new(0, 0));
+/// assert_eq!(camel_case_start("abcDef"), StrIndex::new(3, 3));
+/// assert_eq!(camel_case_start("ABCD"), StrIndex::new(4, 4));
+/// assert_eq!(camel_case_start("abcd"), StrIndex::new(4, 4));
+/// assert_eq!(camel_case_start("\u{f6}\u{f6}cd"), StrIndex::new(4, 6));
+/// ```
+#[must_use]
+pub fn camel_case_start(s: &str) -> StrIndex {
+    let char_count = s.chars().count();
+    let range = 0..char_count;
+    let mut iter = range.rev().zip(s.char_indices().rev());
+    if let Some((char_index, (_, first))) = iter.next() {
+        if !first.is_lowercase() {
+            return StrIndex::new(char_index, s.len());
+        }
+    } else {
+        return StrIndex::new(char_count, s.len());
+    }
+    let mut down = true;
+    let mut last_index = StrIndex::new(char_count, s.len());
+    for (char_index, (byte_index, c)) in iter {
+        if down {
+            if c.is_uppercase() {
+                down = false;
+                last_index.byte_index = byte_index;
+                last_index.char_index = char_index;
+            } else if !c.is_lowercase() {
+                return last_index;
+            }
+        } else if c.is_lowercase() {
+            down = true;
+        } else if c.is_uppercase() {
+            last_index.byte_index = byte_index;
+            last_index.char_index = char_index;
+        } else {
+            return last_index;
+        }
+    }
+    last_index
+}
+
+/// Dealing with sting comparison can be complicated, this struct ensures that both the
+/// character and byte count are provided for correct indexing.
+#[derive(Debug, Default, PartialEq, Eq)]
+pub struct StrCount {
+    pub char_count: usize,
+    pub byte_count: usize,
+}
+
+impl StrCount {
+    pub fn new(char_count: usize, byte_count: usize) -> Self {
+        Self { char_count, byte_count }
+    }
+}
+
+/// Returns the number of chars that match from the start
+///
+/// ```
+/// assert_eq!(count_match_start("hello_mouse", "hello_penguin"), StrCount::new(6, 6));
+/// assert_eq!(count_match_start("hello_clippy", "bye_bugs"), StrCount::new(0, 0));
+/// assert_eq!(count_match_start("hello_world", "hello_world"), StrCount::new(11, 11));
+/// assert_eq!(count_match_start("T\u{f6}ffT\u{f6}ff", "T\u{f6}ff"), StrCount::new(4, 5));
+/// ```
+#[must_use]
+pub fn count_match_start(str1: &str, str2: &str) -> StrCount {
+    // (char_index, char1)
+    let char_count = str1.chars().count();
+    let iter1 = (0..=char_count).zip(str1.chars());
+    // (byte_index, char2)
+    let iter2 = str2.char_indices();
+
+    iter1
+        .zip(iter2)
+        .take_while(|((_, c1), (_, c2))| c1 == c2)
+        .last()
+        .map_or_else(StrCount::default, |((char_index, _), (byte_index, character))| {
+            StrCount::new(char_index + 1, byte_index + character.len_utf8())
+        })
+}
+
+/// Returns the number of chars and bytes that match from the end
+///
+/// ```
+/// assert_eq!(count_match_end("hello_cat", "bye_cat"), StrCount::new(4, 4));
+/// assert_eq!(count_match_end("if_item_thing", "enum_value"), StrCount::new(0, 0));
+/// assert_eq!(count_match_end("Clippy", "Clippy"), StrCount::new(6, 6));
+/// assert_eq!(count_match_end("MyT\u{f6}ff", "YourT\u{f6}ff"), StrCount::new(4, 5));
+/// ```
+#[must_use]
+pub fn count_match_end(str1: &str, str2: &str) -> StrCount {
+    let char_count = str1.chars().count();
+    if char_count == 0 {
+        return StrCount::default();
+    }
+
+    // (char_index, char1)
+    let iter1 = (0..char_count).rev().zip(str1.chars().rev());
+    // (byte_index, char2)
+    let byte_count = str2.len();
+    let iter2 = str2.char_indices().rev();
+
+    iter1
+        .zip(iter2)
+        .take_while(|((_, c1), (_, c2))| c1 == c2)
+        .last()
+        .map_or_else(StrCount::default, |((char_index, _), (byte_index, _))| {
+            StrCount::new(char_count - char_index, byte_count - byte_index)
+        })
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+
+    #[test]
+    fn camel_case_start_full() {
+        assert_eq!(camel_case_start("AbcDef"), StrIndex::new(0, 0));
+        assert_eq!(camel_case_start("Abc"), StrIndex::new(0, 0));
+        assert_eq!(camel_case_start("ABcd"), StrIndex::new(0, 0));
+        assert_eq!(camel_case_start("ABcdEf"), StrIndex::new(0, 0));
+        assert_eq!(camel_case_start("AabABcd"), StrIndex::new(0, 0));
+    }
+
+    #[test]
+    fn camel_case_start_partial() {
+        assert_eq!(camel_case_start("abcDef"), StrIndex::new(3, 3));
+        assert_eq!(camel_case_start("aDbc"), StrIndex::new(1, 1));
+        assert_eq!(camel_case_start("aabABcd"), StrIndex::new(3, 3));
+        assert_eq!(camel_case_start("\u{f6}\u{f6}AabABcd"), StrIndex::new(2, 4));
+    }
+
+    #[test]
+    fn camel_case_start_not() {
+        assert_eq!(camel_case_start("AbcDef_"), StrIndex::new(7, 7));
+        assert_eq!(camel_case_start("AbcDD"), StrIndex::new(5, 5));
+        assert_eq!(camel_case_start("all_small"), StrIndex::new(9, 9));
+        assert_eq!(camel_case_start("\u{f6}_all_small"), StrIndex::new(11, 12));
+    }
+
+    #[test]
+    fn camel_case_start_caps() {
+        assert_eq!(camel_case_start("ABCD"), StrIndex::new(4, 4));
+    }
+
+    #[test]
+    fn camel_case_until_full() {
+        assert_eq!(camel_case_until("AbcDef"), StrIndex::new(6, 6));
+        assert_eq!(camel_case_until("Abc"), StrIndex::new(3, 3));
+        assert_eq!(camel_case_until("Abc\u{f6}\u{f6}\u{f6}"), StrIndex::new(6, 9));
+    }
+
+    #[test]
+    fn camel_case_until_not() {
+        assert_eq!(camel_case_until("abcDef"), StrIndex::new(0, 0));
+        assert_eq!(camel_case_until("aDbc"), StrIndex::new(0, 0));
+    }
+
+    #[test]
+    fn camel_case_until_partial() {
+        assert_eq!(camel_case_until("AbcDef_"), StrIndex::new(6, 6));
+        assert_eq!(camel_case_until("CallTypeC"), StrIndex::new(8, 8));
+        assert_eq!(camel_case_until("AbcDD"), StrIndex::new(3, 3));
+        assert_eq!(camel_case_until("Abc\u{f6}\u{f6}DD"), StrIndex::new(5, 7));
+    }
+
+    #[test]
+    fn until_caps() {
+        assert_eq!(camel_case_until("ABCD"), StrIndex::new(0, 0));
+    }
+}
index 004eb28b44640fb59ab3d43c31203ab97c622870..bd32696d6dbda7d15b4b6975a6195f673d2f76c7 100644 (file)
@@ -16,6 +16,7 @@ because that's clearly a non-descriptive name.
   - [Edition 2018 tests](#edition-2018-tests)
   - [Testing manually](#testing-manually)
   - [Lint declaration](#lint-declaration)
+  - [Lint registration](#lint-registration)
   - [Lint passes](#lint-passes)
   - [Emitting a lint](#emitting-a-lint)
   - [Adding the lint logic](#adding-the-lint-logic)
@@ -43,9 +44,9 @@ take a look at our [lint naming guidelines][lint_naming]. To get started on this
 lint you can run `cargo dev new_lint --name=foo_functions --pass=early
 --category=pedantic` (category will default to nursery if not provided). This
 command will create two files: `tests/ui/foo_functions.rs` and
-`clippy_lints/src/foo_functions.rs`, as well as run `cargo dev update_lints` to
-register the new lint. For cargo lints, two project hierarchies (fail/pass) will
-be created by default under `tests/ui-cargo`.
+`clippy_lints/src/foo_functions.rs`, as well as
+[registering the lint](#lint-registration). For cargo lints, two project
+hierarchies (fail/pass) will be created by default under `tests/ui-cargo`.
 
 Next, we'll open up these files and add our lint!
 
@@ -220,32 +221,34 @@ declare_lint_pass!(FooFunctions => [FOO_FUNCTIONS]);
 impl EarlyLintPass for FooFunctions {}
 ```
 
-Normally after declaring the lint, we have to run `cargo dev update_lints`,
-which updates some files, so Clippy knows about the new lint. Since we used
-`cargo dev new_lint ...` to generate the lint declaration, this was done
-automatically. While `update_lints` automates most of the things, it doesn't
-automate everything. We will have to register our lint pass manually in the
-`register_plugins` function in `clippy_lints/src/lib.rs`:
+[declare_clippy_lint]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L60
+[example_lint_page]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
+[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints
+[category_level_mapping]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L110
+
+## Lint registration
+
+When using `cargo dev new_lint`, the lint is automatically registered and
+nothing more has to be done.
+
+When declaring a new lint by hand and `cargo dev update_lints` is used, the lint
+pass may have to be registered manually in the `register_plugins` function in
+`clippy_lints/src/lib.rs`:
 
 ```rust
-store.register_early_pass(|| box foo_functions::FooFunctions);
+store.register_early_pass(|| Box::new(foo_functions::FooFunctions));
 ```
 
 As one may expect, there is a corresponding `register_late_pass` method
 available as well. Without a call to one of `register_early_pass` or
 `register_late_pass`, the lint pass in question will not be run.
 
-One reason that `cargo dev` does not automate this step is that multiple lints
-can use the same lint pass, so registering the lint pass may already be done
-when adding a new lint. Another reason that this step is not automated is that
-the order that the passes are registered determines the order the passes
-actually run, which in turn affects the order that any emitted lints are output
-in.
-
-[declare_clippy_lint]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L60
-[example_lint_page]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
-[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints
-[category_level_mapping]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L110
+One reason that `cargo dev update_lints` does not automate this step is that
+multiple lints can use the same lint pass, so registering the lint pass may
+already be done when adding a new lint. Another reason that this step is not
+automated is that the order that the passes are registered determines the order
+the passes actually run, which in turn affects the order that any emitted lints
+are output in.
 
 ## Lint passes
 
@@ -564,7 +567,8 @@ in the following steps:
     /// <The configuration field doc comment>
     (configuration_ident: Type = DefaultValue),
     ```
-    The doc comment will be automatically added to the lint documentation.
+    The doc comment is automatically added to the documentation of the listed lints. The default
+    value will be formatted using the `Debug` implementation of the type.
 2. Adding the configuration value to the lint impl struct:
     1. This first requires the definition of a lint impl struct. Lint impl structs are usually
         generated with the `declare_lint_pass!` macro. This struct needs to be defined manually
index 67eaf286004f9515cabbfefe3d889ec4b9c74b3f..09554c08987b1ae66902243826bcfec6b063c91f 100644 (file)
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2021-10-21"
+channel = "nightly-2021-11-04"
 components = ["llvm-tools-preview", "rustc-dev", "rust-src"]
index c15835ef2995687327d9227c861b1decd8b3f85d..f25cf1d3ef56185243762a4f3296f4f7ca2eca98 100644 (file)
@@ -104,7 +104,10 @@ fn extern_flags() -> String {
 }
 
 fn default_config() -> compiletest::Config {
-    let mut config = compiletest::Config::default();
+    let mut config = compiletest::Config {
+        edition: Some("2021".into()),
+        ..compiletest::Config::default()
+    };
 
     if let Ok(filters) = env::var("TESTNAME") {
         config.filters = filters.split(',').map(std::string::ToString::to_string).collect();
index bd342e390f52f3d065bdef329f2c082ed3f322c7..7d6edc2b1e095fb1cb59e81cca7b28bba7f44497 100644 (file)
@@ -1,7 +1,10 @@
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 #![warn(rust_2018_idioms, unused_lifetimes)]
 #![allow(clippy::assertions_on_constants)]
+#![feature(path_file_prefix)]
 
+use std::cmp::Ordering;
+use std::ffi::OsStr;
 use std::fs::{self, DirEntry};
 use std::path::Path;
 
@@ -21,29 +24,39 @@ fn test_missing_tests() {
     }
 }
 
-/*
-Test for missing files.
-
-Since rs files are alphabetically before stderr/stdout, we can sort by the full name
-and iter in that order. If we've seen the file stem for the first time and it's not
-a rust file, it means the rust file has to be missing.
-*/
+// Test for missing files.
 fn explore_directory(dir: &Path) -> Vec<String> {
     let mut missing_files: Vec<String> = Vec::new();
     let mut current_file = String::new();
     let mut files: Vec<DirEntry> = fs::read_dir(dir).unwrap().filter_map(Result::ok).collect();
-    files.sort_by_key(std::fs::DirEntry::path);
+    files.sort_by(|x, y| {
+        match x.path().file_prefix().cmp(&y.path().file_prefix()) {
+            Ordering::Equal => (),
+            ord => return ord,
+        }
+        // Sort rs files before the others if they share the same prefix. So when we see
+        // the file prefix for the first time and it's not a rust file, it means the rust
+        // file has to be missing.
+        match (
+            x.path().extension().and_then(OsStr::to_str),
+            y.path().extension().and_then(OsStr::to_str),
+        ) {
+            (Some("rs"), _) => Ordering::Less,
+            (_, Some("rs")) => Ordering::Greater,
+            _ => Ordering::Equal,
+        }
+    });
     for entry in &files {
         let path = entry.path();
         if path.is_dir() {
             missing_files.extend(explore_directory(&path));
         } else {
-            let file_stem = path.file_stem().unwrap().to_str().unwrap().to_string();
+            let file_prefix = path.file_prefix().unwrap().to_str().unwrap().to_string();
             if let Some(ext) = path.extension() {
                 match ext.to_str().unwrap() {
-                    "rs" => current_file = file_stem.clone(),
+                    "rs" => current_file = file_prefix.clone(),
                     "stderr" | "stdout" => {
-                        if file_stem != current_file {
+                        if file_prefix != current_file {
                             missing_files.push(path.to_str().unwrap().to_string());
                         }
                     },
index 33a3ef7513631aab7d1fb367d49c9993ab1c44ad..e678c896fd3e3b3dc8e7bcba92fb5b641a6f8797 100644 (file)
@@ -1,5 +1,3 @@
-// edition:2018
-
 #![warn(clippy::too_many_lines)]
 
 // This function should be considered one line.
index 7551cac9f504b968918e65f3d82ae0ee1b800cf0..d736bf899735a5cfb5ed02eef151b4c20cbd635f 100644 (file)
@@ -1,5 +1,5 @@
 error: this function has too many lines (2/1)
-  --> $DIR/test.rs:20:1
+  --> $DIR/test.rs:18:1
    |
 LL | / fn too_many_lines() {
 LL | |     println!("This is bad.");
@@ -10,7 +10,7 @@ LL | | }
    = note: `-D clippy::too-many-lines` implied by `-D warnings`
 
 error: this function has too many lines (4/1)
-  --> $DIR/test.rs:26:1
+  --> $DIR/test.rs:24:1
    |
 LL | / async fn async_too_many_lines() {
 LL | |     println!("This is bad.");
@@ -19,7 +19,7 @@ LL | | }
    | |_^
 
 error: this function has too many lines (4/1)
-  --> $DIR/test.rs:32:1
+  --> $DIR/test.rs:30:1
    |
 LL | / fn closure_too_many_lines() {
 LL | |     let _ = {
@@ -30,7 +30,7 @@ LL | | }
    | |_^
 
 error: this function has too many lines (2/1)
-  --> $DIR/test.rs:54:1
+  --> $DIR/test.rs:52:1
    |
 LL | / fn comment_before_code() {
 LL | |     let _ = "test";
index 9377eb69b233aca281df4305c86149d13f90b2f6..2498672d77fb04526208e6ec42d9eb8f2772156c 100644 (file)
@@ -1,3 +1,4 @@
+#![allow(clippy::excessive_precision)]
 #[deny(clippy::unreadable_literal)]
 
 fn allow_inconsistent_digit_grouping() {
index 9119ef19a7be1aae36193412bcba84b58b204340..be505bda4792c757982e7c51566cbe6d672740d2 100644 (file)
@@ -1,5 +1,5 @@
 error: digits grouped inconsistently by underscores
-  --> $DIR/test.rs:18:18
+  --> $DIR/test.rs:19:18
    |
 LL |     let _fail1 = 100_200_300.123456789;
    |                  ^^^^^^^^^^^^^^^^^^^^^ help: consider: `100_200_300.123_456_789`
index 2180f848d62cd256f7538d100d6cf5c634398ec2..cb516d0f97783fee0b7b4a71c3cc9336a5072c64 100644 (file)
@@ -1,3 +1,4 @@
+//FIXME: suggestions are wrongly expanded, this should be fixed along with #7843
 #![allow(non_fmt_panics)]
 
 macro_rules! assert_const {
@@ -6,7 +7,6 @@ macro_rules! assert_const {
         debug_assert!($len < 0);
     };
 }
-
 fn main() {
     assert!(true);
     assert!(false);
@@ -14,7 +14,7 @@ fn main() {
     assert!(false, "false message");
 
     let msg = "panic message";
-    assert!(false, msg.to_uppercase());
+    assert!(false, "{}", msg.to_uppercase());
 
     const B: bool = true;
     assert!(B);
index 4ca1e6f6e88cc783cf0b2ecd25d9b0c44ddfea5e..ec80ec702fb574ad4cf6380b9e7b2179230a8c84 100644 (file)
@@ -26,22 +26,13 @@ LL |     assert!(true, "true message");
    = help: remove it
    = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: `assert!(false, "false message")` should probably be replaced
+error: `assert!(false, $crate::const_format_args!($($t)+))` should probably be replaced
   --> $DIR/assertions_on_constants.rs:14:5
    |
 LL |     assert!(false, "false message");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: use `panic!("false message")` or `unreachable!("false message")`
-   = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: `assert!(false, msg.to_uppercase())` should probably be replaced
-  --> $DIR/assertions_on_constants.rs:17:5
-   |
-LL |     assert!(false, msg.to_uppercase());
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: use `panic!(msg.to_uppercase())` or `unreachable!(msg.to_uppercase())`
+   = help: use `panic!($crate::const_format_args!($($t)+))` or `unreachable!($crate::const_format_args!($($t)+))`
    = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: `assert!(true)` will be optimized out by the compiler
@@ -62,13 +53,13 @@ LL |     assert!(C);
    = help: use `panic!()` or `unreachable!()`
    = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: `assert!(false, "C message")` should probably be replaced
+error: `assert!(false, $crate::const_format_args!($($t)+))` should probably be replaced
   --> $DIR/assertions_on_constants.rs:24:5
    |
 LL |     assert!(C, "C message");
    |     ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: use `panic!("C message")` or `unreachable!("C message")`
+   = help: use `panic!($crate::const_format_args!($($t)+))` or `unreachable!($crate::const_format_args!($($t)+))`
    = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: `debug_assert!(true)` will be optimized out by the compiler
@@ -80,5 +71,5 @@ LL |     debug_assert!(true);
    = help: remove it
    = note: this error originates in the macro `$crate::assert` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 9 previous errors
+error: aborting due to 8 previous errors
 
index 9b1a7ac3ba9de85493244232abca89ce4d5d5452..e20b58269b93e60485b68b74618b3bc4a6fe77d3 100644 (file)
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 
 #![feature(async_closure)]
 #![warn(clippy::async_yields_async)]
index 731c094edb42b16b7a8488293fb09affc43d92db..c1dfa398450250f6d67a6d1290e34c139865d8e1 100644 (file)
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 
 #![feature(async_closure)]
 #![warn(clippy::async_yields_async)]
index 3f2051458f677c219930503943f5ef00ae44224a..b0c4215e7ddf1be1c4bbcaeb031e3896096f9386 100644 (file)
@@ -1,5 +1,5 @@
 error: an async construct yields a type which is itself awaitable
-  --> $DIR/async_yields_async.rs:40:9
+  --> $DIR/async_yields_async.rs:39:9
    |
 LL |        let _h = async {
    |   ____________________-
@@ -20,7 +20,7 @@ LL +         }.await
    |
 
 error: an async construct yields a type which is itself awaitable
-  --> $DIR/async_yields_async.rs:45:9
+  --> $DIR/async_yields_async.rs:44:9
    |
 LL |       let _i = async {
    |  ____________________-
@@ -33,7 +33,7 @@ LL | |     };
    | |_____- outer async construct
 
 error: an async construct yields a type which is itself awaitable
-  --> $DIR/async_yields_async.rs:51:9
+  --> $DIR/async_yields_async.rs:50:9
    |
 LL |        let _j = async || {
    |   _______________________-
@@ -53,7 +53,7 @@ LL +         }.await
    |
 
 error: an async construct yields a type which is itself awaitable
-  --> $DIR/async_yields_async.rs:56:9
+  --> $DIR/async_yields_async.rs:55:9
    |
 LL |       let _k = async || {
    |  _______________________-
@@ -66,7 +66,7 @@ LL | |     };
    | |_____- outer async construct
 
 error: an async construct yields a type which is itself awaitable
-  --> $DIR/async_yields_async.rs:58:23
+  --> $DIR/async_yields_async.rs:57:23
    |
 LL |     let _l = async || CustomFutureType;
    |                       ^^^^^^^^^^^^^^^^
@@ -76,7 +76,7 @@ LL |     let _l = async || CustomFutureType;
    |                       help: consider awaiting this value: `CustomFutureType.await`
 
 error: an async construct yields a type which is itself awaitable
-  --> $DIR/async_yields_async.rs:64:9
+  --> $DIR/async_yields_async.rs:63:9
    |
 LL |       let _m = async || {
    |  _______________________-
index 0458950edee1c9660d41a4e15a974038f3949eac..dd6640a387a23877548f96c8b6a40185b27c7cfd 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::await_holding_lock)]
 
 use std::sync::Mutex;
index a5fcff7e0e44363f02087f6c87fdfacc46638734..ddfb104cdfbd07ab1207f133e075182b3d409d0e 100644 (file)
@@ -1,12 +1,12 @@
 error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await
-  --> $DIR/await_holding_lock.rs:7:9
+  --> $DIR/await_holding_lock.rs:6:9
    |
 LL |     let guard = x.lock().unwrap();
    |         ^^^^^
    |
    = note: `-D clippy::await-holding-lock` implied by `-D warnings`
 note: these are all the await points this lock is held through
-  --> $DIR/await_holding_lock.rs:7:5
+  --> $DIR/await_holding_lock.rs:6:5
    |
 LL | /     let guard = x.lock().unwrap();
 LL | |     baz().await
@@ -14,13 +14,13 @@ LL | | }
    | |_^
 
 error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await
-  --> $DIR/await_holding_lock.rs:28:9
+  --> $DIR/await_holding_lock.rs:27:9
    |
 LL |     let guard = x.lock().unwrap();
    |         ^^^^^
    |
 note: these are all the await points this lock is held through
-  --> $DIR/await_holding_lock.rs:28:5
+  --> $DIR/await_holding_lock.rs:27:5
    |
 LL | /     let guard = x.lock().unwrap();
 LL | |
@@ -32,13 +32,13 @@ LL | | }
    | |_^
 
 error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await
-  --> $DIR/await_holding_lock.rs:41:13
+  --> $DIR/await_holding_lock.rs:40:13
    |
 LL |         let guard = x.lock().unwrap();
    |             ^^^^^
    |
 note: these are all the await points this lock is held through
-  --> $DIR/await_holding_lock.rs:41:9
+  --> $DIR/await_holding_lock.rs:40:9
    |
 LL | /         let guard = x.lock().unwrap();
 LL | |         baz().await
@@ -46,13 +46,13 @@ LL | |     };
    | |_____^
 
 error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await
-  --> $DIR/await_holding_lock.rs:53:13
+  --> $DIR/await_holding_lock.rs:52:13
    |
 LL |         let guard = x.lock().unwrap();
    |             ^^^^^
    |
 note: these are all the await points this lock is held through
-  --> $DIR/await_holding_lock.rs:53:9
+  --> $DIR/await_holding_lock.rs:52:9
    |
 LL | /         let guard = x.lock().unwrap();
 LL | |         baz().await
index 88841597bb60bf5bc8a8bff346fdfc9391a40cfe..23b7095de3a39ae31a36bbc37a7b625c38bec5b3 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::await_holding_refcell_ref)]
 
 use std::cell::RefCell;
index 55e41dbca96f834046b43c624e377ddcb6bbb6d3..67cc0032be2f46742725351dd9beca969d458b4e 100644 (file)
@@ -1,12 +1,12 @@
 error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
-  --> $DIR/await_holding_refcell_ref.rs:7:9
+  --> $DIR/await_holding_refcell_ref.rs:6:9
    |
 LL |     let b = x.borrow();
    |         ^
    |
    = note: `-D clippy::await-holding-refcell-ref` implied by `-D warnings`
 note: these are all the await points this ref is held through
-  --> $DIR/await_holding_refcell_ref.rs:7:5
+  --> $DIR/await_holding_refcell_ref.rs:6:5
    |
 LL | /     let b = x.borrow();
 LL | |     baz().await
@@ -14,13 +14,13 @@ LL | | }
    | |_^
 
 error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
-  --> $DIR/await_holding_refcell_ref.rs:12:9
+  --> $DIR/await_holding_refcell_ref.rs:11:9
    |
 LL |     let b = x.borrow_mut();
    |         ^
    |
 note: these are all the await points this ref is held through
-  --> $DIR/await_holding_refcell_ref.rs:12:5
+  --> $DIR/await_holding_refcell_ref.rs:11:5
    |
 LL | /     let b = x.borrow_mut();
 LL | |     baz().await
@@ -28,13 +28,13 @@ LL | | }
    | |_^
 
 error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
-  --> $DIR/await_holding_refcell_ref.rs:33:9
+  --> $DIR/await_holding_refcell_ref.rs:32:9
    |
 LL |     let b = x.borrow_mut();
    |         ^
    |
 note: these are all the await points this ref is held through
-  --> $DIR/await_holding_refcell_ref.rs:33:5
+  --> $DIR/await_holding_refcell_ref.rs:32:5
    |
 LL | /     let b = x.borrow_mut();
 LL | |
@@ -46,13 +46,13 @@ LL | | }
    | |_^
 
 error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
-  --> $DIR/await_holding_refcell_ref.rs:45:9
+  --> $DIR/await_holding_refcell_ref.rs:44:9
    |
 LL |     let b = x.borrow_mut();
    |         ^
    |
 note: these are all the await points this ref is held through
-  --> $DIR/await_holding_refcell_ref.rs:45:5
+  --> $DIR/await_holding_refcell_ref.rs:44:5
    |
 LL | /     let b = x.borrow_mut();
 LL | |
@@ -64,13 +64,13 @@ LL | | }
    | |_^
 
 error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
-  --> $DIR/await_holding_refcell_ref.rs:60:13
+  --> $DIR/await_holding_refcell_ref.rs:59:13
    |
 LL |         let b = x.borrow_mut();
    |             ^
    |
 note: these are all the await points this ref is held through
-  --> $DIR/await_holding_refcell_ref.rs:60:9
+  --> $DIR/await_holding_refcell_ref.rs:59:9
    |
 LL | /         let b = x.borrow_mut();
 LL | |         baz().await
@@ -78,13 +78,13 @@ LL | |     };
    | |_____^
 
 error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
-  --> $DIR/await_holding_refcell_ref.rs:72:13
+  --> $DIR/await_holding_refcell_ref.rs:71:13
    |
 LL |         let b = x.borrow_mut();
    |             ^
    |
 note: these are all the await points this ref is held through
-  --> $DIR/await_holding_refcell_ref.rs:72:9
+  --> $DIR/await_holding_refcell_ref.rs:71:9
    |
 LL | /         let b = x.borrow_mut();
 LL | |         baz().await
index 8ee0969b0f0761b16371eb485570ac83ad3abe5d..ebc1ed5587fe30a9b8f6675e6ac51b79f1a9725f 100644 (file)
@@ -92,4 +92,27 @@ fn main() {
     (1i64).checked_rem_euclid(-1i64).unwrap() as u64;
     (1i64).checked_rem_euclid(-1i64).unwrap() as u128;
     (1isize).checked_rem_euclid(-1isize).unwrap() as usize;
+
+    // no lint for `cast_possible_truncation`
+    // with `signum` method call (see issue #5395)
+    let x: i64 = 5;
+    let _ = x.signum() as i32;
+
+    let s = x.signum();
+    let _ = s as i32;
+
+    // Test for signed min
+    (-99999999999i64).min(1) as i8; // should be linted because signed
+
+    // Test for various operations that remove enough bits for the result to fit
+    (999999u64 & 1) as u8;
+    (999999u64 % 15) as u8;
+    (999999u64 / 0x1_0000_0000_0000) as u16;
+    ({ 999999u64 >> 56 }) as u8;
+    ({
+        let x = 999999u64;
+        x.min(1)
+    }) as u8;
+    999999u64.clamp(0, 255) as u8;
+    999999u64.clamp(0, 256) as u8; // should still be linted
 }
index 4c66d736494843955903b39f917ac5ee187f61d5..edf8790cf33d861c3978669145d5e500f2232314 100644 (file)
@@ -138,5 +138,17 @@ error: casting `isize` to `usize` may lose the sign of the value
 LL |     -1isize as usize;
    |     ^^^^^^^^^^^^^^^^
 
-error: aborting due to 22 previous errors
+error: casting `i64` to `i8` may truncate the value
+  --> $DIR/cast.rs:105:5
+   |
+LL |     (-99999999999i64).min(1) as i8; // should be linted because signed
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `u64` to `u8` may truncate the value
+  --> $DIR/cast.rs:117:5
+   |
+LL |     999999u64.clamp(0, 256) as u8; // should still be linted
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 24 previous errors
 
diff --git a/src/tools/clippy/tests/ui/crashes/auxiliary/ice-7868-aux.rs b/src/tools/clippy/tests/ui/crashes/auxiliary/ice-7868-aux.rs
new file mode 100644 (file)
index 0000000..bee2989
--- /dev/null
@@ -0,0 +1,3 @@
+fn zero() {
+    unsafe { 0 };
+}
index 4feab7910b7445da53bf0c73ac25bea9ce160a66..9b68cac7ff4854abc60352d7c8cbff472604cf44 100644 (file)
@@ -7,7 +7,6 @@
 // in type inference.
 #![feature(trivial_bounds)]
 #![allow(unused)]
-
 trait A {}
 
 impl A for i32 {}
@@ -22,9 +21,9 @@ struct TwoStrs(str, str)
 
 fn unsized_local()
 where
-    for<'a> Dst<A + 'a>: Sized,
+    for<'a> Dst<dyn A + 'a>: Sized,
 {
-    let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
+    let x: Dst<dyn A> = *(Box::new(Dst { x: 1 }) as Box<Dst<dyn A>>);
 }
 
 fn return_str() -> str
index 9a89047f072777cd7f6bf3f5588083be74b7f6b0..79018080886c0561d33fc88fe31890911f4ccd9f 100644 (file)
@@ -1,30 +1,34 @@
-error: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/ice-3969.rs:25:17
+error: trait bound str: std::marker::Sized does not depend on any type or lifetime parameters
+  --> $DIR/ice-3969.rs:20:10
    |
-LL |     for<'a> Dst<A + 'a>: Sized,
-   |                 ^^^^^^ help: use `dyn`: `dyn A + 'a`
+LL |     str: Sized;
+   |          ^^^^^
    |
-   = note: `-D bare-trait-objects` implied by `-D warnings`
-   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: `-D trivial-bounds` implied by `-D warnings`
 
-error: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/ice-3969.rs:27:16
+error: trait bound for<'a> Dst<(dyn A + 'a)>: std::marker::Sized does not depend on any type or lifetime parameters
+  --> $DIR/ice-3969.rs:24:30
    |
-LL |     let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
-   |                ^ help: use `dyn`: `dyn A`
+LL |     for<'a> Dst<dyn A + 'a>: Sized,
+   |                              ^^^^^
+
+error: trait bound str: std::marker::Sized does not depend on any type or lifetime parameters
+  --> $DIR/ice-3969.rs:31:10
    |
-   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+LL |     str: Sized,
+   |          ^^^^^
 
-error: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/ice-3969.rs:27:57
+error: trait bound std::string::String: std::ops::Neg does not depend on any type or lifetime parameters
+  --> $DIR/ice-3969.rs:38:13
    |
-LL |     let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
-   |                                                         ^ help: use `dyn`: `dyn A`
+LL |     String: ::std::ops::Neg<Output = String>,
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bound i32: std::iter::Iterator does not depend on any type or lifetime parameters
+  --> $DIR/ice-3969.rs:45:10
    |
-   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+LL |     i32: Iterator,
+   |          ^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 5 previous errors
 
index 1b20c9defac823185ec31b6a3229167d0abb5e58..f463f78a99ab738bc0117ad3391817145323c146 100644 (file)
@@ -1,5 +1,3 @@
-// edition:2018
-
 // Regression test for https://github.com/rust-lang/rust-clippy/issues/5207
 
 pub async fn bar<'a, T: 'a>(_: T) {}
index 2e3d9fd1e9240ed097512ca6216325968fa4c078..0ccf0aae9d74298099fd483995d2d73ce76763b3 100644 (file)
@@ -1,6 +1,5 @@
 // originally from glacier fixed/77919.rs
 // encountered errors resolving bounds after type-checking
-
 trait TypeVal<T> {
     const VAL: T;
 }
index eaa5e6f51cb4abd51ed518386e1fb9a867061237..c8239897f3abb5b7032d8f574aeae103599b1e71 100644 (file)
@@ -1,16 +1,20 @@
 error[E0412]: cannot find type `PhantomData` in this scope
-  --> $DIR/ice-6252.rs:9:9
+  --> $DIR/ice-6252.rs:8:9
    |
 LL |     _n: PhantomData,
    |         ^^^^^^^^^^^ not found in this scope
    |
-help: consider importing this struct
+help: consider importing one of these items
+   |
+LL | use core::marker::PhantomData;
+   |
+LL | use serde::__private::PhantomData;
    |
 LL | use std::marker::PhantomData;
    |
 
 error[E0412]: cannot find type `VAL` in this scope
-  --> $DIR/ice-6252.rs:11:63
+  --> $DIR/ice-6252.rs:10:63
    |
 LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
    |          -                                                    ^^^ not found in this scope
@@ -18,7 +22,7 @@ LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
    |          help: you might be missing a type parameter: `, VAL`
 
 error[E0046]: not all trait items implemented, missing: `VAL`
-  --> $DIR/ice-6252.rs:11:1
+  --> $DIR/ice-6252.rs:10:1
    |
 LL |     const VAL: T;
    |     ------------- `VAL` from trait
index 5595d8d1d626978d136f7c61e26daa74a07010dd..4ad0d351372f7559de26a2a84d6974f0cdf3643a 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 #![allow(clippy::never_loop)]
 
 async fn f() {
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7868.rs b/src/tools/clippy/tests/ui/crashes/ice-7868.rs
new file mode 100644 (file)
index 0000000..c693216
--- /dev/null
@@ -0,0 +1,7 @@
+#![warn(clippy::undocumented_unsafe_blocks)]
+#![allow(clippy::no_effect)]
+
+#[path = "auxiliary/ice-7868-aux.rs"]
+mod zero;
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7868.stderr b/src/tools/clippy/tests/ui/crashes/ice-7868.stderr
new file mode 100644 (file)
index 0000000..d7b49eb
--- /dev/null
@@ -0,0 +1,15 @@
+error: unsafe block missing a safety comment
+  --> $DIR/auxiliary/ice-7868-aux.rs:2:5
+   |
+LL |     unsafe { 0 };
+   |     ^^^^^^^^^^^^
+   |
+   = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings`
+help: consider adding a safety comment
+   |
+LL ~     // Safety: ...
+LL ~     unsafe { 0 };
+   |
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7869.rs b/src/tools/clippy/tests/ui/crashes/ice-7869.rs
new file mode 100644 (file)
index 0000000..8f97a06
--- /dev/null
@@ -0,0 +1,7 @@
+enum Tila {
+    TyöAlkoi,
+    TyöKeskeytyi,
+    TyöValmis,
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7869.stderr b/src/tools/clippy/tests/ui/crashes/ice-7869.stderr
new file mode 100644 (file)
index 0000000..4fa9fb2
--- /dev/null
@@ -0,0 +1,15 @@
+error: all variants have the same prefix: `Työ`
+  --> $DIR/ice-7869.rs:1:1
+   |
+LL | / enum Tila {
+LL | |     TyöAlkoi,
+LL | |     TyöKeskeytyi,
+LL | |     TyöValmis,
+LL | | }
+   | |_^
+   |
+   = note: `-D clippy::enum-variant-names` implied by `-D warnings`
+   = help: remove the prefixes and use full paths to the variants instead of glob imports
+
+error: aborting due to previous error
+
index c57a45dc7aab9b1c1f3e48dfc7e41558b6002fc9..901eb4e50398888f50747c1ba2a496703474d82e 100644 (file)
@@ -1,5 +1,3 @@
-// edition:2018
-
 use serde::Deserialize;
 
 /// Tests that we do not lint for unused underscores in a `MacroAttribute`
index 477a47118d4116587fc6526ca01f3f72edf639e2..c5de412556567ffe6718fc9ada4471dcb5e4cc8b 100644 (file)
@@ -1,9 +1,9 @@
-// compile-flags: --edition=2018
 #![feature(custom_inner_attributes)]
 #![rustfmt::skip]
 #![warn(clippy::debug_assert_with_mut_call)]
 #![allow(clippy::redundant_closure_call)]
 
+
 struct S;
 
 impl S {
index 1943d0092e6244851b9c5480a879116b788e56b9..39a2601fee9aca39e6d3882f27c8d1008ffce339 100644 (file)
@@ -1,19 +1,18 @@
-#[warn(clippy::unstable_as_slice)]
-#[warn(clippy::unstable_as_mut_slice)]
-#[warn(clippy::misaligned_transmute)]
-#[warn(clippy::unused_collect)]
-#[warn(clippy::invalid_ref)]
-#[warn(clippy::into_iter_on_array)]
-#[warn(clippy::unused_label)]
-#[warn(clippy::regex_macro)]
-#[warn(clippy::drop_bounds)]
-#[warn(clippy::temporary_cstring_as_ptr)]
-#[warn(clippy::panic_params)]
-#[warn(clippy::unknown_clippy_lints)]
-#[warn(clippy::find_map)]
-#[warn(clippy::filter_map)]
-#[warn(clippy::pub_enum_variant_names)]
-#[warn(clippy::wrong_pub_self_convention)]
-#[warn(clippy::invalid_atomic_ordering)]
+#![warn(clippy::should_assert_eq)]
+#![warn(clippy::extend_from_slice)]
+#![warn(clippy::range_step_by_zero)]
+#![warn(clippy::unstable_as_slice)]
+#![warn(clippy::unstable_as_mut_slice)]
+#![warn(clippy::misaligned_transmute)]
+#![warn(clippy::assign_ops)]
+#![warn(clippy::if_let_redundant_pattern_matching)]
+#![warn(clippy::unsafe_vector_initialization)]
+#![warn(clippy::unused_collect)]
+#![warn(clippy::replace_consts)]
+#![warn(clippy::regex_macro)]
+#![warn(clippy::find_map)]
+#![warn(clippy::filter_map)]
+#![warn(clippy::pub_enum_variant_names)]
+#![warn(clippy::wrong_pub_self_convention)]
 
 fn main() {}
index 51048e45c0677c208bb8e050edc7fa0169eb8a82..6095f134d55e0d2ea7452696adfb9a047521f077 100644 (file)
-error: lint `clippy::unstable_as_slice` has been removed: `Vec::as_slice` has been stabilized in 1.7
-  --> $DIR/deprecated.rs:1:8
+error: lint `clippy::should_assert_eq` has been removed: `assert!()` will be more flexible with RFC 2011
+  --> $DIR/deprecated.rs:1:9
    |
-LL | #[warn(clippy::unstable_as_slice)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::should_assert_eq)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D renamed-and-removed-lints` implied by `-D warnings`
 
-error: lint `clippy::unstable_as_mut_slice` has been removed: `Vec::as_mut_slice` has been stabilized in 1.7
-  --> $DIR/deprecated.rs:2:8
+error: lint `clippy::extend_from_slice` has been removed: `.extend_from_slice(_)` is a faster way to extend a Vec by a slice
+  --> $DIR/deprecated.rs:2:9
    |
-LL | #[warn(clippy::unstable_as_mut_slice)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::extend_from_slice)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::misaligned_transmute` has been removed: this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr
-  --> $DIR/deprecated.rs:3:8
+error: lint `clippy::range_step_by_zero` has been removed: `iterator.step_by(0)` panics nowadays
+  --> $DIR/deprecated.rs:3:9
    |
-LL | #[warn(clippy::misaligned_transmute)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::range_step_by_zero)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::unused_collect` has been removed: `collect` has been marked as #[must_use] in rustc and that covers all cases of this lint
-  --> $DIR/deprecated.rs:4:8
+error: lint `clippy::unstable_as_slice` has been removed: `Vec::as_slice` has been stabilized in 1.7
+  --> $DIR/deprecated.rs:4:9
    |
-LL | #[warn(clippy::unused_collect)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::unstable_as_slice)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
-  --> $DIR/deprecated.rs:5:8
+error: lint `clippy::unstable_as_mut_slice` has been removed: `Vec::as_mut_slice` has been stabilized in 1.7
+  --> $DIR/deprecated.rs:5:9
    |
-LL | #[warn(clippy::invalid_ref)]
-   |        ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
+LL | #![warn(clippy::unstable_as_mut_slice)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-  --> $DIR/deprecated.rs:6:8
+error: lint `clippy::misaligned_transmute` has been removed: this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr
+  --> $DIR/deprecated.rs:6:9
    |
-LL | #[warn(clippy::into_iter_on_array)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
+LL | #![warn(clippy::misaligned_transmute)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::unused_label` has been renamed to `unused_labels`
-  --> $DIR/deprecated.rs:7:8
+error: lint `clippy::assign_ops` has been removed: using compound assignment operators (e.g., `+=`) is harmless
+  --> $DIR/deprecated.rs:7:9
    |
-LL | #[warn(clippy::unused_label)]
-   |        ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
+LL | #![warn(clippy::assign_ops)]
+   |         ^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::regex_macro` has been removed: the regex! macro has been removed from the regex crate in 2018
-  --> $DIR/deprecated.rs:8:8
+error: lint `clippy::if_let_redundant_pattern_matching` has been removed: this lint has been changed to redundant_pattern_matching
+  --> $DIR/deprecated.rs:8:9
    |
-LL | #[warn(clippy::regex_macro)]
-   |        ^^^^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::if_let_redundant_pattern_matching)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-  --> $DIR/deprecated.rs:9:8
+error: lint `clippy::unsafe_vector_initialization` has been removed: the replacement suggested by this lint had substantially different behavior
+  --> $DIR/deprecated.rs:9:9
    |
-LL | #[warn(clippy::drop_bounds)]
-   |        ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
+LL | #![warn(clippy::unsafe_vector_initialization)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
-  --> $DIR/deprecated.rs:10:8
+error: lint `clippy::unused_collect` has been removed: `collect` has been marked as #[must_use] in rustc and that covers all cases of this lint
+  --> $DIR/deprecated.rs:10:9
    |
-LL | #[warn(clippy::temporary_cstring_as_ptr)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
+LL | #![warn(clippy::unused_collect)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
-  --> $DIR/deprecated.rs:11:8
+error: lint `clippy::replace_consts` has been removed: associated-constants `MIN`/`MAX` of integers are preferred to `{min,max}_value()` and module constants
+  --> $DIR/deprecated.rs:11:9
    |
-LL | #[warn(clippy::panic_params)]
-   |        ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
+LL | #![warn(clippy::replace_consts)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
-  --> $DIR/deprecated.rs:12:8
+error: lint `clippy::regex_macro` has been removed: the regex! macro has been removed from the regex crate in 2018
+  --> $DIR/deprecated.rs:12:9
    |
-LL | #[warn(clippy::unknown_clippy_lints)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
+LL | #![warn(clippy::regex_macro)]
+   |         ^^^^^^^^^^^^^^^^^^^
 
 error: lint `clippy::find_map` has been removed: this lint has been replaced by `manual_find_map`, a more specific lint
-  --> $DIR/deprecated.rs:13:8
+  --> $DIR/deprecated.rs:13:9
    |
-LL | #[warn(clippy::find_map)]
-   |        ^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::find_map)]
+   |         ^^^^^^^^^^^^^^^^
 
 error: lint `clippy::filter_map` has been removed: this lint has been replaced by `manual_filter_map`, a more specific lint
-  --> $DIR/deprecated.rs:14:8
+  --> $DIR/deprecated.rs:14:9
    |
-LL | #[warn(clippy::filter_map)]
-   |        ^^^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::filter_map)]
+   |         ^^^^^^^^^^^^^^^^^^
 
 error: lint `clippy::pub_enum_variant_names` has been removed: set the `avoid-breaking-exported-api` config option to `false` to enable the `enum_variant_names` lint for public items
-  --> $DIR/deprecated.rs:15:8
+  --> $DIR/deprecated.rs:15:9
    |
-LL | #[warn(clippy::pub_enum_variant_names)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::pub_enum_variant_names)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: lint `clippy::wrong_pub_self_convention` has been removed: set the `avoid-breaking-exported-api` config option to `false` to enable the `wrong_self_convention` lint for public items
-  --> $DIR/deprecated.rs:16:8
-   |
-LL | #[warn(clippy::wrong_pub_self_convention)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
-  --> $DIR/deprecated.rs:17:8
+  --> $DIR/deprecated.rs:16:9
    |
-LL | #[warn(clippy::invalid_atomic_ordering)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
+LL | #![warn(clippy::wrong_pub_self_convention)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 17 previous errors
+error: aborting due to 16 previous errors
 
index d4832daa6895970746de537909bb6339af07331e..9a150c67a21ea583cadad59326c607f33cb8b318 100644 (file)
@@ -52,12 +52,14 @@ macro_rules! m_mut {
     };
 }
 
+#[derive(Copy, Clone)]
 pub struct S;
 impl S {
     pub fn f(&self) -> &Self {
         m!(self)
     }
-    pub fn f_mut(&self) -> &Self {
+    #[allow(unused_mut)] // mut will be unused, once the macro is fixed
+    pub fn f_mut(mut self) -> Self {
         m_mut!(self)
     }
 }
index be7cc669b5b6daf3c0cb855d6fe861e7920e943e..80ba7e9bd0b8202cbe9202343e3dd227000ff95f 100644 (file)
@@ -52,12 +52,14 @@ macro_rules! m_mut {
     };
 }
 
+#[derive(Copy, Clone)]
 pub struct S;
 impl S {
     pub fn f(&self) -> &Self {
         m!(self)
     }
-    pub fn f_mut(&self) -> &Self {
+    #[allow(unused_mut)] // mut will be unused, once the macro is fixed
+    pub fn f_mut(mut self) -> Self {
         m_mut!(self)
     }
 }
index 4df241c9fc39be35b1fe3a00ac017e637ad69e82..e27f9fea708ee16c0bcfd889cf27ad6ed7b39b8d 100644 (file)
@@ -1,6 +1,5 @@
 #![warn(clippy::diverging_sub_expression)]
 #![allow(clippy::match_same_arms, clippy::logic_bug)]
-
 #[allow(clippy::empty_loop)]
 fn diverge() -> ! {
     loop {}
index 170e7d92de4acff6b643a1ead8d762e2d61e2d8b..c712a6a7e38eaf1433c0aee8f46e4897612370a7 100644 (file)
@@ -1,5 +1,5 @@
 error: sub-expression diverges
-  --> $DIR/diverging_sub_expression.rs:20:10
+  --> $DIR/diverging_sub_expression.rs:19:10
    |
 LL |     b || diverge();
    |          ^^^^^^^^^
@@ -7,34 +7,42 @@ LL |     b || diverge();
    = note: `-D clippy::diverging-sub-expression` implied by `-D warnings`
 
 error: sub-expression diverges
-  --> $DIR/diverging_sub_expression.rs:21:10
+  --> $DIR/diverging_sub_expression.rs:20:10
    |
 LL |     b || A.foo();
    |          ^^^^^^^
 
 error: sub-expression diverges
-  --> $DIR/diverging_sub_expression.rs:30:26
+  --> $DIR/diverging_sub_expression.rs:29:26
    |
 LL |             6 => true || return,
    |                          ^^^^^^
 
 error: sub-expression diverges
-  --> $DIR/diverging_sub_expression.rs:31:26
+  --> $DIR/diverging_sub_expression.rs:30:26
    |
 LL |             7 => true || continue,
    |                          ^^^^^^^^
 
 error: sub-expression diverges
-  --> $DIR/diverging_sub_expression.rs:34:26
+  --> $DIR/diverging_sub_expression.rs:33:26
    |
 LL |             3 => true || diverge(),
    |                          ^^^^^^^^^
 
 error: sub-expression diverges
-  --> $DIR/diverging_sub_expression.rs:39:26
+  --> $DIR/diverging_sub_expression.rs:36:30
+   |
+LL |                 _ => true || panic!("boo"),
+   |                              ^^^^^^^^^^^^^
+   |
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: sub-expression diverges
+  --> $DIR/diverging_sub_expression.rs:38:26
    |
 LL |             _ => true || break,
    |                          ^^^^^
 
-error: aborting due to 6 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
new file mode 100644 (file)
index 0000000..747801b
--- /dev/null
@@ -0,0 +1,215 @@
+// run-rustfix
+//! This file tests for the `DOC_MARKDOWN` lint.
+
+#![allow(dead_code, incomplete_features)]
+#![warn(clippy::doc_markdown)]
+#![feature(custom_inner_attributes, generic_const_exprs, const_option)]
+#![rustfmt::skip]
+
+/// The `foo_bar` function does _nothing_. See also `foo::bar`. (note the dot there)
+/// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not `Foo::some_fun`
+/// which should be reported only once despite being __doubly bad__.
+/// Here be `::a::global:path`, and _`::another::global::path`_.  :: is not a path though.
+/// Import an item from `::awesome::global::blob::` (Intended postfix)
+/// These are the options for `::Cat`: (Intended trailing single colon, shouldn't be linted)
+/// That's not code ~`NotInCodeBlock`~.
+/// `be_sure_we_got_to_the_end_of_it`
+fn foo_bar() {
+}
+
+/// That one tests multiline ticks.
+/// ```rust
+/// foo_bar FOO_BAR
+/// _foo bar_
+/// ```
+///
+/// ~~~rust
+/// foo_bar FOO_BAR
+/// _foo bar_
+/// ~~~
+/// `be_sure_we_got_to_the_end_of_it`
+fn multiline_codeblock() {
+}
+
+/// This _is a test for
+/// multiline
+/// emphasis_.
+/// `be_sure_we_got_to_the_end_of_it`
+fn test_emphasis() {
+}
+
+/// This tests units. See also #835.
+/// kiB MiB GiB TiB PiB EiB
+/// kib Mib Gib Tib Pib Eib
+/// kB MB GB TB PB EB
+/// kb Mb Gb Tb Pb Eb
+/// 32kiB 32MiB 32GiB 32TiB 32PiB 32EiB
+/// 32kib 32Mib 32Gib 32Tib 32Pib 32Eib
+/// 32kB 32MB 32GB 32TB 32PB 32EB
+/// 32kb 32Mb 32Gb 32Tb 32Pb 32Eb
+/// NaN
+/// `be_sure_we_got_to_the_end_of_it`
+fn test_units() {
+}
+
+/// This tests allowed identifiers.
+/// KiB MiB GiB TiB PiB EiB
+/// DirectX
+/// ECMAScript
+/// GPLv2 GPLv3
+/// GitHub GitLab
+/// IPv4 IPv6
+/// ClojureScript CoffeeScript JavaScript PureScript TypeScript
+/// NaN NaNs
+/// OAuth GraphQL
+/// OCaml
+/// OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenDNS
+/// WebGL
+/// TensorFlow
+/// TrueType
+/// iOS macOS FreeBSD
+/// TeX LaTeX BibTeX BibLaTeX
+/// MinGW
+/// CamelCase (see also #2395)
+/// `be_sure_we_got_to_the_end_of_it`
+fn test_allowed() {
+}
+
+/// This test has [a `link_with_underscores`][chunked-example] inside it. See #823.
+/// See also [the issue tracker](https://github.com/rust-lang/rust-clippy/search?q=clippy::doc_markdown&type=Issues)
+/// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link].
+/// It can also be [`inline_link2`].
+///
+/// [chunked-example]: https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example
+/// [inline_link]: https://foobar
+/// [inline_link2]: https://foobar
+/// The `main` function is the entry point of the program. Here it only calls the `foo_bar` and
+/// `multiline_ticks` functions.
+///
+/// expression of the type  `_ <bit_op> m <cmp_op> c` (where `<bit_op>`
+/// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>` ,
+/// `be_sure_we_got_to_the_end_of_it`
+fn main() {
+    foo_bar();
+    multiline_codeblock();
+    test_emphasis();
+    test_units();
+}
+
+/// ## `CamelCaseThing`
+/// Talks about `CamelCaseThing`. Titles should be ignored; see issue #897.
+///
+/// # `CamelCaseThing`
+///
+/// Not a title #897 `CamelCaseThing`
+/// `be_sure_we_got_to_the_end_of_it`
+fn issue897() {
+}
+
+/// I am confused by brackets? (`x_y`)
+/// I am confused by brackets? (foo `x_y`)
+/// I am confused by brackets? (`x_y` foo)
+/// `be_sure_we_got_to_the_end_of_it`
+fn issue900() {
+}
+
+/// Diesel queries also have a similar problem to [Iterator][iterator], where
+/// /// More talking
+/// returning them from a function requires exposing the implementation of that
+/// function. The [`helper_types`][helper_types] module exists to help with this,
+/// but you might want to hide the return type or have it conditionally change.
+/// Boxing can achieve both.
+///
+/// [iterator]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html
+/// [helper_types]: ../helper_types/index.html
+/// `be_sure_we_got_to_the_end_of_it`
+fn issue883() {
+}
+
+/// `foo_bar
+/// baz_quz`
+/// [foo
+/// bar](https://doc.rust-lang.org/stable/std/iter/trait.IteratorFooBar.html)
+fn multiline() {
+}
+
+/** E.g., serialization of an empty list: `FooBar`
+```
+That's in a code block: `PackedNode`
+```
+
+And `BarQuz` too.
+`be_sure_we_got_to_the_end_of_it`
+*/
+fn issue1073() {
+}
+
+/** E.g., serialization of an empty list: `FooBar`
+```
+That's in a code block: PackedNode
+```
+
+And `BarQuz` too.
+`be_sure_we_got_to_the_end_of_it`
+*/
+fn issue1073_alt() {
+}
+
+/// Tests more than three quotes:
+/// ````
+/// DoNotWarn
+/// ```
+/// StillDont
+/// ````
+/// `be_sure_we_got_to_the_end_of_it`
+fn four_quotes() {
+}
+
+#[cfg_attr(feature = "a", doc = " ```")]
+#[cfg_attr(not(feature = "a"), doc = " ```ignore")]
+/// fn main() {
+///     let s = "localhost:10000".to_string();
+///     println!("{}", s);
+/// }
+/// ```
+fn issue_1469() {}
+
+/**
+ * This is a doc comment that should not be a list
+ *This would also be an error under a strict common mark interpretation
+ */
+fn issue_1920() {}
+
+/// An iterator over `mycrate::Collection`'s values.
+/// It should not lint a `'static` lifetime in ticks.
+fn issue_2210() {}
+
+/// This should not cause the lint to trigger:
+/// #REQ-data-family.lint_partof_exists
+fn issue_2343() {}
+
+/// This should not cause an ICE:
+/// __|_ _|__||_|
+fn pulldown_cmark_crash() {}
+
+/// This should not lint
+/// (regression test for #7758)
+/// [plain text][path::to::item]
+fn intra_doc_link() {}
+
+// issue #7033 - generic_const_exprs ICE
+struct S<T, const N: usize>
+where [(); N.checked_next_power_of_two().unwrap()]: {
+    arr: [T; N.checked_next_power_of_two().unwrap()],
+    n: usize,
+}
+
+impl<T: Copy + Default, const N: usize> S<T, N>
+where [(); N.checked_next_power_of_two().unwrap()]: {
+    fn new() -> Self {
+        Self {
+            arr: [T::default(); N.checked_next_power_of_two().unwrap()],
+            n: 0,
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.rs b/src/tools/clippy/tests/ui/doc/doc-fixable.rs
new file mode 100644 (file)
index 0000000..f3cf966
--- /dev/null
@@ -0,0 +1,215 @@
+// run-rustfix
+//! This file tests for the `DOC_MARKDOWN` lint.
+
+#![allow(dead_code, incomplete_features)]
+#![warn(clippy::doc_markdown)]
+#![feature(custom_inner_attributes, generic_const_exprs, const_option)]
+#![rustfmt::skip]
+
+/// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
+/// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not Foo::some_fun
+/// which should be reported only once despite being __doubly bad__.
+/// Here be ::a::global:path, and _::another::global::path_.  :: is not a path though.
+/// Import an item from ::awesome::global::blob:: (Intended postfix)
+/// These are the options for ::Cat: (Intended trailing single colon, shouldn't be linted)
+/// That's not code ~NotInCodeBlock~.
+/// be_sure_we_got_to_the_end_of_it
+fn foo_bar() {
+}
+
+/// That one tests multiline ticks.
+/// ```rust
+/// foo_bar FOO_BAR
+/// _foo bar_
+/// ```
+///
+/// ~~~rust
+/// foo_bar FOO_BAR
+/// _foo bar_
+/// ~~~
+/// be_sure_we_got_to_the_end_of_it
+fn multiline_codeblock() {
+}
+
+/// This _is a test for
+/// multiline
+/// emphasis_.
+/// be_sure_we_got_to_the_end_of_it
+fn test_emphasis() {
+}
+
+/// This tests units. See also #835.
+/// kiB MiB GiB TiB PiB EiB
+/// kib Mib Gib Tib Pib Eib
+/// kB MB GB TB PB EB
+/// kb Mb Gb Tb Pb Eb
+/// 32kiB 32MiB 32GiB 32TiB 32PiB 32EiB
+/// 32kib 32Mib 32Gib 32Tib 32Pib 32Eib
+/// 32kB 32MB 32GB 32TB 32PB 32EB
+/// 32kb 32Mb 32Gb 32Tb 32Pb 32Eb
+/// NaN
+/// be_sure_we_got_to_the_end_of_it
+fn test_units() {
+}
+
+/// This tests allowed identifiers.
+/// KiB MiB GiB TiB PiB EiB
+/// DirectX
+/// ECMAScript
+/// GPLv2 GPLv3
+/// GitHub GitLab
+/// IPv4 IPv6
+/// ClojureScript CoffeeScript JavaScript PureScript TypeScript
+/// NaN NaNs
+/// OAuth GraphQL
+/// OCaml
+/// OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenDNS
+/// WebGL
+/// TensorFlow
+/// TrueType
+/// iOS macOS FreeBSD
+/// TeX LaTeX BibTeX BibLaTeX
+/// MinGW
+/// CamelCase (see also #2395)
+/// be_sure_we_got_to_the_end_of_it
+fn test_allowed() {
+}
+
+/// This test has [a link_with_underscores][chunked-example] inside it. See #823.
+/// See also [the issue tracker](https://github.com/rust-lang/rust-clippy/search?q=clippy::doc_markdown&type=Issues)
+/// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link].
+/// It can also be [inline_link2].
+///
+/// [chunked-example]: https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example
+/// [inline_link]: https://foobar
+/// [inline_link2]: https://foobar
+/// The `main` function is the entry point of the program. Here it only calls the `foo_bar` and
+/// `multiline_ticks` functions.
+///
+/// expression of the type  `_ <bit_op> m <cmp_op> c` (where `<bit_op>`
+/// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>` ,
+/// be_sure_we_got_to_the_end_of_it
+fn main() {
+    foo_bar();
+    multiline_codeblock();
+    test_emphasis();
+    test_units();
+}
+
+/// ## CamelCaseThing
+/// Talks about `CamelCaseThing`. Titles should be ignored; see issue #897.
+///
+/// # CamelCaseThing
+///
+/// Not a title #897 CamelCaseThing
+/// be_sure_we_got_to_the_end_of_it
+fn issue897() {
+}
+
+/// I am confused by brackets? (`x_y`)
+/// I am confused by brackets? (foo `x_y`)
+/// I am confused by brackets? (`x_y` foo)
+/// be_sure_we_got_to_the_end_of_it
+fn issue900() {
+}
+
+/// Diesel queries also have a similar problem to [Iterator][iterator], where
+/// /// More talking
+/// returning them from a function requires exposing the implementation of that
+/// function. The [`helper_types`][helper_types] module exists to help with this,
+/// but you might want to hide the return type or have it conditionally change.
+/// Boxing can achieve both.
+///
+/// [iterator]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html
+/// [helper_types]: ../helper_types/index.html
+/// be_sure_we_got_to_the_end_of_it
+fn issue883() {
+}
+
+/// `foo_bar
+/// baz_quz`
+/// [foo
+/// bar](https://doc.rust-lang.org/stable/std/iter/trait.IteratorFooBar.html)
+fn multiline() {
+}
+
+/** E.g., serialization of an empty list: FooBar
+```
+That's in a code block: `PackedNode`
+```
+
+And BarQuz too.
+be_sure_we_got_to_the_end_of_it
+*/
+fn issue1073() {
+}
+
+/** E.g., serialization of an empty list: FooBar
+```
+That's in a code block: PackedNode
+```
+
+And BarQuz too.
+be_sure_we_got_to_the_end_of_it
+*/
+fn issue1073_alt() {
+}
+
+/// Tests more than three quotes:
+/// ````
+/// DoNotWarn
+/// ```
+/// StillDont
+/// ````
+/// be_sure_we_got_to_the_end_of_it
+fn four_quotes() {
+}
+
+#[cfg_attr(feature = "a", doc = " ```")]
+#[cfg_attr(not(feature = "a"), doc = " ```ignore")]
+/// fn main() {
+///     let s = "localhost:10000".to_string();
+///     println!("{}", s);
+/// }
+/// ```
+fn issue_1469() {}
+
+/**
+ * This is a doc comment that should not be a list
+ *This would also be an error under a strict common mark interpretation
+ */
+fn issue_1920() {}
+
+/// An iterator over mycrate::Collection's values.
+/// It should not lint a `'static` lifetime in ticks.
+fn issue_2210() {}
+
+/// This should not cause the lint to trigger:
+/// #REQ-data-family.lint_partof_exists
+fn issue_2343() {}
+
+/// This should not cause an ICE:
+/// __|_ _|__||_|
+fn pulldown_cmark_crash() {}
+
+/// This should not lint
+/// (regression test for #7758)
+/// [plain text][path::to::item]
+fn intra_doc_link() {}
+
+// issue #7033 - generic_const_exprs ICE
+struct S<T, const N: usize>
+where [(); N.checked_next_power_of_two().unwrap()]: {
+    arr: [T; N.checked_next_power_of_two().unwrap()],
+    n: usize,
+}
+
+impl<T: Copy + Default, const N: usize> S<T, N>
+where [(); N.checked_next_power_of_two().unwrap()]: {
+    fn new() -> Self {
+        Self {
+            arr: [T::default(); N.checked_next_power_of_two().unwrap()],
+            n: 0,
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.stderr b/src/tools/clippy/tests/ui/doc/doc-fixable.stderr
new file mode 100644 (file)
index 0000000..31132f8
--- /dev/null
@@ -0,0 +1,184 @@
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:9:9
+   |
+LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
+   |         ^^^^^^^ help: try: ``foo_bar``
+   |
+   = note: `-D clippy::doc-markdown` implied by `-D warnings`
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:9:51
+   |
+LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
+   |                                                   ^^^^^^^^ help: try: ``foo::bar``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:10:83
+   |
+LL | /// Markdown is _weird_. I mean _really weird_. This /_ is ok. So is `_`. But not Foo::some_fun
+   |                                                                                   ^^^^^^^^^^^^^ help: try: ``Foo::some_fun``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:12:13
+   |
+LL | /// Here be ::a::global:path, and _::another::global::path_.  :: is not a path though.
+   |             ^^^^^^^^^^^^^^^^ help: try: ``::a::global:path``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:12:36
+   |
+LL | /// Here be ::a::global:path, and _::another::global::path_.  :: is not a path though.
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``::another::global::path``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:13:25
+   |
+LL | /// Import an item from ::awesome::global::blob:: (Intended postfix)
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``::awesome::global::blob::``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:14:31
+   |
+LL | /// These are the options for ::Cat: (Intended trailing single colon, shouldn't be linted)
+   |                               ^^^^^ help: try: ``::Cat``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:15:22
+   |
+LL | /// That's not code ~NotInCodeBlock~.
+   |                      ^^^^^^^^^^^^^^ help: try: ``NotInCodeBlock``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:16:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:30:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:37:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:51:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:74:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:78:22
+   |
+LL | /// This test has [a link_with_underscores][chunked-example] inside it. See #823.
+   |                      ^^^^^^^^^^^^^^^^^^^^^ help: try: ``link_with_underscores``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:81:21
+   |
+LL | /// It can also be [inline_link2].
+   |                     ^^^^^^^^^^^^ help: try: ``inline_link2``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:91:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:99:8
+   |
+LL | /// ## CamelCaseThing
+   |        ^^^^^^^^^^^^^^ help: try: ``CamelCaseThing``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:102:7
+   |
+LL | /// # CamelCaseThing
+   |       ^^^^^^^^^^^^^^ help: try: ``CamelCaseThing``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:104:22
+   |
+LL | /// Not a title #897 CamelCaseThing
+   |                      ^^^^^^^^^^^^^^ help: try: ``CamelCaseThing``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:105:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:112:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:125:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:136:43
+   |
+LL | /** E.g., serialization of an empty list: FooBar
+   |                                           ^^^^^^ help: try: ``FooBar``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:141:5
+   |
+LL | And BarQuz too.
+   |     ^^^^^^ help: try: ``BarQuz``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:142:1
+   |
+LL | be_sure_we_got_to_the_end_of_it
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:147:43
+   |
+LL | /** E.g., serialization of an empty list: FooBar
+   |                                           ^^^^^^ help: try: ``FooBar``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:152:5
+   |
+LL | And BarQuz too.
+   |     ^^^^^^ help: try: ``BarQuz``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:153:1
+   |
+LL | be_sure_we_got_to_the_end_of_it
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:164:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:183:22
+   |
+LL | /// An iterator over mycrate::Collection's values.
+   |                      ^^^^^^^^^^^^^^^^^^^ help: try: ``mycrate::Collection``
+
+error: aborting due to 30 previous errors
+
diff --git a/src/tools/clippy/tests/ui/doc/doc.rs b/src/tools/clippy/tests/ui/doc/doc.rs
deleted file mode 100644 (file)
index 342208e..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-//! This file tests for the `DOC_MARKDOWN` lint.
-
-#![allow(dead_code, incomplete_features)]
-#![warn(clippy::doc_markdown)]
-#![feature(custom_inner_attributes, generic_const_exprs, const_option)]
-#![rustfmt::skip]
-
-/// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
-/// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not Foo::some_fun
-/// which should be reported only once despite being __doubly bad__.
-/// Here be ::a::global:path.
-/// That's not code ~NotInCodeBlock~.
-/// be_sure_we_got_to_the_end_of_it
-fn foo_bar() {
-}
-
-/// That one tests multiline ticks.
-/// ```rust
-/// foo_bar FOO_BAR
-/// _foo bar_
-/// ```
-///
-/// ~~~rust
-/// foo_bar FOO_BAR
-/// _foo bar_
-/// ~~~
-/// be_sure_we_got_to_the_end_of_it
-fn multiline_codeblock() {
-}
-
-/// This _is a test for
-/// multiline
-/// emphasis_.
-/// be_sure_we_got_to_the_end_of_it
-fn test_emphasis() {
-}
-
-/// This tests units. See also #835.
-/// kiB MiB GiB TiB PiB EiB
-/// kib Mib Gib Tib Pib Eib
-/// kB MB GB TB PB EB
-/// kb Mb Gb Tb Pb Eb
-/// 32kiB 32MiB 32GiB 32TiB 32PiB 32EiB
-/// 32kib 32Mib 32Gib 32Tib 32Pib 32Eib
-/// 32kB 32MB 32GB 32TB 32PB 32EB
-/// 32kb 32Mb 32Gb 32Tb 32Pb 32Eb
-/// NaN
-/// be_sure_we_got_to_the_end_of_it
-fn test_units() {
-}
-
-/// This tests allowed identifiers.
-/// KiB MiB GiB TiB PiB EiB
-/// DirectX
-/// ECMAScript
-/// GPLv2 GPLv3
-/// GitHub GitLab
-/// IPv4 IPv6
-/// ClojureScript CoffeeScript JavaScript PureScript TypeScript
-/// NaN NaNs
-/// OAuth GraphQL
-/// OCaml
-/// OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenDNS
-/// WebGL
-/// TensorFlow
-/// TrueType
-/// iOS macOS FreeBSD
-/// TeX LaTeX BibTeX BibLaTeX
-/// MinGW
-/// CamelCase (see also #2395)
-/// be_sure_we_got_to_the_end_of_it
-fn test_allowed() {
-}
-
-/// This test has [a link_with_underscores][chunked-example] inside it. See #823.
-/// See also [the issue tracker](https://github.com/rust-lang/rust-clippy/search?q=clippy::doc_markdown&type=Issues)
-/// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link].
-/// It can also be [inline_link2].
-///
-/// [chunked-example]: https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example
-/// [inline_link]: https://foobar
-/// [inline_link2]: https://foobar
-/// The `main` function is the entry point of the program. Here it only calls the `foo_bar` and
-/// `multiline_ticks` functions.
-///
-/// expression of the type  `_ <bit_op> m <cmp_op> c` (where `<bit_op>`
-/// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>` ,
-/// be_sure_we_got_to_the_end_of_it
-fn main() {
-    foo_bar();
-    multiline_codeblock();
-    test_emphasis();
-    test_units();
-}
-
-/// ## CamelCaseThing
-/// Talks about `CamelCaseThing`. Titles should be ignored; see issue #897.
-///
-/// # CamelCaseThing
-///
-/// Not a title #897 CamelCaseThing
-/// be_sure_we_got_to_the_end_of_it
-fn issue897() {
-}
-
-/// I am confused by brackets? (`x_y`)
-/// I am confused by brackets? (foo `x_y`)
-/// I am confused by brackets? (`x_y` foo)
-/// be_sure_we_got_to_the_end_of_it
-fn issue900() {
-}
-
-/// Diesel queries also have a similar problem to [Iterator][iterator], where
-/// /// More talking
-/// returning them from a function requires exposing the implementation of that
-/// function. The [`helper_types`][helper_types] module exists to help with this,
-/// but you might want to hide the return type or have it conditionally change.
-/// Boxing can achieve both.
-///
-/// [iterator]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html
-/// [helper_types]: ../helper_types/index.html
-/// be_sure_we_got_to_the_end_of_it
-fn issue883() {
-}
-
-/// `foo_bar
-/// baz_quz`
-/// [foo
-/// bar](https://doc.rust-lang.org/stable/std/iter/trait.IteratorFooBar.html)
-fn multiline() {
-}
-
-/** E.g., serialization of an empty list: FooBar
-```
-That's in a code block: `PackedNode`
-```
-
-And BarQuz too.
-be_sure_we_got_to_the_end_of_it
-*/
-fn issue1073() {
-}
-
-/** E.g., serialization of an empty list: FooBar
-```
-That's in a code block: PackedNode
-```
-
-And BarQuz too.
-be_sure_we_got_to_the_end_of_it
-*/
-fn issue1073_alt() {
-}
-
-/// Tests more than three quotes:
-/// ````
-/// DoNotWarn
-/// ```
-/// StillDont
-/// ````
-/// be_sure_we_got_to_the_end_of_it
-fn four_quotes() {
-}
-
-/// See [NIST SP 800-56A, revision 2].
-///
-/// [NIST SP 800-56A, revision 2]:
-///     https://github.com/rust-lang/rust-clippy/issues/902#issuecomment-261919419
-fn issue_902_comment() {}
-
-#[cfg_attr(feature = "a", doc = " ```")]
-#[cfg_attr(not(feature = "a"), doc = " ```ignore")]
-/// fn main() {
-///     let s = "localhost:10000".to_string();
-///     println!("{}", s);
-/// }
-/// ```
-fn issue_1469() {}
-
-/**
- * This is a doc comment that should not be a list
- *This would also be an error under a strict common mark interpretation
- */
-fn issue_1920() {}
-
-/// Ok: <http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels>
-///
-/// Not ok: http://www.unicode.org
-/// Not ok: https://www.unicode.org
-/// Not ok: http://www.unicode.org/
-/// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels
-fn issue_1832() {}
-
-/// An iterator over mycrate::Collection's values.
-/// It should not lint a `'static` lifetime in ticks.
-fn issue_2210() {}
-
-/// This should not cause the lint to trigger:
-/// #REQ-data-family.lint_partof_exists
-fn issue_2343() {}
-
-/// This should not cause an ICE:
-/// __|_ _|__||_|
-fn pulldown_cmark_crash() {}
-
-/// This should not lint
-/// (regression test for #7758)
-/// [plain text][path::to::item]
-fn intra_doc_link() {}
-
-// issue #7033 - generic_const_exprs ICE
-struct S<T, const N: usize>
-where [(); N.checked_next_power_of_two().unwrap()]: {
-    arr: [T; N.checked_next_power_of_two().unwrap()],
-    n: usize,
-}
-
-impl<T: Copy + Default, const N: usize> S<T, N>
-where [(); N.checked_next_power_of_two().unwrap()]: {
-    fn new() -> Self {
-        Self {
-            arr: [T::default(); N.checked_next_power_of_two().unwrap()],
-            n: 0,
-        }
-    }
-}
diff --git a/src/tools/clippy/tests/ui/doc/doc.stderr b/src/tools/clippy/tests/ui/doc/doc.stderr
deleted file mode 100644 (file)
index 7eab8a8..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-error: you should put `foo_bar` between ticks in the documentation
-  --> $DIR/doc.rs:8:9
-   |
-LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
-   |         ^^^^^^^
-   |
-   = note: `-D clippy::doc-markdown` implied by `-D warnings`
-
-error: you should put `foo::bar` between ticks in the documentation
-  --> $DIR/doc.rs:8:51
-   |
-LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
-   |                                                   ^^^^^^^^
-
-error: you should put `Foo::some_fun` between ticks in the documentation
-  --> $DIR/doc.rs:9:83
-   |
-LL | /// Markdown is _weird_. I mean _really weird_. This /_ is ok. So is `_`. But not Foo::some_fun
-   |                                                                                   ^^^^^^^^^^^^^
-
-error: you should put `a::global:path` between ticks in the documentation
-  --> $DIR/doc.rs:11:15
-   |
-LL | /// Here be ::a::global:path.
-   |               ^^^^^^^^^^^^^^
-
-error: you should put `NotInCodeBlock` between ticks in the documentation
-  --> $DIR/doc.rs:12:22
-   |
-LL | /// That's not code ~NotInCodeBlock~.
-   |                      ^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:13:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:27:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:34:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:48:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:71:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `link_with_underscores` between ticks in the documentation
-  --> $DIR/doc.rs:75:22
-   |
-LL | /// This test has [a link_with_underscores][chunked-example] inside it. See #823.
-   |                      ^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `inline_link2` between ticks in the documentation
-  --> $DIR/doc.rs:78:21
-   |
-LL | /// It can also be [inline_link2].
-   |                     ^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:88:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `CamelCaseThing` between ticks in the documentation
-  --> $DIR/doc.rs:96:8
-   |
-LL | /// ## CamelCaseThing
-   |        ^^^^^^^^^^^^^^
-
-error: you should put `CamelCaseThing` between ticks in the documentation
-  --> $DIR/doc.rs:99:7
-   |
-LL | /// # CamelCaseThing
-   |       ^^^^^^^^^^^^^^
-
-error: you should put `CamelCaseThing` between ticks in the documentation
-  --> $DIR/doc.rs:101:22
-   |
-LL | /// Not a title #897 CamelCaseThing
-   |                      ^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:102:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:109:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:122:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `FooBar` between ticks in the documentation
-  --> $DIR/doc.rs:133:43
-   |
-LL | /** E.g., serialization of an empty list: FooBar
-   |                                           ^^^^^^
-
-error: you should put `BarQuz` between ticks in the documentation
-  --> $DIR/doc.rs:138:5
-   |
-LL | And BarQuz too.
-   |     ^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:139:1
-   |
-LL | be_sure_we_got_to_the_end_of_it
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `FooBar` between ticks in the documentation
-  --> $DIR/doc.rs:144:43
-   |
-LL | /** E.g., serialization of an empty list: FooBar
-   |                                           ^^^^^^
-
-error: you should put `BarQuz` between ticks in the documentation
-  --> $DIR/doc.rs:149:5
-   |
-LL | And BarQuz too.
-   |     ^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:150:1
-   |
-LL | be_sure_we_got_to_the_end_of_it
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:161:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put bare URLs between `<`/`>` or make a proper Markdown link
-  --> $DIR/doc.rs:188:13
-   |
-LL | /// Not ok: http://www.unicode.org
-   |             ^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put bare URLs between `<`/`>` or make a proper Markdown link
-  --> $DIR/doc.rs:189:13
-   |
-LL | /// Not ok: https://www.unicode.org
-   |             ^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put bare URLs between `<`/`>` or make a proper Markdown link
-  --> $DIR/doc.rs:190:13
-   |
-LL | /// Not ok: http://www.unicode.org/
-   |             ^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put bare URLs between `<`/`>` or make a proper Markdown link
-  --> $DIR/doc.rs:191:13
-   |
-LL | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `mycrate::Collection` between ticks in the documentation
-  --> $DIR/doc.rs:194:22
-   |
-LL | /// An iterator over mycrate::Collection's values.
-   |                      ^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 31 previous errors
-
diff --git a/src/tools/clippy/tests/ui/doc/issue_1832.rs b/src/tools/clippy/tests/ui/doc/issue_1832.rs
new file mode 100644 (file)
index 0000000..10586f1
--- /dev/null
@@ -0,0 +1,9 @@
+/// Ok: <http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels>
+///
+/// Not ok: http://www.unicode.org
+/// Not ok: https://www.unicode.org
+/// Not ok: http://www.unicode.org/
+/// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels
+fn issue_1832() {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/doc/issue_902.rs b/src/tools/clippy/tests/ui/doc/issue_902.rs
new file mode 100644 (file)
index 0000000..4b0c835
--- /dev/null
@@ -0,0 +1,7 @@
+/// See [NIST SP 800-56A, revision 2].
+///
+/// [NIST SP 800-56A, revision 2]:
+///     https://github.com/rust-lang/rust-clippy/issues/902#issuecomment-261919419
+fn issue_902_comment() {}
+
+fn main() {}
index 45ca34e2a8c8b34a2e6ede2509ad9367abac2709..9670e5c24fb3ecbcf5a9febdca1e2a93ddf61c07 100644 (file)
@@ -18,11 +18,11 @@ LL | /// This paragraph has `unbalanced_tick marks and should stop_linting.
    |
    = help: a backtick may be missing a pair
 
-error: you should put `should_be` between ticks in the documentation
+error: item in documentation is missing backticks
   --> $DIR/unbalanced_ticks.rs:15:32
    |
 LL | /// This paragraph is fine and should_be linted normally.
-   |                                ^^^^^^^^^
+   |                                ^^^^^^^^^ help: try: ``should_be``
 
 error: backticks are unbalanced
   --> $DIR/unbalanced_ticks.rs:17:1
@@ -32,11 +32,11 @@ LL | /// Double unbalanced backtick from ``here to here` should lint.
    |
    = help: a backtick may be missing a pair
 
-error: you should put `not_fine` between ticks in the documentation
+error: item in documentation is missing backticks
   --> $DIR/unbalanced_ticks.rs:30:8
    |
 LL | /// ## not_fine
-   |        ^^^^^^^^
+   |        ^^^^^^^^ help: try: ``not_fine``
 
 error: backticks are unbalanced
   --> $DIR/unbalanced_ticks.rs:32:1
@@ -54,11 +54,11 @@ LL | /// - This `item has unbalanced tick marks
    |
    = help: a backtick may be missing a pair
 
-error: you should put `backticks_here` between ticks in the documentation
+error: item in documentation is missing backticks
   --> $DIR/unbalanced_ticks.rs:35:23
    |
 LL | /// - This item needs backticks_here
-   |                       ^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^ help: try: ``backticks_here``
 
 error: aborting due to 8 previous errors
 
index c77a74a58f22c6072dcfb295ea22794afbe1309c..30fdd3b087371226352c9b07dd81f60119f744b3 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::missing_errors_doc)]
 #![allow(clippy::result_unit_err)]
 #![allow(clippy::unnecessary_wraps)]
index b5a81419daee35d295197158c9e20d5a17f21871..c7b616e2897087c01ee59976e37fe287afb6dbbc 100644 (file)
@@ -1,5 +1,5 @@
 error: docs for function returning `Result` missing `# Errors` section
-  --> $DIR/doc_errors.rs:8:1
+  --> $DIR/doc_errors.rs:7: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:12:1
+  --> $DIR/doc_errors.rs:11: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:17:1
+  --> $DIR/doc_errors.rs:16: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:22:1
+  --> $DIR/doc_errors.rs:21: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:52:5
+  --> $DIR/doc_errors.rs:51: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:57:5
+  --> $DIR/doc_errors.rs:56: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:86:5
+  --> $DIR/doc_errors.rs:85:5
    |
 LL |     fn trait_method_missing_errors_header() -> Result<(), ()>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 03bb30f9083ac4f3c21ab23a635747ef8ba128fd..4464a21b3b654bdf89b238a5c0594b61edbf06ce 100644 (file)
@@ -125,3 +125,8 @@ impl T {
         pub unsafe fn f() {}
     }
 }
+
+/// # Implementation safety
+pub unsafe trait DocumentedUnsafeTraitWithImplementationHeader {
+    fn method();
+}
index d47dfcb5ba1eab1b8654a2c270700748923a4bee..38a8fbd74dcf61b540b16b34a496b9005d5ba800 100644 (file)
@@ -1,4 +1,5 @@
 #[warn(clippy::double_neg)]
+#[allow(clippy::no_effect)]
 fn main() {
     let x = 1;
     -x;
index d82ed05f0543dbf65a7fb5768c39ac7703561081..7cdb040b6873937266598277e48d240d796c95ca 100644 (file)
@@ -1,5 +1,5 @@
 error: `--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op
-  --> $DIR/double_neg.rs:6:5
+  --> $DIR/double_neg.rs:7:5
    |
 LL |     --x;
    |     ^^^
index 447fbb9e1bff3440c35200354408ccdeb9fe60b1..add8a91e26b85a2b9745a73053ff73d418a54cdd 100644 (file)
@@ -60,7 +60,7 @@ LL | | }
    |
    = help: remove the prefixes and use full paths to the variants instead of glob imports
 
-error: all variants have the same prefix: `With`
+error: all variants have the same prefix: `WithOut`
   --> $DIR/enum_variants.rs:81:1
    |
 LL | / enum Seallll {
index 8e6a32b7be33d2eccde04199653c2d467942f3c0..aad78319d48209549db51ff8e3de027a5b4a8b59 100644 (file)
@@ -1,5 +1,3 @@
-// edition:2018
-
 #[warn(clippy::eval_order_dependence)]
 #[allow(
     unused_assignments,
index 4f611e308e18619e50f0b408ed7c07f60c28b47d..7c6265a08790deee6d8df446b49846dab095e770 100644 (file)
@@ -1,48 +1,48 @@
 error: unsequenced read of `x`
-  --> $DIR/eval_order_dependence.rs:16:9
+  --> $DIR/eval_order_dependence.rs:14:9
    |
 LL |     } + x;
    |         ^
    |
    = note: `-D clippy::eval-order-dependence` implied by `-D warnings`
 note: whether read occurs before this write depends on evaluation order
-  --> $DIR/eval_order_dependence.rs:14:9
+  --> $DIR/eval_order_dependence.rs:12:9
    |
 LL |         x = 1;
    |         ^^^^^
 
 error: unsequenced read of `x`
-  --> $DIR/eval_order_dependence.rs:19:5
+  --> $DIR/eval_order_dependence.rs:17:5
    |
 LL |     x += {
    |     ^
    |
 note: whether read occurs before this write depends on evaluation order
-  --> $DIR/eval_order_dependence.rs:20:9
+  --> $DIR/eval_order_dependence.rs:18:9
    |
 LL |         x = 20;
    |         ^^^^^^
 
 error: unsequenced read of `x`
-  --> $DIR/eval_order_dependence.rs:32:12
+  --> $DIR/eval_order_dependence.rs:30:12
    |
 LL |         a: x,
    |            ^
    |
 note: whether read occurs before this write depends on evaluation order
-  --> $DIR/eval_order_dependence.rs:34:13
+  --> $DIR/eval_order_dependence.rs:32:13
    |
 LL |             x = 6;
    |             ^^^^^
 
 error: unsequenced read of `x`
-  --> $DIR/eval_order_dependence.rs:41:9
+  --> $DIR/eval_order_dependence.rs:39:9
    |
 LL |         x += {
    |         ^
    |
 note: whether read occurs before this write depends on evaluation order
-  --> $DIR/eval_order_dependence.rs:42:13
+  --> $DIR/eval_order_dependence.rs:40:13
    |
 LL |             x = 20;
    |             ^^^^^^
index 495cd97e05e15d472bef961da5a2e9eab1573814..5d5af4e4632970afe821f9b42b82eae5bd445e08 100644 (file)
@@ -1,5 +1,4 @@
 #![deny(clippy::fallible_impl_from)]
-#![allow(clippy::if_then_panic)]
 
 // docs example
 struct Foo(i32);
index f5d0b98c10862cd11a4db14d65c484f90c988dd4..4e0f08a1215c0401fa8f18493fb8ad0a833dcd63 100644 (file)
@@ -1,5 +1,5 @@
 error: consider implementing `TryFrom` instead
-  --> $DIR/fallible_impl_from.rs:6:1
+  --> $DIR/fallible_impl_from.rs:5:1
    |
 LL | / impl From<String> for Foo {
 LL | |     fn from(s: String) -> Self {
@@ -15,13 +15,13 @@ LL | #![deny(clippy::fallible_impl_from)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail
 note: potential failure(s)
-  --> $DIR/fallible_impl_from.rs:8:13
+  --> $DIR/fallible_impl_from.rs:7:13
    |
 LL |         Foo(s.parse().unwrap())
    |             ^^^^^^^^^^^^^^^^^^
 
 error: consider implementing `TryFrom` instead
-  --> $DIR/fallible_impl_from.rs:27:1
+  --> $DIR/fallible_impl_from.rs:26:1
    |
 LL | / impl From<usize> for Invalid {
 LL | |     fn from(i: usize) -> Invalid {
@@ -34,14 +34,14 @@ LL | | }
    |
    = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail
 note: potential failure(s)
-  --> $DIR/fallible_impl_from.rs:30:13
+  --> $DIR/fallible_impl_from.rs:29:13
    |
 LL |             panic!();
    |             ^^^^^^^^
-   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: consider implementing `TryFrom` instead
-  --> $DIR/fallible_impl_from.rs:36:1
+  --> $DIR/fallible_impl_from.rs:35:1
    |
 LL | / impl From<Option<String>> for Invalid {
 LL | |     fn from(s: Option<String>) -> Invalid {
@@ -54,7 +54,7 @@ LL | | }
    |
    = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail
 note: potential failure(s)
-  --> $DIR/fallible_impl_from.rs:38:17
+  --> $DIR/fallible_impl_from.rs:37:17
    |
 LL |         let s = s.unwrap();
    |                 ^^^^^^^^^^
@@ -65,10 +65,10 @@ LL |         } else if s.parse::<u32>().unwrap() != 42 {
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |             panic!("{:?}", s);
    |             ^^^^^^^^^^^^^^^^^
-   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: consider implementing `TryFrom` instead
-  --> $DIR/fallible_impl_from.rs:54:1
+  --> $DIR/fallible_impl_from.rs:53:1
    |
 LL | / impl<'a> From<&'a mut <Box<u32> as ProjStrTrait>::ProjString> for Invalid {
 LL | |     fn from(s: &'a mut <Box<u32> as ProjStrTrait>::ProjString) -> Invalid {
@@ -81,13 +81,13 @@ LL | | }
    |
    = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail
 note: potential failure(s)
-  --> $DIR/fallible_impl_from.rs:56:12
+  --> $DIR/fallible_impl_from.rs:55:12
    |
 LL |         if s.parse::<u32>().ok().unwrap() != 42 {
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |             panic!("{:?}", s);
    |             ^^^^^^^^^^^^^^^^^
-   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 4 previous errors
 
index 7d6fd607e6545469dc9fa2e0286eae5417d00628..1442ee08e7546aa20056ccb5b3f27e894b6c4cb8 100644 (file)
@@ -1,4 +1,5 @@
 #![warn(clippy::fn_params_excessive_bools)]
+#![allow(clippy::too_many_arguments)]
 
 extern "C" {
     fn f(_: bool, _: bool, _: bool, _: bool);
index 4e5dbc261d66bababa570af2a3b283536f668e45..cd9d07fa115d6d3bca7d24f8250925cb0a0aa879 100644 (file)
@@ -1,5 +1,5 @@
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:17:1
+  --> $DIR/fn_params_excessive_bools.rs:18:1
    |
 LL | fn g(_: bool, _: bool, _: bool, _: bool) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL | fn g(_: bool, _: bool, _: bool, _: bool) {}
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:20:1
+  --> $DIR/fn_params_excessive_bools.rs:21:1
    |
 LL | fn t(_: S, _: S, _: Box<S>, _: Vec<u32>, _: bool, _: bool, _: bool, _: bool) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL | fn t(_: S, _: S, _: Box<S>, _: Vec<u32>, _: bool, _: bool, _: bool, _: bool
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:24:5
+  --> $DIR/fn_params_excessive_bools.rs:25:5
    |
 LL |     fn f(_: bool, _: bool, _: bool, _: bool);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,7 +24,7 @@ LL |     fn f(_: bool, _: bool, _: bool, _: bool);
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:29:5
+  --> $DIR/fn_params_excessive_bools.rs:30:5
    |
 LL |     fn f(&self, _: bool, _: bool, _: bool, _: bool) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -32,7 +32,7 @@ LL |     fn f(&self, _: bool, _: bool, _: bool, _: bool) {}
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:41:5
+  --> $DIR/fn_params_excessive_bools.rs:42:5
    |
 LL | /     fn n(_: bool, _: u32, _: bool, _: Box<u32>, _: bool, _: bool) {
 LL | |         fn nn(_: bool, _: bool, _: bool, _: bool) {}
@@ -42,7 +42,7 @@ LL | |     }
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:42:9
+  --> $DIR/fn_params_excessive_bools.rs:43:9
    |
 LL |         fn nn(_: bool, _: bool, _: bool, _: bool) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 73fc750511c78684cdd8650d03e6ce1dc40582b1..64cb7b1cfb80f6c33ff5e81f7af29cceb1e8b73d 100644 (file)
@@ -16,6 +16,8 @@ fn main() {
     r##"foo {}
 " bar"##.to_string();
 
+    let _ = String::new();
+
     "foo".to_string();
     format!("{:?}", "foo"); // Don't warn about `Debug`.
     format!("{:8}", "foo");
index 2f4595650cbf3c8d3cdd716e3ea32a0e24113b58..a065b1b5683c1b9ccbfeb81df5cf1b96d7d12c4d 100644 (file)
@@ -18,6 +18,8 @@ fn main() {
 " bar"##
     );
 
+    let _ = format!("");
+
     format!("{}", "foo");
     format!("{:?}", "foo"); // Don't warn about `Debug`.
     format!("{:8}", "foo");
index 701399b32d62834a9d993339b83df1f5ba8d03ab..58ad7499bb26f530c5202239ac79858ab1aaa79c 100644 (file)
@@ -34,64 +34,70 @@ LL ~ " bar"##.to_string();
    |
 
 error: useless use of `format!`
-  --> $DIR/format.rs:21:5
+  --> $DIR/format.rs:21:13
+   |
+LL |     let _ = format!("");
+   |             ^^^^^^^^^^^ help: consider using `String::new()`: `String::new()`
+
+error: useless use of `format!`
+  --> $DIR/format.rs:23:5
    |
 LL |     format!("{}", "foo");
    |     ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:25:5
+  --> $DIR/format.rs:27:5
    |
 LL |     format!("{:+}", "foo"); // Warn when the format makes no difference.
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:26:5
+  --> $DIR/format.rs:28:5
    |
 LL |     format!("{:<}", "foo"); // Warn when the format makes no difference.
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:31:5
+  --> $DIR/format.rs:33:5
    |
 LL |     format!("{}", arg);
    |     ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:35:5
+  --> $DIR/format.rs:37:5
    |
 LL |     format!("{:+}", arg); // Warn when the format makes no difference.
    |     ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:36:5
+  --> $DIR/format.rs:38:5
    |
 LL |     format!("{:<}", arg); // Warn when the format makes no difference.
    |     ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:63:5
+  --> $DIR/format.rs:65:5
    |
 LL |     format!("{}", 42.to_string());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `42.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:65:5
+  --> $DIR/format.rs:67:5
    |
 LL |     format!("{}", x.display().to_string());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.display().to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:69:18
+  --> $DIR/format.rs:71:18
    |
 LL |     let _ = Some(format!("{}", a + "bar"));
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `a + "bar"`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:73:22
+  --> $DIR/format.rs:75:22
    |
 LL |     let _s: String = format!("{}", &*v.join("/n"));
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `(&*v.join("/n")).to_string()`
 
-error: aborting due to 14 previous errors
+error: aborting due to 15 previous errors
 
index 8376566c4d62d57fcfa1c51198500c4ac517e904..69b5e1c722e0320df446f0fb6a01d74d20fead7f 100644 (file)
@@ -5,6 +5,7 @@
 #![allow(unused_variables)]
 #![allow(clippy::assertions_on_constants)]
 #![allow(clippy::eq_op)]
+#![allow(clippy::print_literal)]
 #![warn(clippy::to_string_in_format_args)]
 
 use std::io::{stdout, Write};
@@ -97,9 +98,20 @@ fn main() {
     println!("{}", Z(1));
     println!("{}", **x);
     println!("{}", ***x_ref);
+    // https://github.com/rust-lang/rust-clippy/issues/7903
+    println!("{foo}{bar}", foo = "foo", bar = "bar");
+    println!("{foo}{bar}", foo = "foo", bar = "bar");
+    println!("{foo}{bar}", bar = "bar", foo = "foo");
+    println!("{foo}{bar}", bar = "bar", foo = "foo");
 
+    // negative tests
     println!("error: something failed at {}", Somewhere.to_string());
+    // The next two tests are negative because caching the string might be faster than calling `<X as
+    // Display>::fmt` twice.
     println!("{} and again {0}", x.to_string());
+    println!("{foo}{foo}", foo = "foo".to_string());
     my_macro!();
     println!("error: something failed at {}", my_other_macro!());
+    // https://github.com/rust-lang/rust-clippy/issues/7903
+    println!("{foo}{foo:?}", foo = "foo".to_string());
 }
index 164cc07066dc3b892022b616b34f4130083c12ce..3a434c5bf002a3350a08a0da2988747de925bcc9 100644 (file)
@@ -5,6 +5,7 @@
 #![allow(unused_variables)]
 #![allow(clippy::assertions_on_constants)]
 #![allow(clippy::eq_op)]
+#![allow(clippy::print_literal)]
 #![warn(clippy::to_string_in_format_args)]
 
 use std::io::{stdout, Write};
@@ -97,9 +98,20 @@ fn main() {
     println!("{}", Z(1).to_string());
     println!("{}", x.to_string());
     println!("{}", x_ref.to_string());
+    // https://github.com/rust-lang/rust-clippy/issues/7903
+    println!("{foo}{bar}", foo = "foo".to_string(), bar = "bar");
+    println!("{foo}{bar}", foo = "foo", bar = "bar".to_string());
+    println!("{foo}{bar}", bar = "bar".to_string(), foo = "foo");
+    println!("{foo}{bar}", bar = "bar", foo = "foo".to_string());
 
+    // negative tests
     println!("error: something failed at {}", Somewhere.to_string());
+    // The next two tests are negative because caching the string might be faster than calling `<X as
+    // Display>::fmt` twice.
     println!("{} and again {0}", x.to_string());
+    println!("{foo}{foo}", foo = "foo".to_string());
     my_macro!();
     println!("error: something failed at {}", my_other_macro!());
+    // https://github.com/rust-lang/rust-clippy/issues/7903
+    println!("{foo}{foo:?}", foo = "foo".to_string());
 }
index 9cfc97edeafb8215fabae9014bc1b543840a650c..c0cbca507958d1306cfbf008fb3b1d16e2f3959d 100644 (file)
@@ -1,5 +1,5 @@
 error: `to_string` applied to a type that implements `Display` in `format!` args
-  --> $DIR/format_args.rs:75:72
+  --> $DIR/format_args.rs:76:72
    |
 LL |     let _ = format!("error: something failed at {}", Location::caller().to_string());
    |                                                                        ^^^^^^^^^^^^ help: remove this
@@ -7,100 +7,124 @@ LL |     let _ = format!("error: something failed at {}", Location::caller().to_
    = note: `-D clippy::to-string-in-format-args` implied by `-D warnings`
 
 error: `to_string` applied to a type that implements `Display` in `write!` args
-  --> $DIR/format_args.rs:79:27
+  --> $DIR/format_args.rs:80:27
    |
 LL |         Location::caller().to_string()
    |                           ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `writeln!` args
-  --> $DIR/format_args.rs:84:27
+  --> $DIR/format_args.rs:85:27
    |
 LL |         Location::caller().to_string()
    |                           ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `print!` args
-  --> $DIR/format_args.rs:86:63
+  --> $DIR/format_args.rs:87:63
    |
 LL |     print!("error: something failed at {}", Location::caller().to_string());
    |                                                               ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `println!` args
-  --> $DIR/format_args.rs:87:65
+  --> $DIR/format_args.rs:88:65
    |
 LL |     println!("error: something failed at {}", Location::caller().to_string());
    |                                                                 ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `eprint!` args
-  --> $DIR/format_args.rs:88:64
+  --> $DIR/format_args.rs:89:64
    |
 LL |     eprint!("error: something failed at {}", Location::caller().to_string());
    |                                                                ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `eprintln!` args
-  --> $DIR/format_args.rs:89:66
+  --> $DIR/format_args.rs:90:66
    |
 LL |     eprintln!("error: something failed at {}", Location::caller().to_string());
    |                                                                  ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `format_args!` args
-  --> $DIR/format_args.rs:90:77
+  --> $DIR/format_args.rs:91:77
    |
 LL |     let _ = format_args!("error: something failed at {}", Location::caller().to_string());
    |                                                                             ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `assert!` args
-  --> $DIR/format_args.rs:91:70
+  --> $DIR/format_args.rs:92:70
    |
 LL |     assert!(true, "error: something failed at {}", Location::caller().to_string());
    |                                                                      ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `assert_eq!` args
-  --> $DIR/format_args.rs:92:73
+  --> $DIR/format_args.rs:93:73
    |
 LL |     assert_eq!(0, 0, "error: something failed at {}", Location::caller().to_string());
    |                                                                         ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `assert_ne!` args
-  --> $DIR/format_args.rs:93:73
+  --> $DIR/format_args.rs:94:73
    |
 LL |     assert_ne!(0, 0, "error: something failed at {}", Location::caller().to_string());
    |                                                                         ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `panic!` args
-  --> $DIR/format_args.rs:94:63
+  --> $DIR/format_args.rs:95:63
    |
 LL |     panic!("error: something failed at {}", Location::caller().to_string());
    |                                                               ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `println!` args
-  --> $DIR/format_args.rs:95:20
+  --> $DIR/format_args.rs:96:20
    |
 LL |     println!("{}", X(1).to_string());
    |                    ^^^^^^^^^^^^^^^^ help: use this: `*X(1)`
 
 error: `to_string` applied to a type that implements `Display` in `println!` args
-  --> $DIR/format_args.rs:96:20
+  --> $DIR/format_args.rs:97:20
    |
 LL |     println!("{}", Y(&X(1)).to_string());
    |                    ^^^^^^^^^^^^^^^^^^^^ help: use this: `***Y(&X(1))`
 
 error: `to_string` applied to a type that implements `Display` in `println!` args
-  --> $DIR/format_args.rs:97:24
+  --> $DIR/format_args.rs:98:24
    |
 LL |     println!("{}", Z(1).to_string());
    |                        ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `println!` args
-  --> $DIR/format_args.rs:98:20
+  --> $DIR/format_args.rs:99:20
    |
 LL |     println!("{}", x.to_string());
    |                    ^^^^^^^^^^^^^ help: use this: `**x`
 
 error: `to_string` applied to a type that implements `Display` in `println!` args
-  --> $DIR/format_args.rs:99:20
+  --> $DIR/format_args.rs:100:20
    |
 LL |     println!("{}", x_ref.to_string());
    |                    ^^^^^^^^^^^^^^^^^ help: use this: `***x_ref`
 
-error: aborting due to 17 previous errors
+error: `to_string` applied to a type that implements `Display` in `println!` args
+  --> $DIR/format_args.rs:102:39
+   |
+LL |     println!("{foo}{bar}", foo = "foo".to_string(), bar = "bar");
+   |                                       ^^^^^^^^^^^^ help: remove this
+
+error: `to_string` applied to a type that implements `Display` in `println!` args
+  --> $DIR/format_args.rs:103:52
+   |
+LL |     println!("{foo}{bar}", foo = "foo", bar = "bar".to_string());
+   |                                                    ^^^^^^^^^^^^ help: remove this
+
+error: `to_string` applied to a type that implements `Display` in `println!` args
+  --> $DIR/format_args.rs:104:39
+   |
+LL |     println!("{foo}{bar}", bar = "bar".to_string(), foo = "foo");
+   |                                       ^^^^^^^^^^^^ help: remove this
+
+error: `to_string` applied to a type that implements `Display` in `println!` args
+  --> $DIR/format_args.rs:105:52
+   |
+LL |     println!("{foo}{bar}", bar = "bar", foo = "foo".to_string());
+   |                                                    ^^^^^^^^^^^^ help: remove this
+
+error: aborting due to 21 previous errors
 
index a8c06c2bde6645e418bd8d3f76599e24be4d9c2e..b24ddf7321e4000cf7fe20cee6ca5485ab6fab0f 100644 (file)
@@ -51,6 +51,7 @@ fn main() {
     assert_ne!(0, 0, "error: {}", format!("something failed at {}", Location::caller()));
     panic!("error: {}", format!("something failed at {}", Location::caller()));
 
+    // negative tests
     println!("error: {}", format_args!("something failed at {}", Location::caller()));
     println!("error: {:>70}", format!("something failed at {}", Location::caller()));
     println!("error: {} {0}", format!("something failed at {}", Location::caller()));
index 0d14807ff1cfcf1f2745b521f0c101c7ca85eddb..471a8e0de6e193047e17ffa3e4273dce9799ac62 100644 (file)
@@ -3,6 +3,7 @@
 #![allow(unused_assignments)]
 #![allow(clippy::if_same_then_else)]
 #![allow(clippy::deref_addrof)]
+#![allow(clippy::nonminimal_bool)]
 
 fn foo() -> bool {
     true
index bde434c7e2e78737ae451a9c8dd776712aba5090..9272cd6048441790c403e0750193c78fa6c56049 100644 (file)
@@ -1,5 +1,5 @@
 error: this looks like you are trying to use `.. -= ..`, but you really are doing `.. = (- ..)`
-  --> $DIR/formatting.rs:15:6
+  --> $DIR/formatting.rs:16:6
    |
 LL |     a =- 35;
    |      ^^^^
@@ -8,7 +8,7 @@ LL |     a =- 35;
    = note: to remove this lint, use either `-=` or `= -`
 
 error: this looks like you are trying to use `.. *= ..`, but you really are doing `.. = (* ..)`
-  --> $DIR/formatting.rs:16:6
+  --> $DIR/formatting.rs:17:6
    |
 LL |     a =* &191;
    |      ^^^^
@@ -16,7 +16,7 @@ LL |     a =* &191;
    = note: to remove this lint, use either `*=` or `= *`
 
 error: this looks like you are trying to use `.. != ..`, but you really are doing `.. = (! ..)`
-  --> $DIR/formatting.rs:19:6
+  --> $DIR/formatting.rs:20:6
    |
 LL |     b =! false;
    |      ^^^^
@@ -24,7 +24,7 @@ LL |     b =! false;
    = note: to remove this lint, use either `!=` or `= !`
 
 error: possibly missing a comma here
-  --> $DIR/formatting.rs:28:19
+  --> $DIR/formatting.rs:29:19
    |
 LL |         -1, -2, -3 // <= no comma here
    |                   ^
@@ -33,7 +33,7 @@ LL |         -1, -2, -3 // <= no comma here
    = note: to remove this lint, add a comma or write the expr in a single line
 
 error: possibly missing a comma here
-  --> $DIR/formatting.rs:32:19
+  --> $DIR/formatting.rs:33:19
    |
 LL |         -1, -2, -3 // <= no comma here
    |                   ^
@@ -41,7 +41,7 @@ LL |         -1, -2, -3 // <= no comma here
    = note: to remove this lint, add a comma or write the expr in a single line
 
 error: possibly missing a comma here
-  --> $DIR/formatting.rs:69:11
+  --> $DIR/formatting.rs:70:11
    |
 LL |         -1
    |           ^
index d3a920de4b6ad8a685f3c04096a3afd414826998..858036692d68f401d36c464754b82662f150c540 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::future_not_send)]
 
 use std::cell::Cell;
index c734051ccf320b086567185414793a707c50a379..3cc05e2fdbec65c0b9574b0c45b924f63bcd6ca5 100644 (file)
@@ -1,12 +1,12 @@
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:8:62
+  --> $DIR/future_not_send.rs:7:62
    |
 LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    |                                                              ^^^^ future returned by `private_future` is not `Send`
    |
    = note: `-D clippy::future-not-send` implied by `-D warnings`
 note: future is not `Send` as this value is used across an await
-  --> $DIR/future_not_send.rs:9:5
+  --> $DIR/future_not_send.rs:8:5
    |
 LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    |                         -- has type `std::rc::Rc<[u8]>` which is not `Send`
@@ -16,7 +16,7 @@ LL | }
    | - `rc` is later dropped here
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
 note: future is not `Send` as this value is used across an await
-  --> $DIR/future_not_send.rs:9:5
+  --> $DIR/future_not_send.rs:8:5
    |
 LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    |                                       ---- has type `&std::cell::Cell<usize>` which is not `Send`
@@ -27,13 +27,13 @@ LL | }
    = note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`
 
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:12:42
+  --> $DIR/future_not_send.rs:11:42
    |
 LL | pub async fn public_future(rc: Rc<[u8]>) {
    |                                          ^ future returned by `public_future` is not `Send`
    |
 note: future is not `Send` as this value is used across an await
-  --> $DIR/future_not_send.rs:13:5
+  --> $DIR/future_not_send.rs:12:5
    |
 LL | pub async fn public_future(rc: Rc<[u8]>) {
    |                            -- has type `std::rc::Rc<[u8]>` which is not `Send`
@@ -44,45 +44,45 @@ LL | }
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
 
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:20:63
+  --> $DIR/future_not_send.rs:19:63
    |
 LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    |                                                               ^^^^ future returned by `private_future2` is not `Send`
    |
 note: captured value is not `Send`
-  --> $DIR/future_not_send.rs:20:26
+  --> $DIR/future_not_send.rs:19:26
    |
 LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    |                          ^^ has type `std::rc::Rc<[u8]>` which is not `Send`
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
 note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
-  --> $DIR/future_not_send.rs:20:40
+  --> $DIR/future_not_send.rs:19:40
    |
 LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    |                                        ^^^^ has type `&std::cell::Cell<usize>` which is not `Send`, because `std::cell::Cell<usize>` is not `Sync`
    = note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`
 
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:24:43
+  --> $DIR/future_not_send.rs:23:43
    |
 LL | pub async fn public_future2(rc: Rc<[u8]>) {}
    |                                           ^ future returned by `public_future2` is not `Send`
    |
 note: captured value is not `Send`
-  --> $DIR/future_not_send.rs:24:29
+  --> $DIR/future_not_send.rs:23:29
    |
 LL | pub async fn public_future2(rc: Rc<[u8]>) {}
    |                             ^^ has type `std::rc::Rc<[u8]>` which is not `Send`
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
 
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:35:39
+  --> $DIR/future_not_send.rs:34:39
    |
 LL |     async fn private_future(&self) -> usize {
    |                                       ^^^^^ future returned by `private_future` is not `Send`
    |
 note: future is not `Send` as this value is used across an await
-  --> $DIR/future_not_send.rs:36:9
+  --> $DIR/future_not_send.rs:35:9
    |
 LL |     async fn private_future(&self) -> usize {
    |                             ----- has type `&Dummy` which is not `Send`
@@ -94,13 +94,13 @@ LL |     }
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`
 
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:40:39
+  --> $DIR/future_not_send.rs:39:39
    |
 LL |     pub async fn public_future(&self) {
    |                                       ^ future returned by `public_future` is not `Send`
    |
 note: future is not `Send` as this value is used across an await
-  --> $DIR/future_not_send.rs:41:9
+  --> $DIR/future_not_send.rs:40:9
    |
 LL |     pub async fn public_future(&self) {
    |                                ----- has type `&Dummy` which is not `Send`
@@ -111,13 +111,13 @@ LL |     }
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`
 
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:50:37
+  --> $DIR/future_not_send.rs:49:37
    |
 LL | async fn generic_future<T>(t: T) -> T
    |                                     ^ future returned by `generic_future` is not `Send`
    |
 note: future is not `Send` as this value is used across an await
-  --> $DIR/future_not_send.rs:55:5
+  --> $DIR/future_not_send.rs:54:5
    |
 LL |     let rt = &t;
    |         -- has type `&T` which is not `Send`
@@ -129,13 +129,13 @@ LL | }
    = note: `T` doesn't implement `std::marker::Sync`
 
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:66:34
+  --> $DIR/future_not_send.rs:65:34
    |
 LL | async fn unclear_future<T>(t: T) {}
    |                                  ^ future returned by `unclear_future` is not `Send`
    |
 note: captured value is not `Send`
-  --> $DIR/future_not_send.rs:66:28
+  --> $DIR/future_not_send.rs:65:28
    |
 LL | async fn unclear_future<T>(t: T) {}
    |                            ^ has type `T` which is not `Send`
index dc3fb1ceac9a44ba1dd69d063040b49f9feff534..b7012b43d29766d154786e866357b15b838d5756 100644 (file)
@@ -1,6 +1,9 @@
 #![warn(clippy::all)]
 #![warn(clippy::if_not_else)]
 
+fn foo() -> bool {
+    unimplemented!()
+}
 fn bla() -> bool {
     unimplemented!()
 }
@@ -16,4 +19,11 @@ fn main() {
     } else {
         println!("Bunny");
     }
+    if !foo() {
+        println!("Foo");
+    } else if !bla() {
+        println!("Bugs");
+    } else {
+        println!("Bunny");
+    }
 }
index 53d1b86d02a962a639631ea29c6415573cb8ee51..8c8cc44bb035882e2484a96a8874351632c6be89 100644 (file)
@@ -1,5 +1,5 @@
 error: unnecessary boolean `not` operation
-  --> $DIR/if_not_else.rs:9:5
+  --> $DIR/if_not_else.rs:12:5
    |
 LL | /     if !bla() {
 LL | |         println!("Bugs");
@@ -12,7 +12,7 @@ LL | |     }
    = help: remove the `!` and swap the blocks of the `if`/`else`
 
 error: unnecessary `!=` operation
-  --> $DIR/if_not_else.rs:14:5
+  --> $DIR/if_not_else.rs:17:5
    |
 LL | /     if 4 != 5 {
 LL | |         println!("Bugs");
diff --git a/src/tools/clippy/tests/ui/if_then_panic.fixed b/src/tools/clippy/tests/ui/if_then_panic.fixed
deleted file mode 100644 (file)
index 0998f8f..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-// run-rustfix
-#![warn(clippy::if_then_panic)]
-
-fn main() {
-    let a = vec![1, 2, 3];
-    let c = Some(2);
-    if !a.is_empty()
-        && a.len() == 3
-        && c != None
-        && !a.is_empty()
-        && a.len() == 3
-        && !a.is_empty()
-        && a.len() == 3
-        && !a.is_empty()
-        && a.len() == 3
-    {
-        panic!("qaqaq{:?}", a);
-    }
-    assert!(a.is_empty(), "qaqaq{:?}", a);
-    assert!(a.is_empty(), "qwqwq");
-    if a.len() == 3 {
-        println!("qwq");
-        println!("qwq");
-        println!("qwq");
-    }
-    if let Some(b) = c {
-        panic!("orz {}", b);
-    }
-    if a.len() == 3 {
-        panic!("qaqaq");
-    } else {
-        println!("qwq");
-    }
-    let b = vec![1, 2, 3];
-    assert!(!b.is_empty(), "panic1");
-    assert!(!(b.is_empty() && a.is_empty()), "panic2");
-    assert!(!(a.is_empty() && !b.is_empty()), "panic3");
-    assert!(!(b.is_empty() || a.is_empty()), "panic4");
-    assert!(!(a.is_empty() || !b.is_empty()), "panic5");
-}
diff --git a/src/tools/clippy/tests/ui/if_then_panic.rs b/src/tools/clippy/tests/ui/if_then_panic.rs
deleted file mode 100644 (file)
index 10433c8..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-// run-rustfix
-#![warn(clippy::if_then_panic)]
-
-fn main() {
-    let a = vec![1, 2, 3];
-    let c = Some(2);
-    if !a.is_empty()
-        && a.len() == 3
-        && c != None
-        && !a.is_empty()
-        && a.len() == 3
-        && !a.is_empty()
-        && a.len() == 3
-        && !a.is_empty()
-        && a.len() == 3
-    {
-        panic!("qaqaq{:?}", a);
-    }
-    if !a.is_empty() {
-        panic!("qaqaq{:?}", a);
-    }
-    if !a.is_empty() {
-        panic!("qwqwq");
-    }
-    if a.len() == 3 {
-        println!("qwq");
-        println!("qwq");
-        println!("qwq");
-    }
-    if let Some(b) = c {
-        panic!("orz {}", b);
-    }
-    if a.len() == 3 {
-        panic!("qaqaq");
-    } else {
-        println!("qwq");
-    }
-    let b = vec![1, 2, 3];
-    if b.is_empty() {
-        panic!("panic1");
-    }
-    if b.is_empty() && a.is_empty() {
-        panic!("panic2");
-    }
-    if a.is_empty() && !b.is_empty() {
-        panic!("panic3");
-    }
-    if b.is_empty() || a.is_empty() {
-        panic!("panic4");
-    }
-    if a.is_empty() || !b.is_empty() {
-        panic!("panic5");
-    }
-}
diff --git a/src/tools/clippy/tests/ui/if_then_panic.stderr b/src/tools/clippy/tests/ui/if_then_panic.stderr
deleted file mode 100644 (file)
index 5bb62f8..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-error: only a `panic!` in `if`-then statement
-  --> $DIR/if_then_panic.rs:19:5
-   |
-LL | /     if !a.is_empty() {
-LL | |         panic!("qaqaq{:?}", a);
-LL | |     }
-   | |_____^ help: try: `assert!(a.is_empty(), "qaqaq{:?}", a);`
-   |
-   = note: `-D clippy::if-then-panic` implied by `-D warnings`
-
-error: only a `panic!` in `if`-then statement
-  --> $DIR/if_then_panic.rs:22:5
-   |
-LL | /     if !a.is_empty() {
-LL | |         panic!("qwqwq");
-LL | |     }
-   | |_____^ help: try: `assert!(a.is_empty(), "qwqwq");`
-
-error: only a `panic!` in `if`-then statement
-  --> $DIR/if_then_panic.rs:39:5
-   |
-LL | /     if b.is_empty() {
-LL | |         panic!("panic1");
-LL | |     }
-   | |_____^ help: try: `assert!(!b.is_empty(), "panic1");`
-
-error: only a `panic!` in `if`-then statement
-  --> $DIR/if_then_panic.rs:42:5
-   |
-LL | /     if b.is_empty() && a.is_empty() {
-LL | |         panic!("panic2");
-LL | |     }
-   | |_____^ help: try: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
-
-error: only a `panic!` in `if`-then statement
-  --> $DIR/if_then_panic.rs:45:5
-   |
-LL | /     if a.is_empty() && !b.is_empty() {
-LL | |         panic!("panic3");
-LL | |     }
-   | |_____^ help: try: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
-
-error: only a `panic!` in `if`-then statement
-  --> $DIR/if_then_panic.rs:48:5
-   |
-LL | /     if b.is_empty() || a.is_empty() {
-LL | |         panic!("panic4");
-LL | |     }
-   | |_____^ help: try: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
-
-error: only a `panic!` in `if`-then statement
-  --> $DIR/if_then_panic.rs:51:5
-   |
-LL | /     if a.is_empty() || !b.is_empty() {
-LL | |         panic!("panic5");
-LL | |     }
-   | |_____^ help: try: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
-
-error: aborting due to 7 previous errors
-
index aa69b0974101c822a06a790c742bed645e46813b..fd96ca3f466eabe7cc9ed034040925a658f274c9 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 // aux-build:implicit_hasher_macros.rs
 #![deny(clippy::implicit_hasher)]
 #![allow(unused)]
index 3f5f56b923fe2453b25e792bc9b5a912f880cd90..59b0fba2a4cfee460b8e2d120a91b01fb1c3d952 100644 (file)
@@ -1,11 +1,11 @@
 error: impl for `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:17:35
+  --> $DIR/implicit_hasher.rs:16:35
    |
 LL | impl<K: Hash + Eq, V> Foo<i8> for HashMap<K, V> {
    |                                   ^^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/implicit_hasher.rs:3:9
+  --> $DIR/implicit_hasher.rs:2:9
    |
 LL | #![deny(clippy::implicit_hasher)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^
@@ -19,7 +19,7 @@ LL |         (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default:
    |          ~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: impl for `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:26:36
+  --> $DIR/implicit_hasher.rs:25:36
    |
 LL | impl<K: Hash + Eq, V> Foo<i8> for (HashMap<K, V>,) {
    |                                    ^^^^^^^^^^^^^
@@ -34,7 +34,7 @@ LL |         ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Defa
    |           ~~~~~~~~~~~~~~~~~~     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: impl for `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:31:19
+  --> $DIR/implicit_hasher.rs:30:19
    |
 LL | impl Foo<i16> for HashMap<String, String> {
    |                   ^^^^^^^^^^^^^^^^^^^^^^^
@@ -49,7 +49,7 @@ LL |         (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default:
    |          ~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: impl for `HashSet` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:48:32
+  --> $DIR/implicit_hasher.rs:47:32
    |
 LL | impl<T: Hash + Eq> Foo<i8> for HashSet<T> {
    |                                ^^^^^^^^^^
@@ -64,7 +64,7 @@ LL |         (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default:
    |          ~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: impl for `HashSet` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:53:19
+  --> $DIR/implicit_hasher.rs:52:19
    |
 LL | impl Foo<i16> for HashSet<String> {
    |                   ^^^^^^^^^^^^^^^
@@ -79,7 +79,7 @@ LL |         (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default:
    |          ~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: parameter of type `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:70:23
+  --> $DIR/implicit_hasher.rs:69:23
    |
 LL | pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
    |                       ^^^^^^^^^^^^^^^^^
@@ -90,7 +90,7 @@ LL | pub fn foo<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32, S>, _s
    |           +++++++++++++++++++++++++++++            ~~~~~~~~~~~~~~~~~~~~
 
 error: parameter of type `HashSet` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:70:53
+  --> $DIR/implicit_hasher.rs:69:53
    |
 LL | pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
    |                                                     ^^^^^^^^^^^^
@@ -101,7 +101,7 @@ LL | pub fn foo<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32>, _set:
    |           +++++++++++++++++++++++++++++                                          ~~~~~~~~~~~~~~~
 
 error: impl for `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:74:43
+  --> $DIR/implicit_hasher.rs:73:43
    |
 LL |         impl<K: Hash + Eq, V> Foo<u8> for HashMap<K, V> {
    |                                           ^^^^^^^^^^^^^
@@ -120,7 +120,7 @@ LL |                 (HashMap::default(), HashMap::with_capacity_and_hasher(10,
    |                  ~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: parameter of type `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:82:33
+  --> $DIR/implicit_hasher.rs:81:33
    |
 LL |         pub fn $name(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
    |                                 ^^^^^^^^^^^^^^^^^
@@ -135,7 +135,7 @@ LL |         pub fn $name<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i
    |                     +++++++++++++++++++++++++++++            ~~~~~~~~~~~~~~~~~~~~
 
 error: parameter of type `HashSet` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:82:63
+  --> $DIR/implicit_hasher.rs:81:63
    |
 LL |         pub fn $name(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
    |                                                               ^^^^^^^^^^^^
@@ -150,7 +150,7 @@ LL |         pub fn $name<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i
    |                     +++++++++++++++++++++++++++++                                          ~~~~~~~~~~~~~~~
 
 error: parameter of type `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:101:35
+  --> $DIR/implicit_hasher.rs:100:35
    |
 LL | pub async fn election_vote(_data: HashMap<i32, i32>) {}
    |                                   ^^^^^^^^^^^^^^^^^
index 7698b88a88c8aa80a143ac27ab11e145a880ef51..a51f7bc6a29ffff52a301b84053f3c8f58bddc53 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 // run-rustfix
 
 #![warn(clippy::implicit_return)]
index 45bbc2ec670e05463d1a0f8d6f8d5fc557561cfe..03f8ec49d51e5457a57e2c9a71e30669fb984b1d 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 // run-rustfix
 
 #![warn(clippy::implicit_return)]
index 5e078b15ce393f6070b3f932ec0553d0c880f91f..522bc3bf895a7a3159dccdb74e56fe032c10c483 100644 (file)
@@ -1,5 +1,5 @@
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:13:5
+  --> $DIR/implicit_return.rs:12:5
    |
 LL |     true
    |     ^^^^ help: add `return` as shown: `return true`
@@ -7,85 +7,85 @@ LL |     true
    = note: `-D clippy::implicit-return` implied by `-D warnings`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:17:15
+  --> $DIR/implicit_return.rs:16:15
    |
 LL |     if true { true } else { false }
    |               ^^^^ help: add `return` as shown: `return true`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:17:29
+  --> $DIR/implicit_return.rs:16:29
    |
 LL |     if true { true } else { false }
    |                             ^^^^^ help: add `return` as shown: `return false`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:23:17
+  --> $DIR/implicit_return.rs:22:17
    |
 LL |         true => false,
    |                 ^^^^^ help: add `return` as shown: `return false`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:24:20
+  --> $DIR/implicit_return.rs:23:20
    |
 LL |         false => { true },
    |                    ^^^^ help: add `return` as shown: `return true`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:37:9
+  --> $DIR/implicit_return.rs:36:9
    |
 LL |         break true;
    |         ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:44:13
+  --> $DIR/implicit_return.rs:43:13
    |
 LL |             break true;
    |             ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:52:13
+  --> $DIR/implicit_return.rs:51:13
    |
 LL |             break true;
    |             ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:70:18
+  --> $DIR/implicit_return.rs:69:18
    |
 LL |     let _ = || { true };
    |                  ^^^^ help: add `return` as shown: `return true`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:71:16
+  --> $DIR/implicit_return.rs:70:16
    |
 LL |     let _ = || true;
    |                ^^^^ help: add `return` as shown: `return true`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:79:5
+  --> $DIR/implicit_return.rs:78:5
    |
 LL |     format!("test {}", "test")
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `return` as shown: `return format!("test {}", "test")`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:88:5
+  --> $DIR/implicit_return.rs:87:5
    |
 LL |     m!(true, false)
    |     ^^^^^^^^^^^^^^^ help: add `return` as shown: `return m!(true, false)`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:94:13
+  --> $DIR/implicit_return.rs:93:13
    |
 LL |             break true;
    |             ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:99:17
+  --> $DIR/implicit_return.rs:98:17
    |
 LL |                 break 'outer false;
    |                 ^^^^^^^^^^^^^^^^^^ help: change `break` to `return` as shown: `return false`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:114:5
+  --> $DIR/implicit_return.rs:113:5
    |
 LL | /     loop {
 LL | |         m!(true);
@@ -100,7 +100,7 @@ LL +     }
    |
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:128:5
+  --> $DIR/implicit_return.rs:127:5
    |
 LL |     true
    |     ^^^^ help: add `return` as shown: `return true`
index d1025743790a9747bfb95c6bb746d0b1e15b917c..eb66d1afddce39dfce67d421a7229232b52b2b6f 100644 (file)
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 #![warn(clippy::inconsistent_struct_constructor)]
 #![allow(clippy::redundant_field_names)]
 #![allow(clippy::unnecessary_operation)]
index b095aa64a2174371e94d9f2c240ed910c9c893ca..5caadc7c62083fb2b214df04ded3b16e2bb665f7 100644 (file)
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 #![warn(clippy::inconsistent_struct_constructor)]
 #![allow(clippy::redundant_field_names)]
 #![allow(clippy::unnecessary_operation)]
index ef308dedb1661c331703d68d9ab973477f473d51..c90189e964f09e68cea01babbb5d25ba03689909 100644 (file)
@@ -1,5 +1,5 @@
 error: struct constructor field order is inconsistent with struct definition field order
-  --> $DIR/inconsistent_struct_constructor.rs:34:9
+  --> $DIR/inconsistent_struct_constructor.rs:33:9
    |
 LL |         Foo { y, x, z };
    |         ^^^^^^^^^^^^^^^ help: try: `Foo { x, y, z }`
@@ -7,7 +7,7 @@ LL |         Foo { y, x, z };
    = note: `-D clippy::inconsistent-struct-constructor` implied by `-D warnings`
 
 error: struct constructor field order is inconsistent with struct definition field order
-  --> $DIR/inconsistent_struct_constructor.rs:56:9
+  --> $DIR/inconsistent_struct_constructor.rs:55:9
    |
 LL | /         Foo {
 LL | |             z,
diff --git a/src/tools/clippy/tests/ui/issue-7447.stderr b/src/tools/clippy/tests/ui/issue-7447.stderr
new file mode 100644 (file)
index 0000000..463a48b
--- /dev/null
@@ -0,0 +1,19 @@
+error: sub-expression diverges
+  --> $DIR/issue-7447.rs:23:15
+   |
+LL |     byte_view(panic!());
+   |               ^^^^^^^^
+   |
+   = note: `-D clippy::diverging-sub-expression` implied by `-D warnings`
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: sub-expression diverges
+  --> $DIR/issue-7447.rs:24:19
+   |
+LL |     group_entries(panic!());
+   |                   ^^^^^^^^
+   |
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
index cc699b79e433ca39756717f16714487a05421da7..d9d48189bd74e741f381f9449783ecefd5cce514 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 #![allow(dead_code)]
 
 async fn sink1<'a>(_: &'a str) {} // lint
index 0426508e622f8fd471a61e0464e1ba53ccf537a3..20419457b47f0ee3018f9ec888939e1d96cfbae4 100644 (file)
@@ -1,5 +1,5 @@
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/issue_4266.rs:4:1
+  --> $DIR/issue_4266.rs:3:1
    |
 LL | async fn sink1<'a>(_: &'a str) {} // lint
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL | async fn sink1<'a>(_: &'a str) {} // lint
    = note: `-D clippy::needless-lifetimes` implied by `-D warnings`
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/issue_4266.rs:8:1
+  --> $DIR/issue_4266.rs:7:1
    |
 LL | async fn one_to_one<'a>(s: &'a str) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 97c5929783d882c51dd754244c8bec46ff292f5d..90a6eef75261f505c6fd517b1280c548581f2d8e 100644 (file)
@@ -33,6 +33,7 @@ impl HasIter {
     }
 }
 
+#[allow(unused_must_use)]
 fn main() {
     let mut vec = vec![0, 1, 2, 3];
     let mut boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]);
@@ -50,7 +51,7 @@ fn main() {
     linked_list.push_back(1);
     binary_heap.push(1);
 
-    let _ = &vec[..].len();
+    &vec[..].len();
     vec.len();
     boxed_slice.len();
     vec_deque.len();
@@ -62,13 +63,13 @@ fn main() {
     binary_heap.len();
 
     vec.len();
-    let _ = &vec[..].len();
+    &vec[..].len();
     vec_deque.len();
     hash_map.len();
     b_tree_map.len();
     linked_list.len();
 
-    let _ = &vec[..].len();
+    &vec[..].len();
     vec.len();
     vec_deque.len();
     hash_set.len();
index 70bb734763f09bef26eb35bc4b45f9c196dce29b..6681a480a28c817472eb5bdb1976bb5a948cd61b 100644 (file)
@@ -33,6 +33,7 @@ fn into_iter(self) -> IteratorFalsePositives {
     }
 }
 
+#[allow(unused_must_use)]
 fn main() {
     let mut vec = vec![0, 1, 2, 3];
     let mut boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]);
@@ -50,7 +51,7 @@ fn main() {
     linked_list.push_back(1);
     binary_heap.push(1);
 
-    let _ = &vec[..].iter().count();
+    &vec[..].iter().count();
     vec.iter().count();
     boxed_slice.iter().count();
     vec_deque.iter().count();
@@ -62,13 +63,13 @@ fn main() {
     binary_heap.iter().count();
 
     vec.iter_mut().count();
-    let _ = &vec[..].iter_mut().count();
+    &vec[..].iter_mut().count();
     vec_deque.iter_mut().count();
     hash_map.iter_mut().count();
     b_tree_map.iter_mut().count();
     linked_list.iter_mut().count();
 
-    let _ = &vec[..].into_iter().count();
+    &vec[..].into_iter().count();
     vec.into_iter().count();
     vec_deque.into_iter().count();
     hash_set.into_iter().count();
index 1d2c22f9dfad5470e0b1d478b439a26587bc7a1b..2e3d7fc35de9c0de17d3f712bbc87a892c90dbad 100644 (file)
 error: called `.iter().count()` on a `slice`
-  --> $DIR/iter_count.rs:53:14
+  --> $DIR/iter_count.rs:54:6
    |
-LL |     let _ = &vec[..].iter().count();
-   |              ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
+LL |     &vec[..].iter().count();
+   |      ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
    |
    = note: `-D clippy::iter-count` implied by `-D warnings`
 
 error: called `.iter().count()` on a `Vec`
-  --> $DIR/iter_count.rs:54:5
+  --> $DIR/iter_count.rs:55:5
    |
 LL |     vec.iter().count();
    |     ^^^^^^^^^^^^^^^^^^ help: try: `vec.len()`
 
 error: called `.iter().count()` on a `slice`
-  --> $DIR/iter_count.rs:55:5
+  --> $DIR/iter_count.rs:56:5
    |
 LL |     boxed_slice.iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice.len()`
 
 error: called `.iter().count()` on a `VecDeque`
-  --> $DIR/iter_count.rs:56:5
+  --> $DIR/iter_count.rs:57:5
    |
 LL |     vec_deque.iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec_deque.len()`
 
 error: called `.iter().count()` on a `HashSet`
-  --> $DIR/iter_count.rs:57:5
+  --> $DIR/iter_count.rs:58:5
    |
 LL |     hash_set.iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_set.len()`
 
 error: called `.iter().count()` on a `HashMap`
-  --> $DIR/iter_count.rs:58:5
+  --> $DIR/iter_count.rs:59:5
    |
 LL |     hash_map.iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.len()`
 
 error: called `.iter().count()` on a `BTreeMap`
-  --> $DIR/iter_count.rs:59:5
+  --> $DIR/iter_count.rs:60:5
    |
 LL |     b_tree_map.iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_map.len()`
 
 error: called `.iter().count()` on a `BTreeSet`
-  --> $DIR/iter_count.rs:60:5
+  --> $DIR/iter_count.rs:61:5
    |
 LL |     b_tree_set.iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_set.len()`
 
 error: called `.iter().count()` on a `LinkedList`
-  --> $DIR/iter_count.rs:61:5
+  --> $DIR/iter_count.rs:62:5
    |
 LL |     linked_list.iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `linked_list.len()`
 
 error: called `.iter().count()` on a `BinaryHeap`
-  --> $DIR/iter_count.rs:62:5
+  --> $DIR/iter_count.rs:63:5
    |
 LL |     binary_heap.iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `binary_heap.len()`
 
 error: called `.iter_mut().count()` on a `Vec`
-  --> $DIR/iter_count.rs:64:5
+  --> $DIR/iter_count.rs:65:5
    |
 LL |     vec.iter_mut().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.len()`
 
 error: called `.iter_mut().count()` on a `slice`
-  --> $DIR/iter_count.rs:65:14
+  --> $DIR/iter_count.rs:66:6
    |
-LL |     let _ = &vec[..].iter_mut().count();
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
+LL |     &vec[..].iter_mut().count();
+   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
 
 error: called `.iter_mut().count()` on a `VecDeque`
-  --> $DIR/iter_count.rs:66:5
+  --> $DIR/iter_count.rs:67:5
    |
 LL |     vec_deque.iter_mut().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec_deque.len()`
 
 error: called `.iter_mut().count()` on a `HashMap`
-  --> $DIR/iter_count.rs:67:5
+  --> $DIR/iter_count.rs:68:5
    |
 LL |     hash_map.iter_mut().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.len()`
 
 error: called `.iter_mut().count()` on a `BTreeMap`
-  --> $DIR/iter_count.rs:68:5
+  --> $DIR/iter_count.rs:69:5
    |
 LL |     b_tree_map.iter_mut().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_map.len()`
 
 error: called `.iter_mut().count()` on a `LinkedList`
-  --> $DIR/iter_count.rs:69:5
+  --> $DIR/iter_count.rs:70:5
    |
 LL |     linked_list.iter_mut().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `linked_list.len()`
 
 error: called `.into_iter().count()` on a `slice`
-  --> $DIR/iter_count.rs:71:14
+  --> $DIR/iter_count.rs:72:6
    |
-LL |     let _ = &vec[..].into_iter().count();
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
+LL |     &vec[..].into_iter().count();
+   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
 
 error: called `.into_iter().count()` on a `Vec`
-  --> $DIR/iter_count.rs:72:5
+  --> $DIR/iter_count.rs:73:5
    |
 LL |     vec.into_iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.len()`
 
 error: called `.into_iter().count()` on a `VecDeque`
-  --> $DIR/iter_count.rs:73:5
+  --> $DIR/iter_count.rs:74:5
    |
 LL |     vec_deque.into_iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec_deque.len()`
 
 error: called `.into_iter().count()` on a `HashSet`
-  --> $DIR/iter_count.rs:74:5
+  --> $DIR/iter_count.rs:75:5
    |
 LL |     hash_set.into_iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_set.len()`
 
 error: called `.into_iter().count()` on a `HashMap`
-  --> $DIR/iter_count.rs:75:5
+  --> $DIR/iter_count.rs:76:5
    |
 LL |     hash_map.into_iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.len()`
 
 error: called `.into_iter().count()` on a `BTreeMap`
-  --> $DIR/iter_count.rs:76:5
+  --> $DIR/iter_count.rs:77:5
    |
 LL |     b_tree_map.into_iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_map.len()`
 
 error: called `.into_iter().count()` on a `BTreeSet`
-  --> $DIR/iter_count.rs:77:5
+  --> $DIR/iter_count.rs:78:5
    |
 LL |     b_tree_set.into_iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_set.len()`
 
 error: called `.into_iter().count()` on a `LinkedList`
-  --> $DIR/iter_count.rs:78:5
+  --> $DIR/iter_count.rs:79:5
    |
 LL |     linked_list.into_iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `linked_list.len()`
 
 error: called `.into_iter().count()` on a `BinaryHeap`
-  --> $DIR/iter_count.rs:79:5
+  --> $DIR/iter_count.rs:80:5
    |
 LL |     binary_heap.into_iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `binary_heap.len()`
index b9d66347c27487b9857e99e2be575796273ac6b7..1e938e72b57775356d326a9f0bac9dcae6b57525 100644 (file)
@@ -1,5 +1,3 @@
-// edition:2018
-
 #![warn(clippy::len_without_is_empty)]
 #![allow(dead_code, unused)]
 
index 3282709bcd6717f664ef135c6132b38e9ab3a389..a1f48f7610b44857edf7f6f8f9e6dbbc520c1a0d 100644 (file)
@@ -1,5 +1,5 @@
 error: struct `PubOne` has a public `len` method, but no `is_empty` method
-  --> $DIR/len_without_is_empty.rs:9:5
+  --> $DIR/len_without_is_empty.rs:7:5
    |
 LL |     pub fn len(&self) -> isize {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     pub fn len(&self) -> isize {
    = note: `-D clippy::len-without-is-empty` implied by `-D warnings`
 
 error: trait `PubTraitsToo` has a `len` method but no (possibly inherited) `is_empty` method
-  --> $DIR/len_without_is_empty.rs:57:1
+  --> $DIR/len_without_is_empty.rs:55:1
    |
 LL | / pub trait PubTraitsToo {
 LL | |     fn len(&self) -> isize;
@@ -15,45 +15,45 @@ LL | | }
    | |_^
 
 error: struct `HasIsEmpty` has a public `len` method, but a private `is_empty` method
-  --> $DIR/len_without_is_empty.rs:70:5
+  --> $DIR/len_without_is_empty.rs:68:5
    |
 LL |     pub fn len(&self) -> isize {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `is_empty` defined here
-  --> $DIR/len_without_is_empty.rs:74:5
+  --> $DIR/len_without_is_empty.rs:72:5
    |
 LL |     fn is_empty(&self) -> bool {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: struct `HasWrongIsEmpty` has a public `len` method, but the `is_empty` method has an unexpected signature
-  --> $DIR/len_without_is_empty.rs:82:5
+  --> $DIR/len_without_is_empty.rs:80:5
    |
 LL |     pub fn len(&self) -> isize {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `is_empty` defined here
-  --> $DIR/len_without_is_empty.rs:86:5
+  --> $DIR/len_without_is_empty.rs:84:5
    |
 LL |     pub fn is_empty(&self, x: u32) -> bool {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: expected signature: `(&self) -> bool`
 
 error: struct `MismatchedSelf` has a public `len` method, but the `is_empty` method has an unexpected signature
-  --> $DIR/len_without_is_empty.rs:94:5
+  --> $DIR/len_without_is_empty.rs:92:5
    |
 LL |     pub fn len(self) -> isize {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `is_empty` defined here
-  --> $DIR/len_without_is_empty.rs:98:5
+  --> $DIR/len_without_is_empty.rs:96:5
    |
 LL |     pub fn is_empty(&self) -> bool {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: expected signature: `(self) -> bool`
 
 error: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_empty` method
-  --> $DIR/len_without_is_empty.rs:173:1
+  --> $DIR/len_without_is_empty.rs:171:1
    |
 LL | / pub trait DependsOnFoo: Foo {
 LL | |     fn len(&mut self) -> usize;
@@ -61,33 +61,33 @@ LL | | }
    | |_^
 
 error: struct `OptionalLen3` has a public `len` method, but the `is_empty` method has an unexpected signature
-  --> $DIR/len_without_is_empty.rs:218:5
+  --> $DIR/len_without_is_empty.rs:216:5
    |
 LL |     pub fn len(&self) -> usize {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `is_empty` defined here
-  --> $DIR/len_without_is_empty.rs:223:5
+  --> $DIR/len_without_is_empty.rs:221:5
    |
 LL |     pub fn is_empty(&self) -> Option<bool> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: expected signature: `(&self) -> bool`
 
 error: struct `ResultLen` has a public `len` method, but the `is_empty` method has an unexpected signature
-  --> $DIR/len_without_is_empty.rs:230:5
+  --> $DIR/len_without_is_empty.rs:228:5
    |
 LL |     pub fn len(&self) -> Result<usize, ()> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `is_empty` defined here
-  --> $DIR/len_without_is_empty.rs:235:5
+  --> $DIR/len_without_is_empty.rs:233:5
    |
 LL |     pub fn is_empty(&self) -> Option<bool> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: expected signature: `(&self) -> bool` or `(&self) -> Result<bool>
 
 error: this returns a `Result<_, ()>`
-  --> $DIR/len_without_is_empty.rs:230:5
+  --> $DIR/len_without_is_empty.rs:228:5
    |
 LL |     pub fn len(&self) -> Result<usize, ()> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -96,7 +96,7 @@ LL |     pub fn len(&self) -> Result<usize, ()> {
    = help: use a custom `Error` type instead
 
 error: this returns a `Result<_, ()>`
-  --> $DIR/len_without_is_empty.rs:242:5
+  --> $DIR/len_without_is_empty.rs:240:5
    |
 LL |     pub fn len(&self) -> Result<usize, ()> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -104,7 +104,7 @@ LL |     pub fn len(&self) -> Result<usize, ()> {
    = help: use a custom `Error` type instead
 
 error: this returns a `Result<_, ()>`
-  --> $DIR/len_without_is_empty.rs:246:5
+  --> $DIR/len_without_is_empty.rs:244:5
    |
 LL |     pub fn is_empty(&self) -> Result<bool, ()> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -112,7 +112,7 @@ LL |     pub fn is_empty(&self) -> Result<bool, ()> {
    = help: use a custom `Error` type instead
 
 error: this returns a `Result<_, ()>`
-  --> $DIR/len_without_is_empty.rs:253:5
+  --> $DIR/len_without_is_empty.rs:251:5
    |
 LL |     pub fn len(&self) -> Result<usize, ()> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index a72a74b9131d8bb21fb3b2431fd344c2d069706c..0cadd5a3da1983e4436d9f946808a84aa45a55b7 100644 (file)
@@ -2,8 +2,9 @@
 
 #![warn(clippy::mixed_case_hex_literals)]
 #![warn(clippy::zero_prefixed_literal)]
-#![allow(clippy::unseparated_literal_suffix)]
-#![allow(dead_code)]
+#![warn(clippy::unseparated_literal_suffix)]
+#![warn(clippy::separated_literal_suffix)]
+#![allow(dead_code, overflowing_literals)]
 
 fn main() {
     let ok1 = 0xABCD;
index 99542e20f785fea9f916c59976b20850fcd8edc7..365b240747352d76bc06b3e802e04f0049dabec6 100644 (file)
@@ -1,25 +1,65 @@
+error: integer type suffix should not be separated by an underscore
+  --> $DIR/literals.rs:12:15
+   |
+LL |     let ok4 = 0xab_cd_i32;
+   |               ^^^^^^^^^^^ help: remove the underscore: `0xab_cdi32`
+   |
+   = note: `-D clippy::separated-literal-suffix` implied by `-D warnings`
+
+error: integer type suffix should not be separated by an underscore
+  --> $DIR/literals.rs:13:15
+   |
+LL |     let ok5 = 0xAB_CD_u32;
+   |               ^^^^^^^^^^^ help: remove the underscore: `0xAB_CDu32`
+
+error: integer type suffix should not be separated by an underscore
+  --> $DIR/literals.rs:14:15
+   |
+LL |     let ok5 = 0xAB_CD_isize;
+   |               ^^^^^^^^^^^^^ help: remove the underscore: `0xAB_CDisize`
+
 error: inconsistent casing in hexadecimal literal
-  --> $DIR/literals.rs:14:17
+  --> $DIR/literals.rs:15:17
    |
 LL |     let fail1 = 0xabCD;
    |                 ^^^^^^
    |
    = note: `-D clippy::mixed-case-hex-literals` implied by `-D warnings`
 
+error: integer type suffix should not be separated by an underscore
+  --> $DIR/literals.rs:16:17
+   |
+LL |     let fail2 = 0xabCD_u32;
+   |                 ^^^^^^^^^^ help: remove the underscore: `0xabCDu32`
+
 error: inconsistent casing in hexadecimal literal
-  --> $DIR/literals.rs:15:17
+  --> $DIR/literals.rs:16:17
    |
 LL |     let fail2 = 0xabCD_u32;
    |                 ^^^^^^^^^^
 
+error: integer type suffix should not be separated by an underscore
+  --> $DIR/literals.rs:17:17
+   |
+LL |     let fail2 = 0xabCD_isize;
+   |                 ^^^^^^^^^^^^ help: remove the underscore: `0xabCDisize`
+
 error: inconsistent casing in hexadecimal literal
-  --> $DIR/literals.rs:16:17
+  --> $DIR/literals.rs:17:17
    |
 LL |     let fail2 = 0xabCD_isize;
    |                 ^^^^^^^^^^^^
 
+error: integer type suffix should be separated by an underscore
+  --> $DIR/literals.rs:18:27
+   |
+LL |     let fail_multi_zero = 000_123usize;
+   |                           ^^^^^^^^^^^^ help: add an underscore: `000_123_usize`
+   |
+   = note: `-D clippy::unseparated-literal-suffix` implied by `-D warnings`
+
 error: this is a decimal constant
-  --> $DIR/literals.rs:17:27
+  --> $DIR/literals.rs:18:27
    |
 LL |     let fail_multi_zero = 000_123usize;
    |                           ^^^^^^^^^^^^
@@ -34,8 +74,14 @@ help: if you mean to use an octal constant, use `0o`
 LL |     let fail_multi_zero = 0o123usize;
    |                           ~~~~~~~~~~
 
+error: integer type suffix should not be separated by an underscore
+  --> $DIR/literals.rs:21:16
+   |
+LL |     let ok10 = 0_i64;
+   |                ^^^^^ help: remove the underscore: `0i64`
+
 error: this is a decimal constant
-  --> $DIR/literals.rs:21:17
+  --> $DIR/literals.rs:22:17
    |
 LL |     let fail8 = 0123;
    |                 ^^^^
@@ -49,8 +95,14 @@ help: if you mean to use an octal constant, use `0o`
 LL |     let fail8 = 0o123;
    |                 ~~~~~
 
+error: integer type suffix should not be separated by an underscore
+  --> $DIR/literals.rs:31:16
+   |
+LL |     let ok17 = 0x123_4567_8901_usize;
+   |                ^^^^^^^^^^^^^^^^^^^^^ help: remove the underscore: `0x123_4567_8901usize`
+
 error: digits grouped inconsistently by underscores
-  --> $DIR/literals.rs:33:18
+  --> $DIR/literals.rs:34:18
    |
 LL |     let fail19 = 12_3456_21;
    |                  ^^^^^^^^^^ help: consider: `12_345_621`
@@ -58,19 +110,19 @@ LL |     let fail19 = 12_3456_21;
    = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings`
 
 error: digits grouped inconsistently by underscores
-  --> $DIR/literals.rs:34:18
+  --> $DIR/literals.rs:35:18
    |
 LL |     let fail22 = 3__4___23;
    |                  ^^^^^^^^^ help: consider: `3_423`
 
 error: digits grouped inconsistently by underscores
-  --> $DIR/literals.rs:35:18
+  --> $DIR/literals.rs:36:18
    |
 LL |     let fail23 = 3__16___23;
    |                  ^^^^^^^^^^ help: consider: `31_623`
 
 error: digits of hex or binary literal not grouped by four
-  --> $DIR/literals.rs:37:18
+  --> $DIR/literals.rs:38:18
    |
 LL |     let fail24 = 0xAB_ABC_AB;
    |                  ^^^^^^^^^^^ help: consider: `0x0ABA_BCAB`
@@ -78,10 +130,10 @@ LL |     let fail24 = 0xAB_ABC_AB;
    = note: `-D clippy::unusual-byte-groupings` implied by `-D warnings`
 
 error: digits of hex or binary literal not grouped by four
-  --> $DIR/literals.rs:38:18
+  --> $DIR/literals.rs:39:18
    |
 LL |     let fail25 = 0b01_100_101;
    |                  ^^^^^^^^^^^^ help: consider: `0b0110_0101`
 
-error: aborting due to 10 previous errors
+error: aborting due to 18 previous errors
 
index 70d49d9f2c4ae1edd8497e9133f3598369431148..9171558f3a2d74d1f79d2c9b62d6a3282db33b82 100644 (file)
@@ -1,4 +1,3 @@
-// compile-flags: --edition 2018
 // aux-build:macro_rules.rs
 // aux-build:macro_use_helper.rs
 // aux-build:proc_macro_derive.rs
index 68370023861145dc15a29d4a6696138e06910d05..cd01fd43f6d325eefb79e07d1bc71753ef1a164c 100644 (file)
@@ -1,4 +1,3 @@
-// compile-flags: --edition 2018
 // aux-build:macro_rules.rs
 // aux-build:macro_use_helper.rs
 // aux-build:proc_macro_derive.rs
index 49314b7506d336187642b16deee4aad13d34f342..f8c86c8d9179f8af918b684eb9294c18ea4a7008 100644 (file)
@@ -1,5 +1,5 @@
 error: `macro_use` attributes are no longer needed in the Rust 2018 edition
-  --> $DIR/macro_use_imports.rs:19:5
+  --> $DIR/macro_use_imports.rs:18:5
    |
 LL |     #[macro_use]
    |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro};`
@@ -7,22 +7,22 @@ LL |     #[macro_use]
    = note: `-D clippy::macro-use-imports` implied by `-D warnings`
 
 error: `macro_use` attributes are no longer needed in the Rust 2018 edition
-  --> $DIR/macro_use_imports.rs:25:5
+  --> $DIR/macro_use_imports.rs:20:5
    |
 LL |     #[macro_use]
-   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;`
+   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;`
 
 error: `macro_use` attributes are no longer needed in the Rust 2018 edition
-  --> $DIR/macro_use_imports.rs:21:5
+  --> $DIR/macro_use_imports.rs:22:5
    |
 LL |     #[macro_use]
-   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;`
+   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};`
 
 error: `macro_use` attributes are no longer needed in the Rust 2018 edition
-  --> $DIR/macro_use_imports.rs:23:5
+  --> $DIR/macro_use_imports.rs:24:5
    |
 LL |     #[macro_use]
-   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};`
+   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed b/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
new file mode 100644 (file)
index 0000000..11fe06c
--- /dev/null
@@ -0,0 +1,43 @@
+// revisions: edition2018 edition2021
+// [edition2018] edition:2018
+// [edition2021] edition:2021
+// run-rustfix
+#![warn(clippy::manual_assert)]
+
+fn main() {
+    let a = vec![1, 2, 3];
+    let c = Some(2);
+    if !a.is_empty()
+        && a.len() == 3
+        && c != None
+        && !a.is_empty()
+        && a.len() == 3
+        && !a.is_empty()
+        && a.len() == 3
+        && !a.is_empty()
+        && a.len() == 3
+    {
+        panic!("qaqaq{:?}", a);
+    }
+    assert!(a.is_empty(), "qaqaq{:?}", a);
+    assert!(a.is_empty(), "qwqwq");
+    if a.len() == 3 {
+        println!("qwq");
+        println!("qwq");
+        println!("qwq");
+    }
+    if let Some(b) = c {
+        panic!("orz {}", b);
+    }
+    if a.len() == 3 {
+        panic!("qaqaq");
+    } else {
+        println!("qwq");
+    }
+    let b = vec![1, 2, 3];
+    assert!(!b.is_empty(), "panic1");
+    assert!(!(b.is_empty() && a.is_empty()), "panic2");
+    assert!(!(a.is_empty() && !b.is_empty()), "panic3");
+    assert!(!(b.is_empty() || a.is_empty()), "panic4");
+    assert!(!(a.is_empty() || !b.is_empty()), "panic5");
+}
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr b/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr
new file mode 100644 (file)
index 0000000..03c0347
--- /dev/null
@@ -0,0 +1,60 @@
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:22:5
+   |
+LL | /     if !a.is_empty() {
+LL | |         panic!("qaqaq{:?}", a);
+LL | |     }
+   | |_____^ help: try: `assert!(a.is_empty(), "qaqaq{:?}", a);`
+   |
+   = note: `-D clippy::manual-assert` implied by `-D warnings`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:25:5
+   |
+LL | /     if !a.is_empty() {
+LL | |         panic!("qwqwq");
+LL | |     }
+   | |_____^ help: try: `assert!(a.is_empty(), "qwqwq");`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:42:5
+   |
+LL | /     if b.is_empty() {
+LL | |         panic!("panic1");
+LL | |     }
+   | |_____^ help: try: `assert!(!b.is_empty(), "panic1");`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:45:5
+   |
+LL | /     if b.is_empty() && a.is_empty() {
+LL | |         panic!("panic2");
+LL | |     }
+   | |_____^ help: try: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:48:5
+   |
+LL | /     if a.is_empty() && !b.is_empty() {
+LL | |         panic!("panic3");
+LL | |     }
+   | |_____^ help: try: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:51:5
+   |
+LL | /     if b.is_empty() || a.is_empty() {
+LL | |         panic!("panic4");
+LL | |     }
+   | |_____^ help: try: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:54:5
+   |
+LL | /     if a.is_empty() || !b.is_empty() {
+LL | |         panic!("panic5");
+LL | |     }
+   | |_____^ help: try: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
+
+error: aborting due to 7 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed b/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed
new file mode 100644 (file)
index 0000000..11fe06c
--- /dev/null
@@ -0,0 +1,43 @@
+// revisions: edition2018 edition2021
+// [edition2018] edition:2018
+// [edition2021] edition:2021
+// run-rustfix
+#![warn(clippy::manual_assert)]
+
+fn main() {
+    let a = vec![1, 2, 3];
+    let c = Some(2);
+    if !a.is_empty()
+        && a.len() == 3
+        && c != None
+        && !a.is_empty()
+        && a.len() == 3
+        && !a.is_empty()
+        && a.len() == 3
+        && !a.is_empty()
+        && a.len() == 3
+    {
+        panic!("qaqaq{:?}", a);
+    }
+    assert!(a.is_empty(), "qaqaq{:?}", a);
+    assert!(a.is_empty(), "qwqwq");
+    if a.len() == 3 {
+        println!("qwq");
+        println!("qwq");
+        println!("qwq");
+    }
+    if let Some(b) = c {
+        panic!("orz {}", b);
+    }
+    if a.len() == 3 {
+        panic!("qaqaq");
+    } else {
+        println!("qwq");
+    }
+    let b = vec![1, 2, 3];
+    assert!(!b.is_empty(), "panic1");
+    assert!(!(b.is_empty() && a.is_empty()), "panic2");
+    assert!(!(a.is_empty() && !b.is_empty()), "panic3");
+    assert!(!(b.is_empty() || a.is_empty()), "panic4");
+    assert!(!(a.is_empty() || !b.is_empty()), "panic5");
+}
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr b/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr
new file mode 100644 (file)
index 0000000..03c0347
--- /dev/null
@@ -0,0 +1,60 @@
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:22:5
+   |
+LL | /     if !a.is_empty() {
+LL | |         panic!("qaqaq{:?}", a);
+LL | |     }
+   | |_____^ help: try: `assert!(a.is_empty(), "qaqaq{:?}", a);`
+   |
+   = note: `-D clippy::manual-assert` implied by `-D warnings`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:25:5
+   |
+LL | /     if !a.is_empty() {
+LL | |         panic!("qwqwq");
+LL | |     }
+   | |_____^ help: try: `assert!(a.is_empty(), "qwqwq");`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:42:5
+   |
+LL | /     if b.is_empty() {
+LL | |         panic!("panic1");
+LL | |     }
+   | |_____^ help: try: `assert!(!b.is_empty(), "panic1");`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:45:5
+   |
+LL | /     if b.is_empty() && a.is_empty() {
+LL | |         panic!("panic2");
+LL | |     }
+   | |_____^ help: try: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:48:5
+   |
+LL | /     if a.is_empty() && !b.is_empty() {
+LL | |         panic!("panic3");
+LL | |     }
+   | |_____^ help: try: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:51:5
+   |
+LL | /     if b.is_empty() || a.is_empty() {
+LL | |         panic!("panic4");
+LL | |     }
+   | |_____^ help: try: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:54:5
+   |
+LL | /     if a.is_empty() || !b.is_empty() {
+LL | |         panic!("panic5");
+LL | |     }
+   | |_____^ help: try: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
+
+error: aborting due to 7 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_assert.fixed b/src/tools/clippy/tests/ui/manual_assert.fixed
new file mode 100644 (file)
index 0000000..11fe06c
--- /dev/null
@@ -0,0 +1,43 @@
+// revisions: edition2018 edition2021
+// [edition2018] edition:2018
+// [edition2021] edition:2021
+// run-rustfix
+#![warn(clippy::manual_assert)]
+
+fn main() {
+    let a = vec![1, 2, 3];
+    let c = Some(2);
+    if !a.is_empty()
+        && a.len() == 3
+        && c != None
+        && !a.is_empty()
+        && a.len() == 3
+        && !a.is_empty()
+        && a.len() == 3
+        && !a.is_empty()
+        && a.len() == 3
+    {
+        panic!("qaqaq{:?}", a);
+    }
+    assert!(a.is_empty(), "qaqaq{:?}", a);
+    assert!(a.is_empty(), "qwqwq");
+    if a.len() == 3 {
+        println!("qwq");
+        println!("qwq");
+        println!("qwq");
+    }
+    if let Some(b) = c {
+        panic!("orz {}", b);
+    }
+    if a.len() == 3 {
+        panic!("qaqaq");
+    } else {
+        println!("qwq");
+    }
+    let b = vec![1, 2, 3];
+    assert!(!b.is_empty(), "panic1");
+    assert!(!(b.is_empty() && a.is_empty()), "panic2");
+    assert!(!(a.is_empty() && !b.is_empty()), "panic3");
+    assert!(!(b.is_empty() || a.is_empty()), "panic4");
+    assert!(!(a.is_empty() || !b.is_empty()), "panic5");
+}
diff --git a/src/tools/clippy/tests/ui/manual_assert.rs b/src/tools/clippy/tests/ui/manual_assert.rs
new file mode 100644 (file)
index 0000000..8713426
--- /dev/null
@@ -0,0 +1,57 @@
+// revisions: edition2018 edition2021
+// [edition2018] edition:2018
+// [edition2021] edition:2021
+// run-rustfix
+#![warn(clippy::manual_assert)]
+
+fn main() {
+    let a = vec![1, 2, 3];
+    let c = Some(2);
+    if !a.is_empty()
+        && a.len() == 3
+        && c != None
+        && !a.is_empty()
+        && a.len() == 3
+        && !a.is_empty()
+        && a.len() == 3
+        && !a.is_empty()
+        && a.len() == 3
+    {
+        panic!("qaqaq{:?}", a);
+    }
+    if !a.is_empty() {
+        panic!("qaqaq{:?}", a);
+    }
+    if !a.is_empty() {
+        panic!("qwqwq");
+    }
+    if a.len() == 3 {
+        println!("qwq");
+        println!("qwq");
+        println!("qwq");
+    }
+    if let Some(b) = c {
+        panic!("orz {}", b);
+    }
+    if a.len() == 3 {
+        panic!("qaqaq");
+    } else {
+        println!("qwq");
+    }
+    let b = vec![1, 2, 3];
+    if b.is_empty() {
+        panic!("panic1");
+    }
+    if b.is_empty() && a.is_empty() {
+        panic!("panic2");
+    }
+    if a.is_empty() && !b.is_empty() {
+        panic!("panic3");
+    }
+    if b.is_empty() || a.is_empty() {
+        panic!("panic4");
+    }
+    if a.is_empty() || !b.is_empty() {
+        panic!("panic5");
+    }
+}
index 5184f6fdb88b3991850aead57bf02ea0a75b46cf..136cc96be70cafa57951fc7edd89c784892803b1 100644 (file)
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 #![warn(clippy::manual_async_fn)]
 #![allow(unused)]
 
index 68c0e591f0b6eed6b4ffd5eeb1b8bd0fde47bae1..ddc453ffdb7500958c5e26cbf62a65a4859640f7 100644 (file)
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 #![warn(clippy::manual_async_fn)]
 #![allow(unused)]
 
index 51f1a52b6dd65154d3b50d0a56bedfb8d24c37c9..7435f46074c8167287b383f5cee7f67c3e5afb0f 100644 (file)
@@ -1,5 +1,5 @@
 error: this function can be simplified using the `async fn` syntax
-  --> $DIR/manual_async_fn.rs:8:1
+  --> $DIR/manual_async_fn.rs:7:1
    |
 LL | fn fut() -> impl Future<Output = i32> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -15,7 +15,7 @@ LL | fn fut() -> impl Future<Output = i32> { 42 }
    |                                       ~~~~~~
 
 error: this function can be simplified using the `async fn` syntax
-  --> $DIR/manual_async_fn.rs:13:1
+  --> $DIR/manual_async_fn.rs:12:1
    |
 LL | fn fut2() ->impl Future<Output = i32> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -30,7 +30,7 @@ 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
+  --> $DIR/manual_async_fn.rs:17:1
    |
 LL | fn fut3()-> impl Future<Output = i32> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -45,7 +45,7 @@ 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
+  --> $DIR/manual_async_fn.rs:21:1
    |
 LL | fn empty_fut() -> impl Future<Output = ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -60,7 +60,7 @@ LL | fn empty_fut() -> impl Future<Output = ()> {}
    |                                            ~~
 
 error: this function can be simplified using the `async fn` syntax
-  --> $DIR/manual_async_fn.rs:27:1
+  --> $DIR/manual_async_fn.rs:26:1
    |
 LL | fn empty_fut2() ->impl Future<Output = ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -75,7 +75,7 @@ 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
+  --> $DIR/manual_async_fn.rs:31:1
    |
 LL | fn empty_fut3()-> impl Future<Output = ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -90,7 +90,7 @@ 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
+  --> $DIR/manual_async_fn.rs:35:1
    |
 LL | fn core_fut() -> impl core::future::Future<Output = i32> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -105,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:58:5
+  --> $DIR/manual_async_fn.rs:57:5
    |
 LL |     fn inh_fut() -> impl Future<Output = i32> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -125,7 +125,7 @@ LL +             let c = 21;
  ...
 
 error: this function can be simplified using the `async fn` syntax
-  --> $DIR/manual_async_fn.rs:93:1
+  --> $DIR/manual_async_fn.rs:92:1
    |
 LL | fn elided(_: &i32) -> impl Future<Output = i32> + '_ {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -140,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:102:1
+  --> $DIR/manual_async_fn.rs:101:1
    |
 LL | fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> + 'a + 'b {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 40d01df6379a696496028454027d8acaba84f1c8..294d79abc0459fe481a9125f07b1fd8faf67ac69 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 // run-rustfix
 
 #![warn(clippy::manual_map)]
index cfef0c5cc4ec66207834005b7b151d666737c0fa..d11bf5ecb825ae28a1ae76ba6f1594199e37dfc8 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 // run-rustfix
 
 #![warn(clippy::manual_map)]
index cdc2c0e62a9b9434838946240bbbc1f44e3a7f5c..0036b8151ded0514259d03687784e3597716b977 100644 (file)
@@ -1,5 +1,5 @@
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:15:5
+  --> $DIR/manual_map_option.rs:14:5
    |
 LL | /     match Some(0) {
 LL | |         Some(_) => Some(2),
@@ -10,7 +10,7 @@ LL | |     };
    = note: `-D clippy::manual-map` implied by `-D warnings`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:20:5
+  --> $DIR/manual_map_option.rs:19:5
    |
 LL | /     match Some(0) {
 LL | |         Some(x) => Some(x + 1),
@@ -19,7 +19,7 @@ LL | |     };
    | |_____^ help: try this: `Some(0).map(|x| x + 1)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:25:5
+  --> $DIR/manual_map_option.rs:24:5
    |
 LL | /     match Some("") {
 LL | |         Some(x) => Some(x.is_empty()),
@@ -28,7 +28,7 @@ LL | |     };
    | |_____^ help: try this: `Some("").map(|x| x.is_empty())`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:30:5
+  --> $DIR/manual_map_option.rs:29:5
    |
 LL | /     if let Some(x) = Some(0) {
 LL | |         Some(!x)
@@ -38,7 +38,7 @@ LL | |     };
    | |_____^ help: try this: `Some(0).map(|x| !x)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:37:5
+  --> $DIR/manual_map_option.rs:36:5
    |
 LL | /     match Some(0) {
 LL | |         Some(x) => { Some(std::convert::identity(x)) }
@@ -47,7 +47,7 @@ LL | |     };
    | |_____^ help: try this: `Some(0).map(std::convert::identity)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:42:5
+  --> $DIR/manual_map_option.rs:41:5
    |
 LL | /     match Some(&String::new()) {
 LL | |         Some(x) => Some(str::len(x)),
@@ -56,7 +56,7 @@ LL | |     };
    | |_____^ help: try this: `Some(&String::new()).map(|x| str::len(x))`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:52:5
+  --> $DIR/manual_map_option.rs:51:5
    |
 LL | /     match &Some([0, 1]) {
 LL | |         Some(x) => Some(x[0]),
@@ -65,7 +65,7 @@ LL | |     };
    | |_____^ help: try this: `Some([0, 1]).as_ref().map(|x| x[0])`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:57:5
+  --> $DIR/manual_map_option.rs:56:5
    |
 LL | /     match &Some(0) {
 LL | |         &Some(x) => Some(x * 2),
@@ -74,7 +74,7 @@ LL | |     };
    | |_____^ help: try this: `Some(0).map(|x| x * 2)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:62:5
+  --> $DIR/manual_map_option.rs:61:5
    |
 LL | /     match Some(String::new()) {
 LL | |         Some(ref x) => Some(x.is_empty()),
@@ -83,7 +83,7 @@ LL | |     };
    | |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.is_empty())`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:67:5
+  --> $DIR/manual_map_option.rs:66:5
    |
 LL | /     match &&Some(String::new()) {
 LL | |         Some(x) => Some(x.len()),
@@ -92,7 +92,7 @@ LL | |     };
    | |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.len())`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:72:5
+  --> $DIR/manual_map_option.rs:71:5
    |
 LL | /     match &&Some(0) {
 LL | |         &&Some(x) => Some(x + x),
@@ -101,7 +101,7 @@ LL | |     };
    | |_____^ help: try this: `Some(0).map(|x| x + x)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:85:9
+  --> $DIR/manual_map_option.rs:84:9
    |
 LL | /         match &mut Some(String::new()) {
 LL | |             Some(x) => Some(x.push_str("")),
@@ -110,7 +110,7 @@ LL | |         };
    | |_________^ help: try this: `Some(String::new()).as_mut().map(|x| x.push_str(""))`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:91:5
+  --> $DIR/manual_map_option.rs:90:5
    |
 LL | /     match &mut Some(String::new()) {
 LL | |         Some(ref x) => Some(x.len()),
@@ -119,7 +119,7 @@ LL | |     };
    | |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.len())`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:96:5
+  --> $DIR/manual_map_option.rs:95:5
    |
 LL | /     match &mut &Some(String::new()) {
 LL | |         Some(x) => Some(x.is_empty()),
@@ -128,7 +128,7 @@ LL | |     };
    | |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.is_empty())`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:101:5
+  --> $DIR/manual_map_option.rs:100:5
    |
 LL | /     match Some((0, 1, 2)) {
 LL | |         Some((x, y, z)) => Some(x + y + z),
@@ -137,7 +137,7 @@ LL | |     };
    | |_____^ help: try this: `Some((0, 1, 2)).map(|(x, y, z)| x + y + z)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:106:5
+  --> $DIR/manual_map_option.rs:105:5
    |
 LL | /     match Some([1, 2, 3]) {
 LL | |         Some([first, ..]) => Some(first),
@@ -146,7 +146,7 @@ LL | |     };
    | |_____^ help: try this: `Some([1, 2, 3]).map(|[first, ..]| first)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:111:5
+  --> $DIR/manual_map_option.rs:110:5
    |
 LL | /     match &Some((String::new(), "test")) {
 LL | |         Some((x, y)) => Some((y, x)),
@@ -155,7 +155,7 @@ LL | |     };
    | |_____^ help: try this: `Some((String::new(), "test")).as_ref().map(|(x, y)| (y, x))`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:169:5
+  --> $DIR/manual_map_option.rs:168:5
    |
 LL | /     match Some(0) {
 LL | |         Some(x) => Some(vec![x]),
@@ -164,7 +164,7 @@ LL | |     };
    | |_____^ help: try this: `Some(0).map(|x| vec![x])`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:174:5
+  --> $DIR/manual_map_option.rs:173:5
    |
 LL | /     match option_env!("") {
 LL | |         Some(x) => Some(String::from(x)),
@@ -173,7 +173,7 @@ LL | |     };
    | |_____^ help: try this: `option_env!("").map(String::from)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:194:12
+  --> $DIR/manual_map_option.rs:193:12
    |
 LL |       } else if let Some(x) = Some(0) {
    |  ____________^
@@ -184,7 +184,7 @@ LL | |     };
    | |_____^ help: try this: `{ Some(0).map(|x| x + 1) }`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:202:12
+  --> $DIR/manual_map_option.rs:201:12
    |
 LL |       } else if let Some(x) = Some(0) {
    |  ____________^
index 65769819110eb6f00b05332c7ae0b54c6ba8fa2b..88fcce66873aa3a73b6194eeddcacc88762bffb7 100644 (file)
@@ -1,3 +1,4 @@
+#![allow(clippy::too_many_arguments, clippy::diverging_sub_expression)]
 #![warn(clippy::many_single_char_names)]
 
 fn bla() {
index 27e62e641ade9c2d3b208922bd7d3367c6d21f0a..ade0f84bc50653be1b7f4574e7ff5fc9afd35cd3 100644 (file)
@@ -1,5 +1,5 @@
 error: 5 bindings with single-character names in scope
-  --> $DIR/many_single_char_names.rs:4:9
+  --> $DIR/many_single_char_names.rs:5:9
    |
 LL |     let a: i32;
    |         ^
@@ -12,7 +12,7 @@ LL |             let e: i32;
    = note: `-D clippy::many-single-char-names` implied by `-D warnings`
 
 error: 6 bindings with single-character names in scope
-  --> $DIR/many_single_char_names.rs:4:9
+  --> $DIR/many_single_char_names.rs:5:9
    |
 LL |     let a: i32;
    |         ^
@@ -25,7 +25,7 @@ LL |             let f: i32;
    |                 ^
 
 error: 5 bindings with single-character names in scope
-  --> $DIR/many_single_char_names.rs:4:9
+  --> $DIR/many_single_char_names.rs:5:9
    |
 LL |     let a: i32;
    |         ^
@@ -36,13 +36,13 @@ LL |             e => panic!(),
    |             ^
 
 error: 8 bindings with single-character names in scope
-  --> $DIR/many_single_char_names.rs:29:13
+  --> $DIR/many_single_char_names.rs:30:13
    |
 LL | fn bindings(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32, h: i32) {}
    |             ^       ^       ^       ^       ^       ^       ^       ^
 
 error: 8 bindings with single-character names in scope
-  --> $DIR/many_single_char_names.rs:32:10
+  --> $DIR/many_single_char_names.rs:33:10
    |
 LL |     let (a, b, c, d, e, f, g, h): (bool, bool, bool, bool, bool, bool, bool, bool) = unimplemented!();
    |          ^  ^  ^  ^  ^  ^  ^  ^
index ff91c4498ec62afd43c12497579a6a66925fd42a..845986a4eadabeee40414a90d26162cbb4ba5007 100644 (file)
@@ -100,6 +100,13 @@ fn overlapping() {
         _ => (),
     }
 
+    // Issue #7829
+    match 0 {
+        -1..=1 => (),
+        -2..=2 => (),
+        _ => (),
+    }
+
     if let None = Some(42) {
         // nothing
     } else if let None = Some(42) {
index 50246486bb6fc9371206f17adfe284b5e722a566..7e3674ab8c9f2c633094cce82c11d3351ebb8cb8 100644 (file)
@@ -1,5 +1,5 @@
 #![warn(clippy::match_ref_pats)]
-#![allow(clippy::equatable_if_let)]
+#![allow(clippy::equatable_if_let, clippy::enum_variant_names)]
 
 fn ref_pats() {
     {
index 208a4bba3d23c40d5cf2cbe4a2f650c18ba584b5..ac555c87d83b21a14beecece000d2cd7a55cbbdf 100644 (file)
@@ -12,6 +12,49 @@ fn as_str_match() {
     }
 }
 
+fn non_alphabetic() {
+    let var = "~!@#$%^&*()-_=+FOO";
+
+    match var.to_ascii_lowercase().as_str() {
+        "1234567890" => {},
+        "~!@#$%^&*()-_=+foo" => {},
+        "\n\r\t\x7F" => {},
+        _ => {},
+    }
+}
+
+fn unicode_cased() {
+    let var = "ВОДЫ";
+
+    match var.to_lowercase().as_str() {
+        "水" => {},
+        "νερό" => {},
+        "воды" => {},
+        "물" => {},
+        _ => {},
+    }
+}
+
+fn titlecase() {
+    let var = "BarDz";
+
+    match var.to_lowercase().as_str() {
+        "foolj" => {},
+        "bardz" => {},
+        _ => {},
+    }
+}
+
+fn no_case_equivalent() {
+    let var = "barʁ";
+
+    match var.to_uppercase().as_str() {
+        "FOOɕ" => {},
+        "BARʁ" => {},
+        _ => {},
+    }
+}
+
 fn addrof_unary_match() {
     let var = "BAR";
 
@@ -70,6 +113,49 @@ fn as_str_match_mismatch() {
     }
 }
 
+fn non_alphabetic_mismatch() {
+    let var = "~!@#$%^&*()-_=+FOO";
+
+    match var.to_ascii_lowercase().as_str() {
+        "1234567890" => {},
+        "~!@#$%^&*()-_=+Foo" => {},
+        "\n\r\t\x7F" => {},
+        _ => {},
+    }
+}
+
+fn unicode_cased_mismatch() {
+    let var = "ВОДЫ";
+
+    match var.to_lowercase().as_str() {
+        "水" => {},
+        "νερό" => {},
+        "Воды" => {},
+        "물" => {},
+        _ => {},
+    }
+}
+
+fn titlecase_mismatch() {
+    let var = "BarDz";
+
+    match var.to_lowercase().as_str() {
+        "foolj" => {},
+        "barDz" => {},
+        _ => {},
+    }
+}
+
+fn no_case_equivalent_mismatch() {
+    let var = "barʁ";
+
+    match var.to_uppercase().as_str() {
+        "FOOɕ" => {},
+        "bARʁ" => {},
+        _ => {},
+    }
+}
+
 fn addrof_unary_match_mismatch() {
     let var = "BAR";
 
index fa023477a9c334d20c7a934e93091b270bd41bf0..92baa40ef28f06f99746326de19b31e53055d703 100644 (file)
@@ -1,5 +1,5 @@
 error: this `match` arm has a differing case than its expression
-  --> $DIR/match_str_case_mismatch.rs:68:9
+  --> $DIR/match_str_case_mismatch.rs:111:9
    |
 LL |         "Bar" => {},
    |         ^^^^^
@@ -11,7 +11,51 @@ LL |         "bar" => {},
    |         ~~~~~
 
 error: this `match` arm has a differing case than its expression
-  --> $DIR/match_str_case_mismatch.rs:78:9
+  --> $DIR/match_str_case_mismatch.rs:121:9
+   |
+LL |         "~!@#$%^&*()-_=+Foo" => {},
+   |         ^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider changing the case of this arm to respect `to_ascii_lowercase`
+   |
+LL |         "~!@#$%^&*()-_=+foo" => {},
+   |         ~~~~~~~~~~~~~~~~~~~~
+
+error: this `match` arm has a differing case than its expression
+  --> $DIR/match_str_case_mismatch.rs:133:9
+   |
+LL |         "Воды" => {},
+   |         ^^^^^^
+   |
+help: consider changing the case of this arm to respect `to_lowercase`
+   |
+LL |         "воды" => {},
+   |         ~~~~~~
+
+error: this `match` arm has a differing case than its expression
+  --> $DIR/match_str_case_mismatch.rs:144:9
+   |
+LL |         "barDz" => {},
+   |         ^^^^^^
+   |
+help: consider changing the case of this arm to respect `to_lowercase`
+   |
+LL |         "bardz" => {},
+   |         ~~~~~~
+
+error: this `match` arm has a differing case than its expression
+  --> $DIR/match_str_case_mismatch.rs:154:9
+   |
+LL |         "bARʁ" => {},
+   |         ^^^^^^
+   |
+help: consider changing the case of this arm to respect `to_uppercase`
+   |
+LL |         "BARʁ" => {},
+   |         ~~~~~~
+
+error: this `match` arm has a differing case than its expression
+  --> $DIR/match_str_case_mismatch.rs:164:9
    |
 LL |         "Bar" => {},
    |         ^^^^^
@@ -22,7 +66,7 @@ LL |         "bar" => {},
    |         ~~~~~
 
 error: this `match` arm has a differing case than its expression
-  --> $DIR/match_str_case_mismatch.rs:93:9
+  --> $DIR/match_str_case_mismatch.rs:179:9
    |
 LL |         "bAR" => {},
    |         ^^^^^
@@ -32,5 +76,5 @@ help: consider changing the case of this arm to respect `to_ascii_uppercase`
 LL |         "BAR" => {},
    |         ~~~~~
 
-error: aborting due to 3 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/src/tools/clippy/tests/ui/match_wild_err_arm.edition2018.stderr b/src/tools/clippy/tests/ui/match_wild_err_arm.edition2018.stderr
new file mode 100644 (file)
index 0000000..2a40120
--- /dev/null
@@ -0,0 +1,35 @@
+error: `Err(_)` matches all errors
+  --> $DIR/match_wild_err_arm.rs:14:9
+   |
+LL |         Err(_) => panic!("err"),
+   |         ^^^^^^
+   |
+   = note: `-D clippy::match-wild-err-arm` implied by `-D warnings`
+   = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
+
+error: `Err(_)` matches all errors
+  --> $DIR/match_wild_err_arm.rs:20:9
+   |
+LL |         Err(_) => panic!(),
+   |         ^^^^^^
+   |
+   = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
+
+error: `Err(_)` matches all errors
+  --> $DIR/match_wild_err_arm.rs:26:9
+   |
+LL |         Err(_) => {
+   |         ^^^^^^
+   |
+   = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
+
+error: `Err(_e)` matches all errors
+  --> $DIR/match_wild_err_arm.rs:34:9
+   |
+LL |         Err(_e) => panic!(),
+   |         ^^^^^^^
+   |
+   = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/match_wild_err_arm.edition2021.stderr b/src/tools/clippy/tests/ui/match_wild_err_arm.edition2021.stderr
new file mode 100644 (file)
index 0000000..2a40120
--- /dev/null
@@ -0,0 +1,35 @@
+error: `Err(_)` matches all errors
+  --> $DIR/match_wild_err_arm.rs:14:9
+   |
+LL |         Err(_) => panic!("err"),
+   |         ^^^^^^
+   |
+   = note: `-D clippy::match-wild-err-arm` implied by `-D warnings`
+   = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
+
+error: `Err(_)` matches all errors
+  --> $DIR/match_wild_err_arm.rs:20:9
+   |
+LL |         Err(_) => panic!(),
+   |         ^^^^^^
+   |
+   = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
+
+error: `Err(_)` matches all errors
+  --> $DIR/match_wild_err_arm.rs:26:9
+   |
+LL |         Err(_) => {
+   |         ^^^^^^
+   |
+   = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
+
+error: `Err(_e)` matches all errors
+  --> $DIR/match_wild_err_arm.rs:34:9
+   |
+LL |         Err(_e) => panic!(),
+   |         ^^^^^^^
+   |
+   = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
+
+error: aborting due to 4 previous errors
+
index 823be65efe065703b8481ced833636d15b245373..0a86144b95d5bcc59b148e298783caa02d017217 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: edition2018 edition2021
+// [edition2018] edition:2018
+// [edition2021] edition:2021
 #![feature(exclusive_range_pattern)]
 #![allow(clippy::match_same_arms)]
 #![warn(clippy::match_wild_err_arm)]
diff --git a/src/tools/clippy/tests/ui/match_wild_err_arm.stderr b/src/tools/clippy/tests/ui/match_wild_err_arm.stderr
deleted file mode 100644 (file)
index 6a2a029..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-error: `Err(_)` matches all errors
-  --> $DIR/match_wild_err_arm.rs:11:9
-   |
-LL |         Err(_) => panic!("err"),
-   |         ^^^^^^
-   |
-   = note: `-D clippy::match-wild-err-arm` implied by `-D warnings`
-   = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
-
-error: `Err(_)` matches all errors
-  --> $DIR/match_wild_err_arm.rs:17:9
-   |
-LL |         Err(_) => panic!(),
-   |         ^^^^^^
-   |
-   = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
-
-error: `Err(_)` matches all errors
-  --> $DIR/match_wild_err_arm.rs:23:9
-   |
-LL |         Err(_) => {
-   |         ^^^^^^
-   |
-   = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
-
-error: `Err(_e)` matches all errors
-  --> $DIR/match_wild_err_arm.rs:31:9
-   |
-LL |         Err(_e) => panic!(),
-   |         ^^^^^^^
-   |
-   = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
-
-error: aborting due to 4 previous errors
-
index c441b35b9920390c89edfc6ac504716cf25eae2f..977ce54327b3d984a4f61fca7c2967b734a3ce57 100644 (file)
@@ -1,5 +1,4 @@
 // aux-build:option_helpers.rs
-// edition:2018
 
 #![warn(clippy::all, clippy::pedantic)]
 #![allow(
index 4643e09e2702835ac9803b6050b49f1ba7267171..b63672dd6fdbb546dac805e74727f9bf8982851f 100644 (file)
@@ -1,5 +1,5 @@
 error: methods called `new` usually return `Self`
-  --> $DIR/methods.rs:105:5
+  --> $DIR/methods.rs:104:5
    |
 LL | /     fn new() -> i32 {
 LL | |         0
@@ -9,7 +9,7 @@ LL | |     }
    = note: `-D clippy::new-ret-no-self` implied by `-D warnings`
 
 error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead
-  --> $DIR/methods.rs:126:13
+  --> $DIR/methods.rs:125:13
    |
 LL |       let _ = v.iter().filter(|&x| {
    |  _____________^
index a9bf7140a1e594ae61cf64f9a000ee6716b669b3..148531c285d3d310ed9011992604cf8a5d4c4b43 100644 (file)
@@ -3,7 +3,6 @@
 // injected intrinsics by the compiler.
 #![allow(dead_code)]
 #![feature(global_asm)]
-
 //! Some garbage docs for the crate here
 #![doc = "More garbage"]
 
@@ -90,10 +89,10 @@ fn also_undocumented2() {}
 }
 /// dox
 pub mod public_interface {
-    pub use internal_impl::documented as foo;
-    pub use internal_impl::globbed::*;
-    pub use internal_impl::undocumented1 as bar;
-    pub use internal_impl::{documented, undocumented2};
+    pub use crate::internal_impl::documented as foo;
+    pub use crate::internal_impl::globbed::*;
+    pub use crate::internal_impl::undocumented1 as bar;
+    pub use crate::internal_impl::{documented, undocumented2};
 }
 
 fn main() {}
index a876dc078ebff96f25c8e34efad90156b896a70a..7a3a448c9d6c2730e407e220b73297e57e576119 100644 (file)
@@ -1,5 +1,5 @@
 error: missing documentation for a type alias
-  --> $DIR/missing-doc.rs:10:1
+  --> $DIR/missing-doc.rs:9:1
    |
 LL | type Typedef = String;
    | ^^^^^^^^^^^^^^^^^^^^^^
@@ -7,37 +7,37 @@ LL | type Typedef = String;
    = note: `-D clippy::missing-docs-in-private-items` implied by `-D warnings`
 
 error: missing documentation for a type alias
-  --> $DIR/missing-doc.rs:11:1
+  --> $DIR/missing-doc.rs:10:1
    |
 LL | pub type PubTypedef = String;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a module
-  --> $DIR/missing-doc.rs:13:1
+  --> $DIR/missing-doc.rs:12:1
    |
 LL | mod module_no_dox {}
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a module
-  --> $DIR/missing-doc.rs:14:1
+  --> $DIR/missing-doc.rs:13:1
    |
 LL | pub mod pub_module_no_dox {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a function
-  --> $DIR/missing-doc.rs:18:1
+  --> $DIR/missing-doc.rs:17:1
    |
 LL | pub fn foo2() {}
    | ^^^^^^^^^^^^^^^^
 
 error: missing documentation for a function
-  --> $DIR/missing-doc.rs:19:1
+  --> $DIR/missing-doc.rs:18:1
    |
 LL | fn foo3() {}
    | ^^^^^^^^^^^^
 
 error: missing documentation for an enum
-  --> $DIR/missing-doc.rs:33:1
+  --> $DIR/missing-doc.rs:32:1
    |
 LL | / enum Baz {
 LL | |     BazA { a: isize, b: isize },
@@ -46,31 +46,31 @@ LL | | }
    | |_^
 
 error: missing documentation for a variant
-  --> $DIR/missing-doc.rs:34:5
+  --> $DIR/missing-doc.rs:33:5
    |
 LL |     BazA { a: isize, b: isize },
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a struct field
-  --> $DIR/missing-doc.rs:34:12
+  --> $DIR/missing-doc.rs:33:12
    |
 LL |     BazA { a: isize, b: isize },
    |            ^^^^^^^^
 
 error: missing documentation for a struct field
-  --> $DIR/missing-doc.rs:34:22
+  --> $DIR/missing-doc.rs:33:22
    |
 LL |     BazA { a: isize, b: isize },
    |                      ^^^^^^^^
 
 error: missing documentation for a variant
-  --> $DIR/missing-doc.rs:35:5
+  --> $DIR/missing-doc.rs:34:5
    |
 LL |     BarB,
    |     ^^^^
 
 error: missing documentation for an enum
-  --> $DIR/missing-doc.rs:38:1
+  --> $DIR/missing-doc.rs:37:1
    |
 LL | / pub enum PubBaz {
 LL | |     PubBazA { a: isize },
@@ -78,43 +78,43 @@ LL | | }
    | |_^
 
 error: missing documentation for a variant
-  --> $DIR/missing-doc.rs:39:5
+  --> $DIR/missing-doc.rs:38:5
    |
 LL |     PubBazA { a: isize },
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a struct field
-  --> $DIR/missing-doc.rs:39:15
+  --> $DIR/missing-doc.rs:38:15
    |
 LL |     PubBazA { a: isize },
    |               ^^^^^^^^
 
 error: missing documentation for a constant
-  --> $DIR/missing-doc.rs:59:1
+  --> $DIR/missing-doc.rs:58:1
    |
 LL | const FOO: u32 = 0;
    | ^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a constant
-  --> $DIR/missing-doc.rs:66:1
+  --> $DIR/missing-doc.rs:65:1
    |
 LL | pub const FOO4: u32 = 0;
    | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a static
-  --> $DIR/missing-doc.rs:68:1
+  --> $DIR/missing-doc.rs:67:1
    |
 LL | static BAR: u32 = 0;
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a static
-  --> $DIR/missing-doc.rs:75:1
+  --> $DIR/missing-doc.rs:74:1
    |
 LL | pub static BAR4: u32 = 0;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a module
-  --> $DIR/missing-doc.rs:77:1
+  --> $DIR/missing-doc.rs:76:1
    |
 LL | / mod internal_impl {
 LL | |     /// dox
@@ -126,31 +126,31 @@ LL | | }
    | |_^
 
 error: missing documentation for a function
-  --> $DIR/missing-doc.rs:80:5
+  --> $DIR/missing-doc.rs:79:5
    |
 LL |     pub fn undocumented1() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a function
-  --> $DIR/missing-doc.rs:81:5
+  --> $DIR/missing-doc.rs:80:5
    |
 LL |     pub fn undocumented2() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a function
-  --> $DIR/missing-doc.rs:82:5
+  --> $DIR/missing-doc.rs:81:5
    |
 LL |     fn undocumented3() {}
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a function
-  --> $DIR/missing-doc.rs:87:9
+  --> $DIR/missing-doc.rs:86:9
    |
 LL |         pub fn also_undocumented1() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a function
-  --> $DIR/missing-doc.rs:88:9
+  --> $DIR/missing-doc.rs:87:9
    |
 LL |         fn also_undocumented2() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
index 2e1379a58a67bbd2a32f1676fa684445e194cda9..7dc44529206d551a423dbfea3762038b3b610074 100644 (file)
@@ -1,6 +1,5 @@
 #![warn(clippy::missing_panics_doc)]
 #![allow(clippy::option_map_unit_fn)]
-
 fn main() {}
 
 /// This needs to be documented
index b863063b626dbe68183eda66c717ef6156b78881..60282939ef0334008f00c7d78ea12693c2b22595 100644 (file)
@@ -1,5 +1,5 @@
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:7:1
+  --> $DIR/missing_panics_doc.rs:6:1
    |
 LL | / pub fn unwrap() {
 LL | |     let result = Err("Hi");
@@ -9,13 +9,13 @@ LL | | }
    |
    = note: `-D clippy::missing-panics-doc` implied by `-D warnings`
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:9:5
+  --> $DIR/missing_panics_doc.rs:8:5
    |
 LL |     result.unwrap()
    |     ^^^^^^^^^^^^^^^
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:13:1
+  --> $DIR/missing_panics_doc.rs:12:1
    |
 LL | / pub fn panic() {
 LL | |     panic!("This function panics")
@@ -23,14 +23,14 @@ LL | | }
    | |_^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:14:5
+  --> $DIR/missing_panics_doc.rs:13:5
    |
 LL |     panic!("This function panics")
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:18:1
+  --> $DIR/missing_panics_doc.rs:17:1
    |
 LL | / pub fn todo() {
 LL | |     todo!()
@@ -38,14 +38,14 @@ LL | | }
    | |_^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:19:5
+  --> $DIR/missing_panics_doc.rs:18:5
    |
 LL |     todo!()
    |     ^^^^^^^
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:23:1
+  --> $DIR/missing_panics_doc.rs:22:1
    |
 LL | / pub fn inner_body(opt: Option<u32>) {
 LL | |     opt.map(|x| {
@@ -57,14 +57,14 @@ LL | | }
    | |_^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:26:13
+  --> $DIR/missing_panics_doc.rs:25:13
    |
 LL |             panic!()
    |             ^^^^^^^^
-   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:32:1
+  --> $DIR/missing_panics_doc.rs:31:1
    |
 LL | / pub fn unreachable_and_panic() {
 LL | |     if true { unreachable!() } else { panic!() }
@@ -72,14 +72,14 @@ LL | | }
    | |_^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:33:39
+  --> $DIR/missing_panics_doc.rs:32:39
    |
 LL |     if true { unreachable!() } else { panic!() }
    |                                       ^^^^^^^^
-   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:37:1
+  --> $DIR/missing_panics_doc.rs:36:1
    |
 LL | / pub fn assert_eq() {
 LL | |     let x = 0;
@@ -88,14 +88,14 @@ LL | | }
    | |_^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:39:5
+  --> $DIR/missing_panics_doc.rs:38:5
    |
 LL |     assert_eq!(x, 0);
    |     ^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:43:1
+  --> $DIR/missing_panics_doc.rs:42:1
    |
 LL | / pub fn assert_ne() {
 LL | |     let x = 0;
@@ -104,7 +104,7 @@ LL | | }
    | |_^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:45:5
+  --> $DIR/missing_panics_doc.rs:44:5
    |
 LL |     assert_ne!(x, 0);
    |     ^^^^^^^^^^^^^^^^
index 70cdb067d91380cb2b8866110d8c4160a683c1e4..5d57638af43495bea12bce75b930aa600ae51343 100644 (file)
@@ -3,6 +3,7 @@
 #![allow(
     dead_code,
     unused_variables,
+    overflowing_literals,
     clippy::excessive_precision,
     clippy::inconsistent_digit_grouping
 )]
@@ -21,7 +22,6 @@ fn main() {
     let fail25 = 1E2_f32;
     let fail26 = 43E7_f64;
     let fail27 = 243E17_f32;
-    #[allow(overflowing_literals)]
     let fail28 = 241_251_235E723_f64;
     let ok29 = 42279.911_32;
 
index 729990af3998dbc9d36f0e40b3d8d93175da5009..12171452885d2b009bdb0e0373abe765a0c29a04 100644 (file)
@@ -3,6 +3,7 @@
 #![allow(
     dead_code,
     unused_variables,
+    overflowing_literals,
     clippy::excessive_precision,
     clippy::inconsistent_digit_grouping
 )]
@@ -21,7 +22,6 @@ fn main() {
     let fail25 = 1E2_32;
     let fail26 = 43E7_64;
     let fail27 = 243E17_32;
-    #[allow(overflowing_literals)]
     let fail28 = 241251235E723_64;
     let ok29 = 42279.911_32;
 
index b338b8aa6228d5757cc7c79212f6c48bd0b2f1b9..d24543c26e4b0d7e48cbb4647f03ebcd2abf3cb0 100644 (file)
@@ -1,5 +1,5 @@
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:11:18
+  --> $DIR/mistyped_literal_suffix.rs:12:18
    |
 LL |     let fail14 = 2_32;
    |                  ^^^^ help: did you mean to write: `2_i32`
@@ -7,49 +7,49 @@ LL |     let fail14 = 2_32;
    = note: `#[deny(clippy::mistyped_literal_suffixes)]` on by default
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:12:18
+  --> $DIR/mistyped_literal_suffix.rs:13:18
    |
 LL |     let fail15 = 4_64;
    |                  ^^^^ help: did you mean to write: `4_i64`
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:13:18
+  --> $DIR/mistyped_literal_suffix.rs:14:18
    |
 LL |     let fail16 = 7_8; //
    |                  ^^^ help: did you mean to write: `7_i8`
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:14:18
+  --> $DIR/mistyped_literal_suffix.rs:15:18
    |
 LL |     let fail17 = 23_16; //
    |                  ^^^^^ help: did you mean to write: `23_i16`
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:17:18
+  --> $DIR/mistyped_literal_suffix.rs:18:18
    |
 LL |     let fail20 = 2__8; //
    |                  ^^^^ help: did you mean to write: `2_i8`
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:18:18
+  --> $DIR/mistyped_literal_suffix.rs:19:18
    |
 LL |     let fail21 = 4___16; //
    |                  ^^^^^^ help: did you mean to write: `4_i16`
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:21:18
+  --> $DIR/mistyped_literal_suffix.rs:22:18
    |
 LL |     let fail25 = 1E2_32;
    |                  ^^^^^^ help: did you mean to write: `1E2_f32`
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:22:18
+  --> $DIR/mistyped_literal_suffix.rs:23:18
    |
 LL |     let fail26 = 43E7_64;
    |                  ^^^^^^^ help: did you mean to write: `43E7_f64`
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:23:18
+  --> $DIR/mistyped_literal_suffix.rs:24:18
    |
 LL |     let fail27 = 243E17_32;
    |                  ^^^^^^^^^ help: did you mean to write: `243E17_f32`
index a39d96109f17d8d03e38c4701cc4345d1e51ed30..ad0d694a2174a3a125393790d5767a81afd9c98d 100644 (file)
@@ -38,6 +38,7 @@ struct S2 {}
     //  fn call_with_mut_self<'life0>(self: &'life0 mut Self) {}
     #[rename_my_lifetimes]
     impl T2 for S2 {
+        #[allow(clippy::needless_lifetimes)]
         fn call_with_mut_self(self: &mut Self) {}
     }
 }
index 44a0e6ddeace63bcd54bc6f7284eff4a336ec4e9..b2edbfe4323e16ce6ec4407158daa60f143b335f 100644 (file)
@@ -1,5 +1,5 @@
 error: the type of the `self` parameter does not need to be arbitrary
-  --> $DIR/needless_arbitrary_self_type_unfixable.rs:41:31
+  --> $DIR/needless_arbitrary_self_type_unfixable.rs:42:31
    |
 LL |         fn call_with_mut_self(self: &mut Self) {}
    |                               ^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&'_ mut self`
index 7a8137778b44607cd397c03b04205f43e27aeb84..04b6283da3c3b88d8a5b16c44edfd5d53133dbe6 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 // FIXME: run-rustfix waiting on multi-span suggestions
 
 #![warn(clippy::needless_borrow)]
index 365ecd68d8ff2e9cabc8e0635670712e744d17b1..db3b52b8850e1cfd252e3eda54933f1abe4f8b60 100644 (file)
@@ -1,5 +1,5 @@
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:60:14
+  --> $DIR/needless_borrow_pat.rs:59:14
    |
 LL |         Some(ref x) => x,
    |              ^^^^^ help: try this: `x`
@@ -7,7 +7,7 @@ LL |         Some(ref x) => x,
    = note: `-D clippy::needless-borrow` implied by `-D warnings`
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:66:14
+  --> $DIR/needless_borrow_pat.rs:65:14
    |
 LL |         Some(ref x) => *x,
    |              ^^^^^
@@ -18,7 +18,7 @@ LL |         Some(x) => x,
    |              ~     ~
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:72:14
+  --> $DIR/needless_borrow_pat.rs:71:14
    |
 LL |         Some(ref x) => {
    |              ^^^^^
@@ -31,19 +31,19 @@ LL ~             f1(x);
    |
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:82:14
+  --> $DIR/needless_borrow_pat.rs:81:14
    |
 LL |         Some(ref x) => m1!(x),
    |              ^^^^^ help: try this: `x`
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:87:15
+  --> $DIR/needless_borrow_pat.rs:86:15
    |
 LL |     let _ = |&ref x: &&String| {
    |               ^^^^^ help: try this: `x`
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:92:10
+  --> $DIR/needless_borrow_pat.rs:91:10
    |
 LL |     let (ref y,) = (&x,);
    |          ^^^^^
@@ -55,13 +55,13 @@ LL ~     let _: &String = y;
    |
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:102:14
+  --> $DIR/needless_borrow_pat.rs:101:14
    |
 LL |         Some(ref x) => x.0,
    |              ^^^^^ help: try this: `x`
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:112:14
+  --> $DIR/needless_borrow_pat.rs:111:14
    |
 LL |         E::A(ref x) | E::B(ref x) => *x,
    |              ^^^^^         ^^^^^
@@ -72,13 +72,13 @@ LL |         E::A(x) | E::B(x) => x,
    |              ~         ~     ~
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:118:21
+  --> $DIR/needless_borrow_pat.rs:117:21
    |
 LL |         if let Some(ref x) = Some(&String::new());
    |                     ^^^^^ help: try this: `x`
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:126:12
+  --> $DIR/needless_borrow_pat.rs:125:12
    |
 LL | fn f2<'a>(&ref x: &&'a String) -> &'a String {
    |            ^^^^^
@@ -91,13 +91,13 @@ LL ~     x
    |
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:133:11
+  --> $DIR/needless_borrow_pat.rs:132:11
    |
 LL |     fn f(&ref x: &&String) {
    |           ^^^^^ help: try this: `x`
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:141:11
+  --> $DIR/needless_borrow_pat.rs:140:11
    |
 LL |     fn f(&ref x: &&String) {
    |           ^^^^^
index 83ee27f4887a1822d7aa6ae1eb1deca3fc29edba..f105d3d659ac7fb199e5c4fc593ca224c86447e1 100644 (file)
@@ -12,6 +12,7 @@ macro_rules! nonzero {
     };
 }
 
+#[allow(clippy::nonminimal_bool)]
 fn main() {
     let mut i = 1;
     while i < 10 {
index 22b86f25e8f0e44ced23329d1cc378cc31d27e89..b8657c74caa6930c9408ecc4079a9fd7b5893e0d 100644 (file)
@@ -1,5 +1,5 @@
 error: this `else` block is redundant
-  --> $DIR/needless_continue.rs:28:16
+  --> $DIR/needless_continue.rs:29:16
    |
 LL |           } else {
    |  ________________^
@@ -35,7 +35,7 @@ LL | |         }
                    }
 
 error: there is no need for an explicit `else` block for this `if` expression
-  --> $DIR/needless_continue.rs:43:9
+  --> $DIR/needless_continue.rs:44:9
    |
 LL | /         if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 {
 LL | |             continue;
@@ -55,7 +55,7 @@ LL | |         }
                    }
 
 error: this `continue` expression is redundant
-  --> $DIR/needless_continue.rs:56:9
+  --> $DIR/needless_continue.rs:57:9
    |
 LL |         continue; // should lint here
    |         ^^^^^^^^^
@@ -63,7 +63,7 @@ LL |         continue; // should lint here
    = help: consider dropping the `continue` expression
 
 error: this `continue` expression is redundant
-  --> $DIR/needless_continue.rs:63:9
+  --> $DIR/needless_continue.rs:64:9
    |
 LL |         continue; // should lint here
    |         ^^^^^^^^^
@@ -71,7 +71,7 @@ LL |         continue; // should lint here
    = help: consider dropping the `continue` expression
 
 error: this `continue` expression is redundant
-  --> $DIR/needless_continue.rs:70:9
+  --> $DIR/needless_continue.rs:71:9
    |
 LL |         continue // should lint here
    |         ^^^^^^^^
@@ -79,7 +79,7 @@ LL |         continue // should lint here
    = help: consider dropping the `continue` expression
 
 error: this `continue` expression is redundant
-  --> $DIR/needless_continue.rs:78:9
+  --> $DIR/needless_continue.rs:79:9
    |
 LL |         continue // should lint here
    |         ^^^^^^^^
@@ -87,7 +87,7 @@ LL |         continue // should lint here
    = help: consider dropping the `continue` expression
 
 error: this `else` block is redundant
-  --> $DIR/needless_continue.rs:128:24
+  --> $DIR/needless_continue.rs:129:24
    |
 LL |                   } else {
    |  ________________________^
@@ -110,7 +110,7 @@ LL | |                 }
                            }
 
 error: there is no need for an explicit `else` block for this `if` expression
-  --> $DIR/needless_continue.rs:134:17
+  --> $DIR/needless_continue.rs:135:17
    |
 LL | /                 if condition() {
 LL | |                     continue; // should lint here
index 1d77382bf2cd1132549232dd03fe41af93de9389..b07c4a2381031f2f4c617c4e355e904c8243f9a6 100644 (file)
@@ -27,6 +27,11 @@ fn multiple_in_and_out_2<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
     x
 }
 
+// No error; multiple input refs
+async fn func<'a>(args: &[&'a str]) -> Option<&'a str> {
+    args.get(0).cloned()
+}
+
 // No error; static involved.
 fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 {
     x
index 33a6de1618d12c1a509df271c43b8f57e11d9282..4114e6f1832fc694ddbffecd65819900de31df43 100644 (file)
@@ -19,133 +19,133 @@ LL | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:45:1
+  --> $DIR/needless_lifetimes.rs:50:1
    |
 LL | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:50:1
+  --> $DIR/needless_lifetimes.rs:55:1
    |
 LL | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:62:1
+  --> $DIR/needless_lifetimes.rs:67:1
    |
 LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:86:1
+  --> $DIR/needless_lifetimes.rs:91:1
    |
 LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:116:5
+  --> $DIR/needless_lifetimes.rs:121:5
    |
 LL |     fn self_and_out<'s>(&'s self) -> &'s u8 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:125:5
+  --> $DIR/needless_lifetimes.rs:130:5
    |
 LL |     fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:144:1
+  --> $DIR/needless_lifetimes.rs:149:1
    |
 LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:174:1
+  --> $DIR/needless_lifetimes.rs:179:1
    |
 LL | fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:180:1
+  --> $DIR/needless_lifetimes.rs:185:1
    |
 LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:199:1
+  --> $DIR/needless_lifetimes.rs:204:1
    |
 LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:207:1
+  --> $DIR/needless_lifetimes.rs:212:1
    |
 LL | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:243:1
+  --> $DIR/needless_lifetimes.rs:248:1
    |
 LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:250:9
+  --> $DIR/needless_lifetimes.rs:255:9
    |
 LL |         fn needless_lt<'a>(x: &'a u8) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:254:9
+  --> $DIR/needless_lifetimes.rs:259:9
    |
 LL |         fn needless_lt<'a>(_x: &'a u8) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:267:9
+  --> $DIR/needless_lifetimes.rs:272:9
    |
 LL |         fn baz<'a>(&'a self) -> impl Foo + 'a {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:296:5
+  --> $DIR/needless_lifetimes.rs:301:5
    |
 LL |     fn impl_trait_elidable_nested_named_lifetimes<'a>(i: &'a i32, f: impl for<'b> Fn(&'b i32) -> &'b i32) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:299:5
+  --> $DIR/needless_lifetimes.rs:304:5
    |
 LL |     fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:308:5
+  --> $DIR/needless_lifetimes.rs:313:5
    |
 LL |     fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:320:5
+  --> $DIR/needless_lifetimes.rs:325:5
    |
 LL |     fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:335:5
+  --> $DIR/needless_lifetimes.rs:340:5
    |
 LL |     fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:348:5
+  --> $DIR/needless_lifetimes.rs:353:5
    |
 LL |     fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:351:5
+  --> $DIR/needless_lifetimes.rs:356:5
    |
 LL |     fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 9c999e12b4cbc4c6d5a3afed29e97cffa3638623..812ce7163cd50ab215cd7130493b1e816d71ccf4 100644 (file)
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 
 #![feature(let_else)]
 #![allow(unused)]
index da7dcf4f0a9ea377596a830996947f6d5afa60fb..c42567b517c9115819b3446d5c5281c0da273884 100644 (file)
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 
 #![feature(let_else)]
 #![allow(unused)]
index 2e802cff1e686917ddef5a3c5e1ba7421c617ec4..74dda971fdabb632633f4a125ba15d6e2d5ad1a3 100644 (file)
@@ -1,5 +1,5 @@
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:25:5
+  --> $DIR/needless_return.rs:24:5
    |
 LL |     return true;
    |     ^^^^^^^^^^^^ help: remove `return`: `true`
@@ -7,187 +7,187 @@ LL |     return true;
    = note: `-D clippy::needless-return` implied by `-D warnings`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:29:5
+  --> $DIR/needless_return.rs:28:5
    |
 LL |     return true;
    |     ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:34:9
+  --> $DIR/needless_return.rs:33:9
    |
 LL |         return true;
    |         ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:36:9
+  --> $DIR/needless_return.rs:35:9
    |
 LL |         return false;
    |         ^^^^^^^^^^^^^ help: remove `return`: `false`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:42:17
+  --> $DIR/needless_return.rs:41:17
    |
 LL |         true => return false,
    |                 ^^^^^^^^^^^^ help: remove `return`: `false`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:44:13
+  --> $DIR/needless_return.rs:43:13
    |
 LL |             return true;
    |             ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:51:9
+  --> $DIR/needless_return.rs:50:9
    |
 LL |         return true;
    |         ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:53:16
+  --> $DIR/needless_return.rs:52:16
    |
 LL |     let _ = || return true;
    |                ^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:61:5
+  --> $DIR/needless_return.rs:60:5
    |
 LL |     return;
    |     ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:66:9
+  --> $DIR/needless_return.rs:65:9
    |
 LL |         return;
    |         ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:68:9
+  --> $DIR/needless_return.rs:67:9
    |
 LL |         return;
    |         ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:75:14
+  --> $DIR/needless_return.rs:74:14
    |
 LL |         _ => return,
    |              ^^^^^^ help: replace `return` with an empty block: `{}`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:90:9
+  --> $DIR/needless_return.rs:89:9
    |
 LL |         return String::from("test");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:92:9
+  --> $DIR/needless_return.rs:91:9
    |
 LL |         return String::new();
    |         ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:113:32
+  --> $DIR/needless_return.rs:112:32
    |
 LL |         bar.unwrap_or_else(|_| return)
    |                                ^^^^^^ help: replace `return` with an empty block: `{}`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:118:13
+  --> $DIR/needless_return.rs:117:13
    |
 LL |             return;
    |             ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:120:20
+  --> $DIR/needless_return.rs:119:20
    |
 LL |         let _ = || return;
    |                    ^^^^^^ help: replace `return` with an empty block: `{}`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:126:32
+  --> $DIR/needless_return.rs:125:32
    |
 LL |         res.unwrap_or_else(|_| return Foo)
    |                                ^^^^^^^^^^ help: remove `return`: `Foo`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:135:5
+  --> $DIR/needless_return.rs:134:5
    |
 LL |     return true;
    |     ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:139:5
+  --> $DIR/needless_return.rs:138:5
    |
 LL |     return true;
    |     ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:144:9
+  --> $DIR/needless_return.rs:143:9
    |
 LL |         return true;
    |         ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:146:9
+  --> $DIR/needless_return.rs:145:9
    |
 LL |         return false;
    |         ^^^^^^^^^^^^^ help: remove `return`: `false`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:152:17
+  --> $DIR/needless_return.rs:151:17
    |
 LL |         true => return false,
    |                 ^^^^^^^^^^^^ help: remove `return`: `false`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:154:13
+  --> $DIR/needless_return.rs:153:13
    |
 LL |             return true;
    |             ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:161:9
+  --> $DIR/needless_return.rs:160:9
    |
 LL |         return true;
    |         ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:163:16
+  --> $DIR/needless_return.rs:162:16
    |
 LL |     let _ = || return true;
    |                ^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:171:5
+  --> $DIR/needless_return.rs:170:5
    |
 LL |     return;
    |     ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:176:9
+  --> $DIR/needless_return.rs:175:9
    |
 LL |         return;
    |         ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:178:9
+  --> $DIR/needless_return.rs:177:9
    |
 LL |         return;
    |         ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:185:14
+  --> $DIR/needless_return.rs:184:14
    |
 LL |         _ => return,
    |              ^^^^^^ help: replace `return` with an empty block: `{}`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:200:9
+  --> $DIR/needless_return.rs:199:9
    |
 LL |         return String::from("test");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:202:9
+  --> $DIR/needless_return.rs:201:9
    |
 LL |         return String::new();
    |         ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()`
index 58415b4aede260b668dbd3db7a0f9a56bc56ecd8..9937005d68d8ae43092952b1a4f307d8f21f816c 100644 (file)
@@ -1,5 +1,5 @@
 #![warn(clippy::all)]
-#![allow(unused, clippy::println_empty_string)]
+#![allow(unused, clippy::println_empty_string, non_snake_case)]
 
 #[derive(Clone, Debug)]
 enum MaybeInst {
@@ -14,9 +14,10 @@ struct InstSplit {
 
 impl MaybeInst {
     fn fill(&mut self) {
+        #[allow(non_fmt_panics)]
         let filled = match *self {
-            MaybeInst::Split1(goto1) => panic!(1),
-            MaybeInst::Split2(goto2) => panic!(2),
+            MaybeInst::Split1(goto1) => panic!("1"),
+            MaybeInst::Split2(goto2) => panic!("2"),
             _ => unimplemented!(),
         };
         unimplemented!()
@@ -36,6 +37,7 @@ fn issue2927() {
 }
 
 fn issue3078() {
+    #[allow(clippy::single_match)]
     match "a" {
         stringify!(a) => {},
         _ => {},
index a0ca46f0efc602cd0a6bccc6c35b48dee5697e5e..116d5da8729c0f2d334d91a4966483158f52bd53 100644 (file)
@@ -1,5 +1,5 @@
 error: consider choosing a more descriptive name
-  --> $DIR/non_expressive_names.rs:27:9
+  --> $DIR/non_expressive_names.rs:28:9
    |
 LL |     let _1 = 1; //~ERROR Consider a more descriptive name
    |         ^^
@@ -7,31 +7,31 @@ LL |     let _1 = 1; //~ERROR Consider a more descriptive name
    = note: `-D clippy::just-underscores-and-digits` implied by `-D warnings`
 
 error: consider choosing a more descriptive name
-  --> $DIR/non_expressive_names.rs:28:9
+  --> $DIR/non_expressive_names.rs:29:9
    |
 LL |     let ____1 = 1; //~ERROR Consider a more descriptive name
    |         ^^^^^
 
 error: consider choosing a more descriptive name
-  --> $DIR/non_expressive_names.rs:29:9
+  --> $DIR/non_expressive_names.rs:30:9
    |
 LL |     let __1___2 = 12; //~ERROR Consider a more descriptive name
    |         ^^^^^^^
 
 error: consider choosing a more descriptive name
-  --> $DIR/non_expressive_names.rs:49:13
+  --> $DIR/non_expressive_names.rs:51:13
    |
 LL |         let _1 = 1;
    |             ^^
 
 error: consider choosing a more descriptive name
-  --> $DIR/non_expressive_names.rs:50:13
+  --> $DIR/non_expressive_names.rs:52:13
    |
 LL |         let ____1 = 1;
    |             ^^^^^
 
 error: consider choosing a more descriptive name
-  --> $DIR/non_expressive_names.rs:51:13
+  --> $DIR/non_expressive_names.rs:53:13
    |
 LL |         let __1___2 = 12;
    |             ^^^^^^^
index 4077f1920a3837758a6f02f6f5b5ea8c6a2b078e..9cb6a9d1ecc9bc9e91c0cf071c748ab45a962711 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 // run-rustfix
 #![warn(clippy::option_if_let_else)]
 #![allow(clippy::redundant_closure, clippy::ref_option_ref, clippy::equatable_if_let)]
index 2f414e129d5a77c9952b88bd8e9efa5d0acc4249..b3ba5eb870a693e65053cf50bbc1c914520fbe4a 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 // run-rustfix
 #![warn(clippy::option_if_let_else)]
 #![allow(clippy::redundant_closure, clippy::ref_option_ref, clippy::equatable_if_let)]
index 803d941c36df8b2d8aa80ca7fa381ee8c35c780a..685bb48ea37bc05baf1945d6a66b7c12f69c0934 100644 (file)
@@ -1,5 +1,5 @@
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:7:5
+  --> $DIR/option_if_let_else.rs:6:5
    |
 LL | /     if let Some(x) = string {
 LL | |         (true, x)
@@ -11,19 +11,19 @@ LL | |     }
    = note: `-D clippy::option-if-let-else` implied by `-D warnings`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:25:13
+  --> $DIR/option_if_let_else.rs:24:13
    |
 LL |     let _ = if let Some(s) = *string { s.len() } else { 0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.map_or(0, |s| s.len())`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:26:13
+  --> $DIR/option_if_let_else.rs:25:13
    |
 LL |     let _ = if let Some(s) = &num { s } else { &0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:27:13
+  --> $DIR/option_if_let_else.rs:26:13
    |
 LL |       let _ = if let Some(s) = &mut num {
    |  _____________^
@@ -43,13 +43,13 @@ LL ~     });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:33:13
+  --> $DIR/option_if_let_else.rs:32:13
    |
 LL |     let _ = if let Some(ref s) = num { s } else { &0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:34:13
+  --> $DIR/option_if_let_else.rs:33:13
    |
 LL |       let _ = if let Some(mut s) = num {
    |  _____________^
@@ -69,7 +69,7 @@ LL ~     });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:40:13
+  --> $DIR/option_if_let_else.rs:39:13
    |
 LL |       let _ = if let Some(ref mut s) = num {
    |  _____________^
@@ -89,7 +89,7 @@ LL ~     });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:49:5
+  --> $DIR/option_if_let_else.rs:48:5
    |
 LL | /     if let Some(x) = arg {
 LL | |         let y = x * x;
@@ -108,7 +108,7 @@ LL +     })
    |
 
 error: use Option::map_or_else instead of an if let/else
-  --> $DIR/option_if_let_else.rs:62:13
+  --> $DIR/option_if_let_else.rs:61:13
    |
 LL |       let _ = if let Some(x) = arg {
    |  _____________^
@@ -120,7 +120,7 @@ LL | |     };
    | |_____^ help: try: `arg.map_or_else(|| side_effect(), |x| x)`
 
 error: use Option::map_or_else instead of an if let/else
-  --> $DIR/option_if_let_else.rs:71:13
+  --> $DIR/option_if_let_else.rs:70:13
    |
 LL |       let _ = if let Some(x) = arg {
    |  _____________^
@@ -143,13 +143,13 @@ LL ~     }, |x| x * x * x * x);
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:100:13
+  --> $DIR/option_if_let_else.rs:99:13
    |
 LL |     let _ = if let Some(x) = optional { x + 2 } else { 5 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:109:13
+  --> $DIR/option_if_let_else.rs:108:13
    |
 LL |       let _ = if let Some(x) = Some(0) {
    |  _____________^
@@ -171,13 +171,13 @@ LL ~         });
    |
 
 error: use Option::map_or_else instead of an if let/else
-  --> $DIR/option_if_let_else.rs:137:13
+  --> $DIR/option_if_let_else.rs:136:13
    |
 LL |     let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(0).map_or_else(|| s.len(), |x| s.len() + x)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:141:13
+  --> $DIR/option_if_let_else.rs:140:13
    |
 LL |       let _ = if let Some(x) = Some(0) {
    |  _____________^
index 3d3c19a1be5199e70c2a08f6c439aaca2e8a9645..e75eb1b6eadd85ca225d830e3cb8ffe96bf584fa 100644 (file)
@@ -1,6 +1,5 @@
 #![warn(clippy::panic_in_result_fn)]
 #![allow(clippy::unnecessary_wraps)]
-
 struct A;
 
 impl A {
index f56c2d03c664fb2d98448f7127c92acabb6b2bdc..78d09b8b2108a134b0c91a4c37e5bbd238de6387 100644 (file)
@@ -1,5 +1,5 @@
 error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
-  --> $DIR/panic_in_result_fn.rs:7:5
+  --> $DIR/panic_in_result_fn.rs:6: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!()`, `panic!()` or assertions 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:9:9
+  --> $DIR/panic_in_result_fn.rs:8:9
    |
 LL |         panic!("error");
    |         ^^^^^^^^^^^^^^^
-   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
-  --> $DIR/panic_in_result_fn.rs:12:5
+  --> $DIR/panic_in_result_fn.rs:11:5
    |
 LL | /     fn result_with_unimplemented() -> Result<bool, String> // should emit lint
 LL | |     {
@@ -27,14 +27,14 @@ LL | |     }
    |
    = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions 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:14:9
+  --> $DIR/panic_in_result_fn.rs:13:9
    |
 LL |         unimplemented!();
    |         ^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `unimplemented` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
-  --> $DIR/panic_in_result_fn.rs:17:5
+  --> $DIR/panic_in_result_fn.rs:16:5
    |
 LL | /     fn result_with_unreachable() -> Result<bool, String> // should emit lint
 LL | |     {
@@ -44,14 +44,14 @@ LL | |     }
    |
    = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions 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:19:9
+  --> $DIR/panic_in_result_fn.rs:18:9
    |
 LL |         unreachable!();
    |         ^^^^^^^^^^^^^^
    = note: this error originates in the macro `unreachable` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
-  --> $DIR/panic_in_result_fn.rs:22:5
+  --> $DIR/panic_in_result_fn.rs:21:5
    |
 LL | /     fn result_with_todo() -> Result<bool, String> // should emit lint
 LL | |     {
@@ -61,14 +61,14 @@ LL | |     }
    |
    = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions 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:24:9
+  --> $DIR/panic_in_result_fn.rs:23:9
    |
 LL |         todo!("Finish this");
    |         ^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
-  --> $DIR/panic_in_result_fn.rs:53:1
+  --> $DIR/panic_in_result_fn.rs:52:1
    |
 LL | / fn function_result_with_panic() -> Result<bool, String> // should emit lint
 LL | | {
@@ -78,14 +78,14 @@ LL | | }
    |
    = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions 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:55:5
+  --> $DIR/panic_in_result_fn.rs:54:5
    |
 LL |     panic!("error");
    |     ^^^^^^^^^^^^^^^
-   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
-  --> $DIR/panic_in_result_fn.rs:68:1
+  --> $DIR/panic_in_result_fn.rs:67:1
    |
 LL | / fn main() -> Result<(), String> {
 LL | |     todo!("finish main method");
@@ -95,7 +95,7 @@ LL | | }
    |
    = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions 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:69:5
+  --> $DIR/panic_in_result_fn.rs:68:5
    |
 LL |     todo!("finish main method");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 99e6d2aad8dd6b46ac5229da0866d36218688f0a..67bfef06a05e8cdd3e7b73c19fbc629d5e6fbf3e 100644 (file)
@@ -1,9 +1,4 @@
-#![allow(
-    unused,
-    clippy::many_single_char_names,
-    clippy::redundant_clone,
-    clippy::if_then_panic
-)]
+#![allow(unused, clippy::many_single_char_names, clippy::redundant_clone)]
 #![warn(clippy::ptr_arg)]
 
 use std::borrow::Cow;
@@ -160,3 +155,7 @@ fn foo_str(str: &PathBuf) {
         let _ = str.clone().clone();
     }
 }
+
+// No error for types behind an alias (#7699)
+type A = Vec<u8>;
+fn aliased(a: &A) {}
index 42183447ead737cf34275a3fe9be5edf01a406c4..64594eb870c2c5067b413095f6eabdeded968ebc 100644 (file)
@@ -1,5 +1,5 @@
 error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices
-  --> $DIR/ptr_arg.rs:12:14
+  --> $DIR/ptr_arg.rs:7:14
    |
 LL | fn do_vec(x: &Vec<i64>) {
    |              ^^^^^^^^^ help: change this to: `&[i64]`
@@ -7,25 +7,25 @@ LL | fn do_vec(x: &Vec<i64>) {
    = note: `-D clippy::ptr-arg` implied by `-D warnings`
 
 error: writing `&String` instead of `&str` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:21:14
+  --> $DIR/ptr_arg.rs:16:14
    |
 LL | fn do_str(x: &String) {
    |              ^^^^^^^ help: change this to: `&str`
 
 error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:30:15
+  --> $DIR/ptr_arg.rs:25:15
    |
 LL | fn do_path(x: &PathBuf) {
    |               ^^^^^^^^ help: change this to: `&Path`
 
 error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices
-  --> $DIR/ptr_arg.rs:43:18
+  --> $DIR/ptr_arg.rs:38:18
    |
 LL |     fn do_vec(x: &Vec<i64>);
    |                  ^^^^^^^^^ help: change this to: `&[i64]`
 
 error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices
-  --> $DIR/ptr_arg.rs:56:14
+  --> $DIR/ptr_arg.rs:51:14
    |
 LL | fn cloned(x: &Vec<u8>) -> Vec<u8> {
    |              ^^^^^^^^
@@ -44,7 +44,7 @@ LL |     x.to_owned()
    |
 
 error: writing `&String` instead of `&str` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:65:18
+  --> $DIR/ptr_arg.rs:60:18
    |
 LL | fn str_cloned(x: &String) -> String {
    |                  ^^^^^^^
@@ -67,7 +67,7 @@ LL |     x.to_string()
    |
 
 error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:73:19
+  --> $DIR/ptr_arg.rs:68:19
    |
 LL | fn path_cloned(x: &PathBuf) -> PathBuf {
    |                   ^^^^^^^^
@@ -90,7 +90,7 @@ LL |     x.to_path_buf()
    |
 
 error: writing `&String` instead of `&str` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:81:44
+  --> $DIR/ptr_arg.rs:76:44
    |
 LL | fn false_positive_capacity(x: &Vec<u8>, y: &String) {
    |                                            ^^^^^^^
@@ -109,13 +109,13 @@ LL |     let c = y;
    |             ~
 
 error: using a reference to `Cow` is not recommended
-  --> $DIR/ptr_arg.rs:95:25
+  --> $DIR/ptr_arg.rs:90:25
    |
 LL | fn test_cow_with_ref(c: &Cow<[i32]>) {}
    |                         ^^^^^^^^^^^ help: change this to: `&[i32]`
 
 error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices
-  --> $DIR/ptr_arg.rs:148:21
+  --> $DIR/ptr_arg.rs:143:21
    |
 LL |     fn foo_vec(vec: &Vec<u8>) {
    |                     ^^^^^^^^
@@ -134,7 +134,7 @@ LL |         let _ = vec.to_owned().clone();
    |                 ~~~~~~~~~~~~~~
 
 error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:153:23
+  --> $DIR/ptr_arg.rs:148:23
    |
 LL |     fn foo_path(path: &PathBuf) {
    |                       ^^^^^^^^
@@ -153,7 +153,7 @@ LL |         let _ = path.to_path_buf().clone();
    |                 ~~~~~~~~~~~~~~~~~~
 
 error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:158:21
+  --> $DIR/ptr_arg.rs:153:21
    |
 LL |     fn foo_str(str: &PathBuf) {
    |                     ^^^^^^^^
index ccb2e5a302e91590feb0ba2af50ae467e00e8115..e93469e5f556bd55737c0628961e540e7caf5be1 100644 (file)
@@ -104,7 +104,11 @@ fn func() -> Option<i32> {
     Some(0)
 }
 
-fn result_func(x: Result<i32, &str>) -> Result<i32, &str> {
+fn func_returning_result() -> Result<i32, i32> {
+    Ok(1)
+}
+
+fn result_func(x: Result<i32, i32>) -> Result<i32, i32> {
     let _ = x?;
 
     x?;
@@ -113,9 +117,22 @@ fn result_func(x: Result<i32, &str>) -> Result<i32, &str> {
     let y = if let Ok(x) = x {
         x
     } else {
-        return Err("some error");
+        return Err(0);
+    };
+
+    // issue #7859
+    // no warning
+    let _ = if let Ok(x) = func_returning_result() {
+        x
+    } else {
+        return Err(0);
     };
 
+    // no warning
+    if func_returning_result().is_err() {
+        return func_returning_result();
+    }
+
     Ok(y)
 }
 
index ca3722371f524b53b27ca94f15fd1a46e7d867ca..dd179e9bee8f87d57c6623617d0b646fb154c684 100644 (file)
@@ -134,7 +134,11 @@ fn f() -> Option<String> {
     Some(0)
 }
 
-fn result_func(x: Result<i32, &str>) -> Result<i32, &str> {
+fn func_returning_result() -> Result<i32, i32> {
+    Ok(1)
+}
+
+fn result_func(x: Result<i32, i32>) -> Result<i32, i32> {
     let _ = if let Ok(x) = x { x } else { return x };
 
     if x.is_err() {
@@ -145,9 +149,22 @@ fn result_func(x: Result<i32, &str>) -> Result<i32, &str> {
     let y = if let Ok(x) = x {
         x
     } else {
-        return Err("some error");
+        return Err(0);
+    };
+
+    // issue #7859
+    // no warning
+    let _ = if let Ok(x) = func_returning_result() {
+        x
+    } else {
+        return Err(0);
     };
 
+    // no warning
+    if func_returning_result().is_err() {
+        return func_returning_result();
+    }
+
     Ok(y)
 }
 
index 161588cb73cba06797561917e4ee5fe6fa3710d9..8d782b71dd6a47ae8368b0d8f8c7ba89b13b34b6 100644 (file)
@@ -101,13 +101,13 @@ LL | |     }
    | |_____^ help: replace it with: `f()?;`
 
 error: this if-let-else may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:138:13
+  --> $DIR/question_mark.rs:142:13
    |
 LL |     let _ = if let Ok(x) = x { x } else { return x };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x?`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:140:5
+  --> $DIR/question_mark.rs:144:5
    |
 LL | /     if x.is_err() {
 LL | |         return x;
index 2d711082746e73aab40867f0bcc2285137e5aca2..16b40dcd902869d7184cb1d6b384139166d04380 100644 (file)
@@ -196,7 +196,7 @@ fn clone_then_move_cloned() {
     fn foo<F: Fn()>(_: &Alpha, _: F) {}
     let x = Alpha;
     // ok, data is moved while the clone is in use.
-    foo(&x.clone(), move || {
+    foo(&x, move || {
         let _ = x;
     });
 
index fbc90493ae94b85986e8381ef82e395fbc202e9e..9f59017b26199cad1ae2acb9fe1b96c8048ac363 100644 (file)
@@ -167,5 +167,17 @@ note: cloned value is neither consumed nor mutated
 LL |     let y = x.clone().join("matthias");
    |             ^^^^^^^^^
 
-error: aborting due to 14 previous errors
+error: redundant clone
+  --> $DIR/redundant_clone.rs:199:11
+   |
+LL |     foo(&x.clone(), move || {
+   |           ^^^^^^^^ help: remove this
+   |
+note: this value is dropped without further use
+  --> $DIR/redundant_clone.rs:199:10
+   |
+LL |     foo(&x.clone(), move || {
+   |          ^
+
+error: aborting due to 15 previous errors
 
index 3dd365620ccbf1b4f4eef131819ce9da695f84dd..5649d8dd14c4899fde03e7a75d78bf5309aa4728 100644 (file)
@@ -15,5 +15,6 @@ fn main() {
     #[allow(clippy::needless_return)]
     (|| return 2)();
     (|| -> Option<i32> { None? })();
+    #[allow(clippy::try_err)]
     (|| -> Result<i32, i32> { Err(2)? })();
 }
index 737c8a9f8db43783313ab6d6fdfbfe0341709984..e8a6e940c01cdbebd76dfcceb066bafea11d97cc 100644 (file)
@@ -1,5 +1,5 @@
 #![warn(clippy::redundant_else)]
-#![allow(clippy::needless_return)]
+#![allow(clippy::needless_return, clippy::if_same_then_else)]
 
 fn main() {
     loop {
@@ -105,7 +105,7 @@ fn main() {
         1
     };
     // assign
-    let a;
+    let mut a;
     a = if foo() {
         return;
     } else {
index cd6db8ddc8864fd2a08de85ed9de26c8c31fd553..fe742a4c2f4c5acd69d1300242eb59bb0de67aa2 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 // FIXME: run-rustfix waiting on multi-span suggestions
 
 #![warn(clippy::ref_binding_to_reference)]
index eb36cd516a246a9e4f581b7079efb0bacc8cc09d..c5856e15fa987b3a4c19737019941430373606ce 100644 (file)
@@ -1,5 +1,5 @@
 error: this pattern creates a reference to a reference
-  --> $DIR/ref_binding_to_reference.rs:31:14
+  --> $DIR/ref_binding_to_reference.rs:30:14
    |
 LL |         Some(ref x) => x,
    |              ^^^^^
@@ -11,7 +11,7 @@ LL |         Some(x) => &x,
    |              ~     ~~
 
 error: this pattern creates a reference to a reference
-  --> $DIR/ref_binding_to_reference.rs:37:14
+  --> $DIR/ref_binding_to_reference.rs:36:14
    |
 LL |         Some(ref x) => {
    |              ^^^^^
@@ -25,7 +25,7 @@ LL ~             &x
    |
 
 error: this pattern creates a reference to a reference
-  --> $DIR/ref_binding_to_reference.rs:47:14
+  --> $DIR/ref_binding_to_reference.rs:46:14
    |
 LL |         Some(ref x) => m2!(x),
    |              ^^^^^
@@ -36,7 +36,7 @@ LL |         Some(x) => m2!(&x),
    |              ~         ~~
 
 error: this pattern creates a reference to a reference
-  --> $DIR/ref_binding_to_reference.rs:52:15
+  --> $DIR/ref_binding_to_reference.rs:51:15
    |
 LL |     let _ = |&ref x: &&String| {
    |               ^^^^^
@@ -48,7 +48,7 @@ LL ~         let _: &&String = &x;
    |
 
 error: this pattern creates a reference to a reference
-  --> $DIR/ref_binding_to_reference.rs:58:12
+  --> $DIR/ref_binding_to_reference.rs:57:12
    |
 LL | fn f2<'a>(&ref x: &&'a String) -> &'a String {
    |            ^^^^^
@@ -61,7 +61,7 @@ LL ~     x
    |
 
 error: this pattern creates a reference to a reference
-  --> $DIR/ref_binding_to_reference.rs:65:11
+  --> $DIR/ref_binding_to_reference.rs:64:11
    |
 LL |     fn f(&ref x: &&String) {
    |           ^^^^^
@@ -73,7 +73,7 @@ LL ~         let _: &&String = &x;
    |
 
 error: this pattern creates a reference to a reference
-  --> $DIR/ref_binding_to_reference.rs:73:11
+  --> $DIR/ref_binding_to_reference.rs:72:11
    |
 LL |     fn f(&ref x: &&String) {
    |           ^^^^^
index a66c2e587c8736111e067f1b2dd8a41d583840a5..cc295b509bc51973cd1bf3f03d591bee3bc732e3 100644 (file)
@@ -6,15 +6,58 @@
 #![allow(clippy::module_name_repetitions)]
 #![allow(clippy::new_without_default)]
 #![allow(clippy::redundant_static_lifetimes)]
+#![allow(clippy::bind_instead_of_map)]
+#![allow(clippy::box_collection)]
+#![allow(clippy::blocks_in_if_conditions)]
+#![allow(clippy::map_unwrap_or)]
+#![allow(clippy::unwrap_used)]
+#![allow(clippy::expect_used)]
+#![allow(clippy::for_loops_over_fallibles)]
+#![allow(clippy::useless_conversion)]
+#![allow(clippy::invisible_characters)]
+#![allow(clippy::single_char_add_str)]
+#![allow(clippy::match_result_ok)]
+// uplifted lints
+#![allow(invalid_value)]
+#![allow(array_into_iter)]
+#![allow(unused_labels)]
+#![allow(drop_bounds)]
+#![allow(temporary_cstring_as_ptr)]
+#![allow(non_fmt_panics)]
+#![allow(unknown_lints)]
+#![allow(invalid_atomic_ordering)]
+#![allow(enum_intrinsics_non_enums)]
 // warn for the old lint name here, to test if the renaming worked
+#![warn(clippy::module_name_repetitions)]
+#![warn(clippy::new_without_default)]
+#![warn(clippy::redundant_static_lifetimes)]
 #![warn(clippy::cognitive_complexity)]
+#![warn(clippy::bind_instead_of_map)]
+#![warn(clippy::box_collection)]
+#![warn(clippy::blocks_in_if_conditions)]
+#![warn(clippy::blocks_in_if_conditions)]
+#![warn(clippy::map_unwrap_or)]
+#![warn(clippy::map_unwrap_or)]
+#![warn(clippy::map_unwrap_or)]
+#![warn(clippy::unwrap_used)]
+#![warn(clippy::unwrap_used)]
+#![warn(clippy::expect_used)]
+#![warn(clippy::expect_used)]
+#![warn(clippy::for_loops_over_fallibles)]
+#![warn(clippy::for_loops_over_fallibles)]
+#![warn(clippy::useless_conversion)]
+#![warn(clippy::invisible_characters)]
+#![warn(clippy::single_char_add_str)]
+#![warn(clippy::match_result_ok)]
+// uplifted lints
+#![warn(invalid_value)]
+#![warn(array_into_iter)]
+#![warn(unused_labels)]
+#![warn(drop_bounds)]
+#![warn(temporary_cstring_as_ptr)]
+#![warn(non_fmt_panics)]
+#![warn(unknown_lints)]
+#![warn(invalid_atomic_ordering)]
 #![warn(enum_intrinsics_non_enums)]
 
-#[warn(clippy::module_name_repetitions)]
 fn main() {}
-
-#[warn(clippy::new_without_default)]
-struct Foo;
-
-#[warn(clippy::redundant_static_lifetimes)]
-fn foo() {}
index fa81201a2daf305fd675ddf65668882cdb842419..377075c02464a85becebae4817f176745f490ea0 100644 (file)
@@ -6,15 +6,58 @@
 #![allow(clippy::module_name_repetitions)]
 #![allow(clippy::new_without_default)]
 #![allow(clippy::redundant_static_lifetimes)]
+#![allow(clippy::bind_instead_of_map)]
+#![allow(clippy::box_collection)]
+#![allow(clippy::blocks_in_if_conditions)]
+#![allow(clippy::map_unwrap_or)]
+#![allow(clippy::unwrap_used)]
+#![allow(clippy::expect_used)]
+#![allow(clippy::for_loops_over_fallibles)]
+#![allow(clippy::useless_conversion)]
+#![allow(clippy::invisible_characters)]
+#![allow(clippy::single_char_add_str)]
+#![allow(clippy::match_result_ok)]
+// uplifted lints
+#![allow(invalid_value)]
+#![allow(array_into_iter)]
+#![allow(unused_labels)]
+#![allow(drop_bounds)]
+#![allow(temporary_cstring_as_ptr)]
+#![allow(non_fmt_panics)]
+#![allow(unknown_lints)]
+#![allow(invalid_atomic_ordering)]
+#![allow(enum_intrinsics_non_enums)]
 // warn for the old lint name here, to test if the renaming worked
+#![warn(clippy::stutter)]
+#![warn(clippy::new_without_default_derive)]
+#![warn(clippy::const_static_lifetime)]
 #![warn(clippy::cyclomatic_complexity)]
+#![warn(clippy::option_and_then_some)]
+#![warn(clippy::box_vec)]
+#![warn(clippy::block_in_if_condition_expr)]
+#![warn(clippy::block_in_if_condition_stmt)]
+#![warn(clippy::option_map_unwrap_or)]
+#![warn(clippy::option_map_unwrap_or_else)]
+#![warn(clippy::result_map_unwrap_or_else)]
+#![warn(clippy::option_unwrap_used)]
+#![warn(clippy::result_unwrap_used)]
+#![warn(clippy::option_expect_used)]
+#![warn(clippy::result_expect_used)]
+#![warn(clippy::for_loop_over_option)]
+#![warn(clippy::for_loop_over_result)]
+#![warn(clippy::identity_conversion)]
+#![warn(clippy::zero_width_space)]
+#![warn(clippy::single_char_push_str)]
+#![warn(clippy::if_let_some_result)]
+// uplifted lints
+#![warn(clippy::invalid_ref)]
+#![warn(clippy::into_iter_on_array)]
+#![warn(clippy::unused_label)]
+#![warn(clippy::drop_bounds)]
+#![warn(clippy::temporary_cstring_as_ptr)]
+#![warn(clippy::panic_params)]
+#![warn(clippy::unknown_clippy_lints)]
+#![warn(clippy::invalid_atomic_ordering)]
 #![warn(clippy::mem_discriminant_non_enum)]
 
-#[warn(clippy::stutter)]
 fn main() {}
-
-#[warn(clippy::new_without_default_derive)]
-struct Foo;
-
-#[warn(clippy::const_static_lifetime)]
-fn foo() {}
index 05c7854074c60cd3ba9291173c7c70421cf17ccf..d720f10d117c097ad2df27ae1ac45e9b63e971ee 100644 (file)
+error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
+  --> $DIR/rename.rs:31:9
+   |
+LL | #![warn(clippy::stutter)]
+   |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
+   |
+   = note: `-D renamed-and-removed-lints` implied by `-D warnings`
+
+error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
+  --> $DIR/rename.rs:32:9
+   |
+LL | #![warn(clippy::new_without_default_derive)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
+
+error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
+  --> $DIR/rename.rs:33:9
+   |
+LL | #![warn(clippy::const_static_lifetime)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
+
 error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
-  --> $DIR/rename.rs:10:9
+  --> $DIR/rename.rs:34:9
    |
 LL | #![warn(clippy::cyclomatic_complexity)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
+
+error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
+  --> $DIR/rename.rs:35:9
    |
-   = note: `-D renamed-and-removed-lints` implied by `-D warnings`
+LL | #![warn(clippy::option_and_then_some)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
 
-error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
-  --> $DIR/rename.rs:11:9
+error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
+  --> $DIR/rename.rs:36:9
    |
-LL | #![warn(clippy::mem_discriminant_non_enum)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
+LL | #![warn(clippy::box_vec)]
+   |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
 
-error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
-  --> $DIR/rename.rs:13:8
+error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
+  --> $DIR/rename.rs:37:9
    |
-LL | #[warn(clippy::stutter)]
-   |        ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
+LL | #![warn(clippy::block_in_if_condition_expr)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
-error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
-  --> $DIR/rename.rs:16:8
+error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
+  --> $DIR/rename.rs:38:9
    |
-LL | #[warn(clippy::new_without_default_derive)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
+LL | #![warn(clippy::block_in_if_condition_stmt)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
-error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
-  --> $DIR/rename.rs:19:8
+error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
+  --> $DIR/rename.rs:39:9
+   |
+LL | #![warn(clippy::option_map_unwrap_or)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
+
+error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
+  --> $DIR/rename.rs:40:9
+   |
+LL | #![warn(clippy::option_map_unwrap_or_else)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
+
+error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
+  --> $DIR/rename.rs:41:9
+   |
+LL | #![warn(clippy::result_map_unwrap_or_else)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
+
+error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
+  --> $DIR/rename.rs:42:9
+   |
+LL | #![warn(clippy::option_unwrap_used)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
+
+error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
+  --> $DIR/rename.rs:43:9
+   |
+LL | #![warn(clippy::result_unwrap_used)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
+
+error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
+  --> $DIR/rename.rs:44:9
+   |
+LL | #![warn(clippy::option_expect_used)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
+
+error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
+  --> $DIR/rename.rs:45:9
+   |
+LL | #![warn(clippy::result_expect_used)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
+
+error: lint `clippy::for_loop_over_option` has been renamed to `clippy::for_loops_over_fallibles`
+  --> $DIR/rename.rs:46:9
+   |
+LL | #![warn(clippy::for_loop_over_option)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::for_loops_over_fallibles`
+
+error: lint `clippy::for_loop_over_result` has been renamed to `clippy::for_loops_over_fallibles`
+  --> $DIR/rename.rs:47:9
+   |
+LL | #![warn(clippy::for_loop_over_result)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::for_loops_over_fallibles`
+
+error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
+  --> $DIR/rename.rs:48:9
+   |
+LL | #![warn(clippy::identity_conversion)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
+
+error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
+  --> $DIR/rename.rs:49:9
+   |
+LL | #![warn(clippy::zero_width_space)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
+
+error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
+  --> $DIR/rename.rs:50:9
+   |
+LL | #![warn(clippy::single_char_push_str)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
+
+error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
+  --> $DIR/rename.rs:51:9
+   |
+LL | #![warn(clippy::if_let_some_result)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
+
+error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
+  --> $DIR/rename.rs:53:9
+   |
+LL | #![warn(clippy::invalid_ref)]
+   |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
+
+error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
+  --> $DIR/rename.rs:54:9
+   |
+LL | #![warn(clippy::into_iter_on_array)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
+
+error: lint `clippy::unused_label` has been renamed to `unused_labels`
+  --> $DIR/rename.rs:55:9
+   |
+LL | #![warn(clippy::unused_label)]
+   |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
+
+error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
+  --> $DIR/rename.rs:56:9
+   |
+LL | #![warn(clippy::drop_bounds)]
+   |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
+
+error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
+  --> $DIR/rename.rs:57:9
+   |
+LL | #![warn(clippy::temporary_cstring_as_ptr)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
+
+error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
+  --> $DIR/rename.rs:58:9
+   |
+LL | #![warn(clippy::panic_params)]
+   |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
+
+error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
+  --> $DIR/rename.rs:59:9
+   |
+LL | #![warn(clippy::unknown_clippy_lints)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
+
+error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
+  --> $DIR/rename.rs:60:9
+   |
+LL | #![warn(clippy::invalid_atomic_ordering)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
+
+error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
+  --> $DIR/rename.rs:61:9
    |
-LL | #[warn(clippy::const_static_lifetime)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
+LL | #![warn(clippy::mem_discriminant_non_enum)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
 
-error: aborting due to 5 previous errors
+error: aborting due to 30 previous errors
 
index a7f8f54f2be04cb98667127b87d3db75c50e1301..d7e8d02bd1998fbab6b24867d1ec325556a6e72f 100644 (file)
@@ -1,5 +1,3 @@
-// edition:2018
-
 #![warn(clippy::all, clippy::pedantic)]
 #![allow(
     clippy::missing_errors_doc,
index 69a3390b03b0b2cac0988e1f35dc1796e0bcd41d..ea962f943173aed4359f392e9ee99de13e9b8ec4 100644 (file)
@@ -1,5 +1,3 @@
-// edition:2018
-
 #![warn(clippy::all, clippy::pedantic)]
 #![allow(
     clippy::missing_errors_doc,
index 86c63946516ce84453725eff5a31b58cb1ac246c..bf8b47d5626d283095c5df5db7ed86cccc2ffb40 100644 (file)
@@ -1,5 +1,5 @@
 error: method `add` can be confused for the standard trait method `std::ops::Add::add`
-  --> $DIR/method_list_1.rs:26:5
+  --> $DIR/method_list_1.rs:24:5
    |
 LL | /     pub fn add(self, other: T) -> T {
 LL | |         unimplemented!()
@@ -10,7 +10,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Add` or choosing a less ambiguous method name
 
 error: method `as_mut` can be confused for the standard trait method `std::convert::AsMut::as_mut`
-  --> $DIR/method_list_1.rs:30:5
+  --> $DIR/method_list_1.rs:28:5
    |
 LL | /     pub fn as_mut(&mut self) -> &mut T {
 LL | |         unimplemented!()
@@ -20,7 +20,7 @@ LL | |     }
    = help: consider implementing the trait `std::convert::AsMut` or choosing a less ambiguous method name
 
 error: method `as_ref` can be confused for the standard trait method `std::convert::AsRef::as_ref`
-  --> $DIR/method_list_1.rs:34:5
+  --> $DIR/method_list_1.rs:32:5
    |
 LL | /     pub fn as_ref(&self) -> &T {
 LL | |         unimplemented!()
@@ -30,7 +30,7 @@ LL | |     }
    = help: consider implementing the trait `std::convert::AsRef` or choosing a less ambiguous method name
 
 error: method `bitand` can be confused for the standard trait method `std::ops::BitAnd::bitand`
-  --> $DIR/method_list_1.rs:38:5
+  --> $DIR/method_list_1.rs:36:5
    |
 LL | /     pub fn bitand(self, rhs: T) -> T {
 LL | |         unimplemented!()
@@ -40,7 +40,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::BitAnd` or choosing a less ambiguous method name
 
 error: method `bitor` can be confused for the standard trait method `std::ops::BitOr::bitor`
-  --> $DIR/method_list_1.rs:42:5
+  --> $DIR/method_list_1.rs:40:5
    |
 LL | /     pub fn bitor(self, rhs: Self) -> Self {
 LL | |         unimplemented!()
@@ -50,7 +50,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::BitOr` or choosing a less ambiguous method name
 
 error: method `bitxor` can be confused for the standard trait method `std::ops::BitXor::bitxor`
-  --> $DIR/method_list_1.rs:46:5
+  --> $DIR/method_list_1.rs:44:5
    |
 LL | /     pub fn bitxor(self, rhs: Self) -> Self {
 LL | |         unimplemented!()
@@ -60,7 +60,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::BitXor` or choosing a less ambiguous method name
 
 error: method `borrow` can be confused for the standard trait method `std::borrow::Borrow::borrow`
-  --> $DIR/method_list_1.rs:50:5
+  --> $DIR/method_list_1.rs:48:5
    |
 LL | /     pub fn borrow(&self) -> &str {
 LL | |         unimplemented!()
@@ -70,7 +70,7 @@ LL | |     }
    = help: consider implementing the trait `std::borrow::Borrow` or choosing a less ambiguous method name
 
 error: method `borrow_mut` can be confused for the standard trait method `std::borrow::BorrowMut::borrow_mut`
-  --> $DIR/method_list_1.rs:54:5
+  --> $DIR/method_list_1.rs:52:5
    |
 LL | /     pub fn borrow_mut(&mut self) -> &mut str {
 LL | |         unimplemented!()
@@ -80,7 +80,7 @@ LL | |     }
    = help: consider implementing the trait `std::borrow::BorrowMut` or choosing a less ambiguous method name
 
 error: method `clone` can be confused for the standard trait method `std::clone::Clone::clone`
-  --> $DIR/method_list_1.rs:58:5
+  --> $DIR/method_list_1.rs:56:5
    |
 LL | /     pub fn clone(&self) -> Self {
 LL | |         unimplemented!()
@@ -90,7 +90,7 @@ LL | |     }
    = help: consider implementing the trait `std::clone::Clone` or choosing a less ambiguous method name
 
 error: method `cmp` can be confused for the standard trait method `std::cmp::Ord::cmp`
-  --> $DIR/method_list_1.rs:62:5
+  --> $DIR/method_list_1.rs:60:5
    |
 LL | /     pub fn cmp(&self, other: &Self) -> Self {
 LL | |         unimplemented!()
@@ -100,7 +100,7 @@ LL | |     }
    = help: consider implementing the trait `std::cmp::Ord` or choosing a less ambiguous method name
 
 error: method `deref` can be confused for the standard trait method `std::ops::Deref::deref`
-  --> $DIR/method_list_1.rs:70:5
+  --> $DIR/method_list_1.rs:68:5
    |
 LL | /     pub fn deref(&self) -> &Self {
 LL | |         unimplemented!()
@@ -110,7 +110,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Deref` or choosing a less ambiguous method name
 
 error: method `deref_mut` can be confused for the standard trait method `std::ops::DerefMut::deref_mut`
-  --> $DIR/method_list_1.rs:74:5
+  --> $DIR/method_list_1.rs:72:5
    |
 LL | /     pub fn deref_mut(&mut self) -> &mut Self {
 LL | |         unimplemented!()
@@ -120,7 +120,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::DerefMut` or choosing a less ambiguous method name
 
 error: method `div` can be confused for the standard trait method `std::ops::Div::div`
-  --> $DIR/method_list_1.rs:78:5
+  --> $DIR/method_list_1.rs:76:5
    |
 LL | /     pub fn div(self, rhs: Self) -> Self {
 LL | |         unimplemented!()
@@ -130,7 +130,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Div` or choosing a less ambiguous method name
 
 error: method `drop` can be confused for the standard trait method `std::ops::Drop::drop`
-  --> $DIR/method_list_1.rs:82:5
+  --> $DIR/method_list_1.rs:80:5
    |
 LL | /     pub fn drop(&mut self) {
 LL | |         unimplemented!()
index 2cdc1a06fe689dab34e495eee9466253e7836c8d..b663568806d218dd9e8ac3bb6d2206acad140550 100644 (file)
@@ -1,5 +1,3 @@
-// edition:2018
-
 #![warn(clippy::all, clippy::pedantic)]
 #![allow(
     clippy::missing_errors_doc,
index 0142e2991081c79ae4099788ea6c85ed02535428..426fe3b1adc9de12e9ba88e9f51a034407d6d007 100644 (file)
@@ -1,5 +1,5 @@
 error: method `eq` can be confused for the standard trait method `std::cmp::PartialEq::eq`
-  --> $DIR/method_list_2.rs:27:5
+  --> $DIR/method_list_2.rs:25:5
    |
 LL | /     pub fn eq(&self, other: &Self) -> bool {
 LL | |         unimplemented!()
@@ -10,7 +10,7 @@ LL | |     }
    = help: consider implementing the trait `std::cmp::PartialEq` or choosing a less ambiguous method name
 
 error: method `from_iter` can be confused for the standard trait method `std::iter::FromIterator::from_iter`
-  --> $DIR/method_list_2.rs:31:5
+  --> $DIR/method_list_2.rs:29:5
    |
 LL | /     pub fn from_iter<T>(iter: T) -> Self {
 LL | |         unimplemented!()
@@ -20,7 +20,7 @@ LL | |     }
    = help: consider implementing the trait `std::iter::FromIterator` or choosing a less ambiguous method name
 
 error: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`
-  --> $DIR/method_list_2.rs:35:5
+  --> $DIR/method_list_2.rs:33:5
    |
 LL | /     pub fn from_str(s: &str) -> Result<Self, Self> {
 LL | |         unimplemented!()
@@ -30,7 +30,7 @@ LL | |     }
    = help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name
 
 error: method `hash` can be confused for the standard trait method `std::hash::Hash::hash`
-  --> $DIR/method_list_2.rs:39:5
+  --> $DIR/method_list_2.rs:37:5
    |
 LL | /     pub fn hash(&self, state: &mut T) {
 LL | |         unimplemented!()
@@ -40,7 +40,7 @@ LL | |     }
    = help: consider implementing the trait `std::hash::Hash` or choosing a less ambiguous method name
 
 error: method `index` can be confused for the standard trait method `std::ops::Index::index`
-  --> $DIR/method_list_2.rs:43:5
+  --> $DIR/method_list_2.rs:41:5
    |
 LL | /     pub fn index(&self, index: usize) -> &Self {
 LL | |         unimplemented!()
@@ -50,7 +50,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Index` or choosing a less ambiguous method name
 
 error: method `index_mut` can be confused for the standard trait method `std::ops::IndexMut::index_mut`
-  --> $DIR/method_list_2.rs:47:5
+  --> $DIR/method_list_2.rs:45:5
    |
 LL | /     pub fn index_mut(&mut self, index: usize) -> &mut Self {
 LL | |         unimplemented!()
@@ -60,7 +60,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::IndexMut` or choosing a less ambiguous method name
 
 error: method `into_iter` can be confused for the standard trait method `std::iter::IntoIterator::into_iter`
-  --> $DIR/method_list_2.rs:51:5
+  --> $DIR/method_list_2.rs:49:5
    |
 LL | /     pub fn into_iter(self) -> Self {
 LL | |         unimplemented!()
@@ -70,7 +70,7 @@ LL | |     }
    = help: consider implementing the trait `std::iter::IntoIterator` or choosing a less ambiguous method name
 
 error: method `mul` can be confused for the standard trait method `std::ops::Mul::mul`
-  --> $DIR/method_list_2.rs:55:5
+  --> $DIR/method_list_2.rs:53:5
    |
 LL | /     pub fn mul(self, rhs: Self) -> Self {
 LL | |         unimplemented!()
@@ -80,7 +80,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Mul` or choosing a less ambiguous method name
 
 error: method `neg` can be confused for the standard trait method `std::ops::Neg::neg`
-  --> $DIR/method_list_2.rs:59:5
+  --> $DIR/method_list_2.rs:57:5
    |
 LL | /     pub fn neg(self) -> Self {
 LL | |         unimplemented!()
@@ -90,7 +90,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Neg` or choosing a less ambiguous method name
 
 error: method `next` can be confused for the standard trait method `std::iter::Iterator::next`
-  --> $DIR/method_list_2.rs:63:5
+  --> $DIR/method_list_2.rs:61:5
    |
 LL | /     pub fn next(&mut self) -> Option<Self> {
 LL | |         unimplemented!()
@@ -100,7 +100,7 @@ LL | |     }
    = help: consider implementing the trait `std::iter::Iterator` or choosing a less ambiguous method name
 
 error: method `not` can be confused for the standard trait method `std::ops::Not::not`
-  --> $DIR/method_list_2.rs:67:5
+  --> $DIR/method_list_2.rs:65:5
    |
 LL | /     pub fn not(self) -> Self {
 LL | |         unimplemented!()
@@ -110,7 +110,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Not` or choosing a less ambiguous method name
 
 error: method `rem` can be confused for the standard trait method `std::ops::Rem::rem`
-  --> $DIR/method_list_2.rs:71:5
+  --> $DIR/method_list_2.rs:69:5
    |
 LL | /     pub fn rem(self, rhs: Self) -> Self {
 LL | |         unimplemented!()
@@ -120,7 +120,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Rem` or choosing a less ambiguous method name
 
 error: method `shl` can be confused for the standard trait method `std::ops::Shl::shl`
-  --> $DIR/method_list_2.rs:75:5
+  --> $DIR/method_list_2.rs:73:5
    |
 LL | /     pub fn shl(self, rhs: Self) -> Self {
 LL | |         unimplemented!()
@@ -130,7 +130,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Shl` or choosing a less ambiguous method name
 
 error: method `shr` can be confused for the standard trait method `std::ops::Shr::shr`
-  --> $DIR/method_list_2.rs:79:5
+  --> $DIR/method_list_2.rs:77:5
    |
 LL | /     pub fn shr(self, rhs: Self) -> Self {
 LL | |         unimplemented!()
@@ -140,7 +140,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Shr` or choosing a less ambiguous method name
 
 error: method `sub` can be confused for the standard trait method `std::ops::Sub::sub`
-  --> $DIR/method_list_2.rs:83:5
+  --> $DIR/method_list_2.rs:81:5
    |
 LL | /     pub fn sub(self, rhs: Self) -> Self {
 LL | |         unimplemented!()
index daa073414577c8bfd897f37fe8b9a944eb063fe3..76f6ce9ee6b47f3826824a35e2495c0513d80c23 100644 (file)
@@ -1,5 +1,10 @@
 #![warn(clippy::similar_names)]
-#![allow(unused, clippy::println_empty_string)]
+#![allow(
+    unused,
+    clippy::println_empty_string,
+    clippy::empty_loop,
+    clippy::diverging_sub_expression
+)]
 
 struct Foo {
     apple: i32,
index f621595abaea2ee295423dbcb04b990f63b7184c..faf572b0c6bc27010c8af554b37cd863e295ab2a 100644 (file)
@@ -1,84 +1,84 @@
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:15:9
+  --> $DIR/similar_names.rs:20:9
    |
 LL |     let bpple: i32;
    |         ^^^^^
    |
    = note: `-D clippy::similar-names` implied by `-D warnings`
 note: existing binding defined here
-  --> $DIR/similar_names.rs:13:9
+  --> $DIR/similar_names.rs:18:9
    |
 LL |     let apple: i32;
    |         ^^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:17:9
+  --> $DIR/similar_names.rs:22:9
    |
 LL |     let cpple: i32;
    |         ^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:13:9
+  --> $DIR/similar_names.rs:18:9
    |
 LL |     let apple: i32;
    |         ^^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:41:9
+  --> $DIR/similar_names.rs:46:9
    |
 LL |     let bluby: i32;
    |         ^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:40:9
+  --> $DIR/similar_names.rs:45:9
    |
 LL |     let blubx: i32;
    |         ^^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:45:9
+  --> $DIR/similar_names.rs:50:9
    |
 LL |     let coke: i32;
    |         ^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:43:9
+  --> $DIR/similar_names.rs:48:9
    |
 LL |     let cake: i32;
    |         ^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:63:9
+  --> $DIR/similar_names.rs:68:9
    |
 LL |     let xyzeabc: i32;
    |         ^^^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:61:9
+  --> $DIR/similar_names.rs:66:9
    |
 LL |     let xyz1abc: i32;
    |         ^^^^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:67:9
+  --> $DIR/similar_names.rs:72:9
    |
 LL |     let parsee: i32;
    |         ^^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:65:9
+  --> $DIR/similar_names.rs:70:9
    |
 LL |     let parser: i32;
    |         ^^^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:88:16
+  --> $DIR/similar_names.rs:93:16
    |
 LL |         bpple: sprang,
    |                ^^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:87:16
+  --> $DIR/similar_names.rs:92:16
    |
 LL |         apple: spring,
    |                ^^^^^^
index f66b445b7b6a35249600338185df6d6bb7774bb6..4c40739d6f553874865157ad7c9cb06a1051ea0a 100644 (file)
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 #![warn(clippy::single_component_path_imports)]
 #![allow(unused_imports)]
 
index 09d4865859584ed792063e9e6bb510a1b679c012..9280bab3c71b5cae19b6d4f7e57b47bb7a5a478f 100644 (file)
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 #![warn(clippy::single_component_path_imports)]
 #![allow(unused_imports)]
 
index 7005fa8f125d36255c12bf6c8b93cf6644f64eba..509c88ac256a8c0dc99ecdbcac0a8dd6fe97529f 100644 (file)
@@ -1,5 +1,5 @@
 error: this import is redundant
-  --> $DIR/single_component_path_imports.rs:24:5
+  --> $DIR/single_component_path_imports.rs:23:5
    |
 LL |     use regex;
    |     ^^^^^^^^^^ help: remove it entirely
@@ -7,7 +7,7 @@ LL |     use regex;
    = note: `-D clippy::single-component-path-imports` implied by `-D warnings`
 
 error: this import is redundant
-  --> $DIR/single_component_path_imports.rs:6:1
+  --> $DIR/single_component_path_imports.rs:5:1
    |
 LL | use regex;
    | ^^^^^^^^^^ help: remove it entirely
index 05863f9a2bf488c06722209622ceae63cce12de7..e43f5d381aaa1087a928a49d86529693a74fdba9 100644 (file)
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 #![warn(clippy::single_component_path_imports)]
 #![allow(unused_imports)]
 
index 633deea348b81d415778fc372cae9a720c5c5ffc..3c65ca3054c6919eb859317608a43151ea71eb5c 100644 (file)
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 #![warn(clippy::single_component_path_imports)]
 #![allow(unused_imports)]
 
index 239efb393b1ab4ac058a959ebe323044cad662f1..37d5176129ff30a2d06733b35c2b2c9b5404574f 100644 (file)
@@ -1,5 +1,5 @@
 error: this import is redundant
-  --> $DIR/single_component_path_imports_macro.rs:16:1
+  --> $DIR/single_component_path_imports_macro.rs:15:1
    |
 LL | use m2; // fail
    | ^^^^^^^ help: remove it entirely
index 94117061b270da718a68172b91b920c1c18c434b..c75beb747861882c0a158a46a92b67ca5af5af6e 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::single_component_path_imports)]
 #![allow(unused_imports)]
 
index 0c3256c1ce43a71ea37159b4a65991603e493a59..cf990be1b9ff1cea7a0efe5c9509652b1a1ec271 100644 (file)
@@ -1,5 +1,5 @@
 error: this import is redundant
-  --> $DIR/single_component_path_imports_nested_first.rs:14:10
+  --> $DIR/single_component_path_imports_nested_first.rs:13:10
    |
 LL |     use {regex, serde};
    |          ^^^^^
@@ -8,7 +8,7 @@ LL |     use {regex, serde};
    = help: remove this import
 
 error: this import is redundant
-  --> $DIR/single_component_path_imports_nested_first.rs:14:17
+  --> $DIR/single_component_path_imports_nested_first.rs:13:17
    |
 LL |     use {regex, serde};
    |                 ^^^^^
@@ -16,7 +16,7 @@ LL |     use {regex, serde};
    = help: remove this import
 
 error: this import is redundant
-  --> $DIR/single_component_path_imports_nested_first.rs:5:1
+  --> $DIR/single_component_path_imports_nested_first.rs:4:1
    |
 LL | use regex;
    | ^^^^^^^^^^ help: remove it entirely
index 94319ade0ac4b9672ad2064bab6844db2e634887..48e8e530261bea39d8b1586d2f60cde8233ee65a 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::single_component_path_imports)]
 #![allow(unused_imports)]
 
index c7437b234566a95f08dd4794f7cecc2af1430adf..4fb0cf40b6e00d40bb2c0345a28457af33695442 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::single_component_path_imports)]
 #![allow(unused_imports)]
 
diff --git a/src/tools/clippy/tests/ui/string_slice.rs b/src/tools/clippy/tests/ui/string_slice.rs
new file mode 100644 (file)
index 0000000..be4dfc8
--- /dev/null
@@ -0,0 +1,10 @@
+#[warn(clippy::string_slice)]
+#[allow(clippy::no_effect)]
+
+fn main() {
+    &"Ölkanne"[1..];
+    let m = "Mötörhead";
+    &m[2..5];
+    let s = String::from(m);
+    &s[0..2];
+}
diff --git a/src/tools/clippy/tests/ui/string_slice.stderr b/src/tools/clippy/tests/ui/string_slice.stderr
new file mode 100644 (file)
index 0000000..55040bf
--- /dev/null
@@ -0,0 +1,22 @@
+error: indexing into a string may panic if the index is within a UTF-8 character
+  --> $DIR/string_slice.rs:5:6
+   |
+LL |     &"Ölkanne"[1..];
+   |      ^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::string-slice` implied by `-D warnings`
+
+error: indexing into a string may panic if the index is within a UTF-8 character
+  --> $DIR/string_slice.rs:7:6
+   |
+LL |     &m[2..5];
+   |      ^^^^^^^
+
+error: indexing into a string may panic if the index is within a UTF-8 character
+  --> $DIR/string_slice.rs:9:6
+   |
+LL |     &s[0..2];
+   |      ^^^^^^^
+
+error: aborting due to 3 previous errors
+
index be8bc22bf98a05d062caff083c4c6e1d1d903c85..fcd827a91c7f62d843bfd47a30016a58e9dbbf2d 100644 (file)
@@ -1,6 +1,7 @@
 // aux-build:proc_macro_suspicious_else_formatting.rs
 
 #![warn(clippy::suspicious_else_formatting)]
+#![allow(clippy::if_same_then_else)]
 
 extern crate proc_macro_suspicious_else_formatting;
 use proc_macro_suspicious_else_formatting::DeriveBadSpan;
index d1db195cbb8787bc0003738f2f2c1e37adbf7fe3..ee68eb5a791c45d5ea2c5c3ab4edc2fe8810fc35 100644 (file)
@@ -1,5 +1,5 @@
 error: this looks like an `else {..}` but the `else` is missing
-  --> $DIR/suspicious_else_formatting.rs:16:6
+  --> $DIR/suspicious_else_formatting.rs:17:6
    |
 LL |     } {
    |      ^
@@ -8,7 +8,7 @@ LL |     } {
    = note: to remove this lint, add the missing `else` or add a new line before the next block
 
 error: this looks like an `else if` but the `else` is missing
-  --> $DIR/suspicious_else_formatting.rs:20:6
+  --> $DIR/suspicious_else_formatting.rs:21:6
    |
 LL |     } if foo() {
    |      ^
@@ -16,7 +16,7 @@ LL |     } if foo() {
    = note: to remove this lint, add the missing `else` or add a new line before the second `if`
 
 error: this looks like an `else if` but the `else` is missing
-  --> $DIR/suspicious_else_formatting.rs:27:10
+  --> $DIR/suspicious_else_formatting.rs:28:10
    |
 LL |         } if foo() {
    |          ^
@@ -24,7 +24,7 @@ LL |         } if foo() {
    = note: to remove this lint, add the missing `else` or add a new line before the second `if`
 
 error: this looks like an `else if` but the `else` is missing
-  --> $DIR/suspicious_else_formatting.rs:35:10
+  --> $DIR/suspicious_else_formatting.rs:36:10
    |
 LL |         } if foo() {
    |          ^
@@ -32,7 +32,7 @@ LL |         } if foo() {
    = note: to remove this lint, add the missing `else` or add a new line before the second `if`
 
 error: this is an `else {..}` but the formatting might hide it
-  --> $DIR/suspicious_else_formatting.rs:44:6
+  --> $DIR/suspicious_else_formatting.rs:45:6
    |
 LL |       } else
    |  ______^
@@ -42,7 +42,7 @@ LL | |     {
    = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}`
 
 error: this is an `else if` but the formatting might hide it
-  --> $DIR/suspicious_else_formatting.rs:56:6
+  --> $DIR/suspicious_else_formatting.rs:57:6
    |
 LL |       } else
    |  ______^
@@ -52,7 +52,7 @@ LL | |     if foo() { // the span of the above error should continue here
    = note: to remove this lint, remove the `else` or remove the new line between `else` and `if`
 
 error: this is an `else if` but the formatting might hide it
-  --> $DIR/suspicious_else_formatting.rs:61:6
+  --> $DIR/suspicious_else_formatting.rs:62:6
    |
 LL |       }
    |  ______^
@@ -63,7 +63,7 @@ LL | |     if foo() { // the span of the above error should continue here
    = note: to remove this lint, remove the `else` or remove the new line between `else` and `if`
 
 error: this is an `else {..}` but the formatting might hide it
-  --> $DIR/suspicious_else_formatting.rs:88:6
+  --> $DIR/suspicious_else_formatting.rs:89:6
    |
 LL |       }
    |  ______^
@@ -75,7 +75,7 @@ LL | |     {
    = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}`
 
 error: this is an `else {..}` but the formatting might hide it
-  --> $DIR/suspicious_else_formatting.rs:96:6
+  --> $DIR/suspicious_else_formatting.rs:97:6
    |
 LL |       }
    |  ______^
index 2f8c7cec50f8ec47f1802a554e3d381a859ba3a3..3201d5de0f35620663dea65c8903b481d8ac9eb6 100644 (file)
@@ -1,4 +1,5 @@
 #![warn(clippy::suspicious_operation_groupings)]
+#![allow(clippy::eq_op)]
 
 struct Vec3 {
     x: f64,
@@ -187,7 +188,7 @@ fn inside_fn_with_similar_expression(s1: &S, s2: &S, strict: bool) -> bool {
     }
 }
 
-fn inside_an_if_statement(s1: &S, s2: &S) {
+fn inside_an_if_statement(s1: &mut S, s2: &S) {
     // There's no `s1.b`
     if s1.a < s2.a && s1.a < s2.b {
         s1.c = s2.c;
index dd6f2f6641d678b14b1d401fac951d98ce43f913..baf9bc74b000ec30468a9e08112d1decaed61346 100644 (file)
@@ -1,5 +1,5 @@
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:14:9
+  --> $DIR/suspicious_operation_groupings.rs:15:9
    |
 LL |         self.x == other.y && self.y == other.y && self.z == other.z
    |         ^^^^^^^^^^^^^^^^^ help: did you mean: `self.x == other.x`
@@ -7,151 +7,151 @@ LL |         self.x == other.y && self.y == other.y && self.z == other.z
    = note: `-D clippy::suspicious-operation-groupings` implied by `-D warnings`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:27:20
+  --> $DIR/suspicious_operation_groupings.rs:28:20
    |
 LL |     s1.a < s2.a && s1.a < s2.b
    |                    ^^^^^^^^^^^ help: did you mean: `s1.b < s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:75:33
+  --> $DIR/suspicious_operation_groupings.rs:76:33
    |
 LL |     s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d
    |                                 ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:80:19
+  --> $DIR/suspicious_operation_groupings.rs:81:19
    |
 LL |     s1.a * s2.a + s1.b * s2.c + s1.c * s2.c
    |                   ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:80:19
+  --> $DIR/suspicious_operation_groupings.rs:81:19
    |
 LL |     s1.a * s2.a + s1.b * s2.c + s1.c * s2.c
    |                   ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:85:19
+  --> $DIR/suspicious_operation_groupings.rs:86:19
    |
 LL |     s1.a * s2.a + s2.b * s2.b + s1.c * s2.c
    |                   ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:90:19
+  --> $DIR/suspicious_operation_groupings.rs:91:19
    |
 LL |     s1.a * s2.a + s1.b * s1.b + s1.c * s2.c
    |                   ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:95:5
+  --> $DIR/suspicious_operation_groupings.rs:96:5
    |
 LL |     s1.a * s1.a + s1.b * s2.b + s1.c * s2.c
    |     ^^^^^^^^^^^ help: did you mean: `s1.a * s2.a`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:100:33
+  --> $DIR/suspicious_operation_groupings.rs:101:33
    |
 LL |     s1.a * s2.a + s1.b * s2.b + s1.c * s1.c
    |                                 ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:113:20
+  --> $DIR/suspicious_operation_groupings.rs:114:20
    |
 LL |     (s1.a * s2.a + s1.b * s1.b)
    |                    ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:118:34
+  --> $DIR/suspicious_operation_groupings.rs:119:34
    |
 LL |     (s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d)
    |                                  ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:123:38
+  --> $DIR/suspicious_operation_groupings.rs:124:38
    |
 LL |     (s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)
    |                                      ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:128:39
+  --> $DIR/suspicious_operation_groupings.rs:129:39
    |
 LL |     ((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d))
    |                                       ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:133:42
+  --> $DIR/suspicious_operation_groupings.rs:134:42
    |
 LL |     (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d)))
    |                                          ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:133:42
+  --> $DIR/suspicious_operation_groupings.rs:134:42
    |
 LL |     (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d)))
    |                                          ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:138:40
+  --> $DIR/suspicious_operation_groupings.rs:139:40
    |
 LL |     (((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b)) + (s1.d * s2.d))
    |                                        ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:143:40
+  --> $DIR/suspicious_operation_groupings.rs:144:40
    |
 LL |     ((s1.a * s2.a) + ((s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)))
    |                                        ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:148:20
+  --> $DIR/suspicious_operation_groupings.rs:149:20
    |
 LL |     (s1.a * s2.a + s2.b * s2.b) / 2
    |                    ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:153:35
+  --> $DIR/suspicious_operation_groupings.rs:154:35
    |
 LL |     i32::swap_bytes(s1.a * s2.a + s2.b * s2.b)
    |                                   ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:158:29
+  --> $DIR/suspicious_operation_groupings.rs:159:29
    |
 LL |     s1.a > 0 && s1.b > 0 && s1.d == s2.c && s1.d == s2.d
    |                             ^^^^^^^^^^^^ help: did you mean: `s1.c == s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:163:17
+  --> $DIR/suspicious_operation_groupings.rs:164:17
    |
 LL |     s1.a > 0 && s1.d == s2.c && s1.b > 0 && s1.d == s2.d
    |                 ^^^^^^^^^^^^ help: did you mean: `s1.c == s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:172:77
+  --> $DIR/suspicious_operation_groupings.rs:173:77
    |
 LL |     (n1.inner.0).0 == (n2.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.1).0
    |                                                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `(n1.inner.2).0 == (n2.inner.2).0`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:186:25
+  --> $DIR/suspicious_operation_groupings.rs:187:25
    |
 LL |         s1.a <= s2.a && s1.a <= s2.b
    |                         ^^^^^^^^^^^^ help: did you mean: `s1.b <= s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:192:23
+  --> $DIR/suspicious_operation_groupings.rs:193:23
    |
 LL |     if s1.a < s2.a && s1.a < s2.b {
    |                       ^^^^^^^^^^^ help: did you mean: `s1.b < s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:199:48
+  --> $DIR/suspicious_operation_groupings.rs:200:48
    |
 LL |     -(-(-s1.a * -s2.a) + (-(-s1.b * -s2.b) + -(-s1.c * -s2.b) + -(-s1.d * -s2.d)))
    |                                                ^^^^^^^^^^^^^ help: did you mean: `-s1.c * -s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:204:27
+  --> $DIR/suspicious_operation_groupings.rs:205:27
    |
 LL |     -(if -s1.a < -s2.a && -s1.a < -s2.b { s1.c } else { s2.a })
    |                           ^^^^^^^^^^^^^ help: did you mean: `-s1.b < -s2.b`
diff --git a/src/tools/clippy/tests/ui/unit_hash.rs b/src/tools/clippy/tests/ui/unit_hash.rs
new file mode 100644 (file)
index 0000000..989916c
--- /dev/null
@@ -0,0 +1,27 @@
+#![warn(clippy::unit_hash)]
+
+use std::collections::hash_map::DefaultHasher;
+use std::hash::Hash;
+
+enum Foo {
+    Empty,
+    WithValue(u8),
+}
+
+fn do_nothing() {}
+
+fn main() {
+    let mut state = DefaultHasher::new();
+    let my_enum = Foo::Empty;
+
+    match my_enum {
+        Foo::Empty => ().hash(&mut state),
+        Foo::WithValue(x) => x.hash(&mut state),
+    }
+
+    let res = ();
+    res.hash(&mut state);
+
+    #[allow(clippy::unit_arg)]
+    do_nothing().hash(&mut state);
+}
diff --git a/src/tools/clippy/tests/ui/unit_hash.stderr b/src/tools/clippy/tests/ui/unit_hash.stderr
new file mode 100644 (file)
index 0000000..da27629
--- /dev/null
@@ -0,0 +1,27 @@
+error: this call to `hash` on the unit type will do nothing
+  --> $DIR/unit_hash.rs:18:23
+   |
+LL |         Foo::Empty => ().hash(&mut state),
+   |                       ^^^^^^^^^^^^^^^^^^^ help: remove the call to `hash` or consider using: `0_u8.hash(&mut state)`
+   |
+   = note: `-D clippy::unit-hash` implied by `-D warnings`
+   = note: the implementation of `Hash` for `()` is a no-op
+
+error: this call to `hash` on the unit type will do nothing
+  --> $DIR/unit_hash.rs:23:5
+   |
+LL |     res.hash(&mut state);
+   |     ^^^^^^^^^^^^^^^^^^^^ help: remove the call to `hash` or consider using: `0_u8.hash(&mut state)`
+   |
+   = note: the implementation of `Hash` for `()` is a no-op
+
+error: this call to `hash` on the unit type will do nothing
+  --> $DIR/unit_hash.rs:26:5
+   |
+LL |     do_nothing().hash(&mut state);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `hash` or consider using: `0_u8.hash(&mut state)`
+   |
+   = note: the implementation of `Hash` for `()` is a no-op
+
+error: aborting due to 3 previous errors
+
index 4f4203f5fdbf67fd59049f85769d322ae2ff73ba..2a3a506a57b1437310918767ad1fa55ab0987052 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::unused_async)]
 
 async fn foo() -> i32 {
index 8b834d205b176970c8911b5f371c1282de83feb1..cc6096d65d9f351a016e0fcd7423ac12405ba587 100644 (file)
@@ -1,5 +1,5 @@
 error: unused `async` for function with no await statements
-  --> $DIR/unused_async.rs:4:1
+  --> $DIR/unused_async.rs:3:1
    |
 LL | / async fn foo() -> i32 {
 LL | |     4
index dcf818f80763052c6d4fae4d6e282b0b67c438c2..4e33e343ce0e9c414b42abf6d5e73d6b488392c6 100644 (file)
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 // aux-build:proc_macro_derive.rs
 
 #![warn(clippy::use_self)]
index 9da6fef7a380c792781aceadb6ffbb2258395995..7b621ff9bcabf5be14250e8740311b04516047b8 100644 (file)
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 // aux-build:proc_macro_derive.rs
 
 #![warn(clippy::use_self)]
index e14368a11aa746eddd1fffeeb88c3bc36c35982d..ecb78b3f9721b0b575a4a153e08e9833f63917b5 100644 (file)
@@ -1,5 +1,5 @@
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:23:21
+  --> $DIR/use_self.rs:22:21
    |
 LL |         fn new() -> Foo {
    |                     ^^^ help: use the applicable keyword: `Self`
@@ -7,163 +7,163 @@ LL |         fn new() -> Foo {
    = note: `-D clippy::use-self` implied by `-D warnings`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:24:13
+  --> $DIR/use_self.rs:23:13
    |
 LL |             Foo {}
    |             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:26:22
+  --> $DIR/use_self.rs:25:22
    |
 LL |         fn test() -> Foo {
    |                      ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:27:13
+  --> $DIR/use_self.rs:26:13
    |
 LL |             Foo::new()
    |             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:32:25
+  --> $DIR/use_self.rs:31:25
    |
 LL |         fn default() -> Foo {
    |                         ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:33:13
+  --> $DIR/use_self.rs:32:13
    |
 LL |             Foo::new()
    |             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:98:24
+  --> $DIR/use_self.rs:97:24
    |
 LL |         fn bad(foos: &[Foo]) -> impl Iterator<Item = &Foo> {
    |                        ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:98:55
+  --> $DIR/use_self.rs:97:55
    |
 LL |         fn bad(foos: &[Foo]) -> impl Iterator<Item = &Foo> {
    |                                                       ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:113:13
+  --> $DIR/use_self.rs:112:13
    |
 LL |             TS(0)
    |             ^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:148:29
+  --> $DIR/use_self.rs:147:29
    |
 LL |                 fn bar() -> Bar {
    |                             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:149:21
+  --> $DIR/use_self.rs:148:21
    |
 LL |                     Bar { foo: Foo {} }
    |                     ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:160:21
+  --> $DIR/use_self.rs:159:21
    |
 LL |         fn baz() -> Foo {
    |                     ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:161:13
+  --> $DIR/use_self.rs:160:13
    |
 LL |             Foo {}
    |             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:178:21
+  --> $DIR/use_self.rs:177:21
    |
 LL |             let _ = Enum::B(42);
    |                     ^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:179:21
+  --> $DIR/use_self.rs:178:21
    |
 LL |             let _ = Enum::C { field: true };
    |                     ^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:180:21
+  --> $DIR/use_self.rs:179:21
    |
 LL |             let _ = Enum::A;
    |                     ^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:222:13
+  --> $DIR/use_self.rs:221:13
    |
 LL |             nested::A::fun_1();
    |             ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:223:13
+  --> $DIR/use_self.rs:222:13
    |
 LL |             nested::A::A;
    |             ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:225:13
+  --> $DIR/use_self.rs:224:13
    |
 LL |             nested::A {};
    |             ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:244:13
+  --> $DIR/use_self.rs:243:13
    |
 LL |             TestStruct::from_something()
    |             ^^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:258:25
+  --> $DIR/use_self.rs:257:25
    |
 LL |         async fn g() -> S {
    |                         ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:259:13
+  --> $DIR/use_self.rs:258:13
    |
 LL |             S {}
    |             ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:263:16
+  --> $DIR/use_self.rs:262:16
    |
 LL |             &p[S::A..S::B]
    |                ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:263:22
+  --> $DIR/use_self.rs:262:22
    |
 LL |             &p[S::A..S::B]
    |                      ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:286:29
+  --> $DIR/use_self.rs:285:29
    |
 LL |         fn foo(value: T) -> Foo<T> {
    |                             ^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:287:13
+  --> $DIR/use_self.rs:286:13
    |
 LL |             Foo::<T> { value }
    |             ^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:459:13
+  --> $DIR/use_self.rs:458:13
    |
 LL |             A::new::<submod::B>(submod::B {})
    |             ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:496:13
+  --> $DIR/use_self.rs:495:13
    |
 LL |             S2::new()
    |             ^^ help: use the applicable keyword: `Self`
index d8bda7e8f48a7eb32cc22fc54c4cb5d24d1ffea8..21d66d5df79ecfa0a8b1727424d38ffb1134081f 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 // aux-build:proc_macro_derive.rs
 
 #![feature(rustc_private)]
index 2cbfc5ca2e2705e0bb618bfad420339277493f22..790b849210c9b35875ff2c9b8c4d47f4c54017cd 100644 (file)
@@ -1,5 +1,5 @@
 error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
-  --> $DIR/used_underscore_binding.rs:26:5
+  --> $DIR/used_underscore_binding.rs:25:5
    |
 LL |     _foo + 1
    |     ^^^^
@@ -7,31 +7,31 @@ LL |     _foo + 1
    = note: `-D clippy::used-underscore-binding` implied by `-D warnings`
 
 error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
-  --> $DIR/used_underscore_binding.rs:31:20
+  --> $DIR/used_underscore_binding.rs:30:20
    |
 LL |     println!("{}", _foo);
    |                    ^^^^
 
 error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
-  --> $DIR/used_underscore_binding.rs:32:16
+  --> $DIR/used_underscore_binding.rs:31:16
    |
 LL |     assert_eq!(_foo, _foo);
    |                ^^^^
 
 error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
-  --> $DIR/used_underscore_binding.rs:32:22
+  --> $DIR/used_underscore_binding.rs:31:22
    |
 LL |     assert_eq!(_foo, _foo);
    |                      ^^^^
 
 error: used binding `_underscore_field` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
-  --> $DIR/used_underscore_binding.rs:45:5
+  --> $DIR/used_underscore_binding.rs:44:5
    |
 LL |     s._underscore_field += 1;
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: used binding `_i` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
-  --> $DIR/used_underscore_binding.rs:100:16
+  --> $DIR/used_underscore_binding.rs:99:16
    |
 LL |         uses_i(_i);
    |                ^^
index 98bc1e80731ff3934643d2c565f70ad241ddd7f1..8402c33a4cd5fb695d37116caf003763dcf186bd 100644 (file)
@@ -1,8 +1,13 @@
+// edition:2015
 // run-rustfix
 // aux-build:wildcard_imports_helper.rs
 
+// the 2015 edition here is needed because edition 2018 changed the module system
+// (see https://doc.rust-lang.org/edition-guide/rust-2018/path-changes.html) which means the lint
+// no longer detects some of the cases starting with Rust 2018.
+// FIXME: We should likely add another edition 2021 test case for this lint
+
 #![warn(clippy::wildcard_imports)]
-//#![allow(clippy::redundant_pub_crate)]
 #![allow(unused)]
 #![allow(clippy::unnecessary_wraps)]
 #![warn(unused_imports)]
index 4ef61f9245b58f9420daded6c79a1d84e201edb9..faaeaade9b02bff03b30793a73638ba5a3a560eb 100644 (file)
@@ -1,8 +1,13 @@
+// edition:2015
 // run-rustfix
 // aux-build:wildcard_imports_helper.rs
 
+// the 2015 edition here is needed because edition 2018 changed the module system
+// (see https://doc.rust-lang.org/edition-guide/rust-2018/path-changes.html) which means the lint
+// no longer detects some of the cases starting with Rust 2018.
+// FIXME: We should likely add another edition 2021 test case for this lint
+
 #![warn(clippy::wildcard_imports)]
-//#![allow(clippy::redundant_pub_crate)]
 #![allow(unused)]
 #![allow(clippy::unnecessary_wraps)]
 #![warn(unused_imports)]
index d7af0c046e88694f34a1ff399931fe346cc8904c..7534a65ec9bd56c0878846b81663d05ef269cb92 100644 (file)
@@ -1,5 +1,5 @@
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:12:5
+  --> $DIR/wildcard_imports.rs:17: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:13:5
+  --> $DIR/wildcard_imports.rs:18:5
    |
 LL | use crate::mod_mod::*;
    |     ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:14:5
+  --> $DIR/wildcard_imports.rs:19: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:16:5
+  --> $DIR/wildcard_imports.rs:21:5
    |
 LL | use crate::struct_mod::*;
    |     ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:20:5
+  --> $DIR/wildcard_imports.rs:25: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:21:5
+  --> $DIR/wildcard_imports.rs:26:5
    |
 LL | use wildcard_imports_helper::*;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:92:13
+  --> $DIR/wildcard_imports.rs:97:13
    |
 LL |         use crate::fn_mod::*;
    |             ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:98:75
+  --> $DIR/wildcard_imports.rs:103: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:99:13
+  --> $DIR/wildcard_imports.rs:104:13
    |
 LL |         use wildcard_imports_helper::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:110:20
+  --> $DIR/wildcard_imports.rs:115:20
    |
 LL |         use self::{inner::*, inner2::*};
    |                    ^^^^^^^^ help: try: `inner::inner_foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:110:30
+  --> $DIR/wildcard_imports.rs:115:30
    |
 LL |         use self::{inner::*, inner2::*};
    |                              ^^^^^^^^^ help: try: `inner2::inner_bar`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:117:13
+  --> $DIR/wildcard_imports.rs:122:13
    |
 LL |         use wildcard_imports_helper::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:146:9
+  --> $DIR/wildcard_imports.rs:151: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:155:9
+  --> $DIR/wildcard_imports.rs:160:9
    |
 LL |     use crate:: in_fn_test::  * ;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:156:9
+  --> $DIR/wildcard_imports.rs:161:9
    |
 LL |       use crate:: fn_mod::
    |  _________^
@@ -93,37 +93,37 @@ LL | |         *;
    | |_________^ help: try: `crate:: fn_mod::foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:167:13
+  --> $DIR/wildcard_imports.rs:172:13
    |
 LL |         use super::*;
    |             ^^^^^^^^ help: try: `super::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:202:17
+  --> $DIR/wildcard_imports.rs:207:17
    |
 LL |             use super::*;
    |                 ^^^^^^^^ help: try: `super::insidefoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:210:13
+  --> $DIR/wildcard_imports.rs:215:13
    |
 LL |         use super_imports::*;
    |             ^^^^^^^^^^^^^^^^ help: try: `super_imports::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:219:17
+  --> $DIR/wildcard_imports.rs:224:17
    |
 LL |             use super::super::*;
    |                 ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:228:13
+  --> $DIR/wildcard_imports.rs:233:13
    |
 LL |         use super::super::super_imports::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:236:13
+  --> $DIR/wildcard_imports.rs:241:13
    |
 LL |         use super::*;
    |             ^^^^^^^^ help: try: `super::foofoo`
index 151dd0c27d57dbab4f7b4e98f485eb3993e10b3b..1b9da8a55e53fe8796ff7b92ee9b393db29b25bd 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::wrong_self_convention)]
 #![allow(dead_code)]
 
index ce23317abf651f59f66ca971aeb15e1520355cfa..590ee6d9c529d6493b8e29b755c2d3e07f982b2b 100644 (file)
@@ -1,5 +1,5 @@
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention.rs:17:17
+  --> $DIR/wrong_self_convention.rs:16:17
    |
 LL |     fn from_i32(self) {}
    |                 ^^^^
@@ -8,7 +8,7 @@ LL |     fn from_i32(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention.rs:23:21
+  --> $DIR/wrong_self_convention.rs:22:21
    |
 LL |     pub fn from_i64(self) {}
    |                     ^^^^
@@ -16,7 +16,7 @@ LL |     pub fn from_i64(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
-  --> $DIR/wrong_self_convention.rs:35:15
+  --> $DIR/wrong_self_convention.rs:34:15
    |
 LL |     fn as_i32(self) {}
    |               ^^^^
@@ -24,7 +24,7 @@ LL |     fn as_i32(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `into_*` usually take `self` by value
-  --> $DIR/wrong_self_convention.rs:37:17
+  --> $DIR/wrong_self_convention.rs:36:17
    |
 LL |     fn into_i32(&self) {}
    |                 ^^^^^
@@ -32,7 +32,7 @@ LL |     fn into_i32(&self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `is_*` usually take `self` by reference or no `self`
-  --> $DIR/wrong_self_convention.rs:39:15
+  --> $DIR/wrong_self_convention.rs:38:15
    |
 LL |     fn is_i32(self) {}
    |               ^^^^
@@ -40,7 +40,7 @@ LL |     fn is_i32(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference
-  --> $DIR/wrong_self_convention.rs:41:15
+  --> $DIR/wrong_self_convention.rs:40:15
    |
 LL |     fn to_i32(self) {}
    |               ^^^^
@@ -48,7 +48,7 @@ LL |     fn to_i32(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention.rs:43:17
+  --> $DIR/wrong_self_convention.rs:42:17
    |
 LL |     fn from_i32(self) {}
    |                 ^^^^
@@ -56,7 +56,7 @@ LL |     fn from_i32(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
-  --> $DIR/wrong_self_convention.rs:45:19
+  --> $DIR/wrong_self_convention.rs:44:19
    |
 LL |     pub fn as_i64(self) {}
    |                   ^^^^
@@ -64,7 +64,7 @@ LL |     pub fn as_i64(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `into_*` usually take `self` by value
-  --> $DIR/wrong_self_convention.rs:46:21
+  --> $DIR/wrong_self_convention.rs:45:21
    |
 LL |     pub fn into_i64(&self) {}
    |                     ^^^^^
@@ -72,7 +72,7 @@ LL |     pub fn into_i64(&self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `is_*` usually take `self` by reference or no `self`
-  --> $DIR/wrong_self_convention.rs:47:19
+  --> $DIR/wrong_self_convention.rs:46:19
    |
 LL |     pub fn is_i64(self) {}
    |                   ^^^^
@@ -80,7 +80,7 @@ LL |     pub fn is_i64(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference
-  --> $DIR/wrong_self_convention.rs:48:19
+  --> $DIR/wrong_self_convention.rs:47:19
    |
 LL |     pub fn to_i64(self) {}
    |                   ^^^^
@@ -88,7 +88,7 @@ LL |     pub fn to_i64(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention.rs:49:21
+  --> $DIR/wrong_self_convention.rs:48:21
    |
 LL |     pub fn from_i64(self) {}
    |                     ^^^^
@@ -96,7 +96,7 @@ LL |     pub fn from_i64(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
-  --> $DIR/wrong_self_convention.rs:94:19
+  --> $DIR/wrong_self_convention.rs:93:19
    |
 LL |         fn as_i32(self) {}
    |                   ^^^^
@@ -104,7 +104,7 @@ LL |         fn as_i32(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `into_*` usually take `self` by value
-  --> $DIR/wrong_self_convention.rs:97:25
+  --> $DIR/wrong_self_convention.rs:96:25
    |
 LL |         fn into_i32_ref(&self) {}
    |                         ^^^^^
@@ -112,7 +112,7 @@ LL |         fn into_i32_ref(&self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `is_*` usually take `self` by reference or no `self`
-  --> $DIR/wrong_self_convention.rs:99:19
+  --> $DIR/wrong_self_convention.rs:98:19
    |
 LL |         fn is_i32(self) {}
    |                   ^^^^
@@ -120,7 +120,7 @@ LL |         fn is_i32(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention.rs:103:21
+  --> $DIR/wrong_self_convention.rs:102:21
    |
 LL |         fn from_i32(self) {}
    |                     ^^^^
@@ -128,7 +128,7 @@ LL |         fn from_i32(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
-  --> $DIR/wrong_self_convention.rs:118:19
+  --> $DIR/wrong_self_convention.rs:117:19
    |
 LL |         fn as_i32(self);
    |                   ^^^^
@@ -136,7 +136,7 @@ LL |         fn as_i32(self);
    = help: consider choosing a less ambiguous name
 
 error: methods called `into_*` usually take `self` by value
-  --> $DIR/wrong_self_convention.rs:121:25
+  --> $DIR/wrong_self_convention.rs:120:25
    |
 LL |         fn into_i32_ref(&self);
    |                         ^^^^^
@@ -144,7 +144,7 @@ LL |         fn into_i32_ref(&self);
    = help: consider choosing a less ambiguous name
 
 error: methods called `is_*` usually take `self` by reference or no `self`
-  --> $DIR/wrong_self_convention.rs:123:19
+  --> $DIR/wrong_self_convention.rs:122:19
    |
 LL |         fn is_i32(self);
    |                   ^^^^
@@ -152,7 +152,7 @@ LL |         fn is_i32(self);
    = help: consider choosing a less ambiguous name
 
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention.rs:127:21
+  --> $DIR/wrong_self_convention.rs:126:21
    |
 LL |         fn from_i32(self);
    |                     ^^^^
@@ -160,7 +160,7 @@ LL |         fn from_i32(self);
    = help: consider choosing a less ambiguous name
 
 error: methods called `into_*` usually take `self` by value
-  --> $DIR/wrong_self_convention.rs:145:25
+  --> $DIR/wrong_self_convention.rs:144:25
    |
 LL |         fn into_i32_ref(&self);
    |                         ^^^^^
@@ -168,7 +168,7 @@ LL |         fn into_i32_ref(&self);
    = help: consider choosing a less ambiguous name
 
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention.rs:151:21
+  --> $DIR/wrong_self_convention.rs:150:21
    |
 LL |         fn from_i32(self);
    |                     ^^^^
@@ -176,7 +176,7 @@ LL |         fn from_i32(self);
    = help: consider choosing a less ambiguous name
 
 error: methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value
-  --> $DIR/wrong_self_convention.rs:175:22
+  --> $DIR/wrong_self_convention.rs:174:22
    |
 LL |         fn to_u64_v2(&self) -> u64 {
    |                      ^^^^^
@@ -184,7 +184,7 @@ LL |         fn to_u64_v2(&self) -> u64 {
    = help: consider choosing a less ambiguous name
 
 error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference
-  --> $DIR/wrong_self_convention.rs:184:19
+  --> $DIR/wrong_self_convention.rs:183:19
    |
 LL |         fn to_u64(self) -> u64 {
    |                   ^^^^
index 0d827c1feb3e722c4842684a441f6386ee2f2eb5..a8fe8331133778ebcf934b4b234c07c430f484c9 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::wrong_self_convention)]
 #![allow(dead_code)]
 
index 0e0d066d656b56a174ff00a9190927ca16abbf70..5bdc47f91f65b42b1376b18a7a661926c6d3805b 100644 (file)
@@ -1,5 +1,5 @@
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention2.rs:55:29
+  --> $DIR/wrong_self_convention2.rs:54:29
    |
 LL |         pub fn from_be_self(self) -> Self {
    |                             ^^^^
@@ -8,7 +8,7 @@ LL |         pub fn from_be_self(self) -> Self {
    = help: consider choosing a less ambiguous name
 
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention2.rs:64:25
+  --> $DIR/wrong_self_convention2.rs:63:25
    |
 LL |         fn from_be_self(self) -> Self;
    |                         ^^^^
index 486a0d772358531ca75e14eea62e41547ad294dd..5bb2116bd339af9ef01ddc281abb2d70416a5610 100644 (file)
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::wrong_self_convention)]
 #![allow(dead_code)]
 
index 6ce37c5949111bf20d20b66ffc00ad6170029a69..8665d8dc9a9dea4f7b1ed03b3b5a26084fdf11d3 100644 (file)
@@ -1,5 +1,5 @@
 error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference
-  --> $DIR/wrong_self_conventions_mut.rs:15:24
+  --> $DIR/wrong_self_conventions_mut.rs:14:24
    |
 LL |         pub fn to_many(&mut self) -> Option<&mut [T]> {
    |                        ^^^^^^^^^
@@ -8,7 +8,7 @@ LL |         pub fn to_many(&mut self) -> Option<&mut [T]> {
    = help: consider choosing a less ambiguous name
 
 error: methods with the following characteristics: (`to_*` and `*_mut`) usually take `self` by mutable reference
-  --> $DIR/wrong_self_conventions_mut.rs:23:28
+  --> $DIR/wrong_self_conventions_mut.rs:22:28
    |
 LL |         pub fn to_many_mut(&self) -> Option<&[T]> {
    |                            ^^^^^
index 98d1ee19f69a1ca8bdfb88a533d2d6c41eb5a34b..5fcaa452ca30e6eaf9278d3e0647fc98de15e09d 100644 (file)
@@ -242,9 +242,6 @@ fn load_from(&mut self, testfile: &Path, cfg: Option<&str>, config: &Config) {
                 if let Some(edition) = config.parse_edition(ln) {
                     self.compile_flags.push(format!("--edition={}", edition));
                     has_edition = true;
-                    if edition == "2021" {
-                        self.compile_flags.push("-Zunstable-options".to_string());
-                    }
                 }
 
                 config.parse_and_update_revisions(ln, &mut self.revisions);
index 2485dbadab5bfdbb5bb6cb55f4ec336a90f98778..157b42e2d17f5a52f3bfdb8870178c7a0f28c7ba 100644 (file)
@@ -168,7 +168,7 @@ fn only_target() {
     let mut config = config();
     config.target = "x86_64-pc-windows-gnu".to_owned();
 
-    assert!(check_ignore(&config, "// only-i686"));
+    assert!(check_ignore(&config, "// only-x86"));
     assert!(check_ignore(&config, "// only-linux"));
     assert!(check_ignore(&config, "// only-msvc"));
     assert!(check_ignore(&config, "// only-32bit"));
index 4470272a9f86672adcf1fbf168723040f89bd8e8..3c85b9076dd1af977591fc0fcbdcd6d54a3fbf01 100644 (file)
@@ -1607,9 +1607,6 @@ fn build_all_auxiliary(&self, rustc: &mut Command) -> PathBuf {
                 get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), is_dylib);
             rustc.arg("--extern").arg(format!("{}={}/{}", aux_name, aux_dir.display(), lib_name));
         }
-        if !self.props.aux_crates.is_empty() {
-            rustc.arg("-Zunstable-options");
-        }
 
         aux_dir
     }
index d03c21dc5086fe499e14d94d00e366669467955a..6ca145a58e92af169c4c2004dc5e524c2038a0a7 100644 (file)
 ];
 
 static ASM_SUPPORTED_ARCHS: &[&str] = &[
-    "x86", "x86_64", "arm", "aarch64", "riscv32", "riscv64", "nvptx64", "hexagon", "mips",
-    "mips64", "spirv", "wasm32",
+    "x86", "x86_64", "arm", "aarch64", "riscv32",
+    "riscv64",
+    // These targets require an additional asm_experimental_arch feature.
+    // "nvptx64", "hexagon", "mips", "mips64", "spirv", "wasm32",
 ];
 
 pub fn has_asm_support(triple: &str) -> bool {
index 94ebbb33e8d8ffad075cd6d06d3248e13e5ecf48..94e82e3d9f7664f993ea6fcb2db1e0a9a156d1df 100644 (file)
@@ -85,6 +85,8 @@
     ("core/slice/trait.SliceIndex.html", &["begin</code>, <code>end"]),
     ("alloc/slice/trait.SliceIndex.html", &["begin</code>, <code>end"]),
     ("std/slice/trait.SliceIndex.html", &["begin</code>, <code>end"]),
+    ("core/primitive.str.html", &["begin</code>, <code>end"]),
+    ("std/primitive.str.html", &["begin</code>, <code>end"]),
 
 ];
 
index fa91a89193d26e6a86e2eee1cbaa38cb28ccebe1..9c18177cd36fe07a3c251234240a9c77a4e66785 160000 (submodule)
@@ -1 +1 @@
-Subproject commit fa91a89193d26e6a86e2eee1cbaa38cb28ccebe1
+Subproject commit 9c18177cd36fe07a3c251234240a9c77a4e66785
index 91cbda43c2af82b9377eff70a21f59ade18cd23c..2c0f433fd2e838ae181f87019b6f1fefe33c6f54 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 91cbda43c2af82b9377eff70a21f59ade18cd23c
+Subproject commit 2c0f433fd2e838ae181f87019b6f1fefe33c6f54
index bb9cd00f3f5829196df0a2a93d12274d82702f8a..a673e425dfff9d41610b59ae14f014486f911018 100644 (file)
@@ -414,7 +414,7 @@ function parseOptions(args) {
         "test_folder": "",
         "test_file": "",
     };
-    var correspondances = {
+    var correspondences = {
         "--resource-suffix": "resource_suffix",
         "--doc-folder": "doc_folder",
         "--test-folder": "test_folder",
@@ -423,17 +423,13 @@ function parseOptions(args) {
     };
 
     for (var i = 0; i < args.length; ++i) {
-        if (args[i] === "--resource-suffix"
-            || args[i] === "--doc-folder"
-            || args[i] === "--test-folder"
-            || args[i] === "--test-file"
-            || args[i] === "--crate-name") {
+        if (correspondences.hasOwnProperty(args[i])) {
             i += 1;
             if (i >= args.length) {
                 console.log("Missing argument after `" + args[i - 1] + "` option.");
                 return null;
             }
-            opts[correspondances[args[i - 1]]] = args[i];
+            opts[correspondences[args[i - 1]]] = args[i];
         } else if (args[i] === "--help") {
             showHelp();
             process.exit(0);
diff --git a/src/tools/rustfmt/.github/workflows/rustdoc_check.yml b/src/tools/rustfmt/.github/workflows/rustdoc_check.yml
new file mode 100644 (file)
index 0000000..ca96d30
--- /dev/null
@@ -0,0 +1,25 @@
+name: rustdoc check
+on:
+  push:
+    branches:
+      - master
+  pull_request:
+
+jobs:
+  rustdoc_check:
+    runs-on: ubuntu-latest
+    name: rustdoc check
+    steps:
+    - name: checkout
+      uses: actions/checkout@v2
+
+    - name: install rustup
+      run: |
+        curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh
+        sh rustup-init.sh -y --default-toolchain none
+        rustup target add x86_64-unknown-linux-gnu
+
+    - name: document rustfmt
+      env:
+        RUSTDOCFLAGS: --document-private-items --enable-index-page --show-type-layout --generate-link-to-definition -Zunstable-options -Dwarnings
+      run: cargo doc -Zskip-rustdoc-fingerprint --no-deps -p rustfmt-nightly -p rustfmt-config_proc_macro
index 7a77dbe154b60f2f55224cfeae2cb41f2127c53c..13826883d2f4bdf537df1df2a687be215adbaf97 100644 (file)
@@ -2062,7 +2062,7 @@ use sit;
 Controls the strategy for how imports are grouped together.
 
 - **Default value**: `Preserve`
-- **Possible values**: `Preserve`, `StdExternalCrate`
+- **Possible values**: `Preserve`, `StdExternalCrate`, `One`
 - **Stable**: No
 
 #### `Preserve` (default):
@@ -2108,6 +2108,23 @@ use super::update::convert_publish_payload;
 use crate::models::Event;
 ```
 
+#### `One`:
+
+Discard existing import groups, and create a single group for everything
+
+```rust
+use super::schema::{Context, Payload};
+use super::update::convert_publish_payload;
+use crate::models::Event;
+use alloc::alloc::Layout;
+use broker::database::PooledConnection;
+use chrono::Utc;
+use core::f32;
+use juniper::{FieldError, FieldResult};
+use std::sync::Arc;
+use uuid::Uuid;
+```
+
 ## `reorder_modules`
 
 Reorder `mod` declarations alphabetically in group.
index e6dc6a220376db13aaea6aa795410a1c37a851c7..3073996019ee26be58d1ec8aaa233545ee8803d9 100644 (file)
@@ -59,7 +59,7 @@ example, the `issue-1111.rs` test file is configured by the file
 ## Debugging
 
 Some `rewrite_*` methods use the `debug!` macro for printing useful information.
-These messages can be printed by using the environment variable `RUST_LOG=rustfmt=DEBUG`.
+These messages can be printed by using the environment variable `RUSTFMT_LOG=rustfmt=DEBUG`.
 These traces can be helpful in understanding which part of the code was used
 and get a better grasp on the execution flow.
 
index 9c7a1c4bc341bed77ce3ee362a8eea5d01ad7974..b3d21e6fb87c79ffa3957b20a4cc405f2787f051 100644 (file)
@@ -47,7 +47,7 @@ cargo +nightly fmt
 
 ## Limitations
 
-Rustfmt tries to work on as much Rust code as possible, sometimes, the code
+Rustfmt tries to work on as much Rust code as possible. Sometimes, the code
 doesn't even need to compile! As we approach a 1.0 release we are also looking
 to limit areas of instability; in particular, post-1.0, the formatting of most
 code should not change as Rustfmt improves. However, there are some things that
@@ -102,6 +102,25 @@ read data from stdin. Alternatively, you can use `cargo fmt` to format all
 binary and library targets of your crate.
 
 You can run `rustfmt --help` for information about available arguments.
+The easiest way to run rustfmt against a project is with `cargo fmt`. `cargo fmt` works on both
+single-crate projects and [cargo workspaces](https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html).
+Please see `cargo fmt --help` for usage information.
+
+You can specify the path to your own `rustfmt` binary for cargo to use by setting the`RUSTFMT` 
+environment variable. This was added in v1.4.22, so you must have this version or newer to leverage this feature (`cargo fmt --version`)
+
+### Running `rustfmt` directly
+
+To format individual files or arbitrary codes from stdin, the `rustfmt` binary should be used. Some
+examples follow:
+
+- `rustfmt lib.rs main.rs` will format "lib.rs" and "main.rs" in place
+- `rustfmt` will read a code from stdin and write formatting to stdout
+  - `echo "fn     main() {}" | rustfmt` would emit "fn main() {}".
+
+For more information, including arguments and emit options, see `rustfmt --help`.
+
+### Verifying code is formatted
 
 When running with `--check`, Rustfmt will exit with `0` if Rustfmt would not
 make any formatting changes to the input, and `1` if Rustfmt would make changes.
@@ -129,7 +148,7 @@ rustfmt to exit with an error code if the input is not formatted correctly.
 It will also print any found differences. (Older versions of Rustfmt don't
 support `--check`, use `--write-mode diff`).
 
-A minimal Travis setup could look like this (requires Rust 1.24.0 or greater):
+A minimal Travis setup could look like this (requires Rust 1.31.0 or greater):
 
 ```yaml
 language: rust
diff --git a/src/tools/rustfmt/appveyor.yml b/src/tools/rustfmt/appveyor.yml
deleted file mode 100644 (file)
index b3dda09..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-environment:
-  global:
-    PROJECT_NAME: rustfmt
-
-build: false
-
-test_script:
-  - echo Why does no one have access to delete me?
index 7aea6222b8bc5f7a8168857e36b7b501b225b267..6a711c0171aebb99078b65ccb5a70629e7338629 100644 (file)
@@ -3,19 +3,28 @@
 ## Installation
 
 - Install [CLion](https://www.jetbrains.com/clion/), [IntelliJ Ultimate or CE](https://www.jetbrains.com/idea/) through the direct download link or using the [JetBrains Toolbox](https://www.jetbrains.com/toolbox/).
-  CLion provides a built-in debugger interface but its not free like IntelliJ CE - which does not provide the debugger interface. (IntelliJ seems to lack the toolchain for that, see this discussion [intellij-rust/issues/535](https://github.com/intellij-rust/intellij-rust/issues/535))
-  
-- Install the [Rust Plugin](https://intellij-rust.github.io/) by navigating to File -> Settings -> Plugins and press "Install JetBrains Plugin"
-  ![plugins](https://user-images.githubusercontent.com/1133787/47240861-f40af680-d3e9-11e8-9b82-cdd5c8d5f5b8.png)
+  CLion and IntelliJ Ultimate [provide a built-in debugger interface](https://github.com/intellij-rust/intellij-rust#compatible-ides) but they are not free like IntelliJ CE.
+
+- Install the [Rust Plugin](https://intellij-rust.github.io/) by navigating to File → Settings → Plugins and searching the plugin in the Marketplace
+  ![plugins](https://user-images.githubusercontent.com/6505554/83944518-6f1e5c00-a81d-11ea-9c35-e16948811ba8.png)
 
-- Press "Install" on the rust plugin
-  ![install rust](https://user-images.githubusercontent.com/1133787/47240803-c0c86780-d3e9-11e8-9265-22f735e4d7ed.png)
+- Press "Install" on the Rust plugin
+  ![install rust](https://user-images.githubusercontent.com/6505554/83944533-82c9c280-a81d-11ea-86b3-ee2e31bc7d12.png)
   
 - Restart CLion/IntelliJ
 
 ## Configuration
 
-- Open the settings window (File -> Settings) and search for "reformat"
+### Run Rustfmt on save
+
+- Open Rustfmt settings (File → Settings → Languages & Frameworks → Rust → Rustfmt) and enable "Run rustfmt on Save"
+  ![run_rustfmt_on_save](https://user-images.githubusercontent.com/6505554/83944610-3468f380-a81e-11ea-9c34-0cbd18dd4969.png)
+
+- IntellJ uses autosave, so now your files will always be formatted according to rustfmt. Alternatively you can use Ctrl+S to reformat file manually
+
+### Bind shortcut to "Reformat File with Rustfmt" action
+
+- Open the settings window (File → Settings) and search for "reformat"
   ![keymap](https://user-images.githubusercontent.com/1133787/47240922-2ae10c80-d3ea-11e8-9d8f-c798d9749240.png)
 - Right-click on "Reformat File with Rustfmt" and assign a keyboard shortcut
 
diff --git a/src/tools/rustfmt/legacy-rustfmt.toml b/src/tools/rustfmt/legacy-rustfmt.toml
deleted file mode 100644 (file)
index f976fa6..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-indent_style = "Visual"
-combine_control_expr = false
index b19ecbdb07c4f425540264a618144618e7acbcab..1d2cad6675117d567194ef4e77cb521abdac7946 100644 (file)
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2021-10-20"
+channel = "nightly-2021-11-08"
 components = ["rustc-dev"]
index a5982820e3ded6f2de868975ac9003ee441623f4..76b66e9da80980ea30f24aa585ac64caea4ef71c 100644 (file)
@@ -451,7 +451,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                         if next.is_doc_comment() {
                             let snippet = context.snippet(missing_span);
                             let (_, mlb) = has_newlines_before_after_comment(snippet);
-                            result.push_str(&mlb);
+                            result.push_str(mlb);
                         }
                     }
                     result.push('\n');
@@ -484,7 +484,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                     if next.is_doc_comment() {
                         let snippet = context.snippet(missing_span);
                         let (_, mlb) = has_newlines_before_after_comment(snippet);
-                        result.push_str(&mlb);
+                        result.push_str(mlb);
                     }
                 }
                 result.push('\n');
index c3dcb84c9488d53b001f5febb9c8803039f9a27c..f653a12a8afeb95fb22d3c42475c14ca8da3947e 100644 (file)
@@ -77,7 +77,7 @@ fn test_doc_comment_is_formatted_correctly(
     ) {
         assert_eq!(
             expected_comment,
-            format!("{}", DocCommentFormatter::new(&literal, style))
+            format!("{}", DocCommentFormatter::new(literal, style))
         );
     }
 }
index 1bcc5c0dada3bd0695d9fd5c8167890ab7eff255..9d2e97c9479fc2dda6c063467b4cbde52a934b4b 100644 (file)
@@ -20,7 +20,7 @@
 };
 
 fn main() {
-    env_logger::init();
+    env_logger::Builder::from_env("RUSTFMT_LOG").init();
     let opts = make_opts();
 
     let exit_code = match execute(&opts) {
index 1d423ac34919b421a31e4f77f4e63030746082a6..759b21218c353e70787f853a6c09725bf7132b10 100644 (file)
@@ -401,12 +401,12 @@ fn get_targets_root_only(
 
 fn get_targets_recursive(
     manifest_path: Option<&Path>,
-    mut targets: &mut BTreeSet<Target>,
+    targets: &mut BTreeSet<Target>,
     visited: &mut BTreeSet<String>,
 ) -> Result<(), io::Error> {
     let metadata = get_cargo_metadata(manifest_path)?;
     for package in &metadata.packages {
-        add_targets(&package.targets, &mut targets);
+        add_targets(&package.targets, targets);
 
         // Look for local dependencies using information available since cargo v1.51
         // It's theoretically possible someone could use a newer version of rustfmt with
@@ -427,7 +427,7 @@ fn get_targets_recursive(
                     .any(|p| p.manifest_path.eq(&manifest_path))
             {
                 visited.insert(dependency.name.to_owned());
-                get_targets_recursive(Some(&manifest_path), &mut targets, visited)?;
+                get_targets_recursive(Some(&manifest_path), targets, visited)?;
             }
         }
     }
index 614638ea2abfbea7c4096c9cf5443bb7afe17041..e26e24ec55ad6c40fe495ddc41c57cba89e218c5 100644 (file)
@@ -568,7 +568,7 @@ fn format_last_child(
         } else {
             self.rewrites
                 .iter()
-                .map(|rw| utils::unicode_str_width(&rw))
+                .map(|rw| utils::unicode_str_width(rw))
                 .sum()
         } + last.tries;
         let one_line_budget = if self.child_count == 1 {
@@ -673,7 +673,7 @@ fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> Opt
                 ChainItemKind::Comment(_, CommentPosition::Top) => result.push_str(&connector),
                 _ => result.push_str(&connector),
             }
-            result.push_str(&rewrite);
+            result.push_str(rewrite);
         }
 
         Some(result)
index dc4f4516252b122267dfb3030bdc01324deeba3a..7b76c232937dc7cea63d7df07716777730cbeef2 100644 (file)
@@ -405,7 +405,7 @@ impl CodeBlockAttribute {
     /// attributes are valid rust attributes
     /// See <https://doc.rust-lang.org/rustdoc/print.html#attributes>
     fn new(attributes: &str) -> CodeBlockAttribute {
-        for attribute in attributes.split(",") {
+        for attribute in attributes.split(',') {
             match attribute.trim() {
                 "" | "rust" | "should_panic" | "no_run" | "edition2015" | "edition2018"
                 | "edition2021" => (),
@@ -563,7 +563,7 @@ fn join_block(s: &str, sep: &str) -> String {
             result.push_str(line);
             result.push_str(match iter.peek() {
                 Some(next_line) if next_line.is_empty() => sep.trim_end(),
-                Some(..) => &sep,
+                Some(..) => sep,
                 None => "",
             });
         }
@@ -622,7 +622,7 @@ fn handle_line(
         let is_last = i == count_newlines(orig);
 
         if let Some(ref mut ib) = self.item_block {
-            if ib.add_line(&line) {
+            if ib.add_line(line) {
                 return false;
             }
             self.is_prev_line_multi_line = false;
@@ -684,8 +684,8 @@ fn handle_line(
         self.item_block = None;
         if let Some(stripped) = line.strip_prefix("```") {
             self.code_block_attr = Some(CodeBlockAttribute::new(stripped))
-        } else if self.fmt.config.wrap_comments() && ItemizedBlock::is_itemized_line(&line) {
-            let ib = ItemizedBlock::new(&line);
+        } else if self.fmt.config.wrap_comments() && ItemizedBlock::is_itemized_line(line) {
+            let ib = ItemizedBlock::new(line);
             self.item_block = Some(ib);
             return false;
         }
@@ -941,7 +941,7 @@ fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle<'_>) -> (&'a s
     {
         (&line[4..], true)
     } else if let CommentStyle::Custom(opener) = *style {
-        if let Some(ref stripped) = line.strip_prefix(opener) {
+        if let Some(stripped) = line.strip_prefix(opener) {
             (stripped, true)
         } else {
             (&line[opener.trim_end().len()..], false)
@@ -1384,7 +1384,7 @@ fn next(&mut self) -> Option<Self::Item> {
             None => unreachable!(),
         };
 
-        while let Some((kind, c)) = self.base.next() {
+        for (kind, c) in self.base.by_ref() {
             // needed to set the kind of the ending character on the last line
             self.kind = kind;
             if c == '\n' {
@@ -1570,7 +1570,7 @@ pub(crate) fn recover_comment_removed(
                 context.parse_sess.span_to_filename(span),
                 vec![FormattingError::from_span(
                     span,
-                    &context.parse_sess,
+                    context.parse_sess,
                     ErrorKind::LostComment,
                 )],
             );
@@ -1675,7 +1675,7 @@ fn next(&mut self) -> Option<Self::Item> {
 fn remove_comment_header(comment: &str) -> &str {
     if comment.starts_with("///") || comment.starts_with("//!") {
         &comment[3..]
-    } else if let Some(ref stripped) = comment.strip_prefix("//") {
+    } else if let Some(stripped) = comment.strip_prefix("//") {
         stripped
     } else if (comment.starts_with("/**") && !comment.starts_with("/**/"))
         || comment.starts_with("/*!")
index e92f8e8a53152e666cec884eae3a8808bcf40d18..bce9e5d07f267a67a8c39917609d4fa38cfbf115 100644 (file)
@@ -20,7 +20,7 @@ pub enum NewlineStyle {
     Windows,
     /// Force CR (`\n).
     Unix,
-    /// `\r\n` in Windows, `\n`` on other platforms.
+    /// `\r\n` in Windows, `\n` on other platforms.
     Native,
 }
 
@@ -112,6 +112,8 @@ pub enum GroupImportsTactic {
     ///  2. other imports
     ///  3. `self` / `crate` / `super` imports
     StdExternalCrate,
+    /// Discard existing groups, and create a single group for everything
+    One,
 }
 
 #[config_type]
index 4448214f3ff2cd1ac4c2fd7e519ca8342c436289..76f2527db3dad1d69c78d8b54c7eeea4244b4469 100644 (file)
@@ -121,7 +121,7 @@ fn emits_single_xml_tree_containing_all_files() {
             format!(r#"<file name="{}">"#, bin_file),
             format!(
                 r#"<error line="2" severity="warning" message="Should be `{}`" />"#,
-                XmlEscaped(&r#"    println!("Hello, world!");"#),
+                XmlEscaped(r#"    println!("Hello, world!");"#),
             ),
             String::from("</file>"),
         ];
@@ -129,7 +129,7 @@ fn emits_single_xml_tree_containing_all_files() {
             format!(r#"<file name="{}">"#, lib_file),
             format!(
                 r#"<error line="2" severity="warning" message="Should be `{}`" />"#,
-                XmlEscaped(&r#"    println!("Greetings!");"#),
+                XmlEscaped(r#"    println!("Greetings!");"#),
             ),
             String::from("</file>"),
         ];
index 2fbbfedb566d13cbe1bb657685de4cd1fa6cd71e..7264ad8bbf365baaf0f2d7e74ff3fb8e61bd5e7d 100644 (file)
@@ -23,7 +23,7 @@ fn emit_formatted_file(
         }: FormattedFile<'_>,
     ) -> Result<EmitterResult, io::Error> {
         const CONTEXT_SIZE: usize = 3;
-        let mismatch = make_diff(&original_text, formatted_text, CONTEXT_SIZE);
+        let mismatch = make_diff(original_text, formatted_text, CONTEXT_SIZE);
         let has_diff = !mismatch.is_empty();
 
         if has_diff {
index 7f1dd363f9379a3bd971dbf87c93e4a0955a0cab..58942e442de05ba39ef3472bbb6b51850711ebfc 100644 (file)
@@ -257,7 +257,7 @@ fn needs_space_before_range(context: &RewriteContext<'_>, lhs: &ast::Expr) -> bo
                         }
                         _ => false,
                     },
-                    ast::ExprKind::Unary(_, ref expr) => needs_space_before_range(context, &expr),
+                    ast::ExprKind::Unary(_, ref expr) => needs_space_before_range(context, expr),
                     _ => false,
                 }
             }
@@ -423,7 +423,7 @@ fn rewrite_empty_block(
     prefix: &str,
     shape: Shape,
 ) -> Option<String> {
-    if block_has_statements(&block) {
+    if block_has_statements(block) {
         return None;
     }
 
@@ -1148,7 +1148,7 @@ pub(crate) fn is_empty_block(
     block: &ast::Block,
     attrs: Option<&[ast::Attribute]>,
 ) -> bool {
-    !block_has_statements(&block)
+    !block_has_statements(block)
         && !block_contains_comment(context, block)
         && attrs.map_or(true, |a| inner_attributes(a).is_empty())
 }
@@ -1207,11 +1207,11 @@ fn rewrite_int_lit(context: &RewriteContext<'_>, lit: &ast::Lit, shape: Shape) -
     let span = lit.span;
     let symbol = lit.token.symbol.as_str();
 
-    if symbol.starts_with("0x") {
+    if let Some(symbol_stripped) = symbol.strip_prefix("0x") {
         let hex_lit = match context.config.hex_literal_case() {
             HexLiteralCase::Preserve => None,
-            HexLiteralCase::Upper => Some(symbol[2..].to_ascii_uppercase()),
-            HexLiteralCase::Lower => Some(symbol[2..].to_ascii_lowercase()),
+            HexLiteralCase::Upper => Some(symbol_stripped.to_ascii_uppercase()),
+            HexLiteralCase::Lower => Some(symbol_stripped.to_ascii_lowercase()),
         };
         if let Some(hex_lit) = hex_lit {
             return wrap_str(
@@ -1621,7 +1621,7 @@ enum StructLitField<'a> {
     };
 
     let fields_str =
-        wrap_struct_field(context, &attrs, &fields_str, shape, v_shape, one_line_width)?;
+        wrap_struct_field(context, attrs, &fields_str, shape, v_shape, one_line_width)?;
     Some(format!("{} {{{}}}", path_str, fields_str))
 
     // FIXME if context.config.indent_style() == Visual, but we run out
@@ -1888,7 +1888,7 @@ pub(crate) fn rewrite_assign_rhs_expr<R: Rewrite>(
     shape: Shape,
     rhs_tactics: RhsTactics,
 ) -> Option<String> {
-    let last_line_width = last_line_width(&lhs).saturating_sub(if lhs.contains('\n') {
+    let last_line_width = last_line_width(lhs).saturating_sub(if lhs.contains('\n') {
         shape.indent.width()
     } else {
         0
@@ -1947,7 +1947,7 @@ pub(crate) fn rewrite_assign_rhs_with_comments<S: Into<String>, R: Rewrite>(
 
     if contains_comment {
         let rhs = rhs.trim_start();
-        combine_strs_with_missing_comments(context, &lhs, &rhs, between_span, shape, allow_extend)
+        combine_strs_with_missing_comments(context, &lhs, rhs, between_span, shape, allow_extend)
     } else {
         Some(lhs + &rhs)
     }
@@ -1962,6 +1962,9 @@ fn choose_rhs<R: Rewrite>(
     has_rhs_comment: bool,
 ) -> Option<String> {
     match orig_rhs {
+        Some(ref new_str) if new_str.is_empty() => {
+            return Some(String::new());
+        }
         Some(ref new_str)
             if !new_str.contains('\n') && unicode_str_width(new_str) <= shape.width =>
         {
index c751932273b0a8f27c494f25799a49a9dfc08f33..655aeda42bf28daab91e885b1fae84f37e355b14 100644 (file)
@@ -64,7 +64,7 @@ pub struct Opts {
 }
 
 fn main() {
-    env_logger::init();
+    env_logger::Builder::from_env("RUSTFMT_LOG").init();
     let opts = Opts::from_args();
     if let Err(e) = run(opts) {
         println!("{}", e);
index 9ef47b887cadb8809345b1dc196017bbbad92c59..7d0facb8f12cf683b93fe7e17f630ce488190652 100644 (file)
@@ -155,7 +155,7 @@ fn format_file(
         let snippet_provider = self.parse_session.snippet_provider(module.span);
         let mut visitor = FmtVisitor::from_parse_sess(
             &self.parse_session,
-            &self.config,
+            self.config,
             &snippet_provider,
             self.report.clone(),
         );
@@ -180,7 +180,7 @@ fn format_file(
             &mut visitor.buffer,
             &path,
             &visitor.skipped_range.borrow(),
-            &self.config,
+            self.config,
             &self.report,
         );
 
index 16f5d1dd4f234fe17091843ebcfa8133bacffaaa..579778edbe742704519998bd1aba4d1fd1bdf95d 100644 (file)
@@ -170,7 +170,7 @@ fn from_args(matches: &Matches, opts: &Options) -> Config {
 }
 
 fn main() {
-    env_logger::init();
+    env_logger::Builder::from_env("RUSTFMT_LOG").init();
 
     let opts = make_opts();
     let matches = opts
index 5ac799366894de843dd6250a97adc2786a1cc1e4..40e0d06f99df8d14b7279dabb7bf503c747a6fcc 100644 (file)
@@ -275,7 +275,7 @@ pub(crate) fn rewrite_top_level(
         shape: Shape,
     ) -> Option<String> {
         let vis = self.visibility.as_ref().map_or(Cow::from(""), |vis| {
-            crate::utils::format_visibility(context, &vis)
+            crate::utils::format_visibility(context, vis)
         });
         let use_str = self
             .rewrite(context, shape.offset_left(vis.len())?)
@@ -929,7 +929,7 @@ impl Rewrite for UseTree {
     fn rewrite(&self, context: &RewriteContext<'_>, mut shape: Shape) -> Option<String> {
         let mut result = String::with_capacity(256);
         let mut iter = self.path.iter().peekable();
-        while let Some(ref segment) = iter.next() {
+        while let Some(segment) = iter.next() {
             let segment_str = segment.rewrite(context, shape)?;
             result.push_str(&segment_str);
             if iter.peek().is_some() {
index 1cb1a2701c36bf24f78109c56c45d320c4da2806..50121a8b6b50e7d506d07e9a14ed645579e2d094 100644 (file)
@@ -226,7 +226,7 @@ pub(crate) fn from_fn_kind(
     fn to_str(&self, context: &RewriteContext<'_>) -> String {
         let mut result = String::with_capacity(128);
         // Vis defaultness constness unsafety abi.
-        result.push_str(&*format_visibility(context, &self.visibility));
+        result.push_str(&*format_visibility(context, self.visibility));
         result.push_str(format_defaultness(self.defaultness));
         result.push_str(format_constness(self.constness));
         result.push_str(format_async(&self.is_async));
@@ -622,7 +622,7 @@ fn both_opaque(
             fn need_empty_line(a: &ast::AssocItemKind, b: &ast::AssocItemKind) -> bool {
                 match (a, b) {
                     (TyAlias(lty), TyAlias(rty))
-                        if both_type(&lty.3, &rty.3) || both_opaque(&lty.3, &rty.3) =>
+                        if both_type(&lty.ty, &rty.ty) || both_opaque(&lty.ty, &rty.ty) =>
                     {
                         false
                     }
@@ -633,7 +633,7 @@ fn need_empty_line(a: &ast::AssocItemKind, b: &ast::AssocItemKind) -> bool {
 
             buffer.sort_by(|(_, a), (_, b)| match (&a.kind, &b.kind) {
                 (TyAlias(lty), TyAlias(rty))
-                    if both_type(&lty.3, &rty.3) || both_opaque(&lty.3, &rty.3) =>
+                    if both_type(&lty.ty, &rty.ty) || both_opaque(&lty.ty, &rty.ty) =>
                 {
                     a.ident.as_str().cmp(&b.ident.as_str())
                 }
@@ -641,8 +641,8 @@ fn need_empty_line(a: &ast::AssocItemKind, b: &ast::AssocItemKind) -> bool {
                     a.ident.as_str().cmp(&b.ident.as_str())
                 }
                 (Fn(..), Fn(..)) => a.span.lo().cmp(&b.span.lo()),
-                (TyAlias(ty), _) if is_type(&ty.3) => Ordering::Less,
-                (_, TyAlias(ty)) if is_type(&ty.3) => Ordering::Greater,
+                (TyAlias(ty), _) if is_type(&ty.ty) => Ordering::Less,
+                (_, TyAlias(ty)) if is_type(&ty.ty) => Ordering::Greater,
                 (TyAlias(..), _) => Ordering::Less,
                 (_, TyAlias(..)) => Ordering::Greater,
                 (Const(..), _) => Ordering::Less,
@@ -679,7 +679,7 @@ pub(crate) fn format_impl(
     offset: Indent,
 ) -> Option<String> {
     if let ast::ItemKind::Impl(impl_kind) = &item.kind {
-        let ast::ImplKind {
+        let ast::Impl {
             ref generics,
             ref self_ty,
             ref items,
@@ -833,7 +833,7 @@ fn format_impl_ref_and_type(
     offset: Indent,
 ) -> Option<String> {
     if let ast::ItemKind::Impl(impl_kind) = &item.kind {
-        let ast::ImplKind {
+        let ast::Impl {
             unsafety,
             polarity,
             defaultness,
@@ -1029,8 +1029,13 @@ pub(crate) fn format_trait(
     offset: Indent,
 ) -> Option<String> {
     if let ast::ItemKind::Trait(trait_kind) = &item.kind {
-        let ast::TraitKind(is_auto, unsafety, ref generics, ref generic_bounds, ref trait_items) =
-            **trait_kind;
+        let ast::Trait {
+            is_auto,
+            unsafety,
+            ref generics,
+            ref bounds,
+            ref items,
+        } = **trait_kind;
         let mut result = String::with_capacity(128);
         let header = format!(
             "{}{}{}trait ",
@@ -1048,11 +1053,11 @@ pub(crate) fn format_trait(
         result.push_str(&generics_str);
 
         // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds.
-        if !generic_bounds.is_empty() {
+        if !bounds.is_empty() {
             let ident_hi = context
                 .snippet_provider
                 .span_after(item.span, &item.ident.as_str());
-            let bound_hi = generic_bounds.last().unwrap().span().hi();
+            let bound_hi = bounds.last().unwrap().span().hi();
             let snippet = context.snippet(mk_sp(ident_hi, bound_hi));
             if contains_comment(snippet) {
                 return None;
@@ -1061,7 +1066,7 @@ pub(crate) fn format_trait(
             result = rewrite_assign_rhs_with(
                 context,
                 result + ":",
-                generic_bounds,
+                bounds,
                 shape,
                 RhsTactics::ForceNextLineWithoutIndent,
             )?;
@@ -1072,10 +1077,10 @@ pub(crate) fn format_trait(
             let where_on_new_line = context.config.indent_style() != IndentStyle::Block;
 
             let where_budget = context.budget(last_line_width(&result));
-            let pos_before_where = if generic_bounds.is_empty() {
+            let pos_before_where = if bounds.is_empty() {
                 generics.where_clause.span.lo()
             } else {
-                generic_bounds[generic_bounds.len() - 1].span().hi()
+                bounds[bounds.len() - 1].span().hi()
             };
             let option = WhereClauseOption::snuggled(&generics_str);
             let where_clause_str = rewrite_where_clause(
@@ -1122,19 +1127,31 @@ pub(crate) fn format_trait(
             }
         }
 
+        let block_span = mk_sp(generics.where_clause.span.hi(), item.span.hi());
+        let snippet = context.snippet(block_span);
+        let open_pos = snippet.find_uncommented("{")? + 1;
+
         match context.config.brace_style() {
             _ if last_line_contains_single_line_comment(&result)
                 || last_line_width(&result) + 2 > context.budget(offset.width()) =>
             {
                 result.push_str(&offset.to_string_with_newline(context.config));
             }
+            _ if context.config.empty_item_single_line()
+                && items.is_empty()
+                && !result.contains('\n')
+                && !contains_comment(&snippet[open_pos..]) =>
+            {
+                result.push_str(" {}");
+                return Some(result);
+            }
             BraceStyle::AlwaysNextLine => {
                 result.push_str(&offset.to_string_with_newline(context.config));
             }
             BraceStyle::PreferSameLine => result.push(' '),
             BraceStyle::SameLineWhere => {
                 if result.contains('\n')
-                    || (!generics.where_clause.predicates.is_empty() && !trait_items.is_empty())
+                    || (!generics.where_clause.predicates.is_empty() && !items.is_empty())
                 {
                     result.push_str(&offset.to_string_with_newline(context.config));
                 } else {
@@ -1144,17 +1161,14 @@ pub(crate) fn format_trait(
         }
         result.push('{');
 
-        let block_span = mk_sp(generics.where_clause.span.hi(), item.span.hi());
-        let snippet = context.snippet(block_span);
-        let open_pos = snippet.find_uncommented("{")? + 1;
         let outer_indent_str = offset.block_only().to_string_with_newline(context.config);
 
-        if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) {
+        if !items.is_empty() || contains_comment(&snippet[open_pos..]) {
             let mut visitor = FmtVisitor::from_context(context);
             visitor.block_indent = offset.block_only().block_indent(context.config);
             visitor.last_pos = block_span.lo() + BytePos(open_pos as u32);
 
-            for item in trait_items {
+            for item in items {
                 visitor.visit_trait_item(item);
             }
 
@@ -1176,18 +1190,6 @@ pub(crate) fn format_trait(
     }
 }
 
-struct OpaqueTypeBounds<'a> {
-    generic_bounds: &'a ast::GenericBounds,
-}
-
-impl<'a> Rewrite for OpaqueTypeBounds<'a> {
-    fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
-        self.generic_bounds
-            .rewrite(context, shape)
-            .map(|s| format!("impl {}", s))
-    }
-}
-
 pub(crate) struct TraitAliasBounds<'a> {
     generic_bounds: &'a ast::GenericBounds,
     generics: &'a ast::Generics,
@@ -1220,7 +1222,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
         } else if fits_single_line {
             Cow::from(" ")
         } else {
-            shape.indent.to_string_with_newline(&context.config)
+            shape.indent.to_string_with_newline(context.config)
         };
 
         Some(format!("{}{}{}", generic_bounds_str, space, where_str))
@@ -1238,7 +1240,7 @@ pub(crate) fn format_trait_alias(
     let alias = rewrite_ident(context, ident);
     // 6 = "trait ", 2 = " ="
     let g_shape = shape.offset_left(6)?.sub_width(2)?;
-    let generics_str = rewrite_generics(context, &alias, generics, g_shape)?;
+    let generics_str = rewrite_generics(context, alias, generics, g_shape)?;
     let vis_str = format_visibility(context, vis);
     let lhs = format!("{}trait {} =", vis_str, generics_str);
     // 1 = ";"
@@ -1386,7 +1388,7 @@ fn format_empty_struct_or_tuple(
     closer: &str,
 ) {
     // 3 = " {}" or "();"
-    let used_width = last_line_used_width(&result, offset.width()) + 3;
+    let used_width = last_line_used_width(result, offset.width()) + 3;
     if used_width > context.config.max_width() {
         result.push_str(&offset.to_string_with_newline(context.config))
     }
@@ -1509,17 +1511,84 @@ fn format_tuple_struct(
     Some(result)
 }
 
-pub(crate) fn rewrite_type<R: Rewrite>(
-    context: &RewriteContext<'_>,
+pub(crate) enum ItemVisitorKind<'a> {
+    Item(&'a ast::Item),
+    AssocTraitItem(&'a ast::AssocItem),
+    AssocImplItem(&'a ast::AssocItem),
+    ForeignItem(&'a ast::ForeignItem),
+}
+
+struct TyAliasRewriteInfo<'c, 'g>(
+    &'c RewriteContext<'c>,
+    Indent,
+    &'g ast::Generics,
+    symbol::Ident,
+    Span,
+);
+
+pub(crate) fn rewrite_type_alias<'a, 'b>(
+    ty_alias_kind: &ast::TyAlias,
+    context: &RewriteContext<'a>,
     indent: Indent,
-    ident: symbol::Ident,
-    vis: &ast::Visibility,
-    generics: &ast::Generics,
+    visitor_kind: &ItemVisitorKind<'b>,
+    span: Span,
+) -> Option<String> {
+    use ItemVisitorKind::*;
+
+    let ast::TyAlias {
+        defaultness,
+        ref generics,
+        ref bounds,
+        ref ty,
+    } = *ty_alias_kind;
+    let ty_opt = ty.as_ref().map(|t| &**t);
+    let (ident, vis) = match visitor_kind {
+        Item(i) => (i.ident, &i.vis),
+        AssocTraitItem(i) | AssocImplItem(i) => (i.ident, &i.vis),
+        ForeignItem(i) => (i.ident, &i.vis),
+    };
+    let rw_info = &TyAliasRewriteInfo(context, indent, generics, ident, span);
+
+    // Type Aliases are formatted slightly differently depending on the context
+    // in which they appear, whether they are opaque, and whether they are associated.
+    // https://rustc-dev-guide.rust-lang.org/opaque-types-type-alias-impl-trait.html
+    // https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/items.md#type-aliases
+    match (visitor_kind, ty_opt) {
+        (Item(_), None) => {
+            let op_ty = OpaqueType { bounds };
+            rewrite_ty(rw_info, Some(bounds), Some(&op_ty), vis)
+        }
+        (Item(_), Some(ty)) => rewrite_ty(rw_info, Some(bounds), Some(&*ty), vis),
+        (AssocImplItem(_), _) => {
+            let result = if let Some(ast::Ty {
+                kind: ast::TyKind::ImplTrait(_, ref bounds),
+                ..
+            }) = ty_opt
+            {
+                let op_ty = OpaqueType { bounds };
+                rewrite_ty(rw_info, None, Some(&op_ty), &DEFAULT_VISIBILITY)
+            } else {
+                rewrite_ty(rw_info, None, ty.as_ref(), vis)
+            }?;
+            match defaultness {
+                ast::Defaultness::Default(..) => Some(format!("default {}", result)),
+                _ => Some(result),
+            }
+        }
+        (AssocTraitItem(_), _) | (ForeignItem(_), _) => {
+            rewrite_ty(rw_info, Some(bounds), ty.as_ref(), vis)
+        }
+    }
+}
+
+fn rewrite_ty<R: Rewrite>(
+    rw_info: &TyAliasRewriteInfo<'_, '_>,
     generic_bounds_opt: Option<&ast::GenericBounds>,
     rhs: Option<&R>,
-    span: Span,
+    vis: &ast::Visibility,
 ) -> Option<String> {
     let mut result = String::with_capacity(128);
+    let TyAliasRewriteInfo(context, indent, generics, ident, span) = *rw_info;
     result.push_str(&format!("{}type ", format_visibility(context, vis)));
     let ident_str = rewrite_ident(context, ident);
 
@@ -1607,28 +1676,6 @@ pub(crate) fn rewrite_type<R: Rewrite>(
     }
 }
 
-pub(crate) fn rewrite_opaque_type(
-    context: &RewriteContext<'_>,
-    indent: Indent,
-    ident: symbol::Ident,
-    generic_bounds: &ast::GenericBounds,
-    generics: &ast::Generics,
-    vis: &ast::Visibility,
-    span: Span,
-) -> Option<String> {
-    let opaque_type_bounds = OpaqueTypeBounds { generic_bounds };
-    rewrite_type(
-        context,
-        indent,
-        ident,
-        vis,
-        generics,
-        Some(generic_bounds),
-        Some(&opaque_type_bounds),
-        span,
-    )
-}
-
 fn type_annotation_spacing(config: &Config) -> (&str, &str) {
     (
         if config.space_before_colon() { " " } else { "" },
@@ -1866,42 +1913,6 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
     }
 }
 
-pub(crate) fn rewrite_impl_type(
-    ident: symbol::Ident,
-    vis: &ast::Visibility,
-    defaultness: ast::Defaultness,
-    ty_opt: Option<&ptr::P<ast::Ty>>,
-    generics: &ast::Generics,
-    context: &RewriteContext<'_>,
-    indent: Indent,
-    span: Span,
-) -> Option<String> {
-    // Opaque type
-    let result = if let Some(rustc_ast::ast::Ty {
-        kind: ast::TyKind::ImplTrait(_, ref bounds),
-        ..
-    }) = ty_opt.map(|t| &**t)
-    {
-        rewrite_type(
-            context,
-            indent,
-            ident,
-            &DEFAULT_VISIBILITY,
-            generics,
-            None,
-            Some(&OpaqueType { bounds }),
-            span,
-        )
-    } else {
-        rewrite_type(context, indent, ident, vis, generics, None, ty_opt, span)
-    }?;
-
-    match defaultness {
-        ast::Defaultness::Default(..) => Some(format!("default {}", result)),
-        _ => Some(result),
-    }
-}
-
 impl Rewrite for ast::FnRetTy {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
         match *self {
@@ -2066,7 +2077,7 @@ fn rewrite_explicit_self(
                     )?;
                     Some(combine_strs_with_missing_comments(
                         context,
-                        &param_attrs,
+                        param_attrs,
                         &format!("&{} {}self", lifetime_str, mut_str),
                         span,
                         shape,
@@ -2075,7 +2086,7 @@ fn rewrite_explicit_self(
                 }
                 None => Some(combine_strs_with_missing_comments(
                     context,
-                    &param_attrs,
+                    param_attrs,
                     &format!("&{}self", mut_str),
                     span,
                     shape,
@@ -2091,7 +2102,7 @@ fn rewrite_explicit_self(
 
             Some(combine_strs_with_missing_comments(
                 context,
-                &param_attrs,
+                param_attrs,
                 &format!("{}self: {}", format_mutability(mutability), type_str),
                 span,
                 shape,
@@ -2100,7 +2111,7 @@ fn rewrite_explicit_self(
         }
         ast::SelfKind::Value(mutability) => Some(combine_strs_with_missing_comments(
             context,
-            &param_attrs,
+            param_attrs,
             &format!("{}self", format_mutability(mutability)),
             span,
             shape,
@@ -2226,7 +2237,7 @@ fn rewrite_fn_base(
     }
 
     // Skip `pub(crate)`.
-    let lo_after_visibility = get_bytepos_after_visibility(&fn_sig.visibility, span);
+    let lo_after_visibility = get_bytepos_after_visibility(fn_sig.visibility, span);
     // A conservative estimation, the goal is to be over all parens in generics
     let params_start = fn_sig
         .generics
@@ -2984,7 +2995,7 @@ fn format_header(
     let mut result = String::with_capacity(128);
     let shape = Shape::indented(offset, context.config);
 
-    result.push_str(&format_visibility(context, vis).trim());
+    result.push_str(format_visibility(context, vis).trim());
 
     // Check for a missing comment between the visibility and the item name.
     let after_vis = vis.span.hi();
@@ -3005,7 +3016,7 @@ fn format_header(
         }
     }
 
-    result.push_str(&rewrite_ident(context, ident));
+    result.push_str(rewrite_ident(context, ident));
 
     result
 }
@@ -3125,17 +3136,22 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
 
         let item_str = match self.kind {
             ast::ForeignItemKind::Fn(ref fn_kind) => {
-                let ast::FnKind(defaultness, ref fn_sig, ref generics, ref block) = **fn_kind;
-                if let Some(ref body) = block {
+                let ast::Fn {
+                    defaultness,
+                    ref sig,
+                    ref generics,
+                    ref body,
+                } = **fn_kind;
+                if let Some(ref body) = body {
                     let mut visitor = FmtVisitor::from_context(context);
                     visitor.block_indent = shape.indent;
                     visitor.last_pos = self.span.lo();
                     let inner_attrs = inner_attributes(&self.attrs);
                     let fn_ctxt = visit::FnCtxt::Foreign;
                     visitor.visit_fn(
-                        visit::FnKind::Fn(fn_ctxt, self.ident, &fn_sig, &self.vis, Some(body)),
+                        visit::FnKind::Fn(fn_ctxt, self.ident, &sig, &self.vis, Some(body)),
                         generics,
-                        &fn_sig.decl,
+                        &sig.decl,
                         self.span,
                         defaultness,
                         Some(&inner_attrs),
@@ -3146,7 +3162,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                         context,
                         shape.indent,
                         self.ident,
-                        &FnSig::from_method_sig(&fn_sig, generics, &self.vis),
+                        &FnSig::from_method_sig(&sig, generics, &self.vis),
                         span,
                         FnBraceStyle::None,
                     )
@@ -3167,19 +3183,9 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                 // 1 = ;
                 rewrite_assign_rhs(context, prefix, &**ty, shape.sub_width(1)?).map(|s| s + ";")
             }
-            ast::ForeignItemKind::TyAlias(ref ty_alias_kind) => {
-                let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref type_default) =
-                    **ty_alias_kind;
-                rewrite_type(
-                    &context,
-                    shape.indent,
-                    self.ident,
-                    &self.vis,
-                    generics,
-                    Some(generic_bounds),
-                    type_default.as_ref(),
-                    self.span,
-                )
+            ast::ForeignItemKind::TyAlias(ref ty_alias) => {
+                let (kind, span) = (&ItemVisitorKind::ForeignItem(&self), self.span);
+                rewrite_type_alias(ty_alias, context, shape.indent, kind, span)
             }
             ast::ForeignItemKind::MacCall(ref mac) => {
                 rewrite_macro(mac, None, context, shape, MacroPosition::Item)
@@ -3229,7 +3235,7 @@ fn rewrite_attrs(
     combine_strs_with_missing_comments(
         context,
         &attrs_str,
-        &item_str,
+        item_str,
         missed_span,
         shape,
         allow_extend,
index 47a7b9d4dbe3cb80baa2d08d979e9e94e2b56241..792a1080f0e92189e276168cc0344ef8ba423eba 100644 (file)
@@ -283,7 +283,7 @@ pub fn fancy_print(
         writeln!(
             t,
             "{}",
-            FormatReportFormatterBuilder::new(&self)
+            FormatReportFormatterBuilder::new(self)
                 .enable_colors(true)
                 .build()
         )?;
@@ -297,7 +297,7 @@ pub fn fancy_print(
 impl fmt::Display for FormatReport {
     // Prints all the formatting errors.
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
-        write!(fmt, "{}", FormatReportFormatterBuilder::new(&self).build())?;
+        write!(fmt, "{}", FormatReportFormatterBuilder::new(self).build())?;
         Ok(())
     }
 }
index c04b4787616933e84528d1695a386eefce5769ab..d341ec8e6b0e7d15f428cc3e91527635129f9687 100644 (file)
@@ -386,7 +386,7 @@ pub(crate) fn write_list<I, T>(items: I, formatting: &ListFormatting<'_>) -> Opt
                         result.push('\n');
                         result.push_str(indent_str);
                         // This is the width of the item (without comments).
-                        line_len = item.item.as_ref().map_or(0, |s| unicode_str_width(&s));
+                        line_len = item.item.as_ref().map_or(0, |s| unicode_str_width(s));
                     }
                 } else {
                     result.push(' ')
@@ -820,7 +820,7 @@ fn calculate_width<I, T>(items: I) -> (usize, usize)
 pub(crate) fn total_item_width(item: &ListItem) -> usize {
     comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..]))
         + comment_len(item.post_comment.as_ref().map(|x| &(*x)[..]))
-        + item.item.as_ref().map_or(0, |s| unicode_str_width(&s))
+        + item.item.as_ref().map_or(0, |s| unicode_str_width(s))
 }
 
 fn comment_len(comment: Option<&str>) -> usize {
index 927187dfd8a2336b20220dd9e794bc04171f0eff..ef747638e33ec83459e4b9f9fe02d052e41c4812 100644 (file)
@@ -186,7 +186,7 @@ fn return_macro_parse_failure_fallback(
         })
         .unwrap_or(false);
     if is_like_block_indent_style {
-        return trim_left_preserve_layout(context.snippet(span), indent, &context.config);
+        return trim_left_preserve_layout(context.snippet(span), indent, context.config);
     }
 
     context.skipped_range.borrow_mut().push((
@@ -437,7 +437,7 @@ fn rewrite_macro_inner(
             // the `macro_name!` and `{ /* macro_body */ }` but skip modifying
             // anything in between the braces (for now).
             let snippet = context.snippet(mac.span()).trim_start_matches(|c| c != '{');
-            match trim_left_preserve_layout(snippet, shape.indent, &context.config) {
+            match trim_left_preserve_layout(snippet, shape.indent, context.config) {
                 Some(macro_body) => Some(format!("{} {}", macro_name, macro_body)),
                 None => Some(format!("{} {}", macro_name, snippet)),
             }
@@ -901,7 +901,7 @@ fn add_repeat(
                     break;
                 }
                 TokenTree::Token(ref t) => {
-                    buffer.push_str(&pprust::token_to_string(&t));
+                    buffer.push_str(&pprust::token_to_string(t));
                 }
                 _ => return None,
             }
@@ -1045,7 +1045,7 @@ fn wrap_macro_args_inner(
     let mut iter = args.iter().peekable();
     let indent_str = shape.indent.to_string_with_newline(context.config);
 
-    while let Some(ref arg) = iter.next() {
+    while let Some(arg) = iter.next() {
         result.push_str(&arg.rewrite(context, shape, use_multiple_lines)?);
 
         if use_multiple_lines
@@ -1055,7 +1055,7 @@ fn wrap_macro_args_inner(
                 result.pop();
             }
             result.push_str(&indent_str);
-        } else if let Some(ref next_arg) = iter.peek() {
+        } else if let Some(next_arg) = iter.peek() {
             let space_before_dollar =
                 !arg.kind.ends_with_space() && next_arg.kind.starts_with_dollar();
             let space_before_brace = next_arg.kind.starts_with_brace();
@@ -1370,7 +1370,7 @@ fn rewrite(
                     {
                         s += &indent_str;
                     }
-                    (s + l + "\n", indent_next_line(kind, &l, &config))
+                    (s + l + "\n", indent_next_line(kind, l, &config))
                 },
             )
             .0;
@@ -1514,11 +1514,11 @@ fn rewrite_macro_with_items(
             MacroArg::Item(item) => item,
             _ => return None,
         };
-        visitor.visit_item(&item);
+        visitor.visit_item(item);
     }
 
     let mut result = String::with_capacity(256);
-    result.push_str(&macro_name);
+    result.push_str(macro_name);
     result.push_str(opener);
     result.push_str(&visitor.block_indent.to_string_with_newline(context.config));
     result.push_str(visitor.buffer.trim());
index 5a6ed0ec06e55a37ca203bafdbd9625a2ad3ce4c..22d23fc1cdba49bc3f1f68fc4247f5f521ceeabd 100644 (file)
@@ -168,7 +168,7 @@ fn collect_beginning_verts(
         .map(|a| {
             context
                 .snippet(a.pat.span)
-                .starts_with("|")
+                .starts_with('|')
                 .then(|| a.pat.span().lo())
         })
         .collect()
@@ -319,7 +319,7 @@ fn flatten_arm_body<'a>(
     let can_extend =
         |expr| !context.config.force_multiline_blocks() && can_flatten_block_around_this(expr);
 
-    if let Some(ref block) = block_can_be_flattened(context, body) {
+    if let Some(block) = block_can_be_flattened(context, body) {
         if let ast::StmtKind::Expr(ref expr) = block.stmts[0].kind {
             if let ast::ExprKind::Block(..) = expr.kind {
                 flatten_arm_body(context, expr, None)
@@ -393,7 +393,7 @@ fn rewrite_match_body(
         if comment_str.is_empty() {
             String::new()
         } else {
-            rewrite_comment(comment_str, false, shape, &context.config)?
+            rewrite_comment(comment_str, false, shape, context.config)?
         }
     };
 
@@ -408,8 +408,8 @@ fn rewrite_match_body(
                 result.push_str(&arrow_comment);
             }
             result.push_str(&nested_indent_str);
-            result.push_str(&body_str);
-            result.push_str(&comma);
+            result.push_str(body_str);
+            result.push_str(comma);
             return Some(result);
         }
 
@@ -451,7 +451,7 @@ fn rewrite_match_body(
             result.push_str(&arrow_comment);
         }
         result.push_str(&block_sep);
-        result.push_str(&body_str);
+        result.push_str(body_str);
         result.push_str(&body_suffix);
         Some(result)
     };
index ded34d9032f91f188c11c9437b41691cdcce75b5..b1f229d9daaf5f411082f260aa68e358de077dc9 100644 (file)
@@ -16,7 +16,7 @@
     Directory, DirectoryOwnership, ModError, ModulePathSuccess, Parser, ParserError,
 };
 use crate::syntux::session::ParseSess;
-use crate::utils::contains_skip;
+use crate::utils::{contains_skip, mk_sp};
 
 mod visitor;
 
@@ -135,10 +135,12 @@ pub(crate) fn visit_crate(
             self.visit_mod_from_ast(&krate.items)?;
         }
 
+        let snippet_provider = self.parse_sess.snippet_provider(krate.span);
+
         self.file_map.insert(
             root_filename,
             Module::new(
-                krate.span,
+                mk_sp(snippet_provider.start_pos(), snippet_provider.end_pos()),
                 None,
                 Cow::Borrowed(&krate.items),
                 Cow::Borrowed(&krate.attrs),
@@ -197,7 +199,7 @@ fn visit_mod_outside_ast(
     /// Visit modules from AST.
     fn visit_mod_from_ast(
         &mut self,
-        items: &'ast Vec<rustc_ast::ptr::P<ast::Item>>,
+        items: &'ast [rustc_ast::ptr::P<ast::Item>],
     ) -> Result<(), ModuleResolutionError> {
         for item in items {
             if is_cfg_if(item) {
@@ -290,7 +292,7 @@ fn visit_sub_mod_inner(
                 };
                 self.visit_sub_mod_after_directory_update(sub_mod, Some(directory))
             }
-            SubModKind::Internal(ref item) => {
+            SubModKind::Internal(item) => {
                 self.push_inline_mod_directory(item.ident, &item.attrs);
                 self.visit_sub_mod_after_directory_update(sub_mod, None)
             }
@@ -317,9 +319,11 @@ fn visit_sub_mod_after_directory_update(
         }
         match (sub_mod.ast_mod_kind, sub_mod.items) {
             (Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _))), _) => {
-                self.visit_mod_from_ast(&items)
+                self.visit_mod_from_ast(items)
+            }
+            (Some(Cow::Owned(ast::ModKind::Loaded(items, _, _))), _) | (_, Cow::Owned(items)) => {
+                self.visit_mod_outside_ast(items)
             }
-            (Some(Cow::Owned(..)), Cow::Owned(items)) => self.visit_mod_outside_ast(items),
             (_, _) => Ok(()),
         }
     }
index ac24181c7805258b89c053d6c444a65709f79af6..3475f5c378cd2fbde554e4a79d0c191bf99d0a97 100644 (file)
@@ -394,7 +394,7 @@ fn rewrite_last_item_with_overflow(
     ) -> Option<String> {
         let last_item = self.last_item()?;
         let rewrite = match last_item {
-            OverflowableItem::Expr(ref expr) => {
+            OverflowableItem::Expr(expr) => {
                 match expr.kind {
                     // When overflowing the closure which consists of a single control flow
                     // expression, force to use block if its condition uses multi line.
index 0f3d5e8f878ba7d7f08883e95c40262bf2d8adfa..d1c75126ea4a7fce24a8eede42ecd677df916d3e 100644 (file)
@@ -55,11 +55,11 @@ fn rewrite_pairs_one_line<T: Rewrite>(
 
     for ((_, rewrite), s) in list.list.iter().zip(list.separators.iter()) {
         if let Some(rewrite) = rewrite {
-            if !is_single_line(&rewrite) || result.len() > shape.width {
+            if !is_single_line(rewrite) || result.len() > shape.width {
                 return None;
             }
 
-            result.push_str(&rewrite);
+            result.push_str(rewrite);
             result.push(' ');
             result.push_str(s);
             result.push(' ');
@@ -94,18 +94,18 @@ fn rewrite_pairs_multiline<T: Rewrite>(
     shape: Shape,
     context: &RewriteContext<'_>,
 ) -> Option<String> {
-    let rhs_offset = shape.rhs_overhead(&context.config);
+    let rhs_offset = shape.rhs_overhead(context.config);
     let nested_shape = (match context.config.indent_style() {
         IndentStyle::Visual => shape.visual_indent(0),
         IndentStyle::Block => shape.block_indent(context.config.tab_spaces()),
     })
-    .with_max_width(&context.config)
+    .with_max_width(context.config)
     .sub_width(rhs_offset)?;
 
     let indent_str = nested_shape.indent.to_string_with_newline(context.config);
     let mut result = String::new();
 
-    result.push_str(&list.list[0].1.as_ref()?);
+    result.push_str(list.list[0].1.as_ref()?);
 
     for ((e, default_rw), s) in list.list[1..].iter().zip(list.separators.iter()) {
         // The following test checks if we should keep two subexprs on the same
@@ -144,7 +144,7 @@ fn rewrite_pairs_multiline<T: Rewrite>(
             }
         }
 
-        result.push_str(&default_rw.as_ref()?);
+        result.push_str(default_rw.as_ref()?);
     }
     Some(result)
 }
@@ -264,12 +264,12 @@ fn flatten(
                 return node.rewrite(context, shape);
             }
             let nested_overhead = sep + 1;
-            let rhs_offset = shape.rhs_overhead(&context.config);
+            let rhs_offset = shape.rhs_overhead(context.config);
             let nested_shape = (match context.config.indent_style() {
                 IndentStyle::Visual => shape.visual_indent(0),
                 IndentStyle::Block => shape.block_indent(context.config.tab_spaces()),
             })
-            .with_max_width(&context.config)
+            .with_max_width(context.config)
             .sub_width(rhs_offset)?;
             let default_shape = match context.config.binop_separator() {
                 SeparatorPlace::Back => nested_shape.sub_width(nested_overhead)?,
index ba8d8024a9707c34ef31c4eae24665eb99f5f39d..a80d63201f982902a385d4a192273810fef1edce 100644 (file)
@@ -456,11 +456,11 @@ fn rewrite_tuple_pat(
     context: &RewriteContext<'_>,
     shape: Shape,
 ) -> Option<String> {
-    let mut pat_vec: Vec<_> = pats.iter().map(|x| TuplePatField::Pat(x)).collect();
-
-    if pat_vec.is_empty() {
+    if pats.is_empty() {
         return Some(format!("{}()", path_str.unwrap_or_default()));
     }
+    let mut pat_vec: Vec<_> = pats.iter().map(TuplePatField::Pat).collect();
+
     let wildcard_suffix_len = count_wildcard_suffix_len(context, &pat_vec, span, shape);
     let (pat_vec, span) = if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2
     {
@@ -482,7 +482,7 @@ fn rewrite_tuple_pat(
     let path_str = path_str.unwrap_or_default();
 
     overflow::rewrite_with_parens(
-        &context,
+        context,
         &path_str,
         pat_vec.iter(),
         shape,
index 2c58350d4feb6d8e0bf9a3cbfc15d084a0af73a7..0732c8ee70059ca372ff28c0d2445a2394c586e8 100644 (file)
@@ -118,7 +118,9 @@ fn rewrite_reorderable_or_regroupable_items(
             };
 
             let mut regrouped_items = match context.config.group_imports() {
-                GroupImportsTactic::Preserve => vec![normalized_items],
+                GroupImportsTactic::Preserve | GroupImportsTactic::One => {
+                    vec![normalized_items]
+                }
                 GroupImportsTactic::StdExternalCrate => group_imports(normalized_items),
             };
 
index b5fe4335dd33dff97c682f1820ab14acd748dffc..d1bb2f80004aa08461ddf0306bf2285130f80e35 100644 (file)
@@ -112,7 +112,7 @@ pub(crate) fn parse_file_as_module(
         span: Span,
     ) -> Result<(Vec<ast::Attribute>, Vec<ptr::P<ast::Item>>, Span), ParserError> {
         let result = catch_unwind(AssertUnwindSafe(|| {
-            let mut parser = new_parser_from_file(sess.inner(), &path, Some(span));
+            let mut parser = new_parser_from_file(sess.inner(), path, Some(span));
             match parser.parse_mod(&TokenKind::Eof) {
                 Ok(result) => Some(result),
                 Err(mut e) => {
@@ -125,18 +125,12 @@ pub(crate) fn parse_file_as_module(
             }
         }));
         match result {
-            Ok(Some(m)) => {
-                if !sess.has_errors() {
-                    return Ok(m);
-                }
-
-                if sess.can_reset_errors() {
-                    sess.reset_errors();
-                    return Ok(m);
-                }
-                Err(ParserError::ParseError)
+            Ok(Some(m)) if !sess.has_errors() => Ok(m),
+            Ok(Some(m)) if sess.can_reset_errors() => {
+                sess.reset_errors();
+                Ok(m)
             }
-            Ok(None) => Err(ParserError::ParseError),
+            Ok(_) => Err(ParserError::ParseError),
             Err(..) if path.exists() => Err(ParserError::ParseError),
             Err(_) => Err(ParserError::ParsePanicError),
         }
index 946c076d9f2d1fdf388b19156c5c2a7b5ca254e0..cdb4893d443b9b381cde8e4c1d284aee5154ddd4 100644 (file)
@@ -164,7 +164,7 @@ pub(crate) fn is_file_parsed(&self, path: &Path) -> bool {
     }
 
     pub(crate) fn ignore_file(&self, path: &FileName) -> bool {
-        self.ignore_path_set.as_ref().is_match(&path)
+        self.ignore_path_set.as_ref().is_match(path)
     }
 
     pub(crate) fn set_silent_emitter(&mut self) {
index 48d61289a9b8f34a25d89237f5842a1d4245ed29..e2620508c340bad91699e8ebd90b36f2a80f6049 100644 (file)
@@ -535,9 +535,9 @@ fn check_files(files: Vec<PathBuf>, opt_config: &Option<PathBuf>) -> (Vec<Format
 
         debug!("Testing '{}'...", file_name.display());
 
-        match idempotent_check(&file_name, &opt_config) {
+        match idempotent_check(&file_name, opt_config) {
             Ok(ref report) if report.has_warnings() => {
-                print!("{}", FormatReportFormatterBuilder::new(&report).build());
+                print!("{}", FormatReportFormatterBuilder::new(report).build());
                 fails += 1;
             }
             Ok(report) => reports.push(report),
index e0b55e3efb2c4f5714f09abad473ff7b498aaa96..ae4a0d0fccb191003dd5bdc04d2378c1b6707228 100644 (file)
@@ -5,21 +5,39 @@
 
 use crate::{FileName, Input, Session};
 
-#[test]
-fn nested_out_of_line_mods_loaded() {
-    // See also https://github.com/rust-lang/rustfmt/issues/4874
-    let filename = "tests/mod-resolver/issue-4874/main.rs";
-    let input_file = PathBuf::from(filename);
+fn verify_mod_resolution(input_file_name: &str, exp_misformatted_files: &[&str]) {
+    let input_file = PathBuf::from(input_file_name);
     let config = read_config(&input_file);
     let mut session = Session::<io::Stdout>::new(config, None);
     let report = session
-        .format(Input::File(filename.into()))
+        .format(Input::File(input_file_name.into()))
         .expect("Should not have had any execution errors");
     let errors_by_file = &report.internal.borrow().0;
-    assert!(errors_by_file.contains_key(&FileName::Real(PathBuf::from(
-        "tests/mod-resolver/issue-4874/bar/baz.rs",
-    ))));
-    assert!(errors_by_file.contains_key(&FileName::Real(PathBuf::from(
-        "tests/mod-resolver/issue-4874/foo/qux.rs",
-    ))));
+    for exp_file in exp_misformatted_files {
+        assert!(errors_by_file.contains_key(&FileName::Real(PathBuf::from(exp_file))));
+    }
+}
+
+#[test]
+fn nested_out_of_line_mods_loaded() {
+    // See also https://github.com/rust-lang/rustfmt/issues/4874
+    verify_mod_resolution(
+        "tests/mod-resolver/issue-4874/main.rs",
+        &[
+            "tests/mod-resolver/issue-4874/bar/baz.rs",
+            "tests/mod-resolver/issue-4874/foo/qux.rs",
+        ],
+    );
+}
+
+#[test]
+fn out_of_line_nested_inline_within_out_of_line() {
+    // See also https://github.com/rust-lang/rustfmt/issues/5063
+    verify_mod_resolution(
+        "tests/mod-resolver/issue-5063/main.rs",
+        &[
+            "tests/mod-resolver/issue-5063/foo/bar/baz.rs",
+            "tests/mod-resolver/issue-5063/foo.rs",
+        ],
+    );
 }
index 62c05ba078c56facce55f848d2b4cee53e0a1c78..9ea90c5e46dd87104522dd220558e7127ade7cdb 100644 (file)
@@ -728,7 +728,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                     result = combine_strs_with_missing_comments(
                         context,
                         result.trim_end(),
-                        &mt.ty.rewrite(&context, shape)?,
+                        &mt.ty.rewrite(context, shape)?,
                         before_ty_span,
                         shape,
                         true,
@@ -738,7 +738,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                     let budget = shape.width.checked_sub(used_width)?;
                     let ty_str = mt
                         .ty
-                        .rewrite(&context, Shape::legacy(budget, shape.indent + used_width))?;
+                        .rewrite(context, Shape::legacy(budget, shape.indent + used_width))?;
                     result.push_str(&ty_str);
                 }
 
index 29e1e070d41114079921683fea87f7cd62ec941f..3a8713c5bdb01d678f41892a2a149ee8946e8575 100644 (file)
@@ -42,7 +42,7 @@ pub(crate) fn is_same_visibility(a: &Visibility, b: &Visibility) -> bool {
         (
             VisibilityKind::Restricted { path: p, .. },
             VisibilityKind::Restricted { path: q, .. },
-        ) => pprust::path_to_string(&p) == pprust::path_to_string(&q),
+        ) => pprust::path_to_string(p) == pprust::path_to_string(q),
         (VisibilityKind::Public, VisibilityKind::Public)
         | (VisibilityKind::Inherited, VisibilityKind::Inherited)
         | (
@@ -689,7 +689,7 @@ mod test {
     #[test]
     fn test_remove_trailing_white_spaces() {
         let s = "    r#\"\n        test\n    \"#";
-        assert_eq!(remove_trailing_white_spaces(&s), s);
+        assert_eq!(remove_trailing_white_spaces(s), s);
     }
 
     #[test]
@@ -698,7 +698,7 @@ fn test_trim_left_preserve_layout() {
         let config = Config::default();
         let indent = Indent::new(4, 0);
         assert_eq!(
-            trim_left_preserve_layout(&s, indent, &config),
+            trim_left_preserve_layout(s, indent, &config),
             Some("aaa\n    bbb\n    ccc".to_string())
         );
     }
index d854d90b40b6d9d33e7f7ff4917d8c872c97f6a5..527042d098a1c61f7d6252438ea4b97ba741c5d7 100644 (file)
@@ -12,8 +12,7 @@
 use crate::coverage::transform_missing_snippet;
 use crate::items::{
     format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_extern_crate,
-    rewrite_impl_type, rewrite_opaque_type, rewrite_type, FnBraceStyle, FnSig, StaticParts,
-    StructParts,
+    rewrite_type_alias, FnBraceStyle, FnSig, ItemVisitorKind, StaticParts, StructParts,
 };
 use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition};
 use crate::modules::Module;
@@ -164,7 +163,7 @@ fn visit_stmt(&mut self, stmt: &Stmt<'_>, include_empty_semi: bool) {
                     );
                 } else {
                     let shape = self.shape();
-                    let rewrite = self.with_context(|ctx| stmt.rewrite(&ctx, shape));
+                    let rewrite = self.with_context(|ctx| stmt.rewrite(ctx, shape));
                     self.push_rewrite(stmt.span(), rewrite)
                 }
             }
@@ -273,9 +272,9 @@ fn close_block(&mut self, span: Span, unindent_comment: bool) {
 
         let comment_snippet = self.snippet(span);
 
-        let align_to_right = if unindent_comment && contains_comment(&comment_snippet) {
+        let align_to_right = if unindent_comment && contains_comment(comment_snippet) {
             let first_lines = comment_snippet.splitn(2, '/').next().unwrap_or("");
-            last_line_width(first_lines) > last_line_width(&comment_snippet)
+            last_line_width(first_lines) > last_line_width(comment_snippet)
         } else {
             false
         };
@@ -439,7 +438,7 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) {
         let filtered_attrs;
         let mut attrs = &item.attrs;
         let skip_context_saved = self.skip_context.clone();
-        self.skip_context.update_with_attrs(&attrs);
+        self.skip_context.update_with_attrs(attrs);
 
         let should_visit_node_again = match item.kind {
             // For use/extern crate items, skip rewriting attributes but check for a skip attribute.
@@ -488,12 +487,12 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) {
                 ast::ItemKind::Use(ref tree) => self.format_import(item, tree),
                 ast::ItemKind::Impl { .. } => {
                     let block_indent = self.block_indent;
-                    let rw = self.with_context(|ctx| format_impl(&ctx, item, block_indent));
+                    let rw = self.with_context(|ctx| format_impl(ctx, item, block_indent));
                     self.push_rewrite(item.span, rw);
                 }
                 ast::ItemKind::Trait(..) => {
                     let block_indent = self.block_indent;
-                    let rw = self.with_context(|ctx| format_trait(&ctx, item, block_indent));
+                    let rw = self.with_context(|ctx| format_trait(ctx, item, block_indent));
                     self.push_rewrite(item.span, rw);
                 }
                 ast::ItemKind::TraitAlias(ref generics, ref generic_bounds) => {
@@ -540,24 +539,22 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) {
                     self.visit_static(&StaticParts::from_item(item));
                 }
                 ast::ItemKind::Fn(ref fn_kind) => {
-                    let ast::FnKind(defaultness, ref fn_signature, ref generics, ref block) =
-                        **fn_kind;
-                    if let Some(ref body) = block {
+                    let ast::Fn {
+                        defaultness,
+                        ref sig,
+                        ref generics,
+                        ref body,
+                    } = **fn_kind;
+                    if let Some(ref body) = body {
                         let inner_attrs = inner_attributes(&item.attrs);
-                        let fn_ctxt = match fn_signature.header.ext {
+                        let fn_ctxt = match sig.header.ext {
                             ast::Extern::None => visit::FnCtxt::Free,
                             _ => visit::FnCtxt::Foreign,
                         };
                         self.visit_fn(
-                            visit::FnKind::Fn(
-                                fn_ctxt,
-                                item.ident,
-                                &fn_signature,
-                                &item.vis,
-                                Some(body),
-                            ),
+                            visit::FnKind::Fn(fn_ctxt, item.ident, &sig, &item.vis, Some(body)),
                             generics,
-                            &fn_signature.decl,
+                            &sig.decl,
                             item.span,
                             defaultness,
                             Some(&inner_attrs),
@@ -565,46 +562,14 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) {
                     } else {
                         let indent = self.block_indent;
                         let rewrite = self.rewrite_required_fn(
-                            indent,
-                            item.ident,
-                            &fn_signature,
-                            &item.vis,
-                            generics,
-                            item.span,
+                            indent, item.ident, &sig, &item.vis, generics, item.span,
                         );
                         self.push_rewrite(item.span, rewrite);
                     }
                 }
-                ast::ItemKind::TyAlias(ref alias_kind) => {
-                    let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref ty) =
-                        **alias_kind;
-                    match ty {
-                        Some(ty) => {
-                            let rewrite = rewrite_type(
-                                &self.get_context(),
-                                self.block_indent,
-                                item.ident,
-                                &item.vis,
-                                generics,
-                                Some(generic_bounds),
-                                Some(&*ty),
-                                item.span,
-                            );
-                            self.push_rewrite(item.span, rewrite);
-                        }
-                        None => {
-                            let rewrite = rewrite_opaque_type(
-                                &self.get_context(),
-                                self.block_indent,
-                                item.ident,
-                                generic_bounds,
-                                generics,
-                                &item.vis,
-                                item.span,
-                            );
-                            self.push_rewrite(item.span, rewrite);
-                        }
-                    }
+                ast::ItemKind::TyAlias(ref ty_alias) => {
+                    use ItemVisitorKind::Item;
+                    self.visit_ty_alias_kind(ty_alias, &Item(&item), item.span);
                 }
                 ast::ItemKind::GlobalAsm(..) => {
                     let snippet = Some(self.snippet(item.span).to_owned());
@@ -627,108 +592,86 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) {
         self.skip_context = skip_context_saved;
     }
 
-    pub(crate) fn visit_trait_item(&mut self, ti: &ast::AssocItem) {
-        skip_out_of_file_lines_range_visitor!(self, ti.span);
+    fn visit_ty_alias_kind(
+        &mut self,
+        ty_kind: &ast::TyAlias,
+        visitor_kind: &ItemVisitorKind<'_>,
+        span: Span,
+    ) {
+        let rewrite = rewrite_type_alias(
+            ty_kind,
+            &self.get_context(),
+            self.block_indent,
+            visitor_kind,
+            span,
+        );
+        self.push_rewrite(span, rewrite);
+    }
+
+    fn visit_assoc_item(&mut self, visitor_kind: &ItemVisitorKind<'_>) {
+        use ItemVisitorKind::*;
+        // TODO(calebcartwright): Not sure the skip spans are correct
+        let (ai, skip_span, assoc_ctxt) = match visitor_kind {
+            AssocTraitItem(ai) => (*ai, ai.span(), visit::AssocCtxt::Trait),
+            AssocImplItem(ai) => (*ai, ai.span, visit::AssocCtxt::Impl),
+            _ => unreachable!(),
+        };
+        skip_out_of_file_lines_range_visitor!(self, ai.span);
 
-        if self.visit_attrs(&ti.attrs, ast::AttrStyle::Outer) {
-            self.push_skipped_with_span(ti.attrs.as_slice(), ti.span(), ti.span());
+        if self.visit_attrs(&ai.attrs, ast::AttrStyle::Outer) {
+            self.push_skipped_with_span(&ai.attrs.as_slice(), skip_span, skip_span);
             return;
         }
 
         // TODO(calebcartwright): consider enabling box_patterns feature gate
-        match ti.kind {
-            ast::AssocItemKind::Const(..) => self.visit_static(&StaticParts::from_trait_item(ti)),
-            ast::AssocItemKind::Fn(ref fn_kind) => {
-                let ast::FnKind(defaultness, ref sig, ref generics, ref block) = **fn_kind;
-                if let Some(ref body) = block {
-                    let inner_attrs = inner_attributes(&ti.attrs);
-                    let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Trait);
+        match (&ai.kind, visitor_kind) {
+            (ast::AssocItemKind::Const(..), AssocTraitItem(_)) => {
+                self.visit_static(&StaticParts::from_trait_item(&ai))
+            }
+            (ast::AssocItemKind::Const(..), AssocImplItem(_)) => {
+                self.visit_static(&StaticParts::from_impl_item(&ai))
+            }
+            (ast::AssocItemKind::Fn(ref fn_kind), _) => {
+                let ast::Fn {
+                    defaultness,
+                    ref sig,
+                    ref generics,
+                    ref body,
+                } = **fn_kind;
+                if let Some(ref body) = body {
+                    let inner_attrs = inner_attributes(&ai.attrs);
+                    let fn_ctxt = visit::FnCtxt::Assoc(assoc_ctxt);
                     self.visit_fn(
-                        visit::FnKind::Fn(fn_ctxt, ti.ident, sig, &ti.vis, Some(body)),
+                        visit::FnKind::Fn(fn_ctxt, ai.ident, sig, &ai.vis, Some(body)),
                         generics,
                         &sig.decl,
-                        ti.span,
+                        ai.span,
                         defaultness,
                         Some(&inner_attrs),
                     );
                 } else {
                     let indent = self.block_indent;
                     let rewrite =
-                        self.rewrite_required_fn(indent, ti.ident, sig, &ti.vis, generics, ti.span);
-                    self.push_rewrite(ti.span, rewrite);
+                        self.rewrite_required_fn(indent, ai.ident, sig, &ai.vis, generics, ai.span);
+                    self.push_rewrite(ai.span, rewrite);
                 }
             }
-            ast::AssocItemKind::TyAlias(ref ty_alias_kind) => {
-                let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref type_default) =
-                    **ty_alias_kind;
-                let rewrite = rewrite_type(
-                    &self.get_context(),
-                    self.block_indent,
-                    ti.ident,
-                    &ti.vis,
-                    generics,
-                    Some(generic_bounds),
-                    type_default.as_ref(),
-                    ti.span,
-                );
-                self.push_rewrite(ti.span, rewrite);
+            (ast::AssocItemKind::TyAlias(ref ty_alias), _) => {
+                self.visit_ty_alias_kind(ty_alias, visitor_kind, ai.span);
             }
-            ast::AssocItemKind::MacCall(ref mac) => {
-                self.visit_mac(mac, Some(ti.ident), MacroPosition::Item);
+            (ast::AssocItemKind::MacCall(ref mac), _) => {
+                self.visit_mac(mac, Some(ai.ident), MacroPosition::Item);
             }
+            _ => unreachable!(),
         }
     }
 
-    pub(crate) fn visit_impl_item(&mut self, ii: &ast::AssocItem) {
-        skip_out_of_file_lines_range_visitor!(self, ii.span);
-
-        if self.visit_attrs(&ii.attrs, ast::AttrStyle::Outer) {
-            self.push_skipped_with_span(ii.attrs.as_slice(), ii.span, ii.span);
-            return;
-        }
+    pub(crate) fn visit_trait_item(&mut self, ti: &ast::AssocItem) {
+        self.visit_assoc_item(&ItemVisitorKind::AssocTraitItem(ti));
+    }
 
-        match ii.kind {
-            ast::AssocItemKind::Fn(ref fn_kind) => {
-                let ast::FnKind(defaultness, ref sig, ref generics, ref block) = **fn_kind;
-                if let Some(ref body) = block {
-                    let inner_attrs = inner_attributes(&ii.attrs);
-                    let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Impl);
-                    self.visit_fn(
-                        visit::FnKind::Fn(fn_ctxt, ii.ident, sig, &ii.vis, Some(body)),
-                        generics,
-                        &sig.decl,
-                        ii.span,
-                        defaultness,
-                        Some(&inner_attrs),
-                    );
-                } else {
-                    let indent = self.block_indent;
-                    let rewrite =
-                        self.rewrite_required_fn(indent, ii.ident, sig, &ii.vis, generics, ii.span);
-                    self.push_rewrite(ii.span, rewrite);
-                }
-            }
-            ast::AssocItemKind::Const(..) => self.visit_static(&StaticParts::from_impl_item(ii)),
-            ast::AssocItemKind::TyAlias(ref ty_alias_kind) => {
-                let ast::TyAliasKind(defaultness, ref generics, _, ref ty) = **ty_alias_kind;
-                self.push_rewrite(
-                    ii.span,
-                    rewrite_impl_type(
-                        ii.ident,
-                        &ii.vis,
-                        defaultness,
-                        ty.as_ref(),
-                        &generics,
-                        &self.get_context(),
-                        self.block_indent,
-                        ii.span,
-                    ),
-                );
-            }
-            ast::AssocItemKind::MacCall(ref mac) => {
-                self.visit_mac(mac, Some(ii.ident), MacroPosition::Item);
-            }
-        }
+    pub(crate) fn visit_impl_item(&mut self, ii: &ast::AssocItem) {
+        self.visit_assoc_item(&ItemVisitorKind::AssocImplItem(ii));
     }
 
     fn visit_mac(&mut self, mac: &ast::MacCall, ident: Option<symbol::Ident>, pos: MacroPosition) {
@@ -905,7 +848,7 @@ fn is_unknown_rustfmt_attr(&self, segments: &[ast::PathSegment]) -> bool {
     }
 
     fn walk_mod_items(&mut self, items: &[rustc_ast::ptr::P<ast::Item>]) {
-        self.visit_items_with_reordering(&ptr_vec_to_ref_vec(&items));
+        self.visit_items_with_reordering(&ptr_vec_to_ref_vec(items));
     }
 
     fn walk_stmts(&mut self, stmts: &[Stmt<'_>], include_current_empty_semi: bool) {
diff --git a/src/tools/rustfmt/tests/mod-resolver/issue-5063/foo.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5063/foo.rs
new file mode 100644 (file)
index 0000000..d569747
--- /dev/null
@@ -0,0 +1,2 @@
+mod bar {
+        mod baz;}
\ No newline at end of file
diff --git a/src/tools/rustfmt/tests/mod-resolver/issue-5063/foo/bar/baz.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5063/foo/bar/baz.rs
new file mode 100644 (file)
index 0000000..3519b0e
--- /dev/null
@@ -0,0 +1 @@
+fn    baz()    {       }
\ No newline at end of file
diff --git a/src/tools/rustfmt/tests/mod-resolver/issue-5063/main.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5063/main.rs
new file mode 100644 (file)
index 0000000..41c81c7
--- /dev/null
@@ -0,0 +1,5 @@
+fn main() {
+    println!("Hello, world!");
+}
+
+mod foo;
\ No newline at end of file
diff --git a/src/tools/rustfmt/tests/source/configs/group_imports/One-merge_imports.rs b/src/tools/rustfmt/tests/source/configs/group_imports/One-merge_imports.rs
new file mode 100644 (file)
index 0000000..157d385
--- /dev/null
@@ -0,0 +1,17 @@
+// rustfmt-group_imports: One
+// rustfmt-imports_granularity: Crate
+use chrono::Utc;
+use super::update::convert_publish_payload;
+
+use juniper::{FieldError, FieldResult};
+use uuid::Uuid;
+use alloc::alloc::Layout;
+
+use std::sync::Arc;
+use alloc::vec::Vec;
+
+use broker::database::PooledConnection;
+
+use super::schema::{Context, Payload};
+use core::f32;
+use crate::models::Event;
diff --git a/src/tools/rustfmt/tests/source/configs/group_imports/One-nested.rs b/src/tools/rustfmt/tests/source/configs/group_imports/One-nested.rs
new file mode 100644 (file)
index 0000000..109bd07
--- /dev/null
@@ -0,0 +1,7 @@
+// rustfmt-group_imports: One
+mod test {
+    use crate::foo::bar;
+
+    use std::path;
+    use crate::foo::bar2;
+}
diff --git a/src/tools/rustfmt/tests/source/configs/group_imports/One-no_reorder.rs b/src/tools/rustfmt/tests/source/configs/group_imports/One-no_reorder.rs
new file mode 100644 (file)
index 0000000..f82f62c
--- /dev/null
@@ -0,0 +1,16 @@
+// rustfmt-group_imports: One
+// rustfmt-reorder_imports: false
+use chrono::Utc;
+use super::update::convert_publish_payload;
+
+use juniper::{FieldError, FieldResult};
+use uuid::Uuid;
+use alloc::alloc::Layout;
+
+use std::sync::Arc;
+
+use broker::database::PooledConnection;
+
+use super::schema::{Context, Payload};
+use core::f32;
+use crate::models::Event;
diff --git a/src/tools/rustfmt/tests/source/configs/group_imports/One.rs b/src/tools/rustfmt/tests/source/configs/group_imports/One.rs
new file mode 100644 (file)
index 0000000..5ab7a95
--- /dev/null
@@ -0,0 +1,15 @@
+// rustfmt-group_imports: One
+use chrono::Utc;
+use super::update::convert_publish_payload;
+
+use juniper::{FieldError, FieldResult};
+use uuid::Uuid;
+use alloc::alloc::Layout;
+
+use std::sync::Arc;
+
+use broker::database::PooledConnection;
+
+use super::schema::{Context, Payload};
+use core::f32;
+use crate::models::Event;
diff --git a/src/tools/rustfmt/tests/source/empty-item-single-line-false.rs b/src/tools/rustfmt/tests/source/empty-item-single-line-false.rs
new file mode 100644 (file)
index 0000000..20c5bc8
--- /dev/null
@@ -0,0 +1,46 @@
+// rustfmt-brace_style: AlwaysNextLine
+// rustfmt-empty_item_single_line: false
+
+fn function()
+{
+
+}
+
+struct Struct
+{
+
+}
+
+enum Enum
+{
+
+}
+
+trait Trait
+{
+
+}
+
+impl<T> Trait for T
+{
+
+}
+
+trait Trait2<T>
+where
+    T: Copy + Display + Write + Read + FromStr, {}
+
+trait Trait3<T>
+where
+    T: Something
+        + SomethingElse
+        + Sync
+        + Send
+        + Display
+        + Debug
+        + Copy
+        + Hash
+        + Debug
+        + Display
+        + Write
+        + Read, {}
index 38094d67a77374b289a06cae9e0fbdf5e49c29a8..0fb6405120aa7c5d7205c3bd6b126383ac36d1c2 100644 (file)
@@ -27,3 +27,38 @@ enum C<T> where T: Copy {}
 
     struct D<T> where T: Copy {}
 }
+
+
+fn function()
+{
+
+}
+
+trait Trait
+{
+
+}
+
+impl<T> Trait for T
+{
+
+}
+
+trait Trait2<T>
+where
+    T: Copy + Display + Write + Read + FromStr, {}
+
+trait Trait3<T>
+where
+    T: Something
+        + SomethingElse
+        + Sync
+        + Send
+        + Display
+        + Debug
+        + Copy
+        + Hash
+        + Debug
+        + Display
+        + Write
+        + Read, {}
diff --git a/src/tools/rustfmt/tests/target/configs/group_imports/One-merge_imports.rs b/src/tools/rustfmt/tests/target/configs/group_imports/One-merge_imports.rs
new file mode 100644 (file)
index 0000000..52e0e1c
--- /dev/null
@@ -0,0 +1,14 @@
+// rustfmt-group_imports: One
+// rustfmt-imports_granularity: Crate
+use super::{
+    schema::{Context, Payload},
+    update::convert_publish_payload,
+};
+use crate::models::Event;
+use alloc::{alloc::Layout, vec::Vec};
+use broker::database::PooledConnection;
+use chrono::Utc;
+use core::f32;
+use juniper::{FieldError, FieldResult};
+use std::sync::Arc;
+use uuid::Uuid;
diff --git a/src/tools/rustfmt/tests/target/configs/group_imports/One-nested.rs b/src/tools/rustfmt/tests/target/configs/group_imports/One-nested.rs
new file mode 100644 (file)
index 0000000..5b64854
--- /dev/null
@@ -0,0 +1,6 @@
+// rustfmt-group_imports: One
+mod test {
+    use crate::foo::bar;
+    use crate::foo::bar2;
+    use std::path;
+}
diff --git a/src/tools/rustfmt/tests/target/configs/group_imports/One-no_reorder.rs b/src/tools/rustfmt/tests/target/configs/group_imports/One-no_reorder.rs
new file mode 100644 (file)
index 0000000..015e841
--- /dev/null
@@ -0,0 +1,12 @@
+// rustfmt-group_imports: One
+// rustfmt-reorder_imports: false
+use chrono::Utc;
+use super::update::convert_publish_payload;
+use juniper::{FieldError, FieldResult};
+use uuid::Uuid;
+use alloc::alloc::Layout;
+use std::sync::Arc;
+use broker::database::PooledConnection;
+use super::schema::{Context, Payload};
+use core::f32;
+use crate::models::Event;
diff --git a/src/tools/rustfmt/tests/target/configs/group_imports/One.rs b/src/tools/rustfmt/tests/target/configs/group_imports/One.rs
new file mode 100644 (file)
index 0000000..3094c7a
--- /dev/null
@@ -0,0 +1,11 @@
+// rustfmt-group_imports: One
+use super::schema::{Context, Payload};
+use super::update::convert_publish_payload;
+use crate::models::Event;
+use alloc::alloc::Layout;
+use broker::database::PooledConnection;
+use chrono::Utc;
+use core::f32;
+use juniper::{FieldError, FieldResult};
+use std::sync::Arc;
+use uuid::Uuid;
diff --git a/src/tools/rustfmt/tests/target/empty-item-single-line-false.rs b/src/tools/rustfmt/tests/target/empty-item-single-line-false.rs
new file mode 100644 (file)
index 0000000..bf7f70e
--- /dev/null
@@ -0,0 +1,41 @@
+// rustfmt-brace_style: AlwaysNextLine
+// rustfmt-empty_item_single_line: false
+
+fn function()
+{
+}
+
+struct Struct {}
+
+enum Enum {}
+
+trait Trait
+{
+}
+
+impl<T> Trait for T
+{
+}
+
+trait Trait2<T>
+where
+    T: Copy + Display + Write + Read + FromStr,
+{
+}
+
+trait Trait3<T>
+where
+    T: Something
+        + SomethingElse
+        + Sync
+        + Send
+        + Display
+        + Debug
+        + Copy
+        + Hash
+        + Debug
+        + Display
+        + Write
+        + Read,
+{
+}
diff --git a/src/tools/rustfmt/tests/target/issue-5012/trailing_comma_always.rs b/src/tools/rustfmt/tests/target/issue-5012/trailing_comma_always.rs
new file mode 100644 (file)
index 0000000..ff9c40f
--- /dev/null
@@ -0,0 +1,8 @@
+// rustfmt-trailing_comma: Always
+
+pub struct Matrix<T, const R: usize, const C: usize,>
+where
+    [T; R * C]:,
+{
+    contents: [T; R * C],
+}
diff --git a/src/tools/rustfmt/tests/target/issue-5012/trailing_comma_never.rs b/src/tools/rustfmt/tests/target/issue-5012/trailing_comma_never.rs
new file mode 100644 (file)
index 0000000..2fac8ea
--- /dev/null
@@ -0,0 +1,8 @@
+// rustfmt-trailing_comma: Never
+
+pub struct Matrix<T, const R: usize, const C: usize>
+where
+    [T; R * C]:
+{
+    contents: [T; R * C]
+}
diff --git a/src/tools/rustfmt/tests/target/issue-5033/minimum_example.rs b/src/tools/rustfmt/tests/target/issue-5033/minimum_example.rs
new file mode 100644 (file)
index 0000000..0e7df41
--- /dev/null
@@ -0,0 +1,8 @@
+// leading comment
+
+#![rustfmt::skip]
+fn main() {
+    println!("main"); // commented
+}
+
+// post comment
diff --git a/src/tools/rustfmt/tests/target/issue-5033/nested_modules.rs b/src/tools/rustfmt/tests/target/issue-5033/nested_modules.rs
new file mode 100644 (file)
index 0000000..7a11133
--- /dev/null
@@ -0,0 +1,11 @@
+#![rustfmt::skip]
+
+mod a {
+    mod b {
+
+    }
+
+    // trailing comment b
+}
+
+// trailing comment a
diff --git a/src/tools/rustfmt/tests/target/issue_4850.rs b/src/tools/rustfmt/tests/target/issue_4850.rs
new file mode 100644 (file)
index 0000000..7d4da90
--- /dev/null
@@ -0,0 +1,4 @@
+impl ThisIsALongStructNameToPushTheWhereToWrapLolololol where
+    [(); this_is_a_long_const_function_name()]:
+{
+}
index 531ac59868314054c6ef5d36707f7f08f64613b7..4935fac04f1111cec322b7443c9f7b58c2677eef 100644 (file)
@@ -40,3 +40,32 @@ struct D<T>
     where
         T: Copy, {}
 }
+
+fn function() {}
+
+trait Trait {}
+
+impl<T> Trait for T {}
+
+trait Trait2<T>
+where
+    T: Copy + Display + Write + Read + FromStr,
+{
+}
+
+trait Trait3<T>
+where
+    T: Something
+        + SomethingElse
+        + Sync
+        + Send
+        + Display
+        + Debug
+        + Copy
+        + Hash
+        + Debug
+        + Display
+        + Write
+        + Read,
+{
+}
index b5e9ceddbafd166832874a26c34009ae1b363f60..3f59fefd041ebd9b70852d82fda4fb8f49ed68d9 100644 (file)
@@ -18,21 +18,13 @@ pub fn check(path: &Path, bad: &mut bool) {
         &mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
         &mut |entry, contents| {
             let file = entry.path();
-            let filestr = file.to_string_lossy().replace("\\", "/");
             let filename = file.file_name().unwrap();
             if filename != "Cargo.toml" {
                 return;
             }
 
             // Library crates are not yet ready to migrate to 2021.
-            //
-            // The reference and rustc-dev-guide are submodules, so are left at
-            // 2018 for now. They should be removed from this exception list
-            // when bumped.
-            if path.components().any(|c| c.as_os_str() == "library")
-                || filestr.contains("src/doc/reference/style-check/Cargo.toml")
-                || filestr.contains("src/doc/rustc-dev-guide/ci/date-check/Cargo.toml")
-            {
+            if path.components().any(|c| c.as_os_str() == "library") {
                 let has = contents.lines().any(is_edition_2018);
                 if !has {
                     tidy_error!(
index 338dfd11310aaa0e17d14ac63ef5b115dc00ceff..129237775fe3f803c561c47886048987a92a4170 100644 (file)
@@ -97,6 +97,7 @@ pub fn check(
             &src_path.join("test/ui"),
             &src_path.join("test/ui-fulldeps"),
             &src_path.join("test/rustdoc-ui"),
+            &src_path.join("test/rustdoc"),
         ],
         &mut |path| super::filter_dirs(path),
         &mut |entry, contents| {
index 4afa36502aca1c063e2caec6a225df919a7e0c5d..88ede45655c94411b89b3bc110c3879279d00ede 100644 (file)
@@ -7,8 +7,8 @@
 
 const ENTRY_LIMIT: usize = 1000;
 // FIXME: The following limits should be reduced eventually.
-const ROOT_ENTRY_LIMIT: usize = 1331;
-const ISSUES_ENTRY_LIMIT: usize = 2488;
+const ROOT_ENTRY_LIMIT: usize = 1275;
+const ISSUES_ENTRY_LIMIT: usize = 2310;
 
 fn check_entries(path: &Path, bad: &mut bool) {
     let dirs = walkdir::WalkDir::new(&path.join("test/ui"))
index 48c7a00de7830c83e4659f49f35358049949fea1..7a9908fe8c0758fcc3047c04b21aa786741d0468 100644 (file)
@@ -2,6 +2,8 @@
 allow-unauthenticated = [
     "C-*", "A-*", "E-*", "NLL-*", "O-*", "S-*", "T-*", "WG-*", "F-*",
     "D-*",
+    "needs-fcp",
+    "relnotes",
     "requires-nightly",
     "regression-*",
     "perf-*",