]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #91209 - camelid:snapshot, r=jyn514
authorMatthias Krüger <matthias.krueger@famsik.de>
Sat, 4 Dec 2021 01:26:22 +0000 (02:26 +0100)
committerGitHub <noreply@github.com>
Sat, 4 Dec 2021 01:26:22 +0000 (02:26 +0100)
Implement `@snapshot` check for htmldocck

This form of check allows performing snapshot tests (à la `src/test/ui`)
on rustdoc HTML output, making it easier to create and update tests.

See [this Zulip thread][1] for more information about the motivation for
this change.

[1]: https://zulip-archive.rust-lang.org/stream/266220-rustdoc/topic/HTML.20snapshot.20tests.html#262651142

r? `@GuillaumeGomez`

733 files changed:
Cargo.lock
RELEASES.md
compiler/rustc_ast/src/ast.rs
compiler/rustc_ast/src/ast_like.rs
compiler/rustc_ast/src/mut_visit.rs
compiler/rustc_ast/src/visit.rs
compiler/rustc_ast_lowering/src/expr.rs
compiler/rustc_ast_lowering/src/item.rs
compiler/rustc_ast_lowering/src/lib.rs
compiler/rustc_ast_lowering/src/path.rs
compiler/rustc_ast_passes/src/ast_validation.rs
compiler/rustc_ast_passes/src/lib.rs
compiler/rustc_ast_pretty/src/pprust/mod.rs
compiler/rustc_attr/src/builtin.rs
compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
compiler/rustc_borrowck/src/diagnostics/mod.rs
compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
compiler/rustc_borrowck/src/diagnostics/region_name.rs
compiler/rustc_borrowck/src/lib.rs
compiler/rustc_borrowck/src/renumber.rs
compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
compiler/rustc_borrowck/src/type_check/free_region_relations.rs
compiler/rustc_builtin_macros/src/cfg_eval.rs
compiler/rustc_builtin_macros/src/format.rs
compiler/rustc_builtin_macros/src/test_harness.rs
compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs
compiler/rustc_codegen_gcc/src/abi.rs
compiler/rustc_codegen_llvm/src/abi.rs
compiler/rustc_codegen_llvm/src/back/write.rs
compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
compiler/rustc_codegen_llvm/src/llvm/ffi.rs
compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs
compiler/rustc_codegen_ssa/src/traits/abi.rs
compiler/rustc_const_eval/src/interpret/intrinsics.rs
compiler/rustc_const_eval/src/interpret/operator.rs
compiler/rustc_const_eval/src/interpret/step.rs
compiler/rustc_const_eval/src/transform/check_consts/check.rs
compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
compiler/rustc_const_eval/src/transform/mod.rs
compiler/rustc_const_eval/src/transform/promote_consts.rs
compiler/rustc_const_eval/src/transform/validate.rs
compiler/rustc_data_structures/src/functor.rs
compiler/rustc_error_codes/src/error_codes/E0038.md
compiler/rustc_errors/src/emitter.rs
compiler/rustc_errors/src/lib.rs
compiler/rustc_expand/src/base.rs
compiler/rustc_expand/src/expand.rs
compiler/rustc_expand/src/lib.rs
compiler/rustc_expand/src/mbe/macro_parser.rs
compiler/rustc_expand/src/parse/tests.rs
compiler/rustc_expand/src/placeholders.rs
compiler/rustc_hir/src/hir.rs
compiler/rustc_hir/src/intravisit.rs
compiler/rustc_hir/src/lang_items.rs
compiler/rustc_infer/src/infer/opaque_types.rs
compiler/rustc_infer/src/infer/resolve.rs
compiler/rustc_infer/src/traits/structural_impls.rs
compiler/rustc_interface/src/passes.rs
compiler/rustc_interface/src/tests.rs
compiler/rustc_lexer/Cargo.toml
compiler/rustc_lexer/src/cursor.rs
compiler/rustc_lexer/src/lib.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
compiler/rustc_lint/src/lib.rs
compiler/rustc_lint/src/non_fmt_panic.rs
compiler/rustc_lint/src/noop_method_call.rs
compiler/rustc_lint/src/types.rs
compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
compiler/rustc_macros/src/type_foldable.rs
compiler/rustc_metadata/src/creader.rs
compiler/rustc_metadata/src/locator.rs
compiler/rustc_metadata/src/rmeta/encoder.rs
compiler/rustc_middle/src/hir/map/mod.rs
compiler/rustc_middle/src/lib.rs
compiler/rustc_middle/src/macros.rs
compiler/rustc_middle/src/middle/region.rs
compiler/rustc_middle/src/mir/coverage.rs
compiler/rustc_middle/src/mir/interpret/error.rs
compiler/rustc_middle/src/mir/mod.rs
compiler/rustc_middle/src/mir/type_foldable.rs
compiler/rustc_middle/src/mir/visit.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/traits/mod.rs
compiler/rustc_middle/src/traits/util.rs [new file with mode: 0644]
compiler/rustc_middle/src/ty/adt.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/error.rs
compiler/rustc_middle/src/ty/fold.rs
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
compiler/rustc_middle/src/ty/print/pretty.rs
compiler/rustc_middle/src/ty/structural_impls.rs
compiler/rustc_middle/src/ty/sty.rs
compiler/rustc_middle/src/ty/subst.rs
compiler/rustc_middle/src/ty/util.rs
compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
compiler/rustc_mir_transform/src/dest_prop.rs
compiler/rustc_mir_transform/src/lib.rs
compiler/rustc_mir_transform/src/remove_false_edges.rs [new file with mode: 0644]
compiler/rustc_mir_transform/src/remove_uninit_drops.rs [new file with mode: 0644]
compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
compiler/rustc_mir_transform/src/reveal_all.rs
compiler/rustc_mir_transform/src/simplify_branches.rs
compiler/rustc_parse/src/lexer/mod.rs
compiler/rustc_parse/src/lexer/unicode_chars.rs
compiler/rustc_parse/src/lib.rs
compiler/rustc_parse/src/parser/diagnostics.rs
compiler/rustc_parse/src/parser/expr.rs
compiler/rustc_parse/src/parser/generics.rs
compiler/rustc_parse/src/parser/item.rs
compiler/rustc_parse/src/parser/pat.rs
compiler/rustc_parse/src/parser/path.rs
compiler/rustc_parse/src/parser/ty.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/lib_features.rs
compiler/rustc_passes/src/reachable.rs
compiler/rustc_passes/src/region.rs
compiler/rustc_passes/src/stability.rs
compiler/rustc_privacy/src/lib.rs
compiler/rustc_resolve/src/build_reduced_graph.rs
compiler/rustc_resolve/src/def_collector.rs
compiler/rustc_resolve/src/diagnostics.rs
compiler/rustc_resolve/src/late.rs
compiler/rustc_resolve/src/late/diagnostics.rs
compiler/rustc_resolve/src/late/lifetimes.rs
compiler/rustc_resolve/src/lib.rs
compiler/rustc_session/src/config.rs
compiler/rustc_session/src/options.rs
compiler/rustc_session/src/parse.rs
compiler/rustc_session/src/session.rs
compiler/rustc_span/src/hygiene.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_target/src/abi/call/mips64.rs
compiler/rustc_target/src/abi/call/mod.rs
compiler/rustc_target/src/abi/call/sparc64.rs
compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
compiler/rustc_target/src/spec/apple_base.rs
compiler/rustc_target/src/spec/i686_apple_darwin.rs
compiler/rustc_target/src/spec/x86_64_apple_darwin.rs
compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
compiler/rustc_trait_selection/src/traits/query/normalize.rs
compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
compiler/rustc_trait_selection/src/traits/select/mod.rs
compiler/rustc_traits/src/normalize_erasing_regions.rs
compiler/rustc_ty_utils/src/needs_drop.rs
compiler/rustc_ty_utils/src/ty.rs
compiler/rustc_typeck/src/check/check.rs
compiler/rustc_typeck/src/check/coercion.rs
compiler/rustc_typeck/src/check/compare_method.rs
compiler/rustc_typeck/src/check/demand.rs
compiler/rustc_typeck/src/check/expr.rs
compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
compiler/rustc_typeck/src/check/method/prelude2021.rs
compiler/rustc_typeck/src/check/mod.rs
compiler/rustc_typeck/src/check/op.rs
compiler/rustc_typeck/src/check/place_op.rs
compiler/rustc_typeck/src/check/upvar.rs
compiler/rustc_typeck/src/check/wfcheck.rs
compiler/rustc_typeck/src/check_unused.rs
compiler/rustc_typeck/src/coherence/builtin.rs
compiler/rustc_typeck/src/collect.rs
compiler/rustc_typeck/src/lib.rs
library/alloc/src/boxed.rs
library/alloc/src/collections/vec_deque/mod.rs
library/alloc/src/lib.rs
library/alloc/src/raw_vec.rs
library/alloc/src/raw_vec/tests.rs
library/alloc/src/string.rs
library/alloc/src/vec/mod.rs
library/alloc/tests/vec.rs
library/core/src/alloc/layout.rs
library/core/src/any.rs
library/core/src/array/mod.rs
library/core/src/fmt/mod.rs
library/core/src/future/future.rs
library/core/src/future/into_future.rs
library/core/src/hash/mod.rs
library/core/src/intrinsics.rs
library/core/src/iter/adapters/skip.rs
library/core/src/iter/adapters/take.rs
library/core/src/iter/traits/double_ended.rs
library/core/src/iter/traits/iterator.rs
library/core/src/lib.rs
library/core/src/mem/maybe_uninit.rs
library/core/src/num/nonzero.rs
library/core/src/ops/control_flow.rs
library/core/src/ops/generator.rs
library/core/src/ops/mod.rs
library/core/src/ops/range.rs
library/core/src/ops/try_trait.rs
library/core/src/option.rs
library/core/src/result.rs
library/core/src/slice/mod.rs
library/core/src/slice/raw.rs
library/core/src/str/lossy.rs
library/core/src/str/validations.rs
library/core/src/time.rs
library/core/tests/array.rs
library/core/tests/iter/adapters/chain.rs
library/core/tests/iter/adapters/flatten.rs
library/core/tests/iter/adapters/skip.rs
library/core/tests/iter/adapters/take.rs
library/core/tests/iter/range.rs
library/core/tests/lib.rs
library/core/tests/mem.rs
library/core/tests/slice.rs
library/std/Cargo.toml
library/std/src/io/error.rs
library/std/src/lib.rs
library/std/src/os/windows/fs.rs
library/std/src/path.rs
library/std/src/sys/hermit/mutex.rs
library/std/src/sys/unix/android.rs
library/std/src/sys/unix/fd.rs
library/std/src/sys/unix/fs.rs
library/std/src/sys/unix/kernel_copy.rs
library/std/src/sys/unix/net.rs
library/std/src/sys/unix/os.rs
library/std/src/sys/unix/os/tests.rs
library/std/src/sys/unix/process/process_unix.rs
library/std/src/sys/unix/thread.rs
library/std/src/sys/unix/weak.rs
library/std/src/thread/local.rs
library/std/src/thread/mod.rs
library/unwind/build.rs
src/bootstrap/lib.rs
src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
src/doc/rustdoc/src/documentation-tests.md
src/doc/rustdoc/src/unstable-features.md
src/doc/unstable-book/src/compiler-flags/instrument-coverage.md
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/doctest.rs
src/librustdoc/doctest/tests.rs
src/librustdoc/error.rs
src/librustdoc/formats/cache.rs
src/librustdoc/html/format.rs
src/librustdoc/html/highlight.rs
src/librustdoc/html/layout.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/write_shared.rs
src/librustdoc/html/static/css/rustdoc.css
src/librustdoc/html/static/js/main.js
src/librustdoc/html/static/js/storage.js
src/librustdoc/html/templates/page.html
src/librustdoc/json/conversions.rs
src/librustdoc/markdown.rs
src/librustdoc/scrape_examples.rs
src/librustdoc/visit_ast.rs
src/llvm-project
src/stage0.json
src/test/assembly/sparc-struct-abi.rs [new file with mode: 0644]
src/test/codegen/sparc-struct-abi.rs
src/test/debuginfo/rc_arc.rs
src/test/mir-opt/const_prop/switch_int.main.SimplifyBranches-after-const-prop.diff [deleted file]
src/test/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff [new file with mode: 0644]
src/test/mir-opt/const_prop/switch_int.rs
src/test/mir-opt/early_otherwise_branch_68867.rs
src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyBranches-final.after.diff [deleted file]
src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff [new file with mode: 0644]
src/test/mir-opt/inline/issue_78442.bar.Inline.diff
src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff
src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff [deleted file]
src/test/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff [new file with mode: 0644]
src/test/mir-opt/simplify_if.rs
src/test/run-make-fulldeps/coverage-llvmir/Makefile
src/test/run-make-fulldeps/coverage-reports/Makefile
src/test/rustdoc-gui/anchors.goml
src/test/rustdoc-gui/search-filter.goml
src/test/rustdoc-gui/src/test_docs/lib.rs
src/test/rustdoc-js/summaries.rs
src/test/rustdoc-ui/auxiliary/overflow.rs [new file with mode: 0644]
src/test/rustdoc-ui/display-output.rs
src/test/rustdoc-ui/display-output.stdout
src/test/rustdoc-ui/intra-doc/auxiliary/through-proc-macro-aux.rs [new file with mode: 0644]
src/test/rustdoc-ui/intra-doc/through-proc-macro.rs [new file with mode: 0644]
src/test/rustdoc-ui/intra-doc/through-proc-macro.stderr [new file with mode: 0644]
src/test/rustdoc-ui/normalize-cycle.rs [new file with mode: 0644]
src/test/rustdoc-ui/normalize-overflow.rs [new file with mode: 0644]
src/test/rustdoc-ui/scrape-examples-ice.rs [new file with mode: 0644]
src/test/rustdoc/auto-impl-primitive.rs
src/test/rustdoc/bad-codeblock-syntax.rs
src/test/rustdoc/check-source-code-urls-to-def.rs
src/test/rustdoc/const-generics/const-impl.rs
src/test/rustdoc/default-trait-method.rs
src/test/rustdoc/deref-const-fn.rs [new file with mode: 0644]
src/test/rustdoc/doc-cfg.rs
src/test/rustdoc/doc-notable_trait-slice.rs [new file with mode: 0644]
src/test/rustdoc/intra-doc/associated-defaults.rs
src/test/rustdoc/intra-doc/associated-items.rs
src/test/rustdoc/intra-doc/auxiliary/my-core.rs
src/test/rustdoc/intra-doc/auxiliary/through-proc-macro-aux.rs [deleted file]
src/test/rustdoc/intra-doc/cross-crate/additional_doc.rs
src/test/rustdoc/intra-doc/cross-crate/auxiliary/additional_doc.rs
src/test/rustdoc/intra-doc/cross-crate/auxiliary/hidden.rs
src/test/rustdoc/intra-doc/cross-crate/auxiliary/intra-doc-basic.rs
src/test/rustdoc/intra-doc/cross-crate/auxiliary/macro_inner.rs
src/test/rustdoc/intra-doc/cross-crate/auxiliary/module.rs
src/test/rustdoc/intra-doc/cross-crate/auxiliary/submodule-inner.rs
src/test/rustdoc/intra-doc/cross-crate/auxiliary/submodule-outer.rs
src/test/rustdoc/intra-doc/cross-crate/basic.rs
src/test/rustdoc/intra-doc/cross-crate/hidden.rs
src/test/rustdoc/intra-doc/cross-crate/macro.rs
src/test/rustdoc/intra-doc/cross-crate/module.rs
src/test/rustdoc/intra-doc/cross-crate/submodule-inner.rs
src/test/rustdoc/intra-doc/cross-crate/submodule-outer.rs
src/test/rustdoc/intra-doc/cross-crate/traits.rs
src/test/rustdoc/intra-doc/disambiguators-removed.rs
src/test/rustdoc/intra-doc/email-address.rs
src/test/rustdoc/intra-doc/extern-crate.rs
src/test/rustdoc/intra-doc/external-traits.rs
src/test/rustdoc/intra-doc/in-bodies.rs
src/test/rustdoc/intra-doc/issue-82209.rs
src/test/rustdoc/intra-doc/libstd-re-export.rs
src/test/rustdoc/intra-doc/mod-ambiguity.rs
src/test/rustdoc/intra-doc/prim-assoc.rs
src/test/rustdoc/intra-doc/prim-methods-external-core.rs
src/test/rustdoc/intra-doc/prim-methods-local.rs
src/test/rustdoc/intra-doc/prim-methods.rs
src/test/rustdoc/intra-doc/prim-precedence.rs
src/test/rustdoc/intra-doc/primitive-disambiguators.rs
src/test/rustdoc/intra-doc/primitive-non-default-impl.rs
src/test/rustdoc/intra-doc/private-failures-ignored.rs
src/test/rustdoc/intra-doc/private.rs
src/test/rustdoc/intra-doc/proc-macro.rs
src/test/rustdoc/intra-doc/pub-use.rs
src/test/rustdoc/intra-doc/raw-ident-self.rs
src/test/rustdoc/intra-doc/through-proc-macro.rs [deleted file]
src/test/rustdoc/intra-doc/trait-item.rs
src/test/rustdoc/intra-doc/true-false.rs
src/test/rustdoc/intra-doc/type-alias.rs
src/test/rustdoc/intra-link-prim-self.rs
src/test/rustdoc/issue-12834.rs
src/test/rustdoc/issue-15318-3.rs
src/test/rustdoc/issue-23511.rs
src/test/rustdoc/issue-42760.rs
src/test/rustdoc/issue-43869.rs
src/test/rustdoc/legacy-const-generic.rs [new file with mode: 0644]
src/test/rustdoc/link-title-escape.rs
src/test/rustdoc/primitive-generic-impl.rs [deleted file]
src/test/rustdoc/primitive/primitive-generic-impl.rs
src/test/rustdoc/proc-macro.rs
src/test/rustdoc/range-arg-pattern.rs
src/test/rustdoc/raw-ident-eliminate-r-hashtag.rs
src/test/rustdoc/sidebar-items.rs
src/test/rustdoc/static-root-path.rs
src/test/rustdoc/titles.rs
src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
src/test/ui/associated-types/issue-59324.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-59324.stderr [new file with mode: 0644]
src/test/ui/associated-types/issue-67684.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-69398.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-71113.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-82079.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-85103.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-85103.stderr [new file with mode: 0644]
src/test/ui/associated-types/issue-87261.rs
src/test/ui/associated-types/issue-87261.stderr
src/test/ui/associated-types/issue-88856.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-91231.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-91234.rs [new file with mode: 0644]
src/test/ui/ast-json/ast-json-noexpand-output.stdout
src/test/ui/ast-json/ast-json-output.stdout
src/test/ui/async-await/async-block-control-flow-static-semantics.rs
src/test/ui/async-await/async-block-control-flow-static-semantics.stderr
src/test/ui/async-await/async-error-span.stderr
src/test/ui/async-await/async-fn-size-moved-locals.rs
src/test/ui/async-await/await-into-future.rs [new file with mode: 0644]
src/test/ui/async-await/generator-desc.stderr
src/test/ui/async-await/issue-67252-unnamed-future.stderr
src/test/ui/async-await/issue-68112.stderr
src/test/ui/async-await/issue-70594.stderr
src/test/ui/async-await/issues/issue-62009-1.stderr
src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr
src/test/ui/async-await/unresolved_type_param.rs
src/test/ui/async-await/unresolved_type_param.stderr
src/test/ui/attributes/issue-90873.rs [new file with mode: 0644]
src/test/ui/attributes/issue-90873.stderr [new file with mode: 0644]
src/test/ui/borrowck/borrowck-and-init.stderr
src/test/ui/borrowck/borrowck-break-uninit-2.stderr
src/test/ui/borrowck/borrowck-break-uninit.stderr
src/test/ui/borrowck/borrowck-or-init.stderr
src/test/ui/borrowck/borrowck-while-break.stderr
src/test/ui/borrowck/issue-24267-flow-exit.stderr
src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.migrate.stderr
src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.nll.stderr
src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs
src/test/ui/borrowck/issue-58776-borrowck-scans-children.migrate.stderr [deleted file]
src/test/ui/borrowck/issue-91206.rs [new file with mode: 0644]
src/test/ui/borrowck/issue-91206.stderr [new file with mode: 0644]
src/test/ui/cast/issue-88621.rs [new file with mode: 0644]
src/test/ui/cast/issue-88621.stderr [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/box.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr
src/test/ui/codemap_tests/tab_3.stderr
src/test/ui/consts/assert-type-intrinsics.rs [new file with mode: 0644]
src/test/ui/consts/assert-type-intrinsics.stderr [new file with mode: 0644]
src/test/ui/consts/assume-type-intrinsics.rs [deleted file]
src/test/ui/consts/assume-type-intrinsics.stderr [deleted file]
src/test/ui/consts/const-cast-different-types.rs
src/test/ui/consts/const-cast-different-types.stderr
src/test/ui/consts/const-cast-wrong-type.rs
src/test/ui/consts/const-cast-wrong-type.stderr
src/test/ui/consts/const-err.rs
src/test/ui/consts/const-eval/conditional_array_execution.stderr
src/test/ui/consts/const-eval/issue-43197.stderr
src/test/ui/consts/drop_zst.rs [new file with mode: 0644]
src/test/ui/consts/drop_zst.stderr [new file with mode: 0644]
src/test/ui/consts/issue-90878-2.rs
src/test/ui/consts/issue-90878-2.stderr
src/test/ui/crate-loading/invalid-rlib.rs
src/test/ui/crate-loading/invalid-rlib.stderr
src/test/ui/crate-loading/missing-std.rs
src/test/ui/crate-loading/missing-std.stderr
src/test/ui/dst/dst-bad-assign-3.stderr
src/test/ui/dst/dst-bad-assign.stderr
src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr
src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs
src/test/ui/error-codes/E0070.rs
src/test/ui/error-codes/E0070.stderr
src/test/ui/error-codes/E0161.edition.stderr
src/test/ui/error-codes/E0161.migrate.stderr
src/test/ui/error-codes/E0161.nll.stderr
src/test/ui/error-codes/E0161.rs
src/test/ui/error-codes/E0161.zflags.stderr
src/test/ui/expr/if/if-without-block.stderr
src/test/ui/extern-flag/empty-extern-arg.rs
src/test/ui/extern-flag/empty-extern-arg.stderr
src/test/ui/extern/extern-crate-multiple-missing.rs [new file with mode: 0644]
src/test/ui/extern/extern-crate-multiple-missing.stderr [new file with mode: 0644]
src/test/ui/fn/implied-bounds-unnorm-associated-type-2.rs [new file with mode: 0644]
src/test/ui/fn/implied-bounds-unnorm-associated-type.nll.stderr [new file with mode: 0644]
src/test/ui/fn/implied-bounds-unnorm-associated-type.rs [new file with mode: 0644]
src/test/ui/fn/implied-bounds-unnorm-associated-type.stderr [new file with mode: 0644]
src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs
src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr
src/test/ui/generator/issue-68112.stderr
src/test/ui/generator/yield-while-ref-reborrowed.stderr
src/test/ui/generic-associated-types/equality-bound.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/equality-bound.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-87748.rs [deleted file]
src/test/ui/generic-associated-types/missing-bounds.fixed
src/test/ui/generic-associated-types/missing-bounds.rs
src/test/ui/generic-associated-types/missing-bounds.stderr
src/test/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.stderr [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.nll.stderr
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs
src/test/ui/hrtb/issue-30786.migrate.stderr
src/test/ui/hrtb/issue-30786.nll.stderr
src/test/ui/hrtb/issue-30786.rs
src/test/ui/impl-trait/auto-trait-leak2.stderr
src/test/ui/impl-trait/impl-trait-in-macro.stderr
src/test/ui/impl-trait/issue-55872-2.rs
src/test/ui/impl-trait/issue-55872-2.stderr
src/test/ui/impl-trait/issue-72911.stderr
src/test/ui/impl-trait/issue-87450.stderr
src/test/ui/impl-trait/issues/issue-78722.stderr
src/test/ui/impl-trait/issues/issue-86201.rs
src/test/ui/impl-trait/universal-two-impl-traits.stderr
src/test/ui/imports/extern-crate-self/extern-crate-self-fail.stderr
src/test/ui/in-band-lifetimes/elided-lifetimes.fixed
src/test/ui/in-band-lifetimes/elided-lifetimes.rs
src/test/ui/in-band-lifetimes/elided-lifetimes.stderr
src/test/ui/integral-variable-unification-error.rs
src/test/ui/integral-variable-unification-error.stderr
src/test/ui/issues-71798.stderr
src/test/ui/issues/issue-13407.rs
src/test/ui/issues/issue-13407.stderr
src/test/ui/issues/issue-16538.mir.stderr
src/test/ui/issues/issue-16538.rs
src/test/ui/issues/issue-16538.thir.stderr
src/test/ui/issues/issue-17718-static-sync.stderr
src/test/ui/issues/issue-24446.rs
src/test/ui/issues/issue-24446.stderr
src/test/ui/issues/issue-2951.stderr
src/test/ui/issues/issue-37131.stderr
src/test/ui/issues/issue-42796.stderr
src/test/ui/issues/issue-47646.stderr
src/test/ui/issues/issue-49851/compiler-builtins-error.rs
src/test/ui/issues/issue-49851/compiler-builtins-error.stderr
src/test/ui/issues/issue-5216.rs
src/test/ui/issues/issue-5216.stderr
src/test/ui/issues/issue-53348.rs
src/test/ui/issues/issue-53348.stderr
src/test/ui/issues/issue-59494.rs
src/test/ui/issues/issue-59494.stderr
src/test/ui/issues/issue-7364.rs
src/test/ui/issues/issue-7364.stderr
src/test/ui/issues/issue-77218.rs [deleted file]
src/test/ui/issues/issue-77218.stderr [deleted file]
src/test/ui/issues/issue-77218/issue-77218-2.fixed [new file with mode: 0644]
src/test/ui/issues/issue-77218/issue-77218-2.rs [new file with mode: 0644]
src/test/ui/issues/issue-77218/issue-77218-2.stderr [new file with mode: 0644]
src/test/ui/issues/issue-77218/issue-77218.fixed [new file with mode: 0644]
src/test/ui/issues/issue-77218/issue-77218.rs [new file with mode: 0644]
src/test/ui/issues/issue-77218/issue-77218.stderr [new file with mode: 0644]
src/test/ui/issues/issue-88150.rs [new file with mode: 0644]
src/test/ui/lexer/lex-bad-binary-literal.rs [new file with mode: 0644]
src/test/ui/lexer/lex-bad-binary-literal.stderr [new file with mode: 0644]
src/test/ui/lexer/lex-bad-char-literals-1.rs [new file with mode: 0644]
src/test/ui/lexer/lex-bad-char-literals-1.stderr [new file with mode: 0644]
src/test/ui/lexer/lex-bad-char-literals-2.rs [new file with mode: 0644]
src/test/ui/lexer/lex-bad-char-literals-2.stderr [new file with mode: 0644]
src/test/ui/lexer/lex-bad-char-literals-3.rs [new file with mode: 0644]
src/test/ui/lexer/lex-bad-char-literals-3.stderr [new file with mode: 0644]
src/test/ui/lexer/lex-bad-char-literals-4.rs [new file with mode: 0644]
src/test/ui/lexer/lex-bad-char-literals-4.stderr [new file with mode: 0644]
src/test/ui/lexer/lex-bad-char-literals-5.rs [new file with mode: 0644]
src/test/ui/lexer/lex-bad-char-literals-5.stderr [new file with mode: 0644]
src/test/ui/lexer/lex-bad-char-literals-6.rs [new file with mode: 0644]
src/test/ui/lexer/lex-bad-char-literals-6.stderr [new file with mode: 0644]
src/test/ui/lexer/lex-bad-char-literals-7.rs [new file with mode: 0644]
src/test/ui/lexer/lex-bad-char-literals-7.stderr [new file with mode: 0644]
src/test/ui/lexer/lex-bad-numeric-literals.rs [new file with mode: 0644]
src/test/ui/lexer/lex-bad-numeric-literals.stderr [new file with mode: 0644]
src/test/ui/lexer/lex-bad-octal-literal.rs [new file with mode: 0644]
src/test/ui/lexer/lex-bad-octal-literal.stderr [new file with mode: 0644]
src/test/ui/lexer/lex-bad-token.rs [new file with mode: 0644]
src/test/ui/lexer/lex-bad-token.stderr [new file with mode: 0644]
src/test/ui/lexer/lex-bare-cr-nondoc-comment.rs [new file with mode: 0644]
src/test/ui/lexer/lex-bare-cr-string-literal-doc-comment.rs [new file with mode: 0644]
src/test/ui/lexer/lex-bare-cr-string-literal-doc-comment.stderr [new file with mode: 0644]
src/test/ui/lexer/lex-stray-backslash.rs [new file with mode: 0644]
src/test/ui/lexer/lex-stray-backslash.stderr [new file with mode: 0644]
src/test/ui/lexer/lexer-crlf-line-endings-string-literal-doc-comment.rs [new file with mode: 0644]
src/test/ui/lifetimes/issue-76168-hr-outlives.rs [new file with mode: 0644]
src/test/ui/limits/issue-55878.stderr
src/test/ui/lint/force-warn/allowed-by-default-lint.stderr
src/test/ui/lint/lint-ctypes-73251-2.rs
src/test/ui/lint/lint-ctypes-73251-2.stderr
src/test/ui/lint/opaque-ty-ffi-unsafe.rs
src/test/ui/lint/opaque-ty-ffi-unsafe.stderr
src/test/ui/lint/reasons.rs
src/test/ui/lint/reasons.stderr
src/test/ui/lint/unused/unused-doc-comments-edge-cases.rs
src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr
src/test/ui/liveness/liveness-move-in-while.stderr
src/test/ui/liveness/liveness-use-after-move.stderr
src/test/ui/liveness/liveness-use-after-send.stderr
src/test/ui/loops/loop-proper-liveness.stderr
src/test/ui/mir/mir_overflow_off.rs
src/test/ui/mismatched_types/issue-84976.stderr
src/test/ui/moves/moves-based-on-type-capture-clause-bad.stderr
src/test/ui/numbers-arithmetic/int-abs-overflow.rs
src/test/ui/optimization-remark.rs [new file with mode: 0644]
src/test/ui/output-type-mismatch.stderr
src/test/ui/parser/const-param-decl-on-type-instead-of-impl.rs [new file with mode: 0644]
src/test/ui/parser/const-param-decl-on-type-instead-of-impl.stderr [new file with mode: 0644]
src/test/ui/parser/emoji-identifiers.rs [new file with mode: 0644]
src/test/ui/parser/emoji-identifiers.stderr [new file with mode: 0644]
src/test/ui/parser/issue-91421.rs [new file with mode: 0644]
src/test/ui/parser/issue-91421.stderr [new file with mode: 0644]
src/test/ui/parser/issues/issue-87086-colon-path-sep.rs
src/test/ui/parser/issues/issue-87086-colon-path-sep.stderr
src/test/ui/parser/lex-bad-binary-literal.rs [deleted file]
src/test/ui/parser/lex-bad-binary-literal.stderr [deleted file]
src/test/ui/parser/lex-bad-char-literals-1.rs [deleted file]
src/test/ui/parser/lex-bad-char-literals-1.stderr [deleted file]
src/test/ui/parser/lex-bad-char-literals-2.rs [deleted file]
src/test/ui/parser/lex-bad-char-literals-2.stderr [deleted file]
src/test/ui/parser/lex-bad-char-literals-3.rs [deleted file]
src/test/ui/parser/lex-bad-char-literals-3.stderr [deleted file]
src/test/ui/parser/lex-bad-char-literals-4.rs [deleted file]
src/test/ui/parser/lex-bad-char-literals-4.stderr [deleted file]
src/test/ui/parser/lex-bad-char-literals-5.rs [deleted file]
src/test/ui/parser/lex-bad-char-literals-5.stderr [deleted file]
src/test/ui/parser/lex-bad-char-literals-6.rs [deleted file]
src/test/ui/parser/lex-bad-char-literals-6.stderr [deleted file]
src/test/ui/parser/lex-bad-char-literals-7.rs [deleted file]
src/test/ui/parser/lex-bad-char-literals-7.stderr [deleted file]
src/test/ui/parser/lex-bad-numeric-literals.rs [deleted file]
src/test/ui/parser/lex-bad-numeric-literals.stderr [deleted file]
src/test/ui/parser/lex-bad-octal-literal.rs [deleted file]
src/test/ui/parser/lex-bad-octal-literal.stderr [deleted file]
src/test/ui/parser/lex-bad-token.rs [deleted file]
src/test/ui/parser/lex-bad-token.stderr [deleted file]
src/test/ui/parser/lex-bare-cr-nondoc-comment.rs [deleted file]
src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.rs [deleted file]
src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr [deleted file]
src/test/ui/parser/lex-stray-backslash.rs [deleted file]
src/test/ui/parser/lex-stray-backslash.stderr [deleted file]
src/test/ui/parser/lexer-crlf-line-endings-string-literal-doc-comment.rs [deleted file]
src/test/ui/pattern/non-structural-match-types.stderr
src/test/ui/pattern/usefulness/issue-88747.rs [new file with mode: 0644]
src/test/ui/proc-macro/crate-attrs-multiple.rs [new file with mode: 0644]
src/test/ui/proc-macro/issue-59191-replace-root-with-fn.rs
src/test/ui/proc-macro/issue-59191-replace-root-with-fn.stderr
src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.nll.stderr [deleted file]
src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.stderr
src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.nll.stderr
src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs
src/test/ui/regions/regions-free-region-ordering-caller.migrate.nll.stderr [deleted file]
src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr
src/test/ui/regions/regions-free-region-ordering-caller.nll.stderr
src/test/ui/regions/regions-free-region-ordering-caller.rs
src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr [deleted file]
src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr
src/test/ui/regions/regions-outlives-projection-container-hrtb.nll.stderr
src/test/ui/regions/regions-outlives-projection-container-hrtb.rs
src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr [deleted file]
src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr
src/test/ui/regions/regions-outlives-projection-container-wc.nll.stderr
src/test/ui/regions/regions-outlives-projection-container-wc.rs
src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs
src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs [new file with mode: 0644]
src/test/ui/rfc1623.nll.stderr
src/test/ui/rfc1623.rs
src/test/ui/rfc1623.stderr
src/test/ui/rust-2018/uniform-paths/deadlock.rs
src/test/ui/rust-2018/uniform-paths/deadlock.stderr
src/test/ui/static/static-mut-bad-types.stderr
src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
src/test/ui/suggestions/if-let-typo.stderr
src/test/ui/suggestions/mut-ref-reassignment.stderr
src/test/ui/svh/changing-crates.rs
src/test/ui/svh/changing-crates.stderr
src/test/ui/svh/svh-change-lit.rs
src/test/ui/svh/svh-change-lit.stderr
src/test/ui/svh/svh-change-significant-cfg.rs
src/test/ui/svh/svh-change-significant-cfg.stderr
src/test/ui/svh/svh-change-trait-bound.rs
src/test/ui/svh/svh-change-trait-bound.stderr
src/test/ui/svh/svh-change-type-arg.rs
src/test/ui/svh/svh-change-type-arg.stderr
src/test/ui/svh/svh-change-type-ret.rs
src/test/ui/svh/svh-change-type-ret.stderr
src/test/ui/svh/svh-change-type-static.rs
src/test/ui/svh/svh-change-type-static.stderr
src/test/ui/svh/svh-use-trait.rs
src/test/ui/svh/svh-use-trait.stderr
src/test/ui/traits/project-modulo-regions.rs [new file with mode: 0644]
src/test/ui/traits/project-modulo-regions.with_clause.stderr [new file with mode: 0644]
src/test/ui/traits/project-modulo-regions.without_clause.stderr [new file with mode: 0644]
src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr
src/test/ui/type-alias-impl-trait/argument-types.stderr
src/test/ui/type-alias-impl-trait/issue-89686.rs
src/test/ui/type-alias-impl-trait/issue-89686.stderr
src/test/ui/type-alias-impl-trait/static-const-types.rs
src/test/ui/type-alias-impl-trait/static-const-types.stderr
src/test/ui/type/issue-91268.rs [new file with mode: 0644]
src/test/ui/type/issue-91268.stderr [new file with mode: 0644]
src/test/ui/type/type-check/assignment-expected-bool.stderr
src/test/ui/type/type-check/assignment-in-if.stderr
src/test/ui/typeck/issue-81293.stderr
src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr
src/test/ui/typeck/issue-91210-ptr-method.fixed [new file with mode: 0644]
src/test/ui/typeck/issue-91210-ptr-method.rs [new file with mode: 0644]
src/test/ui/typeck/issue-91210-ptr-method.stderr [new file with mode: 0644]
src/test/ui/union/issue-81199.rs [new file with mode: 0644]
src/test/ui/union/issue-81199.stderr [new file with mode: 0644]
src/test/ui/use/use-after-move-based-on-type.stderr
src/test/ui/walk-struct-literal-with.stderr
src/tools/cargo
src/tools/clippy/clippy_lints/src/derive.rs
src/tools/clippy/clippy_lints/src/methods/mod.rs
src/tools/clippy/clippy_lints/src/non_copy_const.rs
src/tools/clippy/clippy_lints/src/self_named_constructors.rs
src/tools/clippy/clippy_lints/src/unused_self.rs
src/tools/clippy/tests/ui/crashes/ice-6250.stderr
src/tools/compiletest/src/runtest.rs
src/tools/miri
src/tools/rust-analyzer
src/tools/rustfmt/.github/workflows/linux.yml
src/tools/rustfmt/.github/workflows/mac.yml
src/tools/rustfmt/.github/workflows/windows.yml
src/tools/rustfmt/Configurations.md
src/tools/rustfmt/README.md
src/tools/rustfmt/config_proc_macro/src/lib.rs
src/tools/rustfmt/src/comment.rs
src/tools/rustfmt/src/config/mod.rs
src/tools/rustfmt/src/expr.rs
src/tools/rustfmt/src/ignore_path.rs
src/tools/rustfmt/src/items.rs
src/tools/rustfmt/src/lists.rs
src/tools/rustfmt/src/macros.rs
src/tools/rustfmt/src/syntux/session.rs
src/tools/rustfmt/src/test/mod.rs
src/tools/rustfmt/src/types.rs
src/tools/rustfmt/src/visitor.rs
src/tools/rustfmt/tests/source/comments-in-lists/wrap-comments-not-normalized.rs [new file with mode: 0644]
src/tools/rustfmt/tests/source/comments-in-lists/wrap-comments-true.rs [new file with mode: 0644]
src/tools/rustfmt/tests/source/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs [new file with mode: 0644]
src/tools/rustfmt/tests/source/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs [new file with mode: 0644]
src/tools/rustfmt/tests/source/issue-5088/very_long_comment_wrap_comments_true.rs [new file with mode: 0644]
src/tools/rustfmt/tests/source/issue_4823.rs [new file with mode: 0644]
src/tools/rustfmt/tests/source/issue_5027.rs [new file with mode: 0644]
src/tools/rustfmt/tests/source/issue_5086.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/comments-in-lists/format-doc-comments.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-false.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-not-normalized.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-true.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_false.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_false.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_true.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_false.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_true.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5088/single_line_itemized_block_wrap_comments_false.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5088/single_line_itemized_block_wrap_comments_true.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_false.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_wrap_comments_false.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_wrap_comments_true.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5088/very_long_comment_wrap_comments_false.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5088/very_long_comment_wrap_comments_true.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5095.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue_4823.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue_5027.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue_5086.rs [new file with mode: 0644]
src/tools/tidy/src/deps.rs
src/tools/tidy/src/ui_tests.rs
src/version

index 51ed441d0dbe7cfbdc2054899ee317ae9d0a082c..2233162be3b6b464749f9d474f7d189064dbcd10 100644 (file)
@@ -678,9 +678,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.52"
+version = "0.1.55"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6591c2442ee984e2b264638a8b5e7ae44fd47b32d28e3a08e2e9c3cdb0c2fb0"
+checksum = "c9ac60765140c97aaf531dae151a287646b0805ec725805da9e2a3ee31cd501c"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
@@ -1900,9 +1900,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
 
 [[package]]
 name = "libc"
-version = "0.2.106"
+version = "0.2.108"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a60553f9a9e039a333b4e9b20573b9e9b9c0bb3a11e201ccc48ef4283456d673"
+checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -4040,6 +4040,7 @@ name = "rustc_lexer"
 version = "0.1.0"
 dependencies = [
  "expect-test",
+ "unic-emoji-char",
  "unicode-xid",
 ]
 
@@ -5510,6 +5511,47 @@ version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
 
+[[package]]
+name = "unic-char-property"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221"
+dependencies = [
+ "unic-char-range",
+]
+
+[[package]]
+name = "unic-char-range"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc"
+
+[[package]]
+name = "unic-common"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc"
+
+[[package]]
+name = "unic-emoji-char"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b07221e68897210270a38bde4babb655869637af0f69407f96053a34f76494d"
+dependencies = [
+ "unic-char-property",
+ "unic-char-range",
+ "unic-ucd-version",
+]
+
+[[package]]
+name = "unic-ucd-version"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4"
+dependencies = [
+ "unic-common",
+]
+
 [[package]]
 name = "unicase"
 version = "2.6.0"
index a38ab7cabf468c39aace386fb49321579be2dc22..4b9b20f4cba606cd75ecb00ceab7ca2ba7894f6a 100644 (file)
@@ -1,3 +1,117 @@
+Version 1.57.0 (2021-12-02)
+==========================
+
+Language
+--------
+
+- [Macro attributes may follow `#[derive]` and will see the original (pre-`cfg`) input.][87220]
+- [Accept curly-brace macros in expressions, like `m!{ .. }.method()` and `m!{ .. }?`.][88690]
+- [Allow panicking in constant evaluation.][89508]
+
+Compiler
+--------
+
+- [Create more accurate debuginfo for vtables.][89597]
+- [Add `armv6k-nintendo-3ds` at Tier 3\*.][88529]
+- [Add `armv7-unknown-linux-uclibceabihf` at Tier 3\*.][88952]
+- [Add `m68k-unknown-linux-gnu` at Tier 3\*.][88321]
+- [Add SOLID targets at Tier 3\*:][86191] `aarch64-kmc-solid_asp3`, `armv7a-kmc-solid_asp3-eabi`, `armv7a-kmc-solid_asp3-eabihf`
+
+\* Refer to Rust's [platform support page][platform-support-doc] for more
+   information on Rust's tiered platform support.
+
+Libraries
+---------
+
+- [Avoid allocations and copying in `Vec::leak`][89337]
+- [Add `#[repr(i8)]` to `Ordering`][89507]
+- [Optimize `File::read_to_end` and `read_to_string`][89582]
+- [Update to Unicode 14.0][89614]
+- [Many more functions are marked `#[must_use]`][89692], producing a warning
+  when ignoring their return value. This helps catch mistakes such as expecting
+  a function to mutate a value in place rather than return a new value.
+
+Stabilised APIs
+---------------
+
+- [`[T; N]::as_mut_slice`][`array::as_mut_slice`]
+- [`[T; N]::as_slice`][`array::as_slice`]
+- [`collections::TryReserveError`]
+- [`HashMap::try_reserve`]
+- [`HashSet::try_reserve`]
+- [`String::try_reserve`]
+- [`String::try_reserve_exact`]
+- [`Vec::try_reserve`]
+- [`Vec::try_reserve_exact`]
+- [`VecDeque::try_reserve`]
+- [`VecDeque::try_reserve_exact`]
+- [`Iterator::map_while`]
+- [`iter::MapWhile`]
+- [`proc_macro::is_available`]
+- [`Command::get_program`]
+- [`Command::get_args`]
+- [`Command::get_envs`]
+- [`Command::get_current_dir`]
+- [`CommandArgs`]
+- [`CommandEnvs`]
+
+These APIs are now usable in const contexts:
+
+- [`hint::unreachable_unchecked`]
+
+Cargo
+-----
+
+- [Stabilize custom profiles][cargo/9943]
+
+Compatibility notes
+-------------------
+
+Internal changes
+----------------
+These changes provide no direct user facing benefits, but represent significant
+improvements to the internals and overall performance of rustc
+and related tools.
+
+- [Added an experimental backend for codegen with `libgccjit`.][87260]
+
+[86191]: https://github.com/rust-lang/rust/pull/86191/
+[87220]: https://github.com/rust-lang/rust/pull/87220/
+[87260]: https://github.com/rust-lang/rust/pull/87260/
+[88243]: https://github.com/rust-lang/rust/pull/88243/
+[88321]: https://github.com/rust-lang/rust/pull/88321/
+[88529]: https://github.com/rust-lang/rust/pull/88529/
+[88690]: https://github.com/rust-lang/rust/pull/88690/
+[88952]: https://github.com/rust-lang/rust/pull/88952/
+[89337]: https://github.com/rust-lang/rust/pull/89337/
+[89507]: https://github.com/rust-lang/rust/pull/89507/
+[89508]: https://github.com/rust-lang/rust/pull/89508/
+[89582]: https://github.com/rust-lang/rust/pull/89582/
+[89597]: https://github.com/rust-lang/rust/pull/89597/
+[89614]: https://github.com/rust-lang/rust/pull/89614/
+[89692]: https://github.com/rust-lang/rust/issues/89692/
+[cargo/9943]: https://github.com/rust-lang/cargo/pull/9943/
+[`array::as_mut_slice`]: https://doc.rust-lang.org/std/primitive.array.html#method.as_mut_slice
+[`array::as_slice`]: https://doc.rust-lang.org/std/primitive.array.html#method.as_slice
+[`collections::TryReserveError`]: https://doc.rust-lang.org/std/collections/struct.TryReserveError.html
+[`HashMap::try_reserve`]: https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.try_reserve
+[`HashSet::try_reserve`]: https://doc.rust-lang.org/std/collections/hash_set/struct.HashSet.html#method.try_reserve
+[`String::try_reserve`]: https://doc.rust-lang.org/alloc/string/struct.String.html#method.try_reserve
+[`String::try_reserve_exact`]: https://doc.rust-lang.org/alloc/string/struct.String.html#method.try_reserve_exact
+[`Vec::try_reserve`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.try_reserve
+[`Vec::try_reserve_exact`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.try_reserve_exact
+[`VecDeque::try_reserve`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.try_reserve
+[`VecDeque::try_reserve_exact`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.try_reserve_exact
+[`Iterator::map_while`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map_while
+[`iter::MapWhile`]: https://doc.rust-lang.org/std/iter/struct.MapWhile.html
+[`proc_macro::is_available`]: https://doc.rust-lang.org/proc_macro/fn.is_available.html
+[`Command::get_program`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_program
+[`Command::get_args`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_args
+[`Command::get_envs`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_envs
+[`Command::get_current_dir`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_current_dir
+[`CommandArgs`]: https://doc.rust-lang.org/std/process/struct.CommandArgs.html
+[`CommandEnvs`]: https://doc.rust-lang.org/std/process/struct.CommandEnvs.html
+
 Version 1.56.1 (2021-11-01)
 ===========================
 
index abfe8360987c868bbc696928ec38eb92ea60b7bc..4d4c6217ad07ac1e4afec6e55ed867f7fc50b4de 100644 (file)
@@ -405,6 +405,21 @@ pub struct GenericParam {
     pub kind: GenericParamKind,
 }
 
+impl GenericParam {
+    pub fn span(&self) -> Span {
+        match &self.kind {
+            GenericParamKind::Lifetime | GenericParamKind::Type { default: None } => {
+                self.ident.span
+            }
+            GenericParamKind::Type { default: Some(ty) } => self.ident.span.to(ty.span),
+            GenericParamKind::Const { kw_span, default: Some(default), .. } => {
+                kw_span.to(default.value.span)
+            }
+            GenericParamKind::Const { kw_span, default: None, ty } => kw_span.to(ty.span),
+        }
+    }
+}
+
 /// Represents lifetime, type and const parameters attached to a declaration of
 /// a function, enum, trait, etc.
 #[derive(Clone, Encodable, Decodable, Debug)]
@@ -502,6 +517,8 @@ pub struct Crate {
     pub attrs: Vec<Attribute>,
     pub items: Vec<P<Item>>,
     pub span: Span,
+    // Placeholder ID if the crate node is a macro placeholder.
+    pub is_placeholder: Option<NodeId>,
 }
 
 /// Possible values inside of compile-time attribute lists.
index d586426d70ef053c4825ee567eb7289b2e48c18e..b9c397974a163b5330014dd2247e6916c4be0c65 100644 (file)
@@ -1,7 +1,7 @@
 use super::ptr::P;
 use super::token::Nonterminal;
 use super::tokenstream::LazyTokenStream;
-use super::{Arm, ExprField, FieldDef, GenericParam, Param, PatField, Variant};
+use super::{Arm, Crate, ExprField, FieldDef, GenericParam, Param, PatField, Variant};
 use super::{AssocItem, Expr, ForeignItem, Item, Local, MacCallStmt};
 use super::{AttrItem, AttrKind, Block, Pat, Path, Ty, Visibility};
 use super::{AttrVec, Attribute, Stmt, StmtKind};
@@ -276,7 +276,7 @@ fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
 // These ast nodes only support inert attributes, so they don't
 // store tokens (since nothing can observe them)
 derive_has_attrs_no_tokens! {
-    FieldDef, Arm, ExprField, PatField, Variant, Param, GenericParam
+    FieldDef, Arm, ExprField, PatField, Variant, Param, GenericParam, Crate
 }
 
 // These AST nodes don't support attributes, but can
index fc5cc963992579b76514eeddb92d9fb0a851b3b3..205625573a6d930fc75d8338e452e63f04db5d43 100644 (file)
@@ -284,6 +284,10 @@ fn visit_span(&mut self, _sp: &mut Span) {
 /// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
 /// when using a `flat_map_*` or `filter_map_*` method within a `visit_`
 /// method. Abort the program if the closure panics.
+///
+/// FIXME: Abort on panic means that any fatal error inside `visit_clobber` will abort the compiler.
+/// Instead of aborting on catching a panic we need to reset the visited node to some valid but
+/// possibly meaningless value and rethrow the panic.
 //
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
 pub fn visit_clobber<T, F>(t: &mut T, f: F)
@@ -1105,36 +1109,11 @@ pub fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
     visit_unsafety(unsafety, vis);
 }
 
-// FIXME: Avoid visiting the crate as a `Mod` item, flat map only the inner items if possible,
-// or make crate visiting first class if necessary.
 pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
-    visit_clobber(krate, |Crate { attrs, items, span }| {
-        let item_vis =
-            Visibility { kind: VisibilityKind::Public, span: span.shrink_to_lo(), tokens: None };
-        let item = P(Item {
-            ident: Ident::empty(),
-            attrs,
-            id: DUMMY_NODE_ID,
-            vis: item_vis,
-            span,
-            kind: ItemKind::Mod(Unsafe::No, ModKind::Loaded(items, Inline::Yes, span)),
-            tokens: None,
-        });
-        let items = vis.flat_map_item(item);
-
-        let len = items.len();
-        if len == 0 {
-            Crate { attrs: vec![], items: vec![], span }
-        } else if len == 1 {
-            let Item { attrs, span, kind, .. } = items.into_iter().next().unwrap().into_inner();
-            match kind {
-                ItemKind::Mod(_, ModKind::Loaded(items, ..)) => Crate { attrs, items, span },
-                _ => panic!("visitor converted a module to not a module"),
-            }
-        } else {
-            panic!("a crate cannot expand to more than one item");
-        }
-    });
+    let Crate { attrs, items, span, is_placeholder: _ } = krate;
+    visit_attrs(attrs, vis);
+    items.flat_map_in_place(|item| vis.flat_map_item(item));
+    vis.visit_span(span);
 }
 
 // Mutates one item into possibly many items.
index be794ed221ae702331d0940d0df935545d255b61..6840f092da61ba8d7e678f11609c761fa26dcf1a 100644 (file)
@@ -211,6 +211,9 @@ fn visit_expr_field(&mut self, f: &'ast ExprField) {
     fn visit_pat_field(&mut self, fp: &'ast PatField) {
         walk_pat_field(self, fp)
     }
+    fn visit_crate(&mut self, krate: &'ast Crate) {
+        walk_crate(self, krate)
+    }
 }
 
 #[macro_export]
index a0a63620c08a9e02fae235ec9ed36a2b56a71cb5..c9578c2f50f9073260c5633ad726a9d54e7120b5 100644 (file)
@@ -593,7 +593,7 @@ pub(super) fn make_async_expr(
 
     /// Desugar `<expr>.await` into:
     /// ```rust
-    /// match <expr> {
+    /// match ::std::future::IntoFuture::into_future(<expr>) {
     ///     mut pinned => loop {
     ///         match unsafe { ::std::future::Future::poll(
     ///             <::std::pin::Pin>::new_unchecked(&mut pinned),
@@ -629,7 +629,7 @@ fn lower_expr_await(&mut self, await_span: Span, expr: &Expr) -> hir::ExprKind<'
             await_span,
             self.allow_gen_future.clone(),
         );
-        let expr = self.lower_expr(expr);
+        let expr = self.lower_expr_mut(expr);
 
         let pinned_ident = Ident::with_dummy_span(sym::pinned);
         let (pinned_pat, pinned_pat_hid) =
@@ -746,10 +746,26 @@ fn lower_expr_await(&mut self, await_span: Span, expr: &Expr) -> hir::ExprKind<'
         // mut pinned => loop { ... }
         let pinned_arm = self.arm(pinned_pat, loop_expr);
 
-        // match <expr> {
+        // `match ::std::future::IntoFuture::into_future(<expr>) { ... }`
+        let into_future_span = self.mark_span_with_reason(
+            DesugaringKind::Await,
+            await_span,
+            self.allow_into_future.clone(),
+        );
+        let into_future_expr = self.expr_call_lang_item_fn(
+            into_future_span,
+            hir::LangItem::IntoFutureIntoFuture,
+            arena_vec![self; expr],
+        );
+
+        // match <into_future_expr> {
         //     mut pinned => loop { .. }
         // }
-        hir::ExprKind::Match(expr, arena_vec![self; pinned_arm], hir::MatchSource::AwaitDesugar)
+        hir::ExprKind::Match(
+            into_future_expr,
+            arena_vec![self; pinned_arm],
+            hir::MatchSource::AwaitDesugar,
+        )
     }
 
     fn lower_expr_closure(
@@ -915,14 +931,22 @@ fn is_ordinary(lower_ctx: &mut LoweringContext<'_, '_>, lhs: &Expr) -> bool {
             );
         }
         if !self.sess.features_untracked().destructuring_assignment {
-            feature_err(
+            let mut err = feature_err(
                 &self.sess.parse_sess,
                 sym::destructuring_assignment,
                 eq_sign_span,
                 "destructuring assignments are unstable",
-            )
-            .span_label(lhs.span, "cannot assign to this expression")
-            .emit();
+            );
+            err.span_label(lhs.span, "cannot assign to this expression");
+            if self.is_in_loop_condition {
+                err.span_suggestion_verbose(
+                    lhs.span.shrink_to_lo(),
+                    "you might have meant to use pattern destructuring",
+                    "let ".to_string(),
+                    rustc_errors::Applicability::MachineApplicable,
+                );
+            }
+            err.emit();
         }
 
         let mut assignments = vec![];
index 6a4571cf6d278928ab4bd8ae10ceda56613f7e56..692f39368243aaa0c52ce0242504c2f81611536d 100644 (file)
@@ -40,6 +40,11 @@ fn with_trait_impl_ref<T>(
 }
 
 impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
+    fn visit_attribute(&mut self, _: &'a Attribute) {
+        // We do not want to lower expressions that appear in attributes,
+        // as they are not accessible to the rest of the HIR.
+    }
+
     fn visit_item(&mut self, item: &'a Item) {
         let hir_id = self.lctx.with_hir_id_owner(item.id, |lctx| {
             let node = lctx.without_in_scope_lifetime_defs(|lctx| lctx.lower_item(item));
index 2b3a538772ecbc62d57ae5cea8eb7e34665a9e46..1a4f0a26f2bd55c6d702f569ccb5eb439ca02104 100644 (file)
@@ -162,6 +162,7 @@ struct LoweringContext<'a, 'hir: 'a> {
 
     allow_try_trait: Option<Lrc<[Symbol]>>,
     allow_gen_future: Option<Lrc<[Symbol]>>,
+    allow_into_future: Option<Lrc<[Symbol]>>,
 }
 
 pub trait ResolverAstLowering {
@@ -320,6 +321,7 @@ pub fn lower_crate<'a, 'hir>(
         in_scope_lifetimes: Vec::new(),
         allow_try_trait: Some([sym::try_trait_v2][..].into()),
         allow_gen_future: Some([sym::gen_future][..].into()),
+        allow_into_future: Some([sym::into_future][..].into()),
     }
     .lower_crate(krate)
 }
@@ -1786,7 +1788,7 @@ fn lower_async_fn_ret_ty(
             GenericArg::Lifetime(hir::Lifetime {
                 hir_id: self.next_id(),
                 span: self.lower_span(span),
-                name: hir::LifetimeName::Implicit,
+                name: hir::LifetimeName::Implicit(false),
             })));
         let generic_args = self.arena.alloc_from_iter(generic_args);
 
@@ -1927,7 +1929,7 @@ fn lower_generic_param(
                     });
                 let param_name = match lt.name {
                     hir::LifetimeName::Param(param_name) => param_name,
-                    hir::LifetimeName::Implicit
+                    hir::LifetimeName::Implicit(_)
                     | hir::LifetimeName::Underscore
                     | hir::LifetimeName::Static => hir::ParamName::Plain(lt.name.ident()),
                     hir::LifetimeName::ImplicitObjectLifetimeDefault => {
@@ -2290,7 +2292,7 @@ fn elided_ref_lifetime(&mut self, span: Span) -> hir::Lifetime {
 
             AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span),
 
-            AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span),
+            AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span, false),
         }
     }
 
@@ -2322,11 +2324,12 @@ fn elided_path_lifetimes<'s>(
         &'s mut self,
         span: Span,
         count: usize,
+        param_mode: ParamMode,
     ) -> impl Iterator<Item = hir::Lifetime> + Captures<'a> + Captures<'s> + Captures<'hir> {
-        (0..count).map(move |_| self.elided_path_lifetime(span))
+        (0..count).map(move |_| self.elided_path_lifetime(span, param_mode))
     }
 
-    fn elided_path_lifetime(&mut self, span: Span) -> hir::Lifetime {
+    fn elided_path_lifetime(&mut self, span: Span, param_mode: ParamMode) -> hir::Lifetime {
         match self.anonymous_lifetime_mode {
             AnonymousLifetimeMode::CreateParameter => {
                 // We should have emitted E0726 when processing this path above
@@ -2342,7 +2345,7 @@ fn elided_path_lifetime(&mut self, span: Span) -> hir::Lifetime {
             // lifetime. Instead, we simply create an implicit lifetime, which will be checked
             // later, at which point a suitable error will be emitted.
             AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => {
-                self.new_implicit_lifetime(span)
+                self.new_implicit_lifetime(span, param_mode == ParamMode::Explicit)
             }
         }
     }
@@ -2385,11 +2388,11 @@ fn elided_dyn_bound(&mut self, span: Span) -> hir::Lifetime {
         r
     }
 
-    fn new_implicit_lifetime(&mut self, span: Span) -> hir::Lifetime {
+    fn new_implicit_lifetime(&mut self, span: Span, missing: bool) -> hir::Lifetime {
         hir::Lifetime {
             hir_id: self.next_id(),
             span: self.lower_span(span),
-            name: hir::LifetimeName::Implicit,
+            name: hir::LifetimeName::Implicit(missing),
         }
     }
 
@@ -2536,7 +2539,7 @@ fn visit_generic_param(&mut self, param: &'v hir::GenericParam<'v>) {
 
         fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
             let name = match lifetime.name {
-                hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => {
+                hir::LifetimeName::Implicit(_) | hir::LifetimeName::Underscore => {
                     if self.collect_elided_lifetimes {
                         // Use `'_` for both implicit and underscore lifetimes in
                         // `type Foo<'_> = impl SomeTrait<'_>;`.
index 929f427484dba4ac28ba65fd7bf931c067c46376..78afc33974826a048c4b59d31c001a19e4b49fc4 100644 (file)
@@ -7,8 +7,6 @@
 use rustc_hir::def::{DefKind, PartialRes, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::GenericArg;
-use rustc_session::lint::builtin::ELIDED_LIFETIMES_IN_PATHS;
-use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_span::symbol::Ident;
 use rustc_span::{BytePos, Span, DUMMY_SP};
 
@@ -231,15 +229,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) {
                             // Do not suggest going from `Trait()` to `Trait<>`
                             if !data.inputs.is_empty() {
-                                if let Some(split) = snippet.find('(') {
-                                    let trait_name = &snippet[0..split];
-                                    let args = &snippet[split + 1..snippet.len() - 1];
-                                    err.span_suggestion(
-                                        data.span,
-                                        "use angle brackets instead",
-                                        format!("{}<{}>", trait_name, args),
-                                        Applicability::MaybeIncorrect,
-                                    );
+                                // Suggest replacing `(` and `)` with `<` and `>`
+                                // The snippet may be missing the closing `)`, skip that case
+                                if snippet.ends_with(')') {
+                                    if let Some(split) = snippet.find('(') {
+                                        let trait_name = &snippet[0..split];
+                                        let args = &snippet[split + 1..snippet.len() - 1];
+                                        err.span_suggestion(
+                                            data.span,
+                                            "use angle brackets instead",
+                                            format!("{}<{}>", trait_name, args),
+                                            Applicability::MaybeIncorrect,
+                                        );
+                                    }
                                 }
                             }
                         };
@@ -270,12 +272,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         let has_lifetimes =
             generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
-        if !generic_args.parenthesized && !has_lifetimes {
+        if !generic_args.parenthesized && !has_lifetimes && expected_lifetimes > 0 {
             // Note: these spans are used for diagnostics when they can't be inferred.
             // See rustc_resolve::late::lifetimes::LifetimeContext::add_missing_lifetime_specifiers_label
             let elided_lifetime_span = if generic_args.span.is_empty() {
                 // If there are no brackets, use the identifier span.
-                segment.ident.span
+                path_span
             } else if generic_args.is_empty() {
                 // If there are brackets, but not generic arguments, then use the opening bracket
                 generic_args.span.with_hi(generic_args.span.lo() + BytePos(1))
@@ -284,67 +286,47 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo()
             };
             generic_args.args = self
-                .elided_path_lifetimes(elided_lifetime_span, expected_lifetimes)
+                .elided_path_lifetimes(elided_lifetime_span, expected_lifetimes, param_mode)
                 .map(GenericArg::Lifetime)
                 .chain(generic_args.args.into_iter())
                 .collect();
-            if expected_lifetimes > 0 && param_mode == ParamMode::Explicit {
+            // In create-parameter mode we error here because we don't want to support
+            // deprecated impl elision in new features like impl elision and `async fn`,
+            // both of which work using the `CreateParameter` mode:
+            //
+            //     impl Foo for std::cell::Ref<u32> // note lack of '_
+            //     async fn foo(_: std::cell::Ref<u32>) { ... }
+            if let (ParamMode::Explicit, AnonymousLifetimeMode::CreateParameter) =
+                (param_mode, self.anonymous_lifetime_mode)
+            {
                 let anon_lt_suggestion = vec!["'_"; expected_lifetimes].join(", ");
                 let no_non_lt_args = generic_args.args.len() == expected_lifetimes;
                 let no_bindings = generic_args.bindings.is_empty();
-                let (incl_angl_brckt, insertion_sp, suggestion) = if no_non_lt_args && no_bindings {
+                let (incl_angl_brckt, suggestion) = if no_non_lt_args && no_bindings {
                     // If there are no generic args, our suggestion can include the angle brackets.
-                    (true, path_span.shrink_to_hi(), format!("<{}>", anon_lt_suggestion))
+                    (true, format!("<{}>", anon_lt_suggestion))
                 } else {
                     // Otherwise we'll insert a `'_, ` right after the opening bracket.
-                    let span = generic_args
-                        .span
-                        .with_lo(generic_args.span.lo() + BytePos(1))
-                        .shrink_to_lo();
-                    (false, span, format!("{}, ", anon_lt_suggestion))
+                    (false, format!("{}, ", anon_lt_suggestion))
                 };
-                match self.anonymous_lifetime_mode {
-                    // In create-parameter mode we error here because we don't want to support
-                    // deprecated impl elision in new features like impl elision and `async fn`,
-                    // both of which work using the `CreateParameter` mode:
-                    //
-                    //     impl Foo for std::cell::Ref<u32> // note lack of '_
-                    //     async fn foo(_: std::cell::Ref<u32>) { ... }
-                    AnonymousLifetimeMode::CreateParameter => {
-                        let mut err = struct_span_err!(
-                            self.sess,
-                            path_span,
-                            E0726,
-                            "implicit elided lifetime not allowed here"
-                        );
-                        rustc_errors::add_elided_lifetime_in_path_suggestion(
-                            &self.sess.source_map(),
-                            &mut err,
-                            expected_lifetimes,
-                            path_span,
-                            incl_angl_brckt,
-                            insertion_sp,
-                            suggestion,
-                        );
-                        err.note("assuming a `'static` lifetime...");
-                        err.emit();
-                    }
-                    AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => {
-                        self.resolver.lint_buffer().buffer_lint_with_diagnostic(
-                            ELIDED_LIFETIMES_IN_PATHS,
-                            CRATE_NODE_ID,
-                            path_span,
-                            "hidden lifetime parameters in types are deprecated",
-                            BuiltinLintDiagnostics::ElidedLifetimesInPaths(
-                                expected_lifetimes,
-                                path_span,
-                                incl_angl_brckt,
-                                insertion_sp,
-                                suggestion,
-                            ),
-                        );
-                    }
-                }
+                let insertion_sp = elided_lifetime_span.shrink_to_hi();
+                let mut err = struct_span_err!(
+                    self.sess,
+                    path_span,
+                    E0726,
+                    "implicit elided lifetime not allowed here"
+                );
+                rustc_errors::add_elided_lifetime_in_path_suggestion(
+                    &self.sess.source_map(),
+                    &mut err,
+                    expected_lifetimes,
+                    path_span,
+                    incl_angl_brckt,
+                    insertion_sp,
+                    suggestion,
+                );
+                err.note("assuming a `'static` lifetime...");
+                err.emit();
             }
         }
 
index 1822ba6ec996493d952d217a25fa39253c5c383a..efc30121987e289389fb54525bf191035a814efb 100644 (file)
@@ -23,7 +23,7 @@
 use rustc_span::Span;
 use rustc_target::spec::abi;
 use std::mem;
-use std::ops::DerefMut;
+use std::ops::{Deref, DerefMut};
 
 const MORE_EXTERN: &str =
     "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html";
@@ -1714,6 +1714,53 @@ fn deny_equality_constraints(
             }
         }
     }
+    // Given `A: Foo, A::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
+    if let TyKind::Path(None, full_path) = &predicate.lhs_ty.kind {
+        if let [potential_param, potential_assoc] = &full_path.segments[..] {
+            for param in &generics.params {
+                if param.ident == potential_param.ident {
+                    for bound in &param.bounds {
+                        if let ast::GenericBound::Trait(trait_ref, TraitBoundModifier::None) = bound
+                        {
+                            if let [trait_segment] = &trait_ref.trait_ref.path.segments[..] {
+                                let assoc = pprust::path_to_string(&ast::Path::from_ident(
+                                    potential_assoc.ident,
+                                ));
+                                let ty = pprust::ty_to_string(&predicate.rhs_ty);
+                                let (args, span) = match &trait_segment.args {
+                                    Some(args) => match args.deref() {
+                                        ast::GenericArgs::AngleBracketed(args) => {
+                                            let Some(arg) = args.args.last() else {
+                                                continue;
+                                            };
+                                            (
+                                                format!(", {} = {}", assoc, ty),
+                                                arg.span().shrink_to_hi(),
+                                            )
+                                        }
+                                        _ => continue,
+                                    },
+                                    None => (
+                                        format!("<{} = {}>", assoc, ty),
+                                        trait_segment.span().shrink_to_hi(),
+                                    ),
+                                };
+                                err.multipart_suggestion(
+                                    &format!(
+                                        "if `{}::{}` is an associated type you're trying to set, \
+                                        use the associated type binding syntax",
+                                        trait_segment.ident, potential_assoc.ident,
+                                    ),
+                                    vec![(span, args), (predicate.span, String::new())],
+                                    Applicability::MaybeIncorrect,
+                                );
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
     err.note(
         "see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information",
     );
index 47666670b2b63dbb2f2fbbe714e278011e1da4d7..adc4d117b805f587e349d4f8294fefe0731d4a00 100644 (file)
@@ -6,6 +6,7 @@
 
 #![feature(iter_is_partitioned)]
 #![feature(box_patterns)]
+#![feature(let_else)]
 #![recursion_limit = "256"]
 
 pub mod ast_validation;
index e74f38dd89c35c4a34bb572b5c34070bdeb89594..4b5703a429e718cc7db732f884fa080783bb27ab 100644 (file)
@@ -75,3 +75,12 @@ pub fn attribute_to_string(attr: &ast::Attribute) -> String {
 pub fn to_string(f: impl FnOnce(&mut State<'_>)) -> String {
     State::new().to_string(f)
 }
+
+pub fn crate_to_string_for_macros(krate: &ast::Crate) -> String {
+    State::new().to_string(|s| {
+        s.print_inner_attributes(&krate.attrs);
+        for item in &krate.items {
+            s.print_item(item);
+        }
+    })
+}
index 719caaabbbf0a343c30138abf75e2153c0690de6..f441c105f70039e8308322ca9cdf6ddd93a6d365 100644 (file)
@@ -519,8 +519,10 @@ pub fn eval_condition(
                 [NestedMetaItem::Literal(Lit { kind: LitKind::Str(sym, ..), span, .. })] => {
                     (sym, span)
                 }
-                [NestedMetaItem::Literal(Lit { span, .. })
-                | NestedMetaItem::MetaItem(MetaItem { span, .. })] => {
+                [
+                    NestedMetaItem::Literal(Lit { span, .. })
+                    | NestedMetaItem::MetaItem(MetaItem { span, .. }),
+                ] => {
                     sess.span_diagnostic
                         .struct_span_err(*span, "expected a version literal")
                         .emit();
index 46a3c0fa1015248cfcc806148757693432b26c00..8c4508ed18882dcad064805ca7c83915260ec93c 100644 (file)
@@ -977,9 +977,7 @@ pub(crate) fn report_borrowed_value_does_not_live_long_enough(
                 Some(ref name),
                 BorrowExplanation::MustBeValidFor {
                     category:
-                        category
-                        @
-                        (ConstraintCategory::Return(_)
+                        category @ (ConstraintCategory::Return(_)
                         | ConstraintCategory::CallArgument
                         | ConstraintCategory::OpaqueType),
                     from_closure: false,
index 79623e26eb710d304d4556ad30a335aa42a07fbe..42f5d557542088a10d3da5cb673a85f494cd66e7 100644 (file)
@@ -738,15 +738,13 @@ pub(super) fn describe_for_unnamed_place(&self, tcx: TyCtxt<'_>) -> String {
             BorrowedContentSource::DerefRawPointer => "a raw pointer".to_string(),
             BorrowedContentSource::DerefSharedRef => "a shared reference".to_string(),
             BorrowedContentSource::DerefMutableRef => "a mutable reference".to_string(),
-            BorrowedContentSource::OverloadedDeref(ty) => match ty.kind() {
-                ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Rc, def.did) => {
-                    "an `Rc`".to_string()
-                }
-                ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Arc, def.did) => {
-                    "an `Arc`".to_string()
-                }
-                _ => format!("dereference of `{}`", ty),
-            },
+            BorrowedContentSource::OverloadedDeref(ty) => ty
+                .ty_adt_def()
+                .and_then(|adt| match tcx.get_diagnostic_name(adt.did)? {
+                    name @ (sym::Rc | sym::Arc) => Some(format!("an `{}`", name)),
+                    _ => None,
+                })
+                .unwrap_or_else(|| format!("dereference of `{}`", ty)),
             BorrowedContentSource::OverloadedIndex(ty) => format!("index of `{}`", ty),
         }
     }
@@ -770,15 +768,13 @@ pub(super) fn describe_for_immutable_place(&self, tcx: TyCtxt<'_>) -> String {
             BorrowedContentSource::DerefMutableRef => {
                 bug!("describe_for_immutable_place: DerefMutableRef isn't immutable")
             }
-            BorrowedContentSource::OverloadedDeref(ty) => match ty.kind() {
-                ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Rc, def.did) => {
-                    "an `Rc`".to_string()
-                }
-                ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Arc, def.did) => {
-                    "an `Arc`".to_string()
-                }
-                _ => format!("a dereference of `{}`", ty),
-            },
+            BorrowedContentSource::OverloadedDeref(ty) => ty
+                .ty_adt_def()
+                .and_then(|adt| match tcx.get_diagnostic_name(adt.did)? {
+                    name @ (sym::Rc | sym::Arc) => Some(format!("an `{}`", name)),
+                    _ => None,
+                })
+                .unwrap_or_else(|| format!("dereference of `{}`", ty)),
             BorrowedContentSource::OverloadedIndex(ty) => format!("an index of `{}`", ty),
         }
     }
@@ -960,8 +956,7 @@ pub(super) fn move_spans(
                         _ => None,
                     });
                 let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
-                    tcx.is_diagnostic_item(sym::Option, def_id)
-                        || tcx.is_diagnostic_item(sym::Result, def_id)
+                    matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
                 });
                 FnSelfUseKind::Normal { self_arg, implicit_into_iter, is_option_or_result }
             });
index 46e2a99a0d0940cd381dafef4ee1fda32267913b..b4821ee36e0a391a00cb8792ec7f867e19447fcb 100644 (file)
@@ -165,10 +165,13 @@ pub(crate) fn report_mutability_error(
             PlaceRef {
                 local: _,
                 projection:
-                    [.., ProjectionElem::Index(_)
-                    | ProjectionElem::ConstantIndex { .. }
-                    | ProjectionElem::Subslice { .. }
-                    | ProjectionElem::Downcast(..)],
+                    [
+                        ..,
+                        ProjectionElem::Index(_)
+                        | ProjectionElem::ConstantIndex { .. }
+                        | ProjectionElem::Subslice { .. }
+                        | ProjectionElem::Downcast(..),
+                    ],
             } => bug!("Unexpected immutable place."),
         }
 
@@ -217,7 +220,12 @@ pub(crate) fn report_mutability_error(
             PlaceRef {
                 local,
                 projection:
-                    [proj_base @ .., ProjectionElem::Deref, ProjectionElem::Field(field, _), ProjectionElem::Deref],
+                    [
+                        proj_base @ ..,
+                        ProjectionElem::Deref,
+                        ProjectionElem::Field(field, _),
+                        ProjectionElem::Deref,
+                    ],
             } => {
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
 
@@ -447,16 +455,20 @@ pub(crate) fn report_mutability_error(
                                 // check if the RHS is from desugaring
                                 let opt_assignment_rhs_span =
                                     self.body.find_assignments(local).first().map(|&location| {
-                                        let stmt = &self.body[location.block].statements
-                                            [location.statement_index];
-                                        match stmt.kind {
-                                            mir::StatementKind::Assign(box (
-                                                _,
-                                                mir::Rvalue::Use(mir::Operand::Copy(place)),
-                                            )) => {
-                                                self.body.local_decls[place.local].source_info.span
-                                            }
-                                            _ => self.body.source_info(location).span,
+                                        if let Some(mir::Statement {
+                                            source_info: _,
+                                            kind:
+                                                mir::StatementKind::Assign(box (
+                                                    _,
+                                                    mir::Rvalue::Use(mir::Operand::Copy(place)),
+                                                )),
+                                        }) = self.body[location.block]
+                                            .statements
+                                            .get(location.statement_index)
+                                        {
+                                            self.body.local_decls[place.local].source_info.span
+                                        } else {
+                                            self.body.source_info(location).span
                                         }
                                     });
                                 match opt_assignment_rhs_span.and_then(|s| s.desugaring_kind()) {
@@ -759,11 +771,14 @@ fn maybe_body_id_of_fn(hir_map: &Map<'tcx>, id: HirId) -> Option<BodyId> {
                                                 kind:
                                                     Call(
                                                         _,
-                                                        [Expr {
-                                                            kind: MethodCall(path_segment, ..),
-                                                            hir_id,
-                                                            ..
-                                                        }, ..],
+                                                        [
+                                                            Expr {
+                                                                kind: MethodCall(path_segment, ..),
+                                                                hir_id,
+                                                                ..
+                                                            },
+                                                            ..,
+                                                        ],
                                                     ),
                                                 ..
                                             },
index 5edb52b0b650dca370cbced4b8c34a86a2d9def3..80f5f77a025507b320151597b8f75804c4fac261 100644 (file)
@@ -584,7 +584,7 @@ fn match_adt_and_segment<'hir>(
                 Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime_span))
             }
 
-            hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Implicit => {
+            hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Implicit(_) => {
                 // In this case, the user left off the lifetime; so
                 // they wrote something like:
                 //
@@ -769,20 +769,24 @@ fn get_future_inner_return_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::
             let opaque_ty = hir.item(id);
             if let hir::ItemKind::OpaqueTy(hir::OpaqueTy {
                 bounds:
-                    [hir::GenericBound::LangItemTrait(
-                        hir::LangItem::Future,
-                        _,
-                        _,
-                        hir::GenericArgs {
-                            bindings:
-                                [hir::TypeBinding {
-                                    ident: Ident { name: sym::Output, .. },
-                                    kind: hir::TypeBindingKind::Equality { ty },
-                                    ..
-                                }],
-                            ..
-                        },
-                    )],
+                    [
+                        hir::GenericBound::LangItemTrait(
+                            hir::LangItem::Future,
+                            _,
+                            _,
+                            hir::GenericArgs {
+                                bindings:
+                                    [
+                                        hir::TypeBinding {
+                                            ident: Ident { name: sym::Output, .. },
+                                            kind: hir::TypeBindingKind::Equality { ty },
+                                            ..
+                                        },
+                                    ],
+                                ..
+                            },
+                        ),
+                    ],
                 ..
             }) = opaque_ty.kind
             {
index 76d3a83b48daa45d7a4da26c3b847ef5ccbdd0d1..ceaae9d66cd53feff5ea853dee19eca8359bcf6d 100644 (file)
@@ -3,7 +3,6 @@
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(crate_visibility_modifier)]
-#![cfg_attr(bootstrap, feature(format_args_capture))]
 #![feature(in_band_lifetimes)]
 #![feature(iter_zip)]
 #![feature(let_else)]
index 20567610f6557895076e7a79ef877d3259df641b..4b6cab24cdb70457537d01f21608a3cacea06e68 100644 (file)
@@ -1,7 +1,7 @@
 use rustc_index::vec::IndexVec;
 use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
 use rustc_middle::mir::visit::{MutVisitor, TyContext};
-use rustc_middle::mir::{Body, Location, PlaceElem, Promoted};
+use rustc_middle::mir::{Body, Location, Promoted};
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
 
@@ -62,22 +62,6 @@ fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) {
         debug!(?ty);
     }
 
-    fn process_projection_elem(
-        &mut self,
-        elem: PlaceElem<'tcx>,
-        _: Location,
-    ) -> Option<PlaceElem<'tcx>> {
-        if let PlaceElem::Field(field, ty) = elem {
-            let new_ty = self.renumber_regions(ty);
-
-            if new_ty != ty {
-                return Some(PlaceElem::Field(field, new_ty));
-            }
-        }
-
-        None
-    }
-
     #[instrument(skip(self), level = "debug")]
     fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) {
         *substs = self.renumber_regions(*substs);
index ab1a7461b4b9bf5c05149d443af0a0d1f944d7b3..a3b39591f8db261891835ea878a1dfc8a5445560 100644 (file)
@@ -6,6 +6,7 @@
 use rustc_infer::infer::{self, InferCtxt, SubregionOrigin};
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::subst::GenericArgKind;
+use rustc_middle::ty::TypeFoldable;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::DUMMY_SP;
 
@@ -95,11 +96,23 @@ pub(super) fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx
                 self.add_outlives(r1_vid, r2_vid);
             }
 
-            GenericArgKind::Type(t1) => {
+            GenericArgKind::Type(mut t1) => {
                 // we don't actually use this for anything, but
                 // the `TypeOutlives` code needs an origin.
                 let origin = infer::RelateParamBound(DUMMY_SP, t1, None);
 
+                // Placeholder regions need to be converted now because it may
+                // create new region variables, which can't be done later when
+                // verifying these bounds.
+                if t1.has_placeholders() {
+                    t1 = tcx.fold_regions(&t1, &mut false, |r, _| match *r {
+                        ty::RegionKind::RePlaceholder(placeholder) => {
+                            self.constraints.placeholder_region(self.infcx, placeholder)
+                        }
+                        _ => r,
+                    });
+                }
+
                 TypeOutlives::new(
                     &mut *self,
                     tcx,
index f71cf09ecf6304941c6fb6d2a04497185ed0ad58..8d97c3cbb0b0ebd406fa9301d91827a36c08617d 100644 (file)
@@ -256,7 +256,6 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
                 debug!("build: input_or_output={:?}", ty);
                 // We add implied bounds from both the unnormalized and normalized ty
                 // See issue #87748
-                let constraints_implied_1 = self.add_implied_bounds(ty);
                 let TypeOpOutput { output: norm_ty, constraints: constraints1, .. } = self
                     .param_env
                     .and(type_op::normalize::Normalize::new(ty))
@@ -284,10 +283,9 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
                 // }
                 // ```
                 // Both &Self::Bar and &() are WF
-                let constraints_implied_2 =
-                    if ty != norm_ty { self.add_implied_bounds(norm_ty) } else { None };
+                let constraints_implied = self.add_implied_bounds(norm_ty);
                 normalized_inputs_and_output.push(norm_ty);
-                constraints1.into_iter().chain(constraints_implied_1).chain(constraints_implied_2)
+                constraints1.into_iter().chain(constraints_implied)
             })
             .collect();
 
index 307730f7f5f14a9f88f4f627fe2a3b03f84fc3e8..5933a49ea58033cfc291532b3e1e9263ad7dee2a 100644 (file)
@@ -11,7 +11,7 @@
 use rustc_expand::config::StripUnconfigured;
 use rustc_expand::configure;
 use rustc_feature::Features;
-use rustc_parse::parser::ForceCollect;
+use rustc_parse::parser::{ForceCollect, Parser};
 use rustc_session::utils::FlattenNonterminals;
 use rustc_session::Session;
 use rustc_span::symbol::sym;
@@ -77,6 +77,10 @@ fn flat_map_annotatable(
         Annotatable::Param(param) => vis.flat_map_param(param).pop().map(Annotatable::Param),
         Annotatable::FieldDef(sf) => vis.flat_map_field_def(sf).pop().map(Annotatable::FieldDef),
         Annotatable::Variant(v) => vis.flat_map_variant(v).pop().map(Annotatable::Variant),
+        Annotatable::Crate(mut krate) => {
+            vis.visit_crate(&mut krate);
+            Some(Annotatable::Crate(krate))
+        }
     }
 }
 
@@ -101,6 +105,7 @@ fn has_cfg_or_cfg_attr(annotatable: &Annotatable) -> bool {
             Annotatable::Param(param) => finder.visit_param(&param),
             Annotatable::FieldDef(field) => finder.visit_field_def(&field),
             Annotatable::Variant(variant) => finder.visit_variant(&variant),
+            Annotatable::Crate(krate) => finder.visit_crate(krate),
         };
         finder.has_cfg_or_cfg_attr
     }
@@ -138,8 +143,34 @@ fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> Option<Anno
         // the location of `#[cfg]` and `#[cfg_attr]` in the token stream. The tokenization
         // process is lossless, so this process is invisible to proc-macros.
 
-        // FIXME - get rid of this clone
-        let nt = annotatable.clone().into_nonterminal();
+        let parse_annotatable_with: fn(&mut Parser<'_>) -> _ = match annotatable {
+            Annotatable::Item(_) => {
+                |parser| Annotatable::Item(parser.parse_item(ForceCollect::Yes).unwrap().unwrap())
+            }
+            Annotatable::TraitItem(_) => |parser| {
+                Annotatable::TraitItem(
+                    parser.parse_trait_item(ForceCollect::Yes).unwrap().unwrap().unwrap(),
+                )
+            },
+            Annotatable::ImplItem(_) => |parser| {
+                Annotatable::ImplItem(
+                    parser.parse_impl_item(ForceCollect::Yes).unwrap().unwrap().unwrap(),
+                )
+            },
+            Annotatable::ForeignItem(_) => |parser| {
+                Annotatable::ForeignItem(
+                    parser.parse_foreign_item(ForceCollect::Yes).unwrap().unwrap().unwrap(),
+                )
+            },
+            Annotatable::Stmt(_) => |parser| {
+                Annotatable::Stmt(P(parser.parse_stmt(ForceCollect::Yes).unwrap().unwrap()))
+            },
+            Annotatable::Expr(_) => {
+                |parser| Annotatable::Expr(parser.parse_expr_force_collect().unwrap())
+            }
+            _ => unreachable!(),
+        };
+        let nt = annotatable.into_nonterminal();
 
         let mut orig_tokens = rustc_parse::nt_to_tokenstream(
             &nt,
@@ -173,25 +204,7 @@ fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> Option<Anno
         let mut parser =
             rustc_parse::stream_to_parser(&self.cfg.sess.parse_sess, orig_tokens, None);
         parser.capture_cfg = true;
-        annotatable = match annotatable {
-            Annotatable::Item(_) => {
-                Annotatable::Item(parser.parse_item(ForceCollect::Yes).unwrap().unwrap())
-            }
-            Annotatable::TraitItem(_) => Annotatable::TraitItem(
-                parser.parse_trait_item(ForceCollect::Yes).unwrap().unwrap().unwrap(),
-            ),
-            Annotatable::ImplItem(_) => Annotatable::ImplItem(
-                parser.parse_impl_item(ForceCollect::Yes).unwrap().unwrap().unwrap(),
-            ),
-            Annotatable::ForeignItem(_) => Annotatable::ForeignItem(
-                parser.parse_foreign_item(ForceCollect::Yes).unwrap().unwrap().unwrap(),
-            ),
-            Annotatable::Stmt(_) => {
-                Annotatable::Stmt(P(parser.parse_stmt(ForceCollect::Yes).unwrap().unwrap()))
-            }
-            Annotatable::Expr(_) => Annotatable::Expr(parser.parse_expr_force_collect().unwrap()),
-            _ => unreachable!(),
-        };
+        annotatable = parse_annotatable_with(&mut parser);
 
         // Now that we have our re-parsed `AttrAnnotatedTokenStream`, recursively configuring
         // our attribute target will correctly the tokens as well.
index 097eaddb874083ec2895f553eaf16fecfff555ef..62a55c0e49ed08ed94a0263688f01e6ceedba9ba 100644 (file)
@@ -88,8 +88,8 @@ struct Context<'a, 'b> {
     /// * Implicit argument resolution: `"{1:.0$} {2:.foo$} {1:.3$} {4:.0$}"`
     /// * Name resolution: `"{1:.0$} {2:.5$} {1:.3$} {4:.0$}"`
     /// * `count_positions` (in JSON): `{0: 0, 5: 1, 3: 2}`
-    /// * `count_args`: `vec![Exact(0), Exact(5), Exact(3)]`
-    count_args: Vec<Position>,
+    /// * `count_args`: `vec![0, 5, 3]`
+    count_args: Vec<usize>,
     /// Relative slot numbers for count arguments.
     count_positions: FxHashMap<usize, usize>,
     /// Number of count slots assigned.
@@ -513,7 +513,7 @@ fn verify_arg_type(&mut self, arg: Position, ty: ArgumentType) {
                         if let Entry::Vacant(e) = self.count_positions.entry(arg) {
                             let i = self.count_positions_count;
                             e.insert(i);
-                            self.count_args.push(Exact(arg));
+                            self.count_args.push(arg);
                             self.count_positions_count += 1;
                         }
                     }
@@ -769,13 +769,12 @@ fn into_expr(self) -> P<ast::Expr> {
             for arg_ty in self.arg_unique_types[i].iter() {
                 args.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, i));
             }
-            heads.push(self.ecx.expr_addr_of(e.span, e));
+            // use the arg span for `&arg` so that borrowck errors
+            // point to the specific expression passed to the macro
+            // (the span is otherwise unavailable in MIR)
+            heads.push(self.ecx.expr_addr_of(e.span.with_ctxt(self.macsp.ctxt()), e));
         }
-        for pos in self.count_args {
-            let index = match pos {
-                Exact(i) => i,
-                _ => panic!("should never happen"),
-            };
+        for index in self.count_args {
             let span = spans_pos[index];
             args.push(Context::format_arg(self.ecx, self.macsp, span, &Count, index));
         }
index 64ccd4331e58a7c3492840e3bba07e8d88452e4b..418729e78436fc028e5ee902a581376bff319859 100644 (file)
@@ -84,9 +84,35 @@ struct TestHarnessGenerator<'a> {
     tests: Vec<Test>,
 }
 
+impl TestHarnessGenerator<'_> {
+    fn add_test_cases(&mut self, node_id: ast::NodeId, span: Span, prev_tests: Vec<Test>) {
+        let mut tests = mem::replace(&mut self.tests, prev_tests);
+
+        if !tests.is_empty() {
+            // Create an identifier that will hygienically resolve the test
+            // case name, even in another module.
+            let expn_id = self.cx.ext_cx.resolver.expansion_for_ast_pass(
+                span,
+                AstPass::TestHarness,
+                &[],
+                Some(node_id),
+            );
+            for test in &mut tests {
+                // See the comment on `mk_main` for why we're using
+                // `apply_mark` directly.
+                test.ident.span =
+                    test.ident.span.apply_mark(expn_id.to_expn_id(), Transparency::Opaque);
+            }
+            self.cx.test_cases.extend(tests);
+        }
+    }
+}
+
 impl<'a> MutVisitor for TestHarnessGenerator<'a> {
     fn visit_crate(&mut self, c: &mut ast::Crate) {
+        let prev_tests = mem::take(&mut self.tests);
         noop_visit_crate(c, self);
+        self.add_test_cases(ast::CRATE_NODE_ID, c.span, prev_tests);
 
         // Create a main function to run our tests
         c.items.push(mk_main(&mut self.cx));
@@ -103,34 +129,10 @@ fn visit_crate(&mut self, c: &mut ast::Crate) {
 
         // We don't want to recurse into anything other than mods, since
         // mods or tests inside of functions will break things
-        if let ast::ItemKind::Mod(..) = item.kind {
-            let tests = mem::take(&mut self.tests);
+        if let ast::ItemKind::Mod(_, ModKind::Loaded(.., span)) = item.kind {
+            let prev_tests = mem::take(&mut self.tests);
             noop_visit_item_kind(&mut item.kind, self);
-            let mut tests = mem::replace(&mut self.tests, tests);
-
-            if !tests.is_empty() {
-                let parent =
-                    if item.id == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { item.id };
-                // Create an identifier that will hygienically resolve the test
-                // case name, even in another module.
-                let inner_span = match item.kind {
-                    ast::ItemKind::Mod(_, ModKind::Loaded(.., span)) => span,
-                    _ => unreachable!(),
-                };
-                let expn_id = self.cx.ext_cx.resolver.expansion_for_ast_pass(
-                    inner_span,
-                    AstPass::TestHarness,
-                    &[],
-                    Some(parent),
-                );
-                for test in &mut tests {
-                    // See the comment on `mk_main` for why we're using
-                    // `apply_mark` directly.
-                    test.ident.span =
-                        test.ident.span.apply_mark(expn_id.to_expn_id(), Transparency::Opaque);
-                }
-                self.cx.test_cases.extend(tests);
-            }
+            self.add_test_cases(item.id, span, prev_tests);
         }
         smallvec![P(item)]
     }
@@ -146,7 +148,7 @@ fn entry_point_type(sess: &Session, item: &ast::Item, depth: usize) -> EntryPoin
             } else if sess.contains_name(&item.attrs, sym::rustc_main) {
                 EntryPointType::MainAttr
             } else if item.ident.name == sym::main {
-                if depth == 1 {
+                if depth == 0 {
                     // This is a top-level function so can be 'main'
                     EntryPointType::MainNamed
                 } else {
index 2144e7ed67acbc75a7e4ca0c3781e27148f5294c..45d4906259312db4942a3d662acac102593514a6 100644 (file)
@@ -71,7 +71,7 @@ fn apply_arg_attrs_to_abi_param(mut param: AbiParam, arg_attrs: ArgAttributes) -
         .prefix
         .iter()
         .flatten()
-        .map(|&kind| reg_to_abi_param(Reg { kind, size: cast.prefix_chunk_size }))
+        .map(|&reg| reg_to_abi_param(reg))
         .chain((0..rest_count).map(|_| reg_to_abi_param(cast.rest.unit)))
         .collect::<SmallVec<_>>();
 
index ce428c589a478f1f6059d3a4845c21b5e407db82..a8b1e70e2bb801e432b5940d126bd4cad33eca63 100644 (file)
@@ -14,7 +14,7 @@ fn apply_attrs_callsite(&mut self, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, _callsite: S
         // TODO(antoyo)
     }
 
-    fn get_param(&self, index: usize) -> Self::Value {
+    fn get_param(&mut self, index: usize) -> Self::Value {
         self.cx.current_func.borrow().expect("current func")
             .get_param(index as i32)
             .to_rvalue()
@@ -48,8 +48,8 @@ fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, '_>) -> Type<'gcc> {
         let mut args: Vec<_> = self
             .prefix
             .iter()
-            .flat_map(|option_kind| {
-                option_kind.map(|kind| Reg { kind, size: self.prefix_chunk_size }.gcc_type(cx))
+            .flat_map(|option_reg| {
+                option_reg.map(|reg| reg.gcc_type(cx))
             })
             .chain((0..rest_count).map(|_| rest_gcc_unit))
             .collect();
index bedd3523d899e89f0f8205c28b72ad7e03307c17..d38ff588317a26ebf48845a3f1cbe0a596b06221 100644 (file)
@@ -181,9 +181,7 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type {
         let mut args: Vec<_> = self
             .prefix
             .iter()
-            .flat_map(|option_kind| {
-                option_kind.map(|kind| Reg { kind, size: self.prefix_chunk_size }.llvm_type(cx))
-            })
+            .flat_map(|option_reg| option_reg.map(|reg| reg.llvm_type(cx)))
             .chain((0..rest_count).map(|_| rest_ll_unit))
             .collect();
 
@@ -466,6 +464,9 @@ fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) {
                     );
                 }
             }
+            PassMode::Cast(cast) => {
+                cast.attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, cx, llfn);
+            }
             _ => {}
         }
         for arg in &self.args {
@@ -497,8 +498,8 @@ fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) {
                     apply(a);
                     apply(b);
                 }
-                PassMode::Cast(_) => {
-                    apply(&ArgAttributes::new());
+                PassMode::Cast(cast) => {
+                    apply(&cast.attrs);
                 }
             }
         }
@@ -533,6 +534,13 @@ fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll V
                     );
                 }
             }
+            PassMode::Cast(cast) => {
+                cast.attrs.apply_attrs_to_callsite(
+                    llvm::AttributePlace::ReturnValue,
+                    &bx.cx,
+                    callsite,
+                );
+            }
             _ => {}
         }
         if let abi::Abi::Scalar(scalar) = self.ret.layout.abi {
@@ -577,8 +585,8 @@ fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll V
                     apply(bx.cx, a);
                     apply(bx.cx, b);
                 }
-                PassMode::Cast(_) => {
-                    apply(bx.cx, &ArgAttributes::new());
+                PassMode::Cast(cast) => {
+                    apply(bx.cx, &cast.attrs);
                 }
             }
         }
@@ -607,7 +615,7 @@ fn apply_attrs_callsite(&mut self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, callsite: Sel
         fn_abi.apply_attrs_callsite(self, callsite)
     }
 
-    fn get_param(&self, index: usize) -> Self::Value {
+    fn get_param(&mut self, index: usize) -> Self::Value {
         llvm::get_param(self.llfn(), index as c_uint)
     }
 }
index 3d05fc15b38f4121c22f737cccc040d78f734db2..460a8cc69128e9f72c2b64f9977b8e185a4712f0 100644 (file)
@@ -259,6 +259,7 @@ pub(crate) fn save_temp_bitcode(
 pub struct DiagnosticHandlers<'a> {
     data: *mut (&'a CodegenContext<LlvmCodegenBackend>, &'a Handler),
     llcx: &'a llvm::Context,
+    old_handler: Option<&'a llvm::DiagnosticHandler>,
 }
 
 impl<'a> DiagnosticHandlers<'a> {
@@ -267,12 +268,35 @@ pub fn new(
         handler: &'a Handler,
         llcx: &'a llvm::Context,
     ) -> Self {
+        let remark_passes_all: bool;
+        let remark_passes: Vec<CString>;
+        match &cgcx.remark {
+            Passes::All => {
+                remark_passes_all = true;
+                remark_passes = Vec::new();
+            }
+            Passes::Some(passes) => {
+                remark_passes_all = false;
+                remark_passes =
+                    passes.iter().map(|name| CString::new(name.as_str()).unwrap()).collect();
+            }
+        };
+        let remark_passes: Vec<*const c_char> =
+            remark_passes.iter().map(|name: &CString| name.as_ptr()).collect();
         let data = Box::into_raw(Box::new((cgcx, handler)));
         unsafe {
+            let old_handler = llvm::LLVMRustContextGetDiagnosticHandler(llcx);
+            llvm::LLVMRustContextConfigureDiagnosticHandler(
+                llcx,
+                diagnostic_handler,
+                data.cast(),
+                remark_passes_all,
+                remark_passes.as_ptr(),
+                remark_passes.len(),
+            );
             llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, data.cast());
-            llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, data.cast());
+            DiagnosticHandlers { data, llcx, old_handler }
         }
-        DiagnosticHandlers { data, llcx }
     }
 }
 
@@ -281,7 +305,7 @@ fn drop(&mut self) {
         use std::ptr::null_mut;
         unsafe {
             llvm::LLVMRustSetInlineAsmDiagnosticHandler(self.llcx, inline_asm_handler, null_mut());
-            llvm::LLVMContextSetDiagnosticHandler(self.llcx, diagnostic_handler, null_mut());
+            llvm::LLVMRustContextSetDiagnosticHandler(self.llcx, self.old_handler);
             drop(Box::from_raw(self.data));
         }
     }
@@ -337,13 +361,8 @@ fn report_inline_asm(
 
             if enabled {
                 diag_handler.note_without_error(&format!(
-                    "optimization {} for {} at {}:{}:{}: {}",
-                    opt.kind.describe(),
-                    opt.pass_name,
-                    opt.filename,
-                    opt.line,
-                    opt.column,
-                    opt.message
+                    "{}:{}:{}: {}: {}",
+                    opt.filename, opt.line, opt.column, opt.pass_name, opt.message,
                 ));
             }
         }
index 6830864ba04b4e9271a630df3f1f09af993dd66d..0390caaec33e55ef40f8710c521cd56134837e88 100644 (file)
@@ -9,6 +9,7 @@
 use rustc_hir::def_id::{DefId, DefIdSet};
 use rustc_llvm::RustString;
 use rustc_middle::mir::coverage::CodeRegion;
+use rustc_middle::ty::TyCtxt;
 use rustc_span::Symbol;
 
 use std::ffi::CString;
 
 /// Generates and exports the Coverage Map.
 ///
-/// This Coverage Map complies with Coverage Mapping Format version 4 (zero-based encoded as 3),
-/// as defined at [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format)
-/// and published in Rust's November 2020 fork of LLVM. This version is supported by the LLVM
-/// coverage tools (`llvm-profdata` and `llvm-cov`) bundled with Rust's fork of LLVM.
+/// Rust Coverage Map generation supports LLVM Coverage Mapping Format versions
+/// 5 (LLVM 12, only) and 6 (zero-based encoded as 4 and 5, respectively), as defined at
+/// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format).
+/// These versions are supported by the LLVM coverage tools (`llvm-profdata` and `llvm-cov`)
+/// bundled with Rust's fork of LLVM.
 ///
 /// Consequently, Rust's bundled version of Clang also generates Coverage Maps compliant with
 /// the same version. Clang's implementation of Coverage Map generation was referenced when
 pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
     let tcx = cx.tcx;
 
-    // Ensure LLVM supports Coverage Map Version 4 (encoded as a zero-based value: 3).
-    // If not, the LLVM Version must be less than 11.
+    // Ensure the installed version of LLVM supports at least Coverage Map
+    // Version 5 (encoded as a zero-based value: 4), which was introduced with
+    // LLVM 12.
     let version = coverageinfo::mapping_version();
-    if version != 3 {
-        tcx.sess.fatal("rustc option `-Z instrument-coverage` requires LLVM 11 or higher.");
+    if version < 4 {
+        tcx.sess.fatal("rustc option `-Z instrument-coverage` requires LLVM 12 or higher.");
     }
 
     debug!("Generating coverage map for CodegenUnit: `{}`", cx.codegen_unit.name());
@@ -57,7 +60,7 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
         return;
     }
 
-    let mut mapgen = CoverageMapGenerator::new();
+    let mut mapgen = CoverageMapGenerator::new(tcx, version);
 
     // Encode coverage mappings and generate function records
     let mut function_data = Vec::new();
@@ -112,8 +115,26 @@ struct CoverageMapGenerator {
 }
 
 impl CoverageMapGenerator {
-    fn new() -> Self {
-        Self { filenames: FxIndexSet::default() }
+    fn new(tcx: TyCtxt<'_>, version: u32) -> Self {
+        let mut filenames = FxIndexSet::default();
+        if version >= 5 {
+            // LLVM Coverage Mapping Format version 6 (zero-based encoded as 5)
+            // requires setting the first filename to the compilation directory.
+            // Since rustc generates coverage maps with relative paths, the
+            // compilation directory can be combined with the the relative paths
+            // to get absolute paths, if needed.
+            let working_dir = tcx
+                .sess
+                .opts
+                .working_dir
+                .remapped_path_if_available()
+                .to_string_lossy()
+                .to_string();
+            let c_filename =
+                CString::new(working_dir).expect("null error converting filename to C string");
+            filenames.insert(c_filename);
+        }
+        Self { filenames }
     }
 
     /// Using the `expressions` and `counter_regions` collected for the current function, generate
index cd29f2af0165aa36041d7129778d3f3b3b469f4b..10c7bb2eaea943ef8f3adeb5455b481af7cbe3da 100644 (file)
@@ -1525,14 +1525,12 @@ fn generator_layout_and_saved_local_names(
                 // Deref of the `Pin<&mut Self>` state argument.
                 mir::ProjectionElem::Field(..),
                 mir::ProjectionElem::Deref,
-
                 // Field of a variant of the state.
                 mir::ProjectionElem::Downcast(_, variant),
                 mir::ProjectionElem::Field(field, _),
             ] => {
-                let name = &mut generator_saved_local_names[
-                    generator_layout.variant_fields[variant][field]
-                ];
+                let name = &mut generator_saved_local_names
+                    [generator_layout.variant_fields[variant][field]];
                 if name.is_none() {
                     name.replace(var.name);
                 }
index 1d255c075598078f616ef704c1470bcb4d064a33..2ef4c871825cbdc6f28881a01aac9abe43677033 100644 (file)
@@ -675,13 +675,17 @@ struct InvariantOpaque<'a> {
 #[repr(C)]
 pub struct Linker<'a>(InvariantOpaque<'a>);
 
-pub type DiagnosticHandler = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void);
-pub type InlineAsmDiagHandler = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint);
+extern "C" {
+    pub type DiagnosticHandler;
+}
+
+pub type DiagnosticHandlerTy = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void);
+pub type InlineAsmDiagHandlerTy = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint);
 
 pub mod coverageinfo {
     use super::coverage_map;
 
-    /// Aligns with [llvm::coverage::CounterMappingRegion::RegionKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L206-L222)
+    /// Aligns with [llvm::coverage::CounterMappingRegion::RegionKind](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L209-L230)
     #[derive(Copy, Clone, Debug)]
     #[repr(C)]
     pub enum RegionKind {
@@ -700,11 +704,16 @@ pub enum RegionKind {
         /// A GapRegion is like a CodeRegion, but its count is only set as the
         /// line execution count when its the only region in the line.
         GapRegion = 3,
+
+        /// A BranchRegion represents leaf-level boolean expressions and is
+        /// associated with two counters, each representing the number of times the
+        /// expression evaluates to true or false.
+        BranchRegion = 4,
     }
 
     /// This struct provides LLVM's representation of a "CoverageMappingRegion", encoded into the
     /// coverage map, in accordance with the
-    /// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format).
+    /// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format).
     /// The struct composes fields representing the `Counter` type and value(s) (injected counter
     /// ID, or expression type and operands), the source file (an indirect index into a "filenames
     /// array", encoded separately), and source location (start and end positions of the represented
@@ -717,6 +726,10 @@ pub struct CounterMappingRegion {
         /// The counter type and type-dependent counter data, if any.
         counter: coverage_map::Counter,
 
+        /// If the `RegionKind` is a `BranchRegion`, this represents the counter
+        /// for the false branch of the region.
+        false_counter: coverage_map::Counter,
+
         /// An indirect reference to the source filename. In the LLVM Coverage Mapping Format, the
         /// file_id is an index into a function-specific `virtual_file_mapping` array of indexes
         /// that, in turn, are used to look up the filename for this region.
@@ -754,6 +767,7 @@ impl CounterMappingRegion {
         ) -> Self {
             Self {
                 counter,
+                false_counter: coverage_map::Counter::zero(),
                 file_id,
                 expanded_file_id: 0,
                 start_line,
@@ -764,6 +778,31 @@ impl CounterMappingRegion {
             }
         }
 
+        // This function might be used in the future; the LLVM API is still evolving, as is coverage
+        // support.
+        #[allow(dead_code)]
+        crate fn branch_region(
+            counter: coverage_map::Counter,
+            false_counter: coverage_map::Counter,
+            file_id: u32,
+            start_line: u32,
+            start_col: u32,
+            end_line: u32,
+            end_col: u32,
+        ) -> Self {
+            Self {
+                counter,
+                false_counter,
+                file_id,
+                expanded_file_id: 0,
+                start_line,
+                start_col,
+                end_line,
+                end_col,
+                kind: RegionKind::BranchRegion,
+            }
+        }
+
         // This function might be used in the future; the LLVM API is still evolving, as is coverage
         // support.
         #[allow(dead_code)]
@@ -777,6 +816,7 @@ impl CounterMappingRegion {
         ) -> Self {
             Self {
                 counter: coverage_map::Counter::zero(),
+                false_counter: coverage_map::Counter::zero(),
                 file_id,
                 expanded_file_id,
                 start_line,
@@ -799,6 +839,7 @@ impl CounterMappingRegion {
         ) -> Self {
             Self {
                 counter: coverage_map::Counter::zero(),
+                false_counter: coverage_map::Counter::zero(),
                 file_id,
                 expanded_file_id: 0,
                 start_line,
@@ -822,6 +863,7 @@ impl CounterMappingRegion {
         ) -> Self {
             Self {
                 counter,
+                false_counter: coverage_map::Counter::zero(),
                 file_id,
                 expanded_file_id: 0,
                 start_line,
@@ -2289,12 +2331,6 @@ pub fn LLVMRustArchiveIteratorNext(
     #[allow(improper_ctypes)]
     pub fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString);
 
-    pub fn LLVMContextSetDiagnosticHandler(
-        C: &Context,
-        Handler: DiagnosticHandler,
-        DiagnosticContext: *mut c_void,
-    );
-
     #[allow(improper_ctypes)]
     pub fn LLVMRustUnpackOptimizationDiagnostic(
         DI: &'a DiagnosticInfo,
@@ -2324,7 +2360,7 @@ pub fn LLVMRustGetSMDiagnostic(
 
     pub fn LLVMRustSetInlineAsmDiagnosticHandler(
         C: &Context,
-        H: InlineAsmDiagHandler,
+        H: InlineAsmDiagHandlerTy,
         CX: *mut c_void,
     );
 
@@ -2439,4 +2475,19 @@ pub fn LLVMRustComputeLTOCacheKey(
         mod_id: *const c_char,
         data: &ThinLTOData,
     );
+
+    pub fn LLVMRustContextGetDiagnosticHandler(Context: &Context) -> Option<&DiagnosticHandler>;
+    pub fn LLVMRustContextSetDiagnosticHandler(
+        context: &Context,
+        diagnostic_handler: Option<&DiagnosticHandler>,
+    );
+    pub fn LLVMRustContextConfigureDiagnosticHandler(
+        context: &Context,
+        diagnostic_handler_callback: DiagnosticHandlerTy,
+        diagnostic_handler_context: *mut c_void,
+        remark_all_passes: bool,
+        remark_passes: *const *const c_char,
+        remark_passes_len: usize,
+    );
+
 }
index 962c01c2ee7a6fd25cb9633523056319f21643ac..e288760a02b186612249db0225f4ec2a42a57ee4 100644 (file)
@@ -1,6 +1,6 @@
 use rustc_middle::mir::coverage::{CounterValueReference, MappedExpressionIndex};
 
-/// Aligns with [llvm::coverage::Counter::CounterKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L206-L222)
+/// Aligns with [llvm::coverage::Counter::CounterKind](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L95)
 #[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub enum CounterKind {
@@ -17,7 +17,7 @@ pub enum CounterKind {
 ///     `instrprof.increment()`)
 ///   * For `CounterKind::Expression`, `id` is the index into the coverage map's array of
 ///     counter expressions.
-/// Aligns with [llvm::coverage::Counter](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L99-L100)
+/// Aligns with [llvm::coverage::Counter](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L102-L103)
 /// Important: The Rust struct layout (order and types of fields) must match its C++ counterpart.
 #[derive(Copy, Clone, Debug)]
 #[repr(C)]
@@ -59,7 +59,7 @@ pub fn zero_based_id(&self) -> u32 {
     }
 }
 
-/// Aligns with [llvm::coverage::CounterExpression::ExprKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L147)
+/// Aligns with [llvm::coverage::CounterExpression::ExprKind](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L150)
 #[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub enum ExprKind {
@@ -67,7 +67,7 @@ pub enum ExprKind {
     Add = 1,
 }
 
-/// Aligns with [llvm::coverage::CounterExpression](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L148-L149)
+/// Aligns with [llvm::coverage::CounterExpression](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L151-L152)
 /// Important: The Rust struct layout (order and types of fields) must match its C++
 /// counterpart.
 #[derive(Copy, Clone, Debug)]
index dd8495850bd5458e88a78f8a53e0ea04f16b2a8d..a00d78daf4dcbd0c58a2429a4917c0a2e088aca1 100644 (file)
@@ -4,5 +4,5 @@
 
 pub trait AbiBuilderMethods<'tcx>: BackendTypes {
     fn apply_attrs_callsite(&mut self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, callsite: Self::Value);
-    fn get_param(&self, index: usize) -> Self::Value;
+    fn get_param(&mut self, index: usize) -> Self::Value;
 }
index 44da27a43db0a01e08d9c46db4ef4fc8be2c4e70..025d2998b00525e4ee1a1e99ea8143ee365393d7 100644 (file)
@@ -394,10 +394,12 @@ pub fn emulate_intrinsic(
             sym::transmute => {
                 self.copy_op_transmute(&args[0], dest)?;
             }
-            sym::assert_inhabited => {
+            sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => {
                 let ty = instance.substs.type_at(0);
                 let layout = self.layout_of(ty)?;
 
+                // For *all* intrinsics we first check `is_uninhabited` to give a more specific
+                // error message.
                 if layout.abi.is_uninhabited() {
                     // The run-time intrinsic panics just to get a good backtrace; here we abort
                     // since there is no problem showing a backtrace even for aborts.
@@ -409,6 +411,28 @@ pub fn emulate_intrinsic(
                         ),
                     )?;
                 }
+                if intrinsic_name == sym::assert_zero_valid
+                    && !layout.might_permit_raw_init(self, /*zero:*/ true)
+                {
+                    M::abort(
+                        self,
+                        format!(
+                            "aborted execution: attempted to zero-initialize type `{}`, which is invalid",
+                            ty
+                        ),
+                    )?;
+                }
+                if intrinsic_name == sym::assert_uninit_valid
+                    && !layout.might_permit_raw_init(self, /*zero:*/ false)
+                {
+                    M::abort(
+                        self,
+                        format!(
+                            "aborted execution: attempted to leave type `{}` uninitialized, which is invalid",
+                            ty
+                        ),
+                    )?;
+                }
             }
             sym::simd_insert => {
                 let index = u64::from(self.read_scalar(&args[1])?.to_u32()?);
index ac000b1bb566fe7ea9c037167da15e730073085e..a90582fc33820e00003138b94411082a7e3f862e 100644 (file)
@@ -130,7 +130,12 @@ fn binary_int_op(
             let signed = left_layout.abi.is_signed();
             let size = u128::from(left_layout.size.bits());
             let overflow = r >= size;
-            let r = r % size; // mask to type size
+            // The shift offset is implicitly masked to the type size, to make sure this operation
+            // is always defined. This is the one MIR operator that does *not* directly map to a
+            // single LLVM operation. See
+            // <https://github.com/rust-lang/rust/blob/a3b9405ae7bb6ab4e8103b414e75c44598a10fd2/compiler/rustc_codegen_ssa/src/common.rs#L131-L158>
+            // for the corresponding truncation in our codegen backends.
+            let r = r % size;
             let r = u32::try_from(r).unwrap(); // we masked so this will always fit
             let result = if signed {
                 let l = self.sign_extend(l, left_layout) as i128;
index e6037d561dedcb5228ed84e93e524df136f17551..9299ae2b2b9f8f6708f9a1a1646e23818a96f260 100644 (file)
@@ -242,11 +242,15 @@ pub fn eval_rvalue_into_place(
                     let elem_size = first.layout.size;
                     let first_ptr = first.ptr;
                     let rest_ptr = first_ptr.offset(elem_size, self)?;
+                    // For the alignment of `rest_ptr`, we crucially do *not* use `first.align` as
+                    // that place might be more aligned than its type mandates (a `u8` array could
+                    // be 4-aligned if it sits at the right spot in a struct). Instead we use
+                    // `first.layout.align`, i.e., the alignment given by the type.
                     self.memory.copy_repeatedly(
                         first_ptr,
                         first.align,
                         rest_ptr,
-                        first.align,
+                        first.layout.align.abi,
                         elem_size,
                         length - 1,
                         /*nonoverlapping:*/ true,
index 2854e6fd396c243ba358eaa169efff7692dccce8..274665ccd98364f7f4f90d060247840e6f4ca46e 100644 (file)
@@ -1,8 +1,8 @@
 //! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations.
 
 use rustc_errors::{Applicability, Diagnostic, ErrorReported};
+use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_hir::{self as hir, HirId, LangItem};
 use rustc_index::bit_set::BitSet;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
@@ -14,8 +14,7 @@
 use rustc_middle::ty::{Binder, TraitPredicate, TraitRef};
 use rustc_mir_dataflow::{self, Analysis};
 use rustc_span::{sym, Span, Symbol};
-use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
-use rustc_trait_selection::traits::{self, SelectionContext, TraitEngine};
+use rustc_trait_selection::traits::SelectionContext;
 
 use std::mem;
 use std::ops::Deref;
@@ -255,16 +254,6 @@ pub fn check_body(&mut self) {
             self.visit_body(&body);
         }
 
-        // Ensure that the end result is `Sync` in a non-thread local `static`.
-        let should_check_for_sync = self.const_kind()
-            == hir::ConstContext::Static(hir::Mutability::Not)
-            && !tcx.is_thread_local_static(def_id.to_def_id());
-
-        if should_check_for_sync {
-            let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-            check_return_ty_is_sync(tcx, &body, hir_id);
-        }
-
         // If we got through const-checking without emitting any "primary" errors, emit any
         // "secondary" errors if they occurred.
         let secondary_errors = mem::take(&mut self.secondary_errors);
@@ -1004,11 +993,12 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
                 }
 
                 let mut err_span = self.span;
+                let ty_of_dropped_place = dropped_place.ty(self.body, self.tcx).ty;
 
-                let ty_needs_non_const_drop = qualifs::NeedsNonConstDrop::in_any_value_of_ty(
-                    self.ccx,
-                    dropped_place.ty(self.body, self.tcx).ty,
-                );
+                let ty_needs_non_const_drop =
+                    qualifs::NeedsNonConstDrop::in_any_value_of_ty(self.ccx, ty_of_dropped_place);
+
+                debug!(?ty_of_dropped_place, ?ty_needs_non_const_drop);
 
                 if !ty_needs_non_const_drop {
                     return;
@@ -1053,20 +1043,6 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
     }
 }
 
-fn check_return_ty_is_sync(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, hir_id: HirId) {
-    let ty = body.return_ty();
-    tcx.infer_ctxt().enter(|infcx| {
-        let cause = traits::ObligationCause::new(body.span, hir_id, traits::SharedStatic);
-        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);
-        let errors = fulfillment_cx.select_all_or_error(&infcx);
-        if !errors.is_empty() {
-            infcx.report_fulfillment_errors(&errors, None, false);
-        }
-    });
-}
-
 fn place_as_reborrow(
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
index 7a2be3c3bad329c8675c500b61fa3288218cce9b..c1d47baa405311685cde2c10cd5da9c6dbd282ee 100644 (file)
@@ -80,7 +80,8 @@ fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Loc
         trace!("visit_terminator: terminator={:?} location={:?}", terminator, location);
 
         match &terminator.kind {
-            mir::TerminatorKind::Drop { place: dropped_place, .. } => {
+            mir::TerminatorKind::Drop { place: dropped_place, .. }
+            | mir::TerminatorKind::DropAndReplace { place: dropped_place, .. } => {
                 let dropped_ty = dropped_place.ty(self.body, self.tcx).ty;
                 if !NeedsNonConstDrop::in_any_value_of_ty(self.ccx, dropped_ty) {
                     // Instead of throwing a bug, we just return here. This is because we have to
@@ -104,11 +105,6 @@ fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Loc
                 }
             }
 
-            mir::TerminatorKind::DropAndReplace { .. } => span_bug!(
-                terminator.source_info.span,
-                "`DropAndReplace` should be removed by drop elaboration",
-            ),
-
             mir::TerminatorKind::Abort
             | mir::TerminatorKind::Call { .. }
             | mir::TerminatorKind::Assert { .. }
index 38c28f34934a4d01da25fecaec30fe22becf6bbe..a2928bdf51b83195e9f553e6ce249cdf33b42965 100644 (file)
@@ -1,5 +1,3 @@
 pub mod check_consts;
 pub mod promote_consts;
 pub mod validate;
-
-pub use rustc_middle::mir::MirPass;
index a92b20f5cb520ae147c0ddfd3be48fc532738870..464155db89f488f6d2c8492243966998c1ed8e6f 100644 (file)
@@ -27,7 +27,6 @@
 use std::{cmp, iter, mem};
 
 use crate::transform::check_consts::{qualifs, ConstCx};
-use crate::transform::MirPass;
 
 /// A `MirPass` for promotion.
 ///
index b09b2227f3e88b63e860cef4a90da2d6ea0759dc..b4bb6390db4860b69748b70b374314f98566c333 100644 (file)
@@ -1,14 +1,13 @@
 //! Validates the MIR to ensure that invariants are upheld.
 
-use super::MirPass;
 use rustc_index::bit_set::BitSet;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::traversal;
 use rustc_middle::mir::visit::{PlaceContext, Visitor};
 use rustc_middle::mir::{
-    AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceElem,
-    PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, StatementKind, Terminator,
+    AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPass, MirPhase, Operand,
+    PlaceElem, PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, StatementKind, Terminator,
     TerminatorKind, START_BLOCK,
 };
 use rustc_middle::ty::fold::BottomUpFolder;
index 5b83ae31247661e7ecf7969b124d909499f568ed..71ff762c714bfab9095f00c3fcf60c4d32e69054 100644 (file)
@@ -1,35 +1,32 @@
 use rustc_index::vec::{Idx, IndexVec};
 use std::mem;
-use std::ptr;
 
-pub trait IdFunctor {
+pub trait IdFunctor: Sized {
     type Inner;
 
-    fn map_id<F>(self, f: F) -> Self
+    fn try_map_id<F, E>(self, f: F) -> Result<Self, E>
     where
-        F: FnMut(Self::Inner) -> Self::Inner;
+        F: FnMut(Self::Inner) -> Result<Self::Inner, E>;
 }
 
 impl<T> IdFunctor for Box<T> {
     type Inner = T;
 
     #[inline]
-    fn map_id<F>(self, mut f: F) -> Self
+    fn try_map_id<F, E>(self, mut f: F) -> Result<Self, E>
     where
-        F: FnMut(Self::Inner) -> Self::Inner,
+        F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
     {
         let raw = Box::into_raw(self);
-        unsafe {
+        Ok(unsafe {
             // SAFETY: The raw pointer points to a valid value of type `T`.
-            let value = ptr::read(raw);
+            let value = raw.read();
             // SAFETY: Converts `Box<T>` to `Box<MaybeUninit<T>>` which is the
             // inverse of `Box::assume_init()` and should be safe.
-            let mut raw: Box<mem::MaybeUninit<T>> = Box::from_raw(raw.cast());
+            let raw: Box<mem::MaybeUninit<T>> = Box::from_raw(raw.cast());
             // SAFETY: Write the mapped value back into the `Box`.
-            raw.write(f(value));
-            // SAFETY: We just initialized `raw`.
-            raw.assume_init()
-        }
+            Box::write(raw, f(value)?)
+        })
     }
 }
 
@@ -37,9 +34,9 @@ impl<T> IdFunctor for Vec<T> {
     type Inner = T;
 
     #[inline]
-    fn map_id<F>(mut self, mut f: F) -> Self
+    fn try_map_id<F, E>(mut self, mut f: F) -> Result<Self, E>
     where
-        F: FnMut(Self::Inner) -> Self::Inner,
+        F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
     {
         // FIXME: We don't really care about panics here and leak
         // far more than we should, but that should be fine for now.
@@ -49,11 +46,26 @@ fn map_id<F>(mut self, mut f: F) -> Self
             let start = self.as_mut_ptr();
             for i in 0..len {
                 let p = start.add(i);
-                ptr::write(p, f(ptr::read(p)));
+                match f(p.read()) {
+                    Ok(val) => p.write(val),
+                    Err(err) => {
+                        // drop all other elements in self
+                        // (current element was "moved" into the call to f)
+                        for j in (0..i).chain(i + 1..len) {
+                            start.add(j).drop_in_place();
+                        }
+
+                        // returning will drop self, releasing the allocation
+                        // (len is 0 so elements will not be re-dropped)
+                        return Err(err);
+                    }
+                }
             }
+            // Even if we encountered an error, set the len back
+            // so we don't leak memory.
             self.set_len(len);
         }
-        self
+        Ok(self)
     }
 }
 
@@ -61,11 +73,11 @@ impl<T> IdFunctor for Box<[T]> {
     type Inner = T;
 
     #[inline]
-    fn map_id<F>(self, f: F) -> Self
+    fn try_map_id<F, E>(self, f: F) -> Result<Self, E>
     where
-        F: FnMut(Self::Inner) -> Self::Inner,
+        F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
     {
-        Vec::from(self).map_id(f).into()
+        Vec::from(self).try_map_id(f).map(Into::into)
     }
 }
 
@@ -73,10 +85,10 @@ impl<I: Idx, T> IdFunctor for IndexVec<I, T> {
     type Inner = T;
 
     #[inline]
-    fn map_id<F>(self, f: F) -> Self
+    fn try_map_id<F, E>(self, f: F) -> Result<Self, E>
     where
-        F: FnMut(Self::Inner) -> Self::Inner,
+        F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
     {
-        IndexVec::from_raw(self.raw.map_id(f))
+        self.raw.try_map_id(f).map(IndexVec::from_raw)
     }
 }
index 019d54b6202ed4ff5224e7b2826fdf1eb6f98322..ca2eaa54057fabb1f561ebd9631fb9c3f7cccbf1 100644 (file)
@@ -1,34 +1,64 @@
-Trait objects like `Box<Trait>` can only be constructed when certain
-requirements are satisfied by the trait in question.
-
-Trait objects are a form of dynamic dispatch and use a dynamically sized type
-for the inner type. So, for a given trait `Trait`, when `Trait` is treated as a
-type, as in `Box<Trait>`, the inner type is 'unsized'. In such cases the boxed
-pointer is a 'fat pointer' that contains an extra pointer to a table of methods
-(among other things) for dynamic dispatch. This design mandates some
-restrictions on the types of traits that are allowed to be used in trait
-objects, which are collectively termed as 'object safety' rules.
-
-Attempting to create a trait object for a non object-safe trait will trigger
-this error.
-
-There are various rules:
-
-### The trait cannot require `Self: Sized`
-
-When `Trait` is treated as a type, the type does not implement the special
-`Sized` trait, because the type does not have a known size at compile time and
-can only be accessed behind a pointer. Thus, if we have a trait like the
-following:
+For any given trait `Trait` there may be a related _type_ called the _trait
+object type_ which is typically written as `dyn Trait`. In earlier editions of
+Rust, trait object types were written as plain `Trait` (just the name of the
+trait, written in type positions) but this was a bit too confusing, so we now
+write `dyn Trait`.
+
+Some traits are not allowed to be used as trait object types. The traits that
+are allowed to be used as trait object types are called "object-safe" traits.
+Attempting to use a trait object type for a trait that is not object-safe will
+trigger error E0038.
+
+Two general aspects of trait object types give rise to the restrictions:
+
+  1. Trait object types are dynamically sized types (DSTs), and trait objects of
+     these types can only be accessed through pointers, such as `&dyn Trait` or
+     `Box<dyn Trait>`. The size of such a pointer is known, but the size of the
+     `dyn Trait` object pointed-to by the pointer is _opaque_ to code working
+     with it, and different tait objects with the same trait object type may
+     have different sizes.
+
+  2. The pointer used to access a trait object is paired with an extra pointer
+     to a "virtual method table" or "vtable", which is used to implement dynamic
+     dispatch to the object's implementations of the trait's methods. There is a
+     single such vtable for each trait implementation, but different trait
+     objects with the same trait object type may point to vtables from different
+     implementations.
+
+The specific conditions that violate object-safety follow, most of which relate
+to missing size information and vtable polymorphism arising from these aspects.
+
+### The trait requires `Self: Sized`
+
+Traits that are declared as `Trait: Sized` or which otherwise inherit a
+constraint of `Self:Sized` are not object-safe.
+
+The reasoning behind this is somewhat subtle. It derives from the fact that Rust
+requires (and defines) that every trait object type `dyn Trait` automatically
+implements `Trait`. Rust does this to simplify error reporting and ease
+interoperation between static and dynamic polymorphism. For example, this code
+works:
 
 ```
-trait Foo where Self: Sized {
+trait Trait {
+}
+
+fn static_foo<T:Trait + ?Sized>(b: &T) {
+}
 
+fn dynamic_bar(a: &dyn Trait) {
+    static_foo(a)
 }
 ```
 
-We cannot create an object of type `Box<Foo>` or `&Foo` since in this case
-`Self` would not be `Sized`.
+This code works because `dyn Trait`, if it exists, always implements `Trait`.
+
+However as we know, any `dyn Trait` is also unsized, and so it can never
+implement a sized trait like `Trait:Sized`. So, rather than allow an exception
+to the rule that `dyn Trait` always implements `Trait`, Rust chooses to prohibit
+such a `dyn Trait` from existing at all.
+
+Only unsized traits are considered object-safe.
 
 Generally, `Self: Sized` is used to indicate that the trait should not be used
 as a trait object. If the trait comes from your own crate, consider removing
@@ -67,7 +97,7 @@ trait Trait {
     fn foo(&self) -> Self;
 }
 
-fn call_foo(x: Box<Trait>) {
+fn call_foo(x: Box<dyn Trait>) {
     let y = x.foo(); // What type is y?
     // ...
 }
@@ -76,7 +106,8 @@ fn call_foo(x: Box<Trait>) {
 If only some methods aren't object-safe, you can add a `where Self: Sized` bound
 on them to mark them as explicitly unavailable to trait objects. The
 functionality will still be available to all other implementers, including
-`Box<Trait>` which is itself sized (assuming you `impl Trait for Box<Trait>`).
+`Box<dyn Trait>` which is itself sized (assuming you `impl Trait for Box<dyn
+Trait>`).
 
 ```
 trait Trait {
@@ -115,7 +146,9 @@ impl Trait for u8 {
 ```
 
 At compile time each implementation of `Trait` will produce a table containing
-the various methods (and other items) related to the implementation.
+the various methods (and other items) related to the implementation, which will
+be used as the virtual method table for a `dyn Trait` object derived from that
+implementation.
 
 This works fine, but when the method gains generic parameters, we can have a
 problem.
@@ -174,7 +207,7 @@ Now, if we have the following code:
 # impl Trait for u8 { fn foo<T>(&self, on: T) {} }
 # impl Trait for bool { fn foo<T>(&self, on: T) {} }
 # // etc.
-fn call_foo(thing: Box<Trait>) {
+fn call_foo(thing: Box<dyn Trait>) {
     thing.foo(true); // this could be any one of the 8 types above
     thing.foo(1);
     thing.foo("hello");
@@ -200,7 +233,7 @@ trait Trait {
 ```
 
 If this is not an option, consider replacing the type parameter with another
-trait object (e.g., if `T: OtherTrait`, use `on: Box<OtherTrait>`). If the
+trait object (e.g., if `T: OtherTrait`, use `on: Box<dyn OtherTrait>`). If the
 number of types you intend to feed to this method is limited, consider manually
 listing out the methods of different types.
 
@@ -226,7 +259,7 @@ trait Foo {
 }
 ```
 
-### The trait cannot contain associated constants
+### Trait contains associated constants
 
 Just like static functions, associated constants aren't stored on the method
 table. If the trait or any subtrait contain an associated constant, they cannot
@@ -248,7 +281,7 @@ trait Foo {
 }
 ```
 
-### The trait cannot use `Self` as a type parameter in the supertrait listing
+### Trait uses `Self` as a type parameter in the supertrait listing
 
 This is similar to the second sub-error, but subtler. It happens in situations
 like the following:
index 6b79962ddd6095bc600d8d0766b5ce557d8b8a14..3104bc185e7568966c72de3c40e8a3346fc3ac60 100644 (file)
@@ -214,7 +214,7 @@ fn supports_color(&self) -> bool {
 
     /// Formats the substitutions of the primary_span
     ///
-    /// The are a lot of conditions to this method, but in short:
+    /// There are a lot of conditions to this method, but in short:
     ///
     /// * If the current `Diagnostic` has only one visible `CodeSuggestion`,
     ///   we format the `help` suggestion depending on the content of the
@@ -730,13 +730,15 @@ fn render_source_line(
         }
 
         let source_string = match file.get_line(line.line_index - 1) {
-            Some(s) => replace_tabs(&*s),
+            Some(s) => normalize_whitespace(&*s),
             None => return Vec::new(),
         };
 
         let line_offset = buffer.num_lines();
 
-        let left = margin.left(source_string.len()); // Left trim
+        // Left trim
+        let left = margin.left(source_string.len());
+
         // Account for unicode characters of width !=0 that were removed.
         let left = source_string
             .chars()
@@ -1286,7 +1288,7 @@ fn emit_message_default(
             }
             for &(ref text, _) in msg.iter() {
                 // Account for newlines to align output to its label.
-                for (line, text) in replace_tabs(text).lines().enumerate() {
+                for (line, text) in normalize_whitespace(text).lines().enumerate() {
                     buffer.append(
                         0 + line,
                         &format!(
@@ -1550,7 +1552,7 @@ fn emit_message_default(
 
                             self.draw_line(
                                 &mut buffer,
-                                &replace_tabs(&unannotated_line),
+                                &normalize_whitespace(&unannotated_line),
                                 annotated_file.lines[line_idx + 1].line_index - 1,
                                 last_buffer_line_num,
                                 width_offset,
@@ -1623,18 +1625,27 @@ fn emit_suggestion_default(
             suggestions.iter().take(MAX_SUGGESTIONS)
         {
             notice_capitalization |= only_capitalization;
-            // Only show underline if the suggestion spans a single line and doesn't cover the
-            // entirety of the code output. If you have multiple replacements in the same line
-            // of code, show the underline.
-            let show_underline = !(parts.len() == 1 && parts[0].snippet.trim() == complete.trim())
-                && complete.lines().count() == 1;
 
             let has_deletion = parts.iter().any(|p| p.is_deletion());
             let is_multiline = complete.lines().count() > 1;
 
-            let show_diff = has_deletion && !is_multiline;
+            enum DisplaySuggestion {
+                Underline,
+                Diff,
+                None,
+            }
+
+            let show_code_change = if has_deletion && !is_multiline {
+                DisplaySuggestion::Diff
+            } else if (parts.len() != 1 || parts[0].snippet.trim() != complete.trim())
+                && !is_multiline
+            {
+                DisplaySuggestion::Underline
+            } else {
+                DisplaySuggestion::None
+            };
 
-            if show_diff {
+            if let DisplaySuggestion::Diff = show_code_change {
                 row_num += 1;
             }
 
@@ -1657,7 +1668,7 @@ fn emit_suggestion_default(
                     &self.maybe_anonymized(line_start + line_pos),
                     Style::LineNumber,
                 );
-                if show_diff {
+                if let DisplaySuggestion::Diff = show_code_change {
                     // Add the line number for both addition and removal to drive the point home.
                     //
                     // N - fn foo<A: T>(bar: A) {
@@ -1672,7 +1683,7 @@ fn emit_suggestion_default(
                     buffer.puts(
                         row_num - 1,
                         max_line_num_len + 3,
-                        &replace_tabs(
+                        &normalize_whitespace(
                             &*file_lines
                                 .file
                                 .get_line(file_lines.lines[line_pos].line_index)
@@ -1698,7 +1709,7 @@ fn emit_suggestion_default(
                 }
 
                 // print the suggestion
-                buffer.append(row_num, &replace_tabs(line), Style::NoStyle);
+                buffer.append(row_num, &normalize_whitespace(line), Style::NoStyle);
 
                 // Colorize addition/replacements with green.
                 for &SubstitutionHighlight { start, end } in highlight_parts {
@@ -1727,7 +1738,7 @@ fn emit_suggestion_default(
             let mut offsets: Vec<(usize, isize)> = Vec::new();
             // Only show an underline in the suggestions if the suggestion is not the
             // entirety of the code being shown and the displayed code is not multiline.
-            if show_underline {
+            if let DisplaySuggestion::Diff | DisplaySuggestion::Underline = show_code_change {
                 draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
                 for part in parts {
                     let span_start_pos = sm.lookup_char_pos(part.span.lo()).col_display;
@@ -1755,7 +1766,7 @@ fn emit_suggestion_default(
                     assert!(underline_start >= 0 && underline_end >= 0);
                     let padding: usize = max_line_num_len + 3;
                     for p in underline_start..underline_end {
-                        if !show_diff {
+                        if let DisplaySuggestion::Underline = show_code_change {
                             // If this is a replacement, underline with `^`, if this is an addition
                             // underline with `+`.
                             buffer.putc(
@@ -1766,7 +1777,7 @@ fn emit_suggestion_default(
                             );
                         }
                     }
-                    if show_diff {
+                    if let DisplaySuggestion::Diff = show_code_change {
                         // Colorize removal with red in diff format.
                         buffer.set_style_range(
                             row_num - 2,
@@ -1797,7 +1808,7 @@ fn emit_suggestion_default(
             // if we elided some lines, add an ellipsis
             if lines.next().is_some() {
                 buffer.puts(row_num, max_line_num_len - 1, "...", Style::LineNumber);
-            } else if !show_underline {
+            } else if let DisplaySuggestion::None = show_code_change {
                 draw_col_separator_no_space(&mut buffer, row_num, max_line_num_len + 1);
                 row_num += 1;
             }
@@ -2081,8 +2092,9 @@ fn num_decimal_digits(num: usize) -> usize {
 // 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{200D}', ""), // Replace ZWJ with nothing for consistent terminal output of grapheme clusters.
     ('\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{202B}', ""), // supported across 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}', ""),
@@ -2092,7 +2104,7 @@ fn num_decimal_digits(num: usize) -> usize {
     ('\u{2069}', ""),
 ];
 
-fn replace_tabs(str: &str) -> String {
+fn normalize_whitespace(str: &str) -> String {
     let mut s = str.to_string();
     for (c, replacement) in OUTPUT_REPLACEMENTS {
         s = s.replace(*c, replacement);
index bb3d3a415e7d5c939a80234d32919a7f2bc346ba..ee508ac80ba047c25cf5660822a4782646d8b3e5 100644 (file)
@@ -6,7 +6,6 @@
 #![feature(crate_visibility_modifier)]
 #![feature(backtrace)]
 #![feature(if_let_guard)]
-#![cfg_attr(bootstrap, feature(format_args_capture))]
 #![feature(iter_zip)]
 #![feature(let_else)]
 #![feature(nll)]
@@ -1013,7 +1012,9 @@ fn emit_unused_externs(&mut self, lint_level: &str, unused_externs: &[&str]) {
     }
 
     fn treat_err_as_bug(&self) -> bool {
-        self.flags.treat_err_as_bug.map_or(false, |c| self.err_count() >= c.get())
+        self.flags
+            .treat_err_as_bug
+            .map_or(false, |c| self.err_count() + self.lint_err_count >= c.get())
     }
 
     fn print_error_count(&mut self, registry: &Registry) {
@@ -1205,7 +1206,10 @@ fn bump_warn_count(&mut self) {
 
     fn panic_if_treat_err_as_bug(&self) {
         if self.treat_err_as_bug() {
-            match (self.err_count(), self.flags.treat_err_as_bug.map(|c| c.get()).unwrap_or(0)) {
+            match (
+                self.err_count() + self.lint_err_count,
+                self.flags.treat_err_as_bug.map(|c| c.get()).unwrap_or(0),
+            ) {
                 (1, 1) => panic!("aborting due to `-Z treat-err-as-bug=1`"),
                 (0, _) | (1, _) => {}
                 (count, as_bug) => panic!(
index b630bc1f4732f57f1185233d405e73d9b71518ff..07b5e20b2ddc59360fd620d7ec30c2e66063c6bc 100644 (file)
@@ -48,6 +48,7 @@ pub enum Annotatable {
     Param(ast::Param),
     FieldDef(ast::FieldDef),
     Variant(ast::Variant),
+    Crate(ast::Crate),
 }
 
 impl Annotatable {
@@ -66,6 +67,7 @@ pub fn span(&self) -> Span {
             Annotatable::Param(ref p) => p.span,
             Annotatable::FieldDef(ref sf) => sf.span,
             Annotatable::Variant(ref v) => v.span,
+            Annotatable::Crate(ref c) => c.span,
         }
     }
 
@@ -84,6 +86,7 @@ pub fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
             Annotatable::Param(p) => p.visit_attrs(f),
             Annotatable::FieldDef(sf) => sf.visit_attrs(f),
             Annotatable::Variant(v) => v.visit_attrs(f),
+            Annotatable::Crate(c) => c.visit_attrs(f),
         }
     }
 
@@ -102,6 +105,7 @@ pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) {
             Annotatable::Param(p) => visitor.visit_param(p),
             Annotatable::FieldDef(sf) => visitor.visit_field_def(sf),
             Annotatable::Variant(v) => visitor.visit_variant(v),
+            Annotatable::Crate(c) => visitor.visit_crate(c),
         }
     }
 
@@ -122,7 +126,8 @@ pub fn into_nonterminal(self) -> Nonterminal {
             | Annotatable::GenericParam(..)
             | Annotatable::Param(..)
             | Annotatable::FieldDef(..)
-            | Annotatable::Variant(..) => panic!("unexpected annotatable"),
+            | Annotatable::Variant(..)
+            | Annotatable::Crate(..) => panic!("unexpected annotatable"),
         }
     }
 
@@ -220,6 +225,13 @@ pub fn expect_variant(self) -> ast::Variant {
             _ => panic!("expected variant"),
         }
     }
+
+    pub fn expect_crate(self) -> ast::Crate {
+        match self {
+            Annotatable::Crate(krate) => krate,
+            _ => panic!("expected krate"),
+        }
+    }
 }
 
 /// Result of an expansion that may need to be retried.
@@ -419,6 +431,11 @@ fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
     fn make_variants(self: Box<Self>) -> Option<SmallVec<[ast::Variant; 1]>> {
         None
     }
+
+    fn make_crate(self: Box<Self>) -> Option<ast::Crate> {
+        // Fn-like macros cannot produce a crate.
+        unreachable!()
+    }
 }
 
 macro_rules! make_MacEager {
index 89dbd64ed8168171e82b3577e8c440b865e4a17d..ba675daac41db488d9b1631bceffdf9527619605 100644 (file)
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
 use rustc_ast::{AstLike, Block, Inline, ItemKind, MacArgs, MacCall};
 use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem};
-use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe};
+use rustc_ast::{NodeId, PatKind, Path, StmtKind};
 use rustc_ast_pretty::pprust;
 use rustc_attr::is_builtin_attr;
 use rustc_data_structures::map_in_place::MapInPlace;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_data_structures::sync::Lrc;
-use rustc_errors::{Applicability, FatalError, PResult};
+use rustc_errors::{Applicability, PResult};
 use rustc_feature::Features;
 use rustc_parse::parser::{
     AttemptLocalParseRecovery, ForceCollect, Parser, RecoverColon, RecoverComma,
@@ -33,7 +33,7 @@
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::{FileName, LocalExpnId, Span};
 
-use smallvec::{smallvec, SmallVec};
+use smallvec::SmallVec;
 use std::ops::DerefMut;
 use std::path::PathBuf;
 use std::rc::Rc;
@@ -205,6 +205,7 @@ impl<'a> MacResult for crate::mbe::macro_rules::ParserAnyMacro<'a> {
     Variants(SmallVec<[ast::Variant; 1]>) {
         "variant"; many fn flat_map_variant; fn visit_variant(); fn make_variants;
     }
+    Crate(ast::Crate) { "crate"; one fn visit_crate; fn visit_crate; fn make_crate; }
 }
 
 pub enum SupportsMacroExpansion {
@@ -227,9 +228,8 @@ pub fn supports_macro_expansion(self) -> SupportsMacroExpansion {
             AstFragmentKind::Items
             | AstFragmentKind::TraitItems
             | AstFragmentKind::ImplItems
-            | AstFragmentKind::ForeignItems => {
-                SupportsMacroExpansion::Yes { supports_inner_attrs: true }
-            }
+            | AstFragmentKind::ForeignItems
+            | AstFragmentKind::Crate => SupportsMacroExpansion::Yes { supports_inner_attrs: true },
             AstFragmentKind::Arms
             | AstFragmentKind::Fields
             | AstFragmentKind::FieldPats
@@ -288,6 +288,9 @@ fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(
             AstFragmentKind::OptExpr => {
                 AstFragment::OptExpr(items.next().map(Annotatable::expect_expr))
             }
+            AstFragmentKind::Crate => {
+                AstFragment::Crate(items.next().expect("expected exactly one crate").expect_crate())
+            }
             AstFragmentKind::Pat | AstFragmentKind::Ty => {
                 panic!("patterns and types aren't annotatable")
             }
@@ -359,9 +362,7 @@ pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
         MacroExpander { cx, monotonic }
     }
 
-    // FIXME: Avoid visiting the crate as a `Mod` item,
-    // make crate a first class expansion target instead.
-    pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
+    pub fn expand_crate(&mut self, krate: ast::Crate) -> ast::Crate {
         let file_path = match self.cx.source_map().span_to_filename(krate.span) {
             FileName::Real(name) => name
                 .into_local_path()
@@ -375,52 +376,7 @@ pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
             file_path_stack: vec![file_path],
             dir_path,
         });
-
-        let krate_item = AstFragment::Items(smallvec![P(ast::Item {
-            attrs: krate.attrs,
-            span: krate.span,
-            kind: ast::ItemKind::Mod(
-                Unsafe::No,
-                ModKind::Loaded(krate.items, Inline::Yes, krate.span)
-            ),
-            ident: Ident::empty(),
-            id: ast::DUMMY_NODE_ID,
-            vis: ast::Visibility {
-                span: krate.span.shrink_to_lo(),
-                kind: ast::VisibilityKind::Public,
-                tokens: None,
-            },
-            tokens: None,
-        })]);
-
-        match self.fully_expand_fragment(krate_item).make_items().pop().map(P::into_inner) {
-            Some(ast::Item {
-                attrs,
-                kind: ast::ItemKind::Mod(_, ModKind::Loaded(items, ..)),
-                ..
-            }) => {
-                krate.attrs = attrs;
-                krate.items = items;
-            }
-            None => {
-                // Resolution failed so we return an empty expansion
-                krate.attrs = vec![];
-                krate.items = vec![];
-            }
-            Some(ast::Item { span, kind, .. }) => {
-                krate.attrs = vec![];
-                krate.items = vec![];
-                self.cx.span_err(
-                    span,
-                    &format!(
-                        "expected crate top-level item to be a module after macro expansion, found {} {}",
-                        kind.article(), kind.descr()
-                    ),
-                );
-                // FIXME: this workaround issue #84569
-                FatalError.raise();
-            }
-        };
+        let krate = self.fully_expand_fragment(AstFragment::Crate(krate)).make_crate();
         self.cx.trace_macros_diag();
         krate
     }
@@ -708,26 +664,32 @@ fn expand_invoc(
                 SyntaxExtensionKind::Attr(expander) => {
                     self.gate_proc_macro_input(&item);
                     self.gate_proc_macro_attr_item(span, &item);
-                    let mut fake_tokens = false;
-                    if let Annotatable::Item(item_inner) = &item {
-                        if let ItemKind::Mod(_, mod_kind) = &item_inner.kind {
-                            // FIXME: Collect tokens and use them instead of generating
-                            // fake ones. These are unstable, so it needs to be
-                            // fixed prior to stabilization
-                            // Fake tokens when we are invoking an inner attribute, and:
-                            fake_tokens = matches!(attr.style, ast::AttrStyle::Inner) &&
-                                // We are invoking an attribute on the crate root, or an outline
-                                // module
-                                (item_inner.ident.name.is_empty() || !matches!(mod_kind, ast::ModKind::Loaded(_, Inline::Yes, _)));
-                        }
-                    }
-                    let tokens = if fake_tokens {
-                        rustc_parse::fake_token_stream(
+                    let tokens = match &item {
+                        // FIXME: Collect tokens and use them instead of generating
+                        // fake ones. These are unstable, so it needs to be
+                        // fixed prior to stabilization
+                        // Fake tokens when we are invoking an inner attribute, and
+                        // we are invoking it on an out-of-line module or crate.
+                        Annotatable::Crate(krate) => rustc_parse::fake_token_stream_for_crate(
                             &self.cx.sess.parse_sess,
-                            &item.into_nonterminal(),
-                        )
-                    } else {
-                        item.into_tokens(&self.cx.sess.parse_sess)
+                            krate,
+                        ),
+                        Annotatable::Item(item_inner)
+                            if matches!(attr.style, ast::AttrStyle::Inner)
+                                && matches!(
+                                    item_inner.kind,
+                                    ItemKind::Mod(
+                                        _,
+                                        ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _),
+                                    )
+                                ) =>
+                        {
+                            rustc_parse::fake_token_stream(
+                                &self.cx.sess.parse_sess,
+                                &item.into_nonterminal(),
+                            )
+                        }
+                        _ => item.into_tokens(&self.cx.sess.parse_sess),
                     };
                     let attr_item = attr.unwrap_normal_item();
                     if let MacArgs::Eq(..) = attr_item.args {
@@ -804,7 +766,8 @@ fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
             Annotatable::Item(_)
             | Annotatable::TraitItem(_)
             | Annotatable::ImplItem(_)
-            | Annotatable::ForeignItem(_) => return,
+            | Annotatable::ForeignItem(_)
+            | Annotatable::Crate(..) => return,
             Annotatable::Stmt(stmt) => {
                 // Attributes are stable on item statements,
                 // but unstable on all other kinds of statements
@@ -949,6 +912,7 @@ pub fn parse_ast_fragment<'a>(
             RecoverComma::No,
             RecoverColon::Yes,
         )?),
+        AstFragmentKind::Crate => AstFragment::Crate(this.parse_crate_mod()?),
         AstFragmentKind::Arms
         | AstFragmentKind::Fields
         | AstFragmentKind::FieldPats
@@ -1195,6 +1159,30 @@ macro_rules! assign_id {
 }
 
 impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
+    fn visit_crate(&mut self, krate: &mut ast::Crate) {
+        let span = krate.span;
+        let empty_crate =
+            || ast::Crate { attrs: Vec::new(), items: Vec::new(), span, is_placeholder: None };
+        let mut fold_crate = |krate: ast::Crate| {
+            let mut krate = match self.configure(krate) {
+                Some(krate) => krate,
+                None => return empty_crate(),
+            };
+
+            if let Some(attr) = self.take_first_attr(&mut krate) {
+                return self
+                    .collect_attr(attr, Annotatable::Crate(krate), AstFragmentKind::Crate)
+                    .make_crate();
+            }
+
+            noop_visit_crate(&mut krate, self);
+            krate
+        };
+
+        // Cannot use `visit_clobber` here, see the FIXME on it.
+        *krate = fold_crate(mem::replace(krate, empty_crate()));
+    }
+
     fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
         self.cfg.configure_expr(expr);
         visit_clobber(expr.deref_mut(), |mut expr| {
index 4e84a9df6c978ff2793787434b844da19bd0b34a..c721c4b8d7c191d40ab7ae069fbe7a67bf6b6d88 100644 (file)
@@ -1,7 +1,6 @@
 #![feature(crate_visibility_modifier)]
 #![feature(decl_macro)]
 #![feature(destructuring_assignment)]
-#![cfg_attr(bootstrap, feature(format_args_capture))]
 #![feature(if_let_guard)]
 #![feature(iter_zip)]
 #![feature(let_else)]
index a7434d73abe68ea7ec514b8650eee802313ce095..dd82add08dd98db17e9e6e3bb7f5804aee06d5da 100644 (file)
@@ -584,9 +584,7 @@ fn inner_parse_loop<'root, 'tt>(
                 //
                 // At the beginning of the loop, if we reach the end of the delimited submatcher,
                 // we pop the stack to backtrack out of the descent.
-                seq
-                @
-                (TokenTree::Delimited(..)
+                seq @ (TokenTree::Delimited(..)
                 | TokenTree::Token(Token { kind: DocComment(..), .. })) => {
                     let lower_elts = mem::replace(&mut item.top_elts, Tt(seq));
                     let idx = item.idx;
index 6402a81e7c1a5dba758fff4da279b140b9015ab8..4a8236b2cf38d457a2028a120b36db654bca3895 100644 (file)
@@ -65,24 +65,33 @@ fn string_to_tts_macro() {
         let tts: &[TokenTree] = &tts[..];
 
         match tts {
-            [TokenTree::Token(Token { kind: token::Ident(name_macro_rules, false), .. }), TokenTree::Token(Token { kind: token::Not, .. }), TokenTree::Token(Token { kind: token::Ident(name_zip, false), .. }), TokenTree::Delimited(_, macro_delim, macro_tts)]
-                if name_macro_rules == &kw::MacroRules && name_zip.as_str() == "zip" =>
-            {
+            [
+                TokenTree::Token(Token { kind: token::Ident(name_macro_rules, false), .. }),
+                TokenTree::Token(Token { kind: token::Not, .. }),
+                TokenTree::Token(Token { kind: token::Ident(name_zip, false), .. }),
+                TokenTree::Delimited(_, macro_delim, macro_tts),
+            ] if name_macro_rules == &kw::MacroRules && name_zip.as_str() == "zip" => {
                 let tts = &macro_tts.trees().collect::<Vec<_>>();
                 match &tts[..] {
-                    [TokenTree::Delimited(_, first_delim, first_tts), TokenTree::Token(Token { kind: token::FatArrow, .. }), TokenTree::Delimited(_, second_delim, second_tts)]
-                        if macro_delim == &token::Paren =>
-                    {
+                    [
+                        TokenTree::Delimited(_, first_delim, first_tts),
+                        TokenTree::Token(Token { kind: token::FatArrow, .. }),
+                        TokenTree::Delimited(_, second_delim, second_tts),
+                    ] if macro_delim == &token::Paren => {
                         let tts = &first_tts.trees().collect::<Vec<_>>();
                         match &tts[..] {
-                            [TokenTree::Token(Token { kind: token::Dollar, .. }), TokenTree::Token(Token { kind: token::Ident(name, false), .. })]
-                                if first_delim == &token::Paren && name.as_str() == "a" => {}
+                            [
+                                TokenTree::Token(Token { kind: token::Dollar, .. }),
+                                TokenTree::Token(Token { kind: token::Ident(name, false), .. }),
+                            ] if first_delim == &token::Paren && name.as_str() == "a" => {}
                             _ => panic!("value 3: {:?} {:?}", first_delim, first_tts),
                         }
                         let tts = &second_tts.trees().collect::<Vec<_>>();
                         match &tts[..] {
-                            [TokenTree::Token(Token { kind: token::Dollar, .. }), TokenTree::Token(Token { kind: token::Ident(name, false), .. })]
-                                if second_delim == &token::Paren && name.as_str() == "a" => {}
+                            [
+                                TokenTree::Token(Token { kind: token::Dollar, .. }),
+                                TokenTree::Token(Token { kind: token::Ident(name, false), .. }),
+                            ] if second_delim == &token::Paren && name.as_str() == "a" => {}
                             _ => panic!("value 4: {:?} {:?}", second_delim, second_tts),
                         }
                     }
index 12b6bc7bbe7689efffaca0447e1e11af197a7e1f..25b3a5820e60aaaed52d6b42e870f672a23154a3 100644 (file)
@@ -46,6 +46,12 @@ fn mac_placeholder() -> ast::MacCall {
         || P(ast::Pat { id, kind: ast::PatKind::MacCall(mac_placeholder()), span, tokens: None });
 
     match kind {
+        AstFragmentKind::Crate => AstFragment::Crate(ast::Crate {
+            attrs: Default::default(),
+            items: Default::default(),
+            span,
+            is_placeholder: Some(id),
+        }),
         AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
         AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())),
         AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item {
@@ -354,4 +360,12 @@ fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
             _ => noop_visit_ty(ty, self),
         }
     }
+
+    fn visit_crate(&mut self, krate: &mut ast::Crate) {
+        if let Some(id) = krate.is_placeholder {
+            *krate = self.remove(id).make_crate();
+        } else {
+            noop_visit_crate(krate, self)
+        }
+    }
 }
index c67d3df3dedd85b9d4457e50ecdcf9b669809ebd..2466e69f83646b0ab092d3fc3b7066030989315e 100644 (file)
@@ -92,7 +92,9 @@ pub enum LifetimeName {
     Param(ParamName),
 
     /// User wrote nothing (e.g., the lifetime in `&u32`).
-    Implicit,
+    ///
+    /// The bool indicates whether the user should have written something.
+    Implicit(bool),
 
     /// Implicit lifetime in a context like `dyn Foo`. This is
     /// distinguished from implicit lifetimes elsewhere because the
@@ -122,7 +124,7 @@ impl LifetimeName {
     pub fn ident(&self) -> Ident {
         match *self {
             LifetimeName::ImplicitObjectLifetimeDefault
-            | LifetimeName::Implicit
+            | LifetimeName::Implicit(_)
             | LifetimeName::Error => Ident::empty(),
             LifetimeName::Underscore => Ident::with_dummy_span(kw::UnderscoreLifetime),
             LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime),
@@ -133,7 +135,7 @@ pub fn ident(&self) -> Ident {
     pub fn is_elided(&self) -> bool {
         match self {
             LifetimeName::ImplicitObjectLifetimeDefault
-            | LifetimeName::Implicit
+            | LifetimeName::Implicit(_)
             | LifetimeName::Underscore => true,
 
             // It might seem surprising that `Fresh(_)` counts as
@@ -3298,7 +3300,7 @@ mod size_asserts {
     rustc_data_structures::static_assert_size!(super::Expr<'static>, 64);
     rustc_data_structures::static_assert_size!(super::Pat<'static>, 88);
     rustc_data_structures::static_assert_size!(super::QPath<'static>, 24);
-    rustc_data_structures::static_assert_size!(super::Ty<'static>, 72);
+    rustc_data_structures::static_assert_size!(super::Ty<'static>, 80);
 
     rustc_data_structures::static_assert_size!(super::Item<'static>, 184);
     rustc_data_structures::static_assert_size!(super::TraitItem<'static>, 128);
index cff543760f42af954123f20e1bd85c4876e92e02..21f89104c4b5878f09c02b47a19507798e3a531c 100644 (file)
@@ -545,7 +545,7 @@ pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime
         | LifetimeName::Param(ParamName::Error)
         | LifetimeName::Static
         | LifetimeName::Error
-        | LifetimeName::Implicit
+        | LifetimeName::Implicit(_)
         | LifetimeName::ImplicitObjectLifetimeDefault
         | LifetimeName::Underscore => {}
     }
index 3037996d48bc03bb8e1a0ca1cc4847b53c7d082f..a03c561861e2b58a6df22560399dce137d59487d 100644 (file)
@@ -268,6 +268,7 @@ pub fn extract<'a, F>(check_name: F, attrs: &'a [ast::Attribute]) -> Option<(Sym
     Future,                  sym::future_trait,        future_trait,               Target::Trait,          GenericRequirement::Exact(0);
     GeneratorState,          sym::generator_state,     gen_state,                  Target::Enum,           GenericRequirement::None;
     Generator,               sym::generator,           gen_trait,                  Target::Trait,          GenericRequirement::Minimum(1);
+    GeneratorReturn,         sym::generator_return,    generator_return,           Target::AssocTy,        GenericRequirement::None;
     Unpin,                   sym::unpin,               unpin_trait,                Target::Trait,          GenericRequirement::None;
     Pin,                     sym::pin,                 pin_type,                   Target::Struct,         GenericRequirement::None;
 
@@ -347,6 +348,7 @@ pub fn extract<'a, F>(check_name: F, attrs: &'a [ast::Attribute]) -> Option<(Sym
     ControlFlowContinue,     sym::Continue,            cf_continue_variant,        Target::Variant,        GenericRequirement::None;
     ControlFlowBreak,        sym::Break,               cf_break_variant,           Target::Variant,        GenericRequirement::None;
 
+    IntoFutureIntoFuture,    sym::into_future,         into_future_fn,             Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
     IntoIterIntoIter,        sym::into_iter,           into_iter_fn,               Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
     IteratorNext,            sym::next,                next_fn,                    Target::Method(MethodKind::Trait { body: false}), GenericRequirement::None;
 
index e2e07f2072e498ea907e7fb176ed0ff9e9d811f2..89c14bcc2ce2bd76beac8d879eddfac2f3e73afa 100644 (file)
@@ -465,25 +465,24 @@ fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -
                             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),
-                            };
+                        let (in_definition_scope, origin) = match tcx.hir().expect_item(def_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 };
index 4b08c2eb9c19eee7d3bf9cc9327553a17d82518c..f036e1214aaf7d97cee8453922d964a3cd78b7db 100644 (file)
@@ -1,7 +1,7 @@
 use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use super::{FixupError, FixupResult, InferCtxt, Span};
 use rustc_middle::mir;
-use rustc_middle::ty::fold::{TypeFolder, TypeVisitor};
+use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFolder, TypeVisitor};
 use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable};
 
 use std::ops::ControlFlow;
@@ -175,81 +175,72 @@ pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>, value: T) -> Fixu
 where
     T: TypeFoldable<'tcx>,
 {
-    let mut full_resolver = FullTypeResolver { infcx, err: None };
-    let result = value.fold_with(&mut full_resolver);
-    match full_resolver.err {
-        None => Ok(result),
-        Some(e) => Err(e),
-    }
+    value.try_fold_with(&mut FullTypeResolver { infcx })
 }
 
 // N.B. This type is not public because the protocol around checking the
 // `err` field is not enforceable otherwise.
 struct FullTypeResolver<'a, 'tcx> {
     infcx: &'a InferCtxt<'a, 'tcx>,
-    err: Option<FixupError<'tcx>>,
 }
 
 impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
+    type Error = FixupError<'tcx>;
+
     fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
+}
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+impl<'a, 'tcx> FallibleTypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
+    fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         if !t.needs_infer() {
-            t // micro-optimize -- if there is nothing in this type that this fold affects...
+            Ok(t) // micro-optimize -- if there is nothing in this type that this fold affects...
         } else {
             let t = self.infcx.shallow_resolve(t);
             match *t.kind() {
-                ty::Infer(ty::TyVar(vid)) => {
-                    self.err = Some(FixupError::UnresolvedTy(vid));
-                    self.tcx().ty_error()
-                }
-                ty::Infer(ty::IntVar(vid)) => {
-                    self.err = Some(FixupError::UnresolvedIntTy(vid));
-                    self.tcx().ty_error()
-                }
-                ty::Infer(ty::FloatVar(vid)) => {
-                    self.err = Some(FixupError::UnresolvedFloatTy(vid));
-                    self.tcx().ty_error()
-                }
+                ty::Infer(ty::TyVar(vid)) => Err(FixupError::UnresolvedTy(vid)),
+                ty::Infer(ty::IntVar(vid)) => Err(FixupError::UnresolvedIntTy(vid)),
+                ty::Infer(ty::FloatVar(vid)) => Err(FixupError::UnresolvedFloatTy(vid)),
                 ty::Infer(_) => {
                     bug!("Unexpected type in full type resolver: {:?}", t);
                 }
-                _ => t.super_fold_with(self),
+                _ => t.try_super_fold_with(self),
             }
         }
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+    fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
         match *r {
-            ty::ReVar(rid) => self
+            ty::ReVar(rid) => Ok(self
                 .infcx
                 .lexical_region_resolutions
                 .borrow()
                 .as_ref()
                 .expect("region resolution not performed")
-                .resolve_var(rid),
-            _ => r,
+                .resolve_var(rid)),
+            _ => Ok(r),
         }
     }
 
-    fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+    fn try_fold_const(
+        &mut self,
+        c: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
         if !c.needs_infer() {
-            c // micro-optimize -- if there is nothing in this const that this fold affects...
+            Ok(c) // micro-optimize -- if there is nothing in this const that this fold affects...
         } else {
             let c = self.infcx.shallow_resolve(c);
             match c.val {
                 ty::ConstKind::Infer(InferConst::Var(vid)) => {
-                    self.err = Some(FixupError::UnresolvedConst(vid));
-                    return self.tcx().const_error(c.ty);
+                    return Err(FixupError::UnresolvedConst(vid));
                 }
                 ty::ConstKind::Infer(InferConst::Fresh(_)) => {
                     bug!("Unexpected const in full const resolver: {:?}", c);
                 }
                 _ => {}
             }
-            c.super_fold_with(self)
+            c.try_super_fold_with(self)
         }
     }
 }
index c4a2ecee096eb1395a8d50fb206f3a5162156f42..20453eeb1474e847c84d83730d84a33561f8358d 100644 (file)
@@ -1,7 +1,7 @@
 use crate::traits;
 use crate::traits::project::Normalized;
 use rustc_middle::ty;
-use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
+use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeVisitor};
 
 use std::fmt;
 use std::ops::ControlFlow;
@@ -60,16 +60,20 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 // TypeFoldable implementations.
 
 impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx, O> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        traits::Obligation {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        Ok(traits::Obligation {
             cause: self.cause,
             recursion_depth: self.recursion_depth,
-            predicate: self.predicate.fold_with(folder),
-            param_env: self.param_env.fold_with(folder),
-        }
+            predicate: self.predicate.try_fold_with(folder)?,
+            param_env: self.param_env.try_fold_with(folder)?,
+        })
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        self.predicate.visit_with(visitor)
+        self.predicate.visit_with(visitor)?;
+        self.param_env.visit_with(visitor)
     }
 }
index b073ee9682fbdfeef72fb6c9ad20f0fca95a9184..dbee92cf598b5b855e9fa25a4354feeb1966e346 100644 (file)
@@ -35,7 +35,7 @@
 use rustc_session::search_paths::PathKind;
 use rustc_session::{Limit, Session};
 use rustc_span::symbol::{sym, Ident, Symbol};
-use rustc_span::FileName;
+use rustc_span::{FileName, MultiSpan};
 use rustc_trait_selection::traits;
 use rustc_typeck as typeck;
 use tempfile::Builder as TempFileBuilder;
@@ -323,7 +323,7 @@ pub fn configure_and_expand(
 
         let crate_attrs = krate.attrs.clone();
         let extern_mod_loaded = |ident: Ident, attrs, items, span| {
-            let krate = ast::Crate { attrs, items, span };
+            let krate = ast::Crate { attrs, items, span, is_placeholder: None };
             pre_expansion_lint(sess, lint_store, &krate, &crate_attrs, &ident.name.as_str());
             (krate.attrs, krate.items)
         };
@@ -450,6 +450,19 @@ pub fn configure_and_expand(
         });
     }
 
+    // Gate identifiers containing invalid Unicode codepoints that were recovered during lexing.
+    sess.parse_sess.bad_unicode_identifiers.with_lock(|identifiers| {
+        let mut identifiers: Vec<_> = identifiers.drain().collect();
+        identifiers.sort_by_key(|&(key, _)| key);
+        for (ident, mut spans) in identifiers.into_iter() {
+            spans.sort();
+            sess.diagnostic().span_err(
+                MultiSpan::from(spans),
+                &format!("identifiers cannot contain emoji: `{}`", ident),
+            );
+        }
+    });
+
     Ok(krate)
 }
 
index 24d4b05042133f548219983d00a898cc059debe7..6147311af6159a0e36616714b4d8b67f87ed6b01 100644 (file)
@@ -726,7 +726,6 @@ macro_rules! tracked {
     tracked!(dep_info_omit_d_target, true);
     tracked!(dual_proc_macros, true);
     tracked!(fewer_names, Some(true));
-    tracked!(force_overflow_checks, Some(true));
     tracked!(force_unstable_if_unmarked, true);
     tracked!(fuel, Some(("abc".to_string(), 99)));
     tracked!(function_sections, Some(false));
index 60c146f457b42afc0dcd2f849d1aba70476f7836..35af110537d4c3ea859b76fbcf4ad4d9ac8a67c8 100644 (file)
@@ -17,6 +17,7 @@ doctest = false
 # Note that this crate purposefully does not depend on other rustc crates
 [dependencies]
 unicode-xid = "0.2.0"
+unic-emoji-char = "0.9.0"
 
 [dev-dependencies]
 expect-test = "1.0"
index 297f3d19ca1781eb9cc5494584829b4cda07fd07..0ba6c56dbb50147b7e54ad80dccdeb7b00649c39 100644 (file)
@@ -2,10 +2,11 @@
 
 /// Peekable iterator over a char sequence.
 ///
-/// Next characters can be peeked via `nth_char` method,
+/// Next characters can be peeked via `first` method,
 /// and position can be shifted forward via `bump` method.
 pub(crate) struct Cursor<'a> {
     initial_len: usize,
+    /// Iterator over chars. Slightly faster than a &str.
     chars: Chars<'a>,
     #[cfg(debug_assertions)]
     prev: char,
@@ -37,22 +38,21 @@ pub(crate) fn prev(&self) -> char {
         }
     }
 
-    /// Returns nth character relative to the current cursor position.
+    /// Peeks the next symbol from the input stream without consuming it.
     /// If requested position doesn't exist, `EOF_CHAR` is returned.
     /// However, getting `EOF_CHAR` doesn't always mean actual end of file,
     /// it should be checked with `is_eof` method.
-    fn nth_char(&self, n: usize) -> char {
-        self.chars().nth(n).unwrap_or(EOF_CHAR)
-    }
-
-    /// Peeks the next symbol from the input stream without consuming it.
     pub(crate) fn first(&self) -> char {
-        self.nth_char(0)
+        // `.next()` optimizes better than `.nth(0)`
+        self.chars.clone().next().unwrap_or(EOF_CHAR)
     }
 
     /// Peeks the second symbol from the input stream without consuming it.
     pub(crate) fn second(&self) -> char {
-        self.nth_char(1)
+        // `.next()` optimizes better than `.nth(1)`
+        let mut iter = self.chars.clone();
+        iter.next();
+        iter.next().unwrap_or(EOF_CHAR)
     }
 
     /// Checks if there is nothing more to consume.
@@ -65,9 +65,9 @@ pub(crate) fn len_consumed(&self) -> usize {
         self.initial_len - self.chars.as_str().len()
     }
 
-    /// Returns a `Chars` iterator over the remaining characters.
-    fn chars(&self) -> Chars<'a> {
-        self.chars.clone()
+    /// Resets the number of bytes consumed to 0.
+    pub(crate) fn reset_len_consumed(&mut self) {
+        self.initial_len = self.chars.as_str().len();
     }
 
     /// Moves to the next character.
@@ -81,4 +81,13 @@ pub(crate) fn bump(&mut self) -> Option<char> {
 
         Some(c)
     }
+
+    /// Eats symbols while predicate returns true or until the end of file is reached.
+    pub(crate) fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) {
+        // It was tried making optimized version of this for eg. line comments, but
+        // LLVM can inline all of this and compile it down to fast iteration over bytes.
+        while predicate(self.first()) && !self.is_eof() {
+            self.bump();
+        }
+    }
 }
index b64a891cb2526402a421551b2050e2af390fc155..5b8300ab530f92632b22fa65f03282118b89833b 100644 (file)
@@ -64,6 +64,8 @@ pub enum TokenKind {
     /// "ident" or "continue"
     /// At this step keywords are also considered identifiers.
     Ident,
+    /// Like the above, but containing invalid unicode codepoints.
+    InvalidIdent,
     /// "r#ident"
     RawIdent,
     /// An unknown prefix like `foo#`, `foo'`, `foo"`. Note that only the
@@ -225,14 +227,15 @@ pub fn first_token(input: &str) -> Token {
 }
 
 /// Creates an iterator that produces tokens from the input string.
-pub fn tokenize(mut input: &str) -> impl Iterator<Item = Token> + '_ {
+pub fn tokenize(input: &str) -> impl Iterator<Item = Token> + '_ {
+    let mut cursor = Cursor::new(input);
     std::iter::from_fn(move || {
-        if input.is_empty() {
-            return None;
+        if cursor.is_eof() {
+            None
+        } else {
+            cursor.reset_len_consumed();
+            Some(cursor.advance_token())
         }
-        let token = first_token(input);
-        input = &input[token.len..];
-        Some(token)
     })
 }
 
@@ -411,6 +414,10 @@ fn advance_token(&mut self) -> Token {
                 let kind = Str { terminated };
                 Literal { kind, suffix_start }
             }
+            // Identifier starting with an emoji. Only lexed for graceful error recovery.
+            c if !c.is_ascii() && unic_emoji_char::is_emoji(c) => {
+                self.fake_ident_or_unknown_prefix()
+            }
             _ => Unknown,
         };
         Token::new(token_kind, self.len_consumed())
@@ -492,10 +499,28 @@ fn ident_or_unknown_prefix(&mut self) -> TokenKind {
         // we see a prefix here, it is definitely an unknown prefix.
         match self.first() {
             '#' | '"' | '\'' => UnknownPrefix,
+            c if !c.is_ascii() && unic_emoji_char::is_emoji(c) => {
+                self.fake_ident_or_unknown_prefix()
+            }
             _ => Ident,
         }
     }
 
+    fn fake_ident_or_unknown_prefix(&mut self) -> TokenKind {
+        // Start is already eaten, eat the rest of identifier.
+        self.eat_while(|c| {
+            unicode_xid::UnicodeXID::is_xid_continue(c)
+                || (!c.is_ascii() && unic_emoji_char::is_emoji(c))
+                || c == '\u{200d}'
+        });
+        // Known prefixes must have been handled earlier. So if
+        // we see a prefix here, it is definitely an unknown prefix.
+        match self.first() {
+            '#' | '"' | '\'' => UnknownPrefix,
+            _ => InvalidIdent,
+        }
+    }
+
     fn number(&mut self, first_digit: char) -> LiteralKind {
         debug_assert!('0' <= self.prev() && self.prev() <= '9');
         let mut base = Base::Decimal;
@@ -808,11 +833,4 @@ fn eat_identifier(&mut self) {
 
         self.eat_while(is_id_continue);
     }
-
-    /// Eats symbols while predicate returns true or until the end of file is reached.
-    fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) {
-        while predicate(self.first()) && !self.is_eof() {
-            self.bump();
-        }
-    }
 }
index f2e4e70a197796923fb8eae72e799cb39d829d74..077d3e1c82058bd055d33ed0b673571ab001c134 100644 (file)
@@ -1079,6 +1079,10 @@ fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
         warn_if_doc(cx, expr.span, "expressions", &expr.attrs);
     }
+
+    fn check_generic_param(&mut self, cx: &EarlyContext<'_>, param: &ast::GenericParam) {
+        warn_if_doc(cx, param.ident.span, "generic parameters", &param.attrs);
+    }
 }
 
 declare_lint! {
@@ -3011,7 +3015,7 @@ fn check_foreign_item(&mut self, cx: &LateContext<'tcx>, this_fi: &hir::ForeignI
                     this_decl_ty,
                     CItemKind::Declaration,
                 ) {
-                    let orig_fi = tcx.hir().expect_foreign_item(existing_hid);
+                    let orig_fi = tcx.hir().expect_foreign_item(existing_hid.expect_owner());
                     let orig = Self::name_of_extern_decl(tcx, orig_fi);
 
                     // We want to ensure that we use spans for both decls that include where the
index 876245747f64a50acf8a94f702fd3bfc176a9978..65772d02376d43ae082a6e4b11933604c5649fb3 100644 (file)
@@ -91,16 +91,14 @@ fn enforce_mem_variant_count(cx: &LateContext<'_>, func_expr: &hir::Expr<'_>, sp
 
 impl<'tcx> LateLintPass<'tcx> for EnumIntrinsicsNonEnums {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
-        if let hir::ExprKind::Call(ref func, ref args) = expr.kind {
-            if let hir::ExprKind::Path(ref qpath) = func.kind {
-                if let Some(def_id) = cx.qpath_res(qpath, func.hir_id).opt_def_id() {
-                    if cx.tcx.is_diagnostic_item(sym::mem_discriminant, def_id) {
-                        enforce_mem_discriminant(cx, func, expr.span, args[0].span);
-                    } else if cx.tcx.is_diagnostic_item(sym::mem_variant_count, def_id) {
-                        enforce_mem_variant_count(cx, func, expr.span);
-                    }
-                }
-            }
+        let hir::ExprKind::Call(func, args) = &expr.kind else { return };
+        let hir::ExprKind::Path(qpath) = &func.kind else { return };
+        let Some(def_id) = cx.qpath_res(qpath, func.hir_id).opt_def_id() else { return };
+        let Some(name) = cx.tcx.get_diagnostic_name(def_id) else { return };
+        match name {
+            sym::mem_discriminant => enforce_mem_discriminant(cx, func, expr.span, args[0].span),
+            sym::mem_variant_count => enforce_mem_variant_count(cx, func, expr.span),
+            _ => {}
         }
     }
 }
index 507b4421fa160266c860d468c0e5ec1f5eaed56f..1f8c63424f9b1ca6f014e27f9c48fbc6e958b50f 100644 (file)
@@ -30,9 +30,9 @@
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(crate_visibility_modifier)]
-#![cfg_attr(bootstrap, feature(format_args_capture))]
 #![feature(iter_order_by)]
 #![feature(iter_zip)]
+#![feature(let_else)]
 #![feature(never_type)]
 #![feature(nll)]
 #![feature(control_flow_enum)]
index f2ad72f97eca77a9a22937a6b4f2e6602ef33106..4a9b27e89b19927464ef8bdf71849252261c0e70 100644 (file)
@@ -309,14 +309,21 @@ fn panic_call<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>) -> (Span,
     // Unwrap more levels of macro expansion, as panic_2015!()
     // was likely expanded from panic!() and possibly from
     // [debug_]assert!().
-    for &i in
-        &[sym::std_panic_macro, sym::core_panic_macro, sym::assert_macro, sym::debug_assert_macro]
-    {
+    loop {
         let parent = expn.call_site.ctxt().outer_expn_data();
-        if parent.macro_def_id.map_or(false, |id| cx.tcx.is_diagnostic_item(i, id)) {
-            expn = parent;
-            panic_macro = i;
+        let Some(id) = parent.macro_def_id else { break };
+        let Some(name) = cx.tcx.get_diagnostic_name(id) else { break };
+        if !matches!(
+            name,
+            sym::core_panic_macro
+                | sym::std_panic_macro
+                | sym::assert_macro
+                | sym::debug_assert_macro
+        ) {
+            break;
         }
+        expn = parent;
+        panic_macro = name;
     }
 
     let macro_symbol =
index d2c970468abc7d8de5800e76aa684710defaad18..a3a3cd0077dbefd70c80018aaf5550d93ca9b8e6 100644 (file)
@@ -75,38 +75,36 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
             _ => return,
         };
         // (Re)check that it implements the noop diagnostic.
-        for s in [sym::noop_method_clone, sym::noop_method_deref, sym::noop_method_borrow].iter() {
-            if cx.tcx.is_diagnostic_item(*s, i.def_id()) {
-                let method = &call.ident.name;
-                let receiver = &elements[0];
-                let receiver_ty = cx.typeck_results().expr_ty(receiver);
-                let expr_ty = cx.typeck_results().expr_ty_adjusted(expr);
-                if receiver_ty != expr_ty {
-                    // This lint will only trigger if the receiver type and resulting expression \
-                    // type are the same, implying that the method call is unnecessary.
-                    return;
-                }
-                let expr_span = expr.span;
-                let note = format!(
-                    "the type `{:?}` which `{}` is being called on is the same as \
-                     the type returned from `{}`, so the method call does not do \
-                     anything and can be removed",
-                    receiver_ty, method, method,
-                );
-
-                let span = expr_span.with_lo(receiver.span.hi());
-                cx.struct_span_lint(NOOP_METHOD_CALL, span, |lint| {
-                    let method = &call.ident.name;
-                    let message = format!(
-                        "call to `.{}()` on a reference in this situation does nothing",
-                        &method,
-                    );
-                    lint.build(&message)
-                        .span_label(span, "unnecessary method call")
-                        .note(&note)
-                        .emit()
-                });
-            }
+        let Some(name) = cx.tcx.get_diagnostic_name(i.def_id()) else { return };
+        if !matches!(
+            name,
+            sym::noop_method_borrow | sym::noop_method_clone | sym::noop_method_deref
+        ) {
+            return;
         }
+        let method = &call.ident.name;
+        let receiver = &elements[0];
+        let receiver_ty = cx.typeck_results().expr_ty(receiver);
+        let expr_ty = cx.typeck_results().expr_ty_adjusted(expr);
+        if receiver_ty != expr_ty {
+            // This lint will only trigger if the receiver type and resulting expression \
+            // type are the same, implying that the method call is unnecessary.
+            return;
+        }
+        let expr_span = expr.span;
+        let note = format!(
+            "the type `{:?}` which `{}` is being called on is the same as \
+             the type returned from `{}`, so the method call does not do \
+             anything and can be removed",
+            receiver_ty, method, method,
+        );
+
+        let span = expr_span.with_lo(receiver.span.hi());
+        cx.struct_span_lint(NOOP_METHOD_CALL, span, |lint| {
+            let method = &call.ident.name;
+            let message =
+                format!("call to `.{}()` on a reference in this situation does nothing", &method,);
+            lint.build(&message).span_label(span, "unnecessary method call").note(&note).emit()
+        });
     }
 }
index 708cd56e068b537c40be4088eb3d961194443b2f..b20f7357b35b898ac537887318b59999575b6bcf 100644 (file)
@@ -1337,7 +1337,9 @@ fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
             let layout = match cx.layout_of(ty) {
                 Ok(layout) => layout,
                 Err(
-                    ty::layout::LayoutError::Unknown(_) | ty::layout::LayoutError::SizeOverflow(_),
+                    ty::layout::LayoutError::Unknown(_)
+                    | ty::layout::LayoutError::SizeOverflow(_)
+                    | ty::layout::LayoutError::NormalizationFailure(_, _),
                 ) => return,
             };
             let (variants, tag) = match layout.variants {
index 8cd2bd12450e3d55a1c548cc4475d1f598754225..154f554d607dfb60af9afaa03d54952f96d4a178 100644 (file)
@@ -10,6 +10,7 @@ using namespace llvm;
 
 struct LLVMRustCounterMappingRegion {
   coverage::Counter Count;
+  coverage::Counter FalseCount;
   uint32_t FileID;
   uint32_t ExpandedFileID;
   uint32_t LineStart;
@@ -53,7 +54,7 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer(
   MappingRegions.reserve(NumMappingRegions);
   for (const auto &Region : makeArrayRef(RustMappingRegions, NumMappingRegions)) {
     MappingRegions.emplace_back(
-        Region.Count, Region.FileID, Region.ExpandedFileID,
+        Region.Count, Region.FalseCount, Region.FileID, Region.ExpandedFileID,
         Region.LineStart, Region.ColumnStart, Region.LineEnd, Region.ColumnEnd,
         Region.Kind);
   }
@@ -108,5 +109,9 @@ extern "C" void LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str) {
 }
 
 extern "C" uint32_t LLVMRustCoverageMappingVersion() {
-  return coverage::CovMapVersion::Version4;
+#if LLVM_VERSION_GE(13, 0)
+  return coverage::CovMapVersion::Version6;
+#else
+  return coverage::CovMapVersion::Version5;
+#endif
 }
index bb6d42c1a9cbb0c3d42b644863808511802d3854..94d2a4b8e4c9be23d2b505b48e576fbc6c1c79d7 100644 (file)
@@ -1,5 +1,6 @@
 #include "LLVMWrapper.h"
 #include "llvm/IR/DebugInfoMetadata.h"
+#include "llvm/IR/DiagnosticHandler.h"
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/DiagnosticPrinter.h"
 #include "llvm/IR/GlobalVariable.h"
@@ -1177,10 +1178,13 @@ static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
   case DK_SampleProfile:
     return LLVMRustDiagnosticKind::SampleProfile;
   case DK_OptimizationRemark:
+  case DK_MachineOptimizationRemark:
     return LLVMRustDiagnosticKind::OptimizationRemark;
   case DK_OptimizationRemarkMissed:
+  case DK_MachineOptimizationRemarkMissed:
     return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
   case DK_OptimizationRemarkAnalysis:
+  case DK_MachineOptimizationRemarkAnalysis:
     return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
   case DK_OptimizationRemarkAnalysisFPCommute:
     return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
@@ -1783,3 +1787,92 @@ extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
     return LLVMRustResult::Success;
   }
 }
+
+// Transfers ownership of DiagnosticHandler unique_ptr to the caller.
+extern "C" DiagnosticHandler *
+LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) {
+  std::unique_ptr<DiagnosticHandler> DH = unwrap(C)->getDiagnosticHandler();
+  return DH.release();
+}
+
+// Sets unique_ptr to object of DiagnosticHandler to provide custom diagnostic
+// handling. Ownership of the handler is moved to the LLVMContext.
+extern "C" void LLVMRustContextSetDiagnosticHandler(LLVMContextRef C,
+                                                    DiagnosticHandler *DH) {
+  unwrap(C)->setDiagnosticHandler(std::unique_ptr<DiagnosticHandler>(DH));
+}
+
+using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy;
+
+// Configures a diagnostic handler that invokes provided callback when a
+// backend needs to emit a diagnostic.
+//
+// When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise
+// the RemarkPasses array specifies individual passes for which remarks will be
+// enabled.
+extern "C" void LLVMRustContextConfigureDiagnosticHandler(
+    LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
+    void *DiagnosticHandlerContext, bool RemarkAllPasses,
+    const char * const * RemarkPasses, size_t RemarkPassesLen) {
+
+  class RustDiagnosticHandler final : public DiagnosticHandler {
+  public:
+    RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
+                          void *DiagnosticHandlerContext,
+                          bool RemarkAllPasses,
+                          std::vector<std::string> RemarkPasses)
+        : DiagnosticHandlerCallback(DiagnosticHandlerCallback),
+          DiagnosticHandlerContext(DiagnosticHandlerContext),
+          RemarkAllPasses(RemarkAllPasses),
+          RemarkPasses(RemarkPasses) {}
+
+    virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
+      if (DiagnosticHandlerCallback) {
+        DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
+        return true;
+      }
+      return false;
+    }
+
+    bool isAnalysisRemarkEnabled(StringRef PassName) const override {
+      return isRemarkEnabled(PassName);
+    }
+
+    bool isMissedOptRemarkEnabled(StringRef PassName) const override {
+      return isRemarkEnabled(PassName);
+    }
+
+    bool isPassedOptRemarkEnabled(StringRef PassName) const override {
+      return isRemarkEnabled(PassName);
+    }
+
+    bool isAnyRemarkEnabled() const override {
+      return RemarkAllPasses || !RemarkPasses.empty();
+    }
+
+  private:
+    bool isRemarkEnabled(StringRef PassName) const {
+      if (RemarkAllPasses)
+        return true;
+
+      for (auto &Pass : RemarkPasses)
+        if (Pass == PassName)
+          return true;
+
+      return false;
+    }
+
+    LLVMDiagnosticHandlerTy DiagnosticHandlerCallback = nullptr;
+    void *DiagnosticHandlerContext = nullptr;
+
+    bool RemarkAllPasses = false;
+    std::vector<std::string> RemarkPasses;
+  };
+
+  std::vector<std::string> Passes;
+  for (size_t I = 0; I != RemarkPassesLen; ++I)
+    Passes.push_back(RemarkPasses[I]);
+
+  unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
+      DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));
+}
index 082af087bf49fd720236862aa438776024495b49..9f448a593da508128e74f7cbd7ebb71b7251b9c6 100644 (file)
@@ -17,7 +17,7 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::
         vi.construct(|_, index| {
             let bind = &bindings[index];
             quote! {
-                ::rustc_middle::ty::fold::TypeFoldable::fold_with(#bind, __folder)
+                ::rustc_middle::ty::fold::TypeFoldable::try_fold_with(#bind, __folder)?
             }
         })
     });
@@ -25,11 +25,11 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::
     s.bound_impl(
         quote!(::rustc_middle::ty::fold::TypeFoldable<'tcx>),
         quote! {
-            fn super_fold_with<__F: ::rustc_middle::ty::fold::TypeFolder<'tcx>>(
+            fn try_super_fold_with<__F: ::rustc_middle::ty::fold::FallibleTypeFolder<'tcx>>(
                 self,
                 __folder: &mut __F
-            ) -> Self {
-                match self { #body_fold }
+            ) -> Result<Self, __F::Error> {
+                Ok(match self { #body_fold })
             }
 
             fn super_visit_with<__F: ::rustc_middle::ty::fold::TypeVisitor<'tcx>>(
index eb0a693226c480d51c91311cd63ddcc5bd1cfd76..2626a2e189c1d062cffc8b676e4669b77ab3e433 100644 (file)
@@ -512,13 +512,17 @@ fn resolve_crate<'b>(
         name: Symbol,
         span: Span,
         dep_kind: CrateDepKind,
-    ) -> CrateNum {
+    ) -> Option<CrateNum> {
         self.used_extern_options.insert(name);
-        self.maybe_resolve_crate(name, dep_kind, None).unwrap_or_else(|err| {
-            let missing_core =
-                self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err();
-            err.report(&self.sess, span, missing_core)
-        })
+        match self.maybe_resolve_crate(name, dep_kind, None) {
+            Ok(cnum) => Some(cnum),
+            Err(err) => {
+                let missing_core =
+                    self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err();
+                err.report(&self.sess, span, missing_core);
+                None
+            }
+        }
     }
 
     fn maybe_resolve_crate<'b>(
@@ -751,7 +755,7 @@ fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
         };
         info!("panic runtime not found -- loading {}", name);
 
-        let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit);
+        let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; };
         let data = self.cstore.get_crate_data(cnum);
 
         // Sanity check the loaded crate to ensure it is indeed a panic runtime
@@ -791,7 +795,7 @@ fn inject_profiler_runtime(&mut self, krate: &ast::Crate) {
             );
         }
 
-        let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit);
+        let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; };
         let data = self.cstore.get_crate_data(cnum);
 
         // Sanity check the loaded crate to ensure it is indeed a profiler runtime
@@ -991,7 +995,7 @@ pub fn process_extern_crate(
         item: &ast::Item,
         definitions: &Definitions,
         def_id: LocalDefId,
-    ) -> CrateNum {
+    ) -> Option<CrateNum> {
         match item.kind {
             ast::ItemKind::ExternCrate(orig_name) => {
                 debug!(
@@ -1011,7 +1015,7 @@ pub fn process_extern_crate(
                     CrateDepKind::Explicit
                 };
 
-                let cnum = self.resolve_crate(name, item.span, dep_kind);
+                let cnum = self.resolve_crate(name, item.span, dep_kind)?;
 
                 let path_len = definitions.def_path(def_id).data.len();
                 self.update_extern_crate(
@@ -1023,14 +1027,14 @@ pub fn process_extern_crate(
                         dependency_of: LOCAL_CRATE,
                     },
                 );
-                cnum
+                Some(cnum)
             }
             _ => bug!(),
         }
     }
 
-    pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> CrateNum {
-        let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit);
+    pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> Option<CrateNum> {
+        let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit)?;
 
         self.update_extern_crate(
             cnum,
@@ -1043,7 +1047,7 @@ pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> CrateNum {
             },
         );
 
-        cnum
+        Some(cnum)
     }
 
     pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option<CrateNum> {
index 7cba16e0a9ae38d9333afc16d1dc1b0b65699dfc..e2fd8056f1a7c6a63fe728b6a38c5bd36d9706d8 100644 (file)
 use rustc_data_structures::owning_ref::OwningRef;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::MetadataRef;
-use rustc_errors::struct_span_err;
+use rustc_errors::{struct_span_err, FatalError};
 use rustc_session::config::{self, CrateType};
 use rustc_session::cstore::{CrateSource, MetadataLoader};
 use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch};
@@ -814,11 +814,11 @@ pub fn find_plugin_registrar(
     span: Span,
     name: Symbol,
 ) -> PathBuf {
-    match find_plugin_registrar_impl(sess, metadata_loader, name) {
-        Ok(res) => res,
+    find_plugin_registrar_impl(sess, metadata_loader, name).unwrap_or_else(|err| {
         // `core` is always available if we got as far as loading plugins.
-        Err(err) => err.report(sess, span, false),
-    }
+        err.report(sess, span, false);
+        FatalError.raise()
+    })
 }
 
 fn find_plugin_registrar_impl<'a>(
@@ -931,8 +931,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 }
 
 impl CrateError {
-    crate fn report(self, sess: &Session, span: Span, missing_core: bool) -> ! {
-        let mut err = match self {
+    crate fn report(self, sess: &Session, span: Span, missing_core: bool) {
+        let mut diag = match self {
             CrateError::NonAsciiName(crate_name) => sess.struct_span_err(
                 span,
                 &format!("cannot load a crate with a non-ascii name `{}`", crate_name),
@@ -1210,8 +1210,6 @@ impl CrateError {
             ),
         };
 
-        err.emit();
-        sess.abort_if_errors();
-        unreachable!();
+        diag.emit();
     }
 }
index d46829c2ceea693b047305ca5165b8dd0696a9fd..514a49d7e2ce27f25b59706720158ad62b249788 100644 (file)
@@ -1152,8 +1152,7 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) {
         debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id);
         let tcx = self.tcx;
 
-        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-        let ast_item = tcx.hir().expect_trait_item(hir_id);
+        let ast_item = tcx.hir().expect_trait_item(def_id.expect_local());
         let trait_item = tcx.associated_item(def_id);
 
         let container = match trait_item.defaultness {
@@ -1221,8 +1220,7 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) {
         debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id);
         let tcx = self.tcx;
 
-        let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-        let ast_item = self.tcx.hir().expect_impl_item(hir_id);
+        let ast_item = self.tcx.hir().expect_impl_item(def_id.expect_local());
         let impl_item = self.tcx.associated_item(def_id);
 
         let container = match impl_item.defaultness {
@@ -1751,7 +1749,7 @@ fn encode_crate_deps(&mut self) -> Lazy<[CrateDep]> {
     fn encode_lib_features(&mut self) -> Lazy<[(Symbol, Option<Symbol>)]> {
         empty_proc_macro!(self);
         let tcx = self.tcx;
-        let lib_features = tcx.lib_features();
+        let lib_features = tcx.lib_features(());
         self.lazy(lib_features.to_vec())
     }
 
index d9d0781b37aacefe4afab97366de2b6448907d6e..5c4c2eee21fc1e5c954720987ee08f079a97b44f 100644 (file)
@@ -869,24 +869,24 @@ pub fn get_foreign_abi(&self, hir_id: HirId) -> Abi {
         bug!("expected foreign mod or inlined parent, found {}", self.node_to_string(parent))
     }
 
-    pub fn expect_item(&self, id: HirId) -> &'hir Item<'hir> {
-        match self.tcx.hir_owner(id.expect_owner()) {
+    pub fn expect_item(&self, id: LocalDefId) -> &'hir Item<'hir> {
+        match self.tcx.hir_owner(id) {
             Some(Owner { node: OwnerNode::Item(item), .. }) => item,
-            _ => bug!("expected item, found {}", self.node_to_string(id)),
+            _ => bug!("expected item, found {}", self.node_to_string(HirId::make_owner(id))),
         }
     }
 
-    pub fn expect_impl_item(&self, id: HirId) -> &'hir ImplItem<'hir> {
-        match self.tcx.hir_owner(id.expect_owner()) {
+    pub fn expect_impl_item(&self, id: LocalDefId) -> &'hir ImplItem<'hir> {
+        match self.tcx.hir_owner(id) {
             Some(Owner { node: OwnerNode::ImplItem(item), .. }) => item,
-            _ => bug!("expected impl item, found {}", self.node_to_string(id)),
+            _ => bug!("expected impl item, found {}", self.node_to_string(HirId::make_owner(id))),
         }
     }
 
-    pub fn expect_trait_item(&self, id: HirId) -> &'hir TraitItem<'hir> {
-        match self.tcx.hir_owner(id.expect_owner()) {
+    pub fn expect_trait_item(&self, id: LocalDefId) -> &'hir TraitItem<'hir> {
+        match self.tcx.hir_owner(id) {
             Some(Owner { node: OwnerNode::TraitItem(item), .. }) => item,
-            _ => bug!("expected trait item, found {}", self.node_to_string(id)),
+            _ => bug!("expected trait item, found {}", self.node_to_string(HirId::make_owner(id))),
         }
     }
 
@@ -897,10 +897,12 @@ pub fn expect_variant(&self, id: HirId) -> &'hir Variant<'hir> {
         }
     }
 
-    pub fn expect_foreign_item(&self, id: HirId) -> &'hir ForeignItem<'hir> {
-        match self.tcx.hir_owner(id.expect_owner()) {
+    pub fn expect_foreign_item(&self, id: LocalDefId) -> &'hir ForeignItem<'hir> {
+        match self.tcx.hir_owner(id) {
             Some(Owner { node: OwnerNode::ForeignItem(item), .. }) => item,
-            _ => bug!("expected foreign item, found {}", self.node_to_string(id)),
+            _ => {
+                bug!("expected foreign item, found {}", self.node_to_string(HirId::make_owner(id)))
+            }
         }
     }
 
index 9ce9f65a49066bb88064a3e6786a551a8a52de8a..b67ad8b770ea1537ca2e8264d2a36a5eeb50cb30 100644 (file)
@@ -56,6 +56,7 @@
 #![feature(try_blocks)]
 #![feature(try_reserve_kind)]
 #![feature(nonzero_ops)]
+#![feature(unwrap_infallible)]
 #![recursion_limit = "512"]
 
 #[macro_use]
index c0f2a76c19d6e93021fc68ce50469f1e8bdc743f..4e927f00acd5eda6cc42bf9c773746e402ee6676 100644 (file)
@@ -52,11 +52,11 @@ macro_rules! TrivialTypeFoldableImpls {
     (for <$tcx:lifetime> { $($ty:ty,)+ }) => {
         $(
             impl<$tcx> $crate::ty::fold::TypeFoldable<$tcx> for $ty {
-                fn super_fold_with<F: $crate::ty::fold::TypeFolder<$tcx>>(
+                fn try_super_fold_with<F: $crate::ty::fold::FallibleTypeFolder<$tcx>>(
                     self,
                     _: &mut F
-                ) -> $ty {
-                    self
+                ) -> ::std::result::Result<$ty, F::Error> {
+                    Ok(self)
                 }
 
                 fn super_visit_with<F: $crate::ty::fold::TypeVisitor<$tcx>>(
@@ -95,10 +95,10 @@ macro_rules! EnumTypeFoldableImpl {
         impl<$($p),*> $crate::ty::fold::TypeFoldable<$tcx> for $s
             $(where $($wc)*)*
         {
-            fn super_fold_with<V: $crate::ty::fold::TypeFolder<$tcx>>(
+            fn try_super_fold_with<V: $crate::ty::fold::FallibleTypeFolder<$tcx>>(
                 self,
                 folder: &mut V,
-            ) -> Self {
+            ) -> ::std::result::Result<Self, V::Error> {
                 EnumTypeFoldableImpl!(@FoldVariants(self, folder) input($($variants)*) output())
             }
 
@@ -112,9 +112,9 @@ fn super_visit_with<V: $crate::ty::fold::TypeVisitor<$tcx>>(
     };
 
     (@FoldVariants($this:expr, $folder:expr) input() output($($output:tt)*)) => {
-        match $this {
+        Ok(match $this {
             $($output)*
-        }
+        })
     };
 
     (@FoldVariants($this:expr, $folder:expr)
@@ -126,7 +126,7 @@ fn super_visit_with<V: $crate::ty::fold::TypeVisitor<$tcx>>(
                 output(
                     $variant ( $($variant_arg),* ) => {
                         $variant (
-                            $($crate::ty::fold::TypeFoldable::fold_with($variant_arg, $folder)),*
+                            $($crate::ty::fold::TypeFoldable::try_fold_with($variant_arg, $folder)?),*
                         )
                     }
                     $($output)*
@@ -145,7 +145,7 @@ fn super_visit_with<V: $crate::ty::fold::TypeVisitor<$tcx>>(
                         $variant {
                             $($variant_arg: $crate::ty::fold::TypeFoldable::fold_with(
                                 $variant_arg, $folder
-                            )),* }
+                            )?),* }
                     }
                     $($output)*
                 )
index 605e0bc2e63ef7d6810989ebafc401bf3822f274..39ca41c92ff7569f749f4371fef9696591020bb3 100644 (file)
@@ -7,13 +7,12 @@
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html
 
 use crate::ty::TyCtxt;
-use rustc_hir as hir;
-use rustc_hir::Node;
-use rustc_query_system::ich::{NodeIdHashingMode, StableHashingContext};
-
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir as hir;
+use rustc_hir::Node;
 use rustc_macros::HashStable;
+use rustc_query_system::ich::{NodeIdHashingMode, StableHashingContext};
 use rustc_span::{Span, DUMMY_SP};
 
 use std::fmt;
@@ -210,11 +209,6 @@ pub struct ScopeTree {
     /// If not empty, this body is the root of this region hierarchy.
     pub root_body: Option<hir::HirId>,
 
-    /// The parent of the root body owner, if the latter is an
-    /// an associated const or method, as impls/traits can also
-    /// have lifetime parameters free in this body.
-    pub root_parent: Option<hir::HirId>,
-
     /// Maps from a scope ID to the enclosing scope id;
     /// this is usually corresponding to the lexical nesting, though
     /// in the case of closures the parent scope is the innermost
@@ -445,7 +439,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for ScopeTree {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         let ScopeTree {
             root_body,
-            root_parent,
             ref body_expr_count,
             ref parent_map,
             ref var_map,
@@ -455,8 +448,7 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
         } = *self;
 
         hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
-            root_body.hash_stable(hcx, hasher);
-            root_parent.hash_stable(hcx, hasher);
+            root_body.hash_stable(hcx, hasher)
         });
 
         body_expr_count.hash_stable(hcx, hasher);
index ddb1a84fe7bdffbd368cf8028572c4916a27f704..640d3a5a02b0f0ae7e1efc759a9f13a9997096a5 100644 (file)
@@ -21,9 +21,9 @@ pub struct ExpressionOperandId {
 impl ExpressionOperandId {
     /// An expression operand for a "zero counter", as described in the following references:
     ///
-    /// * <https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#counter>
-    /// * <https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#tag>
-    /// * <https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#counter-expressions>
+    /// * <https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#counter>
+    /// * <https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#tag>
+    /// * <https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#counter-expressions>
     ///
     /// This operand can be used to count two or more separate code regions with a single counter,
     /// if they run sequentially with no branches, by injecting the `Counter` in a `BasicBlock` for
index 7a51bb4a1f32ae828f9de259450a815ba37981c1..8e4a17bfa65cb531c578999f827b596570f9ef6a 100644 (file)
@@ -492,9 +492,6 @@ pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
     }
 }
 
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-static_assert_size!(InterpError<'_>, 64);
-
 pub enum InterpError<'tcx> {
     /// The program caused undefined behavior.
     UndefinedBehavior(UndefinedBehaviorInfo<'tcx>),
index 253ac266bedaa246cc1039b9a6e5191447cb152b..df36b2e4e0b3ed0f239bd17b26fd9b617a2412e6 100644 (file)
@@ -7,7 +7,7 @@
 use crate::mir::visit::MirVisitable;
 use crate::ty::adjustment::PointerCast;
 use crate::ty::codec::{TyDecoder, TyEncoder};
-use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
+use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeVisitor};
 use crate::ty::print::{FmtPrinter, Printer};
 use crate::ty::subst::{Subst, SubstsRef};
 use crate::ty::{self, List, Ty, TyCtxt};
@@ -1803,6 +1803,16 @@ fn is_indirect(&self) -> bool {
             | Self::Downcast(_, _) => false,
         }
     }
+
+    /// Returns `true` if this is a `Downcast` projection with the given `VariantIdx`.
+    pub fn is_downcast_to(&self, v: VariantIdx) -> bool {
+        matches!(*self, Self::Downcast(_, x) if x == v)
+    }
+
+    /// Returns `true` if this is a `Field` projection with the given index.
+    pub fn is_field_to(&self, f: Field) -> bool {
+        matches!(*self, Self::Field(x, _) if x == f)
+    }
 }
 
 /// Alias for projections as they appear in places, where the base is a place
@@ -2246,8 +2256,12 @@ pub enum BinOp {
     /// The `*` operator (multiplication)
     Mul,
     /// The `/` operator (division)
+    ///
+    /// Division by zero is UB.
     Div,
     /// The `%` operator (modulus)
+    ///
+    /// Using zero as the modulus (second operand) is UB.
     Rem,
     /// The `^` operator (bitwise xor)
     BitXor,
@@ -2256,8 +2270,12 @@ pub enum BinOp {
     /// The `|` operator (bitwise or)
     BitOr,
     /// The `<<` operator (shift left)
+    ///
+    /// The offset is truncated to the size of the first operand before shifting.
     Shl,
     /// The `>>` operator (shift right)
+    ///
+    /// The offset is truncated to the size of the first operand before shifting.
     Shr,
     /// The `==` operator (equality)
     Eq,
@@ -2752,11 +2770,14 @@ pub(crate) fn variant(
 TrivialTypeFoldableAndLiftImpls! { ProjectionKind, }
 
 impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        UserTypeProjection {
-            base: self.base.fold_with(folder),
-            projs: self.projs.fold_with(folder),
-        }
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        Ok(UserTypeProjection {
+            base: self.base.try_fold_with(folder)?,
+            projs: self.projs.try_fold_with(folder)?,
+        })
     }
 
     fn super_visit_with<Vs: TypeVisitor<'tcx>>(
index b7201f7acf392dac6567e4d4ba7d6e69298b467c..ad8b9d323eed584be331cc999292a64f044d9208 100644 (file)
 }
 
 impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         use crate::mir::TerminatorKind::*;
 
         let kind = match self.kind {
             Goto { target } => Goto { target },
             SwitchInt { discr, switch_ty, targets } => SwitchInt {
-                discr: discr.fold_with(folder),
-                switch_ty: switch_ty.fold_with(folder),
+                discr: discr.try_fold_with(folder)?,
+                switch_ty: switch_ty.try_fold_with(folder)?,
                 targets,
             },
             Drop { place, target, unwind } => {
-                Drop { place: place.fold_with(folder), target, unwind }
+                Drop { place: place.try_fold_with(folder)?, target, unwind }
             }
             DropAndReplace { place, value, target, unwind } => DropAndReplace {
-                place: place.fold_with(folder),
-                value: value.fold_with(folder),
+                place: place.try_fold_with(folder)?,
+                value: value.try_fold_with(folder)?,
                 target,
                 unwind,
             },
             Yield { value, resume, resume_arg, drop } => Yield {
-                value: value.fold_with(folder),
+                value: value.try_fold_with(folder)?,
                 resume,
-                resume_arg: resume_arg.fold_with(folder),
+                resume_arg: resume_arg.try_fold_with(folder)?,
                 drop,
             },
             Call { func, args, destination, cleanup, from_hir_call, fn_span } => {
-                let dest = destination.map(|(loc, dest)| (loc.fold_with(folder), dest));
+                let dest = destination
+                    .map(|(loc, dest)| (loc.try_fold_with(folder).map(|loc| (loc, dest))))
+                    .transpose()?;
 
                 Call {
-                    func: func.fold_with(folder),
-                    args: args.fold_with(folder),
+                    func: func.try_fold_with(folder)?,
+                    args: args.try_fold_with(folder)?,
                     destination: dest,
                     cleanup,
                     from_hir_call,
@@ -56,16 +61,19 @@ fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
             Assert { cond, expected, msg, target, cleanup } => {
                 use AssertKind::*;
                 let msg = match msg {
-                    BoundsCheck { len, index } => {
-                        BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder) }
+                    BoundsCheck { len, index } => BoundsCheck {
+                        len: len.try_fold_with(folder)?,
+                        index: index.try_fold_with(folder)?,
+                    },
+                    Overflow(op, l, r) => {
+                        Overflow(op, l.try_fold_with(folder)?, r.try_fold_with(folder)?)
                     }
-                    Overflow(op, l, r) => Overflow(op, l.fold_with(folder), r.fold_with(folder)),
-                    OverflowNeg(op) => OverflowNeg(op.fold_with(folder)),
-                    DivisionByZero(op) => DivisionByZero(op.fold_with(folder)),
-                    RemainderByZero(op) => RemainderByZero(op.fold_with(folder)),
+                    OverflowNeg(op) => OverflowNeg(op.try_fold_with(folder)?),
+                    DivisionByZero(op) => DivisionByZero(op.try_fold_with(folder)?),
+                    RemainderByZero(op) => RemainderByZero(op.try_fold_with(folder)?),
                     ResumedAfterReturn(_) | ResumedAfterPanic(_) => msg,
                 };
-                Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup }
+                Assert { cond: cond.try_fold_with(folder)?, expected, msg, target, cleanup }
             }
             GeneratorDrop => GeneratorDrop,
             Resume => Resume,
@@ -78,13 +86,13 @@ fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
             FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
             InlineAsm { template, operands, options, line_spans, destination } => InlineAsm {
                 template,
-                operands: operands.fold_with(folder),
+                operands: operands.try_fold_with(folder)?,
                 options,
                 line_spans,
                 destination,
             },
         };
-        Terminator { source_info: self.source_info, kind }
+        Ok(Terminator { source_info: self.source_info, kind })
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -140,8 +148,8 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
-        self
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
+        Ok(self)
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
@@ -150,8 +158,14 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::Br
 }
 
 impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        Place { local: self.local.fold_with(folder), projection: self.projection.fold_with(folder) }
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        Ok(Place {
+            local: self.local.try_fold_with(folder)?,
+            projection: self.projection.try_fold_with(folder)?,
+        })
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -161,7 +175,10 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         ty::util::fold_list(self, folder, |tcx, v| tcx.intern_place_elems(v))
     }
 
@@ -171,47 +188,57 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         use crate::mir::Rvalue::*;
-        match self {
-            Use(op) => Use(op.fold_with(folder)),
-            Repeat(op, len) => Repeat(op.fold_with(folder), len.fold_with(folder)),
-            ThreadLocalRef(did) => ThreadLocalRef(did.fold_with(folder)),
-            Ref(region, bk, place) => Ref(region.fold_with(folder), bk, place.fold_with(folder)),
-            AddressOf(mutability, place) => AddressOf(mutability, place.fold_with(folder)),
-            Len(place) => Len(place.fold_with(folder)),
-            Cast(kind, op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)),
-            BinaryOp(op, box (rhs, lhs)) => {
-                BinaryOp(op, Box::new((rhs.fold_with(folder), lhs.fold_with(folder))))
+        Ok(match self {
+            Use(op) => Use(op.try_fold_with(folder)?),
+            Repeat(op, len) => Repeat(op.try_fold_with(folder)?, len.try_fold_with(folder)?),
+            ThreadLocalRef(did) => ThreadLocalRef(did.try_fold_with(folder)?),
+            Ref(region, bk, place) => {
+                Ref(region.try_fold_with(folder)?, bk, place.try_fold_with(folder)?)
             }
-            CheckedBinaryOp(op, box (rhs, lhs)) => {
-                CheckedBinaryOp(op, Box::new((rhs.fold_with(folder), lhs.fold_with(folder))))
+            AddressOf(mutability, place) => AddressOf(mutability, place.try_fold_with(folder)?),
+            Len(place) => Len(place.try_fold_with(folder)?),
+            Cast(kind, op, ty) => Cast(kind, op.try_fold_with(folder)?, ty.try_fold_with(folder)?),
+            BinaryOp(op, box (rhs, lhs)) => {
+                BinaryOp(op, Box::new((rhs.try_fold_with(folder)?, lhs.try_fold_with(folder)?)))
             }
-            UnaryOp(op, val) => UnaryOp(op, val.fold_with(folder)),
-            Discriminant(place) => Discriminant(place.fold_with(folder)),
-            NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)),
+            CheckedBinaryOp(op, box (rhs, lhs)) => CheckedBinaryOp(
+                op,
+                Box::new((rhs.try_fold_with(folder)?, lhs.try_fold_with(folder)?)),
+            ),
+            UnaryOp(op, val) => UnaryOp(op, val.try_fold_with(folder)?),
+            Discriminant(place) => Discriminant(place.try_fold_with(folder)?),
+            NullaryOp(op, ty) => NullaryOp(op, ty.try_fold_with(folder)?),
             Aggregate(kind, fields) => {
-                let kind = kind.map_id(|kind| match kind {
-                    AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
-                    AggregateKind::Tuple => AggregateKind::Tuple,
-                    AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt(
-                        def,
-                        v,
-                        substs.fold_with(folder),
-                        user_ty.fold_with(folder),
-                        n,
-                    ),
-                    AggregateKind::Closure(id, substs) => {
-                        AggregateKind::Closure(id, substs.fold_with(folder))
-                    }
-                    AggregateKind::Generator(id, substs, movablity) => {
-                        AggregateKind::Generator(id, substs.fold_with(folder), movablity)
-                    }
-                });
-                Aggregate(kind, fields.fold_with(folder))
+                let kind = kind.try_map_id(|kind| {
+                    Ok(match kind {
+                        AggregateKind::Array(ty) => AggregateKind::Array(ty.try_fold_with(folder)?),
+                        AggregateKind::Tuple => AggregateKind::Tuple,
+                        AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt(
+                            def,
+                            v,
+                            substs.try_fold_with(folder)?,
+                            user_ty.try_fold_with(folder)?,
+                            n,
+                        ),
+                        AggregateKind::Closure(id, substs) => {
+                            AggregateKind::Closure(id, substs.try_fold_with(folder)?)
+                        }
+                        AggregateKind::Generator(id, substs, movablity) => {
+                            AggregateKind::Generator(id, substs.try_fold_with(folder)?, movablity)
+                        }
+                    })
+                })?;
+                Aggregate(kind, fields.try_fold_with(folder)?)
             }
-            ShallowInitBox(op, ty) => ShallowInitBox(op.fold_with(folder), ty.fold_with(folder)),
-        }
+            ShallowInitBox(op, ty) => {
+                ShallowInitBox(op.try_fold_with(folder)?, ty.try_fold_with(folder)?)
+            }
+        })
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -265,12 +292,15 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        match self {
-            Operand::Copy(place) => Operand::Copy(place.fold_with(folder)),
-            Operand::Move(place) => Operand::Move(place.fold_with(folder)),
-            Operand::Constant(c) => Operand::Constant(c.fold_with(folder)),
-        }
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        Ok(match self {
+            Operand::Copy(place) => Operand::Copy(place.try_fold_with(folder)?),
+            Operand::Move(place) => Operand::Move(place.try_fold_with(folder)?),
+            Operand::Constant(c) => Operand::Constant(c.try_fold_with(folder)?),
+        })
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -282,19 +312,22 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         use crate::mir::ProjectionElem::*;
 
-        match self {
+        Ok(match self {
             Deref => Deref,
-            Field(f, ty) => Field(f, ty.fold_with(folder)),
-            Index(v) => Index(v.fold_with(folder)),
+            Field(f, ty) => Field(f, ty.try_fold_with(folder)?),
+            Index(v) => Index(v.try_fold_with(folder)?),
             Downcast(symbol, variantidx) => Downcast(symbol, variantidx),
             ConstantIndex { offset, min_length, from_end } => {
                 ConstantIndex { offset, min_length, from_end }
             }
             Subslice { from, to, from_end } => Subslice { from, to, from_end },
-        }
+        })
     }
 
     fn super_visit_with<Vs: TypeVisitor<'tcx>>(
@@ -312,8 +345,8 @@ fn super_visit_with<Vs: TypeVisitor<'tcx>>(
 }
 
 impl<'tcx> TypeFoldable<'tcx> for Field {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
-        self
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
+        Ok(self)
     }
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
         ControlFlow::CONTINUE
@@ -321,8 +354,8 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::Br
 }
 
 impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
-        self
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
+        Ok(self)
     }
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
         ControlFlow::CONTINUE
@@ -330,8 +363,8 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::Br
 }
 
 impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
-        self
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
+        Ok(self)
     }
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
         ControlFlow::CONTINUE
@@ -339,12 +372,15 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::Br
 }
 
 impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        Constant {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        Ok(Constant {
             span: self.span,
-            user_ty: self.user_ty.fold_with(folder),
-            literal: self.literal.fold_with(folder),
-        }
+            user_ty: self.user_ty.try_fold_with(folder)?,
+            literal: self.literal.try_fold_with(folder)?,
+        })
     }
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
         self.literal.visit_with(visitor)?;
@@ -354,14 +390,17 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 
 impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
     #[inline(always)]
-    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        folder.fold_mir_const(self)
+    fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        folder.try_fold_mir_const(self)
     }
 
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         match self {
-            ConstantKind::Ty(c) => ConstantKind::Ty(c.fold_with(folder)),
-            ConstantKind::Val(v, t) => ConstantKind::Val(v, t.fold_with(folder)),
+            ConstantKind::Ty(c) => Ok(ConstantKind::Ty(c.try_fold_with(folder)?)),
+            ConstantKind::Val(v, t) => Ok(ConstantKind::Val(v, t.try_fold_with(folder)?)),
         }
     }
 
index fda7ebe1a49c15c2697ae150b964124af43a019e..4c23ab49fa29f71efd91a9e12c482d41bf0ada32 100644 (file)
@@ -1004,8 +1004,12 @@ fn process_projection_elem(
 
                     if new_local == local { None } else { Some(PlaceElem::Index(new_local)) }
                 }
+                PlaceElem::Field(field, ty) => {
+                    let mut new_ty = ty;
+                    self.visit_ty(&mut new_ty, TyContext::Location(location));
+                    if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None }
+                }
                 PlaceElem::Deref
-                | PlaceElem::Field(..)
                 | PlaceElem::ConstantIndex { .. }
                 | PlaceElem::Subslice { .. }
                 | PlaceElem::Downcast(..) => None,
index 3e287e11ed1abb91f663ab271e26976202c201d3..8667a6bea11f664eae6186f0ebb5fc4ca923d84a 100644 (file)
         desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id.to_def_id()) }
     }
 
-    query get_lib_features(_: ()) -> LibFeatures {
+    query lib_features(_: ()) -> LibFeatures {
         storage(ArenaCacheSelector<'tcx>)
-        eval_always
         desc { "calculating the lib features map" }
     }
     query defined_lib_features(_: CrateNum)
 
     query upvars_mentioned(def_id: DefId) -> Option<&'tcx FxIndexMap<hir::HirId, hir::Upvar>> {
         desc { |tcx| "collecting upvars mentioned in `{}`", tcx.def_path_str(def_id) }
-        eval_always
     }
     query maybe_unused_trait_import(def_id: LocalDefId) -> bool {
         desc { |tcx| "maybe_unused_trait_import for `{}`", tcx.def_path_str(def_id.to_def_id()) }
         desc { "normalizing `{:?}`", goal }
     }
 
+    // FIXME: Implement `normalize_generic_arg_after_erasing_regions` and
+    // `normalize_mir_const_after_erasing_regions` in terms of
+    // `try_normalize_generic_arg_after_erasing_regions` and
+    // `try_normalize_mir_const_after_erasing_regions`, respectively.
+
     /// Do not call this query directly: invoke `normalize_erasing_regions` instead.
     query normalize_generic_arg_after_erasing_regions(
         goal: ParamEnvAnd<'tcx, GenericArg<'tcx>>
         desc { "normalizing `{}`", goal.value }
     }
 
+    /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead.
+    query try_normalize_generic_arg_after_erasing_regions(
+        goal: ParamEnvAnd<'tcx, GenericArg<'tcx>>
+    ) -> Result<GenericArg<'tcx>, NoSolution> {
+        desc { "normalizing `{}`", goal.value }
+    }
+
+    /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead.
+    query try_normalize_mir_const_after_erasing_regions(
+        goal: ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>
+    ) -> Result<mir::ConstantKind<'tcx>, NoSolution> {
+        desc { "normalizing `{}`", goal.value }
+    }
+
     query implied_outlives_bounds(
         goal: CanonicalTyGoal<'tcx>
     ) -> Result<
index 49071e7995b4cd972de134c8c1d1958277c50b54..49a64cb246ad0dd09af4b58d55e69b0cfcfd41d2 100644 (file)
@@ -7,6 +7,7 @@
 pub mod select;
 pub mod specialization_graph;
 mod structural_impls;
+pub mod util;
 
 use crate::infer::canonical::Canonical;
 use crate::thir::abstract_const::NotConstEvaluatable;
diff --git a/compiler/rustc_middle/src/traits/util.rs b/compiler/rustc_middle/src/traits/util.rs
new file mode 100644 (file)
index 0000000..3490c68
--- /dev/null
@@ -0,0 +1,49 @@
+use rustc_data_structures::stable_set::FxHashSet;
+
+use crate::ty::{PolyTraitRef, TyCtxt};
+
+/// Given a PolyTraitRef, get the PolyTraitRefs of the trait's (transitive) supertraits.
+///
+/// A simplfied version of the same function at `rustc_infer::traits::util::supertraits`.
+pub fn supertraits<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: PolyTraitRef<'tcx>,
+) -> impl Iterator<Item = PolyTraitRef<'tcx>> {
+    Elaborator { tcx, visited: FxHashSet::from_iter([trait_ref]), stack: vec![trait_ref] }
+}
+
+struct Elaborator<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    visited: FxHashSet<PolyTraitRef<'tcx>>,
+    stack: Vec<PolyTraitRef<'tcx>>,
+}
+
+impl<'tcx> Elaborator<'tcx> {
+    fn elaborate(&mut self, trait_ref: PolyTraitRef<'tcx>) {
+        let supertrait_refs = self
+            .tcx
+            .super_predicates_of(trait_ref.def_id())
+            .predicates
+            .into_iter()
+            .flat_map(|(pred, _)| {
+                pred.subst_supertrait(self.tcx, &trait_ref).to_opt_poly_trait_ref()
+            })
+            .map(|t| t.value)
+            .filter(|supertrait_ref| self.visited.insert(*supertrait_ref));
+
+        self.stack.extend(supertrait_refs);
+    }
+}
+
+impl<'tcx> Iterator for Elaborator<'tcx> {
+    type Item = PolyTraitRef<'tcx>;
+
+    fn next(&mut self) -> Option<PolyTraitRef<'tcx>> {
+        if let Some(trait_ref) = self.stack.pop() {
+            self.elaborate(trait_ref);
+            Some(trait_ref)
+        } else {
+            None
+        }
+    }
+}
index 44f741c5df1a2b37b6025dae3af9c5564c7b6b93..771ce2eb884afbf7e91f0647de6eb67bf8de2435 100644 (file)
@@ -7,7 +7,7 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_query_system::ich::StableHashingContext;
@@ -64,6 +64,30 @@ pub struct AdtFlags: u32 {
 /// Moreover, Rust only allows recursive data types through indirection.
 ///
 /// [adt]: https://en.wikipedia.org/wiki/Algebraic_data_type
+///
+/// # Recursive types
+///
+/// It may seem impossible to represent recursive types using [`Ty`],
+/// since [`TyKind::Adt`] includes [`AdtDef`], which includes its fields,
+/// creating a cycle. However, `AdtDef` does not actually include the *types*
+/// of its fields; it includes just their [`DefId`]s.
+///
+/// [`TyKind::Adt`]: ty::TyKind::Adt
+///
+/// For example, the following type:
+///
+/// ```
+/// struct S { x: Box<S> }
+/// ```
+///
+/// is essentially represented with [`Ty`] as the following pseudocode:
+///
+/// ```
+/// struct S { x }
+/// ```
+///
+/// where `x` here represents the `DefId` of `S.x`. Then, the `DefId`
+/// can be used with [`TyCtxt::type_of()`] to get the type of the field.
 pub struct AdtDef {
     /// The `DefId` of the struct, enum or union item.
     pub did: DefId,
@@ -314,6 +338,22 @@ pub fn all_fields(&self) -> impl Iterator<Item = &FieldDef> + Clone {
     /// Whether the ADT lacks fields. Note that this includes uninhabited enums,
     /// e.g., `enum Void {}` is considered payload free as well.
     pub fn is_payloadfree(&self) -> bool {
+        // Treat the ADT as not payload-free if arbitrary_enum_discriminant is used (#88621).
+        // This would disallow the following kind of enum from being casted into integer.
+        // ```
+        // enum Enum {
+        //    Foo() = 1,
+        //    Bar{} = 2,
+        //    Baz = 3,
+        // }
+        // ```
+        if self
+            .variants
+            .iter()
+            .any(|v| matches!(v.discr, VariantDiscr::Explicit(_)) && v.ctor_kind != CtorKind::Const)
+        {
+            return false;
+        }
         self.variants.iter().all(|v| v.fields.is_empty())
     }
 
index 8240273acad4cd89eb1bcabfff4defc8dbf00cf7..275a2128c45564f5f468e6eba57940d7b30fd5f6 100644 (file)
@@ -5,7 +5,6 @@
 use crate::hir::place::Place as HirPlace;
 use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
 use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource};
-use crate::middle;
 use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath, ObjectLifetimeDefault};
 use crate::middle::stability;
 use crate::mir::interpret::{self, Allocation, ConstValue, Scalar};
@@ -1112,7 +1111,11 @@ pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound<u128>, Bound<u12
             };
             debug!("layout_scalar_valid_range: attr={:?}", attr);
             if let Some(
-                &[ast::NestedMetaItem::Literal(ast::Lit { kind: ast::LitKind::Int(a, _), .. })],
+                &[
+                    ast::NestedMetaItem::Literal(ast::Lit {
+                        kind: ast::LitKind::Int(a, _), ..
+                    }),
+                ],
             ) = attr.meta_item_list().as_deref()
             {
                 Bound::Included(a)
@@ -1217,10 +1220,6 @@ pub fn consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool {
         self.sess.consider_optimizing(&cname, msg)
     }
 
-    pub fn lib_features(self) -> &'tcx middle::lib_features::LibFeatures {
-        self.get_lib_features(())
-    }
-
     /// Obtain all lang items of this crate and all dependencies (recursively)
     pub fn lang_items(self) -> &'tcx rustc_hir::lang_items::LanguageItems {
         self.get_lang_items(())
index b14a69892657bcb7bce9c32efc9c9314f5df4b73..bda40a9abb097929f2ad485099873fad97b318e4 100644 (file)
@@ -777,9 +777,7 @@ fn suggest_constraining_opaque_associated_type(
         if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() {
             let opaque_local_def_id = def_id.as_local();
             let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id {
-                let hir = self.hir();
-                let opaque_hir_id = hir.local_def_id_to_hir_id(opaque_local_def_id);
-                match &hir.expect_item(opaque_hir_id).kind {
+                match &self.hir().expect_item(opaque_local_def_id).kind {
                     hir::ItemKind::OpaqueTy(opaque_hir_ty) => opaque_hir_ty,
                     _ => bug!("The HirId comes from a `ty::Opaque`"),
                 }
index e16491dcc90b25eeb62ff3858833d11fbfb406f2..aff485a413226b005226998c8dd6ca99294bbe50 100644 (file)
 ///
 /// To implement this conveniently, use the derive macro located in `rustc_macros`.
 pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self;
-    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        self.super_fold_with(folder)
+    /// Consumers may find this more convenient to use with infallible folders than
+    /// [`try_super_fold_with`][`TypeFoldable::try_super_fold_with`], to which the
+    /// provided default definition delegates.  Implementors **should not** override
+    /// this provided default definition, to ensure that the two methods are coherent
+    /// (provide a definition of `try_super_fold_with` instead).
+    fn super_fold_with<F: TypeFolder<'tcx, Error = !>>(self, folder: &mut F) -> Self {
+        self.try_super_fold_with(folder).into_ok()
+    }
+    /// Consumers may find this more convenient to use with infallible folders than
+    /// [`try_fold_with`][`TypeFoldable::try_fold_with`], to which the provided
+    /// default definition delegates.  Implementors **should not** override this
+    /// provided default definition, to ensure that the two methods are coherent
+    /// (provide a definition of `try_fold_with` instead).
+    fn fold_with<F: TypeFolder<'tcx, Error = !>>(self, folder: &mut F) -> Self {
+        self.try_fold_with(folder).into_ok()
+    }
+
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error>;
+
+    fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        self.try_super_fold_with(folder)
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
@@ -179,8 +200,8 @@ fn still_further_specializable(&self) -> bool {
 }
 
 impl TypeFoldable<'tcx> for hir::Constness {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
-        self
+    fn try_super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
+        Ok(self)
     }
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
         ControlFlow::CONTINUE
@@ -192,37 +213,152 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::Br
 /// default implementation that does an "identity" fold. Within each
 /// identity fold, it should invoke `foo.fold_with(self)` to fold each
 /// sub-item.
+///
+/// If this folder is fallible (and therefore its [`Error`][`TypeFolder::Error`]
+/// associated type is something other than the default, never),
+/// [`FallibleTypeFolder`] should be implemented manually; otherwise,
+/// a blanket implementation of [`FallibleTypeFolder`] will defer to
+/// the infallible methods of this trait to ensure that the two APIs
+/// are coherent.
 pub trait TypeFolder<'tcx>: Sized {
+    type Error = !;
+
     fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
 
     fn fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T>
     where
         T: TypeFoldable<'tcx>,
+        Self: TypeFolder<'tcx, Error = !>,
     {
         t.super_fold_with(self)
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx>
+    where
+        Self: TypeFolder<'tcx, Error = !>,
+    {
         t.super_fold_with(self)
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx>
+    where
+        Self: TypeFolder<'tcx, Error = !>,
+    {
         r.super_fold_with(self)
     }
 
-    fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+    fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx>
+    where
+        Self: TypeFolder<'tcx, Error = !>,
+    {
         c.super_fold_with(self)
     }
 
-    fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
+    fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx>
+    where
+        Self: TypeFolder<'tcx, Error = !>,
+    {
         p.super_fold_with(self)
     }
 
-    fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
+    fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx>
+    where
+        Self: TypeFolder<'tcx, Error = !>,
+    {
         bug!("most type folders should not be folding MIR datastructures: {:?}", c)
     }
 }
 
+/// The `FallibleTypeFolder` trait defines the actual *folding*. There is a
+/// method defined for every foldable type. Each of these has a
+/// default implementation that does an "identity" fold. Within each
+/// identity fold, it should invoke `foo.try_fold_with(self)` to fold each
+/// sub-item.
+///
+/// A blanket implementation of this trait (that defers to the relevant
+/// method of [`TypeFolder`]) is provided for all infallible folders in
+/// order to ensure the two APIs are coherent.
+pub trait FallibleTypeFolder<'tcx>: TypeFolder<'tcx> {
+    fn try_fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Result<Binder<'tcx, T>, Self::Error>
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        t.try_super_fold_with(self)
+    }
+
+    fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+        t.try_super_fold_with(self)
+    }
+
+    fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
+        r.try_super_fold_with(self)
+    }
+
+    fn try_fold_const(
+        &mut self,
+        c: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+        c.try_super_fold_with(self)
+    }
+
+    fn try_fold_predicate(
+        &mut self,
+        p: ty::Predicate<'tcx>,
+    ) -> Result<ty::Predicate<'tcx>, Self::Error> {
+        p.try_super_fold_with(self)
+    }
+
+    fn try_fold_mir_const(
+        &mut self,
+        c: mir::ConstantKind<'tcx>,
+    ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
+        bug!("most type folders should not be folding MIR datastructures: {:?}", c)
+    }
+}
+
+// Blanket implementation of fallible trait for infallible folders
+// delegates to infallible methods to prevent incoherence
+impl<'tcx, F> FallibleTypeFolder<'tcx> for F
+where
+    F: TypeFolder<'tcx, Error = !>,
+{
+    fn try_fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Result<Binder<'tcx, T>, Self::Error>
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        Ok(self.fold_binder(t))
+    }
+
+    fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+        Ok(self.fold_ty(t))
+    }
+
+    fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
+        Ok(self.fold_region(r))
+    }
+
+    fn try_fold_const(
+        &mut self,
+        c: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+        Ok(self.fold_const(c))
+    }
+
+    fn try_fold_predicate(
+        &mut self,
+        p: ty::Predicate<'tcx>,
+    ) -> Result<ty::Predicate<'tcx>, Self::Error> {
+        Ok(self.fold_predicate(p))
+    }
+
+    fn try_fold_mir_const(
+        &mut self,
+        c: mir::ConstantKind<'tcx>,
+    ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
+        Ok(self.fold_mir_const(c))
+    }
+}
+
 pub trait TypeVisitor<'tcx>: Sized {
     type BreakTy = !;
     /// Supplies the `tcx` for an unevaluated anonymous constant in case its default substs
index b87e23af72b702076ea2ea84f8d5b48bf87b6f43..02811b2491c15fd4d579546b4d0a6f1d0c400c92 100644 (file)
@@ -1,5 +1,6 @@
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
+use crate::ty::normalize_erasing_regions::NormalizationError;
 use crate::ty::subst::Subst;
 use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable};
 use rustc_ast as ast;
@@ -199,6 +200,7 @@ fn to_int_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
 pub enum LayoutError<'tcx> {
     Unknown(Ty<'tcx>),
     SizeOverflow(Ty<'tcx>),
+    NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>),
 }
 
 impl<'tcx> fmt::Display for LayoutError<'tcx> {
@@ -208,16 +210,24 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             LayoutError::SizeOverflow(ty) => {
                 write!(f, "values of the type `{}` are too big for the current architecture", ty)
             }
+            LayoutError::NormalizationFailure(t, e) => write!(
+                f,
+                "unable to determine layout for `{}` because `{}` cannot be normalized",
+                t,
+                e.get_type_for_failure()
+            ),
         }
     }
 }
 
+#[instrument(skip(tcx, query), level = "debug")]
 fn layout_of<'tcx>(
     tcx: TyCtxt<'tcx>,
     query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
 ) -> Result<TyAndLayout<'tcx>, LayoutError<'tcx>> {
     ty::tls::with_related_context(tcx, move |icx| {
         let (param_env, ty) = query.into_parts();
+        debug!(?ty);
 
         if !tcx.recursion_limit().value_within_limit(icx.layout_depth) {
             tcx.sess.fatal(&format!("overflow representing the type `{}`", ty));
@@ -229,7 +239,18 @@ fn layout_of<'tcx>(
         ty::tls::enter_context(&icx, |_| {
             let param_env = param_env.with_reveal_all_normalized(tcx);
             let unnormalized_ty = ty;
-            let ty = tcx.normalize_erasing_regions(param_env, ty);
+
+            // FIXME: We might want to have two different versions of `layout_of`:
+            // One that can be called after typecheck has completed and can use
+            // `normalize_erasing_regions` here and another one that can be called
+            // before typecheck has completed and uses `try_normalize_erasing_regions`.
+            let ty = match tcx.try_normalize_erasing_regions(param_env, ty) {
+                Ok(t) => t,
+                Err(normalization_error) => {
+                    return Err(LayoutError::NormalizationFailure(ty, normalization_error));
+                }
+            };
+
             if ty != unnormalized_ty {
                 // Ensure this layout is also cached for the normalized type.
                 return tcx.layout_of(param_env.and(ty));
@@ -512,7 +533,7 @@ fn univariant_uninterned(
             }
         }
 
-        if sized && fields.iter().any(|f| f.abi.is_uninhabited()) {
+        if fields.iter().any(|f| f.abi.is_uninhabited()) {
             abi = Abi::Uninhabited;
         }
 
index 673733faa766ff5846c02075833be4fba79c0cf7..7e1804673df2ce479bcf04075448db20dbcd9081 100644 (file)
@@ -9,7 +9,7 @@
 //!
 //! ["The `ty` module: representing types"]: https://rustc-dev-guide.rust-lang.org/ty.html
 
-pub use self::fold::{TypeFoldable, TypeFolder, TypeVisitor};
+pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeVisitor};
 pub use self::AssocItemContainer::*;
 pub use self::BorrowKind::*;
 pub use self::IntVarValue::*;
@@ -1260,8 +1260,14 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
 }
 
 impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> {
-    fn super_fold_with<F: ty::fold::TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        ParamEnv::new(self.caller_bounds().fold_with(folder), self.reveal().fold_with(folder))
+    fn try_super_fold_with<F: ty::fold::FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        Ok(ParamEnv::new(
+            self.caller_bounds().try_fold_with(folder)?,
+            self.reveal().try_fold_with(folder)?,
+        ))
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -1705,7 +1711,7 @@ pub fn inhibit_union_abi_opt(&self) -> bool {
 
 impl<'tcx> FieldDef {
     /// Returns the type of this field. The resulting type is not normalized. The `subst` is
-    /// typically obtained via the second field of `TyKind::AdtDef`.
+    /// typically obtained via the second field of [`TyKind::Adt`].
     pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> {
         tcx.type_of(self.did).subst(tcx, subst)
     }
index 11399506b96e427373baa68ef7b1b9c53598f240..c0e1360640fd2647227c8a9946ef0d0d1eecdfbc 100644 (file)
@@ -8,10 +8,28 @@
 //! or constant found within. (This underlying query is what is cached.)
 
 use crate::mir;
-use crate::ty::fold::{TypeFoldable, TypeFolder};
+use crate::traits::query::NoSolution;
+use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder};
 use crate::ty::subst::{Subst, SubstsRef};
 use crate::ty::{self, Ty, TyCtxt};
 
+#[derive(Debug, Copy, Clone, HashStable, TyEncodable, TyDecodable)]
+pub enum NormalizationError<'tcx> {
+    Type(Ty<'tcx>),
+    Const(ty::Const<'tcx>),
+    ConstantKind(mir::ConstantKind<'tcx>),
+}
+
+impl<'tcx> NormalizationError<'tcx> {
+    pub fn get_type_for_failure(&self) -> String {
+        match self {
+            NormalizationError::Type(t) => format!("{}", t),
+            NormalizationError::Const(c) => format!("{}", c),
+            NormalizationError::ConstantKind(ck) => format!("{}", ck),
+        }
+    }
+}
+
 impl<'tcx> TyCtxt<'tcx> {
     /// Erase the regions in `value` and then fully normalize all the
     /// types found within. The result will also have regions erased.
@@ -32,6 +50,8 @@ pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value:
         // Erase first before we do the real query -- this keeps the
         // cache from being too polluted.
         let value = self.erase_regions(value);
+        debug!(?value);
+
         if !value.has_projections() {
             value
         } else {
@@ -39,6 +59,39 @@ pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value:
         }
     }
 
+    /// Tries to erase the regions in `value` and then fully normalize all the
+    /// types found within. The result will also have regions erased.
+    ///
+    /// Contrary to `normalize_erasing_regions` this function does not assume that normalization
+    /// succeeds.
+    pub fn try_normalize_erasing_regions<T>(
+        self,
+        param_env: ty::ParamEnv<'tcx>,
+        value: T,
+    ) -> Result<T, NormalizationError<'tcx>>
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        debug!(
+            "try_normalize_erasing_regions::<{}>(value={:?}, param_env={:?})",
+            std::any::type_name::<T>(),
+            value,
+            param_env,
+        );
+
+        // Erase first before we do the real query -- this keeps the
+        // cache from being too polluted.
+        let value = self.erase_regions(value);
+        debug!(?value);
+
+        if !value.has_projections() {
+            Ok(value)
+        } else {
+            let mut folder = TryNormalizeAfterErasingRegionsFolder::new(self, param_env);
+            value.try_fold_with(&mut folder)
+        }
+    }
+
     /// If you have a `Binder<'tcx, T>`, you can do this to strip out the
     /// late-bound regions and then normalize the result, yielding up
     /// a `T` (with regions erased). This is appropriate when the
@@ -89,11 +142,14 @@ struct NormalizeAfterErasingRegionsFolder<'tcx> {
 }
 
 impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> {
+    #[instrument(skip(self), level = "debug")]
     fn normalize_generic_arg_after_erasing_regions(
         &self,
         arg: ty::GenericArg<'tcx>,
     ) -> ty::GenericArg<'tcx> {
         let arg = self.param_env.and(arg);
+        debug!(?arg);
+
         self.tcx.normalize_generic_arg_after_erasing_regions(arg)
     }
 }
@@ -118,3 +174,64 @@ fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'t
         self.tcx.normalize_mir_const_after_erasing_regions(arg)
     }
 }
+
+struct TryNormalizeAfterErasingRegionsFolder<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+}
+
+impl<'tcx> TryNormalizeAfterErasingRegionsFolder<'tcx> {
+    fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
+        TryNormalizeAfterErasingRegionsFolder { tcx, param_env }
+    }
+
+    #[instrument(skip(self), level = "debug")]
+    fn try_normalize_generic_arg_after_erasing_regions(
+        &self,
+        arg: ty::GenericArg<'tcx>,
+    ) -> Result<ty::GenericArg<'tcx>, NoSolution> {
+        let arg = self.param_env.and(arg);
+        debug!(?arg);
+
+        self.tcx.try_normalize_generic_arg_after_erasing_regions(arg)
+    }
+}
+
+impl TypeFolder<'tcx> for TryNormalizeAfterErasingRegionsFolder<'tcx> {
+    type Error = NormalizationError<'tcx>;
+
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+}
+
+impl FallibleTypeFolder<'tcx> for TryNormalizeAfterErasingRegionsFolder<'tcx> {
+    fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+        match self.try_normalize_generic_arg_after_erasing_regions(ty.into()) {
+            Ok(t) => Ok(t.expect_ty()),
+            Err(_) => Err(NormalizationError::Type(ty)),
+        }
+    }
+
+    fn try_fold_const(
+        &mut self,
+        c: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+        match self.try_normalize_generic_arg_after_erasing_regions(c.into()) {
+            Ok(t) => Ok(t.expect_const()),
+            Err(_) => Err(NormalizationError::Const(*c)),
+        }
+    }
+
+    fn try_fold_mir_const(
+        &mut self,
+        c: mir::ConstantKind<'tcx>,
+    ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
+        // FIXME: This *probably* needs canonicalization too!
+        let arg = self.param_env.and(c);
+        match self.tcx.try_normalize_mir_const_after_erasing_regions(arg) {
+            Ok(c) => Ok(c),
+            Err(_) => Err(NormalizationError::ConstantKind(c)),
+        }
+    }
+}
index 3846cf19d915b339eaa7fb729950fccbb432f62f..175295b3199e8e2e2c1bf0cc5115ba53133d8657 100644 (file)
@@ -643,81 +643,8 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
                         }
                         return Ok(self);
                     }
-                    // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
-                    // by looking up the projections associated with the def_id.
-                    let bounds = self.tcx().explicit_item_bounds(def_id);
-
-                    let mut first = true;
-                    let mut is_sized = false;
-                    let mut is_future = false;
-                    let mut future_output_ty = None;
-
-                    p!("impl");
-                    for (predicate, _) in bounds {
-                        let predicate = predicate.subst(self.tcx(), substs);
-                        let bound_predicate = predicate.kind();
-
-                        match bound_predicate.skip_binder() {
-                            ty::PredicateKind::Projection(projection_predicate) => {
-                                let Some(future_trait) = self.tcx().lang_items().future_trait() else { continue };
-                                let future_output_def_id =
-                                    self.tcx().associated_item_def_ids(future_trait)[0];
-
-                                if projection_predicate.projection_ty.item_def_id
-                                    == future_output_def_id
-                                {
-                                    // We don't account for multiple `Future::Output = Ty` contraints.
-                                    is_future = true;
-                                    future_output_ty = Some(projection_predicate.ty);
-                                }
-                            }
-                            ty::PredicateKind::Trait(pred) => {
-                                let trait_ref = bound_predicate.rebind(pred.trait_ref);
-                                // Don't print +Sized, but rather +?Sized if absent.
-                                if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait()
-                                {
-                                    is_sized = true;
-                                    continue;
-                                }
-
-                                if Some(trait_ref.def_id())
-                                    == self.tcx().lang_items().future_trait()
-                                {
-                                    is_future = true;
-                                    continue;
-                                }
-
-                                p!(
-                                    write("{}", if first { " " } else { " + " }),
-                                    print(trait_ref.print_only_trait_path())
-                                );
-
-                                first = false;
-                            }
-                            _ => {}
-                        }
-                    }
-
-                    if is_future {
-                        p!(write("{}Future", if first { " " } else { " + " }));
-                        first = false;
 
-                        if let Some(future_output_ty) = future_output_ty {
-                            // Don't print projection types, which we (unfortunately) see often
-                            // in the error outputs involving async blocks.
-                            if !matches!(future_output_ty.kind(), ty::Projection(_)) {
-                                p!("<Output = ", print(future_output_ty), ">");
-                            }
-                        }
-                    }
-
-                    if !is_sized {
-                        p!(write("{}?Sized", if first { " " } else { " + " }));
-                    } else if first {
-                        p!(" Sized");
-                    }
-
-                    Ok(self)
+                    self.pretty_print_opaque_impl_type(def_id, substs)
                 });
             }
             ty::Str => p!("str"),
@@ -826,6 +753,225 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
         Ok(self)
     }
 
+    fn pretty_print_opaque_impl_type(
+        mut self,
+        def_id: DefId,
+        substs: &'tcx ty::List<ty::GenericArg<'tcx>>,
+    ) -> Result<Self::Type, Self::Error> {
+        define_scoped_cx!(self);
+
+        // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
+        // by looking up the projections associated with the def_id.
+        let bounds = self.tcx().explicit_item_bounds(def_id);
+
+        let mut traits = BTreeMap::new();
+        let mut fn_traits = BTreeMap::new();
+        let mut is_sized = false;
+
+        for (predicate, _) in bounds {
+            let predicate = predicate.subst(self.tcx(), substs);
+            let bound_predicate = predicate.kind();
+
+            match bound_predicate.skip_binder() {
+                ty::PredicateKind::Trait(pred) => {
+                    let trait_ref = bound_predicate.rebind(pred.trait_ref);
+
+                    // Don't print + Sized, but rather + ?Sized if absent.
+                    if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() {
+                        is_sized = true;
+                        continue;
+                    }
+
+                    self.insert_trait_and_projection(trait_ref, None, &mut traits, &mut fn_traits);
+                }
+                ty::PredicateKind::Projection(pred) => {
+                    let proj_ref = bound_predicate.rebind(pred);
+                    let trait_ref = proj_ref.required_poly_trait_ref(self.tcx());
+
+                    // Projection type entry -- the def-id for naming, and the ty.
+                    let proj_ty = (proj_ref.projection_def_id(), proj_ref.ty());
+
+                    self.insert_trait_and_projection(
+                        trait_ref,
+                        Some(proj_ty),
+                        &mut traits,
+                        &mut fn_traits,
+                    );
+                }
+                _ => {}
+            }
+        }
+
+        let mut first = true;
+        // Insert parenthesis around (Fn(A, B) -> C) if the opaque ty has more than one other trait
+        let paren_needed = fn_traits.len() > 1 || traits.len() > 0 || !is_sized;
+
+        p!("impl");
+
+        for (fn_once_trait_ref, entry) in fn_traits {
+            // Get the (single) generic ty (the args) of this FnOnce trait ref.
+            let generics = self.generic_args_to_print(
+                self.tcx().generics_of(fn_once_trait_ref.def_id()),
+                fn_once_trait_ref.skip_binder().substs,
+            );
+
+            match (entry.return_ty, generics[0].expect_ty()) {
+                // We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded
+                // a return type.
+                (Some(return_ty), arg_tys) if matches!(arg_tys.kind(), ty::Tuple(_)) => {
+                    let name = if entry.fn_trait_ref.is_some() {
+                        "Fn"
+                    } else if entry.fn_mut_trait_ref.is_some() {
+                        "FnMut"
+                    } else {
+                        "FnOnce"
+                    };
+
+                    p!(
+                        write("{}", if first { " " } else { " + " }),
+                        write("{}{}(", if paren_needed { "(" } else { "" }, name)
+                    );
+
+                    for (idx, ty) in arg_tys.tuple_fields().enumerate() {
+                        if idx > 0 {
+                            p!(", ");
+                        }
+                        p!(print(ty));
+                    }
+
+                    p!(")");
+                    if !return_ty.skip_binder().is_unit() {
+                        p!("-> ", print(return_ty));
+                    }
+                    p!(write("{}", if paren_needed { ")" } else { "" }));
+
+                    first = false;
+                }
+                // If we got here, we can't print as a `impl Fn(A, B) -> C`. Just record the
+                // trait_refs we collected in the OpaqueFnEntry as normal trait refs.
+                _ => {
+                    if entry.has_fn_once {
+                        traits.entry(fn_once_trait_ref).or_default().extend(
+                            // Group the return ty with its def id, if we had one.
+                            entry
+                                .return_ty
+                                .map(|ty| (self.tcx().lang_items().fn_once_output().unwrap(), ty)),
+                        );
+                    }
+                    if let Some(trait_ref) = entry.fn_mut_trait_ref {
+                        traits.entry(trait_ref).or_default();
+                    }
+                    if let Some(trait_ref) = entry.fn_trait_ref {
+                        traits.entry(trait_ref).or_default();
+                    }
+                }
+            }
+        }
+
+        // Print the rest of the trait types (that aren't Fn* family of traits)
+        for (trait_ref, assoc_items) in traits {
+            p!(
+                write("{}", if first { " " } else { " + " }),
+                print(trait_ref.skip_binder().print_only_trait_name())
+            );
+
+            let generics = self.generic_args_to_print(
+                self.tcx().generics_of(trait_ref.def_id()),
+                trait_ref.skip_binder().substs,
+            );
+
+            if !generics.is_empty() || !assoc_items.is_empty() {
+                p!("<");
+                let mut first = true;
+
+                for ty in generics {
+                    if !first {
+                        p!(", ");
+                    }
+                    p!(print(trait_ref.rebind(*ty)));
+                    first = false;
+                }
+
+                for (assoc_item_def_id, ty) in assoc_items {
+                    if !first {
+                        p!(", ");
+                    }
+                    p!(write("{} = ", self.tcx().associated_item(assoc_item_def_id).ident));
+
+                    // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks
+                    match ty.skip_binder().kind() {
+                        ty::Projection(ty::ProjectionTy { item_def_id, .. })
+                            if Some(*item_def_id) == self.tcx().lang_items().generator_return() =>
+                        {
+                            p!("[async output]")
+                        }
+                        _ => {
+                            p!(print(ty))
+                        }
+                    }
+
+                    first = false;
+                }
+
+                p!(">");
+            }
+
+            first = false;
+        }
+
+        if !is_sized {
+            p!(write("{}?Sized", if first { " " } else { " + " }));
+        } else if first {
+            p!(" Sized");
+        }
+
+        Ok(self)
+    }
+
+    /// Insert the trait ref and optionally a projection type associated with it into either the
+    /// traits map or fn_traits map, depending on if the trait is in the Fn* family of traits.
+    fn insert_trait_and_projection(
+        &mut self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        proj_ty: Option<(DefId, ty::Binder<'tcx, Ty<'tcx>>)>,
+        traits: &mut BTreeMap<ty::PolyTraitRef<'tcx>, BTreeMap<DefId, ty::Binder<'tcx, Ty<'tcx>>>>,
+        fn_traits: &mut BTreeMap<ty::PolyTraitRef<'tcx>, OpaqueFnEntry<'tcx>>,
+    ) {
+        let trait_def_id = trait_ref.def_id();
+
+        // If our trait_ref is FnOnce or any of its children, project it onto the parent FnOnce
+        // super-trait ref and record it there.
+        if let Some(fn_once_trait) = self.tcx().lang_items().fn_once_trait() {
+            // If we have a FnOnce, then insert it into
+            if trait_def_id == fn_once_trait {
+                let entry = fn_traits.entry(trait_ref).or_default();
+                // Optionally insert the return_ty as well.
+                if let Some((_, ty)) = proj_ty {
+                    entry.return_ty = Some(ty);
+                }
+                entry.has_fn_once = true;
+                return;
+            } else if Some(trait_def_id) == self.tcx().lang_items().fn_mut_trait() {
+                let super_trait_ref = crate::traits::util::supertraits(self.tcx(), trait_ref)
+                    .find(|super_trait_ref| super_trait_ref.def_id() == fn_once_trait)
+                    .unwrap();
+
+                fn_traits.entry(super_trait_ref).or_default().fn_mut_trait_ref = Some(trait_ref);
+                return;
+            } else if Some(trait_def_id) == self.tcx().lang_items().fn_trait() {
+                let super_trait_ref = crate::traits::util::supertraits(self.tcx(), trait_ref)
+                    .find(|super_trait_ref| super_trait_ref.def_id() == fn_once_trait)
+                    .unwrap();
+
+                fn_traits.entry(super_trait_ref).or_default().fn_trait_ref = Some(trait_ref);
+                return;
+            }
+        }
+
+        // Otherwise, just group our traits and projection types.
+        traits.entry(trait_ref).or_default().extend(proj_ty);
+    }
+
     fn pretty_print_bound_var(
         &mut self,
         debruijn: ty::DebruijnIndex,
@@ -2553,3 +2699,12 @@ fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> {
 pub fn provide(providers: &mut ty::query::Providers) {
     *providers = ty::query::Providers { trimmed_def_paths, ..*providers };
 }
+
+#[derive(Default)]
+pub struct OpaqueFnEntry<'tcx> {
+    // The trait ref is already stored as a key, so just track if we have it as a real predicate
+    has_fn_once: bool,
+    fn_mut_trait_ref: Option<ty::PolyTraitRef<'tcx>>,
+    fn_trait_ref: Option<ty::PolyTraitRef<'tcx>>,
+    return_ty: Option<ty::Binder<'tcx, Ty<'tcx>>>,
+}
index 0f8e80806e31e430edc9dc4ff13fc80fb94b4489..16a6c586358d9815fa8de3302a0bb734f3cca3ff 100644 (file)
@@ -4,7 +4,7 @@
 
 use crate::mir::interpret;
 use crate::mir::ProjectionKind;
-use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
+use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeVisitor};
 use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
 use crate::ty::{self, InferConst, Lift, Ty, TyCtxt};
 use rustc_data_structures::functor::IdFunctor;
@@ -669,8 +669,11 @@ fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
 
 /// AdtDefs are basically the same as a DefId.
 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::AdtDef {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, _folder: &mut F) -> Self {
-        self
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        _folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        Ok(self)
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -679,8 +682,11 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlo
 }
 
 impl<'tcx, T: TypeFoldable<'tcx>, U: TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> (T, U) {
-        (self.0.fold_with(folder), self.1.fold_with(folder))
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<(T, U), F::Error> {
+        Ok((self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?))
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -692,8 +698,15 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 impl<'tcx, A: TypeFoldable<'tcx>, B: TypeFoldable<'tcx>, C: TypeFoldable<'tcx>> TypeFoldable<'tcx>
     for (A, B, C)
 {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> (A, B, C) {
-        (self.0.fold_with(folder), self.1.fold_with(folder), self.2.fold_with(folder))
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<(A, B, C), F::Error> {
+        Ok((
+            self.0.try_fold_with(folder)?,
+            self.1.try_fold_with(folder)?,
+            self.2.try_fold_with(folder)?,
+        ))
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -718,9 +731,12 @@ impl<'tcx, T, E> TypeFoldable<'tcx> for Result<T, E> {
 }
 
 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         // FIXME: Reuse the `Rc` here.
-        Rc::new((*self).clone().fold_with(folder))
+        (*self).clone().try_fold_with(folder).map(Rc::new)
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -729,9 +745,12 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Arc<T> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         // FIXME: Reuse the `Arc` here.
-        Arc::new((*self).clone().fold_with(folder))
+        (*self).clone().try_fold_with(folder).map(Arc::new)
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -740,8 +759,11 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<T> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        self.map_id(|value| value.fold_with(folder))
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        self.try_map_id(|value| value.try_fold_with(folder))
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -750,8 +772,11 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec<T> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        self.map_id(|t| t.fold_with(folder))
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        self.try_map_id(|t| t.try_fold_with(folder))
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -760,8 +785,11 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        self.map_id(|t| t.fold_with(folder))
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        self.try_map_id(|t| t.try_fold_with(folder))
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -770,12 +798,15 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<'tcx, T> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        self.map_bound(|ty| ty.fold_with(folder))
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        self.try_map_bound(|ty| ty.try_fold_with(folder))
     }
 
-    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        folder.fold_binder(self)
+    fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        folder.try_fold_binder(self)
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -788,7 +819,10 @@ fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::Br
 }
 
 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         ty::util::fold_list(self, folder, |tcx, v| tcx.intern_poly_existential_predicates(v))
     }
 
@@ -798,7 +832,10 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         ty::util::fold_list(self, folder, |tcx, v| tcx.intern_type_list(v))
     }
 
@@ -808,7 +845,10 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ProjectionKind> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         ty::util::fold_list(self, folder, |tcx, v| tcx.intern_projs(v))
     }
 
@@ -818,24 +858,33 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         use crate::ty::InstanceDef::*;
-        Self {
-            substs: self.substs.fold_with(folder),
+        Ok(Self {
+            substs: self.substs.try_fold_with(folder)?,
             def: match self.def {
-                Item(def) => Item(def.fold_with(folder)),
-                VtableShim(did) => VtableShim(did.fold_with(folder)),
-                ReifyShim(did) => ReifyShim(did.fold_with(folder)),
-                Intrinsic(did) => Intrinsic(did.fold_with(folder)),
-                FnPtrShim(did, ty) => FnPtrShim(did.fold_with(folder), ty.fold_with(folder)),
-                Virtual(did, i) => Virtual(did.fold_with(folder), i),
+                Item(def) => Item(def.try_fold_with(folder)?),
+                VtableShim(did) => VtableShim(did.try_fold_with(folder)?),
+                ReifyShim(did) => ReifyShim(did.try_fold_with(folder)?),
+                Intrinsic(did) => Intrinsic(did.try_fold_with(folder)?),
+                FnPtrShim(did, ty) => {
+                    FnPtrShim(did.try_fold_with(folder)?, ty.try_fold_with(folder)?)
+                }
+                Virtual(did, i) => Virtual(did.try_fold_with(folder)?, i),
                 ClosureOnceShim { call_once, track_caller } => {
-                    ClosureOnceShim { call_once: call_once.fold_with(folder), track_caller }
+                    ClosureOnceShim { call_once: call_once.try_fold_with(folder)?, track_caller }
+                }
+                DropGlue(did, ty) => {
+                    DropGlue(did.try_fold_with(folder)?, ty.try_fold_with(folder)?)
+                }
+                CloneShim(did, ty) => {
+                    CloneShim(did.try_fold_with(folder)?, ty.try_fold_with(folder)?)
                 }
-                DropGlue(did, ty) => DropGlue(did.fold_with(folder), ty.fold_with(folder)),
-                CloneShim(did, ty) => CloneShim(did.fold_with(folder), ty.fold_with(folder)),
             },
-        }
+        })
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -860,8 +909,11 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for interpret::GlobalId<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        Self { instance: self.instance.fold_with(folder), promoted: self.promoted }
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        Ok(Self { instance: self.instance.try_fold_with(folder)?, promoted: self.promoted })
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -870,26 +922,31 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         let kind = match *self.kind() {
-            ty::RawPtr(tm) => ty::RawPtr(tm.fold_with(folder)),
-            ty::Array(typ, sz) => ty::Array(typ.fold_with(folder), sz.fold_with(folder)),
-            ty::Slice(typ) => ty::Slice(typ.fold_with(folder)),
-            ty::Adt(tid, substs) => ty::Adt(tid, substs.fold_with(folder)),
+            ty::RawPtr(tm) => ty::RawPtr(tm.try_fold_with(folder)?),
+            ty::Array(typ, sz) => ty::Array(typ.try_fold_with(folder)?, sz.try_fold_with(folder)?),
+            ty::Slice(typ) => ty::Slice(typ.try_fold_with(folder)?),
+            ty::Adt(tid, substs) => ty::Adt(tid, substs.try_fold_with(folder)?),
             ty::Dynamic(trait_ty, region) => {
-                ty::Dynamic(trait_ty.fold_with(folder), region.fold_with(folder))
+                ty::Dynamic(trait_ty.try_fold_with(folder)?, region.try_fold_with(folder)?)
+            }
+            ty::Tuple(ts) => ty::Tuple(ts.try_fold_with(folder)?),
+            ty::FnDef(def_id, substs) => ty::FnDef(def_id, substs.try_fold_with(folder)?),
+            ty::FnPtr(f) => ty::FnPtr(f.try_fold_with(folder)?),
+            ty::Ref(r, ty, mutbl) => {
+                ty::Ref(r.try_fold_with(folder)?, ty.try_fold_with(folder)?, mutbl)
             }
-            ty::Tuple(ts) => ty::Tuple(ts.fold_with(folder)),
-            ty::FnDef(def_id, substs) => ty::FnDef(def_id, substs.fold_with(folder)),
-            ty::FnPtr(f) => ty::FnPtr(f.fold_with(folder)),
-            ty::Ref(r, ty, mutbl) => ty::Ref(r.fold_with(folder), ty.fold_with(folder), mutbl),
             ty::Generator(did, substs, movability) => {
-                ty::Generator(did, substs.fold_with(folder), movability)
+                ty::Generator(did, substs.try_fold_with(folder)?, movability)
             }
-            ty::GeneratorWitness(types) => ty::GeneratorWitness(types.fold_with(folder)),
-            ty::Closure(did, substs) => ty::Closure(did, substs.fold_with(folder)),
-            ty::Projection(data) => ty::Projection(data.fold_with(folder)),
-            ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)),
+            ty::GeneratorWitness(types) => ty::GeneratorWitness(types.try_fold_with(folder)?),
+            ty::Closure(did, substs) => ty::Closure(did, substs.try_fold_with(folder)?),
+            ty::Projection(data) => ty::Projection(data.try_fold_with(folder)?),
+            ty::Opaque(did, substs) => ty::Opaque(did, substs.try_fold_with(folder)?),
 
             ty::Bool
             | ty::Char
@@ -903,14 +960,14 @@ fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
             | ty::Bound(..)
             | ty::Placeholder(..)
             | ty::Never
-            | ty::Foreign(..) => return self,
+            | ty::Foreign(..) => return Ok(self),
         };
 
-        if *self.kind() == kind { self } else { folder.tcx().mk_ty(kind) }
+        Ok(if *self.kind() == kind { self } else { folder.tcx().mk_ty(kind) })
     }
 
-    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        folder.fold_ty(self)
+    fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        folder.try_fold_ty(self)
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -961,12 +1018,15 @@ fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::Br
 }
 
 impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, _folder: &mut F) -> Self {
-        self
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        _folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        Ok(self)
     }
 
-    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        folder.fold_region(self)
+    fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        folder.try_fold_region(self)
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -979,13 +1039,16 @@ fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::Br
 }
 
 impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        folder.fold_predicate(self)
+    fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        folder.try_fold_predicate(self)
     }
 
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        let new = self.inner.kind.fold_with(folder);
-        folder.tcx().reuse_or_mk_predicate(self, new)
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        let new = self.inner.kind.try_fold_with(folder)?;
+        Ok(folder.tcx().reuse_or_mk_predicate(self, new))
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -1006,7 +1069,10 @@ fn has_type_flags(&self, flags: ty::TypeFlags) -> bool {
 }
 
 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Predicate<'tcx>> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         ty::util::fold_list(self, folder, |tcx, v| tcx.intern_predicates(v))
     }
 
@@ -1016,8 +1082,11 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec<I, T> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        self.map_id(|x| x.fold_with(folder))
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        self.try_map_id(|x| x.try_fold_with(folder))
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -1026,18 +1095,21 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        let ty = self.ty.fold_with(folder);
-        let val = self.val.fold_with(folder);
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        let ty = self.ty.try_fold_with(folder)?;
+        let val = self.val.try_fold_with(folder)?;
         if ty != self.ty || val != self.val {
-            folder.tcx().mk_const(ty::Const { ty, val })
+            Ok(folder.tcx().mk_const(ty::Const { ty, val }))
         } else {
-            self
+            Ok(self)
         }
     }
 
-    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        folder.fold_const(self)
+    fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        folder.try_fold_const(self)
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -1051,16 +1123,19 @@ fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::Br
 }
 
 impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        match self {
-            ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)),
-            ty::ConstKind::Param(p) => ty::ConstKind::Param(p.fold_with(folder)),
-            ty::ConstKind::Unevaluated(uv) => ty::ConstKind::Unevaluated(uv.fold_with(folder)),
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        Ok(match self {
+            ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.try_fold_with(folder)?),
+            ty::ConstKind::Param(p) => ty::ConstKind::Param(p.try_fold_with(folder)?),
+            ty::ConstKind::Unevaluated(uv) => ty::ConstKind::Unevaluated(uv.try_fold_with(folder)?),
             ty::ConstKind::Value(_)
             | ty::ConstKind::Bound(..)
             | ty::ConstKind::Placeholder(..)
             | ty::ConstKind::Error(_) => self,
-        }
+        })
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -1077,8 +1152,11 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, _folder: &mut F) -> Self {
-        self
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        _folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        Ok(self)
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -1087,12 +1165,15 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlo
 }
 
 impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        ty::Unevaluated {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        Ok(ty::Unevaluated {
             def: self.def,
-            substs_: Some(self.substs(folder.tcx()).fold_with(folder)),
+            substs_: Some(self.substs(folder.tcx()).try_fold_with(folder)?),
             promoted: self.promoted,
-        }
+        })
     }
 
     fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -1112,12 +1193,15 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        ty::Unevaluated {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        Ok(ty::Unevaluated {
             def: self.def,
-            substs_: Some(self.substs(folder.tcx()).fold_with(folder)),
+            substs_: Some(self.substs(folder.tcx()).try_fold_with(folder)?),
             promoted: self.promoted,
-        }
+        })
     }
 
     fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
index 7e054d1e17fcdadc00a82218659acdcdcb6504f1..6bd761d61e247905e41a368844802f5207c71df3 100644 (file)
@@ -356,14 +356,17 @@ pub fn new(
     /// The ordering assumed here must match that used by `ClosureSubsts::new` above.
     fn split(self) -> ClosureSubstsParts<'tcx, GenericArg<'tcx>> {
         match self.substs[..] {
-            [ref parent_substs @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => {
-                ClosureSubstsParts {
-                    parent_substs,
-                    closure_kind_ty,
-                    closure_sig_as_fn_ptr_ty,
-                    tupled_upvars_ty,
-                }
-            }
+            [
+                ref parent_substs @ ..,
+                closure_kind_ty,
+                closure_sig_as_fn_ptr_ty,
+                tupled_upvars_ty,
+            ] => ClosureSubstsParts {
+                parent_substs,
+                closure_kind_ty,
+                closure_sig_as_fn_ptr_ty,
+                tupled_upvars_ty,
+            },
             _ => bug!("closure substs missing synthetics"),
         }
     }
@@ -890,7 +893,7 @@ pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item = DefId> + 'a {
 ///
 /// Trait references also appear in object types like `Foo<U>`, but in
 /// that case the `Self` parameter is absent from the substitutions.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable)]
 pub struct TraitRef<'tcx> {
     pub def_id: DefId,
@@ -1101,6 +1104,18 @@ pub fn map_bound<F, U: TypeFoldable<'tcx>>(self, f: F) -> Binder<'tcx, U>
         Binder(value, self.1)
     }
 
+    pub fn try_map_bound<F, U: TypeFoldable<'tcx>, E>(self, f: F) -> Result<Binder<'tcx, U>, E>
+    where
+        F: FnOnce(T) -> Result<U, E>,
+    {
+        let value = f(self.0)?;
+        if cfg!(debug_assertions) {
+            let mut validator = ValidateBoundVars::new(self.1);
+            value.visit_with(&mut validator);
+        }
+        Ok(Binder(value, self.1))
+    }
+
     /// Wraps a `value` in a binder, using the same bound variables as the
     /// current `Binder`. This should not be used if the new value *changes*
     /// the bound variables. Note: the (old or new) value itself does not
index 73a8e18949de06ad6a4d8d5b3dc0c8329b5c22bf..8fddafaf6206a4c51145047bcff7e462dfd71e42 100644 (file)
@@ -2,7 +2,7 @@
 
 use crate::mir;
 use crate::ty::codec::{TyDecoder, TyEncoder};
-use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
+use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeVisitor};
 use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts};
 use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
 
@@ -153,11 +153,14 @@ fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
 }
 
 impl<'tcx> TypeFoldable<'tcx> for GenericArg<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         match self.unpack() {
-            GenericArgKind::Lifetime(lt) => lt.fold_with(folder).into(),
-            GenericArgKind::Type(ty) => ty.fold_with(folder).into(),
-            GenericArgKind::Const(ct) => ct.fold_with(folder).into(),
+            GenericArgKind::Lifetime(lt) => lt.try_fold_with(folder).map(Into::into),
+            GenericArgKind::Type(ty) => ty.try_fold_with(folder).map(Into::into),
+            GenericArgKind::Const(ct) => ct.try_fold_with(folder).map(Into::into),
         }
     }
 
@@ -372,7 +375,10 @@ pub fn truncate_to(&self, tcx: TyCtxt<'tcx>, generics: &ty::Generics) -> SubstsR
 }
 
 impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         // This code is hot enough that it's worth specializing for the most
         // common length lists, to avoid the overhead of `SmallVec` creation.
         // The match arms are in order of frequency. The 1, 2, and 0 cases are
@@ -381,22 +387,27 @@ fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
         // calling `intern_substs`.
         match self.len() {
             1 => {
-                let param0 = self[0].fold_with(folder);
-                if param0 == self[0] { self } else { folder.tcx().intern_substs(&[param0]) }
+                let param0 = self[0].try_fold_with(folder)?;
+                if param0 == self[0] { Ok(self) } else { Ok(folder.tcx().intern_substs(&[param0])) }
             }
             2 => {
-                let param0 = self[0].fold_with(folder);
-                let param1 = self[1].fold_with(folder);
+                let param0 = self[0].try_fold_with(folder)?;
+                let param1 = self[1].try_fold_with(folder)?;
                 if param0 == self[0] && param1 == self[1] {
-                    self
+                    Ok(self)
                 } else {
-                    folder.tcx().intern_substs(&[param0, param1])
+                    Ok(folder.tcx().intern_substs(&[param0, param1]))
                 }
             }
-            0 => self,
+            0 => Ok(self),
             _ => {
-                let params: SmallVec<[_; 8]> = self.iter().map(|k| k.fold_with(folder)).collect();
-                if params[..] == self[..] { self } else { folder.tcx().intern_substs(&params) }
+                let params: SmallVec<[_; 8]> =
+                    self.iter().map(|k| k.try_fold_with(folder)).collect::<Result<_, _>>()?;
+                if params[..] == self[..] {
+                    Ok(self)
+                } else {
+                    Ok(folder.tcx().intern_substs(&params))
+                }
             }
         }
     }
index 6e7acb244d1597a14fe80673f764381419335e5e..ba9b2eae2c830abaedc5533e8fe463edab8be214 100644 (file)
@@ -1,7 +1,7 @@
 //! Miscellaneous type-system utilities that are too small to deserve their own modules.
 
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use crate::ty::fold::TypeFolder;
+use crate::ty::fold::{FallibleTypeFolder, TypeFolder};
 use crate::ty::layout::IntegerExt;
 use crate::ty::query::TyCtxtAt;
 use crate::ty::subst::{GenericArgKind, Subst, SubstsRef};
@@ -788,10 +788,14 @@ pub fn needs_drop(&'tcx self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>)
                     [component_ty] => component_ty,
                     _ => self,
                 };
+
                 // This doesn't depend on regions, so try to minimize distinct
                 // query keys used.
-                let erased = tcx.normalize_erasing_regions(param_env, query_ty);
-                tcx.needs_drop_raw(param_env.and(erased))
+                // If normalization fails, we just use `query_ty`.
+                let query_ty =
+                    tcx.try_normalize_erasing_regions(param_env, query_ty).unwrap_or(query_ty);
+
+                tcx.needs_drop_raw(param_env.and(query_ty))
             }
         }
     }
@@ -1046,25 +1050,31 @@ pub fn fold_list<'tcx, F, T>(
     list: &'tcx ty::List<T>,
     folder: &mut F,
     intern: impl FnOnce(TyCtxt<'tcx>, &[T]) -> &'tcx ty::List<T>,
-) -> &'tcx ty::List<T>
+) -> Result<&'tcx ty::List<T>, F::Error>
 where
-    F: TypeFolder<'tcx>,
+    F: FallibleTypeFolder<'tcx>,
     T: TypeFoldable<'tcx> + PartialEq + Copy,
 {
     let mut iter = list.iter();
     // Look for the first element that changed
-    if let Some((i, new_t)) = iter.by_ref().enumerate().find_map(|(i, t)| {
-        let new_t = t.fold_with(folder);
-        if new_t == t { None } else { Some((i, new_t)) }
+    match iter.by_ref().enumerate().find_map(|(i, t)| match t.try_fold_with(folder) {
+        Ok(new_t) if new_t == t => None,
+        new_t => Some((i, new_t)),
     }) {
-        // An element changed, prepare to intern the resulting list
-        let mut new_list = SmallVec::<[_; 8]>::with_capacity(list.len());
-        new_list.extend_from_slice(&list[..i]);
-        new_list.push(new_t);
-        new_list.extend(iter.map(|t| t.fold_with(folder)));
-        intern(folder.tcx(), &new_list)
-    } else {
-        list
+        Some((i, Ok(new_t))) => {
+            // An element changed, prepare to intern the resulting list
+            let mut new_list = SmallVec::<[_; 8]>::with_capacity(list.len());
+            new_list.extend_from_slice(&list[..i]);
+            new_list.push(new_t);
+            for t in iter {
+                new_list.push(t.try_fold_with(folder)?)
+            }
+            Ok(intern(folder.tcx(), &new_list))
+        }
+        Some((_, Err(err))) => {
+            return Err(err);
+        }
+        None => Ok(list),
     }
 }
 
index 3ed434131b292ca5920cfea7a223be4704ec66cb..286473c38e36d2920fd15a34fab64d09c510a117 100644 (file)
 use rustc_data_structures::captures::Captures;
 
 use rustc_arena::TypedArena;
+use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::def_id::DefId;
 use rustc_hir::HirId;
 use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -808,8 +809,9 @@ fn is_useful<'p, 'tcx>(
         // We try each or-pattern branch in turn.
         let mut matrix = matrix.clone();
         for v in v.expand_or_pat() {
-            let usefulness =
-                is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false);
+            let usefulness = ensure_sufficient_stack(|| {
+                is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false)
+            });
             ret.extend(usefulness);
             // If pattern has a guard don't add it to the matrix.
             if !is_under_guard {
@@ -840,8 +842,9 @@ fn is_useful<'p, 'tcx>(
             // We cache the result of `Fields::wildcards` because it is used a lot.
             let spec_matrix = start_matrix.specialize_constructor(pcx, &ctor);
             let v = v.pop_head_constructor(cx, &ctor);
-            let usefulness =
-                is_useful(cx, &spec_matrix, &v, witness_preference, hir_id, is_under_guard, false);
+            let usefulness = ensure_sufficient_stack(|| {
+                is_useful(cx, &spec_matrix, &v, witness_preference, hir_id, is_under_guard, false)
+            });
             let usefulness = usefulness.apply_constructor(pcx, start_matrix, &ctor);
 
             // When all the conditions are met we have a match with a `non_exhaustive` enum
index 790d9243fbaec874db7488ff817c615d5068cb1e..c45946a9e2a982d6ca43e534934250481922453a 100644 (file)
@@ -316,28 +316,6 @@ fn visit_local(&mut self, local: &mut Local, context: PlaceContext, location: Lo
         }
     }
 
-    fn process_projection_elem(
-        &mut self,
-        elem: PlaceElem<'tcx>,
-        _: Location,
-    ) -> Option<PlaceElem<'tcx>> {
-        match elem {
-            PlaceElem::Index(local) => {
-                if let Some(replacement) = self.replacements.for_src(local) {
-                    bug!(
-                        "cannot replace {:?} with {:?} in index projection {:?}",
-                        local,
-                        replacement,
-                        elem,
-                    );
-                } else {
-                    None
-                }
-            }
-            _ => None,
-        }
-    }
-
     fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
         if let Some(replacement) = self.replacements.for_src(place.local) {
             // Rebase `place`s projections onto `replacement`'s.
index f9ef31462780731a9375aa0ec7f4f379c17da875..acbea9bda11e4317b15528445ed5634a022f6daf 100644 (file)
@@ -27,7 +27,7 @@
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_index::vec::IndexVec;
 use rustc_middle::mir::visit::Visitor as _;
-use rustc_middle::mir::{dump_mir, traversal, Body, ConstQualifs, MirPhase, Promoted};
+use rustc_middle::mir::{dump_mir, traversal, Body, ConstQualifs, MirPass, MirPhase, Promoted};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
 use rustc_span::{Span, Symbol};
 mod multiple_return_terminators;
 mod normalize_array_len;
 mod nrvo;
+mod remove_false_edges;
 mod remove_noop_landing_pads;
 mod remove_storage_markers;
+mod remove_uninit_drops;
 mod remove_unneeded_drops;
 mod remove_zsts;
 mod required_consts;
 mod uninhabited_enum_branching;
 mod unreachable_prop;
 
-use rustc_const_eval::transform::check_consts;
+use rustc_const_eval::transform::check_consts::{self, ConstCx};
 use rustc_const_eval::transform::promote_consts;
 use rustc_const_eval::transform::validate;
-pub use rustc_const_eval::transform::MirPass;
 use rustc_mir_dataflow::rustc_peek;
 
 pub fn provide(providers: &mut Providers) {
@@ -445,8 +446,20 @@ fn mir_drops_elaborated_and_const_checked<'tcx>(
     let (body, _) = tcx.mir_promoted(def);
     let mut body = body.steal();
 
+    // IMPORTANT
+    remove_false_edges::RemoveFalseEdges.run_pass(tcx, &mut body);
+
+    // Do a little drop elaboration before const-checking if `const_precise_live_drops` is enabled.
+    //
+    // FIXME: Can't use `run_passes` for these, since `run_passes` SILENTLY DOES NOTHING IF THE MIR
+    // PHASE DOESN'T CHANGE.
+    if check_consts::post_drop_elaboration::checking_enabled(&ConstCx::new(tcx, &body)) {
+        simplify::SimplifyCfg::new("remove-false-edges").run_pass(tcx, &mut body);
+        remove_uninit_drops::RemoveUninitDrops.run_pass(tcx, &mut body);
+        check_consts::post_drop_elaboration::check_live_drops(tcx, &body);
+    }
+
     run_post_borrowck_cleanup_passes(tcx, &mut body);
-    check_consts::post_drop_elaboration::check_live_drops(tcx, &body);
     tcx.alloc_steal_mir(body)
 }
 
@@ -456,7 +469,7 @@ fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tc
 
     let post_borrowck_cleanup: &[&dyn MirPass<'tcx>] = &[
         // Remove all things only needed by analysis
-        &simplify_branches::SimplifyBranches::new("initial"),
+        &simplify_branches::SimplifyConstCondition::new("initial"),
         &remove_noop_landing_pads::RemoveNoopLandingPads,
         &cleanup_post_borrowck::CleanupNonCodegenStatements,
         &simplify::SimplifyCfg::new("early-opt"),
@@ -515,13 +528,13 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         &instcombine::InstCombine,
         &separate_const_switch::SeparateConstSwitch,
         &const_prop::ConstProp,
-        &simplify_branches::SimplifyBranches::new("after-const-prop"),
+        &simplify_branches::SimplifyConstCondition::new("after-const-prop"),
         &early_otherwise_branch::EarlyOtherwiseBranch,
         &simplify_comparison_integral::SimplifyComparisonIntegral,
         &simplify_try::SimplifyArmIdentity,
         &simplify_try::SimplifyBranchSame,
         &dest_prop::DestinationPropagation,
-        &simplify_branches::SimplifyBranches::new("final"),
+        &simplify_branches::SimplifyConstCondition::new("final"),
         &remove_noop_landing_pads::RemoveNoopLandingPads,
         &simplify::SimplifyCfg::new("final"),
         &nrvo::RenameReturnPlace,
diff --git a/compiler/rustc_mir_transform/src/remove_false_edges.rs b/compiler/rustc_mir_transform/src/remove_false_edges.rs
new file mode 100644 (file)
index 0000000..71f5ccf
--- /dev/null
@@ -0,0 +1,29 @@
+use rustc_middle::mir::{Body, TerminatorKind};
+use rustc_middle::ty::TyCtxt;
+
+use crate::MirPass;
+
+/// Removes `FalseEdge` and `FalseUnwind` terminators from the MIR.
+///
+/// These are only needed for borrow checking, and can be removed afterwards.
+///
+/// FIXME: This should probably have its own MIR phase.
+pub struct RemoveFalseEdges;
+
+impl<'tcx> MirPass<'tcx> for RemoveFalseEdges {
+    fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        for block in body.basic_blocks_mut() {
+            let terminator = block.terminator_mut();
+            terminator.kind = match terminator.kind {
+                TerminatorKind::FalseEdge { real_target, .. } => {
+                    TerminatorKind::Goto { target: real_target }
+                }
+                TerminatorKind::FalseUnwind { real_target, .. } => {
+                    TerminatorKind::Goto { target: real_target }
+                }
+
+                _ => continue,
+            }
+        }
+    }
+}
diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
new file mode 100644 (file)
index 0000000..c219f26
--- /dev/null
@@ -0,0 +1,171 @@
+use rustc_index::bit_set::BitSet;
+use rustc_middle::mir::{Body, Field, Rvalue, Statement, StatementKind, TerminatorKind};
+use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, VariantDef};
+use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
+use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
+use rustc_mir_dataflow::{self, move_path_children_matching, Analysis, MoveDataParamEnv};
+
+use crate::MirPass;
+
+/// Removes `Drop` and `DropAndReplace` terminators whose target is known to be uninitialized at
+/// that point.
+///
+/// This is redundant with drop elaboration, but we need to do it prior to const-checking, and
+/// running const-checking after drop elaboration makes it opimization dependent, causing issues
+/// like [#90770].
+///
+/// [#90770]: https://github.com/rust-lang/rust/issues/90770
+pub struct RemoveUninitDrops;
+
+impl<'tcx> MirPass<'tcx> for RemoveUninitDrops {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        let param_env = tcx.param_env(body.source.def_id());
+        let Ok(move_data) = MoveData::gather_moves(body, tcx, param_env) else {
+            // We could continue if there are move errors, but there's not much point since our
+            // init data isn't complete.
+            return;
+        };
+
+        let mdpe = MoveDataParamEnv { move_data, param_env };
+        let mut maybe_inits = MaybeInitializedPlaces::new(tcx, body, &mdpe)
+            .into_engine(tcx, body)
+            .pass_name("remove_uninit_drops")
+            .iterate_to_fixpoint()
+            .into_results_cursor(body);
+
+        let mut to_remove = vec![];
+        for (bb, block) in body.basic_blocks().iter_enumerated() {
+            let terminator = block.terminator();
+            let (TerminatorKind::Drop { place, .. } | TerminatorKind::DropAndReplace { place, .. })
+                = &terminator.kind
+            else { continue };
+
+            maybe_inits.seek_before_primary_effect(body.terminator_loc(bb));
+
+            // If there's no move path for the dropped place, it's probably a `Deref`. Let it alone.
+            let LookupResult::Exact(mpi) = mdpe.move_data.rev_lookup.find(place.as_ref()) else {
+                continue;
+            };
+
+            let should_keep = is_needs_drop_and_init(
+                tcx,
+                param_env,
+                maybe_inits.get(),
+                &mdpe.move_data,
+                place.ty(body, tcx).ty,
+                mpi,
+            );
+            if !should_keep {
+                to_remove.push(bb)
+            }
+        }
+
+        for bb in to_remove {
+            let block = &mut body.basic_blocks_mut()[bb];
+
+            let (TerminatorKind::Drop { target, .. } | TerminatorKind::DropAndReplace { target, .. })
+                = &block.terminator().kind
+            else { unreachable!() };
+
+            // Replace block terminator with `Goto`.
+            let target = *target;
+            let old_terminator_kind = std::mem::replace(
+                &mut block.terminator_mut().kind,
+                TerminatorKind::Goto { target },
+            );
+
+            // If this is a `DropAndReplace`, we need to emulate the assignment to the return place.
+            if let TerminatorKind::DropAndReplace { place, value, .. } = old_terminator_kind {
+                block.statements.push(Statement {
+                    source_info: block.terminator().source_info,
+                    kind: StatementKind::Assign(Box::new((place, Rvalue::Use(value)))),
+                });
+            }
+        }
+    }
+}
+
+fn is_needs_drop_and_init(
+    tcx: TyCtxt<'tcx>,
+    param_env: ParamEnv<'tcx>,
+    maybe_inits: &BitSet<MovePathIndex>,
+    move_data: &MoveData<'tcx>,
+    ty: Ty<'tcx>,
+    mpi: MovePathIndex,
+) -> bool {
+    // No need to look deeper if the root is definitely uninit or if it has no `Drop` impl.
+    if !maybe_inits.contains(mpi) || !ty.needs_drop(tcx, param_env) {
+        return false;
+    }
+
+    let field_needs_drop_and_init = |(f, f_ty, mpi)| {
+        let child = move_path_children_matching(move_data, mpi, |x| x.is_field_to(f));
+        let Some(mpi) = child else {
+            return f_ty.needs_drop(tcx, param_env);
+        };
+
+        is_needs_drop_and_init(tcx, param_env, maybe_inits, move_data, f_ty, mpi)
+    };
+
+    // This pass is only needed for const-checking, so it doesn't handle as many cases as
+    // `DropCtxt::open_drop`, since they aren't relevant in a const-context.
+    match ty.kind() {
+        ty::Adt(adt, substs) => {
+            let dont_elaborate = adt.is_union() || adt.is_manually_drop() || adt.has_dtor(tcx);
+            if dont_elaborate {
+                return true;
+            }
+
+            // Look at all our fields, or if we are an enum all our variants and their fields.
+            //
+            // If a field's projection *is not* present in `MoveData`, it has the same
+            // initializedness as its parent (maybe init).
+            //
+            // If its projection *is* present in `MoveData`, then the field may have been moved
+            // from separate from its parent. Recurse.
+            adt.variants.iter_enumerated().any(|(vid, variant)| {
+                // Enums have multiple variants, which are discriminated with a `Downcast` projection.
+                // Structs have a single variant, and don't use a `Downcast` projection.
+                let mpi = if adt.is_enum() {
+                    let downcast =
+                        move_path_children_matching(move_data, mpi, |x| x.is_downcast_to(vid));
+                    let Some(dc_mpi) = downcast else {
+                        return variant_needs_drop(tcx, param_env, substs, variant);
+                    };
+
+                    dc_mpi
+                } else {
+                    mpi
+                };
+
+                variant
+                    .fields
+                    .iter()
+                    .enumerate()
+                    .map(|(f, field)| (Field::from_usize(f), field.ty(tcx, substs), mpi))
+                    .any(field_needs_drop_and_init)
+            })
+        }
+
+        ty::Tuple(_) => ty
+            .tuple_fields()
+            .enumerate()
+            .map(|(f, f_ty)| (Field::from_usize(f), f_ty, mpi))
+            .any(field_needs_drop_and_init),
+
+        _ => true,
+    }
+}
+
+fn variant_needs_drop(
+    tcx: TyCtxt<'tcx>,
+    param_env: ParamEnv<'tcx>,
+    substs: SubstsRef<'tcx>,
+    variant: &VariantDef,
+) -> bool {
+    variant.fields.iter().any(|field| {
+        let f_ty = field.ty(tcx, substs);
+        f_ty.needs_drop(tcx, param_env)
+    })
+}
index c71bc512c31b5e8403eb59e59d5702ecec8d4813..39f78e9555e2f6a0d660624dd0094901c0c99d28 100644 (file)
@@ -1,4 +1,8 @@
-//! This pass replaces a drop of a type that does not need dropping, with a goto
+//! This pass replaces a drop of a type that does not need dropping, with a goto.
+//!
+//! When the MIR is built, we check `needs_drop` before emitting a `Drop` for a place. This pass is
+//! useful because (unlike MIR building) it runs after type checking, so it can make use of
+//! `Reveal::All` to provide more precies type information.
 
 use crate::MirPass;
 use rustc_middle::mir::*;
index 6c423a2bb5756c79476adf6a8186781b61c29914..3bcb71b64f455e2cf0ba4dcd55f4a9c85d50b6e0 100644 (file)
@@ -35,24 +35,4 @@ fn tcx(&self) -> TyCtxt<'tcx> {
     fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
         *ty = self.tcx.normalize_erasing_regions(self.param_env, ty);
     }
-
-    #[inline]
-    fn process_projection_elem(
-        &mut self,
-        elem: PlaceElem<'tcx>,
-        _: Location,
-    ) -> Option<PlaceElem<'tcx>> {
-        match elem {
-            PlaceElem::Field(field, ty) => {
-                let new_ty = self.tcx.normalize_erasing_regions(self.param_env, ty);
-                if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None }
-            }
-            // None of those contain a Ty.
-            PlaceElem::Index(..)
-            | PlaceElem::Deref
-            | PlaceElem::ConstantIndex { .. }
-            | PlaceElem::Subslice { .. }
-            | PlaceElem::Downcast(..) => None,
-        }
-    }
 }
index df90cfa318df0c9943d1523a0055651a50e3de44..4b261334f3e545d7d4718de15b106861abed1c24 100644 (file)
@@ -1,22 +1,21 @@
-//! A pass that simplifies branches when their condition is known.
-
 use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 
 use std::borrow::Cow;
 
-pub struct SimplifyBranches {
+/// A pass that replaces a branch with a goto when its condition is known.
+pub struct SimplifyConstCondition {
     label: String,
 }
 
-impl SimplifyBranches {
+impl SimplifyConstCondition {
     pub fn new(label: &str) -> Self {
-        SimplifyBranches { label: format!("SimplifyBranches-{}", label) }
+        SimplifyConstCondition { label: format!("SimplifyConstCondition-{}", label) }
     }
 }
 
-impl<'tcx> MirPass<'tcx> for SimplifyBranches {
+impl<'tcx> MirPass<'tcx> for SimplifyConstCondition {
     fn name(&self) -> Cow<'_, str> {
         Cow::Borrowed(&self.label)
     }
@@ -53,12 +52,6 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
                     Some(v) if v == expected => TerminatorKind::Goto { target },
                     _ => continue,
                 },
-                TerminatorKind::FalseEdge { real_target, .. } => {
-                    TerminatorKind::Goto { target: real_target }
-                }
-                TerminatorKind::FalseUnwind { real_target, .. } => {
-                    TerminatorKind::Goto { target: real_target }
-                }
                 _ => continue,
             };
         }
index cf35c3cd53b2fb146abf8d69f28d1423dca85db6..1a620968d56a8d092336304a562484b3341a98be 100644 (file)
@@ -1,3 +1,4 @@
+use crate::lexer::unicode_chars::UNICODE_ARRAY;
 use rustc_ast::ast::{self, AttrStyle};
 use rustc_ast::token::{self, CommentKind, Token, TokenKind};
 use rustc_ast::tokenstream::{Spacing, TokenStream};
@@ -222,6 +223,22 @@ fn cook_lexer_token(&self, token: rustc_lexer::TokenKind, start: BytePos) -> Opt
                 }
                 token::Ident(sym, is_raw_ident)
             }
+            rustc_lexer::TokenKind::InvalidIdent
+                // Do not recover an identifier with emoji if the codepoint is a confusable
+                // with a recoverable substitution token, like `➖`.
+                if UNICODE_ARRAY
+                    .iter()
+                    .find(|&&(c, _, _)| {
+                        let sym = self.str_from(start);
+                        sym.chars().count() == 1 && c == sym.chars().next().unwrap()
+                    })
+                    .is_none() =>
+            {
+                let sym = nfc_normalize(self.str_from(start));
+                let span = self.mk_sp(start, self.pos);
+                self.sess.bad_unicode_identifiers.borrow_mut().entry(sym).or_default().push(span);
+                token::Ident(sym, false)
+            }
             rustc_lexer::TokenKind::Literal { kind, suffix_start } => {
                 let suffix_start = start + BytePos(suffix_start as u32);
                 let (kind, symbol) = self.cook_lexer_literal(start, suffix_start, kind);
@@ -293,7 +310,7 @@ fn cook_lexer_token(&self, token: rustc_lexer::TokenKind, start: BytePos) -> Opt
             rustc_lexer::TokenKind::Caret => token::BinOp(token::Caret),
             rustc_lexer::TokenKind::Percent => token::BinOp(token::Percent),
 
-            rustc_lexer::TokenKind::Unknown => {
+            rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => {
                 let c = self.str_from(start).chars().next().unwrap();
                 let mut err =
                     self.struct_fatal_span_char(start, self.pos, "unknown start of token", c);
index 3eebc088f3fb7c4bddea0e010b314163b6b21857..ccd11f06bc582e0fa8ddd9f9c9af39fac9433103 100644 (file)
@@ -7,7 +7,7 @@
 use rustc_span::{symbol::kw, BytePos, Pos, Span};
 
 #[rustfmt::skip] // for line breaks
-const UNICODE_ARRAY: &[(char, &str, char)] = &[
+pub(crate) const UNICODE_ARRAY: &[(char, &str, char)] = &[
     ('
', "Line Separator", ' '),
     ('
', "Paragraph Separator", ' '),
     (' ', "Ogham Space mark", ' '),
index a40f47f895bbea170b52ab030ce1b0fbf333f075..2b1b2f3fce496f9eff9f95254ff0b9628ae29be9 100644 (file)
@@ -326,6 +326,12 @@ pub fn fake_token_stream(sess: &ParseSess, nt: &Nonterminal) -> TokenStream {
     parse_stream_from_source_str(filename, source, sess, Some(nt.span()))
 }
 
+pub fn fake_token_stream_for_crate(sess: &ParseSess, krate: &ast::Crate) -> TokenStream {
+    let source = pprust::crate_to_string_for_macros(krate);
+    let filename = FileName::macro_expansion_source_code(&source);
+    parse_stream_from_source_str(filename, source, sess, Some(krate.span))
+}
+
 pub fn parse_cfg_attr(
     attr: &Attribute,
     parse_sess: &ParseSess,
index 17e79a02360e8478e0c550bdc340b43489de0151..55af2c9ddd32f1cb9a5455e443a0e76b364d530a 100644 (file)
@@ -1,14 +1,19 @@
+use super::pat::Expected;
 use super::ty::AllowPlus;
-use super::TokenType;
-use super::{BlockMode, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep, TokenExpectType};
+use super::{
+    BlockMode, Parser, PathStyle, RecoverColon, RecoverComma, Restrictions, SemiColonMode, SeqSep,
+    TokenExpectType, TokenType,
+};
 
 use rustc_ast as ast;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Lit, LitKind, TokenKind};
 use rustc_ast::util::parser::AssocOp;
-use rustc_ast::{AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec};
-use rustc_ast::{BinOpKind, BindingMode, Block, BlockCheckMode, Expr, ExprKind, GenericArg, Item};
-use rustc_ast::{ItemKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QSelf, Ty, TyKind};
+use rustc_ast::{
+    AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode, Block,
+    BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Mutability, Param, Pat,
+    PatKind, Path, PathSegment, QSelf, Ty, TyKind,
+};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{pluralize, struct_span_err};
@@ -17,6 +22,8 @@
 use rustc_span::symbol::{kw, Ident};
 use rustc_span::{MultiSpan, Span, SpanSnippetError, DUMMY_SP};
 
+use std::mem::take;
+
 use tracing::{debug, trace};
 
 const TURBOFISH_SUGGESTION_STR: &str =
@@ -662,7 +669,7 @@ pub(super) fn check_turbofish_missing_angle_brackets(&mut self, segment: &mut Pa
             let snapshot = self.clone();
             self.bump();
             let lo = self.token.span;
-            match self.parse_angle_args() {
+            match self.parse_angle_args(None) {
                 Ok(args) => {
                     let span = lo.to(self.prev_token.span);
                     // Detect trailing `>` like in `x.collect::Vec<_>>()`.
@@ -719,7 +726,7 @@ pub(super) fn check_mistyped_turbofish_with_multiple_type_params(
                     let x = self.parse_seq_to_before_end(
                         &token::Gt,
                         SeqSep::trailing_allowed(token::Comma),
-                        |p| p.parse_generic_arg(),
+                        |p| p.parse_generic_arg(None),
                     );
                     match x {
                         Ok((_, _, false)) => {
@@ -1103,7 +1110,7 @@ pub(super) fn maybe_recover_from_bad_qpath_stage_2<T: RecoverQPath>(
         self.expect(&token::ModSep)?;
 
         let mut path = ast::Path { segments: Vec::new(), span: DUMMY_SP, tokens: None };
-        self.parse_path_segments(&mut path.segments, T::PATH_STYLE)?;
+        self.parse_path_segments(&mut path.segments, T::PATH_STYLE, None)?;
         path.span = ty_span.to(self.prev_token.span);
 
         let ty_str = self.span_to_snippet(ty_span).unwrap_or_else(|_| pprust::ty_to_string(&ty));
@@ -1909,6 +1916,71 @@ pub fn handle_unambiguous_unbraced_const_arg(&mut self) -> PResult<'a, P<Expr>>
         Ok(expr)
     }
 
+    fn recover_const_param_decl(
+        &mut self,
+        ty_generics: Option<&Generics>,
+    ) -> PResult<'a, Option<GenericArg>> {
+        let snapshot = self.clone();
+        let param = match self.parse_const_param(vec![]) {
+            Ok(param) => param,
+            Err(mut err) => {
+                err.cancel();
+                *self = snapshot;
+                return Err(err);
+            }
+        };
+        let mut err =
+            self.struct_span_err(param.span(), "unexpected `const` parameter declaration");
+        err.span_label(param.span(), "expected a `const` expression, not a parameter declaration");
+        if let (Some(generics), Ok(snippet)) =
+            (ty_generics, self.sess.source_map().span_to_snippet(param.span()))
+        {
+            let (span, sugg) = match &generics.params[..] {
+                [] => (generics.span, format!("<{}>", snippet)),
+                [.., generic] => (generic.span().shrink_to_hi(), format!(", {}", snippet)),
+            };
+            err.multipart_suggestion(
+                "`const` parameters must be declared for the `impl`",
+                vec![(span, sugg), (param.span(), param.ident.to_string())],
+                Applicability::MachineApplicable,
+            );
+        }
+        let value = self.mk_expr_err(param.span());
+        err.emit();
+        return Ok(Some(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })));
+    }
+
+    pub fn recover_const_param_declaration(
+        &mut self,
+        ty_generics: Option<&Generics>,
+    ) -> PResult<'a, Option<GenericArg>> {
+        // We have to check for a few different cases.
+        if let Ok(arg) = self.recover_const_param_decl(ty_generics) {
+            return Ok(arg);
+        }
+
+        // We haven't consumed `const` yet.
+        let start = self.token.span;
+        self.bump(); // `const`
+
+        // Detect and recover from the old, pre-RFC2000 syntax for const generics.
+        let mut err = self
+            .struct_span_err(start, "expected lifetime, type, or constant, found keyword `const`");
+        if self.check_const_arg() {
+            err.span_suggestion_verbose(
+                start.until(self.token.span),
+                "the `const` keyword is only needed in the definition of the type",
+                String::new(),
+                Applicability::MaybeIncorrect,
+            );
+            err.emit();
+            Ok(Some(GenericArg::Const(self.parse_const_arg()?)))
+        } else {
+            let after_kw_const = self.token.span;
+            self.recover_const_arg(after_kw_const, err).map(Some)
+        }
+    }
+
     /// Try to recover from possible generic const argument without `{` and `}`.
     ///
     /// When encountering code like `foo::< bar + 3 >` or `foo::< bar - baz >` we suggest
@@ -2008,4 +2080,177 @@ pub(super) fn incorrect_move_async_order_found(
         );
         err
     }
+
+    /// Some special error handling for the "top-level" patterns in a match arm,
+    /// `for` loop, `let`, &c. (in contrast to subpatterns within such).
+    crate fn maybe_recover_colon_colon_in_pat_typo(
+        &mut self,
+        mut first_pat: P<Pat>,
+        ra: RecoverColon,
+        expected: Expected,
+    ) -> P<Pat> {
+        if RecoverColon::Yes != ra || token::Colon != self.token.kind {
+            return first_pat;
+        }
+        if !matches!(first_pat.kind, PatKind::Ident(_, _, None) | PatKind::Path(..))
+            || !self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident())
+        {
+            return first_pat;
+        }
+        // The pattern looks like it might be a path with a `::` -> `:` typo:
+        // `match foo { bar:baz => {} }`
+        let span = self.token.span;
+        // We only emit "unexpected `:`" error here if we can successfully parse the
+        // whole pattern correctly in that case.
+        let snapshot = self.clone();
+
+        // Create error for "unexpected `:`".
+        match self.expected_one_of_not_found(&[], &[]) {
+            Err(mut err) => {
+                self.bump(); // Skip the `:`.
+                match self.parse_pat_no_top_alt(expected) {
+                    Err(mut inner_err) => {
+                        // Carry on as if we had not done anything, callers will emit a
+                        // reasonable error.
+                        inner_err.cancel();
+                        err.cancel();
+                        *self = snapshot;
+                    }
+                    Ok(mut pat) => {
+                        // We've parsed the rest of the pattern.
+                        let new_span = first_pat.span.to(pat.span);
+                        let mut show_sugg = false;
+                        // Try to construct a recovered pattern.
+                        match &mut pat.kind {
+                            PatKind::Struct(qself @ None, path, ..)
+                            | PatKind::TupleStruct(qself @ None, path, _)
+                            | PatKind::Path(qself @ None, path) => match &first_pat.kind {
+                                PatKind::Ident(_, ident, _) => {
+                                    path.segments.insert(0, PathSegment::from_ident(ident.clone()));
+                                    path.span = new_span;
+                                    show_sugg = true;
+                                    first_pat = pat;
+                                }
+                                PatKind::Path(old_qself, old_path) => {
+                                    path.segments = old_path
+                                        .segments
+                                        .iter()
+                                        .cloned()
+                                        .chain(take(&mut path.segments))
+                                        .collect();
+                                    path.span = new_span;
+                                    *qself = old_qself.clone();
+                                    first_pat = pat;
+                                    show_sugg = true;
+                                }
+                                _ => {}
+                            },
+                            PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None) => {
+                                match &first_pat.kind {
+                                    PatKind::Ident(_, old_ident, _) => {
+                                        let path = PatKind::Path(
+                                            None,
+                                            Path {
+                                                span: new_span,
+                                                segments: vec![
+                                                    PathSegment::from_ident(old_ident.clone()),
+                                                    PathSegment::from_ident(ident.clone()),
+                                                ],
+                                                tokens: None,
+                                            },
+                                        );
+                                        first_pat = self.mk_pat(new_span, path);
+                                        show_sugg = true;
+                                    }
+                                    PatKind::Path(old_qself, old_path) => {
+                                        let mut segments = old_path.segments.clone();
+                                        segments.push(PathSegment::from_ident(ident.clone()));
+                                        let path = PatKind::Path(
+                                            old_qself.clone(),
+                                            Path { span: new_span, segments, tokens: None },
+                                        );
+                                        first_pat = self.mk_pat(new_span, path);
+                                        show_sugg = true;
+                                    }
+                                    _ => {}
+                                }
+                            }
+                            _ => {}
+                        }
+                        if show_sugg {
+                            err.span_suggestion(
+                                span,
+                                "maybe write a path separator here",
+                                "::".to_string(),
+                                Applicability::MaybeIncorrect,
+                            );
+                        } else {
+                            first_pat = self.mk_pat(new_span, PatKind::Wild);
+                        }
+                        err.emit();
+                    }
+                }
+            }
+            _ => {
+                // Carry on as if we had not done anything. This should be unreachable.
+                *self = snapshot;
+            }
+        };
+        first_pat
+    }
+
+    /// Some special error handling for the "top-level" patterns in a match arm,
+    /// `for` loop, `let`, &c. (in contrast to subpatterns within such).
+    crate fn maybe_recover_unexpected_comma(
+        &mut self,
+        lo: Span,
+        rc: RecoverComma,
+    ) -> PResult<'a, ()> {
+        if rc == RecoverComma::No || self.token != token::Comma {
+            return Ok(());
+        }
+
+        // An unexpected comma after a top-level pattern is a clue that the
+        // user (perhaps more accustomed to some other language) forgot the
+        // parentheses in what should have been a tuple pattern; return a
+        // suggestion-enhanced error here rather than choking on the comma later.
+        let comma_span = self.token.span;
+        self.bump();
+        if let Err(mut err) = self.skip_pat_list() {
+            // We didn't expect this to work anyway; we just wanted to advance to the
+            // end of the comma-sequence so we know the span to suggest parenthesizing.
+            err.cancel();
+        }
+        let seq_span = lo.to(self.prev_token.span);
+        let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern");
+        if let Ok(seq_snippet) = self.span_to_snippet(seq_span) {
+            const MSG: &str = "try adding parentheses to match on a tuple...";
+
+            err.span_suggestion(
+                seq_span,
+                MSG,
+                format!("({})", seq_snippet),
+                Applicability::MachineApplicable,
+            );
+            err.span_suggestion(
+                seq_span,
+                "...or a vertical bar to match on multiple alternatives",
+                seq_snippet.replace(",", " |"),
+                Applicability::MachineApplicable,
+            );
+        }
+        Err(err)
+    }
+
+    /// Parse and throw away a parenthesized comma separated
+    /// sequence of patterns until `)` is reached.
+    fn skip_pat_list(&mut self) -> PResult<'a, ()> {
+        while !self.check(&token::CloseDelim(token::Paren)) {
+            self.parse_pat_no_top_alt(None)?;
+            if !self.eat(&token::Comma) {
+                return Ok(());
+            }
+        }
+        Ok(())
+    }
 }
index 3669a4fce9cbf9ba0048156ca6e697cd93d07ebb..1dbd7bad0f0236d416885e9b74123d52b9942916 100644 (file)
@@ -1150,7 +1150,7 @@ fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Exp
         }
 
         let fn_span_lo = self.token.span;
-        let mut segment = self.parse_path_segment(PathStyle::Expr)?;
+        let mut segment = self.parse_path_segment(PathStyle::Expr, None)?;
         self.check_trailing_angle_brackets(&segment, &[&token::OpenDelim(token::Paren)]);
         self.check_turbofish_missing_angle_brackets(&mut segment);
 
@@ -1988,25 +1988,34 @@ fn parse_if_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
         let lo = self.prev_token.span;
         let cond = self.parse_cond_expr()?;
 
+        let missing_then_block_binop_span = || {
+            match cond.kind {
+                ExprKind::Binary(Spanned { span: binop_span, .. }, _, ref right)
+                    if let ExprKind::Block(..) = right.kind => Some(binop_span),
+                _ => None
+            }
+        };
+
         // Verify that the parsed `if` condition makes sense as a condition. If it is a block, then
         // verify that the last statement is either an implicit return (no `;`) or an explicit
         // return. This won't catch blocks with an explicit `return`, but that would be caught by
         // the dead code lint.
-        let thn = if self.eat_keyword(kw::Else) || !cond.returns() {
-            self.error_missing_if_cond(lo, cond.span)
+        let thn = if self.token.is_keyword(kw::Else) || !cond.returns() {
+            if let Some(binop_span) = missing_then_block_binop_span() {
+                self.error_missing_if_then_block(lo, None, Some(binop_span)).emit();
+                self.mk_block_err(cond.span)
+            } else {
+                self.error_missing_if_cond(lo, cond.span)
+            }
         } else {
             let attrs = self.parse_outer_attributes()?.take_for_recovery(); // For recovery.
             let not_block = self.token != token::OpenDelim(token::Brace);
-            let block = self.parse_block().map_err(|mut err| {
+            let block = self.parse_block().map_err(|err| {
                 if not_block {
-                    err.span_label(lo, "this `if` expression has a condition, but no block");
-                    if let ExprKind::Binary(_, _, ref right) = cond.kind {
-                        if let ExprKind::Block(_, _) = right.kind {
-                            err.help("maybe you forgot the right operand of the condition?");
-                        }
-                    }
+                    self.error_missing_if_then_block(lo, Some(err), missing_then_block_binop_span())
+                } else {
+                    err
                 }
-                err
             })?;
             self.error_on_if_block_attrs(lo, false, block.span, &attrs);
             block
@@ -2015,6 +2024,28 @@ fn parse_if_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
         Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els), attrs))
     }
 
+    fn error_missing_if_then_block(
+        &self,
+        if_span: Span,
+        err: Option<DiagnosticBuilder<'a>>,
+        binop_span: Option<Span>,
+    ) -> DiagnosticBuilder<'a> {
+        let msg = "this `if` expression has a condition, but no block";
+
+        let mut err = if let Some(mut err) = err {
+            err.span_label(if_span, msg);
+            err
+        } else {
+            self.struct_span_err(if_span, msg)
+        };
+
+        if let Some(binop_span) = binop_span {
+            err.span_help(binop_span, "maybe you forgot the right operand of the condition?");
+        }
+
+        err
+    }
+
     fn error_missing_if_cond(&self, lo: Span, span: Span) -> P<ast::Block> {
         let sp = self.sess.source_map().next_point(lo);
         self.struct_span_err(sp, "missing condition for `if` expression")
index f175c5b50b3978b9e131357455f76398122cfcdf..a9ab2cd3f68ef77278f97e72961d5ed30bd8aa0b 100644 (file)
@@ -48,7 +48,10 @@ fn parse_ty_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, Gen
         })
     }
 
-    fn parse_const_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, GenericParam> {
+    crate fn parse_const_param(
+        &mut self,
+        preceding_attrs: Vec<Attribute>,
+    ) -> PResult<'a, GenericParam> {
         let const_span = self.token.span;
 
         self.expect_keyword(kw::Const)?;
index 73ca809ab1d3a53f72523025251250e2bd842f18..cbeaf675be4e5657863ce3199814dd24b9da8f6e 100644 (file)
@@ -26,7 +26,7 @@ impl<'a> Parser<'a> {
     /// Parses a source module as a crate. This is the main entry point for the parser.
     pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> {
         let (attrs, items, span) = self.parse_mod(&token::Eof)?;
-        Ok(ast::Crate { attrs, items, span })
+        Ok(ast::Crate { attrs, items, span, is_placeholder: None })
     }
 
     /// Parses a `mod <foo> { ... }` or `mod <foo>;` item.
@@ -514,7 +514,7 @@ fn parse_item_impl(
                 tokens: None,
             })
         } else {
-            self.parse_ty()?
+            self.parse_ty_with_generics_recovery(&generics)?
         };
 
         // If `for` is missing we try to recover.
index bb3947bb47a2550bd5e82d3a633fd7c006bcbf28..ac3123c40e3d96d78190fccbb073386a8ffe31d4 100644 (file)
@@ -3,14 +3,16 @@
 use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor};
 use rustc_ast::ptr::P;
 use rustc_ast::token;
-use rustc_ast::{self as ast, AttrVec, Attribute, MacCall, Pat, PatField, PatKind, RangeEnd};
-use rustc_ast::{BindingMode, Expr, ExprKind, Mutability, Path, QSelf, RangeSyntax};
+use rustc_ast::{
+    self as ast, AttrVec, Attribute, BindingMode, Expr, ExprKind, MacCall, Mutability, Pat,
+    PatField, PatKind, Path, QSelf, RangeEnd, RangeSyntax,
+};
 use rustc_ast_pretty::pprust;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult};
 use rustc_span::source_map::{respan, Span, Spanned};
 use rustc_span::symbol::{kw, sym, Ident};
 
-type Expected = Option<&'static str>;
+pub(super) type Expected = Option<&'static str>;
 
 /// `Expected` for function and lambda parameter patterns.
 pub(super) const PARAM_EXPECTED: Expected = Some("parameter name");
@@ -98,55 +100,9 @@ fn parse_pat_allow_top_alt_inner(
             // If we parsed a leading `|` which should be gated,
             // then we should really gate the leading `|`.
             // This complicated procedure is done purely for diagnostics UX.
-            let mut first_pat = first_pat;
-
-            if let (RecoverColon::Yes, token::Colon) = (ra, &self.token.kind) {
-                if matches!(
-                    first_pat.kind,
-                    PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, None)
-                        | PatKind::Path(..)
-                ) && self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident())
-                {
-                    // The pattern looks like it might be a path with a `::` -> `:` typo:
-                    // `match foo { bar:baz => {} }`
-                    let span = self.token.span;
-                    // We only emit "unexpected `:`" error here if we can successfully parse the
-                    // whole pattern correctly in that case.
-                    let snapshot = self.clone();
-
-                    // Create error for "unexpected `:`".
-                    match self.expected_one_of_not_found(&[], &[]) {
-                        Err(mut err) => {
-                            self.bump(); // Skip the `:`.
-                            match self.parse_pat_no_top_alt(expected) {
-                                Err(mut inner_err) => {
-                                    // Carry on as if we had not done anything, callers will emit a
-                                    // reasonable error.
-                                    inner_err.cancel();
-                                    err.cancel();
-                                    *self = snapshot;
-                                }
-                                Ok(pat) => {
-                                    // We've parsed the rest of the pattern.
-                                    err.span_suggestion(
-                                        span,
-                                        "maybe write a path separator here",
-                                        "::".to_string(),
-                                        Applicability::MachineApplicable,
-                                    );
-                                    err.emit();
-                                    first_pat =
-                                        self.mk_pat(first_pat.span.to(pat.span), PatKind::Wild);
-                                }
-                            }
-                        }
-                        _ => {
-                            // Carry on as if we had not done anything. This should be unreachable.
-                            *self = snapshot;
-                        }
-                    };
-                }
-            }
+
+            // Check if the user wrote `foo:bar` instead of `foo::bar`.
+            let first_pat = self.maybe_recover_colon_colon_in_pat_typo(first_pat, ra, expected);
 
             if let Some(leading_vert_span) = leading_vert_span {
                 // If there was a leading vert, treat this as an or-pattern. This improves
@@ -321,57 +277,6 @@ fn ban_unexpected_or_or(&mut self, lo: Option<Span>) {
         err.emit();
     }
 
-    /// Some special error handling for the "top-level" patterns in a match arm,
-    /// `for` loop, `let`, &c. (in contrast to subpatterns within such).
-    fn maybe_recover_unexpected_comma(&mut self, lo: Span, rc: RecoverComma) -> PResult<'a, ()> {
-        if rc == RecoverComma::No || self.token != token::Comma {
-            return Ok(());
-        }
-
-        // An unexpected comma after a top-level pattern is a clue that the
-        // user (perhaps more accustomed to some other language) forgot the
-        // parentheses in what should have been a tuple pattern; return a
-        // suggestion-enhanced error here rather than choking on the comma later.
-        let comma_span = self.token.span;
-        self.bump();
-        if let Err(mut err) = self.skip_pat_list() {
-            // We didn't expect this to work anyway; we just wanted to advance to the
-            // end of the comma-sequence so we know the span to suggest parenthesizing.
-            err.cancel();
-        }
-        let seq_span = lo.to(self.prev_token.span);
-        let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern");
-        if let Ok(seq_snippet) = self.span_to_snippet(seq_span) {
-            const MSG: &str = "try adding parentheses to match on a tuple...";
-
-            err.span_suggestion(
-                seq_span,
-                MSG,
-                format!("({})", seq_snippet),
-                Applicability::MachineApplicable,
-            );
-            err.span_suggestion(
-                seq_span,
-                "...or a vertical bar to match on multiple alternatives",
-                seq_snippet.replace(",", " |"),
-                Applicability::MachineApplicable,
-            );
-        }
-        Err(err)
-    }
-
-    /// Parse and throw away a parenthesized comma separated
-    /// sequence of patterns until `)` is reached.
-    fn skip_pat_list(&mut self) -> PResult<'a, ()> {
-        while !self.check(&token::CloseDelim(token::Paren)) {
-            self.parse_pat_no_top_alt(None)?;
-            if !self.eat(&token::Comma) {
-                return Ok(());
-            }
-        }
-        Ok(())
-    }
-
     /// A `|` or possibly `||` token shouldn't be here. Ban it.
     fn ban_illegal_vert(&mut self, lo: Option<Span>, pos: &str, ctx: &str) {
         let span = self.token.span;
@@ -1168,7 +1073,7 @@ pub(super) fn mk_pat_ident(&self, span: Span, bm: BindingMode, ident: Ident) ->
         self.mk_pat(span, PatKind::Ident(bm, ident, None))
     }
 
-    fn mk_pat(&self, span: Span, kind: PatKind) -> P<Pat> {
+    pub(super) fn mk_pat(&self, span: Span, kind: PatKind) -> P<Pat> {
         P(Pat { kind, span, id: ast::DUMMY_NODE_ID, tokens: None })
     }
 }
index c7d080a80fe6f843c07895d292f16ae33e501ccd..7f8fadb33bd8af58de28ee95c09865d98c17bc90 100644 (file)
@@ -3,10 +3,11 @@
 use crate::maybe_whole;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Token};
-use rustc_ast::{self as ast, AngleBracketedArg, AngleBracketedArgs, ParenthesizedArgs};
-use rustc_ast::{AnonConst, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode};
-use rustc_ast::{GenericArg, GenericArgs};
-use rustc_ast::{Path, PathSegment, QSelf};
+use rustc_ast::{
+    self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocTyConstraint,
+    AssocTyConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs,
+    Path, PathSegment, QSelf,
+};
 use rustc_errors::{pluralize, Applicability, PResult};
 use rustc_span::source_map::{BytePos, Span};
 use rustc_span::symbol::{kw, sym, Ident};
@@ -78,7 +79,7 @@ pub(super) fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (QSelf, Pa
         }
 
         let qself = QSelf { ty, path_span, position: path.segments.len() };
-        self.parse_path_segments(&mut path.segments, style)?;
+        self.parse_path_segments(&mut path.segments, style, None)?;
 
         Ok((
             qself,
@@ -119,6 +120,10 @@ fn recover_colon_before_qpath_proj(&mut self) -> bool {
         true
     }
 
+    pub(super) fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> {
+        self.parse_path_inner(style, None)
+    }
+
     /// Parses simple paths.
     ///
     /// `path = [::] segment+`
@@ -129,7 +134,11 @@ fn recover_colon_before_qpath_proj(&mut self) -> bool {
     /// `a::b::C::<D>` (with disambiguator)
     /// `Fn(Args)` (without disambiguator)
     /// `Fn::(Args)` (with disambiguator)
-    pub(super) fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> {
+    pub(super) fn parse_path_inner(
+        &mut self,
+        style: PathStyle,
+        ty_generics: Option<&Generics>,
+    ) -> PResult<'a, Path> {
         maybe_whole!(self, NtPath, |path| {
             if style == PathStyle::Mod && path.segments.iter().any(|segment| segment.args.is_some())
             {
@@ -152,7 +161,7 @@ pub(super) fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> {
         if self.eat(&token::ModSep) {
             segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
         }
-        self.parse_path_segments(&mut segments, style)?;
+        self.parse_path_segments(&mut segments, style, ty_generics)?;
 
         Ok(Path { segments, span: lo.to(self.prev_token.span), tokens: None })
     }
@@ -161,9 +170,10 @@ pub(super) fn parse_path_segments(
         &mut self,
         segments: &mut Vec<PathSegment>,
         style: PathStyle,
+        ty_generics: Option<&Generics>,
     ) -> PResult<'a, ()> {
         loop {
-            let segment = self.parse_path_segment(style)?;
+            let segment = self.parse_path_segment(style, ty_generics)?;
             if style == PathStyle::Expr {
                 // In order to check for trailing angle brackets, we must have finished
                 // recursing (`parse_path_segment` can indirectly call this function),
@@ -191,7 +201,11 @@ pub(super) fn parse_path_segments(
         }
     }
 
-    pub(super) fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> {
+    pub(super) fn parse_path_segment(
+        &mut self,
+        style: PathStyle,
+        ty_generics: Option<&Generics>,
+    ) -> PResult<'a, PathSegment> {
         let ident = self.parse_path_segment_ident()?;
         let is_args_start = |token: &Token| {
             matches!(
@@ -229,8 +243,11 @@ pub(super) fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, Pat
                 let lo = self.token.span;
                 let args = if self.eat_lt() {
                     // `<'a, T, A = U>`
-                    let args =
-                        self.parse_angle_args_with_leading_angle_bracket_recovery(style, lo)?;
+                    let args = self.parse_angle_args_with_leading_angle_bracket_recovery(
+                        style,
+                        lo,
+                        ty_generics,
+                    )?;
                     self.expect_gt()?;
                     let span = lo.to(self.prev_token.span);
                     AngleBracketedArgs { args, span }.into()
@@ -238,9 +255,9 @@ pub(super) fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, Pat
                     // `(T, U) -> R`
                     let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
                     let inputs_span = lo.to(self.prev_token.span);
-                    let span = ident.span.to(self.prev_token.span);
                     let output =
                         self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
+                    let span = ident.span.to(self.prev_token.span);
                     ParenthesizedArgs { span, inputs, inputs_span, output }.into()
                 };
 
@@ -275,6 +292,7 @@ fn parse_angle_args_with_leading_angle_bracket_recovery(
         &mut self,
         style: PathStyle,
         lo: Span,
+        ty_generics: Option<&Generics>,
     ) -> PResult<'a, Vec<AngleBracketedArg>> {
         // We need to detect whether there are extra leading left angle brackets and produce an
         // appropriate error and suggestion. This cannot be implemented by looking ahead at
@@ -350,7 +368,7 @@ fn parse_angle_args_with_leading_angle_bracket_recovery(
         let snapshot = if is_first_invocation { Some(self.clone()) } else { None };
 
         debug!("parse_generic_args_with_leading_angle_bracket_recovery: (snapshotting)");
-        match self.parse_angle_args() {
+        match self.parse_angle_args(ty_generics) {
             Ok(args) => Ok(args),
             Err(mut e) if is_first_invocation && self.unmatched_angle_bracket_count > 0 => {
                 // Swap `self` with our backup of the parser state before attempting to parse
@@ -403,7 +421,7 @@ fn parse_angle_args_with_leading_angle_bracket_recovery(
                     .emit();
 
                     // Try again without unmatched angle bracket characters.
-                    self.parse_angle_args()
+                    self.parse_angle_args(ty_generics)
                 }
             }
             Err(e) => Err(e),
@@ -412,9 +430,12 @@ fn parse_angle_args_with_leading_angle_bracket_recovery(
 
     /// Parses (possibly empty) list of generic arguments / associated item constraints,
     /// possibly including trailing comma.
-    pub(super) fn parse_angle_args(&mut self) -> PResult<'a, Vec<AngleBracketedArg>> {
+    pub(super) fn parse_angle_args(
+        &mut self,
+        ty_generics: Option<&Generics>,
+    ) -> PResult<'a, Vec<AngleBracketedArg>> {
         let mut args = Vec::new();
-        while let Some(arg) = self.parse_angle_arg()? {
+        while let Some(arg) = self.parse_angle_arg(ty_generics)? {
             args.push(arg);
             if !self.eat(&token::Comma) {
                 if !self.token.kind.should_end_const_arg() {
@@ -431,9 +452,12 @@ pub(super) fn parse_angle_args(&mut self) -> PResult<'a, Vec<AngleBracketedArg>>
     }
 
     /// Parses a single argument in the angle arguments `<...>` of a path segment.
-    fn parse_angle_arg(&mut self) -> PResult<'a, Option<AngleBracketedArg>> {
+    fn parse_angle_arg(
+        &mut self,
+        ty_generics: Option<&Generics>,
+    ) -> PResult<'a, Option<AngleBracketedArg>> {
         let lo = self.token.span;
-        let arg = self.parse_generic_arg()?;
+        let arg = self.parse_generic_arg(ty_generics)?;
         match arg {
             Some(arg) => {
                 if self.check(&token::Colon) | self.check(&token::Eq) {
@@ -476,7 +500,7 @@ fn parse_angle_arg(&mut self) -> PResult<'a, Option<AngleBracketedArg>> {
     /// That is, parse `<term>` in `Item = <term>`.
     /// Right now, this only admits types in `<term>`.
     fn parse_assoc_equality_term(&mut self, ident: Ident, eq: Span) -> PResult<'a, P<ast::Ty>> {
-        let arg = self.parse_generic_arg()?;
+        let arg = self.parse_generic_arg(None)?;
         let span = ident.span.to(self.prev_token.span);
         match arg {
             Some(GenericArg::Type(ty)) => return Ok(ty),
@@ -563,7 +587,10 @@ pub(super) fn parse_const_arg(&mut self) -> PResult<'a, AnonConst> {
 
     /// Parse a generic argument in a path segment.
     /// This does not include constraints, e.g., `Item = u8`, which is handled in `parse_angle_arg`.
-    pub(super) fn parse_generic_arg(&mut self) -> PResult<'a, Option<GenericArg>> {
+    pub(super) fn parse_generic_arg(
+        &mut self,
+        ty_generics: Option<&Generics>,
+    ) -> PResult<'a, Option<GenericArg>> {
         let start = self.token.span;
         let arg = if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
             // Parse lifetime argument.
@@ -580,25 +607,8 @@ pub(super) fn parse_generic_arg(&mut self) -> PResult<'a, Option<GenericArg>> {
                     return self.recover_const_arg(start, err).map(Some);
                 }
             }
-        } else if self.eat_keyword_noexpect(kw::Const) {
-            // Detect and recover from the old, pre-RFC2000 syntax for const generics.
-            let mut err = self.struct_span_err(
-                start,
-                "expected lifetime, type, or constant, found keyword `const`",
-            );
-            if self.check_const_arg() {
-                err.span_suggestion_verbose(
-                    start.until(self.token.span),
-                    "the `const` keyword is only needed in the definition of the type",
-                    String::new(),
-                    Applicability::MaybeIncorrect,
-                );
-                err.emit();
-                GenericArg::Const(self.parse_const_arg()?)
-            } else {
-                let after_kw_const = self.token.span;
-                return self.recover_const_arg(after_kw_const, err).map(Some);
-            }
+        } else if self.token.is_keyword(kw::Const) {
+            return self.recover_const_param_declaration(ty_generics);
         } else {
             return Ok(None);
         };
index c4c0c17addf107959d8ed95dd909fb3c1f656330..9bfde0e3900da7f086197b832653f8bf72e5cd96 100644 (file)
@@ -4,9 +4,10 @@
 
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Token, TokenKind};
-use rustc_ast::{self as ast, BareFnTy, FnRetTy, GenericParam, Lifetime, MutTy, Ty, TyKind};
-use rustc_ast::{GenericBound, GenericBounds, MacCall, Mutability};
-use rustc_ast::{PolyTraitRef, TraitBoundModifier, TraitObjectSyntax};
+use rustc_ast::{
+    self as ast, BareFnTy, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime,
+    MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, Ty, TyKind,
+};
 use rustc_errors::{pluralize, struct_span_err, Applicability, PResult};
 use rustc_span::source_map::Span;
 use rustc_span::symbol::{kw, sym};
@@ -98,6 +99,20 @@ pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
             AllowCVariadic::No,
             RecoverQPath::Yes,
             RecoverReturnSign::Yes,
+            None,
+        )
+    }
+
+    pub(super) fn parse_ty_with_generics_recovery(
+        &mut self,
+        ty_params: &Generics,
+    ) -> PResult<'a, P<Ty>> {
+        self.parse_ty_common(
+            AllowPlus::Yes,
+            AllowCVariadic::No,
+            RecoverQPath::Yes,
+            RecoverReturnSign::Yes,
+            Some(ty_params),
         )
     }
 
@@ -110,6 +125,7 @@ pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P<Ty>> {
             AllowCVariadic::Yes,
             RecoverQPath::Yes,
             RecoverReturnSign::Yes,
+            None,
         )
     }
 
@@ -125,6 +141,7 @@ pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
             AllowCVariadic::No,
             RecoverQPath::Yes,
             RecoverReturnSign::Yes,
+            None,
         )
     }
 
@@ -135,6 +152,7 @@ pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>> {
             AllowCVariadic::Yes,
             RecoverQPath::Yes,
             RecoverReturnSign::OnlyFatArrow,
+            None,
         )
     }
 
@@ -152,6 +170,7 @@ pub(super) fn parse_ret_ty(
                 AllowCVariadic::No,
                 recover_qpath,
                 recover_return_sign,
+                None,
             )?;
             FnRetTy::Ty(ty)
         } else if recover_return_sign.can_recover(&self.token.kind) {
@@ -171,6 +190,7 @@ pub(super) fn parse_ret_ty(
                 AllowCVariadic::No,
                 recover_qpath,
                 recover_return_sign,
+                None,
             )?;
             FnRetTy::Ty(ty)
         } else {
@@ -184,6 +204,7 @@ fn parse_ty_common(
         allow_c_variadic: AllowCVariadic,
         recover_qpath: RecoverQPath,
         recover_return_sign: RecoverReturnSign,
+        ty_generics: Option<&Generics>,
     ) -> PResult<'a, P<Ty>> {
         let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
         maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
@@ -233,7 +254,7 @@ fn parse_ty_common(
             let (qself, path) = self.parse_qpath(PathStyle::Type)?;
             TyKind::Path(Some(qself), path)
         } else if self.check_path() {
-            self.parse_path_start_ty(lo, allow_plus)?
+            self.parse_path_start_ty(lo, allow_plus, ty_generics)?
         } else if self.can_begin_bound() {
             self.parse_bare_trait_object(lo, allow_plus)?
         } else if self.eat(&token::DotDotDot) {
@@ -512,9 +533,14 @@ fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
     /// 1. a type macro, `mac!(...)`,
     /// 2. a bare trait object, `B0 + ... + Bn`,
     /// 3. or a path, `path::to::MyType`.
-    fn parse_path_start_ty(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
+    fn parse_path_start_ty(
+        &mut self,
+        lo: Span,
+        allow_plus: AllowPlus,
+        ty_generics: Option<&Generics>,
+    ) -> PResult<'a, TyKind> {
         // Simple path
-        let path = self.parse_path(PathStyle::Type)?;
+        let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;
         if self.eat(&token::Not) {
             // Macro invocation in type position
             Ok(TyKind::MacCall(MacCall {
index f761eaae5ab73652822d584ac0c4b0fd0ef7f92b..7c0b3a57da976857ede72d3871a864f93e9e7493 100644 (file)
@@ -32,7 +32,7 @@ pub(crate) fn target_from_impl_item<'tcx>(
     match impl_item.kind {
         hir::ImplItemKind::Const(..) => Target::AssocConst,
         hir::ImplItemKind::Fn(..) => {
-            let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id());
+            let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id()).expect_owner();
             let containing_item = tcx.hir().expect_item(parent_hir_id);
             let containing_impl_is_for_trait = match &containing_item.kind {
                 hir::ItemKind::Impl(impl_) => impl_.of_trait.is_some(),
@@ -582,7 +582,7 @@ fn check_doc_alias_value(
             Target::Impl => Some("implementation block"),
             Target::ForeignMod => Some("extern block"),
             Target::AssocTy => {
-                let parent_hir_id = self.tcx.hir().get_parent_item(hir_id);
+                let parent_hir_id = self.tcx.hir().get_parent_item(hir_id).expect_owner();
                 let containing_item = self.tcx.hir().expect_item(parent_hir_id);
                 if Target::from_item(containing_item) == Target::Impl {
                     Some("type alias in implementation block")
@@ -591,7 +591,7 @@ fn check_doc_alias_value(
                 }
             }
             Target::AssocConst => {
-                let parent_hir_id = self.tcx.hir().get_parent_item(hir_id);
+                let parent_hir_id = self.tcx.hir().get_parent_item(hir_id).expect_owner();
                 let containing_item = self.tcx.hir().expect_item(parent_hir_id);
                 // We can't link to trait impl's consts.
                 let err = "associated constant in trait implementation block";
index 82486a6a5f2e277a75b639edd84c5127e1af0750..9ccf76b5700c201a84cdcf36c2cf9ff62b8e53e4 100644 (file)
@@ -173,6 +173,12 @@ fn const_check_violated(&self, expr: NonConstExpr, span: Span) {
                 None => return true,
             };
 
+            // If the function belongs to a trait, then it must enable the const_trait_impl
+            // feature to use that trait function (with a const default body).
+            if tcx.trait_of_item(def_id).is_some() {
+                return true;
+            }
+
             // If this crate is not using stability attributes, or this function is not claiming to be a
             // stable `const fn`, that is all that is required.
             if !tcx.features().staged_api || tcx.has_attr(def_id, sym::rustc_const_unstable) {
index af1c724410037e13c624891ea67d34cabc974fca..d01b74930c958d807222866485befabebc36150e 100644 (file)
@@ -7,7 +7,6 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(crate_visibility_modifier)]
 #![feature(in_band_lifetimes)]
-#![cfg_attr(bootstrap, feature(format_args_capture))]
 #![feature(iter_zip)]
 #![feature(map_try_insert)]
 #![feature(min_specialization)]
index ff8bd37238d6bc7db187fb58509da637e6919df1..10b8c3104fcad1eba4031a54fdf9becd7e2f6c40 100644 (file)
@@ -124,12 +124,12 @@ fn visit_attribute(&mut self, _: rustc_hir::HirId, attr: &'tcx Attribute) {
     }
 }
 
-fn get_lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures {
+fn lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures {
     let mut collector = LibFeatureCollector::new(tcx);
     tcx.hir().walk_attributes(&mut collector);
     collector.lib_features
 }
 
 pub fn provide(providers: &mut Providers) {
-    providers.get_lib_features = get_lib_features;
+    providers.lib_features = lib_features;
 }
index bd1e9520ee9fe40cac3f6bae237469b21cb262df..fc56a339215bed380262090e34046a566e6c4856 100644 (file)
@@ -173,8 +173,7 @@ fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool {
                             // Check the impl. If the generics on the self
                             // type of the impl require inlining, this method
                             // does too.
-                            let impl_hir_id = self.tcx.hir().local_def_id_to_hir_id(impl_did);
-                            match self.tcx.hir().expect_item(impl_hir_id).kind {
+                            match self.tcx.hir().expect_item(impl_did).kind {
                                 hir::ItemKind::Impl { .. } => {
                                     let generics = self.tcx.generics_of(impl_did);
                                     generics.requires_monomorphization(self.tcx)
index 6a8feb041da19f5978c4cf6055f79e127bf61ffc..ae423070392e1804d9a0baf249a976c5d20b4c58 100644 (file)
@@ -11,7 +11,7 @@
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc_hir::{Arm, Block, Expr, Local, Node, Pat, PatKind, Stmt};
+use rustc_hir::{Arm, Block, Expr, Local, Pat, PatKind, Stmt};
 use rustc_index::vec::Idx;
 use rustc_middle::middle::region::*;
 use rustc_middle::ty::query::Providers;
@@ -837,19 +837,7 @@ fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree {
 
         let body = tcx.hir().body(body_id);
         visitor.scope_tree.root_body = Some(body.value.hir_id);
-
-        // If the item is an associated const or a method,
-        // record its impl/trait parent, as it can also have
-        // lifetime parameters free in this body.
-        match tcx.hir().get(id) {
-            Node::ImplItem(_) | Node::TraitItem(_) => {
-                visitor.scope_tree.root_parent = Some(tcx.hir().get_parent_item(id));
-            }
-            _ => {}
-        }
-
         visitor.visit_body(body);
-
         visitor.scope_tree
     } else {
         ScopeTree::default()
index 8c9f04bef13769ac3cc65aa9da5a49283cd4d2af..92911c3cd2455c7789ad572b10f87b5d221b9f0e 100644 (file)
@@ -970,7 +970,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
 
     // We always collect the lib features declared in the current crate, even if there are
     // no unknown features, because the collection also does feature attribute validation.
-    let local_defined_features = tcx.lib_features().to_vec();
+    let local_defined_features = tcx.lib_features(()).to_vec();
     if !remaining_lib_features.is_empty() {
         check_features(&mut remaining_lib_features, &local_defined_features);
 
index 11668146f7b105560054110ed66e1c3d2cdd79f7..e3d2c9837cf51063799c52bda6db6223ab1be56e 100644 (file)
@@ -559,8 +559,7 @@ fn update_macro_reachable_def(
             // have normal  hygine, so we can treat them like other items without type
             // privacy and mark them reachable.
             DefKind::Macro(_) => {
-                let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
-                let item = self.tcx.hir().expect_item(hir_id);
+                let item = self.tcx.hir().expect_item(def_id);
                 if let hir::ItemKind::Macro(MacroDef { macro_rules: false, .. }) = item.kind {
                     if vis.is_accessible_from(module.to_def_id(), self.tcx) {
                         self.update(def_id, level);
@@ -581,8 +580,7 @@ fn update_macro_reachable_def(
             DefKind::Struct | DefKind::Union => {
                 // While structs and unions have type privacy, their fields do not.
                 if vis.is_public() {
-                    let item =
-                        self.tcx.hir().expect_item(self.tcx.hir().local_def_id_to_hir_id(def_id));
+                    let item = self.tcx.hir().expect_item(def_id);
                     if let hir::ItemKind::Struct(ref struct_def, _)
                     | hir::ItemKind::Union(ref struct_def, _) = item.kind
                     {
@@ -653,9 +651,7 @@ fn update_visibility_of_intermediate_use_statements(
                 // If the module is `self`, i.e. the current crate,
                 // there will be no corresponding item.
                 .filter(|def_id| def_id.index != CRATE_DEF_INDEX || def_id.krate != LOCAL_CRATE)
-                .and_then(|def_id| {
-                    def_id.as_local().map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id))
-                })
+                .and_then(|def_id| def_id.as_local())
                 .map(|module_hir_id| self.tcx.hir().expect_item(module_hir_id))
             {
                 if let hir::ItemKind::Mod(m) = &item.kind {
index 3cf9d324a38da9d2272d4d6c07321d95d5e57330..d45c064d5e37e5b86d32399886b78beffecb9dfc 100644 (file)
@@ -651,11 +651,6 @@ fn build_reduced_graph_for_use_tree(
 
     /// Constructs the reduced graph for one item.
     fn build_reduced_graph_for_item(&mut self, item: &'b Item) {
-        if matches!(item.kind, ItemKind::Mod(..)) && item.ident.name == kw::Empty {
-            // Fake crate root item from expand.
-            return;
-        }
-
         let parent_scope = &self.parent_scope;
         let parent = parent_scope.module;
         let expansion = parent_scope.expansion;
@@ -683,75 +678,13 @@ fn build_reduced_graph_for_item(&mut self, item: &'b Item) {
             }
 
             ItemKind::ExternCrate(orig_name) => {
-                let module = if orig_name.is_none() && ident.name == kw::SelfLower {
-                    self.r
-                        .session
-                        .struct_span_err(item.span, "`extern crate self;` requires renaming")
-                        .span_suggestion(
-                            item.span,
-                            "try",
-                            "extern crate self as name;".into(),
-                            Applicability::HasPlaceholders,
-                        )
-                        .emit();
-                    return;
-                } else if orig_name == Some(kw::SelfLower) {
-                    self.r.graph_root
-                } else {
-                    let crate_id = self.r.crate_loader.process_extern_crate(
-                        item,
-                        &self.r.definitions,
-                        local_def_id,
-                    );
-                    self.r.extern_crate_map.insert(local_def_id, crate_id);
-                    self.r.expect_module(crate_id.as_def_id())
-                };
-
-                let used = self.process_macro_use_imports(item, module);
-                let binding =
-                    (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas);
-                let import = self.r.arenas.alloc_import(Import {
-                    kind: ImportKind::ExternCrate { source: orig_name, target: ident },
-                    root_id: item.id,
-                    id: item.id,
-                    parent_scope: self.parent_scope,
-                    imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
-                    has_attributes: !item.attrs.is_empty(),
-                    use_span_with_attributes: item.span_with_attributes(),
-                    use_span: item.span,
-                    root_span: item.span,
-                    span: item.span,
-                    module_path: Vec::new(),
-                    vis: Cell::new(vis),
-                    used: Cell::new(used),
-                });
-                self.r.potentially_unused_imports.push(import);
-                let imported_binding = self.r.import(binding, import);
-                if ptr::eq(parent, self.r.graph_root) {
-                    if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0())
-                    {
-                        if expansion != LocalExpnId::ROOT
-                            && orig_name.is_some()
-                            && entry.extern_crate_item.is_none()
-                        {
-                            let msg = "macro-expanded `extern crate` items cannot \
-                                       shadow names passed with `--extern`";
-                            self.r.session.span_err(item.span, msg);
-                        }
-                    }
-                    let entry =
-                        self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert(
-                            ExternPreludeEntry {
-                                extern_crate_item: None,
-                                introduced_by_item: true,
-                            },
-                        );
-                    entry.extern_crate_item = Some(imported_binding);
-                    if orig_name.is_some() {
-                        entry.introduced_by_item = true;
-                    }
-                }
-                self.r.define(parent, ident, TypeNS, imported_binding);
+                self.build_reduced_graph_for_extern_crate(
+                    orig_name,
+                    item,
+                    local_def_id,
+                    vis,
+                    parent,
+                );
             }
 
             ItemKind::Mod(..) => {
@@ -889,6 +822,87 @@ fn build_reduced_graph_for_item(&mut self, item: &'b Item) {
         }
     }
 
+    fn build_reduced_graph_for_extern_crate(
+        &mut self,
+        orig_name: Option<Symbol>,
+        item: &Item,
+        local_def_id: LocalDefId,
+        vis: ty::Visibility,
+        parent: Module<'a>,
+    ) {
+        let ident = item.ident;
+        let sp = item.span;
+        let parent_scope = self.parent_scope;
+        let expansion = parent_scope.expansion;
+
+        let (used, module, binding) = if orig_name.is_none() && ident.name == kw::SelfLower {
+            self.r
+                .session
+                .struct_span_err(item.span, "`extern crate self;` requires renaming")
+                .span_suggestion(
+                    item.span,
+                    "rename the `self` crate to be able to import it",
+                    "extern crate self as name;".into(),
+                    Applicability::HasPlaceholders,
+                )
+                .emit();
+            return;
+        } else if orig_name == Some(kw::SelfLower) {
+            Some(self.r.graph_root)
+        } else {
+            self.r.crate_loader.process_extern_crate(item, &self.r.definitions, local_def_id).map(
+                |crate_id| {
+                    self.r.extern_crate_map.insert(local_def_id, crate_id);
+                    self.r.expect_module(crate_id.as_def_id())
+                },
+            )
+        }
+        .map(|module| {
+            let used = self.process_macro_use_imports(item, module);
+            let binding =
+                (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas);
+            (used, Some(ModuleOrUniformRoot::Module(module)), binding)
+        })
+        .unwrap_or((true, None, self.r.dummy_binding));
+        let import = self.r.arenas.alloc_import(Import {
+            kind: ImportKind::ExternCrate { source: orig_name, target: ident },
+            root_id: item.id,
+            id: item.id,
+            parent_scope: self.parent_scope,
+            imported_module: Cell::new(module),
+            has_attributes: !item.attrs.is_empty(),
+            use_span_with_attributes: item.span_with_attributes(),
+            use_span: item.span,
+            root_span: item.span,
+            span: item.span,
+            module_path: Vec::new(),
+            vis: Cell::new(vis),
+            used: Cell::new(used),
+        });
+        self.r.potentially_unused_imports.push(import);
+        let imported_binding = self.r.import(binding, import);
+        if ptr::eq(parent, self.r.graph_root) {
+            if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) {
+                if expansion != LocalExpnId::ROOT
+                    && orig_name.is_some()
+                    && entry.extern_crate_item.is_none()
+                {
+                    let msg = "macro-expanded `extern crate` items cannot \
+                                       shadow names passed with `--extern`";
+                    self.r.session.span_err(item.span, msg);
+                }
+            }
+            let entry = self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert(
+                ExternPreludeEntry { extern_crate_item: None, introduced_by_item: true },
+            );
+            entry.extern_crate_item = Some(imported_binding);
+            if orig_name.is_some() {
+                entry.introduced_by_item = true;
+            }
+        }
+        self.r.define(parent, ident, TypeNS, imported_binding);
+    }
+
     /// Constructs the reduced graph for one foreign item.
     fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) {
         let local_def_id = self.r.local_def_id(item.id);
@@ -1499,4 +1513,13 @@ fn visit_variant(&mut self, variant: &'b ast::Variant) {
 
         visit::walk_variant(self, variant);
     }
+
+    fn visit_crate(&mut self, krate: &'b ast::Crate) {
+        if let Some(id) = krate.is_placeholder {
+            self.visit_invoc_in_module(id);
+        } else {
+            visit::walk_crate(self, krate);
+            self.contains_macro_use(&krate.attrs);
+        }
+    }
 }
index 5879cb1daa582f5360bb69a332cbf53d3d426635..391baa85c61db99f0f85f63dce33f2065786521c 100644 (file)
@@ -7,7 +7,7 @@
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::definitions::*;
 use rustc_span::hygiene::LocalExpnId;
-use rustc_span::symbol::{kw, sym};
+use rustc_span::symbol::sym;
 use rustc_span::Span;
 use tracing::debug;
 
@@ -92,10 +92,6 @@ fn visit_item(&mut self, i: &'a Item) {
         // information we encapsulate into, the better
         let def_data = match &i.kind {
             ItemKind::Impl { .. } => DefPathData::Impl,
-            ItemKind::Mod(..) if i.ident.name == kw::Empty => {
-                // Fake crate root item from expand.
-                return visit::walk_item(self, i);
-            }
             ItemKind::Mod(..)
             | ItemKind::Trait(..)
             | ItemKind::TraitAlias(..)
@@ -346,4 +342,12 @@ fn visit_param(&mut self, p: &'a Param) {
     fn visit_field_def(&mut self, field: &'a FieldDef) {
         self.collect_field(field, None);
     }
+
+    fn visit_crate(&mut self, krate: &'a Crate) {
+        if let Some(id) = krate.is_placeholder {
+            self.visit_macro_invoc(id)
+        } else {
+            visit::walk_crate(self, krate)
+        }
+    }
 }
index 2e4cb4ff7270d75cd451d9b0f3e3ef301667ec56..6a13627a56314f11cb9359ca9348ed8bafeae7a6 100644 (file)
@@ -1178,7 +1178,7 @@ fn lookup_import_candidates_from_module<FilterFn>(
 
     fn binding_description(&self, b: &NameBinding<'_>, ident: Ident, from_prelude: bool) -> String {
         let res = b.res();
-        if b.span.is_dummy() {
+        if b.span.is_dummy() || self.session.source_map().span_to_snippet(b.span).is_err() {
             // These already contain the "built-in" prefix or look bad with it.
             let add_built_in =
                 !matches!(b.res(), Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod);
index e67f7f03516803c0a7cb7ca7acfb57b9f05f4846..12123c946cc08efac1d0def6f0c87af535f9f174 100644 (file)
@@ -431,6 +431,10 @@ struct LateResolutionVisitor<'a, 'b, 'ast> {
 
 /// Walks the whole crate in DFS order, visiting each item, resolving names as it goes.
 impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
+    fn visit_attribute(&mut self, _: &'ast Attribute) {
+        // We do not want to resolve expressions that appear in attributes,
+        // as they do not correspond to actual code.
+    }
     fn visit_item(&mut self, item: &'ast Item) {
         let prev = replace(&mut self.diagnostic_metadata.current_item, Some(item));
         // Always report errors in items we just entered.
index d506931b516e73d3f6d72c234021ed433861a8bf..69697f275e180658a2ce5c0185a44267d22feb08 100644 (file)
@@ -1871,6 +1871,117 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
         err.emit();
     }
 
+    /// Returns whether to add `'static` lifetime to the suggested lifetime list.
+    crate fn report_elision_failure(
+        &mut self,
+        db: &mut DiagnosticBuilder<'_>,
+        params: &[ElisionFailureInfo],
+    ) -> bool {
+        let mut m = String::new();
+        let len = params.len();
+
+        let elided_params: Vec<_> =
+            params.iter().cloned().filter(|info| info.lifetime_count > 0).collect();
+
+        let elided_len = elided_params.len();
+
+        for (i, info) in elided_params.into_iter().enumerate() {
+            let ElisionFailureInfo { parent, index, lifetime_count: n, have_bound_regions, span } =
+                info;
+
+            db.span_label(span, "");
+            let help_name = if let Some(ident) =
+                parent.and_then(|body| self.tcx.hir().body(body).params[index].pat.simple_ident())
+            {
+                format!("`{}`", ident)
+            } else {
+                format!("argument {}", index + 1)
+            };
+
+            m.push_str(
+                &(if n == 1 {
+                    help_name
+                } else {
+                    format!(
+                        "one of {}'s {} {}lifetimes",
+                        help_name,
+                        n,
+                        if have_bound_regions { "free " } else { "" }
+                    )
+                })[..],
+            );
+
+            if elided_len == 2 && i == 0 {
+                m.push_str(" or ");
+            } else if i + 2 == elided_len {
+                m.push_str(", or ");
+            } else if i != elided_len - 1 {
+                m.push_str(", ");
+            }
+        }
+
+        if len == 0 {
+            db.help(
+                "this function's return type contains a borrowed value, \
+                 but there is no value for it to be borrowed from",
+            );
+            true
+        } else if elided_len == 0 {
+            db.help(
+                "this function's return type contains a borrowed value with \
+                 an elided lifetime, but the lifetime cannot be derived from \
+                 the arguments",
+            );
+            true
+        } else if elided_len == 1 {
+            db.help(&format!(
+                "this function's return type contains a borrowed value, \
+                 but the signature does not say which {} it is borrowed from",
+                m
+            ));
+            false
+        } else {
+            db.help(&format!(
+                "this function's return type contains a borrowed value, \
+                 but the signature does not say whether it is borrowed from {}",
+                m
+            ));
+            false
+        }
+    }
+
+    crate fn report_elided_lifetime_in_ty(&self, lifetime_refs: &[&hir::Lifetime]) {
+        let Some(missing_lifetime) = lifetime_refs.iter().find(|lt| {
+            lt.name == hir::LifetimeName::Implicit(true)
+        }) else { return };
+
+        let mut spans: Vec<_> = lifetime_refs.iter().map(|lt| lt.span).collect();
+        spans.sort();
+        let mut spans_dedup = spans.clone();
+        spans_dedup.dedup();
+        let spans_with_counts: Vec<_> = spans_dedup
+            .into_iter()
+            .map(|sp| (sp, spans.iter().filter(|nsp| *nsp == &sp).count()))
+            .collect();
+
+        self.tcx.struct_span_lint_hir(
+            rustc_session::lint::builtin::ELIDED_LIFETIMES_IN_PATHS,
+            missing_lifetime.hir_id,
+            spans,
+            |lint| {
+                let mut db = lint.build("hidden lifetime parameters in types are deprecated");
+                self.add_missing_lifetime_specifiers_label(
+                    &mut db,
+                    spans_with_counts,
+                    &FxHashSet::from_iter([kw::UnderscoreLifetime]),
+                    Vec::new(),
+                    &[],
+                );
+                db.emit()
+            },
+        );
+    }
+
     // FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const
     // generics. We are disallowing this until we can decide on how we want to handle non-'static
     // lifetimes in const generics. See issue #74052 for discussion.
@@ -2297,7 +2408,9 @@ fn span_underscore_borrow(&self) -> Span {
         );
         let is_allowed_lifetime = matches!(
             lifetime_ref.name,
-            hir::LifetimeName::Implicit | hir::LifetimeName::Static | hir::LifetimeName::Underscore
+            hir::LifetimeName::Implicit(_)
+                | hir::LifetimeName::Static
+                | hir::LifetimeName::Underscore
         );
 
         if !self.tcx.lazy_normalization() && is_anon_const && !is_allowed_lifetime {
index 39e710cb77f3fafd9129d6ad80061aea48ef3837..1ff33689b53c7942708dea0ef483f61a385ca503 100644 (file)
@@ -357,11 +357,11 @@ enum Elide {
 #[derive(Clone, Debug)]
 crate struct ElisionFailureInfo {
     /// Where we can find the argument pattern.
-    parent: Option<hir::BodyId>,
+    crate parent: Option<hir::BodyId>,
     /// The index of the argument in the original definition.
-    index: usize,
-    lifetime_count: usize,
-    have_bound_regions: bool,
+    crate index: usize,
+    crate lifetime_count: usize,
+    crate have_bound_regions: bool,
     crate span: Span,
 }
 
@@ -445,7 +445,7 @@ fn do_resolve(
     trait_definition_only: bool,
     with_scope_for_path: bool,
 ) -> NamedRegionMap {
-    let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(local_def_id));
+    let item = tcx.hir().expect_item(local_def_id);
     let mut named_region_map = NamedRegionMap {
         defs: Default::default(),
         late_bound: Default::default(),
@@ -923,7 +923,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
                     }
                 });
                 match lifetime.name {
-                    LifetimeName::Implicit => {
+                    LifetimeName::Implicit(_) => {
                         // For types like `dyn Foo`, we should
                         // generate a special form of elided.
                         span_bug!(ty.span, "object-lifetime-default expected, not implicit",);
@@ -1134,7 +1134,7 @@ fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
                 self.missing_named_lifetime_spots.push((&trait_item.generics).into());
                 let tcx = self.tcx;
                 self.visit_early_late(
-                    Some(tcx.hir().get_parent_item(trait_item.hir_id())),
+                    Some(tcx.hir().get_parent_did(trait_item.hir_id())),
                     trait_item.hir_id(),
                     &sig.decl,
                     &trait_item.generics,
@@ -1203,7 +1203,7 @@ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
                 self.missing_named_lifetime_spots.push((&impl_item.generics).into());
                 let tcx = self.tcx;
                 self.visit_early_late(
-                    Some(tcx.hir().get_parent_item(impl_item.hir_id())),
+                    Some(tcx.hir().get_parent_did(impl_item.hir_id())),
                     impl_item.hir_id(),
                     &sig.decl,
                     &impl_item.generics,
@@ -2176,7 +2176,7 @@ fn check_uses_for_lifetimes_defined_by_scope(&mut self) {
     /// ordering is not important there.
     fn visit_early_late<F>(
         &mut self,
-        parent_id: Option<hir::HirId>,
+        parent_id: Option<LocalDefId>,
         hir_id: hir::HirId,
         decl: &'tcx hir::FnDecl<'tcx>,
         generics: &'tcx hir::Generics<'tcx>,
@@ -2758,7 +2758,7 @@ fn visit_fn_like_elision(
 
             Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Fn(_, ref m), .. }) => {
                 if let hir::ItemKind::Trait(.., ref trait_items) =
-                    self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind
+                    self.tcx.hir().expect_item(self.tcx.hir().get_parent_did(parent)).kind
                 {
                     assoc_item_kind =
                         trait_items.iter().find(|ti| ti.id.hir_id() == parent).map(|ti| ti.kind);
@@ -2771,7 +2771,7 @@ fn visit_fn_like_elision(
 
             Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body), .. }) => {
                 if let hir::ItemKind::Impl(hir::Impl { ref self_ty, ref items, .. }) =
-                    self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind
+                    self.tcx.hir().expect_item(self.tcx.hir().get_parent_did(parent)).kind
                 {
                     impl_self = Some(self_ty);
                     assoc_item_kind =
@@ -3057,9 +3057,9 @@ fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[&'tcx hir::Lifetime]) {
         let error = loop {
             match *scope {
                 // Do not assign any resolution, it will be inferred.
-                Scope::Body { .. } => return,
+                Scope::Body { .. } => break Ok(()),
 
-                Scope::Root => break None,
+                Scope::Root => break Err(None),
 
                 Scope::Binder { s, ref lifetimes, scope_type, .. } => {
                     // collect named lifetimes for suggestions
@@ -3076,50 +3076,54 @@ fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[&'tcx hir::Lifetime]) {
                     scope = s;
                 }
 
-                Scope::Elision { ref elide, ref s, .. } => {
-                    let lifetime = match *elide {
-                        Elide::FreshLateAnon(named_late_bound_vars, ref counter) => {
-                            for lifetime_ref in lifetime_refs {
-                                let lifetime = Region::late_anon(named_late_bound_vars, counter)
-                                    .shifted(late_depth);
+                Scope::Elision {
+                    elide: Elide::FreshLateAnon(named_late_bound_vars, ref counter),
+                    ..
+                } => {
+                    for lifetime_ref in lifetime_refs {
+                        let lifetime =
+                            Region::late_anon(named_late_bound_vars, counter).shifted(late_depth);
 
-                                self.insert_lifetime(lifetime_ref, lifetime);
-                            }
-                            return;
-                        }
-                        Elide::Exact(l) => l.shifted(late_depth),
-                        Elide::Error(ref e) => {
-                            let mut scope = s;
-                            loop {
-                                match scope {
-                                    Scope::Binder { ref lifetimes, s, .. } => {
-                                        // Collect named lifetimes for suggestions.
-                                        for name in lifetimes.keys() {
-                                            if let hir::ParamName::Plain(name) = name {
-                                                lifetime_names.insert(name.name);
-                                                lifetime_spans.push(name.span);
-                                            }
-                                        }
-                                        scope = s;
-                                    }
-                                    Scope::ObjectLifetimeDefault { ref s, .. }
-                                    | Scope::Elision { ref s, .. }
-                                    | Scope::TraitRefBoundary { ref s, .. } => {
-                                        scope = s;
+                        self.insert_lifetime(lifetime_ref, lifetime);
+                    }
+                    break Ok(());
+                }
+
+                Scope::Elision { elide: Elide::Exact(l), .. } => {
+                    let lifetime = l.shifted(late_depth);
+                    for lifetime_ref in lifetime_refs {
+                        self.insert_lifetime(lifetime_ref, lifetime);
+                    }
+                    break Ok(());
+                }
+
+                Scope::Elision { elide: Elide::Error(ref e), ref s, .. } => {
+                    let mut scope = s;
+                    loop {
+                        match scope {
+                            Scope::Binder { ref lifetimes, s, .. } => {
+                                // Collect named lifetimes for suggestions.
+                                for name in lifetimes.keys() {
+                                    if let hir::ParamName::Plain(name) = name {
+                                        lifetime_names.insert(name.name);
+                                        lifetime_spans.push(name.span);
                                     }
-                                    _ => break,
                                 }
+                                scope = s;
+                            }
+                            Scope::ObjectLifetimeDefault { ref s, .. }
+                            | Scope::Elision { ref s, .. }
+                            | Scope::TraitRefBoundary { ref s, .. } => {
+                                scope = s;
                             }
-                            break Some(&e[..]);
+                            _ => break,
                         }
-                        Elide::Forbid => break None,
-                    };
-                    for lifetime_ref in lifetime_refs {
-                        self.insert_lifetime(lifetime_ref, lifetime);
                     }
-                    return;
+                    break Err(Some(&e[..]));
                 }
 
+                Scope::Elision { elide: Elide::Forbid, .. } => break Err(None),
+
                 Scope::ObjectLifetimeDefault { s, .. }
                 | Scope::Supertrait { s, .. }
                 | Scope::TraitRefBoundary { s, .. } => {
@@ -3128,6 +3132,14 @@ fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[&'tcx hir::Lifetime]) {
             }
         };
 
+        let error = match error {
+            Ok(()) => {
+                self.report_elided_lifetime_in_ty(lifetime_refs);
+                return;
+            }
+            Err(error) => error,
+        };
+
         // If we specifically need the `scope_for_path` map, then we're in the
         // diagnostic pass and we don't want to emit more errors.
         if self.map.scope_for_path.is_some() {
@@ -3166,84 +3178,6 @@ fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[&'tcx hir::Lifetime]) {
         err.emit();
     }
 
-    fn report_elision_failure(
-        &mut self,
-        db: &mut DiagnosticBuilder<'_>,
-        params: &[ElisionFailureInfo],
-    ) -> bool /* add `'static` lifetime to lifetime list */ {
-        let mut m = String::new();
-        let len = params.len();
-
-        let elided_params: Vec<_> =
-            params.iter().cloned().filter(|info| info.lifetime_count > 0).collect();
-
-        let elided_len = elided_params.len();
-
-        for (i, info) in elided_params.into_iter().enumerate() {
-            let ElisionFailureInfo { parent, index, lifetime_count: n, have_bound_regions, span } =
-                info;
-
-            db.span_label(span, "");
-            let help_name = if let Some(ident) =
-                parent.and_then(|body| self.tcx.hir().body(body).params[index].pat.simple_ident())
-            {
-                format!("`{}`", ident)
-            } else {
-                format!("argument {}", index + 1)
-            };
-
-            m.push_str(
-                &(if n == 1 {
-                    help_name
-                } else {
-                    format!(
-                        "one of {}'s {} {}lifetimes",
-                        help_name,
-                        n,
-                        if have_bound_regions { "free " } else { "" }
-                    )
-                })[..],
-            );
-
-            if elided_len == 2 && i == 0 {
-                m.push_str(" or ");
-            } else if i + 2 == elided_len {
-                m.push_str(", or ");
-            } else if i != elided_len - 1 {
-                m.push_str(", ");
-            }
-        }
-
-        if len == 0 {
-            db.help(
-                "this function's return type contains a borrowed value, \
-                 but there is no value for it to be borrowed from",
-            );
-            true
-        } else if elided_len == 0 {
-            db.help(
-                "this function's return type contains a borrowed value with \
-                 an elided lifetime, but the lifetime cannot be derived from \
-                 the arguments",
-            );
-            true
-        } else if elided_len == 1 {
-            db.help(&format!(
-                "this function's return type contains a borrowed value, \
-                 but the signature does not say which {} it is borrowed from",
-                m
-            ));
-            false
-        } else {
-            db.help(&format!(
-                "this function's return type contains a borrowed value, \
-                 but the signature does not say whether it is borrowed from {}",
-                m
-            ));
-            false
-        }
-    }
-
     fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
         debug!("resolve_object_lifetime_default(lifetime_ref={:?})", lifetime_ref);
         let mut late_depth = 0;
@@ -3348,7 +3282,7 @@ fn check_lifetime_params(
                                 ))
                                 .emit();
                         }
-                        hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit => {
+                        hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit(_) => {
                             self.resolve_lifetime_ref(lt);
                         }
                         hir::LifetimeName::ImplicitObjectLifetimeDefault => {
index d17e8875a1ec0d9d58354143f6189a8a9ac3927a..909a809b7814ffd824dc79093c6891b71ae0ad9f 100644 (file)
@@ -13,7 +13,6 @@
 #![feature(drain_filter)]
 #![feature(bool_to_option)]
 #![feature(crate_visibility_modifier)]
-#![cfg_attr(bootstrap, feature(format_args_capture))]
 #![feature(iter_zip)]
 #![feature(let_else)]
 #![feature(never_type)]
@@ -1430,12 +1429,9 @@ fn new_module(
     }
 
     pub fn next_node_id(&mut self) -> NodeId {
-        let next = self
-            .next_node_id
-            .as_usize()
-            .checked_add(1)
-            .expect("input too large; ran out of NodeIds");
-        self.next_node_id = ast::NodeId::from_usize(next);
+        let next =
+            self.next_node_id.as_u32().checked_add(1).expect("input too large; ran out of NodeIds");
+        self.next_node_id = ast::NodeId::from_u32(next);
         self.next_node_id
     }
 
@@ -3288,7 +3284,9 @@ fn extern_prelude_get(
                 Some(binding)
             } else {
                 let crate_id = if !speculative {
-                    self.crate_loader.process_path_extern(ident.name, ident.span)
+                    let Some(crate_id) =
+                        self.crate_loader.process_path_extern(ident.name, ident.span) else { return Some(self.dummy_binding); };
+                    crate_id
                 } else {
                     self.crate_loader.maybe_process_path_extern(ident.name)?
                 };
index ab3c122053c5ebd777d5c65d17fbdb48dcc59118..16b68d95858b87b9c63ef82cc17def481aa69aed 100644 (file)
@@ -833,6 +833,13 @@ pub fn is_empty(&self) -> bool {
             Passes::All => false,
         }
     }
+
+    pub fn extend(&mut self, passes: impl IntoIterator<Item = String>) {
+        match *self {
+            Passes::Some(ref mut v) => v.extend(passes),
+            Passes::All => {}
+        }
+    }
 }
 
 pub const fn default_lib_output() -> CrateType {
index a84e16b9dc31ad1f1ca967866eae9ca11a239d36..779f29e3dfedf32824e7b9cb558bc58e01f3436b 100644 (file)
@@ -567,7 +567,7 @@ mod parse {
             v => {
                 let mut passes = vec![];
                 if parse_list(&mut passes, v) {
-                    *slot = Passes::Some(passes);
+                    slot.extend(passes);
                     true
                 } else {
                     false
@@ -1131,8 +1131,6 @@ mod parse {
     fewer_names: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) \
         (default: no)"),
-    force_overflow_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],
-        "force overflow checks on or off"),
     force_unstable_if_unmarked: bool = (false, parse_bool, [TRACKED],
         "force all crates to be `rustc_private` unstable (default: no)"),
     fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED],
index f7246641dca3e952f8369c034a92c80de8988265..d5b520325e55094c3c1a161d697335da01714667 100644 (file)
@@ -119,8 +119,13 @@ pub struct ParseSess {
     pub config: CrateConfig,
     pub edition: Edition,
     pub missing_fragment_specifiers: Lock<FxHashMap<Span, NodeId>>,
-    /// Places where raw identifiers were used. This is used for feature-gating raw identifiers.
+    /// Places where raw identifiers were used. This is used to avoid complaining about idents
+    /// clashing with keywords in new editions.
     pub raw_identifier_spans: Lock<Vec<Span>>,
+    /// Places where identifiers that contain invalid Unicode codepoints but that look like they
+    /// should be. Useful to avoid bad tokenization when encountering emoji. We group them to
+    /// provide a single error per unique incorrect identifier.
+    pub bad_unicode_identifiers: Lock<FxHashMap<Symbol, Vec<Span>>>,
     source_map: Lrc<SourceMap>,
     pub buffered_lints: Lock<Vec<BufferedEarlyLint>>,
     /// Contains the spans of block expressions that could have been incomplete based on the
@@ -160,6 +165,7 @@ pub fn with_span_handler(handler: Handler, source_map: Lrc<SourceMap>) -> Self {
             edition: ExpnId::root().expn_data().edition,
             missing_fragment_specifiers: Default::default(),
             raw_identifier_spans: Lock::new(Vec::new()),
+            bad_unicode_identifiers: Lock::new(Default::default()),
             source_map,
             buffered_lints: Lock::new(vec![]),
             ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
index 69494e6d9b36a491620c6eda245eb90c0ea44e36..54109559a3bb2fd777c493c067a7f2214b5e5166 100644 (file)
@@ -678,11 +678,7 @@ 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
-            .overflow_checks
-            .or(self.opts.debugging_opts.force_overflow_checks)
-            .unwrap_or(self.opts.debug_assertions)
+        self.opts.cg.overflow_checks.unwrap_or(self.opts.debug_assertions)
     }
 
     /// Check whether this compile session and crate type use static crt.
index d590776676bef53dd3067f5bc6b542a0c21fcefd..315b706fbc44ddb6583f0a412a6aea9f26385559 100644 (file)
@@ -264,7 +264,15 @@ pub fn expn_data(self) -> ExpnData {
         HygieneData::with(|data| data.expn_data(self).clone())
     }
 
+    #[inline]
     pub fn is_descendant_of(self, ancestor: ExpnId) -> bool {
+        // a few "fast path" cases to avoid locking HygieneData
+        if ancestor == ExpnId::root() || ancestor == self {
+            return true;
+        }
+        if ancestor.krate != self.krate {
+            return false;
+        }
         HygieneData::with(|data| data.is_descendant_of(self, ancestor))
     }
 
@@ -376,13 +384,22 @@ fn expn_data(&self, expn_id: ExpnId) -> &ExpnData {
     }
 
     fn is_descendant_of(&self, mut expn_id: ExpnId, ancestor: ExpnId) -> bool {
-        while expn_id != ancestor {
+        // a couple "fast path" cases to avoid traversing parents in the loop below
+        if ancestor == ExpnId::root() {
+            return true;
+        }
+        if expn_id.krate != ancestor.krate {
+            return false;
+        }
+        loop {
+            if expn_id == ancestor {
+                return true;
+            }
             if expn_id == ExpnId::root() {
                 return false;
             }
             expn_id = self.expn_data(expn_id).parent;
         }
-        true
     }
 
     fn normalize_to_macros_2_0(&self, ctxt: SyntaxContext) -> SyntaxContext {
@@ -1223,6 +1240,7 @@ pub fn register_expn_id(
     data: ExpnData,
     hash: ExpnHash,
 ) -> ExpnId {
+    debug_assert!(data.parent == ExpnId::root() || krate == data.parent.krate);
     let expn_id = ExpnId { krate, local_id };
     HygieneData::with(|hygiene_data| {
         let _old_data = hygiene_data.foreign_expn_data.insert(expn_id, data);
index 97b155d2377c789eb8ffa8d46f63d3559cf82b89..06e4cee30ed816b67371c733e5f17080fe3986e0 100644 (file)
         Implied,
         Input,
         Into,
+        IntoFuture,
         IntoIterator,
         IoRead,
         IoWrite,
         gen_future,
         gen_kill,
         generator,
+        generator_return,
         generator_state,
         generators,
         generic_arg_infer,
         inout,
         instruction_set,
         intel,
+        into_future,
         into_iter,
         intra_doc_pointers,
         intrinsics,
@@ -1715,8 +1718,9 @@ fn to_stable_hash_key(&self, _: &CTX) -> SymbolStr {
 // found that to regress performance up to 2% in some cases. This might be
 // revisited after further improvements to `indexmap`.
 //
-// This type is private to prevent accidentally constructing more than one `Interner` on the same
-// thread, which makes it easy to mixup `Symbol`s between `Interner`s.
+// This type is private to prevent accidentally constructing more than one
+// `Interner` on the same thread, which makes it easy to mixup `Symbol`s
+// between `Interner`s.
 #[derive(Default)]
 struct InternerInner {
     arena: DroplessArena,
@@ -1742,14 +1746,20 @@ fn intern(&self, string: &str) -> Symbol {
 
         let name = Symbol::new(inner.strings.len() as u32);
 
-        // `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be
-        // UTF-8.
+        // SAFETY: we convert from `&str` to `&[u8]`, clone it into the arena,
+        // and immediately convert the clone back to `&[u8], all because there
+        // is no `inner.arena.alloc_str()` method. This is clearly safe.
         let string: &str =
             unsafe { str::from_utf8_unchecked(inner.arena.alloc_slice(string.as_bytes())) };
-        // It is safe to extend the arena allocation to `'static` because we only access
-        // these while the arena is still alive.
+
+        // SAFETY: we can extend the arena allocation to `'static` because we
+        // only access these while the arena is still alive.
         let string: &'static str = unsafe { &*(string as *const str) };
         inner.strings.push(string);
+
+        // This second hash table lookup can be avoided by using `RawEntryMut`,
+        // but this code path isn't hot enough for it to be worth it. See
+        // #91445 for details.
         inner.names.insert(string, name);
         name
     }
index 2e00ffc7e14730a916f95b3d3514ad74dc9dfe9d..1ac454be5e9ad558657f3f51dd75ff4e62865980 100644 (file)
@@ -1,4 +1,6 @@
-use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
+use crate::abi::call::{
+    ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, PassMode, Reg, Uniform,
+};
 use crate::abi::{self, HasDataLayout, Size, TyAbiInterface};
 
 fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) {
@@ -115,7 +117,7 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
                             for _ in 0..((offset - last_offset).bits() / 64)
                                 .min((prefix.len() - prefix_index) as u64)
                             {
-                                prefix[prefix_index] = Some(RegKind::Integer);
+                                prefix[prefix_index] = Some(Reg::i64());
                                 prefix_index += 1;
                             }
 
@@ -123,7 +125,7 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
                                 break;
                             }
 
-                            prefix[prefix_index] = Some(RegKind::Float);
+                            prefix[prefix_index] = Some(Reg::f64());
                             prefix_index += 1;
                             last_offset = offset + Reg::f64().size;
                         }
@@ -137,8 +139,13 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
     let rest_size = size - Size::from_bytes(8) * prefix_index as u64;
     arg.cast_to(CastTarget {
         prefix,
-        prefix_chunk_size: Size::from_bytes(8),
         rest: Uniform { unit: Reg::i64(), total: rest_size },
+        attrs: ArgAttributes {
+            regular: ArgAttribute::default(),
+            arg_ext: ArgExtension::None,
+            pointee_size: Size::ZERO,
+            pointee_align: None,
+        },
     });
 }
 
index 4768c9e2db5e109ddca539d463d9b8fb381968ed..735b7e76e3862a5ceaf792d0226c9f4fa7e71625 100644 (file)
@@ -214,9 +214,9 @@ pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub struct CastTarget {
-    pub prefix: [Option<RegKind>; 8],
-    pub prefix_chunk_size: Size,
+    pub prefix: [Option<Reg>; 8],
     pub rest: Uniform,
+    pub attrs: ArgAttributes,
 }
 
 impl From<Reg> for CastTarget {
@@ -227,29 +227,48 @@ fn from(unit: Reg) -> CastTarget {
 
 impl From<Uniform> for CastTarget {
     fn from(uniform: Uniform) -> CastTarget {
-        CastTarget { prefix: [None; 8], prefix_chunk_size: Size::ZERO, rest: uniform }
+        CastTarget {
+            prefix: [None; 8],
+            rest: uniform,
+            attrs: ArgAttributes {
+                regular: ArgAttribute::default(),
+                arg_ext: ArgExtension::None,
+                pointee_size: Size::ZERO,
+                pointee_align: None,
+            },
+        }
     }
 }
 
 impl CastTarget {
     pub fn pair(a: Reg, b: Reg) -> CastTarget {
         CastTarget {
-            prefix: [Some(a.kind), None, None, None, None, None, None, None],
-            prefix_chunk_size: a.size,
+            prefix: [Some(a), None, None, None, None, None, None, None],
             rest: Uniform::from(b),
+            attrs: ArgAttributes {
+                regular: ArgAttribute::default(),
+                arg_ext: ArgExtension::None,
+                pointee_size: Size::ZERO,
+                pointee_align: None,
+            },
         }
     }
 
-    pub fn size<C: HasDataLayout>(&self, cx: &C) -> Size {
-        (self.prefix_chunk_size * self.prefix.iter().filter(|x| x.is_some()).count() as u64)
-            .align_to(self.rest.align(cx))
-            + self.rest.total
+    pub fn size<C: HasDataLayout>(&self, _cx: &C) -> Size {
+        let mut size = self.rest.total;
+        for i in 0..self.prefix.iter().count() {
+            match self.prefix[i] {
+                Some(v) => size += Size { raw: v.size.bytes() },
+                None => {}
+            }
+        }
+        return size;
     }
 
     pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
         self.prefix
             .iter()
-            .filter_map(|x| x.map(|kind| Reg { kind, size: self.prefix_chunk_size }.align(cx)))
+            .filter_map(|x| x.map(|reg| reg.align(cx)))
             .fold(cx.data_layout().aggregate_align.abi.max(self.rest.align(cx)), |acc, align| {
                 acc.max(align)
             })
index 5d74c94e2c6f67c32c91632f1642115822425061..39d80c4c7e76d1ceed26b24194c8af4895c65a49 100644 (file)
@@ -1,7 +1,9 @@
 // FIXME: This needs an audit for correctness and completeness.
 
-use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
-use crate::abi::{HasDataLayout, TyAbiInterface};
+use crate::abi::call::{
+    ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, Reg, RegKind, Uniform,
+};
+use crate::abi::{self, HasDataLayout, Size, TyAbiInterface};
 
 fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
 where
@@ -16,7 +18,7 @@ fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Opti
 
         let valid_unit = match unit.kind {
             RegKind::Integer => false,
-            RegKind::Float => true,
+            RegKind::Float => false,
             RegKind::Vector => arg.layout.size.bits() == 128,
         };
 
@@ -24,33 +26,7 @@ fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Opti
     })
 }
 
-fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
-where
-    Ty: TyAbiInterface<'a, C> + Copy,
-    C: HasDataLayout,
-{
-    if !ret.layout.is_aggregate() {
-        ret.extend_integer_width_to(64);
-        return;
-    }
-
-    if let Some(uniform) = is_homogeneous_aggregate(cx, ret) {
-        ret.cast_to(uniform);
-        return;
-    }
-    let size = ret.layout.size;
-    let bits = size.bits();
-    if bits <= 256 {
-        let unit = Reg::i64();
-        ret.cast_to(Uniform { unit, total: size });
-        return;
-    }
-
-    // don't return aggregates in registers
-    ret.make_indirect();
-}
-
-fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
+fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, in_registers_max: Size)
 where
     Ty: TyAbiInterface<'a, C> + Copy,
     C: HasDataLayout,
@@ -60,13 +36,97 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
         return;
     }
 
+    // This doesn't intentionally handle structures with floats which needs
+    // special care below.
     if let Some(uniform) = is_homogeneous_aggregate(cx, arg) {
         arg.cast_to(uniform);
         return;
     }
 
+    if let abi::FieldsShape::Arbitrary { .. } = arg.layout.fields {
+        let dl = cx.data_layout();
+        let size = arg.layout.size;
+        let mut prefix = [None; 8];
+        let mut prefix_index = 0;
+        let mut last_offset = Size::ZERO;
+        let mut has_float = false;
+        let mut arg_attribute = ArgAttribute::default();
+
+        for i in 0..arg.layout.fields.count() {
+            let field = arg.layout.field(cx, i);
+            let offset = arg.layout.fields.offset(i);
+
+            if let abi::Abi::Scalar(scalar) = &field.abi {
+                if scalar.value == abi::F32 || scalar.value == abi::F64 {
+                    has_float = true;
+
+                    if !last_offset.is_aligned(dl.f64_align.abi) && last_offset < offset {
+                        if prefix_index == prefix.len() {
+                            break;
+                        }
+                        prefix[prefix_index] = Some(Reg::i32());
+                        prefix_index += 1;
+                        last_offset = last_offset + Reg::i32().size;
+                    }
+
+                    for _ in 0..((offset - last_offset).bits() / 64)
+                        .min((prefix.len() - prefix_index) as u64)
+                    {
+                        prefix[prefix_index] = Some(Reg::i64());
+                        prefix_index += 1;
+                        last_offset = last_offset + Reg::i64().size;
+                    }
+
+                    if last_offset < offset {
+                        if prefix_index == prefix.len() {
+                            break;
+                        }
+                        prefix[prefix_index] = Some(Reg::i32());
+                        prefix_index += 1;
+                        last_offset = last_offset + Reg::i32().size;
+                    }
+
+                    if prefix_index == prefix.len() {
+                        break;
+                    }
+
+                    if scalar.value == abi::F32 {
+                        arg_attribute = ArgAttribute::InReg;
+                        prefix[prefix_index] = Some(Reg::f32());
+                        last_offset = offset + Reg::f32().size;
+                    } else {
+                        prefix[prefix_index] = Some(Reg::f64());
+                        last_offset = offset + Reg::f64().size;
+                    }
+                    prefix_index += 1;
+                }
+            }
+        }
+
+        if has_float && arg.layout.size <= in_registers_max {
+            let mut rest_size = size - last_offset;
+
+            if (rest_size.raw % 8) != 0 && prefix_index < prefix.len() {
+                prefix[prefix_index] = Some(Reg::i32());
+                rest_size = rest_size - Reg::i32().size;
+            }
+
+            arg.cast_to(CastTarget {
+                prefix,
+                rest: Uniform { unit: Reg::i64(), total: rest_size },
+                attrs: ArgAttributes {
+                    regular: arg_attribute,
+                    arg_ext: ArgExtension::None,
+                    pointee_size: Size::ZERO,
+                    pointee_align: None,
+                },
+            });
+            return;
+        }
+    }
+
     let total = arg.layout.size;
-    if total.bits() > 128 {
+    if total > in_registers_max {
         arg.make_indirect();
         return;
     }
@@ -80,13 +140,13 @@ pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
     C: HasDataLayout,
 {
     if !fn_abi.ret.is_ignore() {
-        classify_ret(cx, &mut fn_abi.ret);
+        classify_arg(cx, &mut fn_abi.ret, Size { raw: 32 });
     }
 
     for arg in &mut fn_abi.args {
         if arg.is_ignore() {
             continue;
         }
-        classify_arg(cx, arg);
+        classify_arg(cx, arg, Size { raw: 16 });
     }
 }
index ca3550e9278d10426b2a7902e695c01849f60157..3ffc852d65080c1cfd16a32fd2b172fa929ef01c 100644 (file)
@@ -9,19 +9,19 @@ pub fn target() -> Target {
     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.extend(super::apple_base::macos_link_env("arm64"));
     base.link_env_remove.extend(super::apple_base::macos_link_env_remove());
 
     // Clang automatically chooses a more specific target based on
     // MACOSX_DEPLOYMENT_TARGET.  To enable cross-language LTO to work
     // correctly, we do too.
-    let arch = "aarch64";
-    let llvm_target = super::apple_base::macos_llvm_target(&arch);
+    let llvm_target = super::apple_base::macos_llvm_target("arm64");
 
     Target {
         llvm_target,
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(),
-        arch: arch.to_string(),
+        arch: "aarch64".to_string(),
         options: TargetOptions {
             mcount: "\u{1}mcount".to_string(),
             frame_pointer: FramePointer::NonLeaf,
index a21b784e11b1ca4578c3dd7454704e87720e0e1e..ba8f9a8ce11607fcc04629a97b9ccf45e0aaabda 100644 (file)
@@ -13,8 +13,10 @@ pub fn opts(os: &str) -> TargetOptions {
     // warnings about the usage of ELF TLS.
     //
     // Here we detect what version is being requested, defaulting to 10.7. ELF
-    // TLS is flagged as enabled if it looks to be supported.
-    let version = macos_deployment_target();
+    // TLS is flagged as enabled if it looks to be supported. The architecture
+    // only matters for default deployment target which is 11.0 for ARM64 and
+    // 10.7 for everything else.
+    let has_elf_tls = macos_deployment_target("x86_64") >= (10, 7);
 
     TargetOptions {
         os: os.to_string(),
@@ -31,7 +33,7 @@ pub fn opts(os: &str) -> TargetOptions {
         has_rpath: true,
         dll_suffix: ".dylib".to_string(),
         archive_format: "darwin".to_string(),
-        has_elf_tls: version >= (10, 7),
+        has_elf_tls,
         abi_return_struct_as_int: true,
         emit_debug_gdb_scripts: false,
         eh_frame_header: false,
@@ -63,15 +65,32 @@ fn deployment_target(var_name: &str) -> Option<(u32, u32)> {
         .and_then(|(a, b)| a.parse::<u32>().and_then(|a| b.parse::<u32>().map(|b| (a, b))).ok())
 }
 
-fn macos_deployment_target() -> (u32, u32) {
-    deployment_target("MACOSX_DEPLOYMENT_TARGET").unwrap_or((10, 7))
+fn macos_default_deployment_target(arch: &str) -> (u32, u32) {
+    if arch == "arm64" { (11, 0) } else { (10, 7) }
+}
+
+fn macos_deployment_target(arch: &str) -> (u32, u32) {
+    deployment_target("MACOSX_DEPLOYMENT_TARGET")
+        .unwrap_or_else(|| macos_default_deployment_target(arch))
 }
 
 pub fn macos_llvm_target(arch: &str) -> String {
-    let (major, minor) = macos_deployment_target();
+    let (major, minor) = macos_deployment_target(arch);
     format!("{}-apple-macosx{}.{}.0", arch, major, minor)
 }
 
+pub fn macos_link_env(arch: &str) -> Vec<(String, String)> {
+    // Use the default deployment target for linking just as with the LLVM target if not
+    // specified via MACOSX_DEPLOYMENT_TARGET, otherwise the system linker would use its
+    // default which varies with Xcode version.
+    if env::var("MACOSX_DEPLOYMENT_TARGET").is_err() {
+        let default = macos_default_deployment_target(arch);
+        vec![("MACOSX_DEPLOYMENT_TARGET".to_string(), format!("{}.{}", default.0, default.1))]
+    } else {
+        vec![]
+    }
+}
+
 pub fn macos_link_env_remove() -> Vec<String> {
     let mut env_remove = Vec::with_capacity(2);
     // Remove the `SDKROOT` environment variable if it's clearly set for the wrong platform, which
index f2635f0656d7a738445df4d41d1dda6302f935ed..05217c09aedd0dca102e295f2b4472712c86d05b 100644 (file)
@@ -5,6 +5,7 @@ pub fn target() -> Target {
     base.cpu = "yonah".to_string();
     base.max_atomic_width = Some(64);
     base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".to_string()]);
+    base.link_env.extend(super::apple_base::macos_link_env("i686"));
     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;
index 22fdaabfcb89b68821fde9b65c7a137c2b1439ba..3e20cb0b272ce8a682509b5e81a7909cf6f9828a 100644 (file)
@@ -10,6 +10,7 @@ pub fn target() -> Target {
         LinkerFlavor::Gcc,
         vec!["-m64".to_string(), "-arch".to_string(), "x86_64".to_string()],
     );
+    base.link_env.extend(super::apple_base::macos_link_env("x86_64"));
     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;
index f8df0e2595973ea54800a053bcd71a742b00bdf5..d9f86fbc23b5d192bc9a84858352ecceab2e1cf1 100644 (file)
@@ -539,11 +539,6 @@ fn report_selection_error(
                         // is otherwise overwhelming and unhelpful (see #85844 for an
                         // example).
 
-                        let trait_is_debug =
-                            self.tcx.is_diagnostic_item(sym::Debug, trait_ref.def_id());
-                        let trait_is_display =
-                            self.tcx.is_diagnostic_item(sym::Display, trait_ref.def_id());
-
                         let in_std_macro =
                             match obligation.cause.span.ctxt().outer_expn_data().macro_def_id {
                                 Some(macro_def_id) => {
@@ -553,7 +548,12 @@ fn report_selection_error(
                                 None => false,
                             };
 
-                        if in_std_macro && (trait_is_debug || trait_is_display) {
+                        if in_std_macro
+                            && matches!(
+                                self.tcx.get_diagnostic_name(trait_ref.def_id()),
+                                Some(sym::Debug | sym::Display)
+                            )
+                        {
                             err.emit();
                             return;
                         }
@@ -2025,9 +2025,7 @@ fn maybe_suggest_unsized_generics(
         debug!("maybe_suggest_unsized_generics: param={:?}", param);
         match node {
             hir::Node::Item(
-                item
-                @
-                hir::Item {
+                item @ hir::Item {
                     // Only suggest indirection for uses of type parameters in ADTs.
                     kind:
                         hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Union(..),
index 1364cf1c9953512f925106e382f141a3bc893a5d..26bacf787e2ebaded063e0854d2b9d55c5163436 100644 (file)
@@ -12,7 +12,7 @@
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_infer::traits::Normalized;
 use rustc_middle::mir;
-use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
+use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder};
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
 
@@ -61,7 +61,6 @@ fn normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
             cause: self.cause,
             param_env: self.param_env,
             obligations: vec![],
-            error: false,
             cache: SsoHashMap::new(),
             anon_depth: 0,
             universes: vec![],
@@ -88,7 +87,7 @@ fn normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
                 normalizer.universes.extend((0..max_visitor.escaping).map(|_| None));
             }
         }
-        let result = value.fold_with(&mut normalizer);
+        let result = value.try_fold_with(&mut normalizer);
         info!(
             "normalize::<{}>: result={:?} with {} obligations",
             std::any::type_name::<T>(),
@@ -100,11 +99,7 @@ fn normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
             std::any::type_name::<T>(),
             normalizer.obligations,
         );
-        if normalizer.error {
-            Err(NoSolution)
-        } else {
-            Ok(Normalized { value: result, obligations: normalizer.obligations })
-        }
+        result.map(|value| Normalized { value, obligations: normalizer.obligations })
     }
 }
 
@@ -171,34 +166,37 @@ struct QueryNormalizer<'cx, 'tcx> {
     param_env: ty::ParamEnv<'tcx>,
     obligations: Vec<PredicateObligation<'tcx>>,
     cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
-    error: bool,
     anon_depth: usize,
     universes: Vec<Option<ty::UniverseIndex>>,
 }
 
 impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
+    type Error = NoSolution;
+
     fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
+}
 
-    fn fold_binder<T: TypeFoldable<'tcx>>(
+impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
+    fn try_fold_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: ty::Binder<'tcx, T>,
-    ) -> ty::Binder<'tcx, T> {
+    ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
         self.universes.push(None);
-        let t = t.super_fold_with(self);
+        let t = t.try_super_fold_with(self);
         self.universes.pop();
         t
     }
 
     #[instrument(level = "debug", skip(self))]
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+    fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         if !needs_normalization(&ty, self.param_env.reveal()) {
-            return ty;
+            return Ok(ty);
         }
 
         if let Some(ty) = self.cache.get(&ty) {
-            return ty;
+            return Ok(ty);
         }
 
         // See note in `rustc_trait_selection::traits::project` about why we
@@ -212,10 +210,10 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
             ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
                 // Only normalize `impl Trait` after type-checking, usually in codegen.
                 match self.param_env.reveal() {
-                    Reveal::UserFacing => ty.super_fold_with(self),
+                    Reveal::UserFacing => ty.try_super_fold_with(self),
 
                     Reveal::All => {
-                        let substs = substs.super_fold_with(self);
+                        let substs = substs.try_super_fold_with(self)?;
                         let recursion_limit = self.tcx().recursion_limit();
                         if !recursion_limit.value_within_limit(self.anon_depth) {
                             let obligation = Obligation::with_depth(
@@ -240,7 +238,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                                 ty
                             );
                         }
-                        let folded_ty = ensure_sufficient_stack(|| self.fold_ty(concrete_ty));
+                        let folded_ty = ensure_sufficient_stack(|| self.try_fold_ty(concrete_ty));
                         self.anon_depth -= 1;
                         folded_ty
                     }
@@ -252,7 +250,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 // we don't need to replace them with placeholders (see branch below).
 
                 let tcx = self.infcx.tcx;
-                let data = data.super_fold_with(self);
+                let data = data.try_super_fold_with(self)?;
 
                 let mut orig_values = OriginalQueryValues::default();
                 // HACK(matthewjasper) `'static` is special-cased in selection,
@@ -262,39 +260,22 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                     .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values);
                 debug!("QueryNormalizer: c_data = {:#?}", c_data);
                 debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
-                match tcx.normalize_projection_ty(c_data) {
-                    Ok(result) => {
-                        // We don't expect ambiguity.
-                        if result.is_ambiguous() {
-                            self.error = true;
-                            return ty.super_fold_with(self);
-                        }
-
-                        match self.infcx.instantiate_query_response_and_region_obligations(
-                            self.cause,
-                            self.param_env,
-                            &orig_values,
-                            result,
-                        ) {
-                            Ok(InferOk { value: result, obligations }) => {
-                                debug!("QueryNormalizer: result = {:#?}", result);
-                                debug!("QueryNormalizer: obligations = {:#?}", obligations);
-                                self.obligations.extend(obligations);
-                                result.normalized_ty
-                            }
-
-                            Err(_) => {
-                                self.error = true;
-                                ty.super_fold_with(self)
-                            }
-                        }
-                    }
-
-                    Err(NoSolution) => {
-                        self.error = true;
-                        ty.super_fold_with(self)
-                    }
+                let result = tcx.normalize_projection_ty(c_data)?;
+                // We don't expect ambiguity.
+                if result.is_ambiguous() {
+                    return Err(NoSolution);
                 }
+                let InferOk { value: result, obligations } =
+                    self.infcx.instantiate_query_response_and_region_obligations(
+                        self.cause,
+                        self.param_env,
+                        &orig_values,
+                        result,
+                    )?;
+                debug!("QueryNormalizer: result = {:#?}", result);
+                debug!("QueryNormalizer: obligations = {:#?}", obligations);
+                self.obligations.extend(obligations);
+                Ok(result.normalized_ty)
             }
 
             ty::Projection(data) => {
@@ -308,7 +289,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                         &mut self.universes,
                         data,
                     );
-                let data = data.super_fold_with(self);
+                let data = data.try_super_fold_with(self)?;
 
                 let mut orig_values = OriginalQueryValues::default();
                 // HACK(matthewjasper) `'static` is special-cased in selection,
@@ -318,57 +299,49 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                     .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values);
                 debug!("QueryNormalizer: c_data = {:#?}", c_data);
                 debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
-                match tcx.normalize_projection_ty(c_data) {
-                    Ok(result) => {
-                        // We don't expect ambiguity.
-                        if result.is_ambiguous() {
-                            self.error = true;
-                            return ty.super_fold_with(self);
-                        }
-                        match self.infcx.instantiate_query_response_and_region_obligations(
-                            self.cause,
-                            self.param_env,
-                            &orig_values,
-                            result,
-                        ) {
-                            Ok(InferOk { value: result, obligations }) => {
-                                debug!("QueryNormalizer: result = {:#?}", result);
-                                debug!("QueryNormalizer: obligations = {:#?}", obligations);
-                                self.obligations.extend(obligations);
-                                crate::traits::project::PlaceholderReplacer::replace_placeholders(
-                                    infcx,
-                                    mapped_regions,
-                                    mapped_types,
-                                    mapped_consts,
-                                    &self.universes,
-                                    result.normalized_ty,
-                                )
-                            }
-                            Err(_) => {
-                                self.error = true;
-                                ty.super_fold_with(self)
-                            }
-                        }
-                    }
-                    Err(NoSolution) => {
-                        self.error = true;
-                        ty.super_fold_with(self)
-                    }
+                let result = tcx.normalize_projection_ty(c_data)?;
+                // We don't expect ambiguity.
+                if result.is_ambiguous() {
+                    return Err(NoSolution);
                 }
+                let InferOk { value: result, obligations } =
+                    self.infcx.instantiate_query_response_and_region_obligations(
+                        self.cause,
+                        self.param_env,
+                        &orig_values,
+                        result,
+                    )?;
+                debug!("QueryNormalizer: result = {:#?}", result);
+                debug!("QueryNormalizer: obligations = {:#?}", obligations);
+                self.obligations.extend(obligations);
+                Ok(crate::traits::project::PlaceholderReplacer::replace_placeholders(
+                    infcx,
+                    mapped_regions,
+                    mapped_types,
+                    mapped_consts,
+                    &self.universes,
+                    result.normalized_ty,
+                ))
             }
 
-            _ => ty.super_fold_with(self),
-        })();
+            _ => ty.try_super_fold_with(self),
+        })()?;
         self.cache.insert(ty, res);
-        res
+        Ok(res)
     }
 
-    fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
-        let constant = constant.super_fold_with(self);
-        constant.eval(self.infcx.tcx, self.param_env)
+    fn try_fold_const(
+        &mut self,
+        constant: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+        let constant = constant.try_super_fold_with(self)?;
+        Ok(constant.eval(self.infcx.tcx, self.param_env))
     }
 
-    fn fold_mir_const(&mut self, constant: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
-        constant.super_fold_with(self)
+    fn try_fold_mir_const(
+        &mut self,
+        constant: mir::ConstantKind<'tcx>,
+    ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
+        constant.try_super_fold_with(self)
     }
 }
index 1d0c54f86dea8bef96e9edb4f930df885799f9ad..6e3e3b9b14480d383fdad71dd9a6829647b5b61f 100644 (file)
@@ -304,7 +304,7 @@ pub(super) fn assemble_candidates<'o>(
                 && obligation.predicate.skip_binder().constness == ty::BoundConstness::ConstIfConst
             {
                 if self.is_in_const_context {
-                    self.assemble_const_drop_candidates(obligation, &mut candidates)?;
+                    self.assemble_const_drop_candidates(obligation, stack, &mut candidates)?;
                 } else {
                     debug!("passing ~const Drop bound; in non-const context");
                     // `~const Drop` when we are not in a const context has no effect.
@@ -536,7 +536,10 @@ fn assemble_candidates_from_impls(
         // This helps us avoid overflow: see issue #72839
         // Since compilation is already guaranteed to fail, this is just
         // to try to show the 'nicest' possible errors to the user.
-        if obligation.references_error() {
+        // We don't check for errors in the `ParamEnv` - in practice,
+        // it seems to cause us to be overly aggressive in deciding
+        // to give up searching for candidates, leading to spurious errors.
+        if obligation.predicate.references_error() {
             return;
         }
 
@@ -911,9 +914,10 @@ fn assemble_builtin_bound_candidates(
         }
     }
 
-    fn assemble_const_drop_candidates(
+    fn assemble_const_drop_candidates<'a>(
         &mut self,
         obligation: &TraitObligation<'tcx>,
+        obligation_stack: &TraitObligationStack<'a, 'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) -> Result<(), SelectionError<'tcx>> {
         let mut stack: Vec<(Ty<'tcx>, usize)> = vec![(obligation.self_ty().skip_binder(), 0)];
@@ -922,7 +926,7 @@ fn assemble_const_drop_candidates(
             let mut noreturn = false;
 
             self.check_recursion_depth(depth, obligation)?;
-            let mut copy_candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
+            let mut new_candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
             let mut copy_obligation =
                 obligation.with(obligation.predicate.rebind(ty::TraitPredicate {
                     trait_ref: ty::TraitRef {
@@ -933,13 +937,29 @@ fn assemble_const_drop_candidates(
                     polarity: ty::ImplPolarity::Positive,
                 }));
             copy_obligation.recursion_depth = depth + 1;
-            self.assemble_candidates_from_impls(&copy_obligation, &mut copy_candidates);
+            self.assemble_candidates_from_impls(&copy_obligation, &mut new_candidates);
             let copy_conditions = self.copy_clone_conditions(&copy_obligation);
-            self.assemble_builtin_bound_candidates(copy_conditions, &mut copy_candidates);
-            if !copy_candidates.vec.is_empty() {
+            self.assemble_builtin_bound_candidates(copy_conditions, &mut new_candidates);
+            let copy_stack = self.push_stack(obligation_stack.list(), &copy_obligation);
+            self.assemble_candidates_from_caller_bounds(&copy_stack, &mut new_candidates)?;
+
+            let const_drop_obligation =
+                obligation.with(obligation.predicate.rebind(ty::TraitPredicate {
+                    trait_ref: ty::TraitRef {
+                        def_id: self.tcx().require_lang_item(hir::LangItem::Drop, None),
+                        substs: self.tcx().mk_substs_trait(ty, &[]),
+                    },
+                    constness: ty::BoundConstness::ConstIfConst,
+                    polarity: ty::ImplPolarity::Positive,
+                }));
+
+            let const_drop_stack = self.push_stack(obligation_stack.list(), &const_drop_obligation);
+            self.assemble_candidates_from_caller_bounds(&const_drop_stack, &mut new_candidates)?;
+
+            if !new_candidates.vec.is_empty() {
                 noreturn = true;
             }
-            debug!(?copy_candidates.vec, "assemble_const_drop_candidates - copy");
+            debug!(?new_candidates.vec, "assemble_const_drop_candidates");
 
             match ty.kind() {
                 ty::Int(_)
index 2aa214694cb1472cd54827befdd2ee2b50a0b7d9..32d04b55754fc62025eb173923f47515af4cea37 100644 (file)
@@ -558,7 +558,11 @@ fn evaluate_predicate_recursively<'o>(
                 },
 
                 ty::PredicateKind::TypeOutlives(pred) => {
-                    if pred.0.is_known_global() {
+                    // A global type with no late-bound regions can only
+                    // contain the "'static" lifetime (any other lifetime
+                    // would either be late-bound or local), so it is guaranteed
+                    // to outlive any other lifetime
+                    if pred.0.is_global(self.infcx.tcx) && !pred.0.has_late_bound_regions() {
                         Ok(EvaluatedToOk)
                     } else {
                         Ok(EvaluatedToOkModuloRegions)
index 61ab5e28b6796151eabdf015a72abfc247aa0a41..4f35909df7f6a8d1ff200a93dad4dcbc21fe5b2c 100644 (file)
         normalize_mir_const_after_erasing_regions: |tcx, goal| {
             normalize_after_erasing_regions(tcx, goal)
         },
+        try_normalize_generic_arg_after_erasing_regions: |tcx, goal| {
+            debug!("try_normalize_generic_arg_after_erasing_regions(goal={:#?}", goal);
+
+            try_normalize_after_erasing_regions(tcx, goal)
+        },
+        try_normalize_mir_const_after_erasing_regions: |tcx, goal| {
+            try_normalize_after_erasing_regions(tcx, goal)
+        },
         ..*p
     };
 }
@@ -56,6 +64,38 @@ fn normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq + Cop
     })
 }
 
+#[instrument(level = "debug", skip(tcx))]
+fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq + Copy>(
+    tcx: TyCtxt<'tcx>,
+    goal: ParamEnvAnd<'tcx, T>,
+) -> Result<T, NoSolution> {
+    let ParamEnvAnd { param_env, value } = goal;
+    tcx.infer_ctxt().enter(|infcx| {
+        let cause = ObligationCause::dummy();
+        match infcx.at(&cause, param_env).normalize(value) {
+            Ok(Normalized { value: normalized_value, obligations: normalized_obligations }) => {
+                // We don't care about the `obligations`; they are
+                // always only region relations, and we are about to
+                // erase those anyway:
+                debug_assert_eq!(
+                    normalized_obligations.iter().find(|p| not_outlives_predicate(&p.predicate)),
+                    None,
+                );
+
+                let resolved_value = infcx.resolve_vars_if_possible(normalized_value);
+                // It's unclear when `resolve_vars` would have an effect in a
+                // fresh `InferCtxt`. If this assert does trigger, it will give
+                // us a test case.
+                debug_assert_eq!(normalized_value, resolved_value);
+                let erased = infcx.tcx.erase_regions(resolved_value);
+                debug_assert!(!erased.needs_infer(), "{:?}", erased);
+                Ok(erased)
+            }
+            Err(NoSolution) => Err(NoSolution),
+        }
+    })
+}
+
 fn not_outlives_predicate(p: &ty::Predicate<'tcx>) -> bool {
     match p.kind().skip_binder() {
         ty::PredicateKind::RegionOutlives(..) | ty::PredicateKind::TypeOutlives(..) => false,
index 595b623b02078078f2348ecf5b8119b1c3080533..fc309aa848ca195d39c755f0ffb8f196b3ca2fc0 100644 (file)
@@ -147,8 +147,10 @@ fn next(&mut self) -> Option<NeedsDropResult<Ty<'tcx>>> {
                             Ok(tys) => tys,
                         };
                         for required_ty in tys {
-                            let required =
-                                tcx.normalize_erasing_regions(self.param_env, required_ty);
+                            let required = tcx
+                                .try_normalize_erasing_regions(self.param_env, required_ty)
+                                .unwrap_or(required_ty);
+
                             queue_type(self, required);
                         }
                     }
index af3706f886e9cbce53fb4e6be54c5ee1872432e4..711a6f2fbebdd44d792d736b2a5e32704a6234e4 100644 (file)
@@ -123,7 +123,7 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
     let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
     let parent_id = tcx.hir().get_parent_item(id);
     let parent_def_id = tcx.hir().local_def_id(parent_id);
-    let parent_item = tcx.hir().expect_item(parent_id);
+    let parent_item = tcx.hir().expect_item(parent_def_id);
     match parent_item.kind {
         hir::ItemKind::Impl(ref impl_) => {
             if let Some(impl_item_ref) =
@@ -158,8 +158,7 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
 }
 
 fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-    let item = tcx.hir().expect_item(hir_id);
+    let item = tcx.hir().expect_item(def_id.expect_local());
     if let hir::ItemKind::Impl(impl_) = &item.kind {
         impl_.defaultness
     } else {
@@ -168,8 +167,7 @@ fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness {
 }
 
 fn impl_constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-    let item = tcx.hir().expect_item(hir_id);
+    let item = tcx.hir().expect_item(def_id.expect_local());
     if let hir::ItemKind::Impl(impl_) = &item.kind {
         impl_.constness
     } else {
@@ -202,8 +200,7 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtSizedConstrain
 }
 
 fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
-    let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-    let item = tcx.hir().expect_item(id);
+    let item = tcx.hir().expect_item(def_id.expect_local());
     match item.kind {
         hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter(
             trait_item_refs.iter().map(|trait_item_ref| trait_item_ref.id.def_id.to_def_id()),
index bb1d9744e66fe068447885de77b80c62f789339a..2061f955d968fb9258877e17167976d376d8416a 100644 (file)
@@ -458,7 +458,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
     def_id: LocalDefId,
     span: Span,
 ) {
-    let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(def_id));
+    let item = tcx.hir().expect_item(def_id);
     debug!(?item, ?span);
 
     struct FoundParentLifetime;
index 28712e0658269d5338fdd39ace5c3a713cc6838e..b4810b4e22fe4f8a6603f1e640c419200d5fe81a 100644 (file)
@@ -1126,8 +1126,10 @@ fn try_find_coercion_lub<E>(
         for expr in exprs {
             let expr = expr.as_coercion_site();
             let noop = match self.typeck_results.borrow().expr_adjustments(expr) {
-                &[Adjustment { kind: Adjust::Deref(_), .. }, Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl_adj)), .. }] =>
-                {
+                &[
+                    Adjustment { kind: Adjust::Deref(_), .. },
+                    Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl_adj)), .. },
+                ] => {
                     match *self.node_ty(expr.hir_id).kind() {
                         ty::Ref(_, _, mt_orig) => {
                             let mutbl_adj: hir::Mutability = mutbl_adj.into();
@@ -1458,7 +1460,7 @@ pub fn coerce_forced_unit<'a>(
                             cause,
                             expected,
                             found,
-                            coercion_error,
+                            coercion_error.clone(),
                             fcx,
                             parent_id,
                             expression.map(|expr| (expr, blk_id)),
@@ -1472,7 +1474,7 @@ pub fn coerce_forced_unit<'a>(
                             cause,
                             expected,
                             found,
-                            coercion_error,
+                            coercion_error.clone(),
                             fcx,
                             id,
                             None,
@@ -1483,7 +1485,12 @@ pub fn coerce_forced_unit<'a>(
                         }
                     }
                     _ => {
-                        err = fcx.report_mismatched_types(cause, expected, found, coercion_error);
+                        err = fcx.report_mismatched_types(
+                            cause,
+                            expected,
+                            found,
+                            coercion_error.clone(),
+                        );
                     }
                 }
 
@@ -1492,7 +1499,14 @@ pub fn coerce_forced_unit<'a>(
                 }
 
                 if let Some(expr) = expression {
-                    fcx.emit_coerce_suggestions(&mut err, expr, found, expected, None);
+                    fcx.emit_coerce_suggestions(
+                        &mut err,
+                        expr,
+                        found,
+                        expected,
+                        None,
+                        coercion_error,
+                    );
                 }
 
                 err.emit_unless(unsized_return);
@@ -1625,11 +1639,10 @@ fn add_impl_trait_explanation<'a>(
                 let ty = <dyn AstConv<'_>>::ast_ty_to_ty(fcx, ty);
                 // Get the `impl Trait`'s `DefId`.
                 if let ty::Opaque(def_id, _) = ty.kind() {
-                    let hir_id = fcx.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
                     // Get the `impl Trait`'s `Item` so that we can get its trait bounds and
                     // get the `Trait`'s `DefId`.
                     if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }) =
-                        fcx.tcx.hir().expect_item(hir_id).kind
+                        fcx.tcx.hir().expect_item(def_id.expect_local()).kind
                     {
                         // Are of this `impl Trait`'s traits object safe?
                         is_object_safe = bounds.iter().all(|bound| {
index 4d4662f73a9556023a59408bb35103ec7563856c..44fc81a889d1732b404cee3674066f1e1f2744e4 100644 (file)
@@ -264,14 +264,9 @@ fn compare_predicate_entailment<'tcx>(
         // First liberate late bound regions and subst placeholders
         let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(trait_m.def_id));
         let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs);
-        // Next, add all inputs and output as well-formed tys. Importantly,
-        // we have to do this before normalization, since the normalized ty may
-        // not contain the input parameters. See issue #87748.
-        wf_tys.extend(trait_sig.inputs_and_output.iter());
         let trait_sig =
             inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig);
-        // Also add the resulting inputs and output as well-formed.
-        // This probably isn't strictly necessary.
+        // Add the resulting inputs and output as well-formed.
         wf_tys.extend(trait_sig.inputs_and_output.iter());
         let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig));
 
@@ -322,9 +317,7 @@ fn compare_predicate_entailment<'tcx>(
                     // When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the
                     // span points only at the type `Box<Self`>, but we want to cover the whole
                     // argument pattern and type.
-                    let impl_m_hir_id =
-                        tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
-                    let span = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
+                    let span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
                         ImplItemKind::Fn(ref sig, body) => tcx
                             .hir()
                             .body_param_names(body)
@@ -346,9 +339,7 @@ fn compare_predicate_entailment<'tcx>(
                     if trait_sig.inputs().len() == *i {
                         // Suggestion to change output type. We do not suggest in `async` functions
                         // to avoid complex logic or incorrect output.
-                        let impl_m_hir_id =
-                            tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
-                        match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
+                        match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
                             ImplItemKind::Fn(ref sig, _)
                                 if sig.header.asyncness == hir::IsAsync::NotAsync =>
                             {
@@ -467,22 +458,19 @@ fn extract_spans_for_error_reporting<'a, 'tcx>(
     trait_m: &ty::AssocItem,
 ) -> (Span, Option<Span>) {
     let tcx = infcx.tcx;
-    let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
-    let mut impl_args = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
+    let mut impl_args = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
         ImplItemKind::Fn(ref sig, _) => {
             sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
         }
         _ => bug!("{:?} is not a method", impl_m),
     };
-    let trait_args = trait_m.def_id.as_local().map(|def_id| {
-        let trait_m_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-        match tcx.hir().expect_trait_item(trait_m_hir_id).kind {
+    let trait_args =
+        trait_m.def_id.as_local().map(|def_id| match tcx.hir().expect_trait_item(def_id).kind {
             TraitItemKind::Fn(ref sig, _) => {
                 sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
             }
             _ => bug!("{:?} is not a TraitItemKind::Fn", trait_m),
-        }
-    });
+        });
 
     match *terr {
         TypeError::ArgumentMutability(i) => {
@@ -600,8 +588,7 @@ fn compare_number_of_generics<'tcx>(
             err_occurred = true;
 
             let (trait_spans, impl_trait_spans) = if let Some(def_id) = trait_.def_id.as_local() {
-                let trait_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-                let trait_item = tcx.hir().expect_trait_item(trait_hir_id);
+                let trait_item = tcx.hir().expect_trait_item(def_id);
                 if trait_item.generics.params.is_empty() {
                     (Some(vec![trait_item.generics.span]), vec![])
                 } else {
@@ -622,8 +609,7 @@ fn compare_number_of_generics<'tcx>(
                 (trait_span.map(|s| vec![s]), vec![])
             };
 
-            let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_.def_id.expect_local());
-            let impl_item = tcx.hir().expect_impl_item(impl_hir_id);
+            let impl_item = tcx.hir().expect_impl_item(impl_.def_id.expect_local());
             let impl_item_impl_trait_spans: Vec<Span> = impl_item
                 .generics
                 .params
@@ -711,8 +697,7 @@ fn compare_number_of_method_arguments<'tcx>(
     let impl_number_args = impl_m_fty.inputs().skip_binder().len();
     if trait_number_args != impl_number_args {
         let trait_span = if let Some(def_id) = trait_m.def_id.as_local() {
-            let trait_id = tcx.hir().local_def_id_to_hir_id(def_id);
-            match tcx.hir().expect_trait_item(trait_id).kind {
+            match tcx.hir().expect_trait_item(def_id).kind {
                 TraitItemKind::Fn(ref trait_m_sig, _) => {
                     let pos = if trait_number_args > 0 { trait_number_args - 1 } else { 0 };
                     if let Some(arg) = trait_m_sig.decl.inputs.get(pos) {
@@ -730,8 +715,7 @@ fn compare_number_of_method_arguments<'tcx>(
         } else {
             trait_item_span
         };
-        let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
-        let impl_span = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
+        let impl_span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
             ImplItemKind::Fn(ref impl_m_sig, _) => {
                 let pos = if impl_number_args > 0 { impl_number_args - 1 } else { 0 };
                 if let Some(arg) = impl_m_sig.decl.inputs.get(pos) {
@@ -1055,7 +1039,7 @@ fn compare_const_param_types<'tcx>(
             );
 
             // Locate the Span containing just the type of the offending impl
-            match tcx.hir().expect_impl_item(impl_c_hir_id).kind {
+            match tcx.hir().expect_impl_item(impl_c.def_id.expect_local()).kind {
                 ImplItemKind::Const(ref ty, _) => cause.make_mut().span = ty.span,
                 _ => bug!("{:?} is not a impl const", impl_c),
             }
@@ -1068,11 +1052,9 @@ fn compare_const_param_types<'tcx>(
                 trait_c.ident
             );
 
-            let trait_c_hir_id =
-                trait_c.def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id));
-            let trait_c_span = trait_c_hir_id.map(|trait_c_hir_id| {
+            let trait_c_span = trait_c.def_id.as_local().map(|trait_c_def_id| {
                 // Add a label to the Span containing just the type of the const
-                match tcx.hir().expect_trait_item(trait_c_hir_id).kind {
+                match tcx.hir().expect_trait_item(trait_c_def_id).kind {
                     TraitItemKind::Const(ref ty, _) => ty.span,
                     _ => bug!("{:?} is not a trait const", trait_c),
                 }
index ece2d7b4f3793f0aaa93b48e50a9fdcddae69491..12cd7ad184892968db333849816429badd9be776 100644 (file)
@@ -10,6 +10,7 @@
 use rustc_hir::{is_range_literal, Node};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::adjustment::AllowTwoPhase;
+use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut};
 use rustc_span::symbol::sym;
@@ -27,8 +28,9 @@ pub fn emit_coerce_suggestions(
         expr_ty: Ty<'tcx>,
         expected: Ty<'tcx>,
         expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
+        error: TypeError<'tcx>,
     ) {
-        self.annotate_expected_due_to_let_ty(err, expr);
+        self.annotate_expected_due_to_let_ty(err, expr, error);
         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);
@@ -145,9 +147,9 @@ pub fn demand_coerce_diag(
         let expr = expr.peel_drop_temps();
         let cause = self.misc(expr.span);
         let expr_ty = self.resolve_vars_with_obligations(checked_ty);
-        let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e);
+        let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e.clone());
 
-        self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr);
+        self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, e);
 
         (expected, Some(err))
     }
@@ -156,15 +158,104 @@ fn annotate_expected_due_to_let_ty(
         &self,
         err: &mut DiagnosticBuilder<'_>,
         expr: &hir::Expr<'_>,
+        error: TypeError<'_>,
     ) {
         let parent = self.tcx.hir().get_parent_node(expr.hir_id);
-        if let Some(hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. })) =
-            self.tcx.hir().find(parent)
-        {
-            if init.hir_id == expr.hir_id {
+        match (self.tcx.hir().find(parent), error) {
+            (Some(hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. })), _)
+                if init.hir_id == expr.hir_id =>
+            {
                 // Point at `let` assignment type.
                 err.span_label(ty.span, "expected due to this");
             }
+            (
+                Some(hir::Node::Expr(hir::Expr {
+                    kind: hir::ExprKind::Assign(lhs, rhs, _), ..
+                })),
+                TypeError::Sorts(ExpectedFound { expected, .. }),
+            ) if rhs.hir_id == expr.hir_id && !expected.is_closure() => {
+                // We ignore closures explicitly because we already point at them elsewhere.
+                // Point at the assigned-to binding.
+                let mut primary_span = lhs.span;
+                let mut secondary_span = lhs.span;
+                let mut post_message = "";
+                match lhs.kind {
+                    hir::ExprKind::Path(hir::QPath::Resolved(
+                        None,
+                        hir::Path {
+                            res:
+                                hir::def::Res::Def(
+                                    hir::def::DefKind::Static | hir::def::DefKind::Const,
+                                    def_id,
+                                ),
+                            ..
+                        },
+                    )) => {
+                        if let Some(hir::Node::Item(hir::Item {
+                            ident,
+                            kind: hir::ItemKind::Static(ty, ..) | hir::ItemKind::Const(ty, ..),
+                            ..
+                        })) = self.tcx.hir().get_if_local(*def_id)
+                        {
+                            primary_span = ty.span;
+                            secondary_span = ident.span;
+                            post_message = " type";
+                        }
+                    }
+                    hir::ExprKind::Path(hir::QPath::Resolved(
+                        None,
+                        hir::Path { res: hir::def::Res::Local(hir_id), .. },
+                    )) => {
+                        if let Some(hir::Node::Binding(pat)) = self.tcx.hir().find(*hir_id) {
+                            let parent = self.tcx.hir().get_parent_node(pat.hir_id);
+                            primary_span = pat.span;
+                            secondary_span = pat.span;
+                            match self.tcx.hir().find(parent) {
+                                Some(hir::Node::Local(hir::Local { ty: Some(ty), .. })) => {
+                                    primary_span = ty.span;
+                                    post_message = " type";
+                                }
+                                Some(hir::Node::Local(hir::Local { init: Some(init), .. })) => {
+                                    primary_span = init.span;
+                                    post_message = " value";
+                                }
+                                Some(hir::Node::Param(hir::Param { ty_span, .. })) => {
+                                    primary_span = *ty_span;
+                                    post_message = " parameter type";
+                                }
+                                _ => {}
+                            }
+                        }
+                    }
+                    _ => {}
+                }
+
+                if primary_span != secondary_span
+                    && self
+                        .tcx
+                        .sess
+                        .source_map()
+                        .is_multiline(secondary_span.shrink_to_hi().until(primary_span))
+                {
+                    // We are pointing at the binding's type or initializer value, but it's pattern
+                    // is in a different line, so we point at both.
+                    err.span_label(secondary_span, "expected due to the type of this binding");
+                    err.span_label(primary_span, &format!("expected due to this{}", post_message));
+                } else if post_message == "" {
+                    // We are pointing at either the assignment lhs or the binding def pattern.
+                    err.span_label(primary_span, "expected due to the type of this binding");
+                } else {
+                    // We are pointing at the binding's type or initializer value.
+                    err.span_label(primary_span, &format!("expected due to this{}", post_message));
+                }
+
+                if !lhs.is_syntactic_place_expr() {
+                    // We already emitted E0070 "invalid left-hand side of assignment", so we
+                    // silence this.
+                    err.delay_as_bug();
+                }
+            }
+            _ => {}
         }
     }
 
index c9fa0fd72fc50cce251f16072821e7a7f61ba806..311106474bea008dff0a8608316965513a02f095 100644 (file)
@@ -46,6 +46,7 @@
 use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::source_map::Span;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::{BytePos, Pos};
 use rustc_trait_selection::traits::{self, ObligationCauseCode};
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -833,7 +834,7 @@ pub(crate) fn check_lhs_assignable(
         &self,
         lhs: &'tcx hir::Expr<'tcx>,
         err_code: &'static str,
-        expr_span: &Span,
+        op_span: Span,
     ) {
         if lhs.is_syntactic_place_expr() {
             return;
@@ -841,11 +842,58 @@ pub(crate) fn check_lhs_assignable(
 
         // FIXME: Make this use SessionDiagnostic once error codes can be dynamically set.
         let mut err = self.tcx.sess.struct_span_err_with_code(
-            *expr_span,
+            op_span,
             "invalid left-hand side of assignment",
             DiagnosticId::Error(err_code.into()),
         );
         err.span_label(lhs.span, "cannot assign to this expression");
+
+        let mut parent = self.tcx.hir().get_parent_node(lhs.hir_id);
+        while let Some(node) = self.tcx.hir().find(parent) {
+            match node {
+                hir::Node::Expr(hir::Expr {
+                    kind:
+                        hir::ExprKind::Loop(
+                            hir::Block {
+                                expr:
+                                    Some(hir::Expr {
+                                        kind:
+                                            hir::ExprKind::Match(expr, ..) | hir::ExprKind::If(expr, ..),
+                                        ..
+                                    }),
+                                ..
+                            },
+                            _,
+                            hir::LoopSource::While,
+                            _,
+                        ),
+                    ..
+                }) => {
+                    // We have a situation like `while Some(0) = value.get(0) {`, where `while let`
+                    // was more likely intended.
+                    err.span_suggestion_verbose(
+                        expr.span.shrink_to_lo(),
+                        "you might have meant to use pattern destructuring",
+                        "let ".to_string(),
+                        Applicability::MachineApplicable,
+                    );
+                    if !self.sess().features_untracked().destructuring_assignment {
+                        // We already emit an E0658 with a suggestion for `while let`, this is
+                        // redundant output.
+                        err.delay_as_bug();
+                    }
+                    break;
+                }
+                hir::Node::Item(_)
+                | hir::Node::ImplItem(_)
+                | hir::Node::TraitItem(_)
+                | hir::Node::Crate(_) => break,
+                _ => {
+                    parent = self.tcx.hir().get_parent_node(parent);
+                }
+            }
+        }
+
         err.emit();
     }
 
@@ -953,7 +1001,7 @@ fn check_expr_assign(
             } else {
                 (Applicability::MaybeIncorrect, false)
             };
-            if !lhs.is_syntactic_place_expr() {
+            if !lhs.is_syntactic_place_expr() && !matches!(lhs.kind, hir::ExprKind::Lit(_)) {
                 // Do not suggest `if let x = y` as `==` is way more likely to be the intention.
                 let hir = self.tcx.hir();
                 if let hir::Node::Expr(hir::Expr { kind: ExprKind::If { .. }, .. }) =
@@ -965,7 +1013,7 @@ fn check_expr_assign(
                         "let ".to_string(),
                         applicability,
                     );
-                }
+                };
             }
             if eq {
                 err.span_suggestion_verbose(
@@ -986,7 +1034,7 @@ fn check_expr_assign(
             return self.tcx.ty_error();
         }
 
-        self.check_lhs_assignable(lhs, "E0070", span);
+        self.check_lhs_assignable(lhs, "E0070", *span);
 
         let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);
         let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty, Some(lhs));
@@ -2016,7 +2064,36 @@ fn ban_take_value_of_method(&self, expr: &hir::Expr<'_>, expr_t: Ty<'tcx>, field
                 Some(span),
             );
         } else {
-            err.help("methods are immutable and cannot be assigned to");
+            let mut found = false;
+
+            if let ty::RawPtr(ty_and_mut) = expr_t.kind() {
+                if let ty::Adt(adt_def, _) = ty_and_mut.ty.kind() {
+                    if adt_def.variants.len() == 1
+                        && adt_def
+                            .variants
+                            .iter()
+                            .next()
+                            .unwrap()
+                            .fields
+                            .iter()
+                            .any(|f| f.ident == field)
+                    {
+                        if let Some(dot_loc) = expr_snippet.rfind('.') {
+                            found = true;
+                            err.span_suggestion(
+                                expr.span.with_hi(expr.span.lo() + BytePos::from_usize(dot_loc)),
+                                "to access the field, dereference first",
+                                format!("(*{})", &expr_snippet[0..dot_loc]),
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
+                    }
+                }
+            }
+
+            if !found {
+                err.help("methods are immutable and cannot be assigned to");
+            }
         }
 
         err.emit();
index 142a0a8fc2501e922c4a35058f87537cec07aed7..a02a7d7cbfeb281c712f27e62ca8afb25ef75464 100644 (file)
@@ -304,20 +304,26 @@ pub fn apply_adjustments(&self, expr: &hir::Expr<'_>, adj: Vec<Adjustment<'tcx>>
                     // is a valid NeverToAny adjustment, because it can't
                     // be reached.
                     (&[Adjustment { kind: Adjust::NeverToAny, .. }], _) => return,
-                    (&[
-                        Adjustment { kind: Adjust::Deref(_), .. },
-                        Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), .. },
-                    ], &[
-                        Adjustment { kind: Adjust::Deref(_), .. },
-                        .. // Any following adjustments are allowed.
-                    ]) => {
+                    (
+                        &[
+                            Adjustment { kind: Adjust::Deref(_), .. },
+                            Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), .. },
+                        ],
+                        &[
+                            Adjustment { kind: Adjust::Deref(_), .. },
+                            .., // Any following adjustments are allowed.
+                        ],
+                    ) => {
                         // A reborrow has no effect before a dereference.
                     }
                     // FIXME: currently we never try to compose autoderefs
                     // and ReifyFnPointer/UnsafeFnPointer, but we could.
-                    _ =>
-                        bug!("while adjusting {:?}, can't compose {:?} and {:?}",
-                             expr, entry.get(), adj)
+                    _ => bug!(
+                        "while adjusting {:?}, can't compose {:?} and {:?}",
+                        expr,
+                        entry.get(),
+                        adj
+                    ),
                 };
                 *entry.get_mut() = adj;
             }
@@ -1097,12 +1103,9 @@ pub(in super::super) fn could_remove_semicolon(
                         (_, _) => return None,
                     };
 
-                let last_hir_id = self.tcx.hir().local_def_id_to_hir_id(last_local_id);
-                let exp_hir_id = self.tcx.hir().local_def_id_to_hir_id(exp_local_id);
-
                 match (
-                    &self.tcx.hir().expect_item(last_hir_id).kind,
-                    &self.tcx.hir().expect_item(exp_hir_id).kind,
+                    &self.tcx.hir().expect_item(last_local_id).kind,
+                    &self.tcx.hir().expect_item(exp_local_id).kind,
                 ) {
                     (
                         hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: last_bounds, .. }),
index a119a6838b8d2f3e900d74f7bd8a144b8daa5c01..74d7f0a80b6cac9cda51017087a25cc792fefcb1 100644 (file)
@@ -737,6 +737,24 @@ pub(in super::super) fn check_block_with_expected(
                         &mut |err| {
                             if let Some(expected_ty) = expected.only_has_type(self) {
                                 self.consider_hint_about_removing_semicolon(blk, expected_ty, err);
+                                if expected_ty == self.tcx.types.bool {
+                                    // If this is caused by a missing `let` in a `while let`,
+                                    // silence this redundant error, as we already emit E0070.
+                                    let parent = self.tcx.hir().get_parent_node(blk.hir_id);
+                                    let parent = self.tcx.hir().get_parent_node(parent);
+                                    let parent = self.tcx.hir().get_parent_node(parent);
+                                    let parent = self.tcx.hir().get_parent_node(parent);
+                                    let parent = self.tcx.hir().get_parent_node(parent);
+                                    match self.tcx.hir().find(parent) {
+                                        Some(hir::Node::Expr(hir::Expr {
+                                            kind: hir::ExprKind::Loop(_, _, hir::LoopSource::While, _),
+                                            ..
+                                        })) => {
+                                            err.delay_as_bug();
+                                        }
+                                        _ => {}
+                                    }
+                                }
                             }
                             if let Some(fn_span) = fn_span {
                                 err.span_label(
index 5c8056b244242343791656967f54d2cd9a92f61a..bc2859719e8ebb66a16e586bed3a4f742ec4d980 100644 (file)
@@ -345,10 +345,7 @@ fn trait_path(&self, span: Span, expr_hir_id: HirId, trait_def_id: DefId) -> Opt
         let import_items: Vec<_> = applicable_trait
             .import_ids
             .iter()
-            .map(|&import_id| {
-                let hir_id = self.tcx.hir().local_def_id_to_hir_id(import_id);
-                self.tcx.hir().expect_item(hir_id)
-            })
+            .map(|&import_id| self.tcx.hir().expect_item(import_id))
             .collect();
 
         // Find an identifier with which this trait was imported (note that `_` doesn't count).
index e7fba3a70ff42d986aa05c28240426c3f8731ff3..7bfd3f0ee804733ba763844cd99d693e55478724 100644 (file)
@@ -391,7 +391,6 @@ fn typeck_with_fallback<'tcx>(
             let mut wf_tys = FxHashSet::default();
             // Compute the fty from point of view of inside the fn.
             let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
-            wf_tys.extend(fn_sig.inputs_and_output.iter());
             let fn_sig = inh.normalize_associated_types_in(
                 body.value.span,
                 body_id.hir_id,
index 9c53a1d4eb68dacc98fba193e2e9efb3963d9f88..f83209f57a897cf54145fd76295746c45faa4e65 100644 (file)
@@ -42,7 +42,7 @@ pub fn check_binop_assign(
                 return_ty
             };
 
-        self.check_lhs_assignable(lhs, "E0067", &op.span);
+        self.check_lhs_assignable(lhs, "E0067", op.span);
 
         ty
     }
index 5d9e6ebd50c85582c32eee27843c66753503d55b..d01e21bcb23602511ad9341ded7af8a4b28aa657 100644 (file)
@@ -440,8 +440,11 @@ fn convert_place_op_to_mutable(
             }
 
             // If we have an autoref followed by unsizing at the end, fix the unsize target.
-            if let [.., Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), .. }, Adjustment { kind: Adjust::Pointer(PointerCast::Unsize), ref mut target }] =
-                adjustments[..]
+            if let [
+                ..,
+                Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), .. },
+                Adjustment { kind: Adjust::Pointer(PointerCast::Unsize), ref mut target },
+            ] = adjustments[..]
             {
                 *target = method.sig.inputs()[0];
             }
index 5f5d308a3329bdf5c7f3c3fe2cbd1e0a445c4f8c..41bbf322a6ecc42577bc6b67c8842b203cd7e2db 100644 (file)
@@ -687,15 +687,11 @@ fn compute_min_captures(
                             r
                         ),
                         (
-                            l
-                            @
-                            (ProjectionKind::Index
+                            l @ (ProjectionKind::Index
                             | ProjectionKind::Subslice
                             | ProjectionKind::Deref
                             | ProjectionKind::Field(..)),
-                            r
-                            @
-                            (ProjectionKind::Index
+                            r @ (ProjectionKind::Index
                             | ProjectionKind::Subslice
                             | ProjectionKind::Deref
                             | ProjectionKind::Field(..)),
index 0050ac99cb19a8c32ac804792a94b2ec2b099783..33a0c3275ca2a4d412a1daa19475f885c5287254 100644 (file)
@@ -84,8 +84,7 @@ fn with_fcx<F>(&mut self, f: F)
 /// the types first.
 #[instrument(skip(tcx), level = "debug")]
 pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-    let item = tcx.hir().expect_item(hir_id);
+    let item = tcx.hir().expect_item(def_id);
 
     debug!(
         ?item.def_id,
@@ -197,7 +196,7 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
 
 pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-    let trait_item = tcx.hir().expect_trait_item(hir_id);
+    let trait_item = tcx.hir().expect_trait_item(def_id);
 
     let (method_sig, span) = match trait_item.kind {
         hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span),
@@ -207,8 +206,8 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     check_object_unsafe_self_trait_by_name(tcx, trait_item);
     check_associated_item(tcx, trait_item.def_id, span, method_sig);
 
-    let encl_trait_hir_id = tcx.hir().get_parent_item(hir_id);
-    let encl_trait = tcx.hir().expect_item(encl_trait_hir_id);
+    let encl_trait_def_id = tcx.hir().get_parent_did(hir_id);
+    let encl_trait = tcx.hir().expect_item(encl_trait_def_id);
     let encl_trait_def_id = encl_trait.def_id.to_def_id();
     let fn_lang_item_name = if Some(encl_trait_def_id) == tcx.lang_items().fn_trait() {
         Some("fn")
@@ -680,8 +679,7 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem
 }
 
 pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-    let impl_item = tcx.hir().expect_impl_item(hir_id);
+    let impl_item = tcx.hir().expect_impl_item(def_id);
 
     let (method_sig, span) = match impl_item.kind {
         hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span),
@@ -1060,6 +1058,20 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo
             );
         }
 
+        // Ensure that the end result is `Sync` in a non-thread local `static`.
+        let should_check_for_sync = tcx.static_mutability(item_id.to_def_id())
+            == Some(hir::Mutability::Not)
+            && !tcx.is_foreign_item(item_id.to_def_id())
+            && !tcx.is_thread_local_static(item_id.to_def_id());
+
+        if should_check_for_sync {
+            fcx.register_bound(
+                item_ty,
+                tcx.require_lang_item(LangItem::Sync, Some(ty_span)),
+                traits::ObligationCause::new(ty_span, fcx.body_id, traits::SharedStatic),
+            );
+        }
+
         // No implied bounds in a const, etc.
         FxHashSet::default()
     });
@@ -1322,11 +1334,6 @@ fn check_fn_or_method<'fcx, 'tcx>(
 ) {
     let sig = fcx.tcx.liberate_late_bound_regions(def_id, sig);
 
-    // Unnormalized types in signature are WF too
-    implied_bounds.extend(sig.inputs());
-    // FIXME(#27579) return types should not be implied bounds
-    implied_bounds.insert(sig.output());
-
     // Normalize the input and output types one at a time, using a different
     // `WellFormedLoc` for each. We cannot call `normalize_associated_types`
     // on the entire `FnSig`, since this would use the same `WellFormedLoc`
index 89ce3700aadcdee53a01a18bb51ca65300b39217..79ed83d59ed9728c5c292e82e345a596c7cde65a 100644 (file)
@@ -119,13 +119,13 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
 
     for extern_crate in &crates_to_lint {
         let def_id = extern_crate.def_id.expect_local();
-        let id = tcx.hir().local_def_id_to_hir_id(def_id);
-        let item = tcx.hir().expect_item(id);
+        let item = tcx.hir().expect_item(def_id);
 
         // If the crate is fully unused, we suggest removing it altogether.
         // We do this in any edition.
         if extern_crate.warn_if_unused {
             if let Some(&span) = unused_extern_crates.get(&def_id) {
+                let id = tcx.hir().local_def_id_to_hir_id(def_id);
                 tcx.struct_span_lint_hir(lint, id, span, |lint| {
                     // Removal suggestion span needs to include attributes (Issue #54400)
                     let span_with_attrs = tcx
@@ -173,6 +173,7 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
         if !tcx.get_attrs(extern_crate.def_id).is_empty() {
             continue;
         }
+        let id = tcx.hir().local_def_id_to_hir_id(def_id);
         tcx.struct_span_lint_hir(lint, id, extern_crate.span, |lint| {
             // Otherwise, we can convert it into a `use` of some kind.
             let base_replacement = match extern_crate.orig_name {
index 372e83592b9c51335fcc04e529071d6684c5b06a..dfb4304ab02c4de8a860d906af82a655f40b5934 100644 (file)
@@ -52,8 +52,7 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
         return;
     }
 
-    let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
-    let sp = match tcx.hir().expect_item(impl_hir_id).kind {
+    let sp = match tcx.hir().expect_item(impl_did).kind {
         ItemKind::Impl(ref impl_) => impl_.self_ty.span,
         _ => bug!("expected Drop impl item"),
     };
@@ -78,7 +77,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
     match can_type_implement_copy(tcx, param_env, self_type) {
         Ok(()) => {}
         Err(CopyImplementationError::InfrigingFields(fields)) => {
-            let item = tcx.hir().expect_item(impl_hir_id);
+            let item = tcx.hir().expect_item(impl_did);
             let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(ref tr), .. }) = item.kind {
                 tr.path.span
             } else {
@@ -97,7 +96,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
             err.emit()
         }
         Err(CopyImplementationError::NotAnAdt) => {
-            let item = tcx.hir().expect_item(impl_hir_id);
+            let item = tcx.hir().expect_item(impl_did);
             let span =
                 if let ItemKind::Impl(ref impl_) = item.kind { impl_.self_ty.span } else { span };
 
@@ -292,8 +291,8 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI
     debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
 
     // this provider should only get invoked for local def-ids
-    let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did.expect_local());
-    let span = tcx.hir().span(impl_hir_id);
+    let impl_did = impl_did.expect_local();
+    let span = tcx.def_span(impl_did);
 
     let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span));
 
@@ -315,6 +314,7 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI
     debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)", source, target);
 
     tcx.infer_ctxt().enter(|infcx| {
+        let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
         let cause = ObligationCause::misc(span, impl_hir_id);
         let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
                            mt_b: ty::TypeAndMut<'tcx>,
@@ -452,13 +452,13 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI
                     .emit();
                     return err_info;
                 } else if diff_fields.len() > 1 {
-                    let item = tcx.hir().expect_item(impl_hir_id);
+                    let item = tcx.hir().expect_item(impl_did);
                     let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(ref t), .. }) =
                         item.kind
                     {
                         t.path.span
                     } else {
-                        tcx.hir().span(impl_hir_id)
+                        tcx.def_span(impl_did)
                     };
 
                     struct_span_err!(
@@ -530,7 +530,11 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI
 
         // Finally, resolve all regions.
         let outlives_env = OutlivesEnvironment::new(param_env);
-        infcx.resolve_regions_and_report_errors(impl_did, &outlives_env, RegionckMode::default());
+        infcx.resolve_regions_and_report_errors(
+            impl_did.to_def_id(),
+            &outlives_env,
+            RegionckMode::default(),
+        );
 
         CoerceUnsizedInfo { custom_kind: kind }
     })
index b9db8a6be5916bbc7b000970e6921b7e6e64c393..4b41730ffd50bd59f353e744f1ac2161b041c457 100644 (file)
@@ -431,7 +431,7 @@ fn projected_ty_from_poly_trait_ref(
             match self.node() {
                 hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => {
                     let item =
-                        self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(self.hir_id()));
+                        self.tcx.hir().expect_item(self.tcx.hir().get_parent_did(self.hir_id()));
                     match &item.kind {
                         hir::ItemKind::Enum(_, generics)
                         | hir::ItemKind::Struct(_, generics)
@@ -666,7 +666,7 @@ fn type_parameter_bounds_in_generics(
                 Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name),
                 None => true,
             })
-            .flat_map(|b| predicates_from_bound(self, ty, b));
+            .flat_map(|b| predicates_from_bound(self, ty, b, ty::List::empty()));
 
         let param_def_id = self.tcx.hir().local_def_id(param_id).to_def_id();
         let from_where_clauses = ast_generics
@@ -685,15 +685,17 @@ fn type_parameter_bounds_in_generics(
                 } else {
                     None
                 };
+                let bvars = self.tcx.late_bound_vars(bp.bounded_ty.hir_id);
+
                 bp.bounds
                     .iter()
                     .filter(|b| match assoc_name {
                         Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name),
                         None => true,
                     })
-                    .filter_map(move |b| bt.map(|bt| (bt, b)))
+                    .filter_map(move |b| bt.map(|bt| (bt, b, bvars)))
             })
-            .flat_map(|(bt, b)| predicates_from_bound(self, bt, b));
+            .flat_map(|(bt, b, bvars)| predicates_from_bound(self, bt, b, bvars));
 
         from_ty_params.chain(from_where_clauses).collect()
     }
@@ -1182,8 +1184,7 @@ fn super_predicates_that_define_assoc_type(
 }
 
 fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-    let item = tcx.hir().expect_item(hir_id);
+    let item = tcx.hir().expect_item(def_id.expect_local());
 
     let (is_auto, unsafety) = match item.kind {
         hir::ItemKind::Trait(is_auto, unsafety, ..) => (is_auto == hir::IsAuto::Yes, unsafety),
@@ -1878,9 +1879,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
 
 fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
     let icx = ItemCtxt::new(tcx, def_id);
-
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-    match tcx.hir().expect_item(hir_id).kind {
+    match tcx.hir().expect_item(def_id.expect_local()).kind {
         hir::ItemKind::Impl(ref impl_) => impl_.of_trait.as_ref().map(|ast_trait_ref| {
             let selfty = tcx.type_of(def_id);
             <dyn AstConv<'_>>::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty)
@@ -1890,9 +1889,8 @@ fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
 }
 
 fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
     let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
-    let item = tcx.hir().expect_item(hir_id);
+    let item = tcx.hir().expect_item(def_id.expect_local());
     match &item.kind {
         hir::ItemKind::Impl(hir::Impl {
             polarity: hir::ImplPolarity::Negative(span),
@@ -2433,14 +2431,10 @@ fn predicates_from_bound<'tcx>(
     astconv: &dyn AstConv<'tcx>,
     param_ty: Ty<'tcx>,
     bound: &'tcx hir::GenericBound<'tcx>,
+    bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
 ) -> Vec<(ty::Predicate<'tcx>, Span)> {
     let mut bounds = Bounds::default();
-    astconv.add_bounds(
-        param_ty,
-        std::array::IntoIter::new([bound]),
-        &mut bounds,
-        ty::List::empty(),
-    );
+    astconv.add_bounds(param_ty, [bound].into_iter(), &mut bounds, bound_vars);
     bounds.predicates(astconv.tcx(), param_ty)
 }
 
@@ -3227,7 +3221,7 @@ fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span:
     let hir_id = tcx.hir().local_def_id_to_hir_id(id);
     let node = tcx.hir().get(hir_id);
     if let Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node {
-        let parent_id = tcx.hir().get_parent_item(hir_id);
+        let parent_id = tcx.hir().get_parent_did(hir_id);
         let parent_item = tcx.hir().expect_item(parent_id);
         if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind {
             tcx.sess
index 0881cf07586b367b88210919adef6be38f15c779..41e06f43c461678a938cc547d2e9b7f0caf6b090 100644 (file)
@@ -58,7 +58,6 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(bool_to_option)]
 #![feature(crate_visibility_modifier)]
-#![cfg_attr(bootstrap, feature(format_args_capture))]
 #![feature(if_let_guard)]
 #![feature(in_band_lifetimes)]
 #![feature(is_sorted)]
index f6332b072cf30237425386602ce9222d69a9404e..ab41f5646e5e50d3015c61bd796b59af69f2c7dc 100644 (file)
@@ -763,6 +763,42 @@ pub unsafe fn assume_init(self) -> Box<T, A> {
         let (raw, alloc) = Box::into_raw_with_allocator(self);
         unsafe { Box::from_raw_in(raw as *mut T, alloc) }
     }
+
+    /// Writes the value and converts to `Box<T, A>`.
+    ///
+    /// This method converts the box similarly to [`Box::assume_init`] but
+    /// writes `value` into it before conversion thus guaranteeing safety.
+    /// In some scenarios use of this method may improve performance because
+    /// the compiler may be able to optimize copying from stack.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(new_uninit)]
+    ///
+    /// let big_box = Box::<[usize; 1024]>::new_uninit();
+    ///
+    /// let mut array = [0; 1024];
+    /// for (i, place) in array.iter_mut().enumerate() {
+    ///     *place = i;
+    /// }
+    ///
+    /// // The optimizer may be able to elide this copy, so previous code writes
+    /// // to heap directly.
+    /// let big_box = Box::write(big_box, array);
+    ///
+    /// for (i, x) in big_box.iter().enumerate() {
+    ///     assert_eq!(*x, i);
+    /// }
+    /// ```
+    #[unstable(feature = "new_uninit", issue = "63291")]
+    #[inline]
+    pub fn write(mut boxed: Self, value: T) -> Box<T, A> {
+        unsafe {
+            (*boxed).write(value);
+            boxed.assume_init()
+        }
+    }
 }
 
 impl<T, A: Allocator> Box<[mem::MaybeUninit<T>], A> {
@@ -1482,8 +1518,6 @@ fn try_from(boxed_slice: Box<[T]>) -> Result<Self, Self::Error> {
 }
 
 impl<A: Allocator> Box<dyn Any, A> {
-    #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
     /// Attempt to downcast the box to a concrete type.
     ///
     /// # Examples
@@ -1501,21 +1535,48 @@ impl<A: Allocator> Box<dyn Any, A> {
     /// print_if_string(Box::new(my_string));
     /// print_if_string(Box::new(0i8));
     /// ```
+    #[inline]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> {
-        if self.is::<T>() {
-            unsafe {
-                let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_allocator(self);
-                Ok(Box::from_raw_in(raw as *mut T, alloc))
-            }
-        } else {
-            Err(self)
+        if self.is::<T>() { unsafe { Ok(self.downcast_unchecked::<T>()) } } else { Err(self) }
+    }
+
+    /// Downcasts the box to a concrete type.
+    ///
+    /// For a safe alternative see [`downcast`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(downcast_unchecked)]
+    ///
+    /// use std::any::Any;
+    ///
+    /// let x: Box<dyn Any> = Box::new(1_usize);
+    ///
+    /// unsafe {
+    ///     assert_eq!(*x.downcast_unchecked::<usize>(), 1);
+    /// }
+    /// ```
+    ///
+    /// # Safety
+    ///
+    /// The contained value must be of type `T`. Calling this method
+    /// with the incorrect type is *undefined behavior*.
+    ///
+    /// [`downcast`]: Self::downcast
+    #[inline]
+    #[unstable(feature = "downcast_unchecked", issue = "90850")]
+    pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> {
+        debug_assert!(self.is::<T>());
+        unsafe {
+            let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_allocator(self);
+            Box::from_raw_in(raw as *mut T, alloc)
         }
     }
 }
 
 impl<A: Allocator> Box<dyn Any + Send, A> {
-    #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
     /// Attempt to downcast the box to a concrete type.
     ///
     /// # Examples
@@ -1533,21 +1594,48 @@ impl<A: Allocator> Box<dyn Any + Send, A> {
     /// print_if_string(Box::new(my_string));
     /// print_if_string(Box::new(0i8));
     /// ```
+    #[inline]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> {
-        if self.is::<T>() {
-            unsafe {
-                let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_allocator(self);
-                Ok(Box::from_raw_in(raw as *mut T, alloc))
-            }
-        } else {
-            Err(self)
+        if self.is::<T>() { unsafe { Ok(self.downcast_unchecked::<T>()) } } else { Err(self) }
+    }
+
+    /// Downcasts the box to a concrete type.
+    ///
+    /// For a safe alternative see [`downcast`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(downcast_unchecked)]
+    ///
+    /// use std::any::Any;
+    ///
+    /// let x: Box<dyn Any + Send> = Box::new(1_usize);
+    ///
+    /// unsafe {
+    ///     assert_eq!(*x.downcast_unchecked::<usize>(), 1);
+    /// }
+    /// ```
+    ///
+    /// # Safety
+    ///
+    /// The contained value must be of type `T`. Calling this method
+    /// with the incorrect type is *undefined behavior*.
+    ///
+    /// [`downcast`]: Self::downcast
+    #[inline]
+    #[unstable(feature = "downcast_unchecked", issue = "90850")]
+    pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> {
+        debug_assert!(self.is::<T>());
+        unsafe {
+            let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_allocator(self);
+            Box::from_raw_in(raw as *mut T, alloc)
         }
     }
 }
 
 impl<A: Allocator> Box<dyn Any + Send + Sync, A> {
-    #[inline]
-    #[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")]
     /// Attempt to downcast the box to a concrete type.
     ///
     /// # Examples
@@ -1565,15 +1653,44 @@ impl<A: Allocator> Box<dyn Any + Send + Sync, A> {
     /// print_if_string(Box::new(my_string));
     /// print_if_string(Box::new(0i8));
     /// ```
+    #[inline]
+    #[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")]
     pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> {
-        if self.is::<T>() {
-            unsafe {
-                let (raw, alloc): (*mut (dyn Any + Send + Sync), _) =
-                    Box::into_raw_with_allocator(self);
-                Ok(Box::from_raw_in(raw as *mut T, alloc))
-            }
-        } else {
-            Err(self)
+        if self.is::<T>() { unsafe { Ok(self.downcast_unchecked::<T>()) } } else { Err(self) }
+    }
+
+    /// Downcasts the box to a concrete type.
+    ///
+    /// For a safe alternative see [`downcast`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(downcast_unchecked)]
+    ///
+    /// use std::any::Any;
+    ///
+    /// let x: Box<dyn Any + Send + Sync> = Box::new(1_usize);
+    ///
+    /// unsafe {
+    ///     assert_eq!(*x.downcast_unchecked::<usize>(), 1);
+    /// }
+    /// ```
+    ///
+    /// # Safety
+    ///
+    /// The contained value must be of type `T`. Calling this method
+    /// with the incorrect type is *undefined behavior*.
+    ///
+    /// [`downcast`]: Self::downcast
+    #[inline]
+    #[unstable(feature = "downcast_unchecked", issue = "90850")]
+    pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> {
+        debug_assert!(self.is::<T>());
+        unsafe {
+            let (raw, alloc): (*mut (dyn Any + Send + Sync), _) =
+                Box::into_raw_with_allocator(self);
+            Box::from_raw_in(raw as *mut T, alloc)
         }
     }
 }
index de607c8fdab31dd098a5ee88c1f76dd81f41ac85..00862615c3c7acf8f8e68d1c527d4c60a9bc8223 100644 (file)
@@ -2179,19 +2179,21 @@ pub fn retain<F>(&mut self, mut f: F)
         }
     }
 
+    // Double the buffer size. This method is inline(never), so we expect it to only
+    // be called in cold paths.
     // This may panic or abort
     #[inline(never)]
     fn grow(&mut self) {
-        if self.is_full() {
-            let old_cap = self.cap();
-            // Double the buffer size.
-            self.buf.reserve_exact(old_cap, old_cap);
-            assert!(self.cap() == old_cap * 2);
-            unsafe {
-                self.handle_capacity_increase(old_cap);
-            }
-            debug_assert!(!self.is_full());
+        // Extend or possibly remove this assertion when valid use-cases for growing the
+        // buffer without it being full emerge
+        debug_assert!(self.is_full());
+        let old_cap = self.cap();
+        self.buf.reserve_exact(old_cap, old_cap);
+        assert!(self.cap() == old_cap * 2);
+        unsafe {
+            self.handle_capacity_increase(old_cap);
         }
+        debug_assert!(!self.is_full());
     }
 
     /// Modifies the `VecDeque` in-place so that `len()` is equal to `new_len`,
index 4a66c3f6b2e26f71dd1ea13860a7bcd1d260f6ad..1bb257acff76a905e10207f36b555d3a9262b179 100644 (file)
 #![feature(fmt_internals)]
 #![feature(fn_traits)]
 #![feature(inherent_ascii_escape)]
-#![cfg_attr(bootstrap, feature(format_args_capture))]
 #![feature(inplace_iteration)]
 #![feature(iter_advance_by)]
 #![feature(iter_zip)]
index 4ab38c802a1599ef507e4bac8aa96d06056fe5d5..3d38e73305a37a577667e03a2cfc5491e4080bd4 100644 (file)
@@ -289,6 +289,14 @@ fn do_reserve_and_handle<T, A: Allocator>(
         }
     }
 
+    /// A specialized version of `reserve()` used only by the hot and
+    /// oft-instantiated `Vec::push()`, which does its own capacity check.
+    #[cfg(not(no_global_oom_handling))]
+    #[inline(never)]
+    pub fn reserve_for_push(&mut self, len: usize) {
+        handle_reserve(self.grow_amortized(len, 1));
+    }
+
     /// The same as `reserve`, but returns on errors instead of panicking or aborting.
     pub fn try_reserve(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> {
         if self.needs_to_grow(len, additional) {
index 8c15a24409bab17793101ddfc1e174cd8edad0a7..ff322f0da97c6e069f62f2e9432e593011cd5e62 100644 (file)
@@ -77,3 +77,87 @@ fn reserve_does_not_overallocate() {
         assert!(v.capacity() >= 12 + 12 / 2);
     }
 }
+
+struct ZST;
+
+// A `RawVec` holding zero-sized elements should always look like this.
+fn zst_sanity<T>(v: &RawVec<T>) {
+    assert_eq!(v.capacity(), usize::MAX);
+    assert_eq!(v.ptr(), core::ptr::Unique::<T>::dangling().as_ptr());
+    assert_eq!(v.current_memory(), None);
+}
+
+#[test]
+fn zst() {
+    let cap_err = Err(crate::collections::TryReserveErrorKind::CapacityOverflow.into());
+
+    assert_eq!(std::mem::size_of::<ZST>(), 0);
+
+    // All these different ways of creating the RawVec produce the same thing.
+
+    let v: RawVec<ZST> = RawVec::new();
+    zst_sanity(&v);
+
+    let v: RawVec<ZST> = RawVec::with_capacity_in(100, Global);
+    zst_sanity(&v);
+
+    let v: RawVec<ZST> = RawVec::with_capacity_in(100, Global);
+    zst_sanity(&v);
+
+    let v: RawVec<ZST> = RawVec::allocate_in(0, AllocInit::Uninitialized, Global);
+    zst_sanity(&v);
+
+    let v: RawVec<ZST> = RawVec::allocate_in(100, AllocInit::Uninitialized, Global);
+    zst_sanity(&v);
+
+    let mut v: RawVec<ZST> = RawVec::allocate_in(usize::MAX, AllocInit::Uninitialized, Global);
+    zst_sanity(&v);
+
+    // Check all these operations work as expected with zero-sized elements.
+
+    assert!(!v.needs_to_grow(100, usize::MAX - 100));
+    assert!(v.needs_to_grow(101, usize::MAX - 100));
+    zst_sanity(&v);
+
+    v.reserve(100, usize::MAX - 100);
+    //v.reserve(101, usize::MAX - 100); // panics, in `zst_reserve_panic` below
+    zst_sanity(&v);
+
+    v.reserve_exact(100, usize::MAX - 100);
+    //v.reserve_exact(101, usize::MAX - 100); // panics, in `zst_reserve_exact_panic` below
+    zst_sanity(&v);
+
+    assert_eq!(v.try_reserve(100, usize::MAX - 100), Ok(()));
+    assert_eq!(v.try_reserve(101, usize::MAX - 100), cap_err);
+    zst_sanity(&v);
+
+    assert_eq!(v.try_reserve_exact(100, usize::MAX - 100), Ok(()));
+    assert_eq!(v.try_reserve_exact(101, usize::MAX - 100), cap_err);
+    zst_sanity(&v);
+
+    assert_eq!(v.grow_amortized(100, usize::MAX - 100), cap_err);
+    assert_eq!(v.grow_amortized(101, usize::MAX - 100), cap_err);
+    zst_sanity(&v);
+
+    assert_eq!(v.grow_exact(100, usize::MAX - 100), cap_err);
+    assert_eq!(v.grow_exact(101, usize::MAX - 100), cap_err);
+    zst_sanity(&v);
+}
+
+#[test]
+#[should_panic(expected = "capacity overflow")]
+fn zst_reserve_panic() {
+    let mut v: RawVec<ZST> = RawVec::new();
+    zst_sanity(&v);
+
+    v.reserve(101, usize::MAX - 100);
+}
+
+#[test]
+#[should_panic(expected = "capacity overflow")]
+fn zst_reserve_exact_panic() {
+    let mut v: RawVec<ZST> = RawVec::new();
+    zst_sanity(&v);
+
+    v.reserve_exact(101, usize::MAX - 100);
+}
index 906b0187f7babf540932b2cd408f71b88b308782..4f926d99c6dbc46e992aa73d4b89b6cd82852a11 100644 (file)
@@ -558,13 +558,13 @@ pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error> {
     pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str> {
         let mut iter = lossy::Utf8Lossy::from_bytes(v).chunks();
 
-        let (first_valid, first_broken) = if let Some(chunk) = iter.next() {
+        let first_valid = if let Some(chunk) = iter.next() {
             let lossy::Utf8LossyChunk { valid, broken } = chunk;
-            if valid.len() == v.len() {
-                debug_assert!(broken.is_empty());
+            if broken.is_empty() {
+                debug_assert_eq!(valid.len(), v.len());
                 return Cow::Borrowed(valid);
             }
-            (valid, broken)
+            valid
         } else {
             return Cow::Borrowed("");
         };
@@ -573,9 +573,7 @@ pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str> {
 
         let mut res = String::with_capacity(v.len());
         res.push_str(first_valid);
-        if !first_broken.is_empty() {
-            res.push_str(REPLACEMENT);
-        }
+        res.push_str(REPLACEMENT);
 
         for lossy::Utf8LossyChunk { valid, broken } in iter {
             res.push_str(valid);
index 85759917765fa6e3d91afa9fd468956c83afdc70..88bde6e8ce48152f1aad625911bc91e2578663e8 100644 (file)
@@ -1726,7 +1726,7 @@ pub fn push(&mut self, value: T) {
         // This will panic or abort if we would allocate > isize::MAX bytes
         // or if the length increment would overflow for zero-sized types.
         if self.len == self.buf.capacity() {
-            self.reserve(1);
+            self.buf.reserve_for_push(self.len);
         }
         unsafe {
             let end = self.as_mut_ptr().add(self.len);
index 00a878c079480b0e1a50f140d82b7ce9df157ec8..773142825329b7dd4130ad8111ff7c226c11f76d 100644 (file)
@@ -985,6 +985,9 @@ fn test_into_iter_advance_by() {
 
     assert_eq!(i.advance_by(usize::MAX), Err(0));
 
+    i.advance_by(0).unwrap();
+    i.advance_back_by(0).unwrap();
+
     assert_eq!(i.len(), 0);
 }
 
index cc32d5223b49f655f691017d675c0d363b5de444..9df0b5c55191591de62b572cedb21cb866eaf85a 100644 (file)
@@ -281,7 +281,9 @@ pub fn pad_to_align(&self) -> Layout {
         // > `usize::MAX`)
         let new_size = self.size() + pad;
 
-        Layout::from_size_align(new_size, self.align()).unwrap()
+        // SAFETY: self.align is already known to be valid and new_size has been
+        // padded already.
+        unsafe { Layout::from_size_align_unchecked(new_size, self.align()) }
     }
 
     /// Creates a layout describing the record for `n` instances of
@@ -403,9 +405,17 @@ pub fn extend_packed(&self, next: Self) -> Result<Self, LayoutError> {
     #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")]
     #[inline]
     pub fn array<T>(n: usize) -> Result<Self, LayoutError> {
-        let (layout, offset) = Layout::new::<T>().repeat(n)?;
-        debug_assert_eq!(offset, mem::size_of::<T>());
-        Ok(layout.pad_to_align())
+        let array_size = mem::size_of::<T>().checked_mul(n).ok_or(LayoutError)?;
+
+        // SAFETY:
+        // - Size: `array_size` cannot be too big because `size_of::<T>()` must
+        //   be a multiple of `align_of::<T>()`. Therefore, `array_size`
+        //   rounded up to the nearest multiple of `align_of::<T>()` is just
+        //   `array_size`. And `array_size` cannot be too big because it was
+        //   just checked by the `checked_mul()`.
+        // - Alignment: `align_of::<T>()` will always give an acceptable
+        //   (non-zero, power of two) alignment.
+        Ok(unsafe { Layout::from_size_align_unchecked(array_size, mem::align_of::<T>()) })
     }
 }
 
index 1fd5aa27fce46562c51ddc6d3b80a7bfc9b45464..72528185707a67fec8cca43880bde8311444285e 100644 (file)
@@ -164,7 +164,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 }
 
 impl dyn Any {
-    /// Returns `true` if the boxed type is the same as `T`.
+    /// Returns `true` if the inner type is the same as `T`.
     ///
     /// # Examples
     ///
@@ -195,7 +195,7 @@ pub fn is<T: Any>(&self) -> bool {
         t == concrete
     }
 
-    /// Returns some reference to the boxed value if it is of type `T`, or
+    /// Returns some reference to the inner value if it is of type `T`, or
     /// `None` if it isn't.
     ///
     /// # Examples
@@ -221,13 +221,13 @@ pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
             // SAFETY: just checked whether we are pointing to the correct type, and we can rely on
             // that check for memory safety because we have implemented Any for all types; no other
             // impls can exist as they would conflict with our impl.
-            unsafe { Some(&*(self as *const dyn Any as *const T)) }
+            unsafe { Some(self.downcast_ref_unchecked()) }
         } else {
             None
         }
     }
 
-    /// Returns some mutable reference to the boxed value if it is of type `T`, or
+    /// Returns some mutable reference to the inner value if it is of type `T`, or
     /// `None` if it isn't.
     ///
     /// # Examples
@@ -257,15 +257,73 @@ pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
             // SAFETY: just checked whether we are pointing to the correct type, and we can rely on
             // that check for memory safety because we have implemented Any for all types; no other
             // impls can exist as they would conflict with our impl.
-            unsafe { Some(&mut *(self as *mut dyn Any as *mut T)) }
+            unsafe { Some(self.downcast_mut_unchecked()) }
         } else {
             None
         }
     }
+
+    /// Returns a reference to the inner value as type `dyn T`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(downcast_unchecked)]
+    ///
+    /// use std::any::Any;
+    ///
+    /// let x: Box<dyn Any> = Box::new(1_usize);
+    ///
+    /// unsafe {
+    ///     assert_eq!(*x.downcast_ref_unchecked::<usize>(), 1);
+    /// }
+    /// ```
+    ///
+    /// # Safety
+    ///
+    /// The contained value must be of type `T`. Calling this method
+    /// with the incorrect type is *undefined behavior*.
+    #[unstable(feature = "downcast_unchecked", issue = "90850")]
+    #[inline]
+    pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
+        debug_assert!(self.is::<T>());
+        // SAFETY: caller guarantees that T is the correct type
+        unsafe { &*(self as *const dyn Any as *const T) }
+    }
+
+    /// Returns a mutable reference to the inner value as type `dyn T`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(downcast_unchecked)]
+    ///
+    /// use std::any::Any;
+    ///
+    /// let mut x: Box<dyn Any> = Box::new(1_usize);
+    ///
+    /// unsafe {
+    ///     *x.downcast_mut_unchecked::<usize>() += 1;
+    /// }
+    ///
+    /// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2);
+    /// ```
+    ///
+    /// # Safety
+    ///
+    /// The contained value must be of type `T`. Calling this method
+    /// with the incorrect type is *undefined behavior*.
+    #[unstable(feature = "downcast_unchecked", issue = "90850")]
+    #[inline]
+    pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
+        debug_assert!(self.is::<T>());
+        // SAFETY: caller guarantees that T is the correct type
+        unsafe { &mut *(self as *mut dyn Any as *mut T) }
+    }
 }
 
 impl dyn Any + Send {
-    /// Forwards to the method defined on the type `Any`.
+    /// Forwards to the method defined on the type `dyn Any`.
     ///
     /// # Examples
     ///
@@ -289,7 +347,7 @@ pub fn is<T: Any>(&self) -> bool {
         <dyn Any>::is::<T>(self)
     }
 
-    /// Forwards to the method defined on the type `Any`.
+    /// Forwards to the method defined on the type `dyn Any`.
     ///
     /// # Examples
     ///
@@ -313,7 +371,7 @@ pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
         <dyn Any>::downcast_ref::<T>(self)
     }
 
-    /// Forwards to the method defined on the type `Any`.
+    /// Forwards to the method defined on the type `dyn Any`.
     ///
     /// # Examples
     ///
@@ -340,6 +398,60 @@ pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
     pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
         <dyn Any>::downcast_mut::<T>(self)
     }
+
+    /// Forwards to the method defined on the type `dyn Any`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(downcast_unchecked)]
+    ///
+    /// use std::any::Any;
+    ///
+    /// let x: Box<dyn Any> = Box::new(1_usize);
+    ///
+    /// unsafe {
+    ///     assert_eq!(*x.downcast_ref_unchecked::<usize>(), 1);
+    /// }
+    /// ```
+    ///
+    /// # Safety
+    ///
+    /// Same as the method on the type `dyn Any`.
+    #[unstable(feature = "downcast_unchecked", issue = "90850")]
+    #[inline]
+    pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
+        // SAFETY: guaranteed by caller
+        unsafe { <dyn Any>::downcast_ref_unchecked::<T>(self) }
+    }
+
+    /// Forwards to the method defined on the type `dyn Any`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(downcast_unchecked)]
+    ///
+    /// use std::any::Any;
+    ///
+    /// let mut x: Box<dyn Any> = Box::new(1_usize);
+    ///
+    /// unsafe {
+    ///     *x.downcast_mut_unchecked::<usize>() += 1;
+    /// }
+    ///
+    /// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2);
+    /// ```
+    ///
+    /// # Safety
+    ///
+    /// Same as the method on the type `dyn Any`.
+    #[unstable(feature = "downcast_unchecked", issue = "90850")]
+    #[inline]
+    pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
+        // SAFETY: guaranteed by caller
+        unsafe { <dyn Any>::downcast_mut_unchecked::<T>(self) }
+    }
 }
 
 impl dyn Any + Send + Sync {
@@ -418,6 +530,52 @@ pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
     pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
         <dyn Any>::downcast_mut::<T>(self)
     }
+
+    /// Forwards to the method defined on the type `Any`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(downcast_unchecked)]
+    ///
+    /// use std::any::Any;
+    ///
+    /// let x: Box<dyn Any> = Box::new(1_usize);
+    ///
+    /// unsafe {
+    ///     assert_eq!(*x.downcast_ref_unchecked::<usize>(), 1);
+    /// }
+    /// ```
+    #[unstable(feature = "downcast_unchecked", issue = "90850")]
+    #[inline]
+    pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
+        // SAFETY: guaranteed by caller
+        unsafe { <dyn Any>::downcast_ref_unchecked::<T>(self) }
+    }
+
+    /// Forwards to the method defined on the type `Any`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(downcast_unchecked)]
+    ///
+    /// use std::any::Any;
+    ///
+    /// let mut x: Box<dyn Any> = Box::new(1_usize);
+    ///
+    /// unsafe {
+    ///     *x.downcast_mut_unchecked::<usize>() += 1;
+    /// }
+    ///
+    /// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2);
+    /// ```
+    #[unstable(feature = "downcast_unchecked", issue = "90850")]
+    #[inline]
+    pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
+        // SAFETY: guaranteed by caller
+        unsafe { <dyn Any>::downcast_mut_unchecked::<T>(self) }
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
index 09bb4519170dae3a4891a55182104cd72610952e..d635829151e4db299bcced797b01220347c9bd33 100644 (file)
@@ -11,7 +11,9 @@
 use crate::hash::{self, Hash};
 use crate::iter::TrustedLen;
 use crate::mem::{self, MaybeUninit};
-use crate::ops::{Index, IndexMut};
+use crate::ops::{
+    ChangeOutputType, ControlFlow, FromResidual, Index, IndexMut, NeverShortCircuit, Residual, Try,
+};
 use crate::slice::{Iter, IterMut};
 
 mod equality;
 }
 
 /// Creates an array `[T; N]` where each fallible array element `T` is returned by the `cb` call.
-/// Unlike `core::array::from_fn`, where the element creation can't fail, this version will return an error
+/// Unlike [`from_fn`], where the element creation can't fail, this version will return an error
 /// if any element creation was unsuccessful.
 ///
+/// The return type of this function depends on the return type of the closure.
+/// If you return `Result<T, E>` from the closure, you'll get a `Result<[T; N]; E>`.
+/// If you return `Option<T>` from the closure, you'll get an `Option<[T; N]>`.
+///
 /// # Arguments
 ///
 /// * `cb`: Callback where the passed argument is the current array index.
 ///
 /// ```rust
 /// #![feature(array_from_fn)]
+/// # // Apparently these doc tests are still on edition2018
+/// # use std::convert::TryInto;
 ///
-/// #[derive(Debug, PartialEq)]
-/// enum SomeError {
-///     Foo,
-/// }
-///
-/// let array = core::array::try_from_fn(|i| Ok::<_, SomeError>(i));
+/// let array: Result<[u8; 5], _> = std::array::try_from_fn(|i| i.try_into());
 /// assert_eq!(array, Ok([0, 1, 2, 3, 4]));
 ///
-/// let another_array = core::array::try_from_fn::<SomeError, _, (), 2>(|_| Err(SomeError::Foo));
-/// assert_eq!(another_array, Err(SomeError::Foo));
+/// let array: Result<[i8; 200], _> = std::array::try_from_fn(|i| i.try_into());
+/// assert!(array.is_err());
+///
+/// let array: Option<[_; 4]> = std::array::try_from_fn(|i| i.checked_add(100));
+/// assert_eq!(array, Some([100, 101, 102, 103]));
+///
+/// let array: Option<[_; 4]> = std::array::try_from_fn(|i| i.checked_sub(100));
+/// assert_eq!(array, None);
 /// ```
 #[inline]
 #[unstable(feature = "array_from_fn", issue = "89379")]
-pub fn try_from_fn<E, F, T, const N: usize>(cb: F) -> Result<[T; N], E>
+pub fn try_from_fn<F, R, const N: usize>(cb: F) -> ChangeOutputType<R, [R::Output; N]>
 where
-    F: FnMut(usize) -> Result<T, E>,
+    F: FnMut(usize) -> R,
+    R: Try,
+    R::Residual: Residual<[R::Output; N]>,
 {
     // SAFETY: we know for certain that this iterator will yield exactly `N`
     // items.
-    unsafe { collect_into_array_rslt_unchecked(&mut (0..N).map(cb)) }
+    unsafe { try_collect_into_array_unchecked(&mut (0..N).map(cb)) }
 }
 
 /// Converts a reference to `T` into a reference to an array of length 1 (without copying).
@@ -330,11 +341,9 @@ fn index_mut(&mut self, index: I) -> &mut Self::Output {
     }
 }
 
-#[cfg(not(bootstrap))]
 #[stable(feature = "copy_clone_array_lib", since = "1.58.0")]
 impl<T: Copy, const N: usize> Copy for [T; N] {}
 
-#[cfg(not(bootstrap))]
 #[stable(feature = "copy_clone_array_lib", since = "1.58.0")]
 impl<T: Clone, const N: usize> Clone for [T; N] {
     #[inline]
@@ -348,12 +357,10 @@ fn clone_from(&mut self, other: &Self) {
     }
 }
 
-#[cfg(not(bootstrap))]
 trait SpecArrayClone: Clone {
     fn clone<const N: usize>(array: &[Self; N]) -> [Self; N];
 }
 
-#[cfg(not(bootstrap))]
 impl<T: Clone> SpecArrayClone for T {
     #[inline]
     default fn clone<const N: usize>(array: &[T; N]) -> [T; N] {
@@ -363,7 +370,6 @@ impl<T: Clone> SpecArrayClone for T {
     }
 }
 
-#[cfg(not(bootstrap))]
 impl<T: Copy> SpecArrayClone for T {
     #[inline]
     fn clone<const N: usize>(array: &[T; N]) -> [T; N] {
@@ -449,6 +455,45 @@ macro_rules! array_impl_default {
         unsafe { collect_into_array_unchecked(&mut IntoIterator::into_iter(self).map(f)) }
     }
 
+    /// A fallible function `f` applied to each element on array `self` in order to
+    /// return an array the same size as `self` or the first error encountered.
+    ///
+    /// The return type of this function depends on the return type of the closure.
+    /// If you return `Result<T, E>` from the closure, you'll get a `Result<[T; N]; E>`.
+    /// If you return `Option<T>` from the closure, you'll get an `Option<[T; N]>`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(array_try_map)]
+    /// let a = ["1", "2", "3"];
+    /// let b = a.try_map(|v| v.parse::<u32>()).unwrap().map(|v| v + 1);
+    /// assert_eq!(b, [2, 3, 4]);
+    ///
+    /// let a = ["1", "2a", "3"];
+    /// let b = a.try_map(|v| v.parse::<u32>());
+    /// assert!(b.is_err());
+    ///
+    /// use std::num::NonZeroU32;
+    /// let z = [1, 2, 0, 3, 4];
+    /// assert_eq!(z.try_map(NonZeroU32::new), None);
+    /// let a = [1, 2, 3];
+    /// let b = a.try_map(NonZeroU32::new);
+    /// let c = b.map(|x| x.map(NonZeroU32::get));
+    /// assert_eq!(c, Some(a));
+    /// ```
+    #[unstable(feature = "array_try_map", issue = "79711")]
+    pub fn try_map<F, R>(self, f: F) -> ChangeOutputType<R, [R::Output; N]>
+    where
+        F: FnMut(T) -> R,
+        R: Try,
+        R::Residual: Residual<[R::Output; N]>,
+    {
+        // SAFETY: we know for certain that this iterator will yield exactly `N`
+        // items.
+        unsafe { try_collect_into_array_unchecked(&mut IntoIterator::into_iter(self).map(f)) }
+    }
+
     /// 'Zips up' two arrays into a single array of pairs.
     ///
     /// `zip()` returns a new array where every element is a tuple where the
@@ -626,42 +671,42 @@ pub fn as_mut_slice(&mut self) -> &mut [T] {
 /// Pulls `N` items from `iter` and returns them as an array. If the iterator
 /// yields fewer than `N` items, this function exhibits undefined behavior.
 ///
-/// See [`collect_into_array`] for more information.
+/// See [`try_collect_into_array`] for more information.
 ///
 ///
 /// # Safety
 ///
 /// It is up to the caller to guarantee that `iter` yields at least `N` items.
 /// Violating this condition causes undefined behavior.
-unsafe fn collect_into_array_rslt_unchecked<E, I, T, const N: usize>(
-    iter: &mut I,
-) -> Result<[T; N], E>
+unsafe fn try_collect_into_array_unchecked<I, T, R, const N: usize>(iter: &mut I) -> R::TryType
 where
     // Note: `TrustedLen` here is somewhat of an experiment. This is just an
     // internal function, so feel free to remove if this bound turns out to be a
     // bad idea. In that case, remember to also remove the lower bound
     // `debug_assert!` below!
-    I: Iterator<Item = Result<T, E>> + TrustedLen,
+    I: Iterator + TrustedLen,
+    I::Item: Try<Output = T, Residual = R>,
+    R: Residual<[T; N]>,
 {
     debug_assert!(N <= iter.size_hint().1.unwrap_or(usize::MAX));
     debug_assert!(N <= iter.size_hint().0);
 
     // SAFETY: covered by the function contract.
-    unsafe { collect_into_array(iter).unwrap_unchecked() }
+    unsafe { try_collect_into_array(iter).unwrap_unchecked() }
 }
 
-// Infallible version of `collect_into_array_rslt_unchecked`.
+// Infallible version of `try_collect_into_array_unchecked`.
 unsafe fn collect_into_array_unchecked<I, const N: usize>(iter: &mut I) -> [I::Item; N]
 where
     I: Iterator + TrustedLen,
 {
-    let mut map = iter.map(Ok::<_, Infallible>);
+    let mut map = iter.map(NeverShortCircuit);
 
     // SAFETY: The same safety considerations w.r.t. the iterator length
-    // apply for `collect_into_array_rslt_unchecked` as for
+    // apply for `try_collect_into_array_unchecked` as for
     // `collect_into_array_unchecked`
-    match unsafe { collect_into_array_rslt_unchecked(&mut map) } {
-        Ok(array) => array,
+    match unsafe { try_collect_into_array_unchecked(&mut map) } {
+        NeverShortCircuit(array) => array,
     }
 }
 
@@ -675,13 +720,15 @@ unsafe fn collect_into_array_rslt_unchecked<E, I, T, const N: usize>(
 ///
 /// If `iter.next()` panicks, all items already yielded by the iterator are
 /// dropped.
-fn collect_into_array<E, I, T, const N: usize>(iter: &mut I) -> Option<Result<[T; N], E>>
+fn try_collect_into_array<I, T, R, const N: usize>(iter: &mut I) -> Option<R::TryType>
 where
-    I: Iterator<Item = Result<T, E>>,
+    I: Iterator,
+    I::Item: Try<Output = T, Residual = R>,
+    R: Residual<[T; N]>,
 {
     if N == 0 {
         // SAFETY: An empty array is always inhabited and has no validity invariants.
-        return unsafe { Some(Ok(mem::zeroed())) };
+        return unsafe { Some(Try::from_output(mem::zeroed())) };
     }
 
     struct Guard<'a, T, const N: usize> {
@@ -706,11 +753,11 @@ fn drop(&mut self) {
     let mut guard = Guard { array_mut: &mut array, initialized: 0 };
 
     while let Some(item_rslt) = iter.next() {
-        let item = match item_rslt {
-            Err(err) => {
-                return Some(Err(err));
+        let item = match item_rslt.branch() {
+            ControlFlow::Break(r) => {
+                return Some(FromResidual::from_residual(r));
             }
-            Ok(elem) => elem,
+            ControlFlow::Continue(elem) => elem,
         };
 
         // SAFETY: `guard.initialized` starts at 0, is increased by one in the
@@ -728,7 +775,7 @@ fn drop(&mut self) {
             // SAFETY: the condition above asserts that all elements are
             // initialized.
             let out = unsafe { MaybeUninit::array_assume_init(array) };
-            return Some(Ok(out));
+            return Some(Try::from_output(out));
         }
     }
 
index 80d3270d73cc824a80759b328ac5dd3eb4fecfe3..6fc3cd0b7c4adcf2abe72f363c745c08a02b1c92 100644 (file)
@@ -2186,28 +2186,34 @@ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Pointer for *const T {
     fn fmt(&self, f: &mut Formatter<'_>) -> Result {
-        let old_width = f.width;
-        let old_flags = f.flags;
-
-        // The alternate flag is already treated by LowerHex as being special-
-        // it denotes whether to prefix with 0x. We use it to work out whether
-        // or not to zero extend, and then unconditionally set it to get the
-        // prefix.
-        if f.alternate() {
-            f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32);
-
-            if f.width.is_none() {
-                f.width = Some((usize::BITS / 4) as usize + 2);
+        /// Since the formatting will be identical for all pointer types, use a non-monomorphized
+        /// implementation for the actual formatting to reduce the amount of codegen work needed
+        fn inner(ptr: *const (), f: &mut Formatter<'_>) -> Result {
+            let old_width = f.width;
+            let old_flags = f.flags;
+
+            // The alternate flag is already treated by LowerHex as being special-
+            // it denotes whether to prefix with 0x. We use it to work out whether
+            // or not to zero extend, and then unconditionally set it to get the
+            // prefix.
+            if f.alternate() {
+                f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32);
+
+                if f.width.is_none() {
+                    f.width = Some((usize::BITS / 4) as usize + 2);
+                }
             }
-        }
-        f.flags |= 1 << (FlagV1::Alternate as u32);
+            f.flags |= 1 << (FlagV1::Alternate as u32);
+
+            let ret = LowerHex::fmt(&(ptr as usize), f);
 
-        let ret = LowerHex::fmt(&(*self as *const () as usize), f);
+            f.width = old_width;
+            f.flags = old_flags;
 
-        f.width = old_width;
-        f.flags = old_flags;
+            ret
+        }
 
-        ret
+        inner(*self as *const (), f)
     }
 }
 
index 09d8a2aac26e944052724ccdc8f7789bcbe37727..6b62236b32fafba661caf2dc1a2ae098029f6d73 100644 (file)
 #[must_use = "futures do nothing unless you `.await` or poll them"]
 #[stable(feature = "futures_api", since = "1.36.0")]
 #[lang = "future_trait"]
-#[rustc_on_unimplemented(label = "`{Self}` is not a future", message = "`{Self}` is not a future")]
+#[rustc_on_unimplemented(
+    label = "`{Self}` is not a future",
+    message = "`{Self}` is not a future",
+    note = "{Self} must be a future or must implement `IntoFuture` to be awaited"
+)]
 pub trait Future {
     /// The type of value produced on completion.
     #[stable(feature = "futures_api", since = "1.36.0")]
index 4020c254446e3eb2c10dcf878810467df5e753c3..cac1866188eff1dc0c13386d2c7b6e5db81a6d0c 100644 (file)
@@ -13,6 +13,7 @@ pub trait IntoFuture {
 
     /// Creates a future from a value.
     #[unstable(feature = "into_future", issue = "67644")]
+    #[cfg_attr(not(bootstrap), lang = "into_future")]
     fn into_future(self) -> Self::Future;
 }
 
index 540160bc4c2a4daadc4d040c58dc529b3d758fe4..3ff84cc9672eb757a3e85d74f2e30d82ce43d617 100644 (file)
 /// `0xFF` byte to the `Hasher` so that the values `("ab", "c")` and `("a",
 /// "bc")` hash differently.
 ///
+/// ## Portability
+///
+/// Due to differences in endianness and type sizes, data fed by `Hash` to a `Hasher`
+/// should not be considered portable across platforms. Additionally the data passed by most
+/// standard library types should not be considered stable between compiler versions.
+///
+/// This means tests shouldn't probe hard-coded hash values or data fed to a `Hasher` and
+/// instead should check consistency with `Eq`.
+///
+/// Serialization formats intended to be portable between platforms or compiler versions should
+/// either avoid encoding hashes or only rely on `Hash` and `Hasher` implementations that
+/// provide additional guarantees.
+///
 /// [`HashMap`]: ../../std/collections/struct.HashMap.html
 /// [`HashSet`]: ../../std/collections/struct.HashSet.html
 /// [`hash`]: Hash::hash
index 0f57fb5b14180432c3481a91c94b66b74495673f..edbc250eb0d0c2a243da0244046d1cfad5c82c48 100644 (file)
@@ -853,19 +853,21 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
     /// This will statically either panic, or do nothing.
     ///
     /// This intrinsic does not have a stable counterpart.
-    #[rustc_const_unstable(feature = "const_assert_type", issue = "none")]
+    #[rustc_const_stable(feature = "const_assert_type", since = "1.59.0")]
     pub fn assert_inhabited<T>();
 
     /// A guard for unsafe functions that cannot ever be executed if `T` does not permit
     /// zero-initialization: This will statically either panic, or do nothing.
     ///
     /// This intrinsic does not have a stable counterpart.
+    #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
     pub fn assert_zero_valid<T>();
 
     /// A guard for unsafe functions that cannot ever be executed if `T` has invalid
     /// bit patterns: This will statically either panic, or do nothing.
     ///
     /// This intrinsic does not have a stable counterpart.
+    #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
     pub fn assert_uninit_valid<T>();
 
     /// Gets a reference to a static `Location` indicating where it was called.
index 565fc224f53ca06bafd5bf2f73790fd794dbc06f..ea1da8ba434edc54e21b15f73c5a7a4d8cf184b6 100644 (file)
@@ -119,8 +119,8 @@ fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
     #[rustc_inherit_overflow_checks]
     fn advance_by(&mut self, n: usize) -> Result<(), usize> {
         let mut rem = n;
-
         let step_one = self.n.saturating_add(rem);
+
         match self.iter.advance_by(step_one) {
             Ok(_) => {
                 rem -= step_one - self.n;
@@ -129,7 +129,7 @@ fn advance_by(&mut self, n: usize) -> Result<(), usize> {
             Err(advanced) => {
                 let advanced_without_skip = advanced.saturating_sub(self.n);
                 self.n = self.n.saturating_sub(advanced);
-                return Err(advanced_without_skip);
+                return if n == 0 { Ok(()) } else { Err(advanced_without_skip) };
             }
         }
 
index 81f6c294fac13f8f70e8f1528ed32640a7e52ad3..2962e0104d11d0f7cb2bd2568d582eb7f490849e 100644 (file)
@@ -215,21 +215,22 @@ fn rfold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
     }
 
     #[inline]
+    #[rustc_inherit_overflow_checks]
     fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
-        let inner_len = self.iter.len();
-        let len = self.n;
-        let remainder = len.saturating_sub(n);
-        let to_advance = inner_len - remainder;
-        match self.iter.advance_back_by(to_advance) {
-            Ok(_) => {
-                self.n = remainder;
-                if n > len {
-                    return Err(len);
-                }
-                return Ok(());
-            }
-            _ => panic!("ExactSizeIterator contract violation"),
-        }
+        // The amount by which the inner iterator needs to be shortened for it to be
+        // at most as long as the take() amount.
+        let trim_inner = self.iter.len().saturating_sub(self.n);
+        // The amount we need to advance inner to fulfill the caller's request.
+        // take(), advance_by() and len() all can be at most usize, so we don't have to worry
+        // about having to advance more than usize::MAX here.
+        let advance_by = trim_inner.saturating_add(n);
+
+        let advanced = match self.iter.advance_back_by(advance_by) {
+            Ok(_) => advance_by - trim_inner,
+            Err(advanced) => advanced - trim_inner,
+        };
+        self.n -= advanced;
+        return if advanced < n { Err(advanced) } else { Ok(()) };
     }
 }
 
index 9a589c1f3b55c3fac8911291c5b8427a813b4fc1..a6aed6d210beb9ea50a34caef132f809246b5895 100644 (file)
@@ -106,9 +106,6 @@ pub trait DoubleEndedIterator: Iterator {
     /// Calling `advance_back_by(0)` can do meaningful work, for example [`Flatten`] can advance its
     /// outer iterator until it finds an inner iterator that is not empty, which then often
     /// allows it to return a more accurate `size_hint()` than in its initial state.
-    /// `advance_back_by(0)` may either return `Ok()` or `Err(0)`. The former conveys no information
-    /// whether the iterator is or is not exhausted, the latter can be treated as if [`next_back`]
-    /// had returned `None`. Replacing a `Err(0)` with `Ok` is only correct for `n = 0`.
     ///
     /// [`advance_by`]: Iterator::advance_by
     /// [`Flatten`]: crate::iter::Flatten
index d957a7527cf58d7902bed1da9465935277de49d4..88e7623eba1ce7fe62df29da4cf4b71e10eab727 100644 (file)
@@ -1,5 +1,5 @@
 use crate::cmp::{self, Ordering};
-use crate::ops::{ControlFlow, Try};
+use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try};
 
 use super::super::TrustedRandomAccessNoCoerce;
 use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse};
@@ -249,9 +249,6 @@ fn some<T>(_: Option<T>, x: T) -> Option<T> {
     /// Calling `advance_by(0)` can do meaningful work, for example [`Flatten`]
     /// can advance its outer iterator until it finds an inner iterator that is not empty, which
     /// then often allows it to return a more accurate `size_hint()` than in its initial state.
-    /// `advance_by(0)` may either return `Ok()` or `Err(0)`. The former conveys no information
-    /// whether the iterator is or is not exhausted, the latter can be treated as if [`next`]
-    /// had returned `None`. Replacing a `Err(0)` with `Ok` is only correct for `n = 0`.
     ///
     /// [`Flatten`]: crate::iter::Flatten
     /// [`next`]: Iterator::next
@@ -461,8 +458,10 @@ fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter>
     /// In other words, it zips two iterators together, into a single one.
     ///
     /// If either iterator returns [`None`], [`next`] from the zipped iterator
-    /// will return [`None`]. If the first iterator returns [`None`], `zip` will
-    /// short-circuit and `next` will not be called on the second iterator.
+    /// will return [`None`].
+    /// If the zipped iterator has no more elements to return then each further attempt to advance
+    /// it will first try to advance the first iterator at most one time and if it still yielded an item
+    /// try to advance the second iterator at most one time.
     ///
     /// # Examples
     ///
@@ -1024,6 +1023,7 @@ fn peekable(self) -> Peekable<Self>
     /// assert_eq!(iter.next(), None);
     /// ```
     #[inline]
+    #[doc(alias = "drop_while")]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>
     where
@@ -2418,6 +2418,10 @@ fn check<T, B>(mut f: impl FnMut(T) -> Option<B>) -> impl FnMut((), T) -> Contro
     /// Applies function to the elements of iterator and returns
     /// the first true result or the first error.
     ///
+    /// The return type of this method depends on the return type of the closure.
+    /// If you return `Result<bool, E>` from the closure, you'll get a `Result<Option<Self::Item>; E>`.
+    /// If you return `Option<bool>` from the closure, you'll get an `Option<Option<Self::Item>>`.
+    ///
     /// # Examples
     ///
     /// ```
@@ -2435,32 +2439,48 @@ fn check<T, B>(mut f: impl FnMut(T) -> Option<B>) -> impl FnMut((), T) -> Contro
     /// let result = a.iter().try_find(|&&s| is_my_num(s, 5));
     /// assert!(result.is_err());
     /// ```
+    ///
+    /// This also supports other types which implement `Try`, not just `Result`.
+    /// ```
+    /// #![feature(try_find)]
+    ///
+    /// use std::num::NonZeroU32;
+    /// let a = [3, 5, 7, 4, 9, 0, 11];
+    /// let result = a.iter().try_find(|&&x| NonZeroU32::new(x).map(|y| y.is_power_of_two()));
+    /// assert_eq!(result, Some(Some(&4)));
+    /// let result = a.iter().take(3).try_find(|&&x| NonZeroU32::new(x).map(|y| y.is_power_of_two()));
+    /// assert_eq!(result, Some(None));
+    /// let result = a.iter().rev().try_find(|&&x| NonZeroU32::new(x).map(|y| y.is_power_of_two()));
+    /// assert_eq!(result, None);
+    /// ```
     #[inline]
     #[unstable(feature = "try_find", reason = "new API", issue = "63178")]
-    fn try_find<F, R, E>(&mut self, f: F) -> Result<Option<Self::Item>, E>
+    fn try_find<F, R>(&mut self, f: F) -> ChangeOutputType<R, Option<Self::Item>>
     where
         Self: Sized,
         F: FnMut(&Self::Item) -> R,
         R: Try<Output = bool>,
-        // FIXME: This bound is rather strange, but means minimal breakage on nightly.
-        // See #85115 for the issue tracking a holistic solution for this and try_map.
-        R: Try<Residual = Result<crate::convert::Infallible, E>>,
+        R::Residual: Residual<Option<Self::Item>>,
     {
         #[inline]
-        fn check<F, T, R, E>(mut f: F) -> impl FnMut((), T) -> ControlFlow<Result<T, E>>
+        fn check<I, V, R>(
+            mut f: impl FnMut(&I) -> V,
+        ) -> impl FnMut((), I) -> ControlFlow<R::TryType>
         where
-            F: FnMut(&T) -> R,
-            R: Try<Output = bool>,
-            R: Try<Residual = Result<crate::convert::Infallible, E>>,
+            V: Try<Output = bool, Residual = R>,
+            R: Residual<Option<I>>,
         {
             move |(), x| match f(&x).branch() {
                 ControlFlow::Continue(false) => ControlFlow::CONTINUE,
-                ControlFlow::Continue(true) => ControlFlow::Break(Ok(x)),
-                ControlFlow::Break(Err(x)) => ControlFlow::Break(Err(x)),
+                ControlFlow::Continue(true) => ControlFlow::Break(Try::from_output(Some(x))),
+                ControlFlow::Break(r) => ControlFlow::Break(FromResidual::from_residual(r)),
             }
         }
 
-        self.try_fold((), check(f)).break_value().transpose()
+        match self.try_fold((), check(f)) {
+            ControlFlow::Break(x) => x,
+            ControlFlow::Continue(()) => Try::from_output(None),
+        }
     }
 
     /// Searches for an element in an iterator, returning its index.
index fdb23529599c890aa6a9aeed9bff1ca85dd4a15c..b0f9368b0c068587764a754bad5ced58c91dbbf8 100644 (file)
 #![feature(const_align_of_val)]
 #![feature(const_alloc_layout)]
 #![feature(const_arguments_as_str)]
-#![feature(const_assert_type)]
 #![feature(const_bigint_helper_methods)]
 #![feature(const_caller_location)]
 #![feature(const_cell_into_inner)]
 #![feature(const_intrinsic_copy)]
 #![feature(const_intrinsic_forget)]
 #![feature(const_likely)]
-#![feature(const_maybe_uninit_as_ptr)]
+#![feature(const_maybe_uninit_as_mut_ptr)]
 #![feature(const_maybe_uninit_assume_init)]
 #![feature(const_num_from_num)]
 #![feature(const_ops)]
 #![feature(const_impl_trait)]
 #![feature(const_mut_refs)]
 #![feature(const_precise_live_drops)]
-#![cfg_attr(bootstrap, feature(const_raw_ptr_deref))]
 #![feature(const_refs_to_cell)]
 #![feature(decl_macro)]
 #![feature(derive_default_enum)]
 #![feature(doc_cfg)]
 #![feature(doc_notable_trait)]
-#![cfg_attr(bootstrap, feature(doc_primitive))]
-#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
+#![feature(rustdoc_internals)]
 #![feature(exhaustive_patterns)]
 #![feature(doc_cfg_hide)]
 #![feature(extern_types)]
 #![feature(try_blocks)]
 #![feature(unboxed_closures)]
 #![feature(unsized_fn_params)]
-#![cfg_attr(not(bootstrap), feature(asm_const))]
+#![feature(asm_const)]
 //
 // Target features:
 #![feature(aarch64_target_feature)]
@@ -409,13 +406,11 @@ pub mod arch {
 #[allow(rustdoc::bare_urls)]
 #[unstable(feature = "portable_simd", issue = "86656")]
 #[cfg(not(all(miri, doctest)))] // Miri does not support all SIMD intrinsics
-#[cfg(not(bootstrap))]
 mod core_simd;
 
 #[doc = include_str!("../../portable-simd/crates/core_simd/src/core_simd_docs.md")]
 #[unstable(feature = "portable_simd", issue = "86656")]
 #[cfg(not(all(miri, doctest)))] // Miri does not support all SIMD intrinsics
-#[cfg(not(bootstrap))]
 pub mod simd {
     #[unstable(feature = "portable_simd", issue = "86656")]
     pub use crate::core_simd::simd::*;
index 624e87955022f50177c025ee425c87c64055ac45..9a29094b52c468d336512a919fc5a2be4b1942c0 100644 (file)
@@ -528,7 +528,7 @@ pub const fn write(&mut self, val: T) -> &mut T {
     /// (Notice that the rules around references to uninitialized data are not finalized yet, but
     /// until they are, it is advisable to avoid them.)
     #[stable(feature = "maybe_uninit", since = "1.36.0")]
-    #[rustc_const_unstable(feature = "const_maybe_uninit_as_ptr", issue = "75251")]
+    #[rustc_const_stable(feature = "const_maybe_uninit_as_ptr", since = "1.59.0")]
     #[inline(always)]
     pub const fn as_ptr(&self) -> *const T {
         // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer.
@@ -567,7 +567,7 @@ pub const fn as_ptr(&self) -> *const T {
     /// (Notice that the rules around references to uninitialized data are not finalized yet, but
     /// until they are, it is advisable to avoid them.)
     #[stable(feature = "maybe_uninit", since = "1.36.0")]
-    #[rustc_const_unstable(feature = "const_maybe_uninit_as_ptr", issue = "75251")]
+    #[rustc_const_unstable(feature = "const_maybe_uninit_as_mut_ptr", issue = "75251")]
     #[inline(always)]
     pub const fn as_mut_ptr(&mut self) -> *mut T {
         // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer.
@@ -620,7 +620,7 @@ pub const fn as_mut_ptr(&mut self) -> *mut T {
     /// // `x` had not been initialized yet, so this last line caused undefined behavior. ⚠️
     /// ```
     #[stable(feature = "maybe_uninit", since = "1.36.0")]
-    #[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")]
+    #[rustc_const_stable(feature = "const_maybe_uninit_assume_init", since = "1.59.0")]
     #[inline(always)]
     #[rustc_diagnostic_item = "assume_init"]
     #[track_caller]
@@ -788,7 +788,7 @@ pub unsafe fn assume_init_drop(&mut self) {
     /// }
     /// ```
     #[stable(feature = "maybe_uninit_ref", since = "1.55.0")]
-    #[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")]
+    #[rustc_const_stable(feature = "const_maybe_uninit_assume_init", since = "1.59.0")]
     #[inline(always)]
     pub const unsafe fn assume_init_ref(&self) -> &T {
         // SAFETY: the caller must guarantee that `self` is initialized.
@@ -968,7 +968,7 @@ pub unsafe fn assume_init_drop(&mut self) {
     ///
     /// [`assume_init_ref`]: MaybeUninit::assume_init_ref
     #[unstable(feature = "maybe_uninit_slice", issue = "63569")]
-    #[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")]
+    #[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")]
     #[inline(always)]
     pub const unsafe fn slice_assume_init_ref(slice: &[Self]) -> &[T] {
         // SAFETY: casting slice to a `*const [T]` is safe since the caller guarantees that
index 7708094e1fceab656457dbd297339a35f914319e..8f895c33a63280f6e376426ae889f79ab9e7fc1d 100644 (file)
@@ -915,15 +915,13 @@ impl $Ty {
                 /// Basic usage:
                 ///
                 /// ```
-                /// #![feature(nonzero_is_power_of_two)]
-                ///
                 #[doc = concat!("let eight = std::num::", stringify!($Ty), "::new(8).unwrap();")]
                 /// assert!(eight.is_power_of_two());
                 #[doc = concat!("let ten = std::num::", stringify!($Ty), "::new(10).unwrap();")]
                 /// assert!(!ten.is_power_of_two());
                 /// ```
                 #[must_use]
-                #[unstable(feature = "nonzero_is_power_of_two", issue = "81106")]
+                #[stable(feature = "nonzero_is_power_of_two", since = "1.59.0")]
                 #[inline]
                 pub const fn is_power_of_two(self) -> bool {
                     // LLVM 11 normalizes `unchecked_sub(x, 1) & x == 0` to the implementation seen here.
index b0c15898a1fd86a362db3c931ea5bf499a5e34d1..5ee8e377de1cdfa30a8b5d7e56f847d7fa0d8e26 100644 (file)
@@ -123,6 +123,11 @@ fn from_residual(residual: ControlFlow<B, convert::Infallible>) -> Self {
     }
 }
 
+#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
+impl<B, C> ops::Residual<C> for ControlFlow<B, convert::Infallible> {
+    type TryType = ControlFlow<B, C>;
+}
+
 impl<B, C> ControlFlow<B, C> {
     /// Returns `true` if this is a `Break` variant.
     ///
index 4f23620b92b806067b336ac4fa76a5f3a7c96459..52a2e464e3a7ce1c908c87f8411570d9597b7633 100644 (file)
@@ -82,6 +82,7 @@ pub trait Generator<R = ()> {
     /// `return` statement or implicitly as the last expression of a generator
     /// literal. For example futures would use this as `Result<T, E>` as it
     /// represents a completed future.
+    #[lang = "generator_return"]
     type Return;
 
     /// Resumes the execution of this generator.
index bd7feb8b183ced5c29727a33299ae357ec72fa47..9d1e7e81b0e7e853eee1b44642e4b49af9957b57 100644 (file)
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive};
 
+#[unstable(feature = "one_sided_range", issue = "69780")]
+pub use self::range::OneSidedRange;
+
 #[unstable(feature = "try_trait_v2", issue = "84277")]
 pub use self::try_trait::{FromResidual, Try};
 
+#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
+pub use self::try_trait::Residual;
+
+pub(crate) use self::try_trait::{ChangeOutputType, NeverShortCircuit};
+
 #[unstable(feature = "generator_trait", issue = "43122")]
 pub use self::generator::{Generator, GeneratorState};
 
index b74ba92c76eb6e459c5989c40e8b1388503f20fe..1136722067874250be22bfba32ef44aa126a213b 100644 (file)
@@ -971,3 +971,21 @@ fn end_bound(&self) -> Bound<&T> {
         Included(self.end)
     }
 }
+
+/// `OneSidedRange` is implemented for built-in range types that are unbounded
+/// on one side. For example, `a..`, `..b` and `..=c` implement `OneSidedRange`,
+/// but `..`, `d..e`, and `f..=g` do not.
+///
+/// Types that implement `OneSidedRange<T>` must return `Bound::Unbounded`
+/// from one of `RangeBounds::start_bound` or `RangeBounds::end_bound`.
+#[unstable(feature = "one_sided_range", issue = "69780")]
+pub trait OneSidedRange<T: ?Sized>: RangeBounds<T> {}
+
+#[unstable(feature = "one_sided_range", issue = "69780")]
+impl<T> OneSidedRange<T> for RangeTo<T> where Self: RangeBounds<T> {}
+
+#[unstable(feature = "one_sided_range", issue = "69780")]
+impl<T> OneSidedRange<T> for RangeFrom<T> where Self: RangeBounds<T> {}
+
+#[unstable(feature = "one_sided_range", issue = "69780")]
+impl<T> OneSidedRange<T> for RangeToInclusive<T> where Self: RangeBounds<T> {}
index 6bdcda775ee8365bc2c4a1f6f950d3af49040979..f4f0a5898097ff305b44eea5a1aefe39a3bb03b5 100644 (file)
@@ -338,3 +338,61 @@ pub trait FromResidual<R = <Self as Try>::Residual> {
     #[unstable(feature = "try_trait_v2", issue = "84277")]
     fn from_residual(residual: R) -> Self;
 }
+
+/// Allows retrieving the canonical type implementing [`Try`] that has this type
+/// as its residual and allows it to hold an `O` as its output.
+///
+/// If you think of the `Try` trait as splitting a type into its [`Try::Output`]
+/// and [`Try::Residual`] components, this allows putting them back together.
+///
+/// For example,
+/// `Result<T, E>: Try<Output = T, Residual = Result<Infallible, E>>`,
+/// and in the other direction,
+/// `<Result<Infallible, E> as Residual<T>>::TryType = Result<T, E>`.
+#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
+pub trait Residual<O> {
+    /// The "return" type of this meta-function.
+    #[unstable(feature = "try_trait_v2_residual", issue = "91285")]
+    type TryType: Try<Output = O, Residual = Self>;
+}
+
+#[unstable(feature = "pub_crate_should_not_need_unstable_attr", issue = "none")]
+pub(crate) type ChangeOutputType<T, V> = <<T as Try>::Residual as Residual<V>>::TryType;
+
+/// An adapter for implementing non-try methods via the `Try` implementation.
+///
+/// Conceptually the same as `Result<T, !>`, but requiring less work in trait
+/// solving and inhabited-ness checking and such, by being an obvious newtype
+/// and not having `From` bounds lying around.
+///
+/// Not currently planned to be exposed publicly, so just `pub(crate)`.
+#[repr(transparent)]
+pub(crate) struct NeverShortCircuit<T>(pub T);
+
+pub(crate) enum NeverShortCircuitResidual {}
+
+impl<T> Try for NeverShortCircuit<T> {
+    type Output = T;
+    type Residual = NeverShortCircuitResidual;
+
+    #[inline]
+    fn branch(self) -> ControlFlow<NeverShortCircuitResidual, T> {
+        ControlFlow::Continue(self.0)
+    }
+
+    #[inline]
+    fn from_output(x: T) -> Self {
+        NeverShortCircuit(x)
+    }
+}
+
+impl<T> FromResidual for NeverShortCircuit<T> {
+    #[inline]
+    fn from_residual(never: NeverShortCircuitResidual) -> Self {
+        match never {}
+    }
+}
+
+impl<T> Residual<T> for NeverShortCircuitResidual {
+    type TryType = NeverShortCircuit<T>;
+}
index baf9948857bbe1e0c2d96eeaad6827e0727bebcd..7b9c6e43960f7b61a2e15931dd090ac1a2656ecb 100644 (file)
@@ -703,7 +703,8 @@ pub fn as_pin_mut(self: Pin<&mut Self>) -> Option<Pin<&mut T>> {
     #[inline]
     #[track_caller]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn expect(self, msg: &str) -> T {
+    #[rustc_const_unstable(feature = "const_option", issue = "67441")]
+    pub const fn expect(self, msg: &str) -> T {
         match self {
             Some(val) => val,
             None => expect_failed(msg),
@@ -848,6 +849,31 @@ pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {
         }
     }
 
+    /// Calls the provided closure with a reference to the contained value (if [`Some`]).
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(result_option_inspect)]
+    ///
+    /// let v = vec![1, 2, 3, 4, 5];
+    ///
+    /// // prints "got: 4"
+    /// let x: Option<&usize> = v.get(3).inspect(|x| println!("got: {}", x));
+    ///
+    /// // prints nothing
+    /// let x: Option<&usize> = v.get(5).inspect(|x| println!("got: {}", x));
+    /// ```
+    #[inline]
+    #[unstable(feature = "result_option_inspect", issue = "91345")]
+    pub fn inspect<F: FnOnce(&T)>(self, f: F) -> Self {
+        if let Some(ref x) = self {
+            f(x);
+        }
+
+        self
+    }
+
     /// Returns the provided default result (if none),
     /// or applies a function to the contained value (if any).
     ///
@@ -1633,7 +1659,7 @@ pub const fn transpose(self) -> Result<Option<T>, E> {
 #[inline(never)]
 #[cold]
 #[track_caller]
-fn expect_failed(msg: &str) -> ! {
+const fn expect_failed(msg: &str) -> ! {
     panic!("{}", msg)
 }
 
@@ -2063,6 +2089,11 @@ fn from_residual(residual: Option<convert::Infallible>) -> Self {
     }
 }
 
+#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
+impl<T> ops::Residual<T> for Option<convert::Infallible> {
+    type TryType = Option<T>;
+}
+
 impl<T> Option<Option<T>> {
     /// Converts from `Option<Option<T>>` to `Option<T>`.
     ///
index 8fec2e928aae2505b8154d91c813dec46c5e627d..e6b8c8ec3385a09077f2f743e975ec1d63d63558 100644 (file)
@@ -854,6 +854,53 @@ pub fn map_err<F, O: FnOnce(E) -> F>(self, op: O) -> Result<T, F> {
         }
     }
 
+    /// Calls the provided closure with a reference to the contained value (if [`Ok`]).
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(result_option_inspect)]
+    ///
+    /// let x: u8 = "4"
+    ///     .parse::<u8>()
+    ///     .inspect(|x| println!("original: {}", x))
+    ///     .map(|x| x.pow(3))
+    ///     .expect("failed to parse number");
+    /// ```
+    #[inline]
+    #[unstable(feature = "result_option_inspect", issue = "91345")]
+    pub fn inspect<F: FnOnce(&T)>(self, f: F) -> Self {
+        if let Ok(ref t) = self {
+            f(t);
+        }
+
+        self
+    }
+
+    /// Calls the provided closure with a reference to the contained error (if [`Err`]).
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(result_option_inspect)]
+    ///
+    /// use std::{fs, io};
+    ///
+    /// fn read() -> io::Result<String> {
+    ///     fs::read_to_string("address.txt")
+    ///         .inspect_err(|e| eprintln!("failed to read file: {}", e))
+    /// }
+    /// ```
+    #[inline]
+    #[unstable(feature = "result_option_inspect", issue = "91345")]
+    pub fn inspect_err<F: FnOnce(&E)>(self, f: F) -> Self {
+        if let Err(ref e) = self {
+            f(e);
+        }
+
+        self
+    }
+
     /////////////////////////////////////////////////////////////////////////
     // Iterator constructors
     /////////////////////////////////////////////////////////////////////////
@@ -1912,3 +1959,8 @@ fn from_residual(residual: Result<convert::Infallible, E>) -> Self {
         }
     }
 }
+
+#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
+impl<T, E> ops::Residual<T> for Result<convert::Infallible, E> {
+    type TryType = Result<T, E>;
+}
index 34754cffae12a4cd94be76d771f3de48d6071295..a3f59d307595485aeeb6e0c0df7db95899c0032c 100644 (file)
@@ -10,7 +10,7 @@
 use crate::marker::Copy;
 use crate::mem;
 use crate::num::NonZeroUsize;
-use crate::ops::{FnMut, Range, RangeBounds};
+use crate::ops::{Bound, FnMut, OneSidedRange, Range, RangeBounds};
 use crate::option::Option;
 use crate::option::Option::{None, Some};
 use crate::ptr;
 #[unstable(feature = "inherent_ascii_escape", issue = "77174")]
 pub use ascii::EscapeAscii;
 
+/// Calculates the direction and split point of a one-sided range.
+///
+/// This is a helper function for `take` and `take_mut` that returns
+/// the direction of the split (front or back) as well as the index at
+/// which to split. Returns `None` if the split index would overflow.
+#[inline]
+fn split_point_of(range: impl OneSidedRange<usize>) -> Option<(Direction, usize)> {
+    use Bound::*;
+
+    Some(match (range.start_bound(), range.end_bound()) {
+        (Unbounded, Excluded(i)) => (Direction::Front, *i),
+        (Unbounded, Included(i)) => (Direction::Front, i.checked_add(1)?),
+        (Excluded(i), Unbounded) => (Direction::Back, i.checked_add(1)?),
+        (Included(i), Unbounded) => (Direction::Back, *i),
+        _ => unreachable!(),
+    })
+}
+
+enum Direction {
+    Front,
+    Back,
+}
+
 #[lang = "slice"]
 #[cfg(not(test))]
 impl<T> [T] {
@@ -3517,6 +3540,245 @@ pub fn partition_point<P>(&self, mut pred: P) -> usize
     {
         self.binary_search_by(|x| if pred(x) { Less } else { Greater }).unwrap_or_else(|i| i)
     }
+
+    /// Removes the subslice corresponding to the given range
+    /// and returns a reference to it.
+    ///
+    /// Returns `None` and does not modify the slice if the given
+    /// range is out of bounds.
+    ///
+    /// Note that this method only accepts one-sided ranges such as
+    /// `2..` or `..6`, but not `2..6`.
+    ///
+    /// # Examples
+    ///
+    /// Taking the first three elements of a slice:
+    ///
+    /// ```
+    /// #![feature(slice_take)]
+    ///
+    /// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
+    /// let mut first_three = slice.take(..3).unwrap();
+    ///
+    /// assert_eq!(slice, &['d']);
+    /// assert_eq!(first_three, &['a', 'b', 'c']);
+    /// ```
+    ///
+    /// Taking the last two elements of a slice:
+    ///
+    /// ```
+    /// #![feature(slice_take)]
+    ///
+    /// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
+    /// let mut tail = slice.take(2..).unwrap();
+    ///
+    /// assert_eq!(slice, &['a', 'b']);
+    /// assert_eq!(tail, &['c', 'd']);
+    /// ```
+    ///
+    /// Getting `None` when `range` is out of bounds:
+    ///
+    /// ```
+    /// #![feature(slice_take)]
+    ///
+    /// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
+    ///
+    /// assert_eq!(None, slice.take(5..));
+    /// assert_eq!(None, slice.take(..5));
+    /// assert_eq!(None, slice.take(..=4));
+    /// let expected: &[char] = &['a', 'b', 'c', 'd'];
+    /// assert_eq!(Some(expected), slice.take(..4));
+    /// ```
+    #[inline]
+    #[must_use = "method does not modify the slice if the range is out of bounds"]
+    #[unstable(feature = "slice_take", issue = "62280")]
+    pub fn take<'a, R: OneSidedRange<usize>>(self: &mut &'a Self, range: R) -> Option<&'a Self> {
+        let (direction, split_index) = split_point_of(range)?;
+        if split_index > self.len() {
+            return None;
+        }
+        let (front, back) = self.split_at(split_index);
+        match direction {
+            Direction::Front => {
+                *self = back;
+                Some(front)
+            }
+            Direction::Back => {
+                *self = front;
+                Some(back)
+            }
+        }
+    }
+
+    /// Removes the subslice corresponding to the given range
+    /// and returns a mutable reference to it.
+    ///
+    /// Returns `None` and does not modify the slice if the given
+    /// range is out of bounds.
+    ///
+    /// Note that this method only accepts one-sided ranges such as
+    /// `2..` or `..6`, but not `2..6`.
+    ///
+    /// # Examples
+    ///
+    /// Taking the first three elements of a slice:
+    ///
+    /// ```
+    /// #![feature(slice_take)]
+    ///
+    /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
+    /// let mut first_three = slice.take_mut(..3).unwrap();
+    ///
+    /// assert_eq!(slice, &mut ['d']);
+    /// assert_eq!(first_three, &mut ['a', 'b', 'c']);
+    /// ```
+    ///
+    /// Taking the last two elements of a slice:
+    ///
+    /// ```
+    /// #![feature(slice_take)]
+    ///
+    /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
+    /// let mut tail = slice.take_mut(2..).unwrap();
+    ///
+    /// assert_eq!(slice, &mut ['a', 'b']);
+    /// assert_eq!(tail, &mut ['c', 'd']);
+    /// ```
+    ///
+    /// Getting `None` when `range` is out of bounds:
+    ///
+    /// ```
+    /// #![feature(slice_take)]
+    ///
+    /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
+    ///
+    /// assert_eq!(None, slice.take_mut(5..));
+    /// assert_eq!(None, slice.take_mut(..5));
+    /// assert_eq!(None, slice.take_mut(..=4));
+    /// let expected: &mut [_] = &mut ['a', 'b', 'c', 'd'];
+    /// assert_eq!(Some(expected), slice.take_mut(..4));
+    /// ```
+    #[inline]
+    #[must_use = "method does not modify the slice if the range is out of bounds"]
+    #[unstable(feature = "slice_take", issue = "62280")]
+    pub fn take_mut<'a, R: OneSidedRange<usize>>(
+        self: &mut &'a mut Self,
+        range: R,
+    ) -> Option<&'a mut Self> {
+        let (direction, split_index) = split_point_of(range)?;
+        if split_index > self.len() {
+            return None;
+        }
+        let (front, back) = mem::take(self).split_at_mut(split_index);
+        match direction {
+            Direction::Front => {
+                *self = back;
+                Some(front)
+            }
+            Direction::Back => {
+                *self = front;
+                Some(back)
+            }
+        }
+    }
+
+    /// Removes the first element of the slice and returns a reference
+    /// to it.
+    ///
+    /// Returns `None` if the slice is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_take)]
+    ///
+    /// let mut slice: &[_] = &['a', 'b', 'c'];
+    /// let first = slice.take_first().unwrap();
+    ///
+    /// assert_eq!(slice, &['b', 'c']);
+    /// assert_eq!(first, &'a');
+    /// ```
+    #[inline]
+    #[unstable(feature = "slice_take", issue = "62280")]
+    pub fn take_first<'a>(self: &mut &'a Self) -> Option<&'a T> {
+        let (first, rem) = self.split_first()?;
+        *self = rem;
+        Some(first)
+    }
+
+    /// Removes the first element of the slice and returns a mutable
+    /// reference to it.
+    ///
+    /// Returns `None` if the slice is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_take)]
+    ///
+    /// let mut slice: &mut [_] = &mut ['a', 'b', 'c'];
+    /// let first = slice.take_first_mut().unwrap();
+    /// *first = 'd';
+    ///
+    /// assert_eq!(slice, &['b', 'c']);
+    /// assert_eq!(first, &'d');
+    /// ```
+    #[inline]
+    #[unstable(feature = "slice_take", issue = "62280")]
+    pub fn take_first_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> {
+        let (first, rem) = mem::take(self).split_first_mut()?;
+        *self = rem;
+        Some(first)
+    }
+
+    /// Removes the last element of the slice and returns a reference
+    /// to it.
+    ///
+    /// Returns `None` if the slice is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_take)]
+    ///
+    /// let mut slice: &[_] = &['a', 'b', 'c'];
+    /// let last = slice.take_last().unwrap();
+    ///
+    /// assert_eq!(slice, &['a', 'b']);
+    /// assert_eq!(last, &'c');
+    /// ```
+    #[inline]
+    #[unstable(feature = "slice_take", issue = "62280")]
+    pub fn take_last<'a>(self: &mut &'a Self) -> Option<&'a T> {
+        let (last, rem) = self.split_last()?;
+        *self = rem;
+        Some(last)
+    }
+
+    /// Removes the last element of the slice and returns a mutable
+    /// reference to it.
+    ///
+    /// Returns `None` if the slice is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_take)]
+    ///
+    /// let mut slice: &mut [_] = &mut ['a', 'b', 'c'];
+    /// let last = slice.take_last_mut().unwrap();
+    /// *last = 'd';
+    ///
+    /// assert_eq!(slice, &['a', 'b']);
+    /// assert_eq!(last, &'d');
+    /// ```
+    #[inline]
+    #[unstable(feature = "slice_take", issue = "62280")]
+    pub fn take_last_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> {
+        let (last, rem) = mem::take(self).split_last_mut()?;
+        *self = rem;
+        Some(last)
+    }
 }
 
 trait CloneFromSpec<T> {
index 81bb16d54015e9551266e41068e1bb6ec63cd5a5..d98db3f57c0f4acdc4797d1381212876c078daf7 100644 (file)
 }
 
 // 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))]
+#[cfg(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) {
@@ -161,7 +161,7 @@ const fn noop<T>(_: *const T) {}
     );
 }
 
-#[cfg(not(all(not(bootstrap), debug_assertions)))]
+#[cfg(not(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).
index 6c21a5e802026b858073de5ebe0f2abdc27377cc..32bd22846e7dd4c7749e231c2b5692efe124aa85 100644 (file)
@@ -61,36 +61,26 @@ fn safe_get(xs: &[u8], i: usize) -> u8 {
         }
 
         let mut i = 0;
+        let mut valid_up_to = 0;
         while i < self.source.len() {
-            let i_ = i;
-
-            // SAFETY: `i` starts at `0`, is less than `self.source.len()`, and
-            // only increases, so `0 <= i < self.source.len()`.
+            // SAFETY: `i < self.source.len()` per previous line.
+            // For some reason the following are both significantly slower:
+            // while let Some(&byte) = self.source.get(i) {
+            // while let Some(byte) = self.source.get(i).copied() {
             let byte = unsafe { *self.source.get_unchecked(i) };
             i += 1;
 
             if byte < 128 {
+                // This could be a `1 => ...` case in the match below, but for
+                // the common case of all-ASCII inputs, we bypass loading the
+                // sizeable UTF8_CHAR_WIDTH table into cache.
             } else {
                 let w = utf8_char_width(byte);
 
-                macro_rules! error {
-                    () => {{
-                        // SAFETY: We have checked up to `i` that source is valid UTF-8.
-                        unsafe {
-                            let r = Utf8LossyChunk {
-                                valid: from_utf8_unchecked(&self.source[0..i_]),
-                                broken: &self.source[i_..i],
-                            };
-                            self.source = &self.source[i..];
-                            return Some(r);
-                        }
-                    }};
-                }
-
                 match w {
                     2 => {
                         if safe_get(self.source, i) & 192 != TAG_CONT_U8 {
-                            error!();
+                            break;
                         }
                         i += 1;
                     }
@@ -100,13 +90,11 @@ macro_rules! error {
                             (0xE1..=0xEC, 0x80..=0xBF) => (),
                             (0xED, 0x80..=0x9F) => (),
                             (0xEE..=0xEF, 0x80..=0xBF) => (),
-                            _ => {
-                                error!();
-                            }
+                            _ => break,
                         }
                         i += 1;
                         if safe_get(self.source, i) & 192 != TAG_CONT_U8 {
-                            error!();
+                            break;
                         }
                         i += 1;
                     }
@@ -115,34 +103,45 @@ macro_rules! error {
                             (0xF0, 0x90..=0xBF) => (),
                             (0xF1..=0xF3, 0x80..=0xBF) => (),
                             (0xF4, 0x80..=0x8F) => (),
-                            _ => {
-                                error!();
-                            }
+                            _ => break,
                         }
                         i += 1;
                         if safe_get(self.source, i) & 192 != TAG_CONT_U8 {
-                            error!();
+                            break;
                         }
                         i += 1;
                         if safe_get(self.source, i) & 192 != TAG_CONT_U8 {
-                            error!();
+                            break;
                         }
                         i += 1;
                     }
-                    _ => {
-                        error!();
-                    }
+                    _ => break,
                 }
             }
+
+            valid_up_to = i;
         }
 
-        let r = Utf8LossyChunk {
-            // SAFETY: We have checked that the entire source is valid UTF-8.
-            valid: unsafe { from_utf8_unchecked(self.source) },
-            broken: &[],
-        };
-        self.source = &[];
-        Some(r)
+        // SAFETY: `i <= self.source.len()` because it is only ever incremented
+        // via `i += 1` and in between every single one of those increments, `i`
+        // is compared against `self.source.len()`. That happens either
+        // literally by `i < self.source.len()` in the while-loop's condition,
+        // or indirectly by `safe_get(self.source, i) & 192 != TAG_CONT_U8`. The
+        // loop is terminated as soon as the latest `i += 1` has made `i` no
+        // longer less than `self.source.len()`, which means it'll be at most
+        // equal to `self.source.len()`.
+        let (inspected, remaining) = unsafe { self.source.split_at_unchecked(i) };
+        self.source = remaining;
+
+        // SAFETY: `valid_up_to <= i` because it is only ever assigned via
+        // `valid_up_to = i` and `i` only increases.
+        let (valid, broken) = unsafe { inspected.split_at_unchecked(valid_up_to) };
+
+        Some(Utf8LossyChunk {
+            // SAFETY: All bytes up to `valid_up_to` are valid UTF-8.
+            valid: unsafe { from_utf8_unchecked(valid) },
+            broken,
+        })
     }
 }
 
index be9c41a491b8e8f68b33e24c6b3a3fdc480185e7..b2ea86d699aa6bf6f88c4dce209189e830ae241e 100644 (file)
@@ -244,22 +244,23 @@ macro_rules! next {
 
 // https://tools.ietf.org/html/rfc3629
 const UTF8_CHAR_WIDTH: &[u8; 256] = &[
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, // 0x1F
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, // 0x3F
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, // 0x5F
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, // 0x7F
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, // 0x9F
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, // 0xBF
-    0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-    2, // 0xDF
-    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xEF
-    4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xFF
+    // 1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
+    0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // D
+    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // E
+    4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F
 ];
 
 /// Given a first byte, determines how many bytes are in this UTF-8 character.
index 5efa04f7e5c578d3874e32588706da60e3d102c8..746d1cacfd0fb050071f7365409f0ca9354dd17f 100644 (file)
@@ -182,7 +182,6 @@ impl Duration {
     #[inline]
     #[must_use]
     #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
-    #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_panic))]
     pub const fn new(secs: u64, nanos: u32) -> Duration {
         let secs = match secs.checked_add((nanos / NANOS_PER_SEC) as u64) {
             Some(secs) => secs,
@@ -482,7 +481,6 @@ pub const fn as_nanos(&self) -> u128 {
                   without modifying the original"]
     #[inline]
     #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
-    #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_panic))]
     pub const fn checked_add(self, rhs: Duration) -> Option<Duration> {
         if let Some(mut secs) = self.secs.checked_add(rhs.secs) {
             let mut nanos = self.nanos + rhs.nanos;
@@ -543,7 +541,6 @@ pub const fn saturating_add(self, rhs: Duration) -> Duration {
                   without modifying the original"]
     #[inline]
     #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
-    #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_panic))]
     pub const fn checked_sub(self, rhs: Duration) -> Option<Duration> {
         if let Some(mut secs) = self.secs.checked_sub(rhs.secs) {
             let nanos = if self.nanos >= rhs.nanos {
@@ -602,7 +599,6 @@ pub const fn saturating_sub(self, rhs: Duration) -> Duration {
                   without modifying the original"]
     #[inline]
     #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
-    #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_panic))]
     pub const fn checked_mul(self, rhs: u32) -> Option<Duration> {
         // Multiply nanoseconds as u64, because it cannot overflow that way.
         let total_nanos = self.nanos as u64 * rhs as u64;
@@ -660,7 +656,6 @@ pub const fn saturating_mul(self, rhs: u32) -> Duration {
                   without modifying the original"]
     #[inline]
     #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
-    #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_panic))]
     pub const fn checked_div(self, rhs: u32) -> Option<Duration> {
         if rhs != 0 {
             let secs = self.secs / (rhs as u64);
index 7dc071b74235d3f872c742f8f540cfb628f369d6..43d30d12355eb491166d4ce7431df6590b15fbb5 100644 (file)
@@ -377,7 +377,7 @@ enum SomeError {
     let array = core::array::try_from_fn(|i| Ok::<_, SomeError>(i));
     assert_eq!(array, Ok([0, 1, 2, 3, 4]));
 
-    let another_array = core::array::try_from_fn::<SomeError, _, (), 2>(|_| Err(SomeError::Foo));
+    let another_array = core::array::try_from_fn::<_, Result<(), _>, 2>(|_| Err(SomeError::Foo));
     assert_eq!(another_array, Err(SomeError::Foo));
 }
 
index 4cd79687b53d4c372ace346ad2e67effc279ce91..f419f9cec12f8555df3281eae5019b75f4b88ea5 100644 (file)
@@ -34,6 +34,7 @@ fn test_chain(xs: &[i32], ys: &[i32]) {
             iter.advance_by(i).unwrap();
             assert_eq!(iter.next(), Some(&xs[i]));
             assert_eq!(iter.advance_by(100), Err(len - i - 1));
+            iter.advance_by(0).unwrap();
         }
 
         for i in 0..ys.len() {
@@ -41,14 +42,17 @@ fn test_chain(xs: &[i32], ys: &[i32]) {
             iter.advance_by(xs.len() + i).unwrap();
             assert_eq!(iter.next(), Some(&ys[i]));
             assert_eq!(iter.advance_by(100), Err(ys.len() - i - 1));
+            iter.advance_by(0).unwrap();
         }
 
         let mut iter = xs.iter().chain(ys);
         iter.advance_by(len).unwrap();
         assert_eq!(iter.next(), None);
+        iter.advance_by(0).unwrap();
 
         let mut iter = xs.iter().chain(ys);
         assert_eq!(iter.advance_by(len + 1), Err(len));
+        iter.advance_by(0).unwrap();
     }
 
     test_chain(&[], &[]);
@@ -67,6 +71,7 @@ fn test_chain(xs: &[i32], ys: &[i32]) {
             iter.advance_back_by(i).unwrap();
             assert_eq!(iter.next_back(), Some(&ys[ys.len() - i - 1]));
             assert_eq!(iter.advance_back_by(100), Err(len - i - 1));
+            iter.advance_back_by(0).unwrap();
         }
 
         for i in 0..xs.len() {
@@ -74,14 +79,17 @@ fn test_chain(xs: &[i32], ys: &[i32]) {
             iter.advance_back_by(ys.len() + i).unwrap();
             assert_eq!(iter.next_back(), Some(&xs[xs.len() - i - 1]));
             assert_eq!(iter.advance_back_by(100), Err(xs.len() - i - 1));
+            iter.advance_back_by(0).unwrap();
         }
 
         let mut iter = xs.iter().chain(ys);
         iter.advance_back_by(len).unwrap();
         assert_eq!(iter.next_back(), None);
+        iter.advance_back_by(0).unwrap();
 
         let mut iter = xs.iter().chain(ys);
         assert_eq!(iter.advance_back_by(len + 1), Err(len));
+        iter.advance_back_by(0).unwrap();
     }
 
     test_chain(&[], &[]);
index 4ae50a2f06681582046d0add9cc74c250e9b6ec1..cd6513327f00e242728906e3b99dae2c7f534cc5 100644 (file)
@@ -61,6 +61,7 @@ fn test_flatten_try_folds() {
 #[test]
 fn test_flatten_advance_by() {
     let mut it = once(0..10).chain(once(10..30)).chain(once(30..40)).flatten();
+
     it.advance_by(5).unwrap();
     assert_eq!(it.next(), Some(5));
     it.advance_by(9).unwrap();
@@ -72,6 +73,8 @@ fn test_flatten_advance_by() {
 
     assert_eq!(it.advance_by(usize::MAX), Err(9));
     assert_eq!(it.advance_back_by(usize::MAX), Err(0));
+    it.advance_by(0).unwrap();
+    it.advance_back_by(0).unwrap();
     assert_eq!(it.size_hint(), (0, Some(0)));
 }
 
index cf60057a1644ad1977b85771367239f298ce3f18..0c464bdd03a2202224d6692e464e24f66eb8709b 100644 (file)
@@ -69,6 +69,17 @@ fn test_iterator_skip_nth() {
     assert_eq!(it.nth(0), None);
 }
 
+#[test]
+fn test_skip_advance_by() {
+    assert_eq!((0..0).skip(10).advance_by(0), Ok(()));
+    assert_eq!((0..0).skip(10).advance_by(1), Err(0));
+    assert_eq!((0u128..(usize::MAX as u128) + 1).skip(usize::MAX).advance_by(usize::MAX), Err(1));
+    assert_eq!((0u128..u128::MAX).skip(usize::MAX).advance_by(1), Ok(()));
+
+    assert_eq!((0..2).skip(1).advance_back_by(10), Err(1));
+    assert_eq!((0..0).skip(1).advance_back_by(0), Ok(()));
+}
+
 #[test]
 fn test_iterator_skip_count() {
     let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
index 89f9cb1e2ed1bd6af4597e3f8e4aa4ace0d6598a..bfb659f0a83780cab58bedecc1bc9c0dd68890ae 100644 (file)
@@ -73,6 +73,28 @@ fn test_iterator_take_nth_back() {
     assert_eq!(it.nth_back(1), None);
 }
 
+#[test]
+fn test_take_advance_by() {
+    let mut take = (0..10).take(3);
+    assert_eq!(take.advance_by(2), Ok(()));
+    assert_eq!(take.next(), Some(2));
+    assert_eq!(take.advance_by(1), Err(0));
+
+    assert_eq!((0..0).take(10).advance_by(0), Ok(()));
+    assert_eq!((0..0).take(10).advance_by(1), Err(0));
+    assert_eq!((0..10).take(4).advance_by(5), Err(4));
+
+    let mut take = (0..10).take(3);
+    assert_eq!(take.advance_back_by(2), Ok(()));
+    assert_eq!(take.next(), Some(0));
+    assert_eq!(take.advance_back_by(1), Err(0));
+
+    assert_eq!((0..2).take(1).advance_back_by(10), Err(1));
+    assert_eq!((0..0).take(1).advance_back_by(1), Err(0));
+    assert_eq!((0..0).take(1).advance_back_by(0), Ok(()));
+    assert_eq!((0..usize::MAX).take(100).advance_back_by(usize::MAX), Err(100));
+}
+
 #[test]
 fn test_iterator_take_short() {
     let xs = [0, 1, 2, 3];
index 6b4cf33efe1ff4574e6c9a3d376d3594da71caad..84498a8eae52eb425feb786904c4509b243fb6f7 100644 (file)
@@ -300,6 +300,9 @@ fn test_range_advance_by() {
 
     assert_eq!(r.advance_by(usize::MAX), Err(usize::MAX - 2));
 
+    r.advance_by(0).unwrap();
+    r.advance_back_by(0).unwrap();
+
     let mut r = 0u128..u128::MAX;
 
     r.advance_by(usize::MAX).unwrap();
index 4563c2085c1290a91ac2c54eac284ba291b64875..d49c2552cfd4c98fdb4846a12697107038db6e9f 100644 (file)
@@ -10,6 +10,7 @@
 #![feature(const_assume)]
 #![feature(const_cell_into_inner)]
 #![feature(const_convert)]
+#![feature(const_maybe_uninit_as_mut_ptr)]
 #![feature(const_maybe_uninit_assume_init)]
 #![feature(const_ptr_read)]
 #![feature(const_ptr_write)]
@@ -35,6 +36,7 @@
 #![feature(pattern)]
 #![feature(sort_internals)]
 #![feature(slice_partition_at_index)]
+#![feature(slice_take)]
 #![feature(maybe_uninit_uninit_array)]
 #![feature(maybe_uninit_array_assume_init)]
 #![feature(maybe_uninit_extra)]
 #![feature(const_mut_refs)]
 #![feature(const_pin)]
 #![feature(const_slice_from_raw_parts)]
-#![cfg_attr(bootstrap, feature(const_raw_ptr_deref))]
 #![feature(never_type)]
 #![feature(unwrap_infallible)]
 #![feature(result_into_ok_or_err)]
-#![cfg_attr(not(bootstrap), feature(portable_simd))]
+#![feature(portable_simd)]
 #![feature(ptr_metadata)]
 #![feature(once_cell)]
 #![feature(unsized_tuple_coercion)]
 mod pin;
 mod ptr;
 mod result;
-#[cfg(not(bootstrap))]
 mod simd;
 mod slice;
 mod str;
index c780bb32ca96d89d818ead5eec654d592aedc00a..3b13dc0832fa4963905bc842c8518376c4744ed6 100644 (file)
@@ -269,3 +269,35 @@ fn uninit_const_assume_init_read() {
     const FOO: u32 = unsafe { MaybeUninit::new(42).assume_init_read() };
     assert_eq!(FOO, 42);
 }
+
+#[test]
+fn const_maybe_uninit() {
+    use std::ptr;
+
+    #[derive(Debug, PartialEq)]
+    struct Foo {
+        x: u8,
+        y: u8,
+    }
+
+    const FIELD_BY_FIELD: Foo = unsafe {
+        let mut val = MaybeUninit::uninit();
+        init_y(&mut val); // order shouldn't matter
+        init_x(&mut val);
+        val.assume_init()
+    };
+
+    const fn init_x(foo: &mut MaybeUninit<Foo>) {
+        unsafe {
+            *ptr::addr_of_mut!((*foo.as_mut_ptr()).x) = 1;
+        }
+    }
+
+    const fn init_y(foo: &mut MaybeUninit<Foo>) {
+        unsafe {
+            *ptr::addr_of_mut!((*foo.as_mut_ptr()).y) = 2;
+        }
+    }
+
+    assert_eq!(FIELD_BY_FIELD, Foo { x: 1, y: 2 });
+}
index 8d05e47edf489f7add51dcf9d43514177166a607..281df8a1326d009ecc4042f1897357c004c11207 100644 (file)
@@ -154,6 +154,7 @@ fn test_iterator_advance_by() {
     assert_eq!(iter.as_slice(), &v[3..]);
     iter.advance_by(2).unwrap();
     assert_eq!(iter.as_slice(), &[]);
+    iter.advance_by(0).unwrap();
 }
 
 #[test]
@@ -175,6 +176,7 @@ fn test_iterator_advance_back_by() {
     assert_eq!(iter.as_slice(), &v[..v.len() - 3]);
     iter.advance_back_by(2).unwrap();
     assert_eq!(iter.as_slice(), &[]);
+    iter.advance_back_by(0).unwrap();
 }
 
 #[test]
@@ -2232,3 +2234,114 @@ fn slice_split_array_mut_out_of_bounds() {
 
     v.split_array_mut::<7>();
 }
+
+macro_rules! take_tests {
+    (slice: &[], $($tts:tt)*) => {
+        take_tests!(ty: &[()], slice: &[], $($tts)*);
+    };
+    (slice: &mut [], $($tts:tt)*) => {
+        take_tests!(ty: &mut [()], slice: &mut [], $($tts)*);
+    };
+    (slice: &$slice:expr, $($tts:tt)*) => {
+        take_tests!(ty: &[_], slice: &$slice, $($tts)*);
+    };
+    (slice: &mut $slice:expr, $($tts:tt)*) => {
+        take_tests!(ty: &mut [_], slice: &mut $slice, $($tts)*);
+    };
+    (ty: $ty:ty, slice: $slice:expr, method: $method:ident, $(($test_name:ident, ($($args:expr),*), $output:expr, $remaining:expr),)*) => {
+        $(
+            #[test]
+            fn $test_name() {
+                let mut slice: $ty = $slice;
+                assert_eq!($output, slice.$method($($args)*));
+                let remaining: $ty = $remaining;
+                assert_eq!(remaining, slice);
+            }
+        )*
+    };
+}
+
+take_tests! {
+    slice: &[0, 1, 2, 3], method: take,
+    (take_in_bounds_range_to, (..1), Some(&[0] as _), &[1, 2, 3]),
+    (take_in_bounds_range_to_inclusive, (..=0), Some(&[0] as _), &[1, 2, 3]),
+    (take_in_bounds_range_from, (2..), Some(&[2, 3] as _), &[0, 1]),
+    (take_oob_range_to, (..5), None, &[0, 1, 2, 3]),
+    (take_oob_range_to_inclusive, (..=4), None, &[0, 1, 2, 3]),
+    (take_oob_range_from, (5..), None, &[0, 1, 2, 3]),
+}
+
+take_tests! {
+    slice: &mut [0, 1, 2, 3], method: take_mut,
+    (take_mut_in_bounds_range_to, (..1), Some(&mut [0] as _), &mut [1, 2, 3]),
+    (take_mut_in_bounds_range_to_inclusive, (..=0), Some(&mut [0] as _), &mut [1, 2, 3]),
+    (take_mut_in_bounds_range_from, (2..), Some(&mut [2, 3] as _), &mut [0, 1]),
+    (take_mut_oob_range_to, (..5), None, &mut [0, 1, 2, 3]),
+    (take_mut_oob_range_to_inclusive, (..=4), None, &mut [0, 1, 2, 3]),
+    (take_mut_oob_range_from, (5..), None, &mut [0, 1, 2, 3]),
+}
+
+take_tests! {
+    slice: &[1, 2], method: take_first,
+    (take_first_nonempty, (), Some(&1), &[2]),
+}
+
+take_tests! {
+    slice: &mut [1, 2], method: take_first_mut,
+    (take_first_mut_nonempty, (), Some(&mut 1), &mut [2]),
+}
+
+take_tests! {
+    slice: &[1, 2], method: take_last,
+    (take_last_nonempty, (), Some(&2), &[1]),
+}
+
+take_tests! {
+    slice: &mut [1, 2], method: take_last_mut,
+    (take_last_mut_nonempty, (), Some(&mut 2), &mut [1]),
+}
+
+take_tests! {
+    slice: &[], method: take_first,
+    (take_first_empty, (), None, &[]),
+}
+
+take_tests! {
+    slice: &mut [], method: take_first_mut,
+    (take_first_mut_empty, (), None, &mut []),
+}
+
+take_tests! {
+    slice: &[], method: take_last,
+    (take_last_empty, (), None, &[]),
+}
+
+take_tests! {
+    slice: &mut [], method: take_last_mut,
+    (take_last_mut_empty, (), None, &mut []),
+}
+
+const EMPTY_MAX: &'static [()] = &[(); usize::MAX];
+
+// can't be a constant due to const mutability rules
+macro_rules! empty_max_mut {
+    () => {
+        &mut [(); usize::MAX] as _
+    };
+}
+
+#[cfg(not(miri))] // Comparing usize::MAX many elements takes forever in Miri (and in rustc without optimizations)
+take_tests! {
+    slice: &[(); usize::MAX], method: take,
+    (take_in_bounds_max_range_to, (..usize::MAX), Some(EMPTY_MAX), &[(); 0]),
+    (take_oob_max_range_to_inclusive, (..=usize::MAX), None, EMPTY_MAX),
+    (take_in_bounds_max_range_from, (usize::MAX..), Some(&[] as _), EMPTY_MAX),
+}
+
+#[cfg(not(miri))] // Comparing usize::MAX many elements takes forever in Miri (and in rustc without optimizations)
+take_tests! {
+    slice: &mut [(); usize::MAX], method: take_mut,
+    (take_mut_in_bounds_max_range_to, (..usize::MAX), Some(empty_max_mut!()), &mut [(); 0]),
+    (take_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()),
+    (take_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()),
+}
index 8f43e902a87ed3b33057dbf39caeb4b613eeef95..f71117483214297ba4c5cc4d8300a2cb14673845 100644 (file)
@@ -15,8 +15,8 @@ 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.106", default-features = false, features = ['rustc-dep-of-std'] }
-compiler_builtins = { version = "0.1.52" }
+libc = { version = "0.2.108", default-features = false, features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "0.1.55" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.11", default-features = false, features = ['rustc-dep-of-std'] }
index d93c6172cfcf6e1e451d97faec6c45ff80f62272..da88c8c9261b41158881982ff3a012009a08e24b 100644 (file)
@@ -440,12 +440,18 @@ pub(crate) const fn new_const(kind: ErrorKind, message: &'static &'static str) -
     /// `GetLastError` on Windows) and will return a corresponding instance of
     /// [`Error`] for the error code.
     ///
+    /// This should be called immediately after a call to a platform function,
+    /// otherwise the state of the error value is indeterminate. In particular,
+    /// other standard library functions may call platform functions that may
+    /// (or may not) reset the error value even if they succeed.
+    ///
     /// # Examples
     ///
     /// ```
     /// use std::io::Error;
     ///
-    /// println!("last OS error: {:?}", Error::last_os_error());
+    /// let os_error = Error::last_os_error();
+    /// println!("last OS error: {:?}", os_error);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
index 504c3b7e9f99c575be33b94fffbfb405ede59e32..41b94cb294cfe1fc5035ec284f7a2592684883be 100644 (file)
 #![feature(const_ipv4)]
 #![feature(const_ipv6)]
 #![feature(const_option)]
-#![cfg_attr(bootstrap, feature(const_raw_ptr_deref))]
-#![cfg_attr(not(bootstrap), feature(const_mut_refs))]
+#![feature(const_mut_refs)]
 #![feature(const_socketaddr)]
 #![feature(const_trait_impl)]
 #![feature(container_error_extra)]
 #![feature(decl_macro)]
 #![feature(doc_cfg)]
 #![feature(doc_cfg_hide)]
-#![cfg_attr(bootstrap, feature(doc_primitive))]
-#![cfg_attr(bootstrap, feature(doc_keyword))]
-#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
+#![feature(rustdoc_internals)]
 #![feature(doc_masked)]
 #![feature(doc_notable_trait)]
 #![feature(dropck_eyepatch)]
 #![feature(panic_internals)]
 #![feature(panic_unwind)]
 #![feature(pin_static_ref)]
-#![cfg_attr(not(bootstrap), feature(portable_simd))]
+#![feature(portable_simd)]
 #![feature(prelude_import)]
 #![feature(ptr_internals)]
 #![feature(rustc_attrs)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::result;
 #[unstable(feature = "portable_simd", issue = "86656")]
-#[cfg(not(bootstrap))]
 pub use core::simd;
 #[unstable(feature = "async_stream", issue = "79024")]
 pub use core::stream;
index be35ab0ca1e66cf62a34cedf54d90a7c99085a2d..31d1e3c1e42ee5b3af37470867aea9f20087fa89 100644 (file)
@@ -543,6 +543,16 @@ fn is_symlink_file(&self) -> bool {
 ///     Ok(())
 /// }
 /// ```
+///
+/// # Limitations
+///
+/// Windows treats symlink creation as a [privileged action][symlink-security],
+/// therefore this function is likely to fail unless the user makes changes to
+/// their system to permit symlink creation. Users can try enabling Developer
+/// Mode, granting the `SeCreateSymbolicLinkPrivilege` privilege, or running
+/// the process as an administrator.
+///
+/// [symlink-security]: https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-symbolic-links
 #[stable(feature = "symlink", since = "1.1.0")]
 pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
     sys::fs::symlink_inner(original.as_ref(), link.as_ref(), false)
@@ -572,6 +582,16 @@ pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io:
 ///     Ok(())
 /// }
 /// ```
+///
+/// # Limitations
+///
+/// Windows treats symlink creation as a [privileged action][symlink-security],
+/// therefore this function is likely to fail unless the user makes changes to
+/// their system to permit symlink creation. Users can try enabling Developer
+/// Mode, granting the `SeCreateSymbolicLinkPrivilege` privilege, or running
+/// the process as an administrator.
+///
+/// [symlink-security]: https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-symbolic-links
 #[stable(feature = "symlink", since = "1.1.0")]
 pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
     sys::fs::symlink_inner(original.as_ref(), link.as_ref(), true)
index cf2cd5adc4848102756a30c207f34e2e4595e169..9ade2847e8ea995c06cf0b02616cf26c70049e3d 100644 (file)
 //! [`PathBuf`]; note that the paths may differ syntactically by the
 //! normalization described in the documentation for the [`components`] method.
 //!
+//! ## Case sensitivity
+//!
+//! Unless otherwise indicated path methods that do not access the filesystem,
+//! such as [`Path::starts_with`] and [`Path::ends_with`], are case sensitive no
+//! matter the platform or filesystem. An exception to this is made for Windows
+//! drive letters.
+//!
 //! ## Simple usage
 //!
 //! Path manipulation includes both parsing components from slices and building
index 691e7e07902d8210d0cd26b100eae745a934370c..415cbba101c67061fd197808fc1463b344f829f0 100644 (file)
@@ -46,8 +46,17 @@ pub const fn new(user_data: T) -> Spinlock<T> {
     #[inline]
     fn obtain_lock(&self) {
         let ticket = self.queue.fetch_add(1, Ordering::SeqCst) + 1;
+        let mut counter: u16 = 0;
         while self.dequeue.load(Ordering::SeqCst) != ticket {
-            hint::spin_loop();
+            counter += 1;
+            if counter < 100 {
+                hint::spin_loop();
+            } else {
+                counter = 0;
+                unsafe {
+                    abi::yield_now();
+                }
+            }
         }
     }
 
index 6a46525f682c4a69860c8f1232112519e291e708..73ff10ab8a221ccad212d9f231caa13fbc5b333d 100644 (file)
 
 #![cfg(target_os = "android")]
 
-use libc::{c_int, c_void, sighandler_t, size_t, ssize_t};
-use libc::{ftruncate, pread, pwrite};
+use libc::{c_int, sighandler_t};
 
-use super::{cvt, cvt_r, weak::weak};
-use crate::io;
+use super::weak::weak;
 
 // The `log2` and `log2f` functions apparently appeared in android-18, or at
 // least you can see they're not present in the android-17 header [1] and they
@@ -81,87 +79,3 @@ pub unsafe fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t {
     let f = f.expect("neither `signal` nor `bsd_signal` symbols found");
     f(signum, handler)
 }
-
-// The `ftruncate64` symbol apparently appeared in android-12, so we do some
-// dynamic detection to see if we can figure out whether `ftruncate64` exists.
-//
-// If it doesn't we just fall back to `ftruncate`, generating an error for
-// too-large values.
-#[cfg(target_pointer_width = "32")]
-pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> {
-    weak!(fn ftruncate64(c_int, i64) -> c_int);
-
-    unsafe {
-        match ftruncate64.get() {
-            Some(f) => cvt_r(|| f(fd, size as i64)).map(drop),
-            None => {
-                if size > i32::MAX as u64 {
-                    Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"cannot truncate >2GB"))
-                } else {
-                    cvt_r(|| ftruncate(fd, size as i32)).map(drop)
-                }
-            }
-        }
-    }
-}
-
-#[cfg(target_pointer_width = "64")]
-pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> {
-    unsafe { cvt_r(|| ftruncate(fd, size as i64)).map(drop) }
-}
-
-#[cfg(target_pointer_width = "32")]
-pub unsafe fn cvt_pread64(
-    fd: c_int,
-    buf: *mut c_void,
-    count: size_t,
-    offset: i64,
-) -> io::Result<ssize_t> {
-    use crate::convert::TryInto;
-    weak!(fn pread64(c_int, *mut c_void, size_t, i64) -> ssize_t);
-    pread64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| {
-        if let Ok(o) = offset.try_into() {
-            cvt(pread(fd, buf, count, o))
-        } else {
-            Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"cannot pread >2GB"))
-        }
-    })
-}
-
-#[cfg(target_pointer_width = "32")]
-pub unsafe fn cvt_pwrite64(
-    fd: c_int,
-    buf: *const c_void,
-    count: size_t,
-    offset: i64,
-) -> io::Result<ssize_t> {
-    use crate::convert::TryInto;
-    weak!(fn pwrite64(c_int, *const c_void, size_t, i64) -> ssize_t);
-    pwrite64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| {
-        if let Ok(o) = offset.try_into() {
-            cvt(pwrite(fd, buf, count, o))
-        } else {
-            Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"cannot pwrite >2GB"))
-        }
-    })
-}
-
-#[cfg(target_pointer_width = "64")]
-pub unsafe fn cvt_pread64(
-    fd: c_int,
-    buf: *mut c_void,
-    count: size_t,
-    offset: i64,
-) -> io::Result<ssize_t> {
-    cvt(pread(fd, buf, count, offset))
-}
-
-#[cfg(target_pointer_width = "64")]
-pub unsafe fn cvt_pwrite64(
-    fd: c_int,
-    buf: *const c_void,
-    count: size_t,
-    offset: i64,
-) -> io::Result<ssize_t> {
-    cvt(pwrite(fd, buf, count, offset))
-}
index 0956726084e02a21f7783841e7ec17bea3faa973..ea688571a9891ff907fc96b2351ae217d936a660 100644 (file)
@@ -99,30 +99,18 @@ pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
     }
 
     pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
-        #[cfg(target_os = "android")]
-        use super::android::cvt_pread64;
-
-        #[cfg(not(target_os = "android"))]
-        unsafe fn cvt_pread64(
-            fd: c_int,
-            buf: *mut c_void,
-            count: usize,
-            offset: i64,
-        ) -> io::Result<isize> {
-            #[cfg(not(target_os = "linux"))]
-            use libc::pread as pread64;
-            #[cfg(target_os = "linux")]
-            use libc::pread64;
-            cvt(pread64(fd, buf, count, offset))
-        }
+        #[cfg(not(any(target_os = "linux", target_os = "android")))]
+        use libc::pread as pread64;
+        #[cfg(any(target_os = "linux", target_os = "android"))]
+        use libc::pread64;
 
         unsafe {
-            cvt_pread64(
+            cvt(pread64(
                 self.as_raw_fd(),
                 buf.as_mut_ptr() as *mut c_void,
                 cmp::min(buf.len(), READ_LIMIT),
                 offset as i64,
-            )
+            ))
             .map(|n| n as usize)
         }
     }
@@ -161,30 +149,18 @@ pub fn is_write_vectored(&self) -> bool {
     }
 
     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
-        #[cfg(target_os = "android")]
-        use super::android::cvt_pwrite64;
-
-        #[cfg(not(target_os = "android"))]
-        unsafe fn cvt_pwrite64(
-            fd: c_int,
-            buf: *const c_void,
-            count: usize,
-            offset: i64,
-        ) -> io::Result<isize> {
-            #[cfg(not(target_os = "linux"))]
-            use libc::pwrite as pwrite64;
-            #[cfg(target_os = "linux")]
-            use libc::pwrite64;
-            cvt(pwrite64(fd, buf, count, offset))
-        }
+        #[cfg(not(any(target_os = "linux", target_os = "android")))]
+        use libc::pwrite as pwrite64;
+        #[cfg(any(target_os = "linux", target_os = "android"))]
+        use libc::pwrite64;
 
         unsafe {
-            cvt_pwrite64(
+            cvt(pwrite64(
                 self.as_raw_fd(),
                 buf.as_ptr() as *const c_void,
                 cmp::min(buf.len(), READ_LIMIT),
                 offset as i64,
-            )
+            ))
             .map(|n| n as usize)
         }
     }
index a4fff9b2e64731c7f775fcff82075bbf3b2c3784..d77e5cae3ad7366964f9e51738580cf8e8879c89 100644 (file)
@@ -46,8 +46,8 @@
 use libc::readdir_r as readdir64_r;
 #[cfg(target_os = "android")]
 use libc::{
-    dirent as dirent64, fstat as fstat64, fstatat as fstatat64, lseek64, lstat as lstat64,
-    open as open64, stat as stat64,
+    dirent as dirent64, fstat as fstat64, fstatat as fstatat64, ftruncate64, lseek64,
+    lstat as lstat64, off64_t, open as open64, stat as stat64,
 };
 #[cfg(not(any(
     target_os = "linux",
@@ -835,16 +835,10 @@ unsafe fn os_datasync(fd: c_int) -> c_int {
     }
 
     pub fn truncate(&self, size: u64) -> io::Result<()> {
-        #[cfg(target_os = "android")]
-        return crate::sys::android::ftruncate64(self.as_raw_fd(), size);
-
-        #[cfg(not(target_os = "android"))]
-        {
-            use crate::convert::TryInto;
-            let size: off64_t =
-                size.try_into().map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
-            cvt_r(|| unsafe { ftruncate64(self.as_raw_fd(), size) }).map(drop)
-        }
+        use crate::convert::TryInto;
+        let size: off64_t =
+            size.try_into().map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
+        cvt_r(|| unsafe { ftruncate64(self.as_raw_fd(), size) }).map(drop)
     }
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
@@ -1154,7 +1148,7 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> {
         } else if #[cfg(target_os = "macos")] {
             // On MacOS, older versions (<=10.9) lack support for linkat while newer
             // versions have it. We want to use linkat if it is available, so we use weak!
-            // to check. `linkat` is preferable to `link` ecause it gives us a flag to
+            // to check. `linkat` is preferable to `link` because it gives us a flag to
             // specify how symlinks should be handled. We pass 0 as the flags argument,
             // meaning it shouldn't follow symlinks.
             weak!(fn linkat(c_int, *const c_char, c_int, *const c_char, c_int) -> c_int);
index f3155fbc0620f1ad8dbd634fb24d3be328d4cbb1..241cf89d3145c6cfcd20dac0b125b31d14cd64b9 100644 (file)
@@ -614,6 +614,9 @@ fn sendfile_splice(mode: SpliceMode, reader: RawFd, writer: RawFd, len: u64) ->
     static HAS_SENDFILE: AtomicBool = AtomicBool::new(true);
     static HAS_SPLICE: AtomicBool = AtomicBool::new(true);
 
+    // Android builds use feature level 14, but the libc wrapper for splice is
+    // gated on feature level 21+, so we have to invoke the syscall directly.
+    #[cfg(target_os = "android")]
     syscall! {
         fn splice(
             srcfd: libc::c_int,
@@ -625,6 +628,9 @@ fn splice(
         ) -> libc::ssize_t
     }
 
+    #[cfg(target_os = "linux")]
+    use libc::splice;
+
     match mode {
         SpliceMode::Sendfile if !HAS_SENDFILE.load(Ordering::Relaxed) => {
             return CopyResult::Fallback(0);
index 9ae6d12dcb95cfc9a30256f3185db31f74ee7004..a82a0172126d4fa51066b4b5313712cb61ffe812 100644 (file)
@@ -501,7 +501,7 @@ unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
 // res_init unconditionally, we call it only when we detect we're linking
 // against glibc version < 2.26. (That is, when we both know its needed and
 // believe it's thread-safe).
-#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))]
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
 fn on_resolver_failure() {
     use crate::sys;
 
@@ -513,5 +513,5 @@ fn on_resolver_failure() {
     }
 }
 
-#[cfg(any(not(target_env = "gnu"), target_os = "vxworks"))]
+#[cfg(not(all(target_os = "linux", target_env = "gnu")))]
 fn on_resolver_failure() {}
index 87893d269120bb0eb09adcbb253b9c5aa441c4c6..e48b589f7d8f5cdf5208f432f36956f96ee4fb1f 100644 (file)
@@ -2,7 +2,7 @@
 
 #![allow(unused_imports)] // lots of cfg code here
 
-#[cfg(all(test, target_env = "gnu"))]
+#[cfg(test)]
 mod tests;
 
 use crate::os::unix::prelude::*;
@@ -97,6 +97,7 @@ pub fn errno() -> i32 {
 }
 
 #[cfg(target_os = "dragonfly")]
+#[allow(dead_code)]
 pub fn set_errno(e: i32) {
     extern "C" {
         #[thread_local]
@@ -636,22 +637,14 @@ pub fn getppid() -> u32 {
     unsafe { libc::getppid() as u32 }
 }
 
-#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))]
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
 pub fn glibc_version() -> Option<(usize, usize)> {
-    if let Some(Ok(version_str)) = glibc_version_cstr().map(CStr::to_str) {
-        parse_glibc_version(version_str)
-    } else {
-        None
-    }
-}
-
-#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))]
-fn glibc_version_cstr() -> Option<&'static CStr> {
-    weak! {
-        fn gnu_get_libc_version() -> *const libc::c_char
+    extern "C" {
+        fn gnu_get_libc_version() -> *const libc::c_char;
     }
-    if let Some(f) = gnu_get_libc_version.get() {
-        unsafe { Some(CStr::from_ptr(f())) }
+    let version_cstr = unsafe { CStr::from_ptr(gnu_get_libc_version()) };
+    if let Ok(version_str) = version_cstr.to_str() {
+        parse_glibc_version(version_str)
     } else {
         None
     }
@@ -659,7 +652,7 @@ fn gnu_get_libc_version() -> *const libc::c_char
 
 // Returns Some((major, minor)) if the string is a valid "x.y" version,
 // ignoring any extra dot-separated parts. Otherwise return None.
-#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))]
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
 fn parse_glibc_version(version: &str) -> Option<(usize, usize)> {
     let mut parsed_ints = version.split('.').map(str::parse::<usize>).fuse();
     match (parsed_ints.next(), parsed_ints.next()) {
index c445acf2722c0dc2fc5d1ea63bc31dbf789f4084..efc29955b05fea7eac7ebe2c41a4ef6c796bc120 100644 (file)
@@ -1,14 +1,12 @@
-use super::*;
-
 #[test]
-#[cfg(not(target_os = "vxworks"))]
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
 fn test_glibc_version() {
     // This mostly just tests that the weak linkage doesn't panic wildly...
-    glibc_version();
+    super::glibc_version();
 }
 
 #[test]
-#[cfg(not(target_os = "vxworks"))]
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
 fn test_parse_glibc_version() {
     let cases = [
         ("0.0", Some((0, 0))),
@@ -20,6 +18,6 @@ fn test_parse_glibc_version() {
         ("foo.1", None),
     ];
     for &(version_str, parsed) in cases.iter() {
-        assert_eq!(parsed, parse_glibc_version(version_str));
+        assert_eq!(parsed, super::parse_glibc_version(version_str));
     }
 }
index 3bf1493f3b8cbd6860cadddd0f7f44789b47d95d..bce35b380e677075da4f2f2a43024787b5d6b378 100644 (file)
@@ -13,7 +13,7 @@
 use crate::os::linux::process::PidFd;
 
 #[cfg(target_os = "linux")]
-use crate::sys::weak::syscall;
+use crate::sys::weak::raw_syscall;
 
 #[cfg(any(
     target_os = "macos",
@@ -162,7 +162,7 @@ struct clone_args {
             cgroup: u64,
         }
 
-        syscall! {
+        raw_syscall! {
             fn clone3(cl_args: *mut clone_args, len: libc::size_t) -> libc::c_long
         }
 
index b99eb2e553f08908effdf7385961767f75b30c88..9e02966b57c0d1066486eca3c1fadd507055a364 100644 (file)
@@ -7,7 +7,9 @@
 use crate::sys::{os, stack_overflow};
 use crate::time::Duration;
 
-#[cfg(any(target_os = "linux", target_os = "solaris", target_os = "illumos"))]
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
+use crate::sys::weak::dlsym;
+#[cfg(any(target_os = "solaris", target_os = "illumos"))]
 use crate::sys::weak::weak;
 #[cfg(not(any(target_os = "l4re", target_os = "vxworks", target_os = "espidf")))]
 pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
@@ -627,10 +629,12 @@ pub unsafe fn current() -> Option<Guard> {
 // We need that information to avoid blowing up when a small stack
 // is created in an application with big thread-local storage requirements.
 // See #6233 for rationale and details.
-#[cfg(target_os = "linux")]
-#[allow(deprecated)]
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
 fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize {
-    weak!(fn __pthread_get_minstack(*const libc::pthread_attr_t) -> libc::size_t);
+    // We use dlsym to avoid an ELF version dependency on GLIBC_PRIVATE. (#23628)
+    // We shouldn't really be using such an internal symbol, but there's currently
+    // no other way to account for the TLS size.
+    dlsym!(fn __pthread_get_minstack(*const libc::pthread_attr_t) -> libc::size_t);
 
     match __pthread_get_minstack.get() {
         None => libc::PTHREAD_STACK_MIN,
@@ -638,9 +642,8 @@ fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize {
     }
 }
 
-// No point in looking up __pthread_get_minstack() on non-glibc
-// platforms.
-#[cfg(all(not(target_os = "linux"), not(target_os = "netbsd")))]
+// No point in looking up __pthread_get_minstack() on non-glibc platforms.
+#[cfg(all(not(all(target_os = "linux", target_env = "gnu")), not(target_os = "netbsd")))]
 fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
     libc::PTHREAD_STACK_MIN
 }
index ba432ec54941ce3140c3a2b58e50418ea6e8280a..32072affe8af45f20c8862e23f73fe7fa059b5a2 100644 (file)
@@ -6,7 +6,7 @@
 //! detection.
 //!
 //! One option to use here is weak linkage, but that is unfortunately only
-//! really workable on Linux. Hence, use dlsym to get the symbol value at
+//! really workable with ELF. Otherwise, use dlsym to get the symbol value at
 //! runtime. This is also done for compatibility with older versions of glibc,
 //! and to avoid creating dependencies on GLIBC_PRIVATE symbols. It assumes that
 //! we've been dynamically linked to the library the symbol comes from, but that
@@ -14,7 +14,8 @@
 //!
 //! A long time ago this used weak linkage for the __pthread_get_minstack
 //! symbol, but that caused Debian to detect an unnecessarily strict versioned
-//! dependency on libc6 (#23628).
+//! dependency on libc6 (#23628) because it is GLIBC_PRIVATE. We now use `dlsym`
+//! for a runtime lookup of that symbol to avoid the ELF versioned dependency.
 
 // There are a variety of `#[cfg]`s controlling which targets are involved in
 // each instance of `weak!` and `syscall!`. Rather than trying to unify all of
 #![allow(dead_code, unused_macros)]
 
 use crate::ffi::CStr;
-use crate::marker;
+use crate::marker::PhantomData;
 use crate::mem;
 use crate::sync::atomic::{self, AtomicUsize, Ordering};
 
+// We can use true weak linkage on ELF targets.
+#[cfg(not(any(target_os = "macos", target_os = "ios")))]
 pub(crate) macro weak {
     (fn $name:ident($($t:ty),*) -> $ret:ty) => (
-        #[allow(non_upper_case_globals)]
-        static $name: crate::sys::weak::Weak<unsafe extern "C" fn($($t),*) -> $ret> =
-            crate::sys::weak::Weak::new(concat!(stringify!($name), '\0'));
+        let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = {
+            extern "C" {
+                #[linkage = "extern_weak"]
+                static $name: *const libc::c_void;
+            }
+            #[allow(unused_unsafe)]
+            ExternWeak::new(unsafe { $name })
+        };
     )
 }
 
-pub struct Weak<F> {
+// On non-ELF targets, use the dlsym approximation of weak linkage.
+#[cfg(any(target_os = "macos", target_os = "ios"))]
+pub(crate) use self::dlsym as weak;
+
+pub(crate) struct ExternWeak<F> {
+    weak_ptr: *const libc::c_void,
+    _marker: PhantomData<F>,
+}
+
+impl<F> ExternWeak<F> {
+    #[inline]
+    pub(crate) fn new(weak_ptr: *const libc::c_void) -> Self {
+        ExternWeak { weak_ptr, _marker: PhantomData }
+    }
+}
+
+impl<F> ExternWeak<F> {
+    #[inline]
+    pub(crate) fn get(&self) -> Option<F> {
+        unsafe {
+            if self.weak_ptr.is_null() {
+                None
+            } else {
+                Some(mem::transmute_copy::<*const libc::c_void, F>(&self.weak_ptr))
+            }
+        }
+    }
+}
+
+pub(crate) macro dlsym {
+    (fn $name:ident($($t:ty),*) -> $ret:ty) => (
+        static DLSYM: DlsymWeak<unsafe extern "C" fn($($t),*) -> $ret> =
+            DlsymWeak::new(concat!(stringify!($name), '\0'));
+        let $name = &DLSYM;
+    )
+}
+
+pub(crate) struct DlsymWeak<F> {
     name: &'static str,
     addr: AtomicUsize,
-    _marker: marker::PhantomData<F>,
+    _marker: PhantomData<F>,
 }
 
-impl<F> Weak<F> {
-    pub const fn new(name: &'static str) -> Weak<F> {
-        Weak { name, addr: AtomicUsize::new(1), _marker: marker::PhantomData }
+impl<F> DlsymWeak<F> {
+    pub(crate) const fn new(name: &'static str) -> Self {
+        DlsymWeak { name, addr: AtomicUsize::new(1), _marker: PhantomData }
     }
 
-    pub fn get(&self) -> Option<F> {
-        assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>());
+    #[inline]
+    pub(crate) fn get(&self) -> Option<F> {
         unsafe {
             // Relaxed is fine here because we fence before reading through the
             // pointer (see the comment below).
@@ -82,6 +127,8 @@ pub fn get(&self) -> Option<F> {
     // Cold because it should only happen during first-time initalization.
     #[cold]
     unsafe fn initialize(&self) -> Option<F> {
+        assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>());
+
         let val = fetch(self.name);
         // This synchronizes with the acquire fence in `get`.
         self.addr.store(val, Ordering::Release);
@@ -105,14 +152,12 @@ unsafe fn fetch(name: &str) -> usize {
 pub(crate) macro syscall {
     (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
         unsafe fn $name($($arg_name: $t),*) -> $ret {
-            use super::os;
-
             weak! { fn $name($($t),*) -> $ret }
 
             if let Some(fun) = $name.get() {
                 fun($($arg_name),*)
             } else {
-                os::set_errno(libc::ENOSYS);
+                super::os::set_errno(libc::ENOSYS);
                 -1
             }
         }
@@ -123,11 +168,6 @@ unsafe fn $name($($arg_name: $t),*) -> $ret {
 pub(crate) macro syscall {
     (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
         unsafe fn $name($($arg_name:$t),*) -> $ret {
-            use weak;
-            // This looks like a hack, but concat_idents only accepts idents
-            // (not paths).
-            use libc::*;
-
             weak! { fn $name($($t),*) -> $ret }
 
             // Use a weak symbol from libc when possible, allowing `LD_PRELOAD`
@@ -135,6 +175,10 @@ unsafe fn $name($($arg_name:$t),*) -> $ret {
             if let Some(fun) = $name.get() {
                 fun($($arg_name),*)
             } else {
+                // This looks like a hack, but concat_idents only accepts idents
+                // (not paths).
+                use libc::*;
+
                 syscall(
                     concat_idents!(SYS_, $name),
                     $($arg_name),*
@@ -143,3 +187,19 @@ unsafe fn $name($($arg_name:$t),*) -> $ret {
         }
     )
 }
+
+#[cfg(any(target_os = "linux", target_os = "android"))]
+pub(crate) macro raw_syscall {
+    (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
+        unsafe fn $name($($arg_name:$t),*) -> $ret {
+            // This looks like a hack, but concat_idents only accepts idents
+            // (not paths).
+            use libc::*;
+
+            syscall(
+                concat_idents!(SYS_, $name),
+                $($arg_name),*
+            ) as $ret
+        }
+    )
+}
index 4da59577d78a19cfb61ba24c47c1b54e7cc37cc9..64c8416b61c79ec4b955f85184e9db5d5ec266a3 100644 (file)
 ///    destroyed, but not all platforms have this guard. Those platforms that do
 ///    not guard typically have a synthetic limit after which point no more
 ///    destructors are run.
+/// 3. When the process exits on Windows systems, TLS destructors may only be
+///    run on the thread that causes the process to exit. This is because the
+///    other threads may be forcibly terminated.
 ///
+/// ## Synchronization in thread-local destructors
+///
+/// On Windows, synchronization operations (such as [`JoinHandle::join`]) in
+/// thread local destructors are prone to deadlocks and so should be avoided.
+/// This is because the [loader lock] is held while a destructor is run. The
+/// lock is acquired whenever a thread starts or exits or when a DLL is loaded
+/// or unloaded. Therefore these events are blocked for as long as a thread
+/// local destructor is running.
+///
+/// [loader lock]: https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices
+/// [`JoinHandle::join`]: crate::thread::JoinHandle::join
 /// [`with`]: LocalKey::with
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct LocalKey<T: 'static> {
index 39b53b51bfa637468b7ca6147b4a2ec7b8a91f1e..343d3ef8dc5388bf0a2a304b8bf2afe5404ffa93 100644 (file)
@@ -1460,9 +1460,12 @@ fn _assert_both<T: Send + Sync>() {}
 /// The purpose of this API is to provide an easy and portable way to query
 /// the default amount of parallelism the program should use. Among other things it
 /// does not expose information on NUMA regions, does not account for
-/// differences in (co)processor capabilities, and will not modify the program's
-/// global state in order to more accurately query the amount of available
-/// parallelism.
+/// differences in (co)processor capabilities or current system load,
+/// and will not modify the program's global state in order to more accurately
+/// query the amount of available parallelism.
+///
+/// Where both fixed steady-state and burst limits are available the steady-state
+/// capacity will be used to ensure more predictable latencies.
 ///
 /// Resource limits can be changed during the runtime of a program, therefore the value is
 /// not cached and instead recomputed every time this function is called. It should not be
index 1d0b4a59a287b05969080147a5aab691d0e36603..a3f5224151d941ec9e3c497403788319fff6be1a 100644 (file)
@@ -17,6 +17,9 @@ fn main() {
         } else {
             println!("cargo:rustc-link-lib=gcc");
         }
+
+        // Android's unwinding library depends on dl_iterate_phdr in `libdl`.
+        println!("cargo:rustc-link-lib=dl");
     } else if target.contains("freebsd") {
         println!("cargo:rustc-link-lib=gcc_s");
     } else if target.contains("netbsd") {
index 3b3c8a9227d95f4c98f76ddf150867eeff761d75..1667dfc3f8544ad3f2ac2bb0519d055a914e956d 100644 (file)
@@ -493,7 +493,7 @@ fn dir_is_empty(dir: &Path) -> bool {
 
         // NOTE: The check for the empty directory is here because when running x.py the first time,
         // the submodule won't be checked out. Check it out now so we can build it.
-        if !channel::GitInfo::new(false, relative_path).is_git() && !dir_is_empty(&absolute_path) {
+        if !channel::GitInfo::new(false, &absolute_path).is_git() && !dir_is_empty(&absolute_path) {
             return;
         }
 
index ba4e1ca31148cf0d29e7af3456d05d4281df1f0a..f71282a1b52d47bd1411e2331df71f32a8557e9c 100644 (file)
@@ -72,7 +72,7 @@ ENV PATH="/node-v14.4.0-linux-x64/bin:${PATH}"
 # https://github.com/puppeteer/puppeteer/issues/375
 #
 # We also specify the version in case we need to update it to go around cache limitations.
-RUN npm install -g browser-ui-test@0.4.5 --unsafe-perm=true
+RUN npm install -g browser-ui-test@0.5.0 --unsafe-perm=true
 
 ENV RUST_CONFIGURE_ARGS \
   --build=x86_64-unknown-linux-gnu \
index 70900a0bab942fa514533aec0fc3f884c8ab89e2..6be53fb4cfed4c53fd5eca1f7fdf74d5f4eb9593 100644 (file)
@@ -261,6 +261,16 @@ conversion, so type inference fails because the type is not unique. Please note
 that you must write the `(())` in one sequence without intermediate whitespace
 so that `rustdoc` understands you want an implicit `Result`-returning function.
 
+## Showing warnings in doctests
+
+You can show warnings in doctests by running `rustdoc --test --test-args=--show-output`
+(or, if you're using cargo, `cargo test --doc -- --show-output`).
+By default, this will still hide `unused` warnings, since so many examples use private functions;
+you can add `#![warn(unused)]` to the top of your example if you want to see unused variables or dead code warnings.
+You can also use [`#![doc(test(attr(warn(unused))))]`][test-attr] in the crate root to enable warnings globally.
+
+[test-attr]: ./the-doc-attribute.md#testattr
+
 ## Documenting macros
 
 Here’s an example of documenting a macro:
index 6e52127591c76c66388d63a6abf817778ddae434..021040215437e0015697c4fd3554292193a3f08e 100644 (file)
@@ -257,22 +257,6 @@ all these files are linked from every page, changing where they are can be cumbe
 specially cache them. This flag will rename all these files in the output to include the suffix in
 the filename. For example, `light.css` would become `light-suf.css` with the above command.
 
-### `--display-doctest-warnings`: display warnings when documenting or running documentation tests
-
-Using this flag looks like this:
-
-```bash
-$ rustdoc src/lib.rs -Z unstable-options --display-doctest-warnings
-$ rustdoc --test src/lib.rs -Z unstable-options --display-doctest-warnings
-```
-
-The intent behind this flag is to allow the user to see warnings that occur within their library or
-their documentation tests, which are usually suppressed. However, [due to a
-bug][issue-display-warnings], this flag doesn't 100% work as intended. See the linked issue for
-details.
-
-[issue-display-warnings]: https://github.com/rust-lang/rust/issues/41574
-
 ### `--extern-html-root-url`: control how rustdoc links to non-local crates
 
 Using this flag looks like this:
index f7c2a26f01817016048f95d961878a64eb50effa..f4d1ca0ec691130ffe2bcd74006655ae213d1012 100644 (file)
@@ -20,7 +20,7 @@ This document describes how to enable and use the LLVM instrumentation-based cov
 When `-Z instrument-coverage` is enabled, the Rust compiler enhances rust-based libraries and binaries by:
 
 -   Automatically injecting calls to an LLVM intrinsic ([`llvm.instrprof.increment`]), at functions and branches in compiled code, to increment counters when conditional sections of code are executed.
--   Embedding additional information in the data section of each library and binary (using the [LLVM Code Coverage Mapping Format] _Version 4_, supported _only_ in LLVM 11 and up), to define the code regions (start and end positions in the source code) being counted.
+-   Embedding additional information in the data section of each library and binary (using the [LLVM Code Coverage Mapping Format] _Version 5_, if compiling with LLVM 12, or _Version 6_, if compiling with LLVM 13 or higher), to define the code regions (start and end positions in the source code) being counted.
 
 When running a coverage-instrumented program, the counter values are written to a `profraw` file at program termination. LLVM bundles tools that read the counter results, combine those results with the coverage map (embedded in the program binary), and generate coverage reports in multiple formats.
 
@@ -123,7 +123,7 @@ If `LLVM_PROFILE_FILE` contains a path to a non-existent directory, the missing
 
 ## Installing LLVM coverage tools
 
-LLVM's supplies two tools—`llvm-profdata` and `llvm-cov`—that process coverage data and generate reports. There are several ways to find and/or install these tools, but note that the coverage mapping data generated by the Rust compiler requires LLVM version 11 or higher. (`llvm-cov --version` typically shows the tool's LLVM version number.):
+LLVM's supplies two tools—`llvm-profdata` and `llvm-cov`—that process coverage data and generate reports. There are several ways to find and/or install these tools, but note that the coverage mapping data generated by the Rust compiler requires LLVM version 12 or higher. (`llvm-cov --version` typically shows the tool's LLVM version number.):
 
 -   The LLVM tools may be installed (or installable) directly to your OS (such as via `apt-get`, for Linux).
 -   If you are building the Rust compiler from source, you can optionally use the bundled LLVM tools, built from source. Those tool binaries can typically be found in your build platform directory at something like: `rust/build/x86_64-unknown-linux-gnu/llvm/bin/llvm-*`.
index d4bf93bb40931178d5236796ed61fdefefa3d316..ba67030d59fb0c999226ba998faeff69eb146dd3 100644 (file)
@@ -359,13 +359,10 @@ fn merge_attrs(
     }
 
     let impl_item = match did.as_local() {
-        Some(did) => {
-            let hir_id = tcx.hir().local_def_id_to_hir_id(did);
-            match &tcx.hir().expect_item(hir_id).kind {
-                hir::ItemKind::Impl(impl_) => Some(impl_),
-                _ => panic!("`DefID` passed to `build_impl` is not an `impl"),
-            }
-        }
+        Some(did) => match &tcx.hir().expect_item(did).kind {
+            hir::ItemKind::Impl(impl_) => Some(impl_),
+            _ => panic!("`DefID` passed to `build_impl` is not an `impl"),
+        },
         None => None,
     };
 
index de1293cd96dfc0160a4c419ae380627bb8a500ff..9c3484b4a316727e39817871d20fcedd32562c94 100644 (file)
 
 use utils::*;
 
-crate use utils::{get_auto_trait_and_blanket_impls, krate, register_res};
-
-crate use self::types::FnRetTy::*;
-crate use self::types::ItemKind::*;
-crate use self::types::SelfTy::*;
-crate use self::types::Type::*;
-crate use self::types::Visibility::{Inherited, Public};
 crate use self::types::*;
+crate use self::utils::{get_auto_trait_and_blanket_impls, krate, register_res};
 
 crate trait Clean<T> {
     fn clean(&self, cx: &mut DocContext<'_>) -> T;
@@ -755,11 +749,42 @@ fn clean_fn_or_proc_macro(
                 } else {
                     hir::Constness::NotConst
                 };
+            clean_fn_decl_legacy_const_generics(&mut func, attrs);
             FunctionItem(func)
         }
     }
 }
 
+/// This is needed to make it more "readable" when documenting functions using
+/// `rustc_legacy_const_generics`. More information in
+/// <https://github.com/rust-lang/rust/issues/83167>.
+fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[ast::Attribute]) {
+    for meta_item_list in attrs
+        .iter()
+        .filter(|a| a.has_name(sym::rustc_legacy_const_generics))
+        .filter_map(|a| a.meta_item_list())
+    {
+        for (pos, literal) in meta_item_list.iter().filter_map(|meta| meta.literal()).enumerate() {
+            match literal.kind {
+                ast::LitKind::Int(a, _) => {
+                    let gen = func.generics.params.remove(0);
+                    if let GenericParamDef { name, kind: GenericParamDefKind::Const { ty, .. } } =
+                        gen
+                    {
+                        func.decl
+                            .inputs
+                            .values
+                            .insert(a as _, Argument { name, type_: *ty, is_const: true });
+                    } else {
+                        panic!("unexpected non const in position {}", pos);
+                    }
+                }
+                _ => panic!("invalid arg index"),
+            }
+        }
+    }
+}
+
 impl<'a> Clean<Function> for (&'a hir::FnSig<'a>, &'a hir::Generics<'a>, hir::BodyId) {
     fn clean(&self, cx: &mut DocContext<'_>) -> Function {
         let (generics, decl) = enter_impl_trait(cx, |cx| {
@@ -785,7 +810,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Arguments {
                     if name.is_empty() {
                         name = kw::Underscore;
                     }
-                    Argument { name, type_: ty.clean(cx) }
+                    Argument { name, type_: ty.clean(cx), is_const: false }
                 })
                 .collect(),
         }
@@ -804,6 +829,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Arguments {
                 .map(|(i, ty)| Argument {
                     name: name_from_pat(body.params[i].pat),
                     type_: ty.clean(cx),
+                    is_const: false,
                 })
                 .collect(),
         }
@@ -834,6 +860,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> FnDecl {
                     .map(|t| Argument {
                         type_: t.clean(cx),
                         name: names.next().map_or(kw::Empty, |i| i.name),
+                        is_const: false,
                     })
                     .collect(),
             },
@@ -956,7 +983,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
 
             let what_rustc_thinks =
                 Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx);
-            let parent_item = cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(self.hir_id()));
+            let parent_item = cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_did(self.hir_id()));
             if let hir::ItemKind::Impl(impl_) = &parent_item.kind {
                 if impl_.of_trait.is_some() {
                     // Trait impl items always inherit the impl's visibility --
@@ -1195,9 +1222,8 @@ fn maybe_expand_private_type_alias(cx: &mut DocContext<'_>, path: &hir::Path<'_>
     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
+        &cx.tcx.hir().expect_item(def_id).kind
     } else {
         return None;
     };
@@ -1344,25 +1370,15 @@ fn normalize(cx: &mut DocContext<'tcx>, ty: Ty<'_>) -> Option<Ty<'tcx>> {
         return None;
     }
 
-    use crate::rustc_trait_selection::infer::TyCtxtInferExt;
-    use crate::rustc_trait_selection::traits::query::normalize::AtExt;
-    use rustc_middle::traits::ObligationCause;
-
     // Try to normalize `<X as Y>::T` to a type
     let lifted = ty.lift_to_tcx(cx.tcx).unwrap();
-    let normalized = cx.tcx.infer_ctxt().enter(|infcx| {
-        infcx
-            .at(&ObligationCause::dummy(), cx.param_env)
-            .normalize(lifted)
-            .map(|resolved| infcx.resolve_vars_if_possible(resolved.value))
-    });
-    match normalized {
+    match cx.tcx.try_normalize_erasing_regions(cx.param_env, lifted) {
         Ok(normalized_value) => {
-            debug!("normalized {:?} to {:?}", ty, normalized_value);
+            trace!("normalized {:?} to {:?}", ty, normalized_value);
             Some(normalized_value)
         }
         Err(err) => {
-            debug!("failed to normalize {:?}: {:?}", ty, err);
+            info!("failed to normalize {:?}: {:?}", ty, err);
             None
         }
     }
@@ -1411,12 +1427,12 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
                 };
                 inline::record_extern_fqn(cx, did, kind);
                 let path = external_path(cx, did, false, vec![], substs);
-                ResolvedPath { path, did }
+                Type::Path { path }
             }
             ty::Foreign(did) => {
                 inline::record_extern_fqn(cx, did, ItemType::ForeignType);
                 let path = external_path(cx, did, false, vec![], InternalSubsts::empty());
-                ResolvedPath { path, did }
+                Type::Path { path }
             }
             ty::Dynamic(obj, ref reg) => {
                 // HACK: pick the first `did` as the `did` of the trait object. Someone
index d28f3ce87785bb9f1bd30f403fb3dda91dc5e25b..1267e88f358f11c38914b2991c95b9af31ba4d62 100644 (file)
@@ -34,7 +34,6 @@
 use crate::clean::cfg::Cfg;
 use crate::clean::external_path;
 use crate::clean::inline::{self, print_inlined_const};
-use crate::clean::types::Type::{QPath, ResolvedPath};
 use crate::clean::utils::{is_literal_expr, print_const_expr, print_evaluated_const};
 use crate::clean::Clean;
 use crate::core::DocContext;
 use crate::html::render::cache::ExternalLocation;
 use crate::html::render::Context;
 
-use self::FnRetTy::*;
-use self::ItemKind::*;
-use self::SelfTy::*;
-use self::Type::*;
+crate use self::FnRetTy::*;
+crate use self::ItemKind::*;
+crate use self::SelfTy::*;
+crate use self::Type::{
+    Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath,
+    RawPointer, Slice, Tuple,
+};
+crate use self::Visibility::{Inherited, Public};
 
 crate type ItemIdSet = FxHashSet<ItemId>;
 
@@ -373,8 +376,8 @@ impl Item {
         self.def_id.as_def_id().and_then(|did| tcx.lookup_stability(did))
     }
 
-    crate fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ConstStability> {
-        self.def_id.as_def_id().and_then(|did| tcx.lookup_const_stability(did))
+    crate fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<ConstStability> {
+        self.def_id.as_def_id().and_then(|did| tcx.lookup_const_stability(did)).map(|cs| *cs)
     }
 
     crate fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
@@ -599,16 +602,16 @@ pub fn from_def_id_and_attrs_and_parts(
         })
     }
 
-    crate fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr> {
+    crate fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<Symbol> {
         match self.stability(tcx)?.level {
-            StabilityLevel::Stable { since, .. } => Some(since.as_str()),
+            StabilityLevel::Stable { since, .. } => Some(since),
             StabilityLevel::Unstable { .. } => None,
         }
     }
 
-    crate fn const_stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr> {
+    crate fn const_stable_since(&self, tcx: TyCtxt<'_>) -> Option<Symbol> {
         match self.const_stability(tcx)?.level {
-            StabilityLevel::Stable { since, .. } => Some(since.as_str()),
+            StabilityLevel::Stable { since, .. } => Some(since),
             StabilityLevel::Unstable { .. } => None,
         }
     }
@@ -1350,6 +1353,9 @@ impl FnDecl {
 crate struct Argument {
     crate type_: Type,
     crate name: Symbol,
+    /// This field is used to represent "const" arguments from the `rustc_legacy_const_generics`
+    /// feature. More information in <https://github.com/rust-lang/rust/issues/83167>.
+    crate is_const: bool,
 }
 
 #[derive(Clone, PartialEq, Debug)]
@@ -1418,8 +1424,9 @@ impl FnRetTy {
 crate enum Type {
     /// A named type, which could be a trait.
     ///
-    /// This is mostly Rustdoc's version of [`hir::Path`]. It has to be different because Rustdoc's [`PathSegment`] can contain cleaned generics.
-    ResolvedPath { path: Path, did: DefId },
+    /// This is mostly Rustdoc's version of [`hir::Path`].
+    /// It has to be different because Rustdoc's [`PathSegment`] can contain cleaned generics.
+    Path { path: Path },
     /// A `dyn Trait` object: `dyn for<'a> Trait<'a> + Send + 'static`
     DynTrait(Vec<PolyTrait>, Option<Lifetime>),
     /// A type parameter.
@@ -1464,6 +1471,45 @@ impl FnRetTy {
 rustc_data_structures::static_assert_size!(Type, 72);
 
 impl Type {
+    /// When comparing types for equality, it can help to ignore `&` wrapping.
+    crate fn without_borrowed_ref(&self) -> &Type {
+        let mut result = self;
+        while let Type::BorrowedRef { type_, .. } = result {
+            result = &*type_;
+        }
+        result
+    }
+
+    /// Check if two types are "potentially the same".
+    /// This is different from `Eq`, because it knows that things like
+    /// `Placeholder` are possible matches for everything.
+    crate fn is_same(&self, other: &Self, cache: &Cache) -> bool {
+        match (self, other) {
+            // Recursive cases.
+            (Type::Tuple(a), Type::Tuple(b)) => {
+                a.len() == b.len() && a.iter().zip(b).all(|(a, b)| a.is_same(&b, cache))
+            }
+            (Type::Slice(a), Type::Slice(b)) => a.is_same(&b, cache),
+            (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_same(&b, cache),
+            (Type::RawPointer(mutability, type_), Type::RawPointer(b_mutability, b_type_)) => {
+                mutability == b_mutability && type_.is_same(&b_type_, cache)
+            }
+            (
+                Type::BorrowedRef { mutability, type_, .. },
+                Type::BorrowedRef { mutability: b_mutability, type_: b_type_, .. },
+            ) => mutability == b_mutability && type_.is_same(&b_type_, cache),
+            // Placeholders and generics are equal to all other types.
+            (Type::Infer, _) | (_, Type::Infer) => true,
+            (Type::Generic(_), _) | (_, Type::Generic(_)) => true,
+            // Other cases, such as primitives, just use recursion.
+            (a, b) => a
+                .def_id(cache)
+                .and_then(|a| Some((a, b.def_id(cache)?)))
+                .map(|(a, b)| a == b)
+                .unwrap_or(false),
+        }
+    }
+
     crate fn primitive_type(&self) -> Option<PrimitiveType> {
         match *self {
             Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
@@ -1485,7 +1531,7 @@ impl Type {
     /// Checks if this is a `T::Name` path for an associated type.
     crate fn is_assoc_ty(&self) -> bool {
         match self {
-            ResolvedPath { path, .. } => path.is_assoc_ty(),
+            Type::Path { path, .. } => path.is_assoc_ty(),
             _ => false,
         }
     }
@@ -1499,7 +1545,7 @@ impl Type {
 
     crate fn generics(&self) -> Option<Vec<&Type>> {
         match self {
-            ResolvedPath { path, .. } => path.generics(),
+            Type::Path { path, .. } => path.generics(),
             _ => None,
         }
     }
@@ -1522,7 +1568,7 @@ impl Type {
 
     fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
         let t: PrimitiveType = match *self {
-            ResolvedPath { did, .. } => return Some(did),
+            Type::Path { ref path } => return Some(path.def_id()),
             DynTrait(ref bounds, _) => return Some(bounds[0].trait_.def_id()),
             Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()),
             BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
index 110322112364c15f0668d66a80cf90296de91014..19b309d6a30c8ea10514b5abb950ebd9610d8fae 100644 (file)
@@ -2,8 +2,7 @@
 use crate::clean::blanket_impl::BlanketImplFinder;
 use crate::clean::{
     inline, Clean, Crate, ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item,
-    ItemKind, Lifetime, Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type,
-    TypeBinding, Visibility,
+    ItemKind, Lifetime, Path, PathSegment, Primitive, PrimitiveType, Type, TypeBinding, Visibility,
 };
 use crate::core::DocContext;
 use crate::formats::item_type::ItemType;
@@ -187,7 +186,8 @@ pub(super) fn external_path(
             for &did in prim.impls(tcx).iter().filter(|did| !did.is_local()) {
                 inline::build_impl(cx, None, did, None, ret);
             }
-        } else if let ResolvedPath { did, .. } = *target {
+        } else if let Type::Path { path } = target {
+            let did = path.def_id();
             if !did.is_local() {
                 inline::build_impls(cx, None, did, None, ret);
             }
@@ -360,8 +360,8 @@ fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: &'tcx ty::Const<'tc
         Res::SelfTy(..) if path.segments.len() == 1 => Generic(kw::SelfUpper),
         Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => Generic(path.segments[0].name),
         _ => {
-            let did = register_res(cx, path.res);
-            ResolvedPath { path, did }
+            let _ = register_res(cx, path.res);
+            Type::Path { path }
         }
     }
 }
@@ -393,20 +393,10 @@ fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: &'tcx ty::Const<'tc
     debug!("register_res({:?})", res);
 
     let (did, kind) = match res {
-        Res::Def(DefKind::AssocTy | DefKind::AssocFn | DefKind::AssocConst, i) => {
-            // associated items are documented, but on the page of their parent
-            (cx.tcx.parent(i).unwrap(), ItemType::Trait)
-        }
-        Res::Def(DefKind::Variant, i) => {
-            // variant items are documented, but on the page of their parent
-            (cx.tcx.parent(i).expect("cannot get parent def id"), ItemType::Enum)
-        }
-        // Each of these have their own page.
+        // These should be added to the cache using `record_extern_fqn`.
         Res::Def(
-            kind
-            @
-            (Fn | TyAlias | Enum | Trait | Struct | Union | Mod | ForeignTy | Const | Static
-            | Macro(..) | TraitAlias),
+            kind @ (AssocTy | AssocFn | AssocConst | Variant | Fn | TyAlias | Enum | Trait | Struct
+            | Union | Mod | ForeignTy | Const | Static | Macro(..) | TraitAlias),
             i,
         ) => (i, kind.into()),
         // This is part of a trait definition; document the trait.
index 493aa56fce6efe061a2b12ba673628625ba88731..04bcade156a9d33f8f4fdbb822ec7050a463c694 100644 (file)
@@ -136,9 +136,6 @@ fn try_from(value: &str) -> Result<Self, Self::Error> {
     ///
     /// Be aware: This option can come both from the CLI and from crate attributes!
     crate manual_passes: Vec<String>,
-    /// Whether to display warnings during doc generation or while gathering doctests. By default,
-    /// all non-rustdoc-specific lints are allowed when generating docs.
-    crate display_doctest_warnings: bool,
     /// Whether to run the `calculate-doc-coverage` pass, which counts the number of public items
     /// with and without documentation.
     crate show_coverage: bool,
@@ -197,7 +194,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             .field("persist_doctests", &self.persist_doctests)
             .field("default_passes", &self.default_passes)
             .field("manual_passes", &self.manual_passes)
-            .field("display_doctest_warnings", &self.display_doctest_warnings)
             .field("show_coverage", &self.show_coverage)
             .field("crate_version", &self.crate_version)
             .field("render_options", &self.render_options)
@@ -556,7 +552,7 @@ fn println_condition(condition: Condition) {
                     ))
                     .emit();
                 }
-                themes.push(StylePath { path: theme_file, disabled: true });
+                themes.push(StylePath { path: theme_file });
             }
         }
 
@@ -639,7 +635,6 @@ fn println_condition(condition: Condition) {
         let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
         let playground_url = matches.opt_str("playground-url");
         let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
-        let display_doctest_warnings = matches.opt_present("display-doctest-warnings");
         let sort_modules_alphabetically = !matches.opt_present("sort-modules-by-appearance");
         let resource_suffix = matches.opt_str("resource-suffix").unwrap_or_default();
         let enable_minification = !matches.opt_present("disable-minification");
@@ -707,7 +702,6 @@ fn println_condition(condition: Condition) {
             test_args,
             default_passes,
             manual_passes,
-            display_doctest_warnings,
             show_coverage,
             crate_version,
             test_run_directory,
index de4a3732e736bbcc68b89fadb052d71d375a56f4..56ccdfae1d8bc1bb2b62ff4254decc8aca379051 100644 (file)
@@ -38,9 +38,6 @@
 crate struct TestOptions {
     /// Whether to disable the default `extern crate my_crate;` when creating doctests.
     crate no_crate_inject: bool,
-    /// Whether to emit compilation warnings when compiling doctests. Setting this will suppress
-    /// the default `#![allow(unused)]`.
-    crate display_doctest_warnings: bool,
     /// Additional crate-level attributes to add to doctests.
     crate attrs: Vec<String>,
 }
@@ -65,6 +62,8 @@
         }
     });
 
+    debug!(?lint_opts);
+
     let crate_types =
         if options.proc_macro_crate { vec![CrateType::ProcMacro] } else { vec![CrateType::Rlib] };
 
@@ -72,7 +71,7 @@
         maybe_sysroot: options.maybe_sysroot.clone(),
         search_paths: options.libs.clone(),
         crate_types,
-        lint_opts: if !options.display_doctest_warnings { lint_opts } else { vec![] },
+        lint_opts,
         lint_cap: Some(options.lint_cap.unwrap_or(lint::Forbid)),
         cg: options.codegen_options.clone(),
         externs: options.externs.clone(),
     };
 
     let test_args = options.test_args.clone();
-    let display_doctest_warnings = options.display_doctest_warnings;
     let nocapture = options.nocapture;
     let externs = options.externs.clone();
     let json_unused_externs = options.json_unused_externs;
             let collector = global_ctxt.enter(|tcx| {
                 let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID);
 
-                let mut opts = scrape_test_config(crate_attrs);
-                opts.display_doctest_warnings |= options.display_doctest_warnings;
+                let opts = scrape_test_config(crate_attrs);
                 let enable_per_target_ignores = options.enable_per_target_ignores;
                 let mut collector = Collector::new(
                     tcx.crate_name(LOCAL_CRATE),
         Err(ErrorReported) => return Err(ErrorReported),
     };
 
-    run_tests(test_args, nocapture, display_doctest_warnings, tests);
+    run_tests(test_args, nocapture, tests);
 
     // Collect and warn about unused externs, but only if we've gotten
     // reports for each doctest
     Ok(())
 }
 
-crate fn run_tests(
-    mut test_args: Vec<String>,
-    nocapture: bool,
-    display_doctest_warnings: bool,
-    tests: Vec<test::TestDescAndFn>,
-) {
+crate fn run_tests(mut test_args: Vec<String>, nocapture: bool, tests: Vec<test::TestDescAndFn>) {
     test_args.insert(0, "rustdoctest".to_string());
     if nocapture {
         test_args.push("--nocapture".to_string());
     }
-    test::test_main(
-        &test_args,
-        tests,
-        Some(test::Options::new().display_output(display_doctest_warnings)),
-    );
+    test::test_main(&test_args, tests, None);
 }
 
 // Look for `#![doc(test(no_crate_inject))]`, used by crates in the std facade.
 fn scrape_test_config(attrs: &[ast::Attribute]) -> TestOptions {
     use rustc_ast_pretty::pprust;
 
-    let mut opts =
-        TestOptions { no_crate_inject: false, display_doctest_warnings: false, attrs: Vec::new() };
+    let mut opts = TestOptions { no_crate_inject: false, attrs: Vec::new() };
 
     let test_attrs: Vec<_> = attrs
         .iter()
@@ -510,7 +497,7 @@ fn drop(&mut self) {
     let mut prog = String::new();
     let mut supports_color = false;
 
-    if opts.attrs.is_empty() && !opts.display_doctest_warnings {
+    if opts.attrs.is_empty() {
         // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some
         // lints that are commonly triggered in doctests. The crate-level test attributes are
         // commonly used to make tests fail in case they trigger warnings, so having this there in
index 1851708096564380e3fab75ca8a3c1617e33ae59..099609d0f912e50b10a9c5a418d11ccdc4fa010e 100644 (file)
@@ -52,8 +52,7 @@ fn main() {
 fn make_test_no_crate_inject() {
     // Even if you do use the crate within the test, setting `opts.no_crate_inject` will skip
     // adding it anyway.
-    let opts =
-        TestOptions { no_crate_inject: true, display_doctest_warnings: false, attrs: vec![] };
+    let opts = TestOptions { no_crate_inject: true, attrs: vec![] };
     let input = "use asdf::qwop;
 assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
@@ -215,20 +214,6 @@ fn make_test_dont_insert_main() {
     assert_eq!((output, len), (expected, 1));
 }
 
-#[test]
-fn make_test_display_doctest_warnings() {
-    // If the user is asking to display doctest warnings, suppress the default `allow(unused)`.
-    let mut opts = TestOptions::default();
-    opts.display_doctest_warnings = true;
-    let input = "assert_eq!(2+2, 4);";
-    let expected = "fn main() {
-assert_eq!(2+2, 4);
-}"
-    .to_string();
-    let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None);
-    assert_eq!((output, len), (expected, 1));
-}
-
 #[test]
 fn make_test_issues_21299_33731() {
     let opts = TestOptions::default();
index 82d0002b98b180d2ae514314740d8d6fd714d4a6..8eadbf63f33d91e02cf683b857676049a1e4b90c 100644 (file)
@@ -39,7 +39,10 @@ macro_rules! try_none {
         match $e {
             Some(e) => e,
             None => {
-                return Err(Error::new(io::Error::new(io::ErrorKind::Other, "not found"), $file));
+                return Err(<crate::error::Error as crate::docfs::PathError>::new(
+                    io::Error::new(io::ErrorKind::Other, "not found"),
+                    $file,
+                ));
             }
         }
     }};
index db2b836de86e459b8b318425e5bb952418304094..d3831450e1d87d8122a7ec2319bed199b769bbe4 100644 (file)
@@ -27,7 +27,7 @@
 #[derive(Default)]
 crate struct Cache {
     /// Maps a type ID to all known implementations for that type. This is only
-    /// recognized for intra-crate `ResolvedPath` types, and is used to print
+    /// recognized for intra-crate [`clean::Type::Path`]s, and is used to print
     /// out extra documentation on the page of an enum/struct.
     ///
     /// The values of the map are a list of implementations and documentation
@@ -401,8 +401,8 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
             clean::ImplItem(ref i) => {
                 self.cache.parent_is_trait_impl = i.trait_.is_some();
                 match i.for_ {
-                    clean::ResolvedPath { did, .. } => {
-                        self.cache.parent_stack.push(did);
+                    clean::Type::Path { ref path } => {
+                        self.cache.parent_stack.push(path.def_id());
                         true
                     }
                     clean::DynTrait(ref bounds, _)
@@ -436,9 +436,9 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
             // Note: matching twice to restrict the lifetime of the `i` borrow.
             let mut dids = FxHashSet::default();
             match i.for_ {
-                clean::ResolvedPath { did, .. }
-                | clean::BorrowedRef { type_: box clean::ResolvedPath { did, .. }, .. } => {
-                    dids.insert(did);
+                clean::Type::Path { ref path }
+                | clean::BorrowedRef { type_: box clean::Type::Path { ref path }, .. } => {
+                    dids.insert(path.def_id());
                 }
                 clean::DynTrait(ref bounds, _)
                 | clean::BorrowedRef { type_: box clean::DynTrait(ref bounds, _), .. } => {
index 4f2049132046d8a534a9c8e9069a15d836d5be84..25471dd726d6b346429abd24ab44d3935ea01edb 100644 (file)
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty;
+use rustc_middle::ty::DefIdTree;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::CRATE_DEF_INDEX;
 use rustc_target::spec::abi::Abi;
@@ -502,7 +504,16 @@ fn print<'a, 'tcx: 'a>(
     cx: &Context<'_>,
     root_path: Option<&str>,
 ) -> Result<(String, ItemType, Vec<String>), HrefError> {
-    let cache = &cx.cache();
+    let tcx = cx.tcx();
+    let def_kind = tcx.def_kind(did);
+    let did = match def_kind {
+        DefKind::AssocTy | DefKind::AssocFn | DefKind::AssocConst | DefKind::Variant => {
+            // documented on their parent's page
+            tcx.parent(did).unwrap()
+        }
+        _ => did,
+    };
+    let cache = cx.cache();
     let relative_to = &cx.current;
     fn to_module_fqp(shortty: ItemType, fqp: &[String]) -> &[String] {
         if shortty == ItemType::Module { fqp } else { &fqp[..fqp.len() - 1] }
@@ -596,8 +607,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.
+/// Used to render a [`clean::Path`].
 fn resolved_path<'cx>(
     w: &mut fmt::Formatter<'_>,
     did: DefId,
@@ -751,8 +761,9 @@ fn fmt_type<'cx>(
 
     match *t {
         clean::Generic(name) => write!(f, "{}", name),
-        clean::ResolvedPath { did, ref path } => {
+        clean::Type::Path { ref path } => {
             // Paths like `T::Output` and `Self::Output` should be rendered with all segments.
+            let did = path.def_id();
             resolved_path(f, did, path, path.is_assoc_ty(), use_absolute, cx)
         }
         clean::DynTrait(ref bounds, ref lt) => {
@@ -1166,6 +1177,10 @@ fn inner_full_print(
                     args.push_str(" <br>");
                     args_plain.push(' ');
                 }
+                if input.is_const {
+                    args.push_str("const ");
+                    args_plain.push_str("const ");
+                }
                 if !input.name.is_empty() {
                     args.push_str(&format!("{}: ", input.name));
                     args_plain.push_str(&format!("{}: ", input.name));
@@ -1338,10 +1353,7 @@ fn print_with_space(&self) -> &str {
     }
 }
 
-crate fn print_constness_with_space(
-    c: &hir::Constness,
-    s: Option<&ConstStability>,
-) -> &'static str {
+crate fn print_constness_with_space(c: &hir::Constness, s: Option<ConstStability>) -> &'static str {
     match (c, s) {
         // const stable or when feature(staged_api) is not set
         (
index e177a11303643d645ef0a9aac29cfaff9bc54047..688860f94e183694215564553200c9c3c82f6e1d 100644 (file)
@@ -632,7 +632,7 @@ fn advance(
                 },
                 Some(c) => c,
             },
-            TokenKind::RawIdent | TokenKind::UnknownPrefix => {
+            TokenKind::RawIdent | TokenKind::UnknownPrefix | TokenKind::InvalidIdent => {
                 Class::Ident(self.new_span(before, text))
             }
             TokenKind::Lifetime { .. } => Class::Lifetime,
index 71d7cc1a09dce5b9656d6e3c9556b5db38fd6776..3d3fa3aaeaa519f803fac82b7377d1fb6fa030d5 100644 (file)
@@ -2,8 +2,8 @@
 
 use rustc_data_structures::fx::FxHashMap;
 
+use crate::error::Error;
 use crate::externalfiles::ExternalHtml;
-use crate::html::escape::Escape;
 use crate::html::format::{Buffer, Print};
 use crate::html::render::{ensure_trailing_slash, StylePath};
 
@@ -50,10 +50,11 @@ struct PageLayout<'a> {
     static_root_path: &'a str,
     page: &'a Page<'a>,
     layout: &'a Layout,
-    style_files: String,
+    themes: Vec<String>,
     sidebar: String,
     content: String,
     krate_with_trailing_slash: String,
+    crate rustdoc_version: &'a str,
 }
 
 crate fn render<T: Print, S: Print>(
@@ -66,29 +67,24 @@ struct PageLayout<'a> {
 ) -> String {
     let static_root_path = page.get_static_root_path();
     let krate_with_trailing_slash = ensure_trailing_slash(&layout.krate).to_string();
-    let style_files = style_files
+    let mut themes: Vec<String> = style_files
         .iter()
-        .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" {} {}>"#,
-                Escape(&format!("{}{}{}", static_root_path, t.0, page.resource_suffix)),
-                if t.1 { "disabled" } else { "" },
-                if t.0 == "light" { "id=\"themeStyle\"" } else { "" }
-            )
-        })
-        .collect::<String>();
+        .map(StylePath::basename)
+        .collect::<Result<_, Error>>()
+        .unwrap_or_default();
+    themes.sort();
+    let rustdoc_version = rustc_interface::util::version_str().unwrap_or("unknown version");
     let content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar.
     let sidebar = Buffer::html().to_display(sidebar);
     let teractx = tera::Context::from_serialize(PageLayout {
         static_root_path,
         page,
         layout,
-        style_files,
+        themes,
         sidebar,
         content,
         krate_with_trailing_slash,
+        rustdoc_version,
     })
     .unwrap();
     templates.render("page.html", &teractx).unwrap()
index 9aa69d94215ded7281c96f0fb1a33c3dbade33eb..d12667c9e5c777c205c8f690ab4c212450fc5754 100644 (file)
@@ -218,7 +218,7 @@ fn get_index_type(clean_type: &clean::Type, generics: Vec<TypeWithKind>) -> Rend
 
 fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option<Symbol> {
     match *clean_type {
-        clean::ResolvedPath { ref path, .. } => {
+        clean::Type::Path { ref path, .. } => {
             let path_segment = path.segments.last().unwrap();
             Some(path_segment.name)
         }
@@ -371,7 +371,7 @@ fn insert_ty(
             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 ty = Type::Path { path };
                     get_real_types(generics, &ty, tcx, recurse + 1, &mut ty_generics, cache);
                 }
             }
index 069862efde6409a0a49891cd32263b08b836a5c7..365d959ad9f3b3dd962f4e962e1062f8a473559b 100644 (file)
@@ -504,9 +504,9 @@ fn init(
         // by the browser as the theme stylesheet. The theme system (hackily) works by
         // changing the href to this stylesheet. All other themes are disabled to
         // prevent rule conflicts
-        scx.style_files.push(StylePath { path: PathBuf::from("light.css"), disabled: false });
-        scx.style_files.push(StylePath { path: PathBuf::from("dark.css"), disabled: true });
-        scx.style_files.push(StylePath { path: PathBuf::from("ayu.css"), disabled: true });
+        scx.style_files.push(StylePath { path: PathBuf::from("light.css") });
+        scx.style_files.push(StylePath { path: PathBuf::from("dark.css") });
+        scx.style_files.push(StylePath { path: PathBuf::from("ayu.css") });
 
         let dst = output;
         scx.ensure_dir(&dst)?;
@@ -596,9 +596,13 @@ fn after_krate(&mut self) -> Result<(), Error> {
         page.description = "Settings of Rustdoc";
         page.root_path = "./";
 
-        let mut style_files = self.shared.style_files.clone();
         let sidebar = "<h2 class=\"location\">Settings</h2><div class=\"sidebar-elems\"></div>";
-        style_files.push(StylePath { path: PathBuf::from("settings.css"), disabled: false });
+        let theme_names: Vec<String> = self
+            .shared
+            .style_files
+            .iter()
+            .map(StylePath::basename)
+            .collect::<Result<_, Error>>()?;
         let v = layout::render(
             &self.shared.templates,
             &self.shared.layout,
@@ -607,9 +611,9 @@ fn after_krate(&mut self) -> Result<(), Error> {
             settings(
                 self.shared.static_root_path.as_deref().unwrap_or("./"),
                 &self.shared.resource_suffix,
-                &self.shared.style_files,
+                theme_names,
             )?,
-            &style_files,
+            &self.shared.style_files,
         );
         self.shared.fs.write(settings_file, v)?;
         if let Some(ref redirections) = self.shared.redirections {
index 24baca285c6ff2fce8e5d3b7a630882f5f83a0ab..166e084012724e18999eb920770880617556c5ad 100644 (file)
@@ -64,7 +64,6 @@
 use serde::{Serialize, Serializer};
 
 use crate::clean::{self, ItemId, RenderedLink, SelfTy};
-use crate::docfs::PathError;
 use crate::error::Error;
 use crate::formats::cache::Cache;
 use crate::formats::item_type::ItemType;
@@ -173,8 +172,12 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
 crate struct StylePath {
     /// The path to the theme
     crate path: PathBuf,
-    /// What the `disabled` attribute should be set to in the HTML tag
-    crate disabled: bool,
+}
+
+impl StylePath {
+    pub fn basename(&self) -> Result<String, Error> {
+        Ok(try_none!(try_none!(self.path.file_stem(), &self.path).to_str(), &self.path).to_string())
+    }
 }
 
 fn write_srclink(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer) {
@@ -353,7 +356,7 @@ enum Setting {
         js_data_name: &'static str,
         description: &'static str,
         default_value: &'static str,
-        options: Vec<(String, String)>,
+        options: Vec<String>,
     },
 }
 
@@ -393,10 +396,9 @@ fn display(&self, root_path: &str, suffix: &str) -> String {
                 options
                     .iter()
                     .map(|opt| format!(
-                        "<option value=\"{}\" {}>{}</option>",
-                        opt.0,
-                        if opt.0 == default_value { "selected" } else { "" },
-                        opt.1,
+                        "<option value=\"{name}\" {}>{name}</option>",
+                        if opt == default_value { "selected" } else { "" },
+                        name = opt,
                     ))
                     .collect::<String>(),
                 root_path,
@@ -421,18 +423,7 @@ fn from(values: (&'static str, Vec<T>)) -> Setting {
     }
 }
 
-fn settings(root_path: &str, suffix: &str, themes: &[StylePath]) -> Result<String, Error> {
-    let theme_names: Vec<(String, String)> = themes
-        .iter()
-        .map(|entry| {
-            let theme =
-                try_none!(try_none!(entry.path.file_stem(), &entry.path).to_str(), &entry.path)
-                    .to_string();
-
-            Ok((theme.clone(), theme))
-        })
-        .collect::<Result<_, Error>>()?;
-
+fn settings(root_path: &str, suffix: &str, theme_names: Vec<String>) -> Result<String, Error> {
     // (id, explanation, default value)
     let settings: &[Setting] = &[
         (
@@ -469,10 +460,11 @@ fn settings(root_path: &str, suffix: &str, themes: &[StylePath]) -> Result<Strin
             <span class=\"in-band\">Rustdoc settings</span>\
         </h1>\
         <div class=\"settings\">{}</div>\
-        <script src=\"{}settings{}.js\"></script>",
+        <link rel=\"stylesheet\" href=\"{root_path}settings{suffix}.css\">\
+        <script src=\"{root_path}settings{suffix}.js\"></script>",
         settings.iter().map(|s| s.display(root_path, suffix)).collect::<String>(),
-        root_path,
-        suffix
+        root_path = root_path,
+        suffix = suffix
     ))
 }
 
@@ -812,17 +804,17 @@ fn assoc_type(
 
 fn render_stability_since_raw(
     w: &mut Buffer,
-    ver: Option<&str>,
-    const_stability: Option<&ConstStability>,
-    containing_ver: Option<&str>,
-    containing_const_ver: Option<&str>,
+    ver: Option<Symbol>,
+    const_stability: Option<ConstStability>,
+    containing_ver: Option<Symbol>,
+    containing_const_ver: Option<Symbol>,
 ) {
     let ver = ver.filter(|inner| !inner.is_empty());
 
     match (ver, const_stability) {
         // stable and const stable
         (Some(v), Some(ConstStability { level: StabilityLevel::Stable { since }, .. }))
-            if Some(since.as_str()).as_deref() != containing_const_ver =>
+            if Some(since) != containing_const_ver =>
         {
             write!(
                 w,
@@ -869,6 +861,7 @@ fn render_assoc_item(
     link: AssocItemLink<'_>,
     parent: ItemType,
     cx: &Context<'_>,
+    render_mode: RenderMode,
 ) {
     fn method(
         w: &mut Buffer,
@@ -879,6 +872,7 @@ fn method(
         link: AssocItemLink<'_>,
         parent: ItemType,
         cx: &Context<'_>,
+        render_mode: RenderMode,
     ) {
         let name = meth.name.as_ref().unwrap();
         let href = match link {
@@ -901,8 +895,14 @@ fn method(
             }
         };
         let vis = meth.visibility.print_with_space(meth.def_id, cx).to_string();
-        let constness =
-            print_constness_with_space(&header.constness, meth.const_stability(cx.tcx()));
+        // FIXME: Once https://github.com/rust-lang/rust/issues/67792 is implemented, we can remove
+        // this condition.
+        let constness = match render_mode {
+            RenderMode::Normal => {
+                print_constness_with_space(&header.constness, meth.const_stability(cx.tcx()))
+            }
+            RenderMode::ForDeref { .. } => "",
+        };
         let asyncness = header.asyncness.print_with_space();
         let unsafety = header.unsafety.print_with_space();
         let defaultness = print_default_space(meth.is_default());
@@ -953,10 +953,10 @@ fn method(
     match *item.kind {
         clean::StrippedItem(..) => {}
         clean::TyMethodItem(ref m) => {
-            method(w, item, m.header, &m.generics, &m.decl, link, parent, cx)
+            method(w, item, m.header, &m.generics, &m.decl, link, parent, cx, render_mode)
         }
         clean::MethodItem(ref m, _) => {
-            method(w, item, m.header, &m.generics, &m.decl, link, parent, cx)
+            method(w, item, m.header, &m.generics, &m.decl, link, parent, cx, render_mode)
         }
         clean::AssocConstItem(ref ty, ref default) => assoc_const(
             w,
@@ -1227,8 +1227,8 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) ->
             | SelfTy::SelfExplicit(clean::BorrowedRef { mutability, .. }) => {
                 (mutability == Mutability::Mut, false, false)
             }
-            SelfTy::SelfExplicit(clean::ResolvedPath { did, .. }) => {
-                (false, Some(did) == tcx.lang_items().owned_box(), false)
+            SelfTy::SelfExplicit(clean::Type::Path { path }) => {
+                (false, Some(path.def_id()) == tcx.lang_items().owned_box(), false)
             }
             SelfTy::SelfValue => (false, false, true),
             _ => (false, false, false),
@@ -1243,10 +1243,17 @@ 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.as_return().and_then(|t| t.def_id(cx.cache())) {
+    if let Some((did, ty)) = decl.output.as_return().and_then(|t| Some((t.def_id(cx.cache())?, t)))
+    {
         if let Some(impls) = cx.cache().impls.get(&did) {
             for i in impls {
                 let impl_ = i.inner_impl();
+                if !impl_.for_.without_borrowed_ref().is_same(ty.without_borrowed_ref(), cx.cache())
+                {
+                    // Two different types might have the same did,
+                    // without actually being the same.
+                    continue;
+                }
                 if let Some(trait_) = &impl_.trait_ {
                     let trait_did = trait_.def_id();
 
@@ -1423,7 +1430,7 @@ fn doc_impl_item(
                         "<div id=\"{}\" class=\"{}{} has-srclink\">",
                         id, item_type, in_trait_class,
                     );
-                    render_rightside(w, cx, item, containing_item);
+                    render_rightside(w, cx, item, containing_item, render_mode);
                     write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
                     w.write_str("<h4 class=\"code-header\">");
                     render_assoc_item(
@@ -1432,6 +1439,7 @@ fn doc_impl_item(
                         link.anchor(source_id.as_ref().unwrap_or(&id)),
                         ItemType::Impl,
                         cx,
+                        render_mode,
                     );
                     w.write_str("</h4>");
                     w.write_str("</div>");
@@ -1467,7 +1475,7 @@ fn doc_impl_item(
                     "<div id=\"{}\" class=\"{}{} has-srclink\">",
                     id, item_type, in_trait_class
                 );
-                render_rightside(w, cx, item, containing_item);
+                render_rightside(w, cx, item, containing_item, render_mode);
                 write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
                 w.write_str("<h4 class=\"code-header\">");
                 assoc_const(
@@ -1646,16 +1654,24 @@ fn render_rightside(
     cx: &Context<'_>,
     item: &clean::Item,
     containing_item: &clean::Item,
+    render_mode: RenderMode,
 ) {
     let tcx = cx.tcx();
 
+    // FIXME: Once https://github.com/rust-lang/rust/issues/67792 is implemented, we can remove
+    // this condition.
+    let (const_stability, const_stable_since) = match render_mode {
+        RenderMode::Normal => (item.const_stability(tcx), containing_item.const_stable_since(tcx)),
+        RenderMode::ForDeref { .. } => (None, None),
+    };
+
     write!(w, "<div class=\"rightside\">");
     render_stability_since_raw(
         w,
-        item.stable_since(tcx).as_deref(),
-        item.const_stability(tcx),
-        containing_item.stable_since(tcx).as_deref(),
-        containing_item.const_stable_since(tcx).as_deref(),
+        item.stable_since(tcx),
+        const_stability,
+        containing_item.stable_since(tcx),
+        const_stable_since,
     );
 
     write_srclink(cx, item, w);
@@ -1691,7 +1707,7 @@ pub(crate) fn render_impl_summary(
         format!(" data-aliases=\"{}\"", aliases.join(","))
     };
     write!(w, "<div id=\"{}\" class=\"impl has-srclink\"{}>", id, aliases);
-    render_rightside(w, cx, &i.impl_item, containing_item);
+    render_rightside(w, cx, &i.impl_item, containing_item, RenderMode::Normal);
     write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
     write!(w, "<h3 class=\"code-header in-band\">");
 
@@ -2520,7 +2536,7 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> {
         }
 
         match ty {
-            clean::Type::ResolvedPath { did, .. } => process_path(did),
+            clean::Type::Path { path } => process_path(path.def_id()),
             clean::Type::Tuple(tys) => {
                 work.extend(tys.into_iter());
             }
index 049d17a4b477af36e53639465ab24202beebbd9e..e139ac8581e7235334ff875cf04c262d769df095 100644 (file)
@@ -101,7 +101,7 @@ pub(super) fn print_item(
     let mut stability_since_raw = Buffer::new();
     render_stability_since_raw(
         &mut stability_since_raw,
-        item.stable_since(cx.tcx()).as_deref(),
+        item.stable_since(cx.tcx()),
         item.const_stability(cx.tcx()),
         None,
         None,
@@ -556,7 +556,14 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
                     );
                 }
                 for t in &types {
-                    render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait, cx);
+                    render_assoc_item(
+                        w,
+                        t,
+                        AssocItemLink::Anchor(None),
+                        ItemType::Trait,
+                        cx,
+                        RenderMode::Normal,
+                    );
                     w.write_str(";\n");
                 }
                 // If there are too many associated constants, hide everything after them
@@ -580,7 +587,14 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
                     w.write_str("\n");
                 }
                 for t in &consts {
-                    render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait, cx);
+                    render_assoc_item(
+                        w,
+                        t,
+                        AssocItemLink::Anchor(None),
+                        ItemType::Trait,
+                        cx,
+                        RenderMode::Normal,
+                    );
                     w.write_str(";\n");
                 }
                 if !toggle && should_hide_fields(count_methods) {
@@ -591,7 +605,14 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
                     w.write_str("\n");
                 }
                 for (pos, m) in required.iter().enumerate() {
-                    render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait, cx);
+                    render_assoc_item(
+                        w,
+                        m,
+                        AssocItemLink::Anchor(None),
+                        ItemType::Trait,
+                        cx,
+                        RenderMode::Normal,
+                    );
                     w.write_str(";\n");
 
                     if pos < required.len() - 1 {
@@ -602,7 +623,14 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
                     w.write_str("\n");
                 }
                 for (pos, m) in provided.iter().enumerate() {
-                    render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait, cx);
+                    render_assoc_item(
+                        w,
+                        m,
+                        AssocItemLink::Anchor(None),
+                        ItemType::Trait,
+                        cx,
+                        RenderMode::Normal,
+                    );
                     match *m.kind {
                         clean::MethodItem(ref inner, _)
                             if !inner.generics.where_predicates.is_empty() =>
@@ -655,7 +683,14 @@ fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item
         write_srclink(cx, m, w);
         write!(w, "</div>");
         write!(w, "<h4 class=\"code-header\">");
-        render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl, cx);
+        render_assoc_item(
+            w,
+            m,
+            AssocItemLink::Anchor(Some(&id)),
+            ItemType::Impl,
+            cx,
+            RenderMode::Normal,
+        );
         w.write_str("</h4>");
         w.write_str("</div>");
         if toggled {
@@ -727,10 +762,11 @@ fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item
         let mut implementor_dups: FxHashMap<Symbol, (DefId, bool)> = FxHashMap::default();
         for implementor in implementors {
             match implementor.inner_impl().for_ {
-                clean::ResolvedPath { ref path, did, .. }
-                | clean::BorrowedRef {
-                    type_: box clean::ResolvedPath { ref path, did, .. }, ..
-                } if !path.is_assoc_ty() => {
+                clean::Type::Path { ref path }
+                | clean::BorrowedRef { type_: box clean::Type::Path { ref path }, .. }
+                    if !path.is_assoc_ty() =>
+                {
+                    let did = path.def_id();
                     let &mut (prev_did, ref mut has_duplicates) =
                         implementor_dups.entry(path.last()).or_insert((did, false));
                     if prev_did != did {
@@ -1426,10 +1462,10 @@ fn render_stability_since(
 ) {
     render_stability_since_raw(
         w,
-        item.stable_since(tcx).as_deref(),
+        item.stable_since(tcx),
         item.const_stability(tcx),
-        containing_item.stable_since(tcx).as_deref(),
-        containing_item.const_stable_since(tcx).as_deref(),
+        containing_item.stable_since(tcx),
+        containing_item.const_stable_since(tcx),
     )
 }
 
@@ -1452,8 +1488,8 @@ fn render_implementor(
     // If there's already another implementor that has the same abridged name, use the
     // full path, for example in `std::iter::ExactSizeIterator`
     let use_absolute = match implementor.inner_impl().for_ {
-        clean::ResolvedPath { ref path, .. }
-        | clean::BorrowedRef { type_: box clean::ResolvedPath { ref path, .. }, .. }
+        clean::Type::Path { ref path, .. }
+        | clean::BorrowedRef { type_: box clean::Type::Path { ref path, .. }, .. }
             if !path.is_assoc_ty() =>
         {
             implementor_dups[&path.last()].1
@@ -1768,6 +1804,13 @@ fn write_size_of_layout(w: &mut Buffer, layout: &Layout, tag_size: u64) {
                  the type was too big.</p>"
             );
         }
+        Err(LayoutError::NormalizationFailure(_, _)) => {
+            writeln!(
+                w,
+                "<p><strong>Note:</strong> Encountered an error during type layout; \
+                the type failed to be normalized.</p>"
+            )
+        }
     }
 
     writeln!(w, "</div>");
index 2d3b2490677e9b3e029cbad752a3a58368f6a965..0d5ba8e80d2429464ca2a1e842b8cc38de524558 100644 (file)
@@ -181,42 +181,34 @@ fn write_minify(
         cx.write_shared(SharedResource::InvocationSpecific { basename: p }, content, &options.emit)
     };
 
-    fn add_background_image_to_css(
-        cx: &Context<'_>,
-        css: &mut String,
-        rule: &str,
-        file: &'static str,
-    ) {
-        css.push_str(&format!(
-            "{} {{ background-image: url({}); }}",
-            rule,
-            SharedResource::ToolchainSpecific { basename: file }
+    // Given "foo.svg", return e.g. "url(\"foo1.58.0.svg\")"
+    fn ver_url(cx: &Context<'_>, basename: &'static str) -> String {
+        format!(
+            "url(\"{}\")",
+            SharedResource::ToolchainSpecific { basename }
                 .path(cx)
                 .file_name()
                 .unwrap()
                 .to_str()
                 .unwrap()
-        ))
+        )
     }
 
-    // Add all the static files. These may already exist, but we just
-    // overwrite them anyway to make sure that they're fresh and up-to-date.
-    let mut rustdoc_css = static_files::RUSTDOC_CSS.to_owned();
-    add_background_image_to_css(
-        cx,
-        &mut rustdoc_css,
-        "details.undocumented[open] > summary::before, \
-         details.rustdoc-toggle[open] > summary::before, \
-         details.rustdoc-toggle[open] > summary.hideme::before",
-        "toggle-minus.svg",
-    );
-    add_background_image_to_css(
+    // We use the AUTOREPLACE mechanism to inject into our static JS and CSS certain
+    // values that are only known at doc build time. Since this mechanism is somewhat
+    // surprising when reading the code, please limit it to rustdoc.css.
+    write_minify(
+        "rustdoc.css",
+        static_files::RUSTDOC_CSS
+            .replace(
+                "/* AUTOREPLACE: */url(\"toggle-minus.svg\")",
+                &ver_url(cx, "toggle-minus.svg"),
+            )
+            .replace("/* AUTOREPLACE: */url(\"toggle-plus.svg\")", &ver_url(cx, "toggle-plus.svg"))
+            .replace("/* AUTOREPLACE: */url(\"down-arrow.svg\")", &ver_url(cx, "down-arrow.svg")),
         cx,
-        &mut rustdoc_css,
-        "details.undocumented > summary::before, details.rustdoc-toggle > summary::before",
-        "toggle-plus.svg",
-    );
-    write_minify("rustdoc.css", rustdoc_css, cx, options)?;
+        options,
+    )?;
 
     // Add all the static files. These may already exist, but we just
     // overwrite them anyway to make sure that they're fresh and up-to-date.
@@ -228,12 +220,12 @@ fn add_background_image_to_css(
     let mut themes: FxHashSet<String> = FxHashSet::default();
 
     for entry in &cx.shared.style_files {
-        let theme = try_none!(try_none!(entry.path.file_stem(), &entry.path).to_str(), &entry.path);
+        let theme = entry.basename()?;
         let extension =
             try_none!(try_none!(entry.path.extension(), &entry.path).to_str(), &entry.path);
 
         // Handle the official themes
-        match theme {
+        match theme.as_str() {
             "light" => write_minify("light.css", static_files::themes::LIGHT, cx, options)?,
             "dark" => write_minify("dark.css", static_files::themes::DARK, cx, options)?,
             "ayu" => write_minify("ayu.css", static_files::themes::AYU, cx, options)?,
@@ -265,26 +257,7 @@ fn add_background_image_to_css(
     let mut themes: Vec<&String> = themes.iter().collect();
     themes.sort();
 
-    // FIXME: this should probably not be a toolchain file since it depends on `--theme`.
-    // But it seems a shame to copy it over and over when it's almost always the same.
-    // Maybe we can change the representation to move this out of main.js?
-    write_minify(
-        "main.js",
-        static_files::MAIN_JS
-            .replace(
-                "/* INSERT THEMES HERE */",
-                &format!(" = {}", serde_json::to_string(&themes).unwrap()),
-            )
-            .replace(
-                "/* INSERT RUSTDOC_VERSION HERE */",
-                &format!(
-                    "rustdoc {}",
-                    rustc_interface::util::version_str().unwrap_or("unknown version")
-                ),
-            ),
-        cx,
-        options,
-    )?;
+    write_minify("main.js", static_files::MAIN_JS, cx, options)?;
     write_minify("search.js", static_files::SEARCH_JS, cx, options)?;
     write_minify("settings.js", static_files::SETTINGS_JS, cx, options)?;
 
@@ -292,18 +265,7 @@ fn add_background_image_to_css(
         write_minify("source-script.js", static_files::sidebar::SOURCE_SCRIPT, cx, options)?;
     }
 
-    {
-        write_minify(
-            "storage.js",
-            format!(
-                "var resourcesSuffix = \"{}\";{}",
-                cx.shared.resource_suffix,
-                static_files::STORAGE_JS
-            ),
-            cx,
-            options,
-        )?;
-    }
+    write_minify("storage.js", static_files::STORAGE_JS, cx, options)?;
 
     if cx.shared.layout.scrape_examples_extension {
         cx.write_minify(
index 0f3eb2ca07d23522c8da5126bec8661602ec74af..fceb508bc4ff5e41461d6398fc073ecb126fd93a 100644 (file)
@@ -305,6 +305,10 @@ nav.sub {
        overflow-y: scroll;
 }
 
+.rustdoc.source .sidebar {
+       overflow-y: auto;
+}
+
 /* Improve the scrollbar display on firefox */
 * {
        scrollbar-width: initial;
@@ -824,6 +828,7 @@ h2.small-section-header > .anchor {
        background-color: transparent;
        background-size: 20px;
        background-position: calc(100% - 1px) 56%;
+       background-image: /* AUTOREPLACE: */url("down-arrow.svg");
 }
 .search-container > .top-button {
        position: absolute;
@@ -1125,15 +1130,17 @@ h3.variant {
        margin-top: 3px;
 }
 
-.docblock > .section-header:first-child {
+.top-doc .docblock > .section-header:first-child {
        margin-left: 15px;
-       margin-top: 0;
 }
-
-.docblock > .section-header:first-child:hover > a:before {
+.top-doc .docblock > .section-header:first-child:hover > a:before {
        left: -10px;
 }
 
+.docblock > .section-header:first-child {
+       margin-top: 0;
+}
+
 :target > code, :target > .code-header {
        opacity: 1;
 }
@@ -1604,6 +1611,16 @@ details.rustdoc-toggle[open] > summary.hideme > span {
        display: none;
 }
 
+details.undocumented[open] > summary::before,
+details.rustdoc-toggle[open] > summary::before,
+details.rustdoc-toggle[open] > summary.hideme::before {
+       background-image: /* AUTOREPLACE: */url("toggle-minus.svg");
+}
+
+details.undocumented > summary::before, details.rustdoc-toggle > summary::before {
+       background-image: /* AUTOREPLACE: */url("toggle-plus.svg");
+}
+
 details.rustdoc-toggle[open] > summary::before,
 details.rustdoc-toggle[open] > summary.hideme::before {
        width: 17px;
index c9fa72cbaab01bfc8c9d514c8c677d3467402fde..5661d4973342f034c207b2b9beb725b934fdd80e 100644 (file)
@@ -37,14 +37,29 @@ if (!DOMTokenList.prototype.remove) {
     };
 }
 
-(function () {
-    var rustdocVars = document.getElementById("rustdoc-vars");
-    if (rustdocVars) {
-        window.rootPath = rustdocVars.attributes["data-root-path"].value;
-        window.currentCrate = rustdocVars.attributes["data-current-crate"].value;
-        window.searchJS = rustdocVars.attributes["data-search-js"].value;
-        window.searchIndexJS = rustdocVars.attributes["data-search-index-js"].value;
+// Get a value from the rustdoc-vars div, which is used to convey data from
+// Rust to the JS. If there is no such element, return null.
+function getVar(name) {
+    var el = document.getElementById("rustdoc-vars");
+    if (el) {
+        return el.attributes["data-" + name].value;
+    } else {
+        return null;
     }
+}
+
+// Given a basename (e.g. "storage") and an extension (e.g. ".js"), return a URL
+// for a resource under the root-path, with the resource-suffix.
+function resourcePath(basename, extension) {
+    return getVar("root-path") + basename + getVar("resource-suffix") + extension;
+}
+
+
+(function () {
+    window.rootPath = getVar("root-path");
+    window.currentCrate = getVar("current-crate");
+    window.searchJS =  resourcePath("search", ".js");
+    window.searchIndexJS = resourcePath("search-index", ".js");
     var sidebarVars = document.getElementById("sidebar-vars");
     if (sidebarVars) {
         window.sidebarCurrent = {
@@ -115,7 +130,7 @@ function hideThemeButtonState() {
 (function () {
     var themeChoices = getThemesElement();
     var themePicker = getThemePickerElement();
-    var availableThemes/* INSERT THEMES HERE */;
+    var availableThemes = getVar("themes").split(",");
 
     function switchThemeButtonState() {
         if (themeChoices.style.display === "block") {
@@ -980,7 +995,7 @@ function hideThemeButtonState() {
         var rustdoc_version = document.createElement("span");
         rustdoc_version.className = "bottom";
         var rustdoc_version_code = document.createElement("code");
-        rustdoc_version_code.innerText = "/* INSERT RUSTDOC_VERSION HERE */";
+        rustdoc_version_code.innerText = "rustdoc " + getVar("rustdoc-version");
         rustdoc_version.appendChild(rustdoc_version_code);
 
         container.appendChild(rustdoc_version);
index 78ed17e6899e9aa17c0d526b7f93ba64cf3d51a2..606c237aea7d01bd5d5c728720043d0f3285d33c 100644 (file)
@@ -1,5 +1,3 @@
-// From rust:
-/* global resourcesSuffix */
 var darkThemes = ["dark", "ayu"];
 window.currentTheme = document.getElementById("themeStyle");
 window.mainTheme = document.getElementById("mainThemeStyle");
@@ -107,9 +105,8 @@ function getCurrentValue(name) {
 }
 
 function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) {
-    var fullBasicCss = "rustdoc" + resourcesSuffix + ".css";
-    var fullNewTheme = newTheme + resourcesSuffix + ".css";
-    var newHref = mainStyleElem.href.replace(fullBasicCss, fullNewTheme);
+    var newHref = mainStyleElem.href.replace(
+        /\/rustdoc([^/]*)\.css/, "/" + newTheme + "$1" + ".css");
 
     // If this new value comes from a system setting or from the previously
     // saved theme, no need to save it.
index cf57d4cf3aa43929ef937bfe1d9c7801af699e56..c07851da18ac1238c308a50d876ea5a9f86a160a 100644 (file)
@@ -7,12 +7,27 @@
     <meta name="description" content="{{page.description}}"> {#- -#}
     <meta name="keywords" content="{{page.keywords}}"> {#- -#}
     <title>{{page.title}}</title> {#- -#}
+    <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path | safe}}SourceSerif4-Regular.ttf.woff2"> {#- -#}
+    <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path | safe}}FiraSans-Regular.woff2"> {#- -#}
+    <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path | safe}}FiraSans-Medium.woff2"> {#- -#}
+    <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path | safe}}SourceCodePro-Regular.ttf.woff2"> {#- -#}
+    <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path | safe}}SourceSerif4-Bold.ttf.woff2"> {#- -#}
+    <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path | safe}}SourceCodePro-Semibold.ttf.woff2"> {#- -#}
     <link rel="stylesheet" type="text/css" {# -#}
           href="{{static_root_path | safe}}normalize{{page.resource_suffix}}.css"> {#- -#}
     <link rel="stylesheet" type="text/css" {# -#}
           href="{{static_root_path | safe}}rustdoc{{page.resource_suffix}}.css" {# -#}
           id="mainThemeStyle"> {#- -#}
-    {{- style_files | safe -}}
+    {%- for theme in themes -%}
+        <link rel="stylesheet" type="text/css" {# -#}
+            href="{{static_root_path | safe}}{{theme}}{{page.resource_suffix}}.css" {#- -#}
+        {%- if theme == "light" -%}
+            id="themeStyle"
+        {%- else -%}
+            disabled
+        {%- endif -%}
+        >
+    {%- endfor -%}
     <script id="default-settings" {# -#}
       {% for k, v in layout.default_settings %}
         data-{{k}}="{{v}}"
             href="{{static_root_path | safe}}favicon{{page.resource_suffix}}.svg"> {#- -#}
     {%- endif -%}
     {{- layout.external_html.in_header | safe -}}
-    <style type="text/css"> {#- -#}
-    #crate-search{ {#- -#}
-        background-image:url("{{static_root_path | safe}}down-arrow{{page.resource_suffix}}.svg"); {#- -#}
-    } {#- -#}
-    </style> {#- -#}
 </head> {#- -#}
 <body class="rustdoc {{page.css_class}}"> {#- -#}
     <!--[if lte IE 11]> {#- -#}
     <div id="rustdoc-vars" {# -#}
          data-root-path="{{page.root_path | safe}}" {# -#}
          data-current-crate="{{layout.krate}}" {# -#}
-         data-search-index-js="{{page.root_path | safe}}search-index{{page.resource_suffix}}.js" {# -#}
-         data-search-js="{{static_root_path | safe}}search{{page.resource_suffix}}.js"> {#- -#}
+         data-themes="{{themes | join(sep=",") }}" {# -#}
+         data-resource-suffix="{{page.resource_suffix}}" {# -#}
+         data-rustdoc-version="{{rustdoc_version}}" {# -#}
+    > {#- -#}
     </div>
 </body> {#- -#}
 </html> {#- -#}
index a46518ef489aa1b3bc1a53d38ad358800826b1ce..7fc295747f41a5657419d11707034609dee05f1f 100644 (file)
@@ -365,8 +365,7 @@ fn from_tcx(bound: clean::GenericBound, tcx: TyCtxt<'_>) -> Self {
         match bound {
             TraitBound(clean::PolyTrait { trait_, generic_params }, modifier) => {
                 // FIXME: should `trait_` be a clean::Path equivalent in JSON?
-                let trait_ =
-                    clean::ResolvedPath { did: trait_.def_id(), path: trait_ }.into_tcx(tcx);
+                let trait_ = clean::Type::Path { path: trait_ }.into_tcx(tcx);
                 GenericBound::TraitBound {
                     trait_,
                     generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(),
@@ -389,11 +388,15 @@ fn from_tcx(bound: clean::GenericBound, tcx: TyCtxt<'_>) -> Self {
 
 impl FromWithTcx<clean::Type> for Type {
     fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
-        use clean::Type::*;
+        use clean::Type::{
+            Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive,
+            QPath, RawPointer, Slice, Tuple,
+        };
+
         match ty {
-            ResolvedPath { path, did } => Type::ResolvedPath {
+            clean::Type::Path { path } => Type::ResolvedPath {
                 name: path.whole_name(),
-                id: from_item_id(did.into()),
+                id: from_item_id(path.def_id().into()),
                 args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))),
                 param_names: Vec::new(),
             },
@@ -436,7 +439,7 @@ fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
             },
             QPath { name, self_type, trait_, .. } => {
                 // FIXME: should `trait_` be a clean::Path equivalent in JSON?
-                let trait_ = ResolvedPath { did: trait_.def_id(), path: trait_ }.into_tcx(tcx);
+                let trait_ = clean::Type::Path { path: trait_ }.into_tcx(tcx);
                 Type::QualifiedPath {
                     name: name.to_string(),
                     self_type: Box::new((*self_type).into_tcx(tcx)),
@@ -502,10 +505,7 @@ 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, 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)
-        });
+        let trait_ = trait_.map(|path| clean::Type::Path { path }.into_tcx(tcx));
         // FIXME: use something like ImplKind in JSON?
         let (synthetic, blanket_impl) = match kind {
             clean::ImplKind::Normal => (false, None),
index 47b24d40edc27ccaac299bfe59f804cd9ca4675d..abb4bec5ca133c69366949290ac3c8a2bbaf58bc 100644 (file)
@@ -131,7 +131,6 @@ fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) {
         .map_err(|err| format!("{}: {}", options.input.display(), err))?;
     let mut opts = TestOptions::default();
     opts.no_crate_inject = true;
-    opts.display_doctest_warnings = options.display_doctest_warnings;
     let mut collector = Collector::new(
         Symbol::intern(&options.input.display().to_string()),
         options.clone(),
@@ -146,11 +145,6 @@ fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) {
 
     find_testable_code(&input_str, &mut collector, codes, options.enable_per_target_ignores, None);
 
-    crate::doctest::run_tests(
-        options.test_args,
-        options.nocapture,
-        options.display_doctest_warnings,
-        collector.tests,
-    );
+    crate::doctest::run_tests(options.test_args, options.nocapture, collector.tests);
     Ok(())
 }
index 3b39e3576e69a39d22f577b29dd3ab4c173feebf..10b6fdf87f41972c414708bfa452b91b8c9fe61e 100644 (file)
@@ -142,16 +142,21 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
             hir::ExprKind::Call(f, _) => {
                 let types = tcx.typeck(ex.hir_id.owner);
 
-                match types.node_type_opt(f.hir_id) {
-                    Some(ty) => (ty, ex.span),
-                    None => {
-                        return;
-                    }
+                if let Some(ty) = types.node_type_opt(f.hir_id) {
+                    (ty, ex.span)
+                } else {
+                    trace!("node_type_opt({}) = None", f.hir_id);
+                    return;
                 }
             }
             hir::ExprKind::MethodCall(_, _, _, span) => {
                 let types = tcx.typeck(ex.hir_id.owner);
-                let def_id = types.type_dependent_def_id(ex.hir_id).unwrap();
+                let def_id = if let Some(def_id) = types.type_dependent_def_id(ex.hir_id) {
+                    def_id
+                } else {
+                    trace!("type_dependent_def_id({}) = None", ex.hir_id);
+                    return;
+                };
                 (tcx.type_of(def_id), span)
             }
             _ => {
index 379de080ffd4d8833fe14b80a3857d3d35a7bda6..a18bd48d72bc426a27f276f99425b0fcc9468480 100644 (file)
@@ -117,8 +117,7 @@ fn store_path(&mut self, did: DefId) {
                 if let Some(local_def_id) = def_id.as_local() {
                     if self.cx.tcx.has_attr(def_id, sym::macro_export) {
                         if inserted.insert(def_id) {
-                            let hir_id = self.cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
-                            let item = self.cx.tcx.hir().expect_item(hir_id);
+                            let item = self.cx.tcx.hir().expect_item(local_def_id);
                             top_level_module.items.push((item, None));
                         }
                     }
index f9b03d0e2d7378f8dd5697ceb72b310060f7598f..01c8b654f9a01371414d1fd69cba38b289510a9e 160000 (submodule)
@@ -1 +1 @@
-Subproject commit f9b03d0e2d7378f8dd5697ceb72b310060f7598f
+Subproject commit 01c8b654f9a01371414d1fd69cba38b289510a9e
index b5a4a3a03fdd7ac1259cfc46b1c39651cf07663e..6c1b95b4145793c917e923f2b22a38cada152878 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-10-22",
+    "date": "2021-11-30",
     "version": "beta"
   },
   "rustfmt": {
-    "date": "2021-10-23",
+    "date": "2021-11-30",
     "version": "nightly"
   },
   "checksums_sha256": {
-    "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"
+    "dist/2021-11-30/cargo-beta-aarch64-apple-darwin.tar.gz": "f7dadcadc22aab3ed9ddd737a9c2af05f42ffe48b431bbad5d43128130480279",
+    "dist/2021-11-30/cargo-beta-aarch64-apple-darwin.tar.xz": "0ee7c052bb1fd3f3655d9ff74b3f38ebb256d3f523750dbde1be9bceb207cda9",
+    "dist/2021-11-30/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "68d914f773b122bd1ceae13a55d3c8365753d09d4371e3962401b9a48945cf20",
+    "dist/2021-11-30/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "b0204e516f0c22b956f227555be5665df96c4e0f60281592b00678b4ea8ad4e9",
+    "dist/2021-11-30/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "77b771198aaf78c039df9c08493a9af5d1eb02e6b88bd4fc3b42269cdbf582d0",
+    "dist/2021-11-30/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "6f6465db2c726cc3d2db73150377ed17cbe164297f8cbffc51c8194494cb0384",
+    "dist/2021-11-30/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "76a8001adffd5d7a607459f1726f3d68c95e6eb4925eac9ccb77b213c37d2385",
+    "dist/2021-11-30/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "07dac7cfe68cb6b0a1872728c1dfb3fde0f9fa27a08933494faaf58a5e35865a",
+    "dist/2021-11-30/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "d2d6d2b56cbcc8bb5b2139818770fc155146d6b4469678de8a1e8249f15137d7",
+    "dist/2021-11-30/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "5f97d1449b9c4461be47615ab49ec408d8f1981b7a1bc0d7b7cce606c14cd5ed",
+    "dist/2021-11-30/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "097d346e828a37ae5be077f0896796ab6238194846f8ae279cd9e2f510645625",
+    "dist/2021-11-30/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "71a7906aea42e1048fc43828ece3da720eea4f9d4ff59e970e273f0fe9191e12",
+    "dist/2021-11-30/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "20e49a6995503dd8215dc9f56ffb87dc9f07fe85a1b0d2f409313836dc0dda3f",
+    "dist/2021-11-30/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "b9388524cec65e789bb5eaf22cfd63ce837b9a98d1b769901597c6f061f1b93d",
+    "dist/2021-11-30/cargo-beta-i686-pc-windows-gnu.tar.gz": "7b0bf29bc67904a64560402891d60506a29b7cd64007d7c1f4e168a574009a9c",
+    "dist/2021-11-30/cargo-beta-i686-pc-windows-gnu.tar.xz": "c580c17566e36cbb91945e0fb9e592ac7578d32da948c70aabb90de80000f5c8",
+    "dist/2021-11-30/cargo-beta-i686-pc-windows-msvc.tar.gz": "e34436449fb69b8ca696b4bcba8e18a612fee189ad8069d765813d39c708ad58",
+    "dist/2021-11-30/cargo-beta-i686-pc-windows-msvc.tar.xz": "322836c74da2b221426782e4b5e174571d1da1935d478b4b8b948608a28a20e8",
+    "dist/2021-11-30/cargo-beta-i686-unknown-linux-gnu.tar.gz": "ab2361cb4cbe44331e34a50728dd56a3db220e08f1b29452f781ee075b236c33",
+    "dist/2021-11-30/cargo-beta-i686-unknown-linux-gnu.tar.xz": "6375ef38e8e6270d6d932d176a7e62014daf153e873667f6d4a5335fa15f8bf3",
+    "dist/2021-11-30/cargo-beta-mips-unknown-linux-gnu.tar.gz": "3e80c94aef4511090e6a83f64b304b835ae2a8e769d3beec96e3f08c0faca01c",
+    "dist/2021-11-30/cargo-beta-mips-unknown-linux-gnu.tar.xz": "af954c96c823d711b372c94a2f2bab32536a4e39bcdd0351674252837096f8b4",
+    "dist/2021-11-30/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "92464fb6d0691a591637cf342842b42b940f8a84525f1e1f51493734f2ad7b1b",
+    "dist/2021-11-30/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "5ddeb87b53749bc532322ee8435fd442adbfaa5e80f3b614b7153c40f46d63d1",
+    "dist/2021-11-30/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "1c60eccc658664853232131fb48dc5d2c66340bb95d242084c211c59407fa667",
+    "dist/2021-11-30/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "257aab89cd0d5d9af408fc346aeccb8d51e1eba5dc0db074db1f4b57a8d4aab2",
+    "dist/2021-11-30/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "20b1fa2138a547f5f6644acfbca9e73f8d228578a600c7710cb2fc34a20eb058",
+    "dist/2021-11-30/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "134dde13eb7dedb8fc608acae62d715937c168a9fe5a449262e9ac9b3f042396",
+    "dist/2021-11-30/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "4ffca03462b91b9cbb02a022546aa0e16118eb1950a8f040929e5bfceee2b9f7",
+    "dist/2021-11-30/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "14bfd567241f969de712240f78d83d21dab0bd11ac42da38a2b02da7a59a9dc9",
+    "dist/2021-11-30/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "f44113175429958961148bef66d0ec1b52850c19c035ac83b0d20139e1116d97",
+    "dist/2021-11-30/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "3e5f05f0f5aa2fb8b2e63eed7b29ce67831158648f64c2892b477b318a86e300",
+    "dist/2021-11-30/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "76258605464ea434a2c28c2fd05f1947b2165fa10a2810958397d8352e20215d",
+    "dist/2021-11-30/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "c4f2e0756f8571ed7b1bd82702d91b32cc40af58e0697c2f307feeb5755f93ae",
+    "dist/2021-11-30/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "c466a280084c164ca4a120b184eab6403c80db962c0d2d1f2cb5b662746ec4da",
+    "dist/2021-11-30/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "b6f97111eeab0403c67965d57f9bee2ecdf5f39eb44941070d3cd06745f235a3",
+    "dist/2021-11-30/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "2ab5f013205446852a06f27b326f6454a5b3fb958413a7e00e1d8402413155b5",
+    "dist/2021-11-30/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "49dd5e7e3b8091546ef932f359fc4260e3f0b7ec851f43dd10f471c6fe50a5cd",
+    "dist/2021-11-30/cargo-beta-x86_64-apple-darwin.tar.gz": "ac20e50e745914c8431a5c6993b9dbb6bf7b745e4b45283b230207e7be1bb167",
+    "dist/2021-11-30/cargo-beta-x86_64-apple-darwin.tar.xz": "dec91c3f6eda827d3976b96da8def71ad3cc0b71fbe1b4e5387a464a8bbd85c3",
+    "dist/2021-11-30/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "e11e26ad4fde6109808f4cd752c2a810c8ca81b890b0c09902be981a72c43723",
+    "dist/2021-11-30/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "fb49db7bce2376335f4fda11cc454b3d762bd7f95c5dba85596100bd0c1e148a",
+    "dist/2021-11-30/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "7703eb725703aeffb57d6a2c0c95c44b6e4eed09b4a99b37346ea895a1d51088",
+    "dist/2021-11-30/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "65e0f34d9b4af3b270d8d4752c94b58e54895d180fddc3f4b535406e16b8a356",
+    "dist/2021-11-30/cargo-beta-x86_64-unknown-freebsd.tar.gz": "4624bd8e93bc1c36bccd15b44f484059f485df1c0cd1b8bcf21c4855c85b7ea4",
+    "dist/2021-11-30/cargo-beta-x86_64-unknown-freebsd.tar.xz": "a277a3fccfba30db2942c8303db16e5112d72c7721fe7a777cf24a301b68ad2c",
+    "dist/2021-11-30/cargo-beta-x86_64-unknown-illumos.tar.gz": "37e034e5c83bab47ac5cd502d4f6385af270040fb7eb59221bc02cdbcf949d0b",
+    "dist/2021-11-30/cargo-beta-x86_64-unknown-illumos.tar.xz": "d26eda6fd5533defbf3983f2bb9c07c0cba00abf4c346443080059c4810ef1b6",
+    "dist/2021-11-30/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "909f8bc8dce0276695f1e88994bd21ba2ad4a3ff66b8172e566b7907d9f2531c",
+    "dist/2021-11-30/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "52807fac650c03c9d398ce6e5987ecfd5e8e30b5c4e94c320ebc2a6fd665740c",
+    "dist/2021-11-30/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "3158dcde7e05e9871572dd7044b3c8466687d8afadbbffa4021a443f4973a4ac",
+    "dist/2021-11-30/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "551ef92e71c001fe48804587e8532b5032d419bd139b2f59cbd8c2e308e3c2ae",
+    "dist/2021-11-30/cargo-beta-x86_64-unknown-netbsd.tar.gz": "9dd630b19f6c9ce26d2ed6a1f46c383d6bc3eecf1efb80f15a651ef4408197c0",
+    "dist/2021-11-30/cargo-beta-x86_64-unknown-netbsd.tar.xz": "1f128e4e8f9e98839caf64e68fbd163de1d5323abf40f718643a815081f898ac",
+    "dist/2021-11-30/rust-std-beta-aarch64-apple-darwin.tar.gz": "3aecc61fe4e056326182db5942cd472039f95788d165940df8b53742f70fb051",
+    "dist/2021-11-30/rust-std-beta-aarch64-apple-darwin.tar.xz": "db3cdaf50925184df6a79914cd1c0df0c9782f96829d23428b1a0ebc814fb468",
+    "dist/2021-11-30/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "61df5ab32d3e11243bc2b8506c65af9d8a84a2bc93fc1315d046e20eb048c62e",
+    "dist/2021-11-30/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "42603c786c02ce754b4c756ac0fe4d88574231f5a8d31b6f9a1192680f8eb180",
+    "dist/2021-11-30/rust-std-beta-aarch64-apple-ios.tar.gz": "49e5d2df9b1019e21c14a1b7f8e69515c16d810dc354ddbe2429857214b3c33e",
+    "dist/2021-11-30/rust-std-beta-aarch64-apple-ios.tar.xz": "5323762166729cc7c3c5045b484ea2f50ec0dbdca15d8c7e82f0c29e1247f8e2",
+    "dist/2021-11-30/rust-std-beta-aarch64-fuchsia.tar.gz": "7510b5b538c735362ec6b12beaa9d3c8720c4ea1f686c643fcc40c5dabca5435",
+    "dist/2021-11-30/rust-std-beta-aarch64-fuchsia.tar.xz": "19b4d188923a820bc8424fed062bab64a56d33f8f00d9ba6792331f06eb0cbc0",
+    "dist/2021-11-30/rust-std-beta-aarch64-linux-android.tar.gz": "77a5e84c97f83ea8263fd147e5f5781a61bb5bdbf1cc40a3a8a72becc8dd486d",
+    "dist/2021-11-30/rust-std-beta-aarch64-linux-android.tar.xz": "c17f843d951d9fa72760e3a071557635da83c0dc279887648979277bcef66aff",
+    "dist/2021-11-30/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "6e86b78826f5e3d18b2f2aa4f274a5d7bacadbde8d7cfc72cc89dbcb0455fec3",
+    "dist/2021-11-30/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "e1b1e9eb09e851c8125319432b9fb52a6aa815b7f5bc82efbba7e375aab44764",
+    "dist/2021-11-30/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "a6589e628f03fc7c39345cfa23827be6cf26391848bc576a66c7701f18a01669",
+    "dist/2021-11-30/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "a0cb9706216575748a953b6e36b59875c6bf9b9410d4a8085974e324c0cbb7e0",
+    "dist/2021-11-30/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "c803cfd7c803de2b210d5e9800d44f3365a0b4ae581d987b415fdfb990de1a30",
+    "dist/2021-11-30/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "a93310d2102699602c348901186992c1305a1a20fd0a2e5d8985a4f32e61eb28",
+    "dist/2021-11-30/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "2ce3460b436c8c44e074ce1cb8c81bb2cd37ec8ea8fde1b766f113b39412d71c",
+    "dist/2021-11-30/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "5e65f8409d2a8eb366f29fe994469f257b18e70ad0707be2ca9c144a0b6f9a78",
+    "dist/2021-11-30/rust-std-beta-aarch64-unknown-none.tar.gz": "a4b73dfbf9df497883b2f5ea3053c256838e1e706f312ee02e1b018b9a7f6099",
+    "dist/2021-11-30/rust-std-beta-aarch64-unknown-none.tar.xz": "a70bd19ae1fa41a3413f0a0b6b2beff569c1b16829cd675967a6d1cd92d8dd54",
+    "dist/2021-11-30/rust-std-beta-arm-linux-androideabi.tar.gz": "46eabf68836f62fe8dfb39c54ee63e9fe211ab84443ff17c46b5240e0d08e723",
+    "dist/2021-11-30/rust-std-beta-arm-linux-androideabi.tar.xz": "9a4e53e3e867e9e18959cba32078c4f7d588247b74e156cc68345808d7b7ecc4",
+    "dist/2021-11-30/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "66d9e4de284d7a221f66a2c615d6ec0805dc8f1a91a184cc96701cf98116be60",
+    "dist/2021-11-30/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "1af2fd7a16d51e2f4bd6e1840b935e2cdc7a8f3b3b1144d22b42cea52b9bd185",
+    "dist/2021-11-30/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "cb479e676240ef682d3ad27390bc2498f80a421d321e9423cb923b972ea86675",
+    "dist/2021-11-30/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "0011ba4db5a8310199011d37818818867703bf6fbbcd7e1a7bead621eda1e5f2",
+    "dist/2021-11-30/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "8b192e6f0263d925aac1436887f67b24fa02f31c0fc708c30827f0363f032ceb",
+    "dist/2021-11-30/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "688755d433c1227db1125ee52e7aa643f27f922b21fbe3a5fcaf70467d159a79",
+    "dist/2021-11-30/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "b336cef0e11136ccf5c41669869426a376d570042d3c99eed6c448cfe165818e",
+    "dist/2021-11-30/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "1be7d7f0de2ae63b9dd282efc24531f1146fbc7831b84d9c0cd2c8cbdff32fe3",
+    "dist/2021-11-30/rust-std-beta-armebv7r-none-eabi.tar.gz": "33d49bd069b9fdbae8a6868e2cce6fcea26cfd0248372d3d3c977828b3fc51cd",
+    "dist/2021-11-30/rust-std-beta-armebv7r-none-eabi.tar.xz": "e204295b8b17388d8b4cfc04de5690b4b6a377da12df7c24f930c064da787200",
+    "dist/2021-11-30/rust-std-beta-armebv7r-none-eabihf.tar.gz": "07584d1a4f4979ff86aa8b8be820810366c4fdbda4e5dec93c0a5883804a2103",
+    "dist/2021-11-30/rust-std-beta-armebv7r-none-eabihf.tar.xz": "4f73d8af677409960ac480c254f25547752ffe08b80785dceb6b6f1fdc0b6646",
+    "dist/2021-11-30/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "fb998ae84f383f1ee93fb946f396545a60d4a58f1f0107653f3dcf97e2cfb4f7",
+    "dist/2021-11-30/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "8d8fdc9404422d0519328d6a622262833c5465b1cba62a59951a05f59d6cb15a",
+    "dist/2021-11-30/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "c8abc1c472326419065caed5567bffc4bcfac2af45fafb7f1327b468f26a0112",
+    "dist/2021-11-30/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "d905b6339363b2538bc39607c0fc58dae2b8023b1c3c1f745654a839ec178988",
+    "dist/2021-11-30/rust-std-beta-armv7-linux-androideabi.tar.gz": "69dbb3e17dcdfa9e6acc465fae4427a2596e8bfc024cc18d30201f41bcdd1be2",
+    "dist/2021-11-30/rust-std-beta-armv7-linux-androideabi.tar.xz": "f012832da820d59a791bf39c25e282c2b92bee75377e4fca7e9520162be62b83",
+    "dist/2021-11-30/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "bb742536d0d7b664ac7277bc5e45f40d64001da0ff1f9e088edc5240e1b35dcf",
+    "dist/2021-11-30/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "6d4c050229400ef1f2e384a4a360569309d1a0828ff07f97c73ca294ef114ca1",
+    "dist/2021-11-30/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "c7c354d1bd4071ef69e8d91ee5c020c9aac613ddb2565c9a3a01fa41903e3715",
+    "dist/2021-11-30/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "1bfe9acf4bc7f1e58f1e5a721172df69be65e049894046561bc94ed6ed67c24c",
+    "dist/2021-11-30/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "96fe9952332d7aee42e61445226793af32995d0f21fde7ebfe751ef2f9acfd90",
+    "dist/2021-11-30/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "2f85ea745f03f779306f78ddff9389f4417d826258a90740a76b37bd14b8fca6",
+    "dist/2021-11-30/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "434b6eaffa2a4c798b4a6f00997d65c55d9fad24d176bbc54dc045339e654432",
+    "dist/2021-11-30/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "955fd83cc57de91fea9aea3f563c4cb5a2611e6dd24406845f7e8be5b7f25f3c",
+    "dist/2021-11-30/rust-std-beta-armv7a-none-eabi.tar.gz": "45a4818cc22f80252264309263994270b2e15ec8db7ced500cef838f09260fa5",
+    "dist/2021-11-30/rust-std-beta-armv7a-none-eabi.tar.xz": "8748379556a312b31788b5458b74d5d7fb2fa61f29e5528e449d216c21f4e9ed",
+    "dist/2021-11-30/rust-std-beta-armv7r-none-eabi.tar.gz": "928a6b77d3e6e8030c6ee454d648c5f6eb0b79a8beda3d11fc3578cc4556ac45",
+    "dist/2021-11-30/rust-std-beta-armv7r-none-eabi.tar.xz": "428526e30a28a9dba01943800a179b7ba144866f36dd69171a4fd1804345b75f",
+    "dist/2021-11-30/rust-std-beta-armv7r-none-eabihf.tar.gz": "e1e43b61b7826fe4f8063d89896e7b86a13e41ed3a17ef2684d1bded5252b7b6",
+    "dist/2021-11-30/rust-std-beta-armv7r-none-eabihf.tar.xz": "5f6478a196f1eabd6d4b58ebacf89c3635a9488f4b2f145283e9352cff5da7b8",
+    "dist/2021-11-30/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "65b23ab952ed313cc9de94eae473a28eb9b7d9ca8aa432f4d3a08c30484e30c7",
+    "dist/2021-11-30/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "949e3b832f70c3effa2b78363b42caf0720ede57722c360b710773bd7f3e1502",
+    "dist/2021-11-30/rust-std-beta-i586-pc-windows-msvc.tar.gz": "06667714b168e2e0d6e0f3e81cc3fb68940f77aa3cd3495d91ce9ff15502ab9f",
+    "dist/2021-11-30/rust-std-beta-i586-pc-windows-msvc.tar.xz": "9794592856633299de53e697579c75bcf6009c6f05c7bfcadf8c63dfa383b3f9",
+    "dist/2021-11-30/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "ffb8b8ec98f9732602edcf3e4e628327f8ef80712c59ebaab5392503ed04460c",
+    "dist/2021-11-30/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "7f60c2798023bdf3993b443783d3d6dd350abfa3bbdce58ada3e9b3d3c4391f0",
+    "dist/2021-11-30/rust-std-beta-i586-unknown-linux-musl.tar.gz": "f086f349faf5f44b0fbd060f3c40b553aa5a6309a02c08e8a45d27cb3a820926",
+    "dist/2021-11-30/rust-std-beta-i586-unknown-linux-musl.tar.xz": "05ebd51df4b17c22569d69a65d9542b5010beea023e545859a23bb244162b537",
+    "dist/2021-11-30/rust-std-beta-i686-linux-android.tar.gz": "0f2a192b970209d10f2ffb4f88dcb6637e1ed822e47fef8e0d3daf4ca8b250d9",
+    "dist/2021-11-30/rust-std-beta-i686-linux-android.tar.xz": "3aee7e88fbcc0290219a8d980efb1c6d8a1642a1576393fe3b5d400a68b17f8b",
+    "dist/2021-11-30/rust-std-beta-i686-pc-windows-gnu.tar.gz": "251780731ee8c996dc1adb59148d7a0307642e11f3bf767c0caaf5f37b70b395",
+    "dist/2021-11-30/rust-std-beta-i686-pc-windows-gnu.tar.xz": "76c8cd535a4ab4f9c0ccca19986f483de63e7c6c0708e37de653acb80621bce0",
+    "dist/2021-11-30/rust-std-beta-i686-pc-windows-msvc.tar.gz": "ce1b7c98f381f207a26ca3fa5937f5e276eb8f91ef6ae2e0e082370e9ca1c21e",
+    "dist/2021-11-30/rust-std-beta-i686-pc-windows-msvc.tar.xz": "106f655c10d182b6581e87cff881bf081efe9404b52885b6efed4eb0f09a3a04",
+    "dist/2021-11-30/rust-std-beta-i686-unknown-freebsd.tar.gz": "2cac777f7178954e5c19e266d57927ddf68b74aa5a0161e35e096569d0a6946c",
+    "dist/2021-11-30/rust-std-beta-i686-unknown-freebsd.tar.xz": "abd915c242fdd2e8f7d53291b2d84d269f9c6f4c4059c725770c3e47e50c4758",
+    "dist/2021-11-30/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "f680956e937e421c7868a22ec3ac2a6de7bc8203fae17937793914f4a9fd1657",
+    "dist/2021-11-30/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "15c71b8a2e8604a49240f5d6d0da65c40c8c207f1ebec943cb8c50cd7a51d879",
+    "dist/2021-11-30/rust-std-beta-i686-unknown-linux-musl.tar.gz": "71c15bbabb5bcadb603513c73e40a96026fc8f6d5c82e9ea9b6569fcc22d5af2",
+    "dist/2021-11-30/rust-std-beta-i686-unknown-linux-musl.tar.xz": "4a9af011d4a2b63a0357c6367210fbf4b6e116b5388ed3a62b758a4bad1fa77f",
+    "dist/2021-11-30/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "c44531c5467c1e01739f3796db1f59c4b6d6483f4bb8c398c751dbc30ed550ed",
+    "dist/2021-11-30/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "0ec54d445e3c24bf7aa8ecdca45f49abfc2e4013c7af682d7134a5e52e752d23",
+    "dist/2021-11-30/rust-std-beta-mips-unknown-linux-musl.tar.gz": "3ea1a25b04112d83771e7b713ff8d33418bd18a7adcaaf6cce68f537cb27fefb",
+    "dist/2021-11-30/rust-std-beta-mips-unknown-linux-musl.tar.xz": "c904834d0fa015d24ba0e929e900ad06bfe773bc4a439f9bbcd8862a5065171c",
+    "dist/2021-11-30/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "498cda7a23e81ed7563650deb320361c8cffdc10de13ce143175e77f720600ed",
+    "dist/2021-11-30/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "bb0e95d7fad089cc84e826adffc416757df4480ffdfd09547625950b13b9e934",
+    "dist/2021-11-30/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "87ae1f563963370eeaa3f46d568339d5589e4fd509d21087db43ca2f1d6a1daf",
+    "dist/2021-11-30/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "da6268585d69c9c71c92dadb658bc7c055b5ce4c87abc52b5451d1111c1675dd",
+    "dist/2021-11-30/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "93c67427050266f49dc367a1f8e694989424664f740ae3911f78f1cc53faf35c",
+    "dist/2021-11-30/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "03f9a6e921555954b33fd7f446e9093ad4b631c86d001303e4c47078d0e1d385",
+    "dist/2021-11-30/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "6c96a53e86f71965f1922585469501504b79c3347d09409033f871b1c9cdc856",
+    "dist/2021-11-30/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "000e43f7e40abecd402242455f8a3d60692043ddb80bd15dd6f52acd1c5af096",
+    "dist/2021-11-30/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "7ee55e1f5a63b52d7b87882fa4131fe848d18dba819d46e16ea2435889d84722",
+    "dist/2021-11-30/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "b8fc28ffd7d97e76913755bedc2f9e7cec7150e036d13fcf7e50dc5a2422d1dd",
+    "dist/2021-11-30/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "af81aaa9bd624f57168762dfbae39853ada92043809bff953e108e97169e5732",
+    "dist/2021-11-30/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "37357e40af421ca5b4d2b95f19eca41ce016404ffcce8abea45e08721664f0e3",
+    "dist/2021-11-30/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "cbbd98fd3ee6bdd3c01e590c2f10367ec38d799e02ddbc1b0e31027684a356f6",
+    "dist/2021-11-30/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "defda4e2ef2f3baf8c7d2a9159d17ca439004687f0b6714826408b94d4f0aed0",
+    "dist/2021-11-30/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "201c5bdc1dba11e039bea9257e17ddd2f50b29448b070fc0edb4a7a9f4e45f45",
+    "dist/2021-11-30/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "0319b07244f443e254e10a04e75633b293faffc5896ade44c05dde0739356f38",
+    "dist/2021-11-30/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "54e7cb5a1534ecdbd484ef304f608eb48464ae2c2330958b65b8101f81291319",
+    "dist/2021-11-30/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "aecedf5ca4d91e98ba3c4faba64699d79b3fd4877f880840d492b4872ccb924a",
+    "dist/2021-11-30/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "a4cf3bde61d46484e36fd41386840250e0c031414ee422bbb3d37f7ac7489ca3",
+    "dist/2021-11-30/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "d93e2a290aea3075cd61b950ded4c3756611acc6a59ba7efb9ce2e4dbac76c59",
+    "dist/2021-11-30/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "69c9f09416b788d93f54734a953ed8dead2a31e1dacd6e67a6550529385b338f",
+    "dist/2021-11-30/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "808a02952a31ae3a171849dc217763f5cd142622e92ae2b383014bbe37e9b551",
+    "dist/2021-11-30/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "67e6b61d822cfc9f95a2808917601cf3d2560d636b12a19ee29a790cc06e8235",
+    "dist/2021-11-30/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "7310493bc6f184b401650fb399015be29a8df009e55fa1cbfbcf9d9608fe61e2",
+    "dist/2021-11-30/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "fd4db925d7eb598f210ab2d96f692cbdb627acbd6a8976259411a4d2356b8728",
+    "dist/2021-11-30/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "b5b0394ef612188fd094e355892aafe4530758fe38dc8859ba917cb2febe028e",
+    "dist/2021-11-30/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "3b7c3ad97393bc702dbd71bc819c0e5f6164cf471171c7c48cfffdf5477b35b6",
+    "dist/2021-11-30/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "21e6f247a6663918c6e38782e43211224d50d4de22a9162be0c5f6d6d0a9afea",
+    "dist/2021-11-30/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "d0c9bd56dcac12d7174e11f2acdb16fba41ffb3aba71b6b1b4b49ce7fa115f6e",
+    "dist/2021-11-30/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "c89adc1cbdb7bfa27f5bfdac38b5ff084eafe081b27548dc243bbff378ec7118",
+    "dist/2021-11-30/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "3e6f8a86901c1350c54bd89e156af029978f4a25f578ea26f49a1f3332da2187",
+    "dist/2021-11-30/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "43e74dbeb89547be1b3ad1b532bef97b577530a8b19b825342efb72d91d4b0bd",
+    "dist/2021-11-30/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "c8c7a22e63353e7c7766e254c3fc0b0277bc8265f1123a38705bf319a7d99a19",
+    "dist/2021-11-30/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "1759ca2de0ff890918a0f634782557ae2b3181e543790878093f303ede45e215",
+    "dist/2021-11-30/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "a9ac36f2b4e88ce2f2789e9df46ae679879c111594cfe82b538e4067adad2b5e",
+    "dist/2021-11-30/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "6260f0616828d79898165bf42875881dc5253143d940ac951b7f295553afb8c9",
+    "dist/2021-11-30/rust-std-beta-sparcv9-sun-solaris.tar.gz": "42d3e5acf2475d732ce5afe3c2ebea6d332c137d061aa256df75b7ce54c16b16",
+    "dist/2021-11-30/rust-std-beta-sparcv9-sun-solaris.tar.xz": "7f84ff29dc36a224961e87d40cd6e531c9309bdafaec5de2b043aa89af511552",
+    "dist/2021-11-30/rust-std-beta-thumbv6m-none-eabi.tar.gz": "6bfdf4e59ac3f9dbde2fa46797bd9bb9cbda232c0d507f04bafd937e88945cb7",
+    "dist/2021-11-30/rust-std-beta-thumbv6m-none-eabi.tar.xz": "d12901a4efc8395df3c1ac137f86c3da07477277fad138edb49d5c4382a3a114",
+    "dist/2021-11-30/rust-std-beta-thumbv7em-none-eabi.tar.gz": "38718b50fa2acacc0fac98931a5714df38feb8370fccf8d7a955de3b2c117dd0",
+    "dist/2021-11-30/rust-std-beta-thumbv7em-none-eabi.tar.xz": "9753c00de1117a5fb9bff4ce2a4434ac6d3d06a1b4b3d0cc44ddb590739b9a0b",
+    "dist/2021-11-30/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "c1eb35c914ad1a762cf550d54b7ec80cb3a8ab6ab39f5c89709f88e04eeba46f",
+    "dist/2021-11-30/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "3c092ac130633f327a0afc8bdf8ba252f05d9b0050383122d7ba31cc3f5ddfc5",
+    "dist/2021-11-30/rust-std-beta-thumbv7m-none-eabi.tar.gz": "fb391d1199eab0854228323d08dd8b27709175697532e4b47e9dab6f26f24a8f",
+    "dist/2021-11-30/rust-std-beta-thumbv7m-none-eabi.tar.xz": "82347d3a0a123c430a526486dbd8c424732181eede038e2f91f1504d510a755b",
+    "dist/2021-11-30/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "0cb559fff7f8dc35e5279217ef6fe7c2b5fa3d68f5ca82f258b6885f42e8d144",
+    "dist/2021-11-30/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "ee1fe1dc9fe620743022939cdeac3ab34135e61897f0707c3b1a0a1b7d730360",
+    "dist/2021-11-30/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "bb8de6fe10aa624fdd63484403e228a5c592b94d4aac95e2b2401cd8b9472f0a",
+    "dist/2021-11-30/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "1bb7f7ac88e250534d89f0b0dc74f13ca563bad53956be74418d2aef28d250a5",
+    "dist/2021-11-30/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "0aea9f5cddb136591d105ebd3607a2e1f402f1c707cf33f21fb5cf1d30101ee0",
+    "dist/2021-11-30/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "f547622b8f052c6290c530d506d8ee314f90c81ace562a0a533b6ad2ba00b987",
+    "dist/2021-11-30/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "80f8f7c613c7ff2097f5c346b3ac4a5cf750167277f28655e0263b05a231668d",
+    "dist/2021-11-30/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "a57b4489a1d46ad3fc303a3b2dd478df66407a3e2dfeb9c12860a543ae5210eb",
+    "dist/2021-11-30/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "6c4264b2bcecc951c39626fc1cf8de36f1eadbda31a552e14274f728978e16a5",
+    "dist/2021-11-30/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "ec72f8e861eed6b5e2518b46cd8008d3bd2b6f2a7a42784a2dc8a6184d3ecc62",
+    "dist/2021-11-30/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "0fc209babd43546d04b3fdd27ce77c96d75aa5eb6595f00586a19a17e4530b59",
+    "dist/2021-11-30/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "ecdb8152992b4a9779aeda2b4cc638163ac24faf45c484f27316a6b3ff0eb297",
+    "dist/2021-11-30/rust-std-beta-wasm32-unknown-unknown.tar.gz": "52bbea99f2405f35f58d5448c353c605c2a87e7546e95b86d8baa39b4fc7a9a2",
+    "dist/2021-11-30/rust-std-beta-wasm32-unknown-unknown.tar.xz": "47ea301d79eada8898907af226b39b4c73ac1fe974963139aee78c3567ee53e4",
+    "dist/2021-11-30/rust-std-beta-wasm32-wasi.tar.gz": "dc9ccfa3e46e4f3b0e11de8a83885695ab154a2211fa89a20670db116d63a4c2",
+    "dist/2021-11-30/rust-std-beta-wasm32-wasi.tar.xz": "52d890b402c7e7bb7c0f9b34f2e216f0937453ab42e7c4ce205739bd64ba7dc7",
+    "dist/2021-11-30/rust-std-beta-x86_64-apple-darwin.tar.gz": "0ccbff8a582047cd6d2a6b30387ea73cfce7e0c61eddf516126836b9f9ca86ff",
+    "dist/2021-11-30/rust-std-beta-x86_64-apple-darwin.tar.xz": "cab55f71575d58aa7213a7dc4cfb0704ca7faec7203c545aeaff178eebe40436",
+    "dist/2021-11-30/rust-std-beta-x86_64-apple-ios.tar.gz": "6863523669b65464bd52e1a47f6decf868cc93d2111ffc222bb4a032a0095e3f",
+    "dist/2021-11-30/rust-std-beta-x86_64-apple-ios.tar.xz": "d5c6e65a656621891f387861c8259116dd9a8ab14e13ea10e93b78834e1d334a",
+    "dist/2021-11-30/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "ec7130bfff74b7226fb5d0f311dd399f7628cb59ce06b4bc9a9f394067855eda",
+    "dist/2021-11-30/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "0f52f00f03126aed0260cbfdd9790a62f9f4ceb24e2a3a6d80e8a15a1b4a09c2",
+    "dist/2021-11-30/rust-std-beta-x86_64-fuchsia.tar.gz": "1a3f4c6c1528050820b85e07aa96af6588c7d61935108cb5110d1e0c964142e8",
+    "dist/2021-11-30/rust-std-beta-x86_64-fuchsia.tar.xz": "fe9488c3476e931440ad487a4cf265fdd3c01e18c9e43b33f51b9eb078821282",
+    "dist/2021-11-30/rust-std-beta-x86_64-linux-android.tar.gz": "c7205b1cdcdff00d91a3991b1f40674b075c34dc0877de4786da5ab85e3b6cfa",
+    "dist/2021-11-30/rust-std-beta-x86_64-linux-android.tar.xz": "87a3cfe8992ad615d5522d97ace91dcc86057d060d82b581df206f2802225a0e",
+    "dist/2021-11-30/rust-std-beta-x86_64-pc-solaris.tar.gz": "cd9eeb26fe909e38d8d8129829d19b4d04d96014496cc7f2f4ae077b94f2aae3",
+    "dist/2021-11-30/rust-std-beta-x86_64-pc-solaris.tar.xz": "b6e59180ff89f7e460fcbc246802e6441c71600774ae5cb2d9af464365a642cb",
+    "dist/2021-11-30/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "45e07be14211ec7c9f3c1ad0eb9f7a9b422b10c842d5d0e8b0b498751ab7ae0f",
+    "dist/2021-11-30/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "593f70209f3b5b4e126d57ece0b1adefb4bc1055cfd168779d854369985b2b2e",
+    "dist/2021-11-30/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "6e14f3431da08f63d82e5b1e2c56fdf13f93ea7b6660dc64b1c855d00c008257",
+    "dist/2021-11-30/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "6e6355686d22213d27f5dbec0b7ded38532e79ac904bae978a8eb5fc880916cf",
+    "dist/2021-11-30/rust-std-beta-x86_64-sun-solaris.tar.gz": "39bdaa250d8f17914602a2185c51014f7fbfb1e30991816a432c3897338b52a1",
+    "dist/2021-11-30/rust-std-beta-x86_64-sun-solaris.tar.xz": "ebab0e4b13e0b3bdbe0ac858d5a4ca28bb813854aea1d8ec86d8e220c68b3442",
+    "dist/2021-11-30/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "a700f1736b96c4e7237305dc98a79163b07127f0aac1f436415c233b8495a5af",
+    "dist/2021-11-30/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "e94ecf7d1c9a5144577fdb14b7232b11dff0ebbfa8aae8cb4884d4ed9c5bae77",
+    "dist/2021-11-30/rust-std-beta-x86_64-unknown-illumos.tar.gz": "209dc9917790c2be8777c597e19a9f43301aaaaac3c9731e9d0512e6918334b9",
+    "dist/2021-11-30/rust-std-beta-x86_64-unknown-illumos.tar.xz": "6e4810c7484c231f0edb15ae5acea822ed5d868eaf041438afea4b6ba38be35e",
+    "dist/2021-11-30/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "df952ee1385da9457c4e95dc08ab59ca915f5f211738982f8db3684cf80967fc",
+    "dist/2021-11-30/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "62d7383ee21b0a7d072b15a9877a922f8dbcea42d910c2cb3c4129152b26ea9a",
+    "dist/2021-11-30/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "be28225516fa38edd34e1af5f051d7c8ab5f433cc5814df199bc451285d95e0c",
+    "dist/2021-11-30/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "1a6fdfac24feb34744daced6c6545c844ff13d5e5f14620520d5ed4b85be8742",
+    "dist/2021-11-30/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "c0f098faa0c9de6a8e82b80dfe44bfa9d4482e118259c33452ef025885ceab6e",
+    "dist/2021-11-30/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "1d1ed7cf8fc16efab3faab9ef5abadac9ab98d3b60522fde0612ac0b256de528",
+    "dist/2021-11-30/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "1ed41e8019480cd151a9ddd0f080afc56ed0afe47cfb7c6b5a6a2473ff6e7e81",
+    "dist/2021-11-30/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "849c04115660abdf1d4460aef2d87021c6ad52423c83dfed3c2cec8e380ae6fe",
+    "dist/2021-11-30/rust-std-beta-x86_64-unknown-redox.tar.gz": "e3a35d33b3282fd156482c85e19817f78dcd964de8b712a6e46b965dc60d5204",
+    "dist/2021-11-30/rust-std-beta-x86_64-unknown-redox.tar.xz": "d5bfbb1415a62547b9e2a24b770a3c6e4d531101cfb2360b7a7de34d0bf18974",
+    "dist/2021-11-30/rustc-beta-aarch64-apple-darwin.tar.gz": "28beba0ff958b93f85618e49f13f4062cefacc82f6b5911d42f00515f99c5abe",
+    "dist/2021-11-30/rustc-beta-aarch64-apple-darwin.tar.xz": "07c6a43130112c93745e729c91669243cd28b73fafc7d9b32b4f22650db7bcad",
+    "dist/2021-11-30/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "9e70dc74c4428438716d14861797380ce7f6617bc93b83c74fc1a6f8aca99392",
+    "dist/2021-11-30/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "8f61ec8129b7b0bcc6b329337e5e0323054a438e999615687a18fdc42a8d0692",
+    "dist/2021-11-30/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "bba3cbfdd2842cdf8f2698b709401db6a641227d1742595e3959f1f0ace37c5f",
+    "dist/2021-11-30/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "fe74ad76a2cffdff0a2fb953f31b73d80a0bce75402bf65f01d250fcae6ff779",
+    "dist/2021-11-30/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "cde952fb3c38a969c0743d2f9d90e256db8613c463a4b23d6119656570978eb5",
+    "dist/2021-11-30/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "f2dd88f1b4ec97aaaebb601d20751d50536e85b2cac36740abbc03fa8a4d0d06",
+    "dist/2021-11-30/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "1a4414987e4da2c8086590fe4ad531f78862443eede3bc9069efb424900746d2",
+    "dist/2021-11-30/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "1682f8bde2562d4b9183fa512bc1e54d2a821fd9f63208a51489f21deeb7fcfd",
+    "dist/2021-11-30/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "ca40f3c5e8fd8bd6d89d3c0a3ad4d767353c1b4138e2720371a275c9c52c9117",
+    "dist/2021-11-30/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "c7afe4eba5cdb02a2e8ae224a0970c8aa36ef429ac298b0f98ff41a0d911aad1",
+    "dist/2021-11-30/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "6acd677fda38aea2b960f2af6438b30c3b6bd759bb3e56228a1096445ddd100f",
+    "dist/2021-11-30/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "451a2e139771f39ec09a7cefd48885ec30f732668d50c750d42e6c58c250f8fe",
+    "dist/2021-11-30/rustc-beta-i686-pc-windows-gnu.tar.gz": "a1df7d105231d4941a55a9f850d39acc201a99dd408d523935799b70fec30c6a",
+    "dist/2021-11-30/rustc-beta-i686-pc-windows-gnu.tar.xz": "3005718736a2a0fa3a4f1be10239cfb467e9cabe6ce366f9909826bd3c06a990",
+    "dist/2021-11-30/rustc-beta-i686-pc-windows-msvc.tar.gz": "695039c6737fb3bfd325fbebdab61aeef80ec427ae3d40d8b82e8b317e147fc8",
+    "dist/2021-11-30/rustc-beta-i686-pc-windows-msvc.tar.xz": "7a5038b7299de71d3677042647fca501984d1f2a52c1d84052956ff7854622b3",
+    "dist/2021-11-30/rustc-beta-i686-unknown-linux-gnu.tar.gz": "d21dd4c98d38186544aee9b22b439d67d77c0a740357dfad7fea3c4a9b8d1332",
+    "dist/2021-11-30/rustc-beta-i686-unknown-linux-gnu.tar.xz": "e62a7c9809de668343323eb9fa1a1f6cc302a6e161e64826e9d31bd202f2f472",
+    "dist/2021-11-30/rustc-beta-mips-unknown-linux-gnu.tar.gz": "b85eb1bff16384b4f6ad268a01bdcec539b9ea412abb6d64618521cb0e63985d",
+    "dist/2021-11-30/rustc-beta-mips-unknown-linux-gnu.tar.xz": "ce79b36723a65419e03ec77ea14680791d683e5e04332eebdf59550bdaaa164d",
+    "dist/2021-11-30/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "e778edd911e09c5c3b46aeccbabcd8ead78dd38086206d03406fc8dce52806e7",
+    "dist/2021-11-30/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "10afe035ca7d3a967b467875b1345dde8bdcd3f8c4af1e917bfa2c676e0fec70",
+    "dist/2021-11-30/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "6b6c3386ebec138ff07a21d3f5631263219c226ca146bf97fe0a7bb9fee9d0c5",
+    "dist/2021-11-30/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "5ff6430623d0f3aa14748f371e34072aba126a16429928f8f99172190f369fee",
+    "dist/2021-11-30/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "369ad16e85e4f2956e400105e6d8374ff64c473c3c3b61ae4d916214d5f922da",
+    "dist/2021-11-30/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "1c8adfb22f724fa98f30f23378a28729e144f6ab9bba54adf13111ca4648ed78",
+    "dist/2021-11-30/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "b3e270c6272420c31ee7bed8ed36c113c879a384fa5b85af0deb7d43a355ca2c",
+    "dist/2021-11-30/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "a21cdd8d182cc64ceaa83e522299860c2710dee780e8f49ff107a73fbd73c3ca",
+    "dist/2021-11-30/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "1a81076b8e49647b61761a38ed283a9a71b326dc321920f7be453e0e15ae2465",
+    "dist/2021-11-30/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "3f8ce23f81623a00de63ce7e82e448eec0901a92f908e6aff362807bae14ff84",
+    "dist/2021-11-30/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "eaa3b365bd91a5770db85e8541ee28c99988635521c0f2dfea05218172f11a55",
+    "dist/2021-11-30/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "3f856ae24c4737bf1928025a10712b6d856788d988fb5018631c525d13b68e29",
+    "dist/2021-11-30/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "c672cbf2caef81f7ab923ff7c6a05f1865057278180a686f810ddc71dacc49d0",
+    "dist/2021-11-30/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "bda5d2234aebdc175c87da3b77d050c56bced21a794c416bb9090c0ae3374be2",
+    "dist/2021-11-30/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "59e01371664f8d39c7a06c205af0f5ab9aabdb3942be4f493d05ab71047619e8",
+    "dist/2021-11-30/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "de956b5275e38e0b4223819973e85f5f65c409addd786f7ac2d525a79c3f0c92",
+    "dist/2021-11-30/rustc-beta-x86_64-apple-darwin.tar.gz": "4f78d90362488a866ea7b1cccbc61f925d94034b46dfa775dea75223e67d755a",
+    "dist/2021-11-30/rustc-beta-x86_64-apple-darwin.tar.xz": "3520d028e9370087cfa57eb7225dd76c008cb08ffb01c8101aaa86104f427f12",
+    "dist/2021-11-30/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "f954349daa7dfd819ec0a7335a47b1d3b2ed0138eae31c56288d9c523cdf56b2",
+    "dist/2021-11-30/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "ca046d8fca5fa48117c61c70a21176d9220a3c62af9fdc9b899c157bb196a5b5",
+    "dist/2021-11-30/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "61ae4421bdf798a5ca1a8bc8c8521dfb29a707e40d382dbd2e155f134956ac33",
+    "dist/2021-11-30/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "495076dfc2fa0b8d96613e34f867de9d43483984a8bd6839bf273c2be38039b6",
+    "dist/2021-11-30/rustc-beta-x86_64-unknown-freebsd.tar.gz": "828526bc23ad8802071bf4f2984faf3549139eb4ce8ebb9ba8711c196d2bf437",
+    "dist/2021-11-30/rustc-beta-x86_64-unknown-freebsd.tar.xz": "fa2464350b2ac29bec6751c551cc45b7af92c25d2cf1109397e724802d4859cf",
+    "dist/2021-11-30/rustc-beta-x86_64-unknown-illumos.tar.gz": "a1d9719668ea1887d6202c25b9dd2b7d40bdd240f3f753af77ac93f126c84c38",
+    "dist/2021-11-30/rustc-beta-x86_64-unknown-illumos.tar.xz": "4b36f5d448bf022f90e284c22a44e0b87ef8518ec93a297ceb703eb612ef80d8",
+    "dist/2021-11-30/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "63e654f5e8707a0536381025bdbb43d498c70a29a5ada0ecdb12e23844cc9a9f",
+    "dist/2021-11-30/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "6b5b74abdcb1cae42620cabc142a119b58823e9f2ac0c3151e087a76323c5cae",
+    "dist/2021-11-30/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "f3aa2d52ce5da066c59de609ebd5df60ac908c7e0db23ac4afe69b927ef2a974",
+    "dist/2021-11-30/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "6e8858dbaf50a8211516e5afa83e4133d878e0d4b19ba4a3e4c3e51cb80210b7",
+    "dist/2021-11-30/rustc-beta-x86_64-unknown-netbsd.tar.gz": "9028dd44728092ccaec86f415abdb3733f3ea58ab7c3d736e96e27540cc66a2d",
+    "dist/2021-11-30/rustc-beta-x86_64-unknown-netbsd.tar.xz": "c6720fd231b54a04e1ba3ed3fe333b1d8ef5b771ce341b4c112169a293bf713a",
+    "dist/2021-11-30/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "d987783ba5117529b325bcf6f5e7abd9eee42b5ea86ce5109a4fd3f450af8062",
+    "dist/2021-11-30/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "5d5838733dc64e302991465c1f371fde855ee410d42d1713ddc1c471b469e1a8",
+    "dist/2021-11-30/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "8593ab35bb800312d6fe4c4a4d151feb26187c6db0d0d5ca5e3e98a007f8a4ff",
+    "dist/2021-11-30/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "a2ded0420cc1d98df255c7ef93247b9a6d3d9ec22e42c477305dc15ef35fd329",
+    "dist/2021-11-30/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "652275e77d73f122c12eb952338661562a48fc76164d6549158abc14fb4e4a4a",
+    "dist/2021-11-30/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "fbb49b56bb11348e07124d8216b8f8b6e26d8697abb05afec0ddb07a456b29e5",
+    "dist/2021-11-30/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "817c7ed90ab8cdec1dcfc8571391a714002b49fd20da0ae32135f57d233ffbfb",
+    "dist/2021-11-30/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "cbd8674c65babce944bab6a6f013d44a2c7d6829434a6b97edb1f1e1df1c076f",
+    "dist/2021-11-30/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "66b13ffad073bc624ebdef219e61f8972fc6be354aaf1f8ede58a3acc01314c3",
+    "dist/2021-11-30/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "11ecfef218376fd2232ad552526b39173c5269130f02e408a7492762cde87a6a",
+    "dist/2021-11-30/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "07ad99e019141843f5d6f8c302b9d20c7453ebead79e9711af33c9c8081b9e22",
+    "dist/2021-11-30/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "6656be84a9b5a63083d63e3a87bc928b424109efff48e3a6770e026c6ea7c2e8",
+    "dist/2021-11-30/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "155422628d41ce9730f4503bffa12e396b58692c906828acf15f0dd39b3d491e",
+    "dist/2021-11-30/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "fc75c3836489bda30d340132d0d5ab8ee7f7c67617e4dc66a9eae559bbdb0421",
+    "dist/2021-11-30/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "181d557c8f73c8f22ed63a8f98e53f6d88871fd694173aea70c53d42c0c55ae2",
+    "dist/2021-11-30/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "5defc562a2f0ced4539006692cc969cf89756637f5f5c62be0276dfedd6f3db6",
+    "dist/2021-11-30/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "f28b3fdf5425e7b782d0f78ca95613efd87b2b0d14d44c4490f17d4eb452f183",
+    "dist/2021-11-30/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "b6cebd5a23bcc504d05c8dd79654baf2ab45b162c59b7b843e24efb7e2344011",
+    "dist/2021-11-30/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "c59850b28fcfb1608c7e91890b8628ac201b87b4d9af7e9fd019e3e4a137c033",
+    "dist/2021-11-30/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "ad808569083691ba31b0e10222f9dd01822ade91689bcb060544f28b99f2a299",
+    "dist/2021-11-30/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "8fca357226b91cc712b888c0a62f9e52b121ab6d9815ea5f53bbfd243b895b69",
+    "dist/2021-11-30/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "7f5451fe6946c16a7ba404c8bab33816d58d478b1dc0ea1ce6b85befe26ddf77",
+    "dist/2021-11-30/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "7cc76ce31cf59f1cbeca87a46c996e905f048acfc70d438eae2a32bb67fc60c1",
+    "dist/2021-11-30/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "429bacebe2a9f1478a00b1573fe4e1b071c6348d800182993c8b5d8ba54d9615",
+    "dist/2021-11-30/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "701a12b5a4a689e6b2ef260e35ed2d22c00452cde5e18ce0d886ace37e81964f",
+    "dist/2021-11-30/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "0ef78c91a3220226619f20b28bf67947a56ff31f369d5ea7bfc2aef356060e42",
+    "dist/2021-11-30/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "0765a3b65315bbb1381927eaf6f65f16fd09dddab41d7398e483bf001ee7bc3e",
+    "dist/2021-11-30/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "c74b0833f995ffad5c812ba130f423485bd8297eca0c4eae227852a88ece8521",
+    "dist/2021-11-30/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "3c9d5a35ef1e459ded4dcdcad40bc5e3bcd5b2821cf4f46dbaf2c2c3259fa3ff",
+    "dist/2021-11-30/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "0aa8975a6dbd103a4764ad643de6094bd6911bd3a90d46e24ad1eafcea2870e7",
+    "dist/2021-11-30/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "a0ee2ec59ed07ba9c9e48076c954f5c6e4d39809d9e4923337db2627ea279c6f",
+    "dist/2021-11-30/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "e712fa72a41dedcd50c6531433220904b9627fa78bfa15cdd96d97161981cb77",
+    "dist/2021-11-30/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "fc7809520a4a41ccb0ffb303c7bbc96443308387890ebdb65a25c3697a5c3eb4",
+    "dist/2021-11-30/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "84a8fa7468b9e59465f85607f84960e11faf0f37bd766d55b6be985db89d0d17",
+    "dist/2021-11-30/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "2703dff8cb1c0ca08787f1c7715885c5b09919c040783ba98bd74f8fe3af704d",
+    "dist/2021-11-30/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "a3e25cc857e990b467c804f41e23bfbe8ef02630b48703fc1c7fae692e16eb80",
+    "dist/2021-11-30/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "659a9ca0e1296f817cd9f90fed9ccd7d3c7c3e7eea7e9c437bbeb2d951a2669c",
+    "dist/2021-11-30/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "21e83ac3b148f0f690cb9a39b385fb0d5a82d6eea9ec46d4d4445b5a660c6d7c",
+    "dist/2021-11-30/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "c8e3300a426cc4a80ba4f1cf0c6822d9b883f24c486b991f2056938be778d43f",
+    "dist/2021-11-30/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "55f1f7d84828b3cc5d13b10e549a74f2f1df11057ed48e75fbafc0d3538daf03",
+    "dist/2021-11-30/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "99bf70cee39b2ce73dbe5827fe3d93e45241faea284acb3f8004cf7e700e1704",
+    "dist/2021-11-30/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "dfc569d57211eae74a2cde5db180d2f2f44bca04f811655ef1f8d8c2154b97ef",
+    "dist/2021-11-30/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "679d69ba6a4b460f9672f1ec1c2939ac41ee7f911a2a74eaf6db477aa088e6e3",
+    "dist/2021-11-30/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "3b9a899fcf40db84be8bd14e7c767c572c7d8c7c85f90997b8278fe8726413ae",
+    "dist/2021-11-30/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "19be469ab711dcee7a7243e865efc5addf8b2cdbdf15150a2c367692c45b9f94",
+    "dist/2021-11-30/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "789c7129e235b65860a514fdb38f01ac195af610d4ac6a296d272a6f36d72344",
+    "dist/2021-11-30/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "18657363783d0967d871ee1ed8905b3db0c3b761910fb06ea10980ec6b5ca082",
+    "dist/2021-11-30/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "8b272546a9eb8b23724fbec5577fc0c917a23e994befc38ebfa797957df03b9d",
+    "dist/2021-11-30/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "4e1de312f07fb98845a881b44c2a76ec9abf61e5aba46e8e384de1cd297957a3",
+    "dist/2021-11-30/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "a13ad29e2d06c9df233882d009ba8354d92d2fb29239cadaf858b9abc8b477d9",
+    "dist/2021-11-30/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "aae38bbf1eb7e0da50eb7f226897dc85e88b5e008ef901a93dadb0550f4055ac",
+    "dist/2021-11-30/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "757564eaa1a339d37b59da304bbc7a846bb883a73c62b78df39dacd947606ec9",
+    "dist/2021-11-30/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "5f3a83079cb1fd7d8b9be44d0df7b57c6dc79da8e1762eace67c122cffc2d4ca",
+    "dist/2021-11-30/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "e47ee14a1e679ee5f23936ba7d7de13dcba082c7f32e366be7a990503c91f6ad"
   }
 }
diff --git a/src/test/assembly/sparc-struct-abi.rs b/src/test/assembly/sparc-struct-abi.rs
new file mode 100644 (file)
index 0000000..dd8e6f6
--- /dev/null
@@ -0,0 +1,64 @@
+// Test SPARC64 ABI
+// - float structure members are passes in floating point registers
+// (#86163)
+
+// assembly-output: emit-asm
+// needs-llvm-components: sparc
+// compile-flags: --target=sparcv9-sun-solaris -Copt-level=3
+#![crate_type = "lib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+#[lang = "copy"]
+pub trait Copy {}
+
+#[repr(C)]
+pub struct Franta {
+    a: f32,
+    b: f32,
+    c: f32,
+    d: f32,
+}
+
+// NB: due to delay slots the `ld` following the call is actually executed before the call.
+#[no_mangle]
+pub unsafe extern "C" fn callee(arg: Franta) {
+    // CHECK-LABEL: callee:
+    // CHECK: st %f3, [[PLACE_D:.*]]
+    // CHECK: st %f2, [[PLACE_C:.*]]
+    // CHECK: st %f1, [[PLACE_B:.*]]
+    // CHECK: st %f0, [[PLACE_A:.*]]
+    // CHECK: call tst_use
+    // CHECK-NEXT: ld [[PLACE_A]], %f1
+    // CHECK: call tst_use
+    // CHECK-NEXT: ld [[PLACE_B]], %f1
+    // CHECK: call tst_use
+    // CHECK-NEXT: ld [[PLACE_C]], %f1
+    // CHECK: call tst_use
+    // CHECK-NEXT: ld [[PLACE_D]], %f1
+    clobber();
+    tst_use(arg.a);
+    tst_use(arg.b);
+    tst_use(arg.c);
+    tst_use(arg.d);
+}
+
+extern "C" {
+    fn opaque_callee(arg: Franta, intarg: i32);
+    fn tst_use(arg: f32);
+    fn clobber();
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn caller() {
+    // CHECK-LABEL: caller:
+    // CHECK: ld [{{.*}}], %f0
+    // CHECK: ld [{{.*}}], %f1
+    // CHECK: ld [{{.*}}], %f2
+    // CHECK: ld [{{.*}}], %f3
+    // CHECK: call opaque_callee
+    // CHECK: mov     3, %o2
+    opaque_callee(Franta { a: 1.0, b: 2.0, c: 3.0, d: 4.0 }, 3);
+}
index f228d7c55008487c583114f1e59e61b490b7bd8d..b531dba46079d659154543ecfd709df5d0c47341 100644 (file)
@@ -1,5 +1,5 @@
 // Checks that we correctly codegen extern "C" functions returning structs.
-// See issue #52638.
+// See issues #52638 and #86163.
 
 // compile-flags: -O --target=sparc64-unknown-linux-gnu --crate-type=rlib
 // needs-llvm-components: sparc
@@ -25,3 +25,59 @@ pub struct Bool {
 pub extern "C" fn structbool() -> Bool {
     Bool { b: true }
 }
+
+
+#[repr(C)]
+pub struct BoolFloat {
+    b: bool,
+    f: f32,
+}
+
+// CHECK: define inreg { i32, float } @structboolfloat()
+// CHECK-NEXT: start:
+// CHECK-NEXT: ret { i32, float } { i32 16777216, float 0x40091EB860000000 }
+#[no_mangle]
+pub extern "C" fn structboolfloat() -> BoolFloat {
+    BoolFloat { b: true, f: 3.14 }
+}
+
+// CHECK: define void @structboolfloat_input({ i32, float } inreg %0)
+// CHECK-NEXT: start:
+#[no_mangle]
+pub extern "C" fn structboolfloat_input(a: BoolFloat) { }
+
+
+#[repr(C)]
+pub struct ShortDouble {
+    s: i16,
+    d: f64,
+}
+
+// CHECK: define { i64, double } @structshortdouble()
+// CHECK-NEXT: start:
+// CHECK-NEXT: ret { i64, double } { i64 34621422135410688, double 3.140000e+00 }
+#[no_mangle]
+pub extern "C" fn structshortdouble() -> ShortDouble {
+    ShortDouble { s: 123, d: 3.14 }
+}
+
+// CHECK: define void @structshortdouble_input({ i64, double } %0)
+// CHECK-NEXT: start:
+#[no_mangle]
+pub extern "C" fn structshortdouble_input(a: ShortDouble) { }
+
+
+#[repr(C)]
+pub struct FloatLongFloat {
+    f: f32,
+    i: i64,
+    g: f32,
+}
+
+// CHECK: define inreg { float, i32, i64, float, i32 } @structfloatlongfloat()
+// CHECK-NEXT: start:
+// CHECK-NEXT: ret { float, i32, i64, float, i32 } { float 0x3FB99999A0000000, i32 undef, i64 123, float 0x40091EB860000000, i32 undef }
+#[no_mangle]
+pub extern "C" fn structfloatlongfloat() -> FloatLongFloat {
+    FloatLongFloat { f: 0.1, i: 123, g: 3.14 }
+}
index 144a746062daaa74f29b328870a06a0c0cd56290..8470ace24b845beef405b8330b11968ca76e76aa 100644 (file)
@@ -1,4 +1,4 @@
-// pretty-printers are not loaded
+// ignore-windows-gnu: pretty-printers are not loaded
 // compile-flags:-g
 
 // min-gdb-version: 8.1
diff --git a/src/test/mir-opt/const_prop/switch_int.main.SimplifyBranches-after-const-prop.diff b/src/test/mir-opt/const_prop/switch_int.main.SimplifyBranches-after-const-prop.diff
deleted file mode 100644 (file)
index 6a5b88c..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-- // MIR for `main` before SimplifyBranches-after-const-prop
-+ // MIR for `main` after SimplifyBranches-after-const-prop
-  
-  fn main() -> () {
-      let mut _0: ();                      // return place in scope 0 at $DIR/switch_int.rs:6:11: 6:11
-      let mut _1: i32;                     // in scope 0 at $DIR/switch_int.rs:7:11: 7:12
-  
-      bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/switch_int.rs:7:11: 7:12
-          _1 = const 1_i32;                // scope 0 at $DIR/switch_int.rs:7:11: 7:12
--         switchInt(const 1_i32) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:7:5: 7:12
-+         goto -> bb2;                     // scope 0 at $DIR/switch_int.rs:7:5: 7:12
-      }
-  
-      bb1: {
-          _0 = foo(const -1_i32) -> bb3;   // scope 0 at $DIR/switch_int.rs:9:14: 9:21
-                                           // mir::Constant
-                                           // + span: $DIR/switch_int.rs:9:14: 9:17
-                                           // + literal: Const { ty: fn(i32) {foo}, val: Value(Scalar(<ZST>)) }
-      }
-  
-      bb2: {
-          _0 = foo(const 0_i32) -> bb3;    // scope 0 at $DIR/switch_int.rs:8:14: 8:20
-                                           // mir::Constant
-                                           // + span: $DIR/switch_int.rs:8:14: 8:17
-                                           // + literal: Const { ty: fn(i32) {foo}, val: Value(Scalar(<ZST>)) }
-      }
-  
-      bb3: {
-          StorageDead(_1);                 // scope 0 at $DIR/switch_int.rs:11:1: 11:2
-          return;                          // scope 0 at $DIR/switch_int.rs:11:2: 11:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff b/src/test/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff
new file mode 100644 (file)
index 0000000..f2b0255
--- /dev/null
@@ -0,0 +1,34 @@
+- // MIR for `main` before SimplifyConstCondition-after-const-prop
++ // MIR for `main` after SimplifyConstCondition-after-const-prop
+  
+  fn main() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/switch_int.rs:6:11: 6:11
+      let mut _1: i32;                     // in scope 0 at $DIR/switch_int.rs:7:11: 7:12
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/switch_int.rs:7:11: 7:12
+          _1 = const 1_i32;                // scope 0 at $DIR/switch_int.rs:7:11: 7:12
+-         switchInt(const 1_i32) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:7:5: 7:12
++         goto -> bb2;                     // scope 0 at $DIR/switch_int.rs:7:5: 7:12
+      }
+  
+      bb1: {
+          _0 = foo(const -1_i32) -> bb3;   // scope 0 at $DIR/switch_int.rs:9:14: 9:21
+                                           // mir::Constant
+                                           // + span: $DIR/switch_int.rs:9:14: 9:17
+                                           // + literal: Const { ty: fn(i32) {foo}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb2: {
+          _0 = foo(const 0_i32) -> bb3;    // scope 0 at $DIR/switch_int.rs:8:14: 8:20
+                                           // mir::Constant
+                                           // + span: $DIR/switch_int.rs:8:14: 8:17
+                                           // + literal: Const { ty: fn(i32) {foo}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb3: {
+          StorageDead(_1);                 // scope 0 at $DIR/switch_int.rs:11:1: 11:2
+          return;                          // scope 0 at $DIR/switch_int.rs:11:2: 11:2
+      }
+  }
+  
index 9e7c73404487ab939712dd9ea93cace62a006c8d..d7319eca18e2d107b913812a77ae5bfa1a996768 100644 (file)
@@ -2,7 +2,7 @@
 fn foo(_: i32) { }
 
 // EMIT_MIR switch_int.main.ConstProp.diff
-// EMIT_MIR switch_int.main.SimplifyBranches-after-const-prop.diff
+// EMIT_MIR switch_int.main.SimplifyConstCondition-after-const-prop.diff
 fn main() {
     match 1 {
         1 => foo(0),
index 02221c4cf4a1f5574fa844ea6d927b1673b14e5a..ca298e9211d4864400aa0116975c4c86ad5c9f04 100644 (file)
@@ -11,7 +11,7 @@ pub enum ViewportPercentageLength {
 }
 
 // EMIT_MIR early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
-// EMIT_MIR early_otherwise_branch_68867.try_sum EarlyOtherwiseBranch.before SimplifyBranches-final.after
+// EMIT_MIR early_otherwise_branch_68867.try_sum EarlyOtherwiseBranch.before SimplifyConstCondition-final.after
 #[no_mangle]
 pub extern "C" fn try_sum(
     x: &ViewportPercentageLength,
diff --git a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyBranches-final.after.diff b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyBranches-final.after.diff
deleted file mode 100644 (file)
index f23d035..0000000
+++ /dev/null
@@ -1,300 +0,0 @@
-- // MIR for `try_sum` before EarlyOtherwiseBranch
-+ // MIR for `try_sum` after SimplifyBranches-final
-  
-  fn try_sum(_1: &ViewportPercentageLength, _2: &ViewportPercentageLength) -> Result<ViewportPercentageLength, ()> {
-      debug x => _1;                       // in scope 0 at $DIR/early_otherwise_branch_68867.rs:17:5: 17:6
-      debug other => _2;                   // in scope 0 at $DIR/early_otherwise_branch_68867.rs:18:5: 18:10
-      let mut _0: std::result::Result<ViewportPercentageLength, ()>; // return place in scope 0 at $DIR/early_otherwise_branch_68867.rs:19:6: 19:42
-      let mut _3: ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
-      let mut _4: (&ViewportPercentageLength, &ViewportPercentageLength); // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
-      let mut _5: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:15: 21:16
-      let mut _6: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:18: 21:23
-      let mut _7: isize;                   // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30
-      let mut _8: isize;                   // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30
-      let mut _9: isize;                   // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:23: 24:34
-      let mut _10: isize;                  // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:23: 25:34
-      let mut _11: isize;                  // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18
-      let _12: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17
-      let _13: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29
-      let mut _14: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49
-      let mut _15: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:41
-      let mut _16: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:49
-      let _17: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17
-      let _18: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29
-      let mut _19: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49
-      let mut _20: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41
-      let mut _21: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49
-      let _22: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19
-      let _23: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33
-      let mut _24: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55
-      let mut _25: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:47
-      let mut _26: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:50: 24:55
-      let _27: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19
-      let _28: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33
-      let mut _29: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55
-      let mut _30: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47
-      let mut _31: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55
-      let mut _32: !;                      // in scope 0 at $DIR/early_otherwise_branch_68867.rs:26:14: 26:28
-      let mut _33: ();                     // in scope 0 at $DIR/early_otherwise_branch_68867.rs:26:25: 26:27
-+     let mut _34: isize;                  // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30
-+     let mut _35: bool;                   // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30
-      scope 1 {
--         debug one => _12;                // in scope 1 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17
--         debug other => _13;              // in scope 1 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29
-+         debug one => _15;                // in scope 1 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17
-+         debug other => _16;              // in scope 1 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29
-      }
-      scope 2 {
--         debug one => _17;                // in scope 2 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17
--         debug other => _18;              // in scope 2 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29
-+         debug one => _20;                // in scope 2 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17
-+         debug other => _21;              // in scope 2 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29
-      }
-      scope 3 {
--         debug one => _22;                // in scope 3 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19
--         debug other => _23;              // in scope 3 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33
-+         debug one => _25;                // in scope 3 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19
-+         debug other => _26;              // in scope 3 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33
-      }
-      scope 4 {
--         debug one => _27;                // in scope 4 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19
--         debug other => _28;              // in scope 4 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33
-+         debug one => _30;                // in scope 4 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19
-+         debug other => _31;              // in scope 4 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33
-      }
-  
-      bb0: {
--         StorageLive(_3);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
--         StorageLive(_4);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
--         StorageLive(_5);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:15: 21:16
--         _5 = _1;                         // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:15: 21:16
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:15: 21:16
-+         (_4.0: &ViewportPercentageLength) = _1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:15: 21:16
-          StorageLive(_6);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:18: 21:23
-          _6 = _2;                         // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:18: 21:23
--         (_4.0: &ViewportPercentageLength) = move _5; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
-          (_4.1: &ViewportPercentageLength) = move _6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
-          StorageDead(_6);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24
--         StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24
-          _11 = discriminant((*(_4.0: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
--         switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
-+         StorageLive(_34);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
-+         _34 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
-+         StorageLive(_35);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
-+         _35 = Ne(_34, _11);              // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
-+         StorageDead(_34);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
-+         switchInt(move _35) -> [false: bb7, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
-      }
-  
-      bb1: {
--         _7 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
--         switchInt(move _7) -> [0_isize: bb6, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
--     }
-- 
--     bb2: {
-+         StorageDead(_35);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:25: 26:27
-          StorageLive(_33);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:25: 26:27
--         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:21: 26:28
-          discriminant(_0) = 1;            // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:21: 26:28
-          StorageDead(_33);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:27: 26:28
--         StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:6: 27:7
--         StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:1: 28:2
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:6: 27:7
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:1: 28:2
-          return;                          // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:2: 28:2
-      }
-  
-+     bb2: {
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17
-+         _15 = (((*(_4.0: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29
-+         _16 = (((*(_4.1: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29
-+         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49
-+         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:41
-+         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:41
-+         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:49
-+         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:49
-+         ((((_0 as Ok).0: ViewportPercentageLength) as Vw).0: f32) = Add(move _15, move _16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49
-+         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:48: 22:49
-+         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:48: 22:49
-+         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:35: 22:50
-+         discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 0; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:35: 22:50
-+         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
-+         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
-+     }
-+ 
-      bb3: {
--         _8 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
--         switchInt(move _8) -> [1_isize: bb7, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17
-+         _20 = (((*(_4.0: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29
-+         _21 = (((*(_4.1: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29
-+         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49
-+         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41
-+         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41
-+         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49
-+         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49
-+         ((((_0 as Ok).0: ViewportPercentageLength) as Vh).0: f32) = Add(move _20, move _21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49
-+         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49
-+         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49
-+         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50
-+         discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 1; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50
-+         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
-+         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
-      }
-  
-      bb4: {
--         _9 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
--         switchInt(move _9) -> [2_isize: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19
-+         _25 = (((*(_4.0: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33
-+         _26 = (((*(_4.1: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33
-+         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55
-+         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:47
-+         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:47
-+         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:50: 24:55
-+         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:50: 24:55
-+         ((((_0 as Ok).0: ViewportPercentageLength) as Vmin).0: f32) = Add(move _25, move _26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55
-+         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:54: 24:55
-+         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:54: 24:55
-+         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:39: 24:56
-+         discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 2; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:39: 24:56
-+         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
-+         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
-      }
-  
-      bb5: {
--         _10 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
--         switchInt(move _10) -> [3_isize: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19
-+         _30 = (((*(_4.0: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33
-+         _31 = (((*(_4.1: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33
-+         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55
-+         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47
-+         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47
-+         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55
-+         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55
-+         ((((_0 as Ok).0: ViewportPercentageLength) as Vmax).0: f32) = Add(move _30, move _31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55
-+         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55
-+         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55
-+         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56
-+         discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 3; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56
-+         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
-+         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
-      }
-  
-      bb6: {
--         StorageLive(_12);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17
--         _12 = (((*(_4.0: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17
--         StorageLive(_13);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29
--         _13 = (((*(_4.1: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29
--         StorageLive(_14);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49
--         StorageLive(_15);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:41
--         _15 = _12;                       // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:41
--         StorageLive(_16);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:49
--         _16 = _13;                       // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:49
--         _14 = Add(move _15, move _16);   // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49
--         StorageDead(_16);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:48: 22:49
--         StorageDead(_15);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:48: 22:49
--         ((_3 as Vw).0: f32) = move _14;  // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:35: 22:50
--         discriminant(_3) = 0;            // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:35: 22:50
--         StorageDead(_14);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
--         StorageDead(_13);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
--         StorageDead(_12);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
--         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7
-+         discriminant(_0) = 0;            // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:6: 27:7
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:1: 28:2
-+         return;                          // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:2: 28:2
-      }
-  
-      bb7: {
--         StorageLive(_17);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17
--         _17 = (((*(_4.0: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17
--         StorageLive(_18);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29
--         _18 = (((*(_4.1: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29
--         StorageLive(_19);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49
--         StorageLive(_20);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41
--         _20 = _17;                       // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41
--         StorageLive(_21);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49
--         _21 = _18;                       // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49
--         _19 = Add(move _20, move _21);   // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49
--         StorageDead(_21);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49
--         StorageDead(_20);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49
--         ((_3 as Vh).0: f32) = move _19;  // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50
--         discriminant(_3) = 1;            // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50
--         StorageDead(_19);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
--         StorageDead(_18);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
--         StorageDead(_17);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
--         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
--     }
-- 
--     bb8: {
--         StorageLive(_22);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19
--         _22 = (((*(_4.0: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19
--         StorageLive(_23);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33
--         _23 = (((*(_4.1: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33
--         StorageLive(_24);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55
--         StorageLive(_25);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:47
--         _25 = _22;                       // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:47
--         StorageLive(_26);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:50: 24:55
--         _26 = _23;                       // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:50: 24:55
--         _24 = Add(move _25, move _26);   // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55
--         StorageDead(_26);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:54: 24:55
--         StorageDead(_25);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:54: 24:55
--         ((_3 as Vmin).0: f32) = move _24; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:39: 24:56
--         discriminant(_3) = 2;            // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:39: 24:56
--         StorageDead(_24);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
--         StorageDead(_23);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
--         StorageDead(_22);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
--         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
--     }
-- 
--     bb9: {
--         StorageLive(_27);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19
--         _27 = (((*(_4.0: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19
--         StorageLive(_28);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33
--         _28 = (((*(_4.1: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33
--         StorageLive(_29);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55
--         StorageLive(_30);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47
--         _30 = _27;                       // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47
--         StorageLive(_31);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55
--         _31 = _28;                       // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55
--         _29 = Add(move _30, move _31);   // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55
--         StorageDead(_31);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55
--         StorageDead(_30);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55
--         ((_3 as Vmax).0: f32) = move _29; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56
--         discriminant(_3) = 3;            // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56
--         StorageDead(_29);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
--         StorageDead(_28);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
--         StorageDead(_27);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
--         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
--     }
-- 
--     bb10: {
--         ((_0 as Ok).0: ViewportPercentageLength) = move _3; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7
--         discriminant(_0) = 0;            // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7
--         StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:6: 27:7
--         StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:1: 28:2
--         return;                          // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:2: 28:2
-+         StorageDead(_35);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30
-+         switchInt(_11) -> [0_isize: bb2, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30
-      }
-  }
-  
diff --git a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff
new file mode 100644 (file)
index 0000000..4429403
--- /dev/null
@@ -0,0 +1,300 @@
+- // MIR for `try_sum` before EarlyOtherwiseBranch
++ // MIR for `try_sum` after SimplifyConstCondition-final
+  
+  fn try_sum(_1: &ViewportPercentageLength, _2: &ViewportPercentageLength) -> Result<ViewportPercentageLength, ()> {
+      debug x => _1;                       // in scope 0 at $DIR/early_otherwise_branch_68867.rs:17:5: 17:6
+      debug other => _2;                   // in scope 0 at $DIR/early_otherwise_branch_68867.rs:18:5: 18:10
+      let mut _0: std::result::Result<ViewportPercentageLength, ()>; // return place in scope 0 at $DIR/early_otherwise_branch_68867.rs:19:6: 19:42
+      let mut _3: ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
+      let mut _4: (&ViewportPercentageLength, &ViewportPercentageLength); // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
+      let mut _5: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:15: 21:16
+      let mut _6: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:18: 21:23
+      let mut _7: isize;                   // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30
+      let mut _8: isize;                   // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30
+      let mut _9: isize;                   // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:23: 24:34
+      let mut _10: isize;                  // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:23: 25:34
+      let mut _11: isize;                  // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18
+      let _12: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17
+      let _13: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29
+      let mut _14: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49
+      let mut _15: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:41
+      let mut _16: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:49
+      let _17: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17
+      let _18: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29
+      let mut _19: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49
+      let mut _20: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41
+      let mut _21: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49
+      let _22: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19
+      let _23: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33
+      let mut _24: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55
+      let mut _25: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:47
+      let mut _26: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:50: 24:55
+      let _27: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19
+      let _28: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33
+      let mut _29: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55
+      let mut _30: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47
+      let mut _31: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55
+      let mut _32: !;                      // in scope 0 at $DIR/early_otherwise_branch_68867.rs:26:14: 26:28
+      let mut _33: ();                     // in scope 0 at $DIR/early_otherwise_branch_68867.rs:26:25: 26:27
++     let mut _34: isize;                  // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30
++     let mut _35: bool;                   // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30
+      scope 1 {
+-         debug one => _12;                // in scope 1 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17
+-         debug other => _13;              // in scope 1 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29
++         debug one => _15;                // in scope 1 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17
++         debug other => _16;              // in scope 1 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29
+      }
+      scope 2 {
+-         debug one => _17;                // in scope 2 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17
+-         debug other => _18;              // in scope 2 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29
++         debug one => _20;                // in scope 2 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17
++         debug other => _21;              // in scope 2 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29
+      }
+      scope 3 {
+-         debug one => _22;                // in scope 3 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19
+-         debug other => _23;              // in scope 3 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33
++         debug one => _25;                // in scope 3 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19
++         debug other => _26;              // in scope 3 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33
+      }
+      scope 4 {
+-         debug one => _27;                // in scope 4 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19
+-         debug other => _28;              // in scope 4 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33
++         debug one => _30;                // in scope 4 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19
++         debug other => _31;              // in scope 4 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33
+      }
+  
+      bb0: {
+-         StorageLive(_3);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
+-         StorageLive(_4);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
+-         StorageLive(_5);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:15: 21:16
+-         _5 = _1;                         // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:15: 21:16
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:15: 21:16
++         (_4.0: &ViewportPercentageLength) = _1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:15: 21:16
+          StorageLive(_6);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:18: 21:23
+          _6 = _2;                         // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:18: 21:23
+-         (_4.0: &ViewportPercentageLength) = move _5; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
+          (_4.1: &ViewportPercentageLength) = move _6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
+          StorageDead(_6);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24
+-         StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24
+          _11 = discriminant((*(_4.0: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
+-         switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
++         StorageLive(_34);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
++         _34 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
++         StorageLive(_35);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
++         _35 = Ne(_34, _11);              // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
++         StorageDead(_34);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
++         switchInt(move _35) -> [false: bb7, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
+      }
+  
+      bb1: {
+-         _7 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
+-         switchInt(move _7) -> [0_isize: bb6, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
+-     }
+- 
+-     bb2: {
++         StorageDead(_35);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:25: 26:27
+          StorageLive(_33);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:25: 26:27
+-         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:21: 26:28
+          discriminant(_0) = 1;            // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:21: 26:28
+          StorageDead(_33);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:27: 26:28
+-         StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:6: 27:7
+-         StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:1: 28:2
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:6: 27:7
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:1: 28:2
+          return;                          // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:2: 28:2
+      }
+  
++     bb2: {
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17
++         _15 = (((*(_4.0: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29
++         _16 = (((*(_4.1: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29
++         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49
++         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:41
++         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:41
++         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:49
++         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:49
++         ((((_0 as Ok).0: ViewportPercentageLength) as Vw).0: f32) = Add(move _15, move _16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49
++         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:48: 22:49
++         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:48: 22:49
++         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:35: 22:50
++         discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 0; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:35: 22:50
++         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
++         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
++     }
++ 
+      bb3: {
+-         _8 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
+-         switchInt(move _8) -> [1_isize: bb7, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17
++         _20 = (((*(_4.0: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29
++         _21 = (((*(_4.1: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29
++         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49
++         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41
++         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41
++         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49
++         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49
++         ((((_0 as Ok).0: ViewportPercentageLength) as Vh).0: f32) = Add(move _20, move _21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49
++         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49
++         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49
++         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50
++         discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 1; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50
++         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
++         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
+      }
+  
+      bb4: {
+-         _9 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
+-         switchInt(move _9) -> [2_isize: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19
++         _25 = (((*(_4.0: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33
++         _26 = (((*(_4.1: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33
++         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55
++         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:47
++         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:47
++         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:50: 24:55
++         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:50: 24:55
++         ((((_0 as Ok).0: ViewportPercentageLength) as Vmin).0: f32) = Add(move _25, move _26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55
++         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:54: 24:55
++         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:54: 24:55
++         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:39: 24:56
++         discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 2; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:39: 24:56
++         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
++         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
+      }
+  
+      bb5: {
+-         _10 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
+-         switchInt(move _10) -> [3_isize: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19
++         _30 = (((*(_4.0: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33
++         _31 = (((*(_4.1: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33
++         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55
++         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47
++         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47
++         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55
++         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55
++         ((((_0 as Ok).0: ViewportPercentageLength) as Vmax).0: f32) = Add(move _30, move _31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55
++         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55
++         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55
++         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56
++         discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 3; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56
++         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
++         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
+      }
+  
+      bb6: {
+-         StorageLive(_12);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17
+-         _12 = (((*(_4.0: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17
+-         StorageLive(_13);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29
+-         _13 = (((*(_4.1: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29
+-         StorageLive(_14);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49
+-         StorageLive(_15);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:41
+-         _15 = _12;                       // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:41
+-         StorageLive(_16);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:49
+-         _16 = _13;                       // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:49
+-         _14 = Add(move _15, move _16);   // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49
+-         StorageDead(_16);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:48: 22:49
+-         StorageDead(_15);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:48: 22:49
+-         ((_3 as Vw).0: f32) = move _14;  // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:35: 22:50
+-         discriminant(_3) = 0;            // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:35: 22:50
+-         StorageDead(_14);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
+-         StorageDead(_13);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
+-         StorageDead(_12);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
+-         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7
++         discriminant(_0) = 0;            // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:6: 27:7
++         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:1: 28:2
++         return;                          // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:2: 28:2
+      }
+  
+      bb7: {
+-         StorageLive(_17);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17
+-         _17 = (((*(_4.0: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17
+-         StorageLive(_18);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29
+-         _18 = (((*(_4.1: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29
+-         StorageLive(_19);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49
+-         StorageLive(_20);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41
+-         _20 = _17;                       // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41
+-         StorageLive(_21);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49
+-         _21 = _18;                       // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49
+-         _19 = Add(move _20, move _21);   // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49
+-         StorageDead(_21);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49
+-         StorageDead(_20);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49
+-         ((_3 as Vh).0: f32) = move _19;  // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50
+-         discriminant(_3) = 1;            // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50
+-         StorageDead(_19);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
+-         StorageDead(_18);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
+-         StorageDead(_17);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
+-         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
+-     }
+- 
+-     bb8: {
+-         StorageLive(_22);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19
+-         _22 = (((*(_4.0: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19
+-         StorageLive(_23);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33
+-         _23 = (((*(_4.1: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33
+-         StorageLive(_24);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55
+-         StorageLive(_25);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:47
+-         _25 = _22;                       // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:47
+-         StorageLive(_26);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:50: 24:55
+-         _26 = _23;                       // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:50: 24:55
+-         _24 = Add(move _25, move _26);   // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55
+-         StorageDead(_26);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:54: 24:55
+-         StorageDead(_25);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:54: 24:55
+-         ((_3 as Vmin).0: f32) = move _24; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:39: 24:56
+-         discriminant(_3) = 2;            // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:39: 24:56
+-         StorageDead(_24);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
+-         StorageDead(_23);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
+-         StorageDead(_22);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
+-         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
+-     }
+- 
+-     bb9: {
+-         StorageLive(_27);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19
+-         _27 = (((*(_4.0: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19
+-         StorageLive(_28);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33
+-         _28 = (((*(_4.1: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33
+-         StorageLive(_29);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55
+-         StorageLive(_30);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47
+-         _30 = _27;                       // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47
+-         StorageLive(_31);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55
+-         _31 = _28;                       // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55
+-         _29 = Add(move _30, move _31);   // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55
+-         StorageDead(_31);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55
+-         StorageDead(_30);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55
+-         ((_3 as Vmax).0: f32) = move _29; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56
+-         discriminant(_3) = 3;            // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56
+-         StorageDead(_29);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
+-         StorageDead(_28);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
+-         StorageDead(_27);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
+-         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
+-     }
+- 
+-     bb10: {
+-         ((_0 as Ok).0: ViewportPercentageLength) = move _3; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7
+-         discriminant(_0) = 0;            // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7
+-         StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:6: 27:7
+-         StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:1: 28:2
+-         return;                          // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:2: 28:2
++         StorageDead(_35);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30
++         switchInt(_11) -> [0_isize: bb2, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30
+      }
+  }
+  
index 4d9e022d825559f69e6d7e4472a98da4412dbdbd..045bc720ca70126c9616819fbbe9da04d270c810 100644 (file)
 +         _4 = hide_foo() -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
                                            // mir::Constant
                                            // + span: $DIR/issue-78442.rs:11:5: 11:13
-                                           // + literal: Const { ty: fn() -> impl std::ops::Fn<()> {hide_foo}, val: Value(Scalar(<ZST>)) }
+                                           // + literal: Const { ty: fn() -> impl Fn() {hide_foo}, val: Value(Scalar(<ZST>)) }
       }
   
       bb1: {
           _3 = &_4;                        // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
           StorageLive(_5);                 // scope 0 at $DIR/issue-78442.rs:11:5: 11:17
--         _2 = <impl Fn<()> as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17
+-         _2 = <impl Fn() as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17
 -                                          // mir::Constant
 -                                          // + span: $DIR/issue-78442.rs:11:5: 11:15
--                                          // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl std::ops::Fn<()>, ()) -> <impl std::ops::Fn<()> as std::ops::FnOnce<()>>::Output {<impl std::ops::Fn<()> as std::ops::Fn<()>>::call}, val: Value(Scalar(<ZST>)) }
+-                                          // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn(), ()) -> <impl Fn() as std::ops::FnOnce<()>>::Output {<impl Fn() as std::ops::Fn<()>>::call}, val: Value(Scalar(<ZST>)) }
 +         _2 = move (*_3)() -> [return: bb5, unwind: bb3]; // scope 1 at $DIR/issue-78442.rs:11:5: 11:17
       }
   
index 45b552cc6340a06d8d40c3545f4227cc57b2609d..3190db52286bc9f0755045bf2ed904c6d0848dd0 100644 (file)
@@ -5,8 +5,8 @@
       debug _baz => _1;                    // in scope 0 at $DIR/issue-78442.rs:9:5: 9:9
       let mut _0: ();                      // return place in scope 0 at $DIR/issue-78442.rs:10:3: 10:3
       let _2: ();                          // in scope 0 at $DIR/issue-78442.rs:11:5: 11:17
--     let mut _3: &impl std::ops::Fn<()>;  // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15
--     let _4: impl std::ops::Fn<()>;       // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15
+-     let mut _3: &impl Fn();              // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15
+-     let _4: impl Fn();                   // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15
 +     let mut _3: &fn() {foo};             // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15
 +     let _4: fn() {foo};                  // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15
       let mut _5: ();                      // in scope 0 at $DIR/issue-78442.rs:11:5: 11:17
           _4 = hide_foo() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
                                            // mir::Constant
                                            // + span: $DIR/issue-78442.rs:11:5: 11:13
-                                           // + literal: Const { ty: fn() -> impl std::ops::Fn<()> {hide_foo}, val: Value(Scalar(<ZST>)) }
+                                           // + literal: Const { ty: fn() -> impl Fn() {hide_foo}, val: Value(Scalar(<ZST>)) }
       }
   
       bb1: {
           _3 = &_4;                        // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
           StorageLive(_5);                 // scope 0 at $DIR/issue-78442.rs:11:5: 11:17
           nop;                             // scope 0 at $DIR/issue-78442.rs:11:5: 11:17
-          _2 = <impl Fn<()> as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17
+          _2 = <impl Fn() as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17
                                            // mir::Constant
                                            // + span: $DIR/issue-78442.rs:11:5: 11:15
-                                           // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl std::ops::Fn<()>, ()) -> <impl std::ops::Fn<()> as std::ops::FnOnce<()>>::Output {<impl std::ops::Fn<()> as std::ops::Fn<()>>::call}, val: Value(Scalar(<ZST>)) }
+                                           // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn(), ()) -> <impl Fn() as std::ops::FnOnce<()>>::Output {<impl Fn() as std::ops::Fn<()>>::call}, val: Value(Scalar(<ZST>)) }
       }
   
       bb2: {
diff --git a/src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff b/src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff
deleted file mode 100644 (file)
index def6f83..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-- // MIR for `main` before SimplifyBranches-after-const-prop
-+ // MIR for `main` after SimplifyBranches-after-const-prop
-  
-  fn main() -> () {
-      let mut _0: ();                      // return place in scope 0 at $DIR/simplify_if.rs:5:11: 5:11
-      let mut _1: bool;                    // in scope 0 at $DIR/simplify_if.rs:6:8: 6:13
-      let _2: ();                          // in scope 0 at $DIR/simplify_if.rs:7:9: 7:15
-  
-      bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/simplify_if.rs:6:8: 6:13
-          _1 = const false;                // scope 0 at $DIR/simplify_if.rs:6:8: 6:13
--         switchInt(const false) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/simplify_if.rs:6:8: 6:13
-+         goto -> bb3;                     // scope 0 at $DIR/simplify_if.rs:6:8: 6:13
-      }
-  
-      bb1: {
-          StorageLive(_2);                 // scope 0 at $DIR/simplify_if.rs:7:9: 7:15
-          _2 = noop() -> bb2;              // scope 0 at $DIR/simplify_if.rs:7:9: 7:15
-                                           // mir::Constant
-                                           // + span: $DIR/simplify_if.rs:7:9: 7:13
-                                           // + literal: Const { ty: fn() {noop}, val: Value(Scalar(<ZST>)) }
-      }
-  
-      bb2: {
-          StorageDead(_2);                 // scope 0 at $DIR/simplify_if.rs:7:15: 7:16
-          nop;                             // scope 0 at $DIR/simplify_if.rs:6:14: 8:6
-          goto -> bb4;                     // scope 0 at $DIR/simplify_if.rs:6:5: 8:6
-      }
-  
-      bb3: {
-          nop;                             // scope 0 at $DIR/simplify_if.rs:8:6: 8:6
-          goto -> bb4;                     // scope 0 at $DIR/simplify_if.rs:6:5: 8:6
-      }
-  
-      bb4: {
-          StorageDead(_1);                 // scope 0 at $DIR/simplify_if.rs:8:5: 8:6
-          return;                          // scope 0 at $DIR/simplify_if.rs:9:2: 9:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff b/src/test/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff
new file mode 100644 (file)
index 0000000..d11c70b
--- /dev/null
@@ -0,0 +1,40 @@
+- // MIR for `main` before SimplifyConstCondition-after-const-prop
++ // MIR for `main` after SimplifyConstCondition-after-const-prop
+  
+  fn main() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/simplify_if.rs:5:11: 5:11
+      let mut _1: bool;                    // in scope 0 at $DIR/simplify_if.rs:6:8: 6:13
+      let _2: ();                          // in scope 0 at $DIR/simplify_if.rs:7:9: 7:15
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/simplify_if.rs:6:8: 6:13
+          _1 = const false;                // scope 0 at $DIR/simplify_if.rs:6:8: 6:13
+-         switchInt(const false) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/simplify_if.rs:6:8: 6:13
++         goto -> bb3;                     // scope 0 at $DIR/simplify_if.rs:6:8: 6:13
+      }
+  
+      bb1: {
+          StorageLive(_2);                 // scope 0 at $DIR/simplify_if.rs:7:9: 7:15
+          _2 = noop() -> bb2;              // scope 0 at $DIR/simplify_if.rs:7:9: 7:15
+                                           // mir::Constant
+                                           // + span: $DIR/simplify_if.rs:7:9: 7:13
+                                           // + literal: Const { ty: fn() {noop}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb2: {
+          StorageDead(_2);                 // scope 0 at $DIR/simplify_if.rs:7:15: 7:16
+          nop;                             // scope 0 at $DIR/simplify_if.rs:6:14: 8:6
+          goto -> bb4;                     // scope 0 at $DIR/simplify_if.rs:6:5: 8:6
+      }
+  
+      bb3: {
+          nop;                             // scope 0 at $DIR/simplify_if.rs:8:6: 8:6
+          goto -> bb4;                     // scope 0 at $DIR/simplify_if.rs:6:5: 8:6
+      }
+  
+      bb4: {
+          StorageDead(_1);                 // scope 0 at $DIR/simplify_if.rs:8:5: 8:6
+          return;                          // scope 0 at $DIR/simplify_if.rs:9:2: 9:2
+      }
+  }
+  
index 67b2027b710c977735ad29b2fdfb4de65ee8d453..2d093d9266bb516667a19505621b36a27aedfcdb 100644 (file)
@@ -1,7 +1,7 @@
 #[inline(never)]
 fn noop() {}
 
-// EMIT_MIR simplify_if.main.SimplifyBranches-after-const-prop.diff
+// EMIT_MIR simplify_if.main.SimplifyConstCondition-after-const-prop.diff
 fn main() {
     if false {
         noop();
index 8722d9e10d91d204fa457b5afc93eb1b3f1f7e42..3c4df3533e147f512a481954d373fdd95e20214a 100644 (file)
@@ -1,5 +1,11 @@
 # needs-profiler-support
 
+# Rust coverage maps support LLVM Coverage Mapping Format versions 5 and 6,
+# corresponding with LLVM versions 12 and 13, respectively.
+# When upgrading LLVM versions, consider whether to enforce a minimum LLVM
+# version during testing, with an additional directive at the top of this file
+# that sets, for example: `min-llvm-version: 12.0`
+
 -include ../coverage/coverage_tools.mk
 
 BASEDIR=../coverage-llvmir
index 4adf02bee0af47eaf85a133e0871c87f6746695a..9122e0406c2efc49ce6d7131de87b01d3b5264b5 100644 (file)
@@ -1,6 +1,12 @@
 # needs-profiler-support
 # ignore-windows-gnu
 
+# Rust coverage maps support LLVM Coverage Mapping Format versions 5 and 6,
+# corresponding with LLVM versions 12 and 13, respectively.
+# When upgrading LLVM versions, consider whether to enforce a minimum LLVM
+# version during testing, with an additional directive at the top of this file
+# that sets, for example: `min-llvm-version: 12.0`
+
 # FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
 # properly. Since we only have GCC on the CI ignore the test for now.
 
@@ -115,6 +121,7 @@ endif
        "$(LLVM_BIN_DIR)"/llvm-cov show \
                        $(DEBUG_FLAG) \
                        $(LLVM_COV_IGNORE_FILES) \
+                       --compilation-dir=. \
                        --Xdemangler="$(RUST_DEMANGLER)" \
                        --show-line-counts-or-regions \
                        --instr-profile="$(TMPDIR)"/$@.profdata \
index 4ce0ed1a4b8fd4f5c647a64c2c6940d2650288d1..8910cbbbb256c7c14cccd904c548591919a52576 100644 (file)
@@ -1,5 +1,6 @@
-// This test is to ensure that the anchors (`§`) have the expected color.
+// This test is to ensure that the anchors (`§`) have the expected color and position.
 goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html
+show-text: true
 
 // This is needed to ensure that the text color is computed.
 show-text: true
@@ -27,3 +28,47 @@ assert-css: ("h2#implementations a.anchor", {"color": "rgb(0, 0, 0)"})
 // Same thing with the impl block title.
 move-cursor-to: "#impl"
 assert-css: ("#impl a.anchor", {"color": "rgb(0, 0, 0)"})
+
+// Now we check the positions: only the first heading of the top doc comment should
+// have a different position.
+move-cursor-to: ".top-doc .docblock .section-header:first-child"
+assert-css: (
+    ".top-doc .docblock .section-header:first-child > a::before",
+    {"left": "-10px", "padding-right": "10px"}
+)
+// We also check that the heading itself has a different indent.
+assert-css: (".top-doc .docblock .section-header:first-child", {"margin-left": "15px"})
+
+move-cursor-to: ".top-doc .docblock .section-header:not(:first-child)"
+assert-css: (
+    ".top-doc .docblock .section-header:not(:first-child) > a::before",
+    {"left": "-25px", "padding-right": "10px"}
+)
+assert-css: (".top-doc .docblock .section-header:not(:first-child)", {"margin-left": "0px"})
+
+// Now let's check some other docblock headings...
+// First the impl block docs.
+move-cursor-to: "#title-for-struct-impl-doc"
+assert-css: (
+    "#title-for-struct-impl-doc > a::before",
+    {"left": "-25px", "padding-right": "10px"}
+)
+assert-css: ("#title-for-struct-impl-doc", {"margin-left": "0px"})
+// Now a method docs.
+move-cursor-to: "#title-for-struct-impl-item-doc"
+assert-css: (
+    "#title-for-struct-impl-item-doc > a::before",
+    {"left": "-25px", "padding-right": "10px"}
+)
+assert-css: ("#title-for-struct-impl-item-doc", {"margin-left": "0px"})
+
+// Finally, we want to ensure that if the first element of the doc block isn't a heading,
+// if there is a heading afterwards, it won't have the indent.
+goto: file://|DOC_PATH|/test_docs/enum.WhoLetTheDogOut.html
+
+move-cursor-to: ".top-doc .docblock .section-header"
+assert-css: (
+    ".top-doc .docblock .section-header > a::before",
+    {"left": "-25px", "padding-right": "10px"}
+)
+assert-css: (".top-doc .docblock .section-header", {"margin-left": "0px"})
index a098dbd9f129bf8f5dd0dedaaf718ba4a49f0fa1..7a8f8ca5311adf90a4ba46a13243115f901c775f 100644 (file)
@@ -1,9 +1,11 @@
 goto: file://|DOC_PATH|/test_docs/index.html
+show-text: true
 write: (".search-input", "test")
 // Waiting for the search results to appear...
 wait-for: "#titles"
 assert-text: ("#results .externcrate", "test_docs")
-text: (".search-input", "")
+
+goto: file://|DOC_PATH|/test_docs/index.html
 // We now want to change the crate filter.
 click: "#crate-search"
 // We select "lib2" option then press enter to change the filter.
index 458bcc4780c6c5abfa909b611982fd7439e8b85b..9b37703dded4b7acf9e494019ecc200c512ad997 100644 (file)
@@ -47,6 +47,8 @@ fn as_ref(&self) -> &str {
 }
 
 /// Just a normal enum.
+///
+/// # title!
 #[doc(alias = "ThisIsAnAlias")]
 pub enum WhoLetTheDogOut {
     /// Woof!
index 418c9f8d0edd02dd969fb56458f1002c652aee6e..1ee1c34aa1562472b8892428ba001b4835b14c60 100644 (file)
@@ -1,6 +1,8 @@
 #![crate_type = "lib"]
 #![crate_name = "summaries"]
 
+#![allow(rustdoc::broken_intra_doc_links)]
+
 //! This *summary* has a [link], [`code`], and [`Sidebar2`] intra-doc.
 //!
 //! This is the second paragraph. It should not be rendered.
diff --git a/src/test/rustdoc-ui/auxiliary/overflow.rs b/src/test/rustdoc-ui/auxiliary/overflow.rs
new file mode 100644 (file)
index 0000000..ff65936
--- /dev/null
@@ -0,0 +1,20 @@
+pub struct B0;
+pub struct B1;
+use std::ops::Shl;
+use std::ops::Sub;
+pub type Shleft<A, B> = <A as Shl<B>>::Output;
+pub type Sub1<A> = <A as Sub<B1>>::Output;
+pub struct UInt<U, B> {
+    pub(crate) msb: U,
+    pub(crate) lsb: B,
+}
+impl<U, B, Ur, Br> Shl<UInt<Ur, Br>> for UInt<U, B>
+where
+    UInt<Ur, Br>: Sub<B1>,
+    UInt<UInt<U, B>, B0>: Shl<Sub1<UInt<Ur, Br>>>,
+{
+    type Output = Shleft<UInt<UInt<U, B>, B0>, Sub1<UInt<Ur, Br>>>;
+    fn shl(self, rhs: UInt<Ur, Br>) -> Self::Output {
+        unimplemented!()
+    }
+}
index 5e390029dca33028ea7a0190bff3601e8f903142..30b32c511b5fa715c3099be9d530d9ee7d33b694 100644 (file)
@@ -1,9 +1,15 @@
+// Test that `--show-output` has an effect and `allow(unused)` can be overriden.
+
 // check-pass
-// compile-flags:-Zunstable-options --display-doctest-warnings --test
+// edition:2018
+// compile-flags:--test --test-args=--show-output
 // normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
 // normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
 
 /// ```
+/// #![warn(unused)]
 /// let x = 12;
+///
+/// fn foo(x: &std::fmt::Display) {}
 /// ```
 pub fn foo() {}
index 00467b9359eb231348834817ea423436f3a03ad3..f76dec1c85008b306be771406c2827d36686da8b 100644 (file)
@@ -1,24 +1,58 @@
 
 running 1 test
-test $DIR/display-output.rs - foo (line 6) ... ok
+test $DIR/display-output.rs - foo (line 9) ... ok
 
 successes:
 
----- $DIR/display-output.rs - foo (line 6) stdout ----
+---- $DIR/display-output.rs - foo (line 9) stdout ----
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/display-output.rs:13:12
+   |
+LL | fn foo(x: &std::fmt::Display) {}
+   |            ^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn std::fmt::Display`
+   |
+   = note: `#[warn(bare_trait_objects)]` on by default
+   = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+
 warning: unused variable: `x`
-  --> $DIR/display-output.rs:7:5
+  --> $DIR/display-output.rs:11:5
    |
 LL | let x = 12;
    |     ^ help: if this is intentional, prefix it with an underscore: `_x`
    |
-   = note: `#[warn(unused_variables)]` on by default
+note: the lint level is defined here
+  --> $DIR/display-output.rs:9:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
+
+warning: unused variable: `x`
+  --> $DIR/display-output.rs:13:8
+   |
+LL | fn foo(x: &std::fmt::Display) {}
+   |        ^ help: if this is intentional, prefix it with an underscore: `_x`
+
+warning: function is never used: `foo`
+  --> $DIR/display-output.rs:13:4
+   |
+LL | fn foo(x: &std::fmt::Display) {}
+   |    ^^^
+   |
+note: the lint level is defined here
+  --> $DIR/display-output.rs:9:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: `#[warn(dead_code)]` implied by `#[warn(unused)]`
 
-warning: 1 warning emitted
+warning: 4 warnings emitted
 
 
 
 successes:
-    $DIR/display-output.rs - foo (line 6)
+    $DIR/display-output.rs - foo (line 9)
 
 test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
 
diff --git a/src/test/rustdoc-ui/intra-doc/auxiliary/through-proc-macro-aux.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/through-proc-macro-aux.rs
new file mode 100644 (file)
index 0000000..5c4a01e
--- /dev/null
@@ -0,0 +1,20 @@
+// force-host
+// no-prefer-dynamic
+#![crate_type = "proc-macro"]
+#![crate_name="some_macros"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn first(_attr: TokenStream, item: TokenStream) -> TokenStream {
+    item // This doesn't erase the spans.
+}
+
+#[proc_macro_attribute]
+pub fn second(_attr: TokenStream, item: TokenStream) -> TokenStream {
+    // Make a new `TokenStream` to erase the spans:
+    let mut out: TokenStream = TokenStream::new();
+    out.extend(item);
+    out
+}
diff --git a/src/test/rustdoc-ui/intra-doc/through-proc-macro.rs b/src/test/rustdoc-ui/intra-doc/through-proc-macro.rs
new file mode 100644 (file)
index 0000000..7628c39
--- /dev/null
@@ -0,0 +1,18 @@
+// check-pass
+// aux-build:through-proc-macro-aux.rs
+// build-aux-docs
+
+// Ensure rustdoc doesn't panic on this code.
+
+#![warn(rustdoc::broken_intra_doc_links)]
+
+extern crate some_macros;
+
+#[some_macros::second]
+pub enum Boom {
+    /// [Oooops]
+    //~^ WARNING unresolved link to `Oooops`
+    Bam,
+}
+
+fn main() {}
diff --git a/src/test/rustdoc-ui/intra-doc/through-proc-macro.stderr b/src/test/rustdoc-ui/intra-doc/through-proc-macro.stderr
new file mode 100644 (file)
index 0000000..f0a7ed1
--- /dev/null
@@ -0,0 +1,15 @@
+warning: unresolved link to `Oooops`
+  --> $DIR/through-proc-macro.rs:13:10
+   |
+LL |     /// [Oooops]
+   |          ^^^^^^ no item named `Oooops` in scope
+   |
+note: the lint level is defined here
+  --> $DIR/through-proc-macro.rs:7:9
+   |
+LL | #![warn(rustdoc::broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: 1 warning emitted
+
diff --git a/src/test/rustdoc-ui/normalize-cycle.rs b/src/test/rustdoc-ui/normalize-cycle.rs
new file mode 100644 (file)
index 0000000..f48cad3
--- /dev/null
@@ -0,0 +1,25 @@
+// check-pass
+// Regresion test for <https://github.com/rust-lang/rust/issues/79459>.
+pub trait Query {}
+
+pub trait AsQuery {
+    type Query;
+}
+
+impl<T: Query> AsQuery for T {
+    type Query = T;
+}
+
+pub trait SelectDsl<Selection> {
+    type Output;
+}
+
+impl<T, Selection> SelectDsl<Selection> for T
+where
+    T: AsQuery,
+    T::Query: SelectDsl<Selection>,
+{
+    type Output = <T::Query as SelectDsl<Selection>>::Output;
+}
+
+pub type Select<Source, Selection> = <Source as SelectDsl<Selection>>::Output;
diff --git a/src/test/rustdoc-ui/normalize-overflow.rs b/src/test/rustdoc-ui/normalize-overflow.rs
new file mode 100644 (file)
index 0000000..0cdcc88
--- /dev/null
@@ -0,0 +1,3 @@
+// aux-crate:overflow=overflow.rs
+// check-pass
+// Regression test for <https://github.com/rust-lang/rust/issues/79506>.
diff --git a/src/test/rustdoc-ui/scrape-examples-ice.rs b/src/test/rustdoc-ui/scrape-examples-ice.rs
new file mode 100644 (file)
index 0000000..d629b62
--- /dev/null
@@ -0,0 +1,4 @@
+// compile-flags: -Z unstable-options --scrape-examples-output-path {{build-base}}/t.calls --scrape-examples-target-crate foobar
+// check-pass
+#![no_std]
+use core as _;
index 83631b89f281a49acc87017e34ff4428398f0074..172333d445d8533450b4dffb2050dea910fa7e15 100644 (file)
@@ -1,4 +1,7 @@
+#![feature(rustdoc_internals)]
+
 #![crate_name = "foo"]
+
 pub use std::fs::File;
 
 // @has 'foo/primitive.i16.html' '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementation'
index 920877028d06a45e4dab83f755f04b00b7cd1265..9ec089fd7ad1386437fa75f8e5a6331d2e6037ad 100644 (file)
@@ -1,3 +1,5 @@
+#![allow(rustdoc::invalid_rust_codeblocks)]
+
 // @has bad_codeblock_syntax/fn.foo.html
 // @has - '//*[@class="docblock"]' '\_'
 /// ```
index 0cb8e4230166ff0d2484afd7e8142479938bcce9..ca4179d403d691362100d0342f1380c6180ecadb 100644 (file)
@@ -2,6 +2,8 @@
 // aux-build:source_code.rs
 // build-aux-docs
 
+#![feature(rustdoc_internals)]
+
 #![crate_name = "foo"]
 
 extern crate source_code;
@@ -29,21 +31,20 @@ fn babar() {}
 // @has - '//a/@href' '/struct.String.html'
 // @has - '//a/@href' '/primitive.u32.html'
 // @has - '//a/@href' '/primitive.str.html'
-// @count - '//a[@href="../../src/foo/check-source-code-urls-to-def.rs.html#21"]' 5
+// @count - '//a[@href="../../src/foo/check-source-code-urls-to-def.rs.html#23"]' 5
 // @has - '//a[@href="../../source_code/struct.SourceCode.html"]' 'source_code::SourceCode'
 pub fn foo(a: u32, b: &str, c: String, d: Foo, e: bar::Bar, f: source_code::SourceCode) {
     let x = 12;
     let y: Foo = Foo;
     let z: Bar = bar::Bar { field: Foo };
     babar();
-    // @has - '//a[@href="../../src/foo/check-source-code-urls-to-def.rs.html#24"]' 'hello'
+    // @has - '//a[@href="../../src/foo/check-source-code-urls-to-def.rs.html#26"]' 'hello'
     y.hello();
 }
 
 // @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#14-16"]' 'bar::sub::Trait'
 // @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#14-16"]' 'Trait'
-pub fn foo2<T: bar::sub::Trait, V: Trait>(t: &T, v: &V, b: bool) {
-}
+pub fn foo2<T: bar::sub::Trait, V: Trait>(t: &T, v: &V, b: bool) {}
 
 // @has - '//a[@href="../../foo/primitive.bool.html"]' 'bool'
 #[doc(primitive = "bool")]
index fed37f6c9a2d55849f8c5db1f4fbf907579c2aa2..cda900773abfa5968d84545d550863567c41af55 100644 (file)
@@ -1,3 +1,5 @@
+#![allow(incomplete_features)]
+
 #![feature(adt_const_params)]
 
 #![crate_name = "foo"]
@@ -15,15 +17,15 @@ pub struct VSet<T, const ORDER: Order> {
     inner: Vec<T>,
 }
 
-// @has foo/struct.VSet.html '//div[@id="impl"]/h3[@class="code-header in-band"]' 'impl<T> VSet<T, {Order::Sorted}>'
-impl <T> VSet<T, {Order::Sorted}> {
+// @has foo/struct.VSet.html '//div[@id="impl"]/h3[@class="code-header in-band"]' 'impl<T> VSet<T, { Order::Sorted }>'
+impl<T> VSet<T, { Order::Sorted }> {
     pub fn new() -> Self {
         Self { inner: Vec::new() }
     }
 }
 
-// @has foo/struct.VSet.html '//div[@id="impl-1"]/h3[@class="code-header in-band"]' 'impl<T> VSet<T, {Order::Unsorted}>'
-impl <T> VSet<T, {Order::Unsorted}> {
+// @has foo/struct.VSet.html '//div[@id="impl-1"]/h3[@class="code-header in-band"]' 'impl<T> VSet<T, { Order::Unsorted }>'
+impl<T> VSet<T, { Order::Unsorted }> {
     pub fn new() -> Self {
         Self { inner: Vec::new() }
     }
@@ -31,7 +33,7 @@ pub fn new() -> Self {
 
 pub struct Escape<const S: &'static str>;
 
-// @has foo/struct.Escape.html '//div[@id="impl"]/h3[@class="code-header in-band"]' 'impl Escape<{ r#"<script>alert("Escape");</script>"# }>'
-impl Escape<{ r#"<script>alert("Escape");</script>"# }> {
+// @has foo/struct.Escape.html '//div[@id="impl"]/h3[@class="code-header in-band"]' 'impl Escape<r#"<script>alert("Escape");</script>"#>'
+impl Escape<r#"<script>alert("Escape");</script>"#> {
     pub fn f() {}
 }
index 3d6ebef5a1d5b095ddd5618200c50ceaac024463..6d0e339c48dc5815ee6d613f359f1e72e7b8febd 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(min_specialization)]
 
 // @has default_trait_method/trait.Item.html
 // @has - '//*[@id="tymethod.foo"]' 'fn foo()'
diff --git a/src/test/rustdoc/deref-const-fn.rs b/src/test/rustdoc/deref-const-fn.rs
new file mode 100644 (file)
index 0000000..ca51f3c
--- /dev/null
@@ -0,0 +1,38 @@
+// This test ensures that the const methods from Deref aren't shown as const.
+// For more information, see https://github.com/rust-lang/rust/issues/90855.
+
+#![crate_name = "foo"]
+
+#![feature(staged_api)]
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+// @has 'foo/struct.Bar.html'
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Bar;
+
+impl Bar {
+    // @has - '//*[@id="method.len"]' 'pub const fn len(&self) -> usize'
+    // @has - '//*[@id="method.len"]//span[@class="since"]' '1.0.0 (const: 1.0.0)'
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_stable(feature = "rust1", since = "1.0.0")]
+    pub const fn len(&self) -> usize { 0 }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Foo {
+    value: Bar,
+}
+
+// @has 'foo/struct.Foo.html'
+// @has - '//*[@id="method.len"]' 'pub fn len(&self) -> usize'
+// @!has - '//*[@id="method.len"]//span[@class="since"]' '1.0.0'
+// @!has - '//*[@id="method.len"]//span[@class="since"]' '(const: 1.0.0)'
+#[stable(feature = "rust1", since = "1.0.0")]
+impl std::ops::Deref for Foo {
+    type Target = Bar;
+
+    fn deref(&self) -> &Self::Target {
+        &self.value
+    }
+}
index 416ffb60098639fb044a1a25b99c9ab1dcade03b..8b2b7870c25f73b8f5e1cec66522b9b3466afefc 100644 (file)
@@ -96,6 +96,6 @@ pub fn uses_cfg_target_feature() {
 // @has doc_cfg/fn.multiple_attrs.html \
 //  '//*[@id="main"]/*[@class="item-info"]/*[@class="stab portability"]' \
 //  'This is supported on x and y and z only.'
-#[doc(inline, cfg(x))]
+#[doc(cfg(x))]
 #[doc(cfg(y), cfg(z))]
 pub fn multiple_attrs() {}
diff --git a/src/test/rustdoc/doc-notable_trait-slice.rs b/src/test/rustdoc/doc-notable_trait-slice.rs
new file mode 100644 (file)
index 0000000..b0d4140
--- /dev/null
@@ -0,0 +1,20 @@
+#![feature(doc_notable_trait)]
+
+#[doc(notable_trait)]
+pub trait SomeTrait {}
+
+pub struct SomeStruct;
+pub struct OtherStruct;
+impl SomeTrait for &[SomeStruct] {}
+
+// @has doc_notable_trait_slice/fn.bare_fn_matches.html
+// @has - '//code[@class="content"]' 'impl SomeTrait for &[SomeStruct]'
+pub fn bare_fn_matches() -> &'static [SomeStruct] {
+    &[]
+}
+
+// @has doc_notable_trait_slice/fn.bare_fn_no_matches.html
+// @!has - '//code[@class="content"]' 'impl SomeTrait for &[SomeStruct]'
+pub fn bare_fn_no_matches() -> &'static [OtherStruct] {
+    &[]
+}
index 68647127fe880317b22fedae82dc95035c8d0c3a..c7e66c826be1e71dea0a27b84c32f0559741e5f5 100644 (file)
@@ -1,4 +1,4 @@
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(rustdoc::broken_intra_doc_links)]
 #![feature(associated_type_defaults)]
 
 pub trait TraitWithDefault {
index d9fed2d69518a11abb41bde4f1fc728cebd3fa61..9b70ea054ad754668828393621aadd95fa0e39a3 100644 (file)
@@ -1,4 +1,4 @@
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 /// [`std::collections::BTreeMap::into_iter`]
 /// [`String::from`] is ambiguous as to which `From` impl
index 92cfd46188b015eba5d86c5d2420b0f976abc562..bb70073fc69866d5dc6687d3776e8b4116ac1ca6 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(no_core, lang_items)]
+#![feature(no_core, lang_items, rustdoc_internals)]
 #![no_core]
 #![crate_type="rlib"]
 
diff --git a/src/test/rustdoc/intra-doc/auxiliary/through-proc-macro-aux.rs b/src/test/rustdoc/intra-doc/auxiliary/through-proc-macro-aux.rs
deleted file mode 100644 (file)
index 5c4a01e..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// force-host
-// no-prefer-dynamic
-#![crate_type = "proc-macro"]
-#![crate_name="some_macros"]
-
-extern crate proc_macro;
-use proc_macro::TokenStream;
-
-#[proc_macro_attribute]
-pub fn first(_attr: TokenStream, item: TokenStream) -> TokenStream {
-    item // This doesn't erase the spans.
-}
-
-#[proc_macro_attribute]
-pub fn second(_attr: TokenStream, item: TokenStream) -> TokenStream {
-    // Make a new `TokenStream` to erase the spans:
-    let mut out: TokenStream = TokenStream::new();
-    out.extend(item);
-    out
-}
index 85c5866ca7ecfbc1b8ad0d56d01f3cc1d84e538e..e52fb9b1c9fd6775eb3771ffb3d3e0b7599a2874 100644 (file)
@@ -1,6 +1,6 @@
 // aux-build:additional_doc.rs
 // build-aux-docs
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 extern crate my_rand;
 
index 849d25687337b7f0af342659dc9fe893512bd783..684fdd449b835857d066908459120c8013c6ec66 100644 (file)
@@ -1,5 +1,5 @@
 #![crate_name = "my_rand"]
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 pub trait RngCore {}
 /// Rng extends [`RngCore`].
index b543ae764c05bb9a014c74c66007dbc4985fe6c1..34f4e9f635f8d18e51fcfe115bc432c5b0e8813e 100644 (file)
@@ -1,5 +1,5 @@
 #![crate_name = "hidden_dep"]
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 #[doc(hidden)]
 pub mod __reexport {
index 5342baecbc4b89aa16cd1b11c0cd6ea279ca4fbb..d6a82996689c3ce494ac68d02eec88b32ba06762 100644 (file)
@@ -1,5 +1,5 @@
 #![crate_name = "a"]
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 pub struct Foo;
 
index a94f9e5dcca2ec5421f286e3ade6932038d556d1..cb7a8afb60eafd7dcf12d1b75777d13f0a70351d 100644 (file)
@@ -1,5 +1,5 @@
 #![crate_name = "macro_inner"]
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 pub struct Foo;
 
index b7e3913f108f7553d089dfd1885d29f430532d56..018fdedd9edcad41ba47e551092d3d81e131e2c0 100644 (file)
@@ -1,5 +1,5 @@
 #![crate_name = "module_inner"]
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 /// [SomeType] links to [bar]
 pub struct SomeType;
 pub trait SomeTrait {}
index 8ae0f6c16b3d8113e67d8412c2207b3dfe9c0297..0612f53d6a7062ff05cb8eb0a2a0913a16d54c8b 100644 (file)
@@ -1,5 +1,5 @@
 #![crate_name = "a"]
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 pub mod bar {
    pub struct Bar;
index d90c529e3855280415bf0a2a7a65fa176e2d4f74..105eb8e112018d55301c5876774b979182803304 100644 (file)
@@ -1,5 +1,5 @@
 #![crate_name = "bar"]
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 pub trait Foo {
     /// [`Bar`] [`Baz`]
index 6ab9140c3c385c85ae472281e65d76334df43a2b..ad7454918b4e50e04f4b634045821c94e2dac925 100644 (file)
@@ -1,6 +1,6 @@
 // aux-build:intra-doc-basic.rs
 // build-aux-docs
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 // from https://github.com/rust-lang/rust/issues/65983
 extern crate a;
index 31337f20f18dc91e1336f26378bbcf2a9c59ae07..4f7d075ba481a0f8107a3126c3d73fa9b2eaf6fd 100644 (file)
@@ -1,6 +1,6 @@
 // aux-build:hidden.rs
 // build-aux-docs
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 // tests https://github.com/rust-lang/rust/issues/73363
 
index 62659ce689a7145ded8ff74124ad93917a37017c..32f0a55d3c6e5280c13cf0b44ca93993e02b2135 100644 (file)
@@ -1,7 +1,7 @@
 // aux-build:macro_inner.rs
 // aux-build:proc_macro.rs
 // build-aux-docs
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 extern crate macro_inner;
 extern crate proc_macro_inner;
 
index 9039e344f7b003711a1a7a60785f29683437d235..fde9322657d11cf74e03332694f764b96a3b6c32 100644 (file)
@@ -1,7 +1,7 @@
 // outer.rs
 // aux-build: module.rs
 // build-aux-docs
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 extern crate module_inner;
 // @has 'module/bar/index.html' '//a[@href="../../module_inner/trait.SomeTrait.html"]' 'SomeTrait'
 // @has 'module/bar/index.html' '//a[@href="../../module_inner/struct.SomeType.html"]' 'SomeType'
index e1465816368bf178ed9fd2e3b8e4faeaed08458e..577fe78a50896aebb1744d538d6b3982a237faf0 100644 (file)
@@ -1,6 +1,6 @@
 // aux-build:submodule-inner.rs
 // build-aux-docs
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 extern crate a;
 
index db7952b5aced0699f2408995dda1d8db8f1cd48d..d0c0b7e85ae2e4427e39cd8948b9eb1e190a8662 100644 (file)
@@ -1,6 +1,6 @@
 // aux-build:submodule-outer.rs
 // edition:2018
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 extern crate bar as bar_;
 
index 68f5cb3a092e4a93ed4c683fdacf913268552c6f..7b9554bfdb070d8b6b2c70da79fbded6a6db4c50 100644 (file)
@@ -1,6 +1,6 @@
 // aux-build:traits.rs
 // build-aux-docs
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 extern crate inner;
 use inner::SomeTrait;
index d782c5cf5dc84ade7959ce68d05c429dbeb81127..331a314130afb7f2cc4f66ed72a307ee811881a8 100644 (file)
@@ -1,4 +1,4 @@
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(rustdoc::broken_intra_doc_links)]
 // first try backticks
 /// Trait: [`trait@Name`], fn: [`fn@Name`], [`Name`][`macro@Name`]
 // @has disambiguators_removed/struct.AtDisambiguator.html
index c407eb80da225aed5eb1895a02d5fc33eb387b26..ae74fbbc892bbeab685cdd652ab95e8a80e4e5a9 100644 (file)
@@ -1,3 +1,5 @@
+#![allow(rustdoc::broken_intra_doc_links)]
+
 //! Email me at <hello@example.com>.
 //! Email me at <hello-world@example.com>.
 //! Email me at <hello@localhost> (this warns but will still become a link).
index 193bca704bfbdffca4c18f58a174672715aec34d..4e4438dea038ec6e1458ddcd045dba40f9424ebd 100644 (file)
@@ -4,6 +4,6 @@
 // though they would never actually get displayed. This tripped intra-doc-link resolution failures,
 // for items that aren't under our control, and not actually getting documented!
 
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 extern crate inner;
index de76f29476c66818f8268035716ea855fb9897e7..a0a66f242c9f5054e09833a4eddac6dce82ba5c2 100644 (file)
@@ -2,7 +2,7 @@
 // ignore-cross-compile
 
 #![crate_name = "outer"]
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 // using a trait that has intra-doc links on it from another crate (whether re-exporting or just
 // implementing it) used to give spurious resolution failure warnings
index ec965a99dc240039c4e83cb80d0e02861f32d53f..55169e5d3c4593cc8d3926acbd2e57a1981705bc 100644 (file)
@@ -1,6 +1,6 @@
 // we need to make sure that intra-doc links on trait impls get resolved in the right scope
 
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 pub mod inner {
     pub struct SomethingOutOfScope;
index 68a5672a8d2091e6ca3c3a7c53fbef0cf59a1e1e..a5fe855cb3681d187feb1440fa9d1667c4ec98d9 100644 (file)
@@ -1,5 +1,5 @@
 #![crate_name = "foo"]
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 pub enum Foo {
     Bar {
         abc: i32,
index fc0ff904389320f01f8be3c86d034311d1dccf41..6c41eb2b5b7c3be47ca6198e10ec9cef0994073b 100644 (file)
@@ -1,4 +1,4 @@
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 #![feature(intra_doc_pointers)]
 
 pub use std::*;
index 24b9dc30a9e496cd50123c6522e829f8540f085a..0c7acbaf09329edd4e3af0f46cb9b190af896faa 100644 (file)
@@ -1,4 +1,4 @@
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 
 pub fn foo() {
index c73140420ff1f858a0d5c0e7c2f4915d371ab02f..dfa7db8a55894c884b9bbcc3752fff5535032c64 100644 (file)
@@ -1,4 +1,4 @@
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 //! [i32::MAX]
 // @has prim_assoc/index.html '//a[@href="{{channel}}/std/primitive.i32.html#associatedconstant.MAX"]' "i32::MAX"
index 9d869984bbd7ce7e1d6333df122ae3fcdd9c267e..47ac953f266099077066d61ba68153292cccb605 100644 (file)
@@ -3,7 +3,7 @@
 // ignore-cross-compile
 // only-linux
 
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 #![feature(no_core, lang_items)]
 #![no_core]
 #![crate_type = "rlib"]
index cfb3c3842ab161694f954813ddfa9823269ce9bf..266bfa2073182e6dade9ee49251492e839e4c63f 100644 (file)
@@ -1,5 +1,5 @@
-#![deny(broken_intra_doc_links)]
-#![feature(no_core, lang_items)]
+#![deny(rustdoc::broken_intra_doc_links)]
+#![feature(no_core, lang_items, rustdoc_internals)]
 #![no_core]
 #![crate_type = "rlib"]
 
index 076117359d26416bc52e08e858e8d32d236a79d4..a9c5d7d4247cef5d3641e84c20aef9f50c5b40d6 100644 (file)
@@ -1,4 +1,4 @@
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 
 // @has prim_methods/index.html
index fcd86a99f1d6bf402125cab94bb84fc76b1360a5..25625b95277feabbe3e9dfd93b714ff20ebfe8c1 100644 (file)
@@ -1,4 +1,4 @@
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 pub mod char {
     /// [char]
index 9b3b698324096e03ec38ae7f982ba3a449f76d95..adcab767d0b947ed5c3f855b53952f633be65d74 100644 (file)
@@ -1,4 +1,4 @@
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 // @has primitive_disambiguators/index.html
 // @has - '//a/@href' '{{channel}}/std/primitive.str.html#method.trim'
 //! [str::trim()]
index f8a824bd08f421c81dde5878eee247b25b1907dc..474bf347750bd6d78b9c98b756b1f3f79ec116e3 100644 (file)
@@ -1,4 +1,4 @@
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 
 // @has primitive_non_default_impl/fn.str_methods.html
index cf8bc0b15869f469a97066101c0ed14a5851dfce..b272bfb5a4df2515b315b9da40296247e3abe4e0 100644 (file)
@@ -2,7 +2,7 @@
 // These failures were legitimate, but not truly relevant - the docs in question couldn't be
 // checked for accuracy anyway.
 
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 /// ooh, i'm a [rebel] just for kicks
 struct SomeStruct;
index 2756a7998e8ea42cdb580578b8b0cc17a6e26b4e..349091e9300bcfcb4bc20dcfef9ccfe95d840c7a 100644 (file)
@@ -1,8 +1,11 @@
-#![crate_name = "private"]
 // compile-flags: --document-private-items
 
 // make sure to update `rustdoc-ui/intra-doc/private.rs` if you update this file
 
+#![allow(rustdoc::private_intra_doc_links)]
+
+#![crate_name = "private"]
+
 /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
 // @has private/struct.DocMe.html '//*a[@href="struct.DontDocMe.html"]' 'DontDocMe'
 // @has private/struct.DocMe.html '//*a[@href="struct.DontDocMe.html#method.f"]' 'DontDocMe::f'
index fce10a130be655a70684bf0809caae5fdc20b94b..78379a90285fe42b83ff312eb64a60155bd5fd72 100644 (file)
@@ -1,6 +1,6 @@
 // aux-build:proc-macro-macro.rs
 // build-aux-docs
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 extern crate proc_macro_macro;
 
index b4f2d6b0617fa914e885eaa8b73582c5e4081b54..0c70cdee91462aacf6fcb4d1d6499b7d1f451e53 100644 (file)
@@ -1,5 +1,5 @@
 // aux-build: intra-link-pub-use.rs
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 #![crate_name = "outer"]
 
 extern crate inner;
index 177c3016fb1515728f54073540a3a0bda841d4e8..1ed33db9300b692574a6f7dca673c3546759e155 100644 (file)
@@ -1,4 +1,4 @@
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 pub mod r#impl {
     pub struct S;
 
diff --git a/src/test/rustdoc/intra-doc/through-proc-macro.rs b/src/test/rustdoc/intra-doc/through-proc-macro.rs
deleted file mode 100644 (file)
index 6134108..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// aux-build:through-proc-macro-aux.rs
-// build-aux-docs
-#![warn(broken_intra_doc_links)]
-extern crate some_macros;
-
-#[some_macros::second]
-pub enum Boom {
-    /// [Oooops]
-    Bam,
-}
-
-fn main() {}
index 0be368d051ee6e509c00bf78aad5a4c2cb3b75e5..e95dba33b5fd97153d671081d770184ef8a553b3 100644 (file)
@@ -1,4 +1,4 @@
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 /// Link to [S::assoc_fn()]
 /// Link to [Default::default()]
index 44aac68841373842844058351f77ca209fc2a788..be9b3e420b7ad2a8aa05d0625fed6d5b38a7ce96 100644 (file)
@@ -1,4 +1,4 @@
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 #![crate_name = "foo"]
 
 
index f3609ccd0a1418e19fde32809d7e13216a03e1cb..6c52082a2776e32d9ecd93885d159d6bd8b67f2b 100644 (file)
@@ -1,6 +1,6 @@
 // Regression test for issue #86120.
 
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 #![crate_name = "foo"]
 
 pub struct Foo;
index 8c47f7ef77e5181e2d88e9d1d58aba86f9682ccf..8a564acf2ca4bb356a0e5bc01cd5b103c62a3be3 100644 (file)
@@ -1,6 +1,7 @@
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 #![feature(lang_items)]
 #![feature(no_core)]
+#![feature(rustdoc_internals)]
 #![no_core]
 
 #[lang = "usize"]
index 558009e6937771758a90cf4fbd2929ab192c3a0f..9605a1e78c105dedfaa2e56f9d3e984e9e8f73a9 100644 (file)
@@ -1,6 +1,7 @@
 // Tests that failing to syntax highlight a rust code-block doesn't cause
 // rustdoc to fail, while still rendering the code-block (without highlighting).
 
+#![allow(rustdoc::invalid_rust_codeblocks)]
 
 // @has issue_12834/fn.foo.html
 // @has - //pre 'a + b '
index 1f7443a657240d1c6cee7903b4b5fc2efe0598cb..2fadc26b006206d8e740c667887f0747e17de79f 100644 (file)
@@ -1,3 +1,5 @@
+#![feature(rustdoc_internals)]
+
 // @has issue_15318_3/primitive.pointer.html
 
 /// dox
index 4972a9fb47fff1218ce3692262f60b7fe6dfb975..6d421f3c2531ae1f09004293426f10f6f9090837 100644 (file)
@@ -1,4 +1,5 @@
 #![feature(lang_items)]
+#![feature(rustdoc_internals)]
 #![no_std]
 
 pub mod str {
index 4944f8157014ed4a7562635f366ee1aaad8b541b..a5394c7d92a9662672186d0501cb7ce65bdd5c3f 100644 (file)
@@ -1,3 +1,5 @@
+#![allow(rustdoc::invalid_rust_codeblocks)]
+
 // @has issue_42760/struct.NonGen.html
 // @has - '//h2' 'Example'
 
index 44356848fbfadbbb3e9f7ea9320581adbc6fd1d3..767d09d85588810a26cada8dcbcb11b5e40846da 100644 (file)
@@ -2,6 +2,7 @@ pub fn g() -> impl Iterator<Item=u8> {
     Some(1u8).into_iter()
 }
 
+#[allow(unused_parens)]
 pub fn h() -> (impl Iterator<Item=u8>) {
     Some(1u8).into_iter()
 }
diff --git a/src/test/rustdoc/legacy-const-generic.rs b/src/test/rustdoc/legacy-const-generic.rs
new file mode 100644 (file)
index 0000000..46a50e2
--- /dev/null
@@ -0,0 +1,16 @@
+#![crate_name = "foo"]
+#![feature(rustc_attrs)]
+
+// @has 'foo/fn.foo.html'
+// @has - '//*[@class="rust fn"]' 'fn foo(x: usize, const Y: usize, z: usize) -> [usize; 3]'
+#[rustc_legacy_const_generics(1)]
+pub fn foo<const Y: usize>(x: usize, z: usize) -> [usize; 3] {
+    [x, Y, z]
+}
+
+// @has 'foo/fn.bar.html'
+// @has - '//*[@class="rust fn"]' 'fn bar(x: usize, const Y: usize, const Z: usize) -> [usize; 3]'
+#[rustc_legacy_const_generics(1, 2)]
+pub fn bar<const Y: usize, const Z: usize>(x: usize) -> [usize; 3] {
+    [x, Y, z]
+}
index 29e82cba98d35424702bdd8c3458a1daeb470eee..01aa8d00b707b58076fd2b97b69b5a909a244704 100644 (file)
@@ -1,3 +1,5 @@
+#![allow(rustdoc::broken_intra_doc_links)]
+
 #![crate_name = "foo"]
 
 //! hello [foo]
diff --git a/src/test/rustdoc/primitive-generic-impl.rs b/src/test/rustdoc/primitive-generic-impl.rs
deleted file mode 100644 (file)
index 0bf6157..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#![crate_name = "foo"]
-
-include!("primitive/primitive-generic-impl.rs");
-
-// @has foo/primitive.i32.html '//div[@id="impl-ToString"]//h3[@class="code-header in-band"]' 'impl<T> ToString for T'
index b9c56be0fcffcbba5cf4bc55807e6d3332a10ede..f9737240c70a294ed34ed06717e5649343b4b111 100644 (file)
@@ -1,3 +1,9 @@
+#![feature(rustdoc_internals)]
+
+#![crate_name = "foo"]
+
+// @has foo/primitive.i32.html '//div[@id="impl-ToString"]//h3[@class="code-header in-band"]' 'impl<T> ToString for T'
+
 #[doc(primitive = "i32")]
 /// Some useless docs, wouhou!
 mod i32 {}
index f6d1f2cf91b5fca1915212708a47ee68c3d6473b..10acb7ac495ec390fae4b368a5a6de807ab56e8c 100644 (file)
@@ -8,7 +8,7 @@
 // @has some_macros/index.html
 // @has - '//a/[@href="attr.some_proc_attr.html"]' 'some_proc_attr'
 
-//! include a link to [some_proc_macro] to make sure it works.
+//! include a link to [some_proc_macro!] to make sure it works.
 
 extern crate proc_macro;
 
index c08faaad0eccfc6a8dabc6c224f225f7fdfabcab..756939ae3773c37fbf9f46c5043d81599aa4888e 100644 (file)
@@ -2,4 +2,4 @@
 
 // @has foo/fn.f.html
 // @has - '//*[@class="rust fn"]' 'pub fn f(_: u8)'
-pub fn f(0u8...255: u8) {}
+pub fn f(0u8..=255: u8) {}
index ad190361267606a0e514d7ee23f93eb5ce12de94..7dbe63854f374f194667bffd08a47aeabcc80c85 100644 (file)
@@ -2,6 +2,7 @@
 
 pub mod internal {
     // @has 'raw_ident_eliminate_r_hashtag/internal/struct.mod.html'
+    #[allow(non_camel_case_types)]
     pub struct r#mod;
 
     /// See [name], [other name]
index 5da660b4df304a5ab3fa4b3b40346c5175889623..ee670e88b5cb4c69c6923cb5c5c09b3c691cc2a5 100644 (file)
@@ -30,11 +30,11 @@ pub struct Bar {
 
 // @has foo/enum.En.html
 // @has - '//*[@class="sidebar-title"]/a[@href="#variants"]' 'Variants'
-// @has - '//*[@class="sidebar-links"]/a' 'foo'
-// @has - '//*[@class="sidebar-links"]/a' 'bar'
+// @has - '//*[@class="sidebar-links"]/a' 'Foo'
+// @has - '//*[@class="sidebar-links"]/a' 'Bar'
 pub enum En {
-    foo,
-    bar,
+    Foo,
+    Bar,
 }
 
 // @has foo/union.MyUnion.html
index 2f7c89c5f1e6b7376d277d22165b9131eb5189fc..f1d49b9fcb20ae98d5eea6d56731d4cc870dd1f0 100644 (file)
@@ -3,7 +3,7 @@
 // @has static_root_path/struct.SomeStruct.html
 // @matches - '"/cache/main\.js"'
 // @!matches - '"\.\./main\.js"'
-// @matches - '"\.\./search-index\.js"'
+// @matches - 'data-root-path="\.\./"'
 // @!matches - '"/cache/search-index\.js"'
 pub struct SomeStruct;
 
index 2084e8517992a4759d657d0f0bb7de42812ff6a5..016ec7bfaa307225b1d403993ad3d42a63875ea2 100644 (file)
@@ -1,5 +1,7 @@
 #![crate_name = "foo"]
 
+#![feature(rustdoc_internals)]
+
 // @matches 'foo/index.html' '//h1' 'Crate foo'
 
 // @matches 'foo/foo_mod/index.html' '//h1' 'Module foo::foo_mod'
index 8051c58898e499241a41ead3775deea95e4b85e4..de0df0aae82d7aa5c997a30a24337f909d6e6488 100644 (file)
@@ -7,8 +7,8 @@
 extern crate rustc_lint;
 #[macro_use]
 extern crate rustc_session;
-extern crate rustc_span;
 extern crate rustc_ast;
+extern crate rustc_span;
 
 use rustc_ast_pretty::pprust;
 use rustc_driver::plugin::Registry;
@@ -44,7 +44,7 @@ fn check_fn(
     ) {
         let item = match cx.tcx.hir().get(id) {
             Node::Item(item) => item,
-            _ => cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(id)),
+            _ => cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(id).expect_owner()),
         };
 
         let allowed = |attr| pprust::attribute_to_string(attr).contains("allowed_attr");
diff --git a/src/test/ui/associated-types/issue-59324.rs b/src/test/ui/associated-types/issue-59324.rs
new file mode 100644 (file)
index 0000000..9e68e9e
--- /dev/null
@@ -0,0 +1,26 @@
+trait NotFoo {}
+
+pub trait Foo: NotFoo {
+    type OnlyFoo;
+}
+
+pub trait Service {
+    type AssocType;
+}
+
+pub trait ThriftService<Bug: NotFoo>:
+//~^ ERROR the trait bound `Bug: Foo` is not satisfied
+//~| ERROR the trait bound `Bug: Foo` is not satisfied
+    Service<AssocType = <Bug as Foo>::OnlyFoo>
+{
+    fn get_service(
+    //~^ ERROR the trait bound `Bug: Foo` is not satisfied
+    //~| ERROR the trait bound `Bug: Foo` is not satisfied
+        &self,
+    ) -> Self::AssocType;
+}
+
+fn with_factory<H>(factory: dyn ThriftService<()>) {}
+//~^ ERROR the trait bound `(): Foo` is not satisfied
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-59324.stderr b/src/test/ui/associated-types/issue-59324.stderr
new file mode 100644 (file)
index 0000000..2f430d3
--- /dev/null
@@ -0,0 +1,69 @@
+error[E0277]: the trait bound `Bug: Foo` is not satisfied
+  --> $DIR/issue-59324.rs:11:1
+   |
+LL | / pub trait ThriftService<Bug: NotFoo>:
+LL | |
+LL | |
+LL | |     Service<AssocType = <Bug as Foo>::OnlyFoo>
+...  |
+LL | |     ) -> Self::AssocType;
+LL | | }
+   | |_^ the trait `Foo` is not implemented for `Bug`
+   |
+help: consider further restricting this bound
+   |
+LL | pub trait ThriftService<Bug: NotFoo + Foo>:
+   |                                     +++++
+
+error[E0277]: the trait bound `Bug: Foo` is not satisfied
+  --> $DIR/issue-59324.rs:11:1
+   |
+LL | / pub trait ThriftService<Bug: NotFoo>:
+LL | |
+LL | |
+LL | |     Service<AssocType = <Bug as Foo>::OnlyFoo>
+...  |
+LL | |     ) -> Self::AssocType;
+LL | | }
+   | |_^ the trait `Foo` is not implemented for `Bug`
+   |
+help: consider further restricting this bound
+   |
+LL | pub trait ThriftService<Bug: NotFoo + Foo>:
+   |                                     +++++
+
+error[E0277]: the trait bound `Bug: Foo` is not satisfied
+  --> $DIR/issue-59324.rs:16:5
+   |
+LL | /     fn get_service(
+LL | |
+LL | |
+LL | |         &self,
+LL | |     ) -> Self::AssocType;
+   | |_________________________^ the trait `Foo` is not implemented for `Bug`
+   |
+help: consider further restricting this bound
+   |
+LL | pub trait ThriftService<Bug: NotFoo + Foo>:
+   |                                     +++++
+
+error[E0277]: the trait bound `Bug: Foo` is not satisfied
+  --> $DIR/issue-59324.rs:16:8
+   |
+LL |     fn get_service(
+   |        ^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug`
+   |
+help: consider further restricting this bound
+   |
+LL | pub trait ThriftService<Bug: NotFoo + Foo>:
+   |                                     +++++
+
+error[E0277]: the trait bound `(): Foo` is not satisfied
+  --> $DIR/issue-59324.rs:23:29
+   |
+LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
+   |                             ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/issue-67684.rs b/src/test/ui/associated-types/issue-67684.rs
new file mode 100644 (file)
index 0000000..49efe8a
--- /dev/null
@@ -0,0 +1,62 @@
+// check-pass
+
+#![allow(dead_code)]
+
+trait ParseError {
+    type StreamError;
+}
+
+impl<T> ParseError for T {
+    type StreamError = ();
+}
+
+trait Stream {
+    type Item;
+    type Error: ParseError;
+}
+
+trait Parser
+where
+    <Self as Parser>::PartialState: Default,
+{
+    type PartialState;
+    fn parse_mode(_: &Self, _: Self::PartialState) {
+        loop {}
+    }
+}
+
+impl Stream for () {
+    type Item = ();
+    type Error = ();
+}
+
+impl Parser for () {
+    type PartialState = ();
+}
+
+struct AndThen<A, B>(core::marker::PhantomData<(A, B)>);
+
+impl<A, B> Parser for AndThen<A, B>
+where
+    A: Stream,
+    B: Into<<A::Error as ParseError>::StreamError>,
+{
+    type PartialState = ();
+}
+
+fn expr<A>() -> impl Parser
+where
+    A: Stream<Error = <A as Stream>::Item>,
+{
+    AndThen::<A, ()>(core::marker::PhantomData)
+}
+
+fn parse_mode_impl<A>()
+where
+    <A as Stream>::Error: ParseError,
+    A: Stream<Error = <A as Stream>::Item>,
+{
+    Parser::parse_mode(&expr::<A>(), Default::default())
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-69398.rs b/src/test/ui/associated-types/issue-69398.rs
new file mode 100644 (file)
index 0000000..ca3d66b
--- /dev/null
@@ -0,0 +1,21 @@
+// check-pass
+
+pub trait Foo {
+    type Bar;
+}
+
+pub trait Broken {
+    type Assoc;
+    fn broken(&self) where Self::Assoc: Foo;
+}
+
+impl<T> Broken for T {
+    type Assoc = ();
+    fn broken(&self) where Self::Assoc: Foo {
+        let _x: <Self::Assoc as Foo>::Bar;
+    }
+}
+
+fn main() {
+    let _m: &dyn Broken<Assoc=()> = &();
+}
diff --git a/src/test/ui/associated-types/issue-71113.rs b/src/test/ui/associated-types/issue-71113.rs
new file mode 100644 (file)
index 0000000..48de891
--- /dev/null
@@ -0,0 +1,16 @@
+// check-pass
+
+use std::borrow::Cow;
+
+enum _Recursive<'a>
+where
+    Self: ToOwned<Owned=Box<Self>>
+{
+    Variant(MyCow<'a, _Recursive<'a>>),
+}
+
+pub struct Wrapper<T>(T);
+
+pub struct MyCow<'a, T: ToOwned<Owned=Box<T>> + 'a>(Wrapper<Cow<'a, T>>);
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-82079.rs b/src/test/ui/associated-types/issue-82079.rs
new file mode 100644 (file)
index 0000000..590c799
--- /dev/null
@@ -0,0 +1,121 @@
+// check-pass
+
+mod convenience_operators {
+    use crate::{Op, Relation};
+    use std::ops::AddAssign;
+    use std::ops::Mul;
+
+    impl<C: Op> Relation<C> {
+        pub fn map<F: Fn(C::D) -> D2 + 'static, D2: 'static>(
+            self,
+            f: F,
+        ) -> Relation<impl Op<D = D2, R = C::R>> {
+            self.map_dr(move |x, r| (f(x), r))
+        }
+    }
+
+    impl<K: 'static, V: 'static, C: Op<D = (K, V)>> Relation<C> {
+        pub fn semijoin<C2: Op<D = K, R = R2>, R2, R3: AddAssign<R3>>(
+            self,
+            other: Relation<C2>,
+        ) -> Relation<impl Op<D = C::D, R = R3>>
+        where
+            C::R: Mul<R2, Output = R3>,
+        {
+            self.join(other.map(|x| (x, ()))).map(|(k, x, ())| (k, x))
+        }
+    }
+}
+
+mod core {
+    mod operator {
+        mod join {
+            use super::Op;
+            use crate::core::Relation;
+            use std::ops::{AddAssign, Mul};
+            struct Join<LC, RC> {
+                _left: LC,
+                _right: RC,
+            }
+            impl<
+                    LC: Op<D = (K, LD), R = LR>,
+                    RC: Op<D = (K, RD), R = RR>,
+                    K: 'static,
+                    LD: 'static,
+                    LR: AddAssign<LR> + Mul<RR, Output = OR>,
+                    RD: 'static,
+                    RR: AddAssign<RR>,
+                    OR: AddAssign<OR>,
+                > Op for Join<LC, RC>
+            {
+                type D = (K, LD, RD);
+                type R = OR;
+            }
+            impl<K: 'static, D: 'static, C: Op<D = (K, D)>> Relation<C> {
+                pub fn join<C2: Op<D = (K, D2)>, D2: 'static, OR: AddAssign<OR>>(
+                    self,
+                    other: Relation<C2>,
+                ) -> Relation<impl Op<D = (K, D, D2), R = OR>>
+                where
+                    C::R: Mul<C2::R, Output = OR>,
+                {
+                    Relation {
+                        inner: Join {
+                            _left: self.inner,
+                            _right: other.inner,
+                        },
+                    }
+                }
+            }
+        }
+        mod map {
+            use super::Op;
+            use crate::core::Relation;
+            use std::ops::AddAssign;
+            struct Map<C, MF> {
+                _inner: C,
+                _op: MF,
+            }
+            impl<
+                    D1,
+                    R1,
+                    D2: 'static,
+                    R2: AddAssign<R2>,
+                    C: Op<D = D1, R = R1>,
+                    MF: Fn(D1, R1) -> (D2, R2),
+                > Op for Map<C, MF>
+            {
+                type D = D2;
+                type R = R2;
+            }
+            impl<C: Op> Relation<C> {
+                pub fn map_dr<F: Fn(C::D, C::R) -> (D2, R2), D2: 'static, R2: AddAssign<R2>>(
+                    self,
+                    f: F,
+                ) -> Relation<impl Op<D = D2, R = R2>> {
+                    Relation {
+                        inner: Map {
+                            _inner: self.inner,
+                            _op: f,
+                        },
+                    }
+                }
+            }
+        }
+        use std::ops::AddAssign;
+        pub trait Op {
+            type D: 'static;
+            type R: AddAssign<Self::R>;
+        }
+    }
+    pub use self::operator::Op;
+    #[derive(Clone)]
+    pub struct Relation<C> {
+        inner: C,
+    }
+}
+
+use self::core::Op;
+pub use self::core::Relation;
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-85103.rs b/src/test/ui/associated-types/issue-85103.rs
new file mode 100644 (file)
index 0000000..c5e1385
--- /dev/null
@@ -0,0 +1,9 @@
+#![feature(rustc_attrs)]
+
+use std::borrow::Cow;
+
+#[rustc_layout(debug)]
+type Edges<'a, E> = Cow<'a, [E]>;
+//~^ ERROR layout error: NormalizationFailure
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-85103.stderr b/src/test/ui/associated-types/issue-85103.stderr
new file mode 100644 (file)
index 0000000..142f3c4
--- /dev/null
@@ -0,0 +1,8 @@
+error: layout error: NormalizationFailure(<[E] as std::borrow::ToOwned>::Owned, Type(<[E] as std::borrow::ToOwned>::Owned))
+  --> $DIR/issue-85103.rs:6:1
+   |
+LL | type Edges<'a, E> = Cow<'a, [E]>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
index 384561f8ccd7e0496ef3c867ff4e015f8955a958..aae562ae72243d34023d060ebe4979b482b2a8b5 100644 (file)
@@ -83,17 +83,17 @@ fn main() {
     //~^ ERROR type mismatch resolving `<impl DerivedTrait as Trait>::Associated == ()`
 
     accepts_trait(returns_opaque_foo());
-    //~^ ERROR type mismatch resolving `<impl Trait + Foo as Trait>::Associated == ()`
+    //~^ ERROR type mismatch resolving `<impl Foo + Trait as Trait>::Associated == ()`
 
     accepts_trait(returns_opaque_derived_foo());
-    //~^ ERROR type mismatch resolving `<impl DerivedTrait + Foo as Trait>::Associated == ()`
+    //~^ ERROR type mismatch resolving `<impl Foo + DerivedTrait as Trait>::Associated == ()`
 
     accepts_generic_trait(returns_opaque_generic());
     //~^ ERROR type mismatch resolving `<impl GenericTrait<()> as GenericTrait<()>>::Associated == ()`
 
     accepts_generic_trait(returns_opaque_generic_foo());
-    //~^ ERROR type mismatch resolving `<impl GenericTrait<()> + Foo as GenericTrait<()>>::Associated == ()`
+    //~^ ERROR type mismatch resolving `<impl Foo + GenericTrait<()> as GenericTrait<()>>::Associated == ()`
 
     accepts_generic_trait(returns_opaque_generic_duplicate());
-    //~^ ERROR type mismatch resolving `<impl GenericTrait<()> + GenericTrait<u8> as GenericTrait<()>>::Associated == ()`
+    //~^ ERROR type mismatch resolving `<impl GenericTrait<u8> + GenericTrait<()> as GenericTrait<()>>::Associated == ()`
 }
index 8db4a49da3c96e4f7790d038e62ac3ad0062a3d4..c00b48abc1c330993d5755fe471e48949a225c4f 100644 (file)
@@ -160,7 +160,7 @@ help: consider constraining the associated type `<impl DerivedTrait as Trait>::A
 LL | fn returns_opaque_derived() -> impl DerivedTrait<Associated = ()> + 'static {
    |                                                 +++++++++++++++++
 
-error[E0271]: type mismatch resolving `<impl Trait + Foo as Trait>::Associated == ()`
+error[E0271]: type mismatch resolving `<impl Foo + Trait as Trait>::Associated == ()`
   --> $DIR/issue-87261.rs:85:5
    |
 LL | fn returns_opaque_foo() -> impl Trait + Foo {
@@ -170,18 +170,18 @@ LL |     accepts_trait(returns_opaque_foo());
    |     ^^^^^^^^^^^^^ expected `()`, found associated type
    |
    = note:    expected unit type `()`
-           found associated type `<impl Trait + Foo as Trait>::Associated`
+           found associated type `<impl Foo + Trait as Trait>::Associated`
 note: required by a bound in `accepts_trait`
   --> $DIR/issue-87261.rs:43:27
    |
 LL | fn accepts_trait<T: Trait<Associated = ()>>(_: T) {}
    |                           ^^^^^^^^^^^^^^^ required by this bound in `accepts_trait`
-help: consider constraining the associated type `<impl Trait + Foo as Trait>::Associated` to `()`
+help: consider constraining the associated type `<impl Foo + Trait as Trait>::Associated` to `()`
    |
 LL | fn returns_opaque_foo() -> impl Trait<Associated = ()> + Foo {
    |                                      +++++++++++++++++
 
-error[E0271]: type mismatch resolving `<impl DerivedTrait + Foo as Trait>::Associated == ()`
+error[E0271]: type mismatch resolving `<impl Foo + DerivedTrait as Trait>::Associated == ()`
   --> $DIR/issue-87261.rs:88:5
    |
 LL | fn returns_opaque_derived_foo() -> impl DerivedTrait + Foo {
@@ -191,8 +191,8 @@ LL |     accepts_trait(returns_opaque_derived_foo());
    |     ^^^^^^^^^^^^^ expected `()`, found associated type
    |
    = note:    expected unit type `()`
-           found associated type `<impl DerivedTrait + Foo as Trait>::Associated`
-   = help: consider constraining the associated type `<impl DerivedTrait + Foo as Trait>::Associated` to `()`
+           found associated type `<impl Foo + DerivedTrait as Trait>::Associated`
+   = help: consider constraining the associated type `<impl Foo + DerivedTrait as Trait>::Associated` to `()`
    = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 note: required by a bound in `accepts_trait`
   --> $DIR/issue-87261.rs:43:27
@@ -221,7 +221,7 @@ help: consider constraining the associated type `<impl GenericTrait<()> as Gener
 LL | fn returns_opaque_generic() -> impl GenericTrait<(), Associated = ()> + 'static {
    |                                                    +++++++++++++++++
 
-error[E0271]: type mismatch resolving `<impl GenericTrait<()> + Foo as GenericTrait<()>>::Associated == ()`
+error[E0271]: type mismatch resolving `<impl Foo + GenericTrait<()> as GenericTrait<()>>::Associated == ()`
   --> $DIR/issue-87261.rs:94:5
    |
 LL | fn returns_opaque_generic_foo() -> impl GenericTrait<()> + Foo {
@@ -231,18 +231,18 @@ LL |     accepts_generic_trait(returns_opaque_generic_foo());
    |     ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type
    |
    = note:    expected unit type `()`
-           found associated type `<impl GenericTrait<()> + Foo as GenericTrait<()>>::Associated`
+           found associated type `<impl Foo + GenericTrait<()> as GenericTrait<()>>::Associated`
 note: required by a bound in `accepts_generic_trait`
   --> $DIR/issue-87261.rs:44:46
    |
 LL | fn accepts_generic_trait<T: GenericTrait<(), Associated = ()>>(_: T) {}
    |                                              ^^^^^^^^^^^^^^^ required by this bound in `accepts_generic_trait`
-help: consider constraining the associated type `<impl GenericTrait<()> + Foo as GenericTrait<()>>::Associated` to `()`
+help: consider constraining the associated type `<impl Foo + GenericTrait<()> as GenericTrait<()>>::Associated` to `()`
    |
 LL | fn returns_opaque_generic_foo() -> impl GenericTrait<(), Associated = ()> + Foo {
    |                                                        +++++++++++++++++
 
-error[E0271]: type mismatch resolving `<impl GenericTrait<()> + GenericTrait<u8> as GenericTrait<()>>::Associated == ()`
+error[E0271]: type mismatch resolving `<impl GenericTrait<u8> + GenericTrait<()> as GenericTrait<()>>::Associated == ()`
   --> $DIR/issue-87261.rs:97:5
    |
 LL | fn returns_opaque_generic_duplicate() -> impl GenericTrait<()> + GenericTrait<u8> {
@@ -252,8 +252,8 @@ LL |     accepts_generic_trait(returns_opaque_generic_duplicate());
    |     ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type
    |
    = note:    expected unit type `()`
-           found associated type `<impl GenericTrait<()> + GenericTrait<u8> as GenericTrait<()>>::Associated`
-   = help: consider constraining the associated type `<impl GenericTrait<()> + GenericTrait<u8> as GenericTrait<()>>::Associated` to `()`
+           found associated type `<impl GenericTrait<u8> + GenericTrait<()> as GenericTrait<()>>::Associated`
+   = help: consider constraining the associated type `<impl GenericTrait<u8> + GenericTrait<()> as GenericTrait<()>>::Associated` to `()`
    = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 note: required by a bound in `accepts_generic_trait`
   --> $DIR/issue-87261.rs:44:46
diff --git a/src/test/ui/associated-types/issue-88856.rs b/src/test/ui/associated-types/issue-88856.rs
new file mode 100644 (file)
index 0000000..7cae7c7
--- /dev/null
@@ -0,0 +1,32 @@
+// check-pass
+
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub trait Trait{
+    type R;
+    fn func(self)->Self::R;
+}
+
+pub struct TraitImpl<const N:usize>(pub i32);
+
+impl<const N:usize> Trait for TraitImpl<N>
+where [();N/2]:,
+{
+    type R = Self;
+    fn func(self)->Self::R {
+        self
+    }
+}
+
+fn sample<P,Convert>(p:P,f:Convert) -> i32
+where
+    P:Trait,Convert:Fn(P::R)->i32
+{
+    f(p.func())
+}
+
+fn main() {
+    let t = TraitImpl::<10>(4);
+    sample(t,|x|x.0);
+}
diff --git a/src/test/ui/associated-types/issue-91231.rs b/src/test/ui/associated-types/issue-91231.rs
new file mode 100644 (file)
index 0000000..3c1cb81
--- /dev/null
@@ -0,0 +1,17 @@
+// check-pass
+
+#![feature(extern_types)]
+#![allow(dead_code)]
+
+extern {
+    type Extern;
+}
+
+trait Trait {
+    type Type;
+}
+
+#[inline]
+fn f<'a>(_: <&'a Extern as Trait>::Type) where &'a Extern: Trait {}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-91234.rs b/src/test/ui/associated-types/issue-91234.rs
new file mode 100644 (file)
index 0000000..2f6c2d3
--- /dev/null
@@ -0,0 +1,13 @@
+// check-pass
+
+struct Struct;
+
+trait Trait {
+    type Type;
+}
+
+enum Enum<'a> where &'a Struct: Trait {
+    Variant(<&'a Struct as Trait>::Type)
+}
+
+fn main() {}
index 8961655ede36f6fc4dad99eeba8bb18096f636ba..22484ba6378d32af0660dc36c60bfec20a740313 100644 (file)
@@ -1 +1 @@
-{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"span":{"lo":0,"hi":0}}
+{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"span":{"lo":0,"hi":0},"is_placeholder":null}
index 082f04134ce8f387eebe81f373327ae5dd12fd8a..ae56bef35ffe70497effb35bc69f15324a97cf0d 100644 (file)
@@ -1 +1 @@
-{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"rust_2015","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"span":{"lo":0,"hi":0}}
+{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"rust_2015","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"span":{"lo":0,"hi":0},"is_placeholder":null}
index 5bc7069ff89e31beebb794fb426c3544eca6d40c..e3832767203bbb6c5845b92ffbfc456d5ee71a87 100644 (file)
@@ -15,16 +15,16 @@ fn return_targets_async_block_not_fn() -> u8 {
         return 0u8;
     };
     let _: &dyn Future<Output = ()> = &block;
-    //~^ ERROR type mismatch resolving `<impl Future as Future>::Output == ()`
+    //~^ ERROR type mismatch
 }
 
 async fn return_targets_async_block_not_async_fn() -> u8 {
-    //~^ ERROR mismatched types
+    //~^ ERROR mismatched types [E0308]
     let block = async {
         return 0u8;
     };
     let _: &dyn Future<Output = ()> = &block;
-    //~^ ERROR type mismatch resolving `<impl Future as Future>::Output == ()`
+    //~^ ERROR type mismatch resolving `<impl Future<Output = [async output]> as Future>::Output == ()`
 }
 
 fn no_break_in_async_block() {
index 919904ce3b6a2fd64d19593e47a6288b29531d10..fe864c65b7cf24ca510d7366305295ad7dc021a0 100644 (file)
@@ -31,7 +31,7 @@ LL | |
 LL | | }
    | |_^ expected `u8`, found `()`
 
-error[E0271]: type mismatch resolving `<impl Future as Future>::Output == ()`
+error[E0271]: type mismatch resolving `<impl Future<Output = [async output]> as Future>::Output == ()`
   --> $DIR/async-block-control-flow-static-semantics.rs:26:39
    |
 LL |     let _: &dyn Future<Output = ()> = &block;
@@ -47,7 +47,7 @@ LL | fn return_targets_async_block_not_fn() -> u8 {
    |    |
    |    implicitly returns `()` as its body has no tail or `return` expression
 
-error[E0271]: type mismatch resolving `<impl Future as Future>::Output == ()`
+error[E0271]: type mismatch resolving `<impl Future<Output = [async output]> as Future>::Output == ()`
   --> $DIR/async-block-control-flow-static-semantics.rs:17:39
    |
 LL |     let _: &dyn Future<Output = ()> = &block;
index 994bfd33ba42e37d2137b6035a29dee7cff67100..2e3f8bb52560add2b82925fc7213979b2669cba9 100644 (file)
@@ -5,6 +5,7 @@ LL | fn get_future() -> impl Future<Output = ()> {
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future
    |
    = help: the trait `Future` is not implemented for `()`
+   = note: () must be a future or must implement `IntoFuture` to be awaited
 
 error[E0698]: type inside `async fn` body must be known in this context
   --> $DIR/async-error-span.rs:13:9
index 636fafc2bc44a248731973987639c545c49daf4f..a603ebd6e8547727824440b4828cae0730fe8962 100644 (file)
@@ -112,7 +112,7 @@ async fn mixed_sizes() {
 fn main() {
     assert_eq!(1025, std::mem::size_of_val(&single()));
     assert_eq!(1026, std::mem::size_of_val(&single_with_noop()));
-    assert_eq!(3078, std::mem::size_of_val(&joined()));
-    assert_eq!(3079, std::mem::size_of_val(&joined_with_noop()));
-    assert_eq!(7181, std::mem::size_of_val(&mixed_sizes()));
+    assert_eq!(3076, std::mem::size_of_val(&joined()));
+    assert_eq!(3076, std::mem::size_of_val(&joined_with_noop()));
+    assert_eq!(6157, std::mem::size_of_val(&mixed_sizes()));
 }
diff --git a/src/test/ui/async-await/await-into-future.rs b/src/test/ui/async-await/await-into-future.rs
new file mode 100644 (file)
index 0000000..b74b168
--- /dev/null
@@ -0,0 +1,30 @@
+// run-pass
+// aux-build: issue-72470-lib.rs
+// edition:2021
+#![feature(into_future)]
+
+extern crate issue_72470_lib;
+use std::{future::{Future, IntoFuture}, pin::Pin};
+
+struct AwaitMe;
+
+impl IntoFuture for AwaitMe {
+    type Output = i32;
+    type Future = Pin<Box<dyn Future<Output = i32>>>;
+
+    fn into_future(self) -> Self::Future {
+        Box::pin(me())
+    }
+}
+
+async fn me() -> i32 {
+    41
+}
+
+async fn run() {
+    assert_eq!(AwaitMe.await, 41);
+}
+
+fn main() {
+    issue_72470_lib::run(run());
+}
index 79834ed7ec1a8fb08d64c5cbdbba08c9a13536ad..4a45d8d2a942344a55427e35341450aec65e3478 100644 (file)
@@ -46,8 +46,8 @@ LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
    |                                           the expected opaque type
    |                                           the found opaque type
    |
-   = note: expected opaque type `impl Future` (`async` closure body)
-              found opaque type `impl Future` (`async` closure body)
+   = note: expected opaque type `impl Future<Output = [async output]>` (`async` closure body)
+              found opaque type `impl Future<Output = [async output]>` (`async` closure body)
 
 error: aborting due to 3 previous errors
 
index d046e2a05611c3d7ac45deb7bdee6db9ba62142f..b61694ad53e5b1a869bc521c519907aca5ae35fb 100644 (file)
@@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
 LL |     spawn(async {
    |     ^^^^^ future created by async block is not `Send`
    |
-   = help: within `impl Future`, the trait `Send` is not implemented for `*mut ()`
+   = help: within `impl Future<Output = [async output]>`, the trait `Send` is not implemented for `*mut ()`
 note: future is not `Send` as this value is used across an await
   --> $DIR/issue-67252-unnamed-future.rs:20:9
    |
index 9682a7055e93c4fd16fdd7748c7e87d1853553ea..a8c2ebe12fa1837eff54e5529e839d9cb079fec7 100644 (file)
@@ -44,13 +44,13 @@ LL |     require_send(send_fut);
    = note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>`
    = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:47:31: 47:36]`
    = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36]>`
-   = note: required because it appears within the type `impl Future`
+   = note: required because it appears within the type `impl Future<Output = [async output]>`
    = note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
    = note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
    = note: required because it appears within the type `{ResumeTy, impl Future<Output = Arc<RefCell<i32>>>, (), i32, Ready<i32>}`
    = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:55:26: 59:6]`
    = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:55:26: 59:6]>`
-   = note: required because it appears within the type `impl Future`
+   = note: required because it appears within the type `impl Future<Output = [async output]>`
 note: required by a bound in `require_send`
   --> $DIR/issue-68112.rs:11:25
    |
index eb24040404b90db8c60434af98708c8b523d84f7..ab05251526b0ddb8567f5fa97879ad1a998011a3 100644 (file)
@@ -25,6 +25,8 @@ LL |     [1; ().await];
    |         ^^^^^^^^ `()` is not a future
    |
    = help: the trait `Future` is not implemented for `()`
+   = note: () must be a future or must implement `IntoFuture` to be awaited
+   = note: required because of the requirements on the impl of `IntoFuture` for `()`
 
 error: aborting due to 4 previous errors
 
index e2ea72a1e617890583230fbc734040c272f528c6..19d6f9bc43866857e46a32766fb3b3409be5c358 100644 (file)
@@ -34,6 +34,8 @@ LL |     (|_| 2333).await;
    |     ^^^^^^^^^^^^^^^^ `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` is not a future
    |
    = help: the trait `Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]`
+   = note: [closure@$DIR/issue-62009-1.rs:12:5: 12:15] must be a future or must implement `IntoFuture` to be awaited
+   = note: required because of the requirements on the impl of `IntoFuture` for `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]`
 
 error: aborting due to 4 previous errors
 
index 666ef851ad66f579ca91fe31afe73cbd6e5cf8f1..6ebefbebe536260f327b9ea2c3143c8dfeb0c84e 100644 (file)
@@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
 LL |     assert_send(async {
    |     ^^^^^^^^^^^ future created by async block is not `Send`
    |
-   = help: within `impl Future`, the trait `Send` is not implemented for `*const u8`
+   = help: within `impl Future<Output = [async output]>`, the trait `Send` is not implemented for `*const u8`
 note: future is not `Send` as this value is used across an await
   --> $DIR/issue-65436-raw-ptr-not-send.rs:14:9
    |
index d313691b388577ffb80a60888bf95c513ad5a3aa..85d868c27032e011fd910d6c591b3f8d457b4fbd 100644 (file)
@@ -10,12 +10,20 @@ async fn foo() {
     //~^ ERROR type inside `async fn` body must be known in this context
     //~| ERROR type inside `async fn` body must be known in this context
     //~| ERROR type inside `async fn` body must be known in this context
+    //~| ERROR type inside `async fn` body must be known in this context
+    //~| ERROR type inside `async fn` body must be known in this context
+    //~| NOTE cannot infer type for type parameter `T`
+    //~| NOTE cannot infer type for type parameter `T`
     //~| NOTE cannot infer type for type parameter `T`
     //~| NOTE cannot infer type for type parameter `T`
     //~| NOTE cannot infer type for type parameter `T`
     //~| NOTE the type is part of the `async fn` body because of this `await`
     //~| NOTE the type is part of the `async fn` body because of this `await`
     //~| NOTE the type is part of the `async fn` body because of this `await`
+    //~| NOTE the type is part of the `async fn` body because of this `await`
+    //~| NOTE the type is part of the `async fn` body because of this `await`
+    //~| NOTE in this expansion of desugaring of `await`
+    //~| NOTE in this expansion of desugaring of `await`
     //~| NOTE in this expansion of desugaring of `await`
     //~| NOTE in this expansion of desugaring of `await`
     //~| NOTE in this expansion of desugaring of `await`
index 6b9e960ca1ae69d27e8149a9e905f81068a156bf..130667a49c53abde9863ef68df09f5691fb4428d 100644 (file)
@@ -34,6 +34,30 @@ note: the type is part of the `async fn` body because of this `await`
 LL |     bar().await;
    |     ^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error[E0698]: type inside `async fn` body must be known in this context
+  --> $DIR/unresolved_type_param.rs:9:5
+   |
+LL |     bar().await;
+   |     ^^^ cannot infer type for type parameter `T` declared on the function `bar`
+   |
+note: the type is part of the `async fn` body because of this `await`
+  --> $DIR/unresolved_type_param.rs:9:5
+   |
+LL |     bar().await;
+   |     ^^^^^^^^^^^
+
+error[E0698]: type inside `async fn` body must be known in this context
+  --> $DIR/unresolved_type_param.rs:9:5
+   |
+LL |     bar().await;
+   |     ^^^ cannot infer type for type parameter `T` declared on the function `bar`
+   |
+note: the type is part of the `async fn` body because of this `await`
+  --> $DIR/unresolved_type_param.rs:9:5
+   |
+LL |     bar().await;
+   |     ^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0698`.
diff --git a/src/test/ui/attributes/issue-90873.rs b/src/test/ui/attributes/issue-90873.rs
new file mode 100644 (file)
index 0000000..76708ea
--- /dev/null
@@ -0,0 +1,9 @@
+#![u=||{static d=||1;}]
+//~^ unexpected token
+//~| cannot find attribute `u` in this scope
+//~| `main` function not found in crate `issue_90873`
+//~| missing type for `static` item
+
+#![a={impl std::ops::Neg for i8 {}}]
+//~^ ERROR unexpected token
+//~| ERROR cannot find attribute `a` in this scope
diff --git a/src/test/ui/attributes/issue-90873.stderr b/src/test/ui/attributes/issue-90873.stderr
new file mode 100644 (file)
index 0000000..d466157
--- /dev/null
@@ -0,0 +1,50 @@
+error: unexpected token: `||
+           {
+               static d: _ = || 1;
+           }`
+  --> $DIR/issue-90873.rs:1:6
+   |
+LL | #![u=||{static d=||1;}]
+   |      ^^^^^^^^^^^^^^^^^
+
+error: unexpected token: `{
+           impl std::ops::Neg for i8 { }
+       }`
+  --> $DIR/issue-90873.rs:7:6
+   |
+LL | #![a={impl std::ops::Neg for i8 {}}]
+   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot find attribute `u` in this scope
+  --> $DIR/issue-90873.rs:1:4
+   |
+LL | #![u=||{static d=||1;}]
+   |    ^
+
+error: cannot find attribute `a` in this scope
+  --> $DIR/issue-90873.rs:7:4
+   |
+LL | #![a={impl std::ops::Neg for i8 {}}]
+   |    ^
+
+error[E0601]: `main` function not found in crate `issue_90873`
+  --> $DIR/issue-90873.rs:1:1
+   |
+LL | / #![u=||{static d=||1;}]
+LL | |
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | #![a={impl std::ops::Neg for i8 {}}]
+   | |____________________________________^ consider adding a `main` function to `$DIR/issue-90873.rs`
+
+error: missing type for `static` item
+  --> $DIR/issue-90873.rs:1:16
+   |
+LL | #![u=||{static d=||1;}]
+   |                ^ help: provide a type for the item: `d: <type>`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0601`.
index c7e357d4604f71a61139add1a416b3c8dae93dc2..d2c7473c036b8769fbcfacccf3792b38cc637cef 100644 (file)
@@ -3,6 +3,8 @@ error[E0381]: borrow of possibly-uninitialized variable: `i`
    |
 LL |     println!("{}", i);
    |                    ^ use of possibly-uninitialized `i`
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index bc9b25c0221fcc59dad651a328f2ebe5575956dc..b134f5cc2d8e3d950e53c3ee966ae0d5aa458eeb 100644 (file)
@@ -3,6 +3,8 @@ error[E0381]: borrow of possibly-uninitialized variable: `x`
    |
 LL |     println!("{}", x);
    |                    ^ use of possibly-uninitialized `x`
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index 766d5cfd6348cd60dc373367100434e827d81ee7..652d7d3076fbda4494248b7573e58784e2ad3d8c 100644 (file)
@@ -3,6 +3,8 @@ error[E0381]: borrow of possibly-uninitialized variable: `x`
    |
 LL |     println!("{}", x);
    |                    ^ use of possibly-uninitialized `x`
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index 3fe8d9eededc5373b3d5c2868803333d846456f8..6c757759f71344514af75d2a2b486bcc0324978f 100644 (file)
@@ -3,6 +3,8 @@ error[E0381]: borrow of possibly-uninitialized variable: `i`
    |
 LL |     println!("{}", i);
    |                    ^ use of possibly-uninitialized `i`
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index 3eaaf8d7df08d30acab3a83f31bf59cf60612efd..fc144a066bb2777fe14784b24128c3d880fef2b0 100644 (file)
@@ -3,6 +3,8 @@ error[E0381]: borrow of possibly-uninitialized variable: `v`
    |
 LL |     println!("{}", v);
    |                    ^ use of possibly-uninitialized `v`
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index 4eb41ca24ddfe1e72b21ae9dd2b08365fc393fe7..e29cf7a1a7519bb8abde2c717b71416354e0b235 100644 (file)
@@ -3,12 +3,16 @@ error[E0381]: borrow of possibly-uninitialized variable: `x`
    |
 LL |     println!("{}", x);
    |                    ^ use of possibly-uninitialized `x`
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0381]: borrow of possibly-uninitialized variable: `x`
   --> $DIR/issue-24267-flow-exit.rs:18:20
    |
 LL |     println!("{}", x);
    |                    ^ use of possibly-uninitialized `x`
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors
 
index 1cdcc18632c62c3193abdca0616cca1c060c089b..10400cff5e51c33396addda8af0a1930e6963b34 100644 (file)
@@ -1,5 +1,5 @@
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:19:46
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:17:46
    |
 LL |     pub fn e(x: &'static mut isize) {
    |              - help: consider changing this to be mutable: `mut x`
@@ -8,7 +8,7 @@ LL |         let mut c1 = |y: &'static mut isize| x = y;
    |                                              ^^^^^ cannot assign
 
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:30:50
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:28:50
    |
 LL |     pub fn ee(x: &'static mut isize) {
    |               - help: consider changing this to be mutable: `mut x`
@@ -17,7 +17,7 @@ LL |             let mut c2 = |y: &'static mut isize| x = y;
    |                                                  ^^^^^ cannot assign
 
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:42:14
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:40:14
    |
 LL |     pub fn capture_assign_whole(x: (i32,)) {
    |                                 - help: consider changing this to be mutable: `mut x`
@@ -25,7 +25,7 @@ LL |         || { x = (1,); };
    |              ^^^^^^^^ cannot assign
 
 error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:47:14
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:45:14
    |
 LL |     pub fn capture_assign_part(x: (i32,)) {
    |                                - help: consider changing this to be mutable: `mut x`
@@ -33,7 +33,7 @@ LL |         || { x.0 = 1; };
    |              ^^^^^^^ cannot assign
 
 error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:52:14
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:50:14
    |
 LL |     pub fn capture_reborrow_whole(x: (i32,)) {
    |                                   - help: consider changing this to be mutable: `mut x`
@@ -41,7 +41,7 @@ LL |         || { &mut x; };
    |              ^^^^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:57:14
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:55:14
    |
 LL |     pub fn capture_reborrow_part(x: (i32,)) {
    |                                  - help: consider changing this to be mutable: `mut x`
index 1cdcc18632c62c3193abdca0616cca1c060c089b..10400cff5e51c33396addda8af0a1930e6963b34 100644 (file)
@@ -1,5 +1,5 @@
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:19:46
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:17:46
    |
 LL |     pub fn e(x: &'static mut isize) {
    |              - help: consider changing this to be mutable: `mut x`
@@ -8,7 +8,7 @@ LL |         let mut c1 = |y: &'static mut isize| x = y;
    |                                              ^^^^^ cannot assign
 
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:30:50
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:28:50
    |
 LL |     pub fn ee(x: &'static mut isize) {
    |               - help: consider changing this to be mutable: `mut x`
@@ -17,7 +17,7 @@ LL |             let mut c2 = |y: &'static mut isize| x = y;
    |                                                  ^^^^^ cannot assign
 
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:42:14
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:40:14
    |
 LL |     pub fn capture_assign_whole(x: (i32,)) {
    |                                 - help: consider changing this to be mutable: `mut x`
@@ -25,7 +25,7 @@ LL |         || { x = (1,); };
    |              ^^^^^^^^ cannot assign
 
 error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:47:14
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:45:14
    |
 LL |     pub fn capture_assign_part(x: (i32,)) {
    |                                - help: consider changing this to be mutable: `mut x`
@@ -33,7 +33,7 @@ LL |         || { x.0 = 1; };
    |              ^^^^^^^ cannot assign
 
 error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:52:14
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:50:14
    |
 LL |     pub fn capture_reborrow_whole(x: (i32,)) {
    |                                   - help: consider changing this to be mutable: `mut x`
@@ -41,7 +41,7 @@ LL |         || { &mut x; };
    |              ^^^^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:57:14
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:55:14
    |
 LL |     pub fn capture_reborrow_part(x: (i32,)) {
    |                                  - help: consider changing this to be mutable: `mut x`
index 751a911a6bb862c4bb68580741941912a0d11e3d..fe7ed8ed3fa248cf2769f5c2e248430a6964daf7 100644 (file)
@@ -3,15 +3,13 @@
 // looks at some parent.
 
 // revisions: migrate nll
+//[nll]compile-flags: -Z borrowck=mir
 
 // Since we are testing nll (and migration) explicitly as a separate
 // revisions, don't worry about the --compare-mode=nll on this test.
 
 // ignore-compare-mode-nll
 
-//[nll]compile-flags: -Z borrowck=mir
-
-
 // transcribed from borrowck-closures-unique.rs
 mod borrowck_closures_unique {
     pub fn e(x: &'static mut isize) {
diff --git a/src/test/ui/borrowck/issue-58776-borrowck-scans-children.migrate.stderr b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.migrate.stderr
deleted file mode 100644 (file)
index efd4e1a..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-error[E0506]: cannot assign to `greeting` because it is borrowed
-  --> $DIR/issue-58776-borrowck-scans-children.rs:11:5
-   |
-LL |     let res = (|| (|| &greeting)())();
-   |                --      -------- borrow occurs due to use in closure
-   |                |
-   |                borrow of `greeting` occurs here
-LL | 
-LL |     greeting = "DEALLOCATED".to_string();
-   |     ^^^^^^^^ assignment to borrowed `greeting` occurs here
-...
-LL |     println!("thread result: {:?}", res);
-   |                                     --- borrow later used here
-
-error[E0505]: cannot move out of `greeting` because it is borrowed
-  --> $DIR/issue-58776-borrowck-scans-children.rs:14:10
-   |
-LL |     let res = (|| (|| &greeting)())();
-   |                --      -------- borrow occurs due to use in closure
-   |                |
-   |                borrow of `greeting` occurs here
-...
-LL |     drop(greeting);
-   |          ^^^^^^^^ move out of `greeting` occurs here
-...
-LL |     println!("thread result: {:?}", res);
-   |                                     --- borrow later used here
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0505, E0506.
-For more information about an error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/issue-91206.rs b/src/test/ui/borrowck/issue-91206.rs
new file mode 100644 (file)
index 0000000..3b1fbf4
--- /dev/null
@@ -0,0 +1,15 @@
+struct TestClient;
+
+impl TestClient {
+    fn get_inner_ref(&self) -> &Vec<usize> {
+        todo!()
+    }
+}
+
+fn main() {
+    let client = TestClient;
+    let inner = client.get_inner_ref();
+    //~^ HELP consider changing this to be a mutable reference
+    inner.clear();
+    //~^ ERROR cannot borrow `*inner` as mutable, as it is behind a `&` reference [E0596]
+}
diff --git a/src/test/ui/borrowck/issue-91206.stderr b/src/test/ui/borrowck/issue-91206.stderr
new file mode 100644 (file)
index 0000000..535d247
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0596]: cannot borrow `*inner` as mutable, as it is behind a `&` reference
+  --> $DIR/issue-91206.rs:13:5
+   |
+LL |     let inner = client.get_inner_ref();
+   |         ----- help: consider changing this to be a mutable reference: `&mut Vec<usize>`
+LL |
+LL |     inner.clear();
+   |     ^^^^^^^^^^^^^ `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/cast/issue-88621.rs b/src/test/ui/cast/issue-88621.rs
new file mode 100644 (file)
index 0000000..9242b80
--- /dev/null
@@ -0,0 +1,13 @@
+#![feature(arbitrary_enum_discriminant)]
+
+#[repr(u8)]
+enum Kind2 {
+    Foo() = 1,
+    Bar{} = 2,
+    Baz = 3,
+}
+
+fn main() {
+    let _ = Kind2::Foo() as u8;
+    //~^ ERROR non-primitive cast
+}
diff --git a/src/test/ui/cast/issue-88621.stderr b/src/test/ui/cast/issue-88621.stderr
new file mode 100644 (file)
index 0000000..e96d866
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0605]: non-primitive cast: `Kind2` as `u8`
+  --> $DIR/issue-88621.rs:11:13
+   |
+LL |     let _ = Kind2::Foo() as u8;
+   |             ^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0605`.
index a3f2f25e447e1ac500cff609f5136a058678adb7..f6c219018321141366399327174683f57402511e 100644 (file)
@@ -81,6 +81,8 @@ LL |     println!("{}", arr[3]);
 ...
 LL |     c();
    |     - mutable borrow later used here
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0502]: cannot borrow `arr` as immutable because it is also borrowed as mutable
   --> $DIR/arrays.rs:73:24
index 2badf0514187eb135ec44b6d9cf4ca04bfd0c83d..29228d85324ef3f39476fb7cd1b558786064d838 100644 (file)
@@ -25,6 +25,8 @@ LL |     println!("{}", e.0.0.m.x);
 LL |
 LL |     c();
    |     - mutable borrow later used here
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0506]: cannot assign to `e.0.0.m.x` because it is borrowed
   --> $DIR/box.rs:55:5
index d2466681a0877a24836da8cd4ed7d180699ec12e..5acf3797ab53feb51128c32fc6248509ea116d60 100644 (file)
@@ -8,6 +8,7 @@ LL |         println!("{}", foo.x);
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = note: this warning originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 warning: 1 warning emitted
 
index 32705af3d016623eba451e00feba3c98ef12328c..4f9fdbd368a88e1e8e3ac2cd93f19687c00f0605 100644 (file)
@@ -13,6 +13,8 @@ LL |     println!("{:?}", p);
 LL |
 LL |     c();
    |     - mutable borrow later used here
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index e067dbbf85bddbfcb03004c38991f4f29f202f5b..ceb91142ac82699eb6dc1be7aecc37a19a659acc 100644 (file)
@@ -14,6 +14,7 @@ note: this function takes ownership of the receiver `self`, which moves `some_ve
    |
 LL |     fn into_iter(self) -> Self::IntoIter;
    |                  ^^^^
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/assert-type-intrinsics.rs b/src/test/ui/consts/assert-type-intrinsics.rs
new file mode 100644 (file)
index 0000000..31ff6ae
--- /dev/null
@@ -0,0 +1,22 @@
+// error-pattern: any use of this value will cause an error
+
+#![feature(never_type)]
+#![feature(const_maybe_uninit_assume_init, const_assert_type2)]
+#![feature(core_intrinsics)]
+
+use std::intrinsics;
+
+#[allow(invalid_value)]
+fn main() {
+    use std::mem::MaybeUninit;
+
+    const _BAD1: () = unsafe {
+        MaybeUninit::<!>::uninit().assume_init();
+    };
+    const _BAD2: () = unsafe {
+        intrinsics::assert_uninit_valid::<bool>();
+    };
+    const _BAD3: () = unsafe {
+        intrinsics::assert_zero_valid::<&'static i32>();
+    };
+}
diff --git a/src/test/ui/consts/assert-type-intrinsics.stderr b/src/test/ui/consts/assert-type-intrinsics.stderr
new file mode 100644 (file)
index 0000000..bb57ee8
--- /dev/null
@@ -0,0 +1,39 @@
+error: any use of this value will cause an error
+  --> $DIR/assert-type-intrinsics.rs:14:9
+   |
+LL | /     const _BAD1: () = unsafe {
+LL | |         MaybeUninit::<!>::uninit().assume_init();
+   | |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!`
+LL | |     };
+   | |______-
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: any use of this value will cause an error
+  --> $DIR/assert-type-intrinsics.rs:17:9
+   |
+LL | /     const _BAD2: () = unsafe {
+LL | |         intrinsics::assert_uninit_valid::<bool>();
+   | |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to leave type `bool` uninitialized, which is invalid
+LL | |     };
+   | |______-
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: any use of this value will cause an error
+  --> $DIR/assert-type-intrinsics.rs:20:9
+   |
+LL | /     const _BAD3: () = unsafe {
+LL | |         intrinsics::assert_zero_valid::<&'static i32>();
+   | |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `&i32`, which is invalid
+LL | |     };
+   | |______-
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/consts/assume-type-intrinsics.rs b/src/test/ui/consts/assume-type-intrinsics.rs
deleted file mode 100644 (file)
index 77370e1..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// error-pattern: any use of this value will cause an error
-
-#![feature(never_type)]
-#![feature(const_maybe_uninit_assume_init)]
-
-#[allow(invalid_value)]
-fn main() {
-    use std::mem::MaybeUninit;
-
-    const _BAD: () = unsafe {
-        MaybeUninit::<!>::uninit().assume_init();
-    };
-}
diff --git a/src/test/ui/consts/assume-type-intrinsics.stderr b/src/test/ui/consts/assume-type-intrinsics.stderr
deleted file mode 100644 (file)
index e660730..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error: any use of this value will cause an error
-  --> $DIR/assume-type-intrinsics.rs:11:9
-   |
-LL | /     const _BAD: () = unsafe {
-LL | |         MaybeUninit::<!>::uninit().assume_init();
-   | |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!`
-LL | |     };
-   | |______-
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error: aborting due to previous error
-
index 3bd5ed8f8c924099e2906f18c8ea735441bb3d32..5e6d7d899ec1ea87bc5c311126b980a385d17617 100644 (file)
@@ -1,6 +1,6 @@
-static a: &'static str = "foo";
-static b: *const u8 = a as *const u8; //~ ERROR casting
-static c: *const u8 = &a as *const u8; //~ ERROR casting
+const a: &str = "foo";
+const b: *const u8 = a as *const u8; //~ ERROR casting
+const c: *const u8 = &a as *const u8; //~ ERROR casting
 
 fn main() {
 }
index 9960ccb4166b5aea72447418334c81b85d444512..9e622de2eb004ecdff911c191ebf42ac80a3c24d 100644 (file)
@@ -1,14 +1,14 @@
 error[E0606]: casting `&'static str` as `*const u8` is invalid
-  --> $DIR/const-cast-different-types.rs:2:23
+  --> $DIR/const-cast-different-types.rs:2:22
    |
-LL | static b: *const u8 = a as *const u8;
-   |                       ^^^^^^^^^^^^^^
+LL | const b: *const u8 = a as *const u8;
+   |                      ^^^^^^^^^^^^^^
 
 error[E0606]: casting `&&'static str` as `*const u8` is invalid
-  --> $DIR/const-cast-different-types.rs:3:23
+  --> $DIR/const-cast-different-types.rs:3:22
    |
-LL | static c: *const u8 = &a as *const u8;
-   |                       ^^^^^^^^^^^^^^^
+LL | const c: *const u8 = &a as *const u8;
+   |                      ^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index c250cc53dbc2b07dd73eb7b35be00de060b90748..6e055a2bcd34029c24e55e05d4f02189be052fd7 100644 (file)
@@ -1,5 +1,5 @@
-static a: [u8; 3] = ['h' as u8, 'i' as u8, 0 as u8];
-static b: *const i8 = &a as *const i8; //~ ERROR mismatched types
+const a: [u8; 3] = ['h' as u8, 'i' as u8, 0 as u8];
+const b: *const i8 = &a as *const i8; //~ ERROR mismatched types
 
 fn main() {
 }
index 282f5ccde772fd62c511e001ec7eeaad68fbad3c..ee186636e4ebe0fe61c7127b2153a658d78505c7 100644 (file)
@@ -1,8 +1,8 @@
 error[E0308]: mismatched types
-  --> $DIR/const-cast-wrong-type.rs:2:23
+  --> $DIR/const-cast-wrong-type.rs:2:22
    |
-LL | static b: *const i8 = &a as *const i8;
-   |                       ^^^^^^^^^^^^^^^ expected `u8`, found `i8`
+LL | const b: *const i8 = &a as *const i8;
+   |                      ^^^^^^^^^^^^^^^ expected `u8`, found `i8`
 
 error: aborting due to previous error
 
index 031f2121a1ee258cc792fd08783c6b95bcb96362..a8633fd87b5e2750ae6261c27cb105e0a71b2a1c 100644 (file)
@@ -1,5 +1,5 @@
 // build-fail
-// compile-flags: -Zforce-overflow-checks=on
+// compile-flags: -overflow-checks=on
 
 #![allow(arithmetic_overflow)]
 #![warn(const_err)]
index 356a7f58d8562eb36e1221c218e059ab05d70e2f..9dc40030a6ff8b1a2a3530d411c327604508145b 100644 (file)
@@ -28,6 +28,7 @@ LL |     println!("{}", 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 #71800 <https://github.com/rust-lang/rust/issues/71800>
+   = note: this warning originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error; 2 warnings emitted
 
index d4d8cbc669a7bf3a4a970eddda29d2cbf6f2e61d..32ab7c74b891f894f708b50e0af77b4e00c733f3 100644 (file)
@@ -39,6 +39,7 @@ LL |     println!("{} {}", X, Y);
    |
    = 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 #71800 <https://github.com/rust-lang/rust/issues/71800>
+   = note: this warning originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/issue-43197.rs:16:26
@@ -54,6 +55,7 @@ LL |     println!("{} {}", X, Y);
    |
    = 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 #71800 <https://github.com/rust-lang/rust/issues/71800>
+   = note: this warning originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors; 4 warnings emitted
 
diff --git a/src/test/ui/consts/drop_zst.rs b/src/test/ui/consts/drop_zst.rs
new file mode 100644 (file)
index 0000000..f7c70d3
--- /dev/null
@@ -0,0 +1,17 @@
+// check-fail
+
+#![feature(const_precise_live_drops)]
+
+struct S;
+
+impl Drop for S {
+    fn drop(&mut self) {
+        println!("Hello!");
+    }
+}
+
+const fn foo() {
+    let s = S; //~ destructor
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/drop_zst.stderr b/src/test/ui/consts/drop_zst.stderr
new file mode 100644 (file)
index 0000000..d4be5aa
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/drop_zst.rs:14:9
+   |
+LL |     let s = S;
+   |         ^ constant functions cannot evaluate destructors
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0493`.
index 7e3f18cc9d5931a20534204415421179323537e2..ac5640646a814bb84e208db725e106e91cdfd3ed 100644 (file)
@@ -1,7 +1,5 @@
  #![l=|x|[b;x ]] //~ ERROR unexpected token: `|x| [b; x]`
 //~^ ERROR cannot find attribute `l` in this scope
-//~^^ ERROR attempt to use a non-constant value in a constant [E0435]
-//~^^^ ERROR cannot find value `b` in this scope [E0425]
 
 // notice the space at the start,
 // we can't attach any attributes to this file because it needs to be at the start
index 9e167424995a7dc5fde235d5be51bc277fc5369e..4ccce36eedf70435d08b3986fbbd2c9105015b8c 100644 (file)
@@ -10,21 +10,5 @@ error: cannot find attribute `l` in this scope
 LL |  #![l=|x|[b;x ]]
    |     ^
 
-error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/issue-90878-2.rs:1:13
-   |
-LL |  #![l=|x|[b;x ]]
-   |        -    ^
-   |        |
-   |        this would need to be a `const`
-
-error[E0425]: cannot find value `b` in this scope
-  --> $DIR/issue-90878-2.rs:1:11
-   |
-LL |  #![l=|x|[b;x ]]
-   |           ^ help: a local variable with a similar name exists: `x`
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0425, E0435.
-For more information about an error, try `rustc --explain E0425`.
index 77c29090a3ee094ddf9458608faa6b56c78d1bcf..aea861e3261b5fc8a19f5be0e18f5b35e371a189 100644 (file)
@@ -6,3 +6,5 @@
 #![no_std]
 use ::foo; //~ ERROR invalid metadata files for crate `foo`
 //~| NOTE failed to mmap file
+//~^^ ERROR invalid metadata files for crate `foo`
+//~| NOTE failed to mmap file
index b2c79f742fb3090cfc84dba8a9ab1af5e61d3799..3c0d23bf7b4cce575aae1978e32884981535d356 100644 (file)
@@ -6,6 +6,14 @@ LL | use ::foo;
    |
    = note: failed to mmap file 'auxiliary/libfoo.rlib'
 
-error: aborting due to previous error
+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 2 previous errors
 
 For more information about this error, try `rustc --explain E0786`.
index 1a34c21ba541370129ee2d367550506a06ec9f14..400d9f6e0ba12c94b6b6b1e414a07f13322518b1 100644 (file)
@@ -1,6 +1,7 @@
 // compile-flags: --target x86_64-unknown-uefi
 // needs-llvm-components: x86
 // rustc-env:CARGO=/usr/bin/cargo
+#![feature(no_core)]
 #![no_core]
 extern crate core;
 //~^ ERROR can't find crate for `core`
index 25808efdfa6993e94c45af96bfd0878e1598f4ad..70bcae1e0edd076cb843a176948814a7f569ff4c 100644 (file)
@@ -1,5 +1,5 @@
 error[E0463]: can't find crate for `core`
-  --> $DIR/missing-std.rs:5:1
+  --> $DIR/missing-std.rs:6:1
    |
 LL | extern crate core;
    | ^^^^^^^^^^^^^^^^^^ can't find crate
@@ -8,6 +8,8 @@ LL | extern crate core;
    = help: consider downloading the target with `rustup target add x86_64-unknown-uefi`
    = help: consider building the standard library from source with `cargo build -Zbuild-std`
 
-error: aborting due to previous error
+error: requires `sized` lang_item
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0463`.
index 04e46233532b204dca5477dc255b4bc6311b9580..b326dbbbc1405aa6878025adc299b196c9bb5911 100644 (file)
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/dst-bad-assign-3.rs:33:12
    |
 LL |     f5.2 = Bar1 {f: 36};
-   |            ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1`
+   |     ----   ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1`
+   |     |
+   |     expected due to the type of this binding
    |
    = note: expected trait object `dyn ToBar`
                     found struct `Bar1`
index f87a34c6d37839f0eb48aa780fbfe7af692ded75..614f213875129fa0fb1124b92ff899534000f4fc 100644 (file)
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/dst-bad-assign.rs:35:14
    |
 LL |     f5.ptr = Bar1 {f: 36};
-   |              ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1`
+   |     ------   ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1`
+   |     |
+   |     expected due to the type of this binding
    |
    = note: expected trait object `dyn ToBar`
                     found struct `Bar1`
index 6aa170fdfd2a77aea894d41a2ec135e1047841f9..c731c32832222f7d480fadea359dd2a641920362 100644 (file)
@@ -21,7 +21,7 @@ LL |     type MainFn = impl Fn();
 LL |     pub const BAR: MainFn = bar;
    |                             ^^^ expected opaque type, found fn item
    |
-   = note: expected opaque type `impl Fn<()>`
+   = note: expected opaque type `impl Fn()`
                   found fn item `fn() {bar}`
 
 error: could not find defining uses
index 22c5332c9259fe9dbec36648690045cd8253fecc..ccc423e4a194cf2c357dd1113e969a87458d31ea 100644 (file)
@@ -22,14 +22,6 @@ impl Enum {
     }
 }
 
-#[allow(dead_code)]
-#[repr(u8)]
-enum FieldlessEnum {
-    Unit = 3,
-    Tuple() = 2,
-    Struct {} = 1,
-}
-
 fn main() {
     const UNIT: Enum = Enum::Unit;
     const TUPLE: Enum = Enum::Tuple(5);
@@ -48,9 +40,4 @@ fn main() {
     assert_eq!(3, UNIT_TAG);
     assert_eq!(2, TUPLE_TAG);
     assert_eq!(1, STRUCT_TAG);
-
-    // Ensure `as` conversions are correct
-    assert_eq!(3, FieldlessEnum::Unit as u8);
-    assert_eq!(2, FieldlessEnum::Tuple() as u8);
-    assert_eq!(1, FieldlessEnum::Struct{} as u8);
 }
index ab956d81098388dcae73cfb409fac6f2a5f099b3..3aae0c9ff6e72ffd4e092e4cc62796ee63fa92d3 100644 (file)
@@ -6,7 +6,6 @@ fn some_function() {
     SOME_CONST = 14; //~ ERROR E0070
     1 = 3; //~ ERROR E0070
     some_other_func() = 4; //~ ERROR E0070
-                           //~^ ERROR E0308
 }
 
 fn main() {
index e24d498e3520c878bccfdcc179b1ce4bcb6d44aa..8868bc257a70317e7f25dcf2042477ead9ea0caf 100644 (file)
@@ -22,13 +22,6 @@ LL |     some_other_func() = 4;
    |     |
    |     cannot assign to this expression
 
-error[E0308]: mismatched types
-  --> $DIR/E0070.rs:8:25
-   |
-LL |     some_other_func() = 4;
-   |                         ^ expected `()`, found integer
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0070, E0308.
-For more information about an error, try `rustc --explain E0070`.
+For more information about this error, try `rustc --explain E0070`.
index 1060675cd45f4937460cc0e655163faf136354be..fb082bc1eabcf51bcd907f1e6d7e802fa2a4188f 100644 (file)
@@ -1,5 +1,5 @@
 error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be statically determined
-  --> $DIR/E0161.rs:29:5
+  --> $DIR/E0161.rs:32:5
    |
 LL |     x.f();
    |     ^^^^^
index 1060675cd45f4937460cc0e655163faf136354be..fb082bc1eabcf51bcd907f1e6d7e802fa2a4188f 100644 (file)
@@ -1,5 +1,5 @@
 error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be statically determined
-  --> $DIR/E0161.rs:29:5
+  --> $DIR/E0161.rs:32:5
    |
 LL |     x.f();
    |     ^^^^^
index 1060675cd45f4937460cc0e655163faf136354be..fb082bc1eabcf51bcd907f1e6d7e802fa2a4188f 100644 (file)
@@ -1,5 +1,5 @@
 error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be statically determined
-  --> $DIR/E0161.rs:29:5
+  --> $DIR/E0161.rs:32:5
    |
 LL |     x.f();
    |     ^^^^^
index ba74529e4b6e43f6bdf837c88333b60891bb843a..f3a7b68c7cf850eac4521ad4082321152d58e42d 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-compare-mode-nll
-
 // Check that E0161 is a hard error in all possible configurations that might
 // affect it.
 
 //[zflagsul] check-pass
 //[editionul] check-pass
 
+// Since we are testing nll (and migration) explicitly as a separate
+// revisions, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
 #![allow(incomplete_features)]
 #![cfg_attr(nll, feature(nll))]
 #![cfg_attr(nllul, feature(nll))]
index 1060675cd45f4937460cc0e655163faf136354be..fb082bc1eabcf51bcd907f1e6d7e802fa2a4188f 100644 (file)
@@ -1,5 +1,5 @@
 error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be statically determined
-  --> $DIR/E0161.rs:29:5
+  --> $DIR/E0161.rs:32:5
    |
 LL |     x.f();
    |     ^^^^^
index ee2bb62e2bb5753877833f84b7479480b9469d84..d3f6ca07617f4ced46de000122fe607bb0b65759 100644 (file)
@@ -7,7 +7,11 @@ LL |     if 5 == {
 LL | }
    | ^ expected `{`
    |
-   = help: maybe you forgot the right operand of the condition?
+help: maybe you forgot the right operand of the condition?
+  --> $DIR/if-without-block.rs:3:10
+   |
+LL |     if 5 == {
+   |          ^^
 
 error: aborting due to previous error
 
index d3cb5aaaeba89095fed6fbae4ac5cdfc7427d8ac..3170537b0e0a088f61916102199d1b5b27c86526 100644 (file)
@@ -1,4 +1,6 @@
 // compile-flags: --extern std=
 // error-pattern: extern location for std does not exist
+// needs-unwind since it affects the error output
+// ignore-emscripten compiled with panic=abort, personality not required
 
 fn main() {}
index 199c4fb616b53bcd9f213d02af068bbc789c929f..b0628a4f6dd62a68fe6b8fe0490c293a45753dc4 100644 (file)
@@ -1,4 +1,8 @@
 error: extern location for std does not exist: 
 
-error: aborting due to previous error
+error: language item required, but not found: `eh_personality`
+
+error: `#[panic_handler]` function required, but not found
+
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/extern/extern-crate-multiple-missing.rs b/src/test/ui/extern/extern-crate-multiple-missing.rs
new file mode 100644 (file)
index 0000000..a6560ca
--- /dev/null
@@ -0,0 +1,10 @@
+// If multiple `extern crate` resolutions fail each of them should produce an error
+extern crate bar; //~ ERROR can't find crate for `bar`
+extern crate foo; //~ ERROR can't find crate for `foo`
+
+fn main() {
+    // If the crate name introduced by `extern crate` failed to resolve then subsequent
+    // derived paths do not emit additional errors
+    foo::something();
+    bar::something();
+}
diff --git a/src/test/ui/extern/extern-crate-multiple-missing.stderr b/src/test/ui/extern/extern-crate-multiple-missing.stderr
new file mode 100644 (file)
index 0000000..893bb4f
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0463]: can't find crate for `bar`
+  --> $DIR/extern-crate-multiple-missing.rs:2:1
+   |
+LL | extern crate bar;
+   | ^^^^^^^^^^^^^^^^^ can't find crate
+
+error[E0463]: can't find crate for `foo`
+  --> $DIR/extern-crate-multiple-missing.rs:3:1
+   |
+LL | extern crate foo;
+   | ^^^^^^^^^^^^^^^^^ can't find crate
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0463`.
diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type-2.rs b/src/test/ui/fn/implied-bounds-unnorm-associated-type-2.rs
new file mode 100644 (file)
index 0000000..5a92bcd
--- /dev/null
@@ -0,0 +1,22 @@
+// check-pass
+
+trait Trait {
+    type Type;
+}
+
+impl<T> Trait for T {
+    type Type = ();
+}
+
+fn f<'a, 'b>(_: <&'a &'b () as Trait>::Type)
+where
+    'a: 'a,
+    'b: 'b,
+{
+}
+
+fn g<'a, 'b>() {
+    f::<'a, 'b>(());
+}
+
+fn main() {}
diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type.nll.stderr b/src/test/ui/fn/implied-bounds-unnorm-associated-type.nll.stderr
new file mode 100644 (file)
index 0000000..e37ec7f
--- /dev/null
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+  --> $DIR/implied-bounds-unnorm-associated-type.rs:14:5
+   |
+LL | fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str {
+   |      --  -- lifetime `'b` defined here
+   |      |
+   |      lifetime `'a` defined here
+LL |     s
+   |     ^ returning this value requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type.rs b/src/test/ui/fn/implied-bounds-unnorm-associated-type.rs
new file mode 100644 (file)
index 0000000..2e5ac7d
--- /dev/null
@@ -0,0 +1,22 @@
+// check-fail
+// See issue #91068. Types in the substs of an associated type can't be implied
+// to be WF, since they don't actually have to be constructed.
+
+trait Trait {
+    type Type;
+}
+
+impl<T> Trait for T {
+    type Type = ();
+}
+
+fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str {
+    s //~ ERROR lifetime mismatch [E0623]
+}
+
+fn main() {
+    let x = String::from("Hello World!");
+    let y = f(&x, ());
+    drop(x);
+    println!("{}", y);
+}
diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type.stderr b/src/test/ui/fn/implied-bounds-unnorm-associated-type.stderr
new file mode 100644 (file)
index 0000000..93ab5dc
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/implied-bounds-unnorm-associated-type.rs:14:5
+   |
+LL | fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str {
+   |                 -------      ----------
+   |                 |
+   |                 these two types are declared with different lifetimes...
+LL |     s
+   |     ^ ...but data from `s` flows here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
index 1c6b9805b51b64e0f02e318c2901b422a6af7d9a..229c174daa86493e75ebf3fa4da83254a2645693 100644 (file)
@@ -1,10 +1,10 @@
 // Test that we use fully-qualified type names in error messages.
 
 fn main() {
-    let x: Option<usize>;
+    let x: //~ NOTE expected due to the type of this binding
+        Option<usize>; //~ NOTE expected due to this type
     x = 5;
     //~^ ERROR mismatched types
-    //~| expected enum `Option<usize>`
-    //~| found type `{integer}`
-    //~| expected enum `Option`, found integer
+    //~| NOTE expected enum `Option<usize>`
+    //~| NOTE expected enum `Option`, found integer
 }
index 03fb299b39cd2e11721ef522431735637305485c..4750c5ccdf7029c993aceba5b5f00547ae3c1db1 100644 (file)
@@ -1,6 +1,10 @@
 error[E0308]: mismatched types
-  --> $DIR/fully-qualified-type-name1.rs:5:9
+  --> $DIR/fully-qualified-type-name1.rs:6:9
    |
+LL |     let x:
+   |         - expected due to the type of this binding
+LL |         Option<usize>;
+   |         ------------- expected due to this type
 LL |     x = 5;
    |         ^ expected enum `Option`, found integer
    |
index c3fc8dd8f92869111f3997310c3cc3542c5d2ca3..a7d7a732548869911355fdea83ebb0616c5f2bd6 100644 (file)
@@ -9,7 +9,7 @@ note: generator is not `Send` as this value is used across a yield
   --> $DIR/issue-68112.rs:31:9
    |
 LL |         let _non_send_gen = make_non_send_generator();
-   |             ------------- has type `impl Generator` which is not `Send`
+   |             ------------- has type `impl Generator<Return = Arc<RefCell<i32>>>` which is not `Send`
 LL |         yield;
    |         ^^^^^ yield occurs here, with `_non_send_gen` maybe used later
 LL |     };
@@ -29,9 +29,9 @@ LL |     require_send(send_gen);
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>`
    = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:38:5: 41:6]`
-   = note: required because it appears within the type `impl Generator`
-   = note: required because it appears within the type `impl Generator`
-   = note: required because it appears within the type `{impl Generator, ()}`
+   = note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>`
+   = note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>`
+   = note: required because it appears within the type `{impl Generator<Return = Arc<RefCell<i32>>>, ()}`
    = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:48:20: 51:6]`
 note: required by a bound in `require_send`
   --> $DIR/issue-68112.rs:22:25
index 68d785efcfe5d5620fa1e6c89604c92a74fd8d9f..67cd1f64d94aad1130f672fe48a3c3e320035938 100644 (file)
@@ -10,6 +10,8 @@ LL |     println!("{}", x);
    |                    ^ second borrow occurs here
 LL |     Pin::new(&mut b).resume(());
    |              ------ first borrow later used here
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generic-associated-types/equality-bound.rs b/src/test/ui/generic-associated-types/equality-bound.rs
new file mode 100644 (file)
index 0000000..fcc2da8
--- /dev/null
@@ -0,0 +1,15 @@
+fn sum<I: Iterator<Item = ()>>(i: I) -> i32 where I::Item = i32 {
+//~^ ERROR equality constraints are not yet supported in `where` clauses
+    panic!()
+}
+fn sum2<I: Iterator>(i: I) -> i32 where I::Item = i32 {
+//~^ ERROR equality constraints are not yet supported in `where` clauses
+    panic!()
+}
+fn sum3<J: Iterator>(i: J) -> i32 where I::Item = i32 {
+//~^ ERROR equality constraints are not yet supported in `where` clauses
+//~| ERROR failed to resolve: use of undeclared type `I`
+    panic!()
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/equality-bound.stderr b/src/test/ui/generic-associated-types/equality-bound.stderr
new file mode 100644 (file)
index 0000000..2743264
--- /dev/null
@@ -0,0 +1,43 @@
+error: equality constraints are not yet supported in `where` clauses
+  --> $DIR/equality-bound.rs:1:51
+   |
+LL | fn sum<I: Iterator<Item = ()>>(i: I) -> i32 where I::Item = i32 {
+   |                                                   ^^^^^^^^^^^^^ not supported
+   |
+   = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
+help: if `Iterator::Item` is an associated type you're trying to set, use the associated type binding syntax
+   |
+LL - fn sum<I: Iterator<Item = ()>>(i: I) -> i32 where I::Item = i32 {
+LL + fn sum<I: Iterator<Item = (), Item = i32>>(i: I) -> i32 where  {
+   | 
+
+error: equality constraints are not yet supported in `where` clauses
+  --> $DIR/equality-bound.rs:5:41
+   |
+LL | fn sum2<I: Iterator>(i: I) -> i32 where I::Item = i32 {
+   |                                         ^^^^^^^^^^^^^ not supported
+   |
+   = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
+help: if `Iterator::Item` is an associated type you're trying to set, use the associated type binding syntax
+   |
+LL - fn sum2<I: Iterator>(i: I) -> i32 where I::Item = i32 {
+LL + fn sum2<I: Iterator<Item = i32>>(i: I) -> i32 where  {
+   | 
+
+error: equality constraints are not yet supported in `where` clauses
+  --> $DIR/equality-bound.rs:9:41
+   |
+LL | fn sum3<J: Iterator>(i: J) -> i32 where I::Item = i32 {
+   |                                         ^^^^^^^^^^^^^ not supported
+   |
+   = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
+
+error[E0433]: failed to resolve: use of undeclared type `I`
+  --> $DIR/equality-bound.rs:9:41
+   |
+LL | fn sum3<J: Iterator>(i: J) -> i32 where I::Item = i32 {
+   |                                         ^ use of undeclared type `I`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/generic-associated-types/issue-87748.rs b/src/test/ui/generic-associated-types/issue-87748.rs
deleted file mode 100644 (file)
index 93c3b39..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// Checks that we properly add implied bounds from unnormalized projections in
-// inputs when typechecking functions.
-
-// check-pass
-
-#![feature(generic_associated_types)]
-
-trait MyTrait {
-    type Assoc<'a, 'b> where 'b: 'a;
-    fn do_sth(arg: Self::Assoc<'_, '_>);
-}
-
-struct A;
-struct B;
-struct C;
-
-impl MyTrait for A {
-    type Assoc<'a, 'b> where 'b: 'a = u32;
-    fn do_sth(_: u32) {}
-}
-impl MyTrait for B {
-    type Assoc<'a, 'b> where 'b: 'a = u32;
-    fn do_sth(_: Self::Assoc<'_, '_>) {}
-}
-impl MyTrait for C {
-    type Assoc<'a, 'b> where 'b: 'a = u32;
-    fn do_sth(_: Self::Assoc<'static, 'static>) {}
-}
-
-fn main () {}
index 54478d16282452334dcdfd7e18a99e2d099f70ab..0e234120a51c5840a5a903c84772647bca701425 100644 (file)
@@ -34,11 +34,12 @@ impl<B: std::ops::Add<Output = B>> Add for D<B> {
 
 struct E<B>(B);
 
-impl<B: Add> Add for E<B> where B: Add<Output = B> {
+impl<B: Add> Add for E<B> where B: Add<Output = B>, B: Add<Output = B> {
+    //~^ ERROR equality constraints are not yet supported in `where` clauses
     type Output = Self;
 
     fn add(self, rhs: Self) -> Self {
-        Self(self.0 + rhs.0)
+        Self(self.0 + rhs.0) //~ ERROR mismatched types
     }
 }
 
index 962d2db9476bd73a0b690c940831ec83d567d308..ffafff5e9f586d2543061aaaa616eec501040f8a 100644 (file)
@@ -34,11 +34,12 @@ fn add(self, rhs: Self) -> Self {
 
 struct E<B>(B);
 
-impl<B: Add> Add for E<B> where B: Add<Output = B> {
+impl<B: Add> Add for E<B> where <B as Add>::Output = B {
+    //~^ ERROR equality constraints are not yet supported in `where` clauses
     type Output = Self;
 
     fn add(self, rhs: Self) -> Self {
-        Self(self.0 + rhs.0)
+        Self(self.0 + rhs.0) //~ ERROR mismatched types
     }
 }
 
index 4d33fe84829e0c6f42c25796741b61cc7f4bc570..c9603b8d1ea4a3bcebe045f1630099e1a08f51eb 100644 (file)
@@ -1,3 +1,15 @@
+error: equality constraints are not yet supported in `where` clauses
+  --> $DIR/missing-bounds.rs:37:33
+   |
+LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^ not supported
+   |
+   = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
+help: if `Output` is an associated type you're trying to set, use the associated type binding syntax
+   |
+LL | impl<B: Add> Add for E<B> where B: Add<Output = B> {
+   |                                 ~~~~~~~~~~~~~~~~~~
+
 error[E0308]: mismatched types
   --> $DIR/missing-bounds.rs:11:11
    |
@@ -43,7 +55,23 @@ help: consider restricting type parameter `B`
 LL | impl<B: std::ops::Add<Output = B>> Add for D<B> {
    |       +++++++++++++++++++++++++++
 
-error: aborting due to 3 previous errors
+error[E0308]: mismatched types
+  --> $DIR/missing-bounds.rs:42:14
+   |
+LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
+   |      - this type parameter
+...
+LL |         Self(self.0 + rhs.0)
+   |              ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type
+   |
+   = note: expected type parameter `B`
+             found associated type `<B as Add>::Output`
+help: consider further restricting type parameter `B`
+   |
+LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B, B: Add<Output = B> {
+   |                                                       ++++++++++++++++++++
+
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0308, E0369.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs b/src/test/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs
new file mode 100644 (file)
index 0000000..b50f56b
--- /dev/null
@@ -0,0 +1,11 @@
+// Regression test for #88586: a higher-ranked outlives bound on Self in a trait
+// definition caused an ICE when debug_assertions were enabled.
+//
+// FIXME: The error output in the absence of the ICE is unhelpful; this should be improved.
+
+trait A where for<'a> Self: 'a
+//~^ ERROR the parameter type `Self` may not live long enough
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.stderr b/src/test/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.stderr
new file mode 100644 (file)
index 0000000..18618ff
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0311]: the parameter type `Self` may not live long enough
+  --> $DIR/issue-88586-hr-self-outlives-in-trait-def.rs:6:1
+   |
+LL | / trait A where for<'a> Self: 'a
+LL | |
+LL | | {
+LL | | }
+   | |_^
+   |
+   = help: consider adding an explicit lifetime bound `Self: 'a`...
+   = note: ...so that the type `Self` will meet its required lifetime bounds...
+note: ...that is required by this bound
+  --> $DIR/issue-88586-hr-self-outlives-in-trait-def.rs:6:29
+   |
+LL | trait A where for<'a> Self: 'a
+   |                             ^^
+
+error: aborting due to previous error
+
index 119cec1fa95bfd98b7d6475665193a9722a68f69..7da6b029c26f0f6ad6e712410fa3fe9e16a4fbf0 100644 (file)
@@ -1,5 +1,5 @@
 error: implementation of `Parser` is not general enough
-  --> $DIR/issue-71955.rs:52:5
+  --> $DIR/issue-71955.rs:57:5
    |
 LL |     foo(bar, "string", |s| s.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
@@ -8,7 +8,7 @@ LL |     foo(bar, "string", |s| s.len() == 5);
    = 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
+  --> $DIR/issue-71955.rs:57:5
    |
 LL |     foo(bar, "string", |s| s.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
@@ -17,7 +17,7 @@ LL |     foo(bar, "string", |s| s.len() == 5);
    = 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
+  --> $DIR/issue-71955.rs:57:5
    |
 LL |     foo(bar, "string", |s| s.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
@@ -26,7 +26,7 @@ LL |     foo(bar, "string", |s| s.len() == 5);
    = 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
+  --> $DIR/issue-71955.rs:57:5
    |
 LL |     foo(bar, "string", |s| s.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
@@ -35,7 +35,7 @@ LL |     foo(bar, "string", |s| s.len() == 5);
    = 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
+  --> $DIR/issue-71955.rs:57:5
    |
 LL |     foo(bar, "string", |s| s.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
@@ -44,7 +44,7 @@ LL |     foo(bar, "string", |s| s.len() == 5);
    = 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
+  --> $DIR/issue-71955.rs:63:5
    |
 LL |     foo(baz, "string", |s| s.0.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
@@ -53,7 +53,7 @@ LL |     foo(baz, "string", |s| s.0.len() == 5);
    = 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
+  --> $DIR/issue-71955.rs:63:5
    |
 LL |     foo(baz, "string", |s| s.0.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
@@ -62,7 +62,7 @@ LL |     foo(baz, "string", |s| s.0.len() == 5);
    = 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
+  --> $DIR/issue-71955.rs:63:5
    |
 LL |     foo(baz, "string", |s| s.0.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
@@ -71,7 +71,7 @@ LL |     foo(baz, "string", |s| s.0.len() == 5);
    = 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
+  --> $DIR/issue-71955.rs:63:5
    |
 LL |     foo(baz, "string", |s| s.0.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
@@ -80,7 +80,7 @@ LL |     foo(baz, "string", |s| s.0.len() == 5);
    = 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
+  --> $DIR/issue-71955.rs:63:5
    |
 LL |     foo(baz, "string", |s| s.0.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
index 69ab446bc7a34eacc72b37a770f7f1b31ad758ae..c2feaa91280557c001a6d88fe53b304e89e5905b 100644 (file)
@@ -1,5 +1,5 @@
 error: fatal error triggered by #[rustc_error]
-  --> $DIR/issue-71955.rs:42:1
+  --> $DIR/issue-71955.rs:47:1
    |
 LL | fn main() {
    | ^^^^^^^^^
index 95e3b3d4e1b886db61e612a4ef32ef7fd67dbadc..3d6778b6942c52c8213684d14fc30ae50ff1df9d 100644 (file)
@@ -3,6 +3,11 @@
 // [nll]compile-flags: -Zborrowck=mir
 // check-fail
 
+// Since we are testing nll (and migration) explicitly as a separate
+// revisions, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
 #![feature(rustc_attrs)]
 
 trait Parser<'s> {
index a497c6257dab65226de295274c21664eabc767e6..a2ab1f1856d3ee3ea8f0f34c9e59b42dc0b23def 100644 (file)
@@ -1,5 +1,5 @@
-error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>`, but its trait bounds were not satisfied
-  --> $DIR/issue-30786.rs:128:22
+error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>`, but its trait bounds were not satisfied
+  --> $DIR/issue-30786.rs:127:22
    |
 LL | pub struct Map<S, F> {
    | --------------------
@@ -8,19 +8,19 @@ LL | pub struct Map<S, F> {
    | doesn't satisfy `_: StreamExt`
 ...
 LL |     let filter = map.filterx(|x: &_| true);
-   |                      ^^^^^^^ method cannot be called on `Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>` due to unsatisfied trait bounds
+   |                      ^^^^^^^ method cannot be called on `Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>` due to unsatisfied trait bounds
    |
 note: the following trait bounds were not satisfied because of the requirements of the implementation of `StreamExt` for `_`:
-      `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream`
-      `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream`
-      `&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream`
-  --> $DIR/issue-30786.rs:106:9
+      `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>: Stream`
+      `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>: Stream`
+      `&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>: Stream`
+  --> $DIR/issue-30786.rs:105:9
    |
 LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
    |         ^^^^^^^^^     ^
 
-error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>`, but its trait bounds were not satisfied
-  --> $DIR/issue-30786.rs:141:24
+error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>`, but its trait bounds were not satisfied
+  --> $DIR/issue-30786.rs:140:24
    |
 LL | pub struct Filter<S, F> {
    | -----------------------
@@ -29,13 +29,13 @@ LL | pub struct Filter<S, F> {
    | doesn't satisfy `_: StreamExt`
 ...
 LL |     let count = filter.countx();
-   |                        ^^^^^^ method cannot be called on `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` due to unsatisfied trait bounds
+   |                        ^^^^^^ method cannot be called on `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>` due to unsatisfied trait bounds
    |
 note: the following trait bounds were not satisfied because of the requirements of the implementation of `StreamExt` for `_`:
-      `&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream`
-      `&'a mut &Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream`
-      `&'a mut &mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream`
-  --> $DIR/issue-30786.rs:106:9
+      `&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream`
+      `&'a mut &Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream`
+      `&'a mut &mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream`
+  --> $DIR/issue-30786.rs:105:9
    |
 LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
    |         ^^^^^^^^^     ^
index a497c6257dab65226de295274c21664eabc767e6..a2ab1f1856d3ee3ea8f0f34c9e59b42dc0b23def 100644 (file)
@@ -1,5 +1,5 @@
-error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>`, but its trait bounds were not satisfied
-  --> $DIR/issue-30786.rs:128:22
+error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>`, but its trait bounds were not satisfied
+  --> $DIR/issue-30786.rs:127:22
    |
 LL | pub struct Map<S, F> {
    | --------------------
@@ -8,19 +8,19 @@ LL | pub struct Map<S, F> {
    | doesn't satisfy `_: StreamExt`
 ...
 LL |     let filter = map.filterx(|x: &_| true);
-   |                      ^^^^^^^ method cannot be called on `Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>` due to unsatisfied trait bounds
+   |                      ^^^^^^^ method cannot be called on `Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>` due to unsatisfied trait bounds
    |
 note: the following trait bounds were not satisfied because of the requirements of the implementation of `StreamExt` for `_`:
-      `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream`
-      `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream`
-      `&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream`
-  --> $DIR/issue-30786.rs:106:9
+      `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>: Stream`
+      `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>: Stream`
+      `&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>: Stream`
+  --> $DIR/issue-30786.rs:105:9
    |
 LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
    |         ^^^^^^^^^     ^
 
-error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>`, but its trait bounds were not satisfied
-  --> $DIR/issue-30786.rs:141:24
+error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>`, but its trait bounds were not satisfied
+  --> $DIR/issue-30786.rs:140:24
    |
 LL | pub struct Filter<S, F> {
    | -----------------------
@@ -29,13 +29,13 @@ LL | pub struct Filter<S, F> {
    | doesn't satisfy `_: StreamExt`
 ...
 LL |     let count = filter.countx();
-   |                        ^^^^^^ method cannot be called on `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` due to unsatisfied trait bounds
+   |                        ^^^^^^ method cannot be called on `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>` due to unsatisfied trait bounds
    |
 note: the following trait bounds were not satisfied because of the requirements of the implementation of `StreamExt` for `_`:
-      `&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream`
-      `&'a mut &Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream`
-      `&'a mut &mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream`
-  --> $DIR/issue-30786.rs:106:9
+      `&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream`
+      `&'a mut &Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream`
+      `&'a mut &mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream`
+  --> $DIR/issue-30786.rs:105:9
    |
 LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
    |         ^^^^^^^^^     ^
index 278c5441ecfb70caf9d96cf5b20901808ef0f4fd..540c26c358b1dfefc9f1d697fc31f361d6e41bb8 100644 (file)
@@ -7,6 +7,7 @@
 // through again.
 
 // revisions: migrate nll
+//[nll]compile-flags: -Z borrowck=mir
 
 // Since we are testing nll (and migration) explicitly as a separate
 // revisions, don't worry about the --compare-mode=nll on this test.
@@ -14,8 +15,6 @@
 // ignore-compare-mode-nll
 // ignore-compare-mode-polonius
 
-//[nll]compile-flags: -Z borrowck=mir
-
 pub trait Stream {
     type Item;
     fn next(self) -> Option<Self::Item>;
index 8c53b4105bb8b838bedc96bcce33eed565c5d1bf..37ae3c6802964212393ce02234250e4f84204d72 100644 (file)
@@ -2,16 +2,16 @@ error[E0277]: `Rc<Cell<i32>>` cannot be sent between threads safely
   --> $DIR/auto-trait-leak2.rs:13:10
    |
 LL | fn before() -> impl Fn(i32) {
-   |                ------------ within this `impl Fn<(i32,)>`
+   |                ------------ within this `impl Fn(i32)`
 ...
 LL |     send(before());
    |     ---- ^^^^^^^^ `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>>`
+   = 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]`
-   = note: required because it appears within the type `impl Fn<(i32,)>`
+   = note: required because it appears within the type `impl Fn(i32)`
 note: required by a bound in `send`
   --> $DIR/auto-trait-leak2.rs:10:12
    |
@@ -27,11 +27,11 @@ LL |     send(after());
    |     required by a bound introduced by this call
 ...
 LL | fn after() -> impl Fn(i32) {
-   |               ------------ within this `impl Fn<(i32,)>`
+   |               ------------ within this `impl Fn(i32)`
    |
-   = help: within `impl Fn<(i32,)>`, the trait `Send` is not implemented for `Rc<Cell<i32>>`
+   = 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:24:5: 24:22]`
-   = note: required because it appears within the type `impl Fn<(i32,)>`
+   = note: required because it appears within the type `impl Fn(i32)`
 note: required by a bound in `send`
   --> $DIR/auto-trait-leak2.rs:10:12
    |
index b5f9986ce408973d7fb0f70dcd62535ee04d53bd..7cfbe3447b8130ac630c90d730799e05b10a039d 100644 (file)
@@ -7,6 +7,8 @@ LL |     ($($tr:tt)*) => { impl $($tr)* };
    |                       expected type parameter
    |                       found type parameter
 ...
+LL |     let mut a = x;
+   |                 - expected due to this value
 LL |     a = y;
    |         ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug`
    |
index 9546d01ac5c6895ea2c0560ab2bf255f94dff540..a519397806e0703ee7e83076dc191016722e607f 100644 (file)
@@ -13,7 +13,7 @@ impl<S> Bar for S {
     type E = impl std::marker::Copy;
     fn foo<T>() -> Self::E {
         //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-        //~| ERROR the trait bound `impl Future: Copy` is not satisfied [E0277]
+        //~| ERROR the trait bound `impl Future<Output = [async output]>: Copy` is not satisfied
         async {}
     }
 }
index 31b8fbd299c51ea9087e988a24a02940feb05aa1..97545ba3d1124c755df086a10ff9195b445ef00f 100644 (file)
@@ -1,8 +1,8 @@
-error[E0277]: the trait bound `impl Future: Copy` is not satisfied
+error[E0277]: the trait bound `impl Future<Output = [async output]>: Copy` is not satisfied
   --> $DIR/issue-55872-2.rs:14:20
    |
 LL |     fn foo<T>() -> Self::E {
-   |                    ^^^^^^^ the trait `Copy` is not implemented for `impl Future`
+   |                    ^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = [async output]>`
 
 error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
   --> $DIR/issue-55872-2.rs:14:28
index 17748ae42770fdfdf7a3e283d75f200671fe596d..e57fbf104dc6f5413643c60337b23cb82eb62bdf 100644 (file)
@@ -19,14 +19,14 @@ LL |
 LL |     lint_files().flat_map(|f| gather_from_file(&f))
    |     -----------------------------------------------
    |     |
-   |     returning here with type `FlatMap<impl Iterator, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>`
-   |     returning here with type `FlatMap<impl Iterator, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>`
+   |     returning here with type `FlatMap<impl Iterator<Item = [type error]>, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>`
+   |     returning here with type `FlatMap<impl Iterator<Item = [type error]>, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>`
 ...
 LL | fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator<Item = Lint> {
-   |                                                      -------------------------- returning this opaque type `FlatMap<impl Iterator, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>`
+   |                                                      -------------------------- returning this opaque type `FlatMap<impl Iterator<Item = [type error]>, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>`
 ...
 LL | fn lint_files() -> impl Iterator<Item = foo::MissingItem> {
-   |                    -------------------------------------- returning this opaque type `FlatMap<impl Iterator, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>`
+   |                    -------------------------------------- returning this opaque type `FlatMap<impl Iterator<Item = [type error]>, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>`
 
 error: aborting due to 3 previous errors
 
index 83eb33efc6b6a23b1c446196e404d5aa3f7e2412..5019e544bd562566540a1a8b2a94823bfa9f6cfd 100644 (file)
@@ -17,10 +17,10 @@ LL | fn foo() -> impl Fn() {
    |             ^^^^^^^^^ recursive opaque type
 ...
 LL |     wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo())))))))
-   |     ----------------------------------------------- returning here with type `impl Fn<()>`
+   |     ----------------------------------------------- returning here with type `impl Fn()`
 ...
 LL | fn wrap(f: impl Fn()) -> impl Fn() {
-   |                          --------- returning this opaque type `impl Fn<()>`
+   |                          --------- returning this opaque type `impl Fn()`
 
 error: aborting due to previous error; 1 warning emitted
 
index 86bde9a0cddab967e843d72c87f133d05165caef..130678de2370cd47ed6978b7c50ef91a15a443d9 100644 (file)
@@ -15,7 +15,7 @@ LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
    |                                           ------------------------------- the found opaque type
    |
    = note: expected opaque type `impl Future<Output = u8>`
-              found opaque type `impl Future`
+              found opaque type `impl Future<Output = [async output]>`
    = note: distinct uses of `impl Trait` result in different opaque types
 
 error: aborting due to previous error
index 8cc4fef890abf8a40c3460ffa309e191203b15f3..e3386d29def02eabcb4840186426032754fc1bc0 100644 (file)
@@ -2,9 +2,9 @@
 #![feature(type_alias_impl_trait)]
 
 type FunType = impl Fn<()>;
-//~^ could not find defining uses
+//~^ ERROR could not find defining uses
 static STATIC_FN: FunType = some_fn;
-//~^ mismatched types
+//~^ ERROR mismatched types
 
 fn some_fn() {}
 
index 7c120235fd17637b085fbe8032cf846f9fa7225b..ab8a53d0db399f5b3b7b0d066487d3116578a5b4 100644 (file)
@@ -6,6 +6,7 @@ LL | fn foo(x: impl Debug, y: impl Debug) -> String {
    |           |
    |           expected type parameter
 LL |     let mut a = x;
+   |                 - expected due to this value
 LL |     a = y;
    |         ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug`
    |
index 8f369f1b03831341284e28cfdd202efdb441ff97..127765727b401f000058c11cefda55831f9b2fb7 100644 (file)
@@ -2,7 +2,12 @@ error: `extern crate self;` requires renaming
   --> $DIR/extern-crate-self-fail.rs:1:1
    |
 LL | extern crate self;
-   | ^^^^^^^^^^^^^^^^^^ help: try: `extern crate self as name;`
+   | ^^^^^^^^^^^^^^^^^^
+   |
+help: rename the `self` crate to be able to import it
+   |
+LL | extern crate self as name;
+   | ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: `#[macro_use]` is not supported on `extern crate self`
   --> $DIR/extern-crate-self-fail.rs:3:1
index 2998f05efbae405301141b8bc64d77eaa5d45f5b..87a79b8813777fb9acd137d5f0cb31dd72a14ff6 100644 (file)
@@ -5,23 +5,24 @@
 #![deny(elided_lifetimes_in_paths)]
 //~^ NOTE the lint level is defined here
 
-use std::cell::{RefCell, Ref};
+use std::cell::{Ref, RefCell};
 
-
-struct Foo<'a> { x: &'a u32 }
+struct Foo<'a> {
+    x: &'a u32,
+}
 
 fn foo(x: &Foo<'_>) {
     //~^ ERROR hidden lifetime parameters in types are deprecated
-    //~| HELP indicate the anonymous lifetime
+    //~| NOTE expected named lifetime parameter
+    //~| HELP consider using the `'_` lifetime
 }
 
 fn bar(x: &Foo<'_>) {}
 
-
 struct Wrapped<'a>(&'a str);
 
 struct WrappedWithBow<'a> {
-    gift: &'a str
+    gift: &'a str,
 }
 
 struct MatchedSet<'a, 'b> {
@@ -31,22 +32,34 @@ struct MatchedSet<'a, 'b> {
 
 fn wrap_gift(gift: &str) -> Wrapped<'_> {
     //~^ ERROR hidden lifetime parameters in types are deprecated
-    //~| HELP indicate the anonymous lifetime
+    //~| NOTE expected named lifetime parameter
+    //~| HELP consider using the `'_` lifetime
     Wrapped(gift)
 }
 
 fn wrap_gift_with_bow(gift: &str) -> WrappedWithBow<'_> {
     //~^ ERROR hidden lifetime parameters in types are deprecated
-    //~| HELP indicate the anonymous lifetime
+    //~| NOTE expected named lifetime parameter
+    //~| HELP consider using the `'_` lifetime
     WrappedWithBow { gift }
 }
 
 fn inspect_matched_set(set: MatchedSet<'_, '_>) {
     //~^ ERROR hidden lifetime parameters in types are deprecated
-    //~| HELP indicate the anonymous lifetime
+    //~| NOTE expected 2 lifetime parameters
+    //~| HELP consider using the `'_` lifetime
     println!("{} {}", set.one, set.another);
 }
 
+// Verify that the lint does not fire, because the added `'_` wouldn't be resolved correctly.
+fn match_sets() -> MatchedSet<'static, 'static> {
+    //~^ ERROR missing lifetime specifiers
+    //~| NOTE expected 2 lifetime parameters
+    //~| HELP this function's return type contains a borrowed value
+    //~| HELP consider using the `'static` lifetime
+    MatchedSet { one: "one", another: "another" }
+}
+
 macro_rules! autowrapper {
     ($type_name:ident, $fn_name:ident, $lt:lifetime) => {
         struct $type_name<$lt> {
@@ -55,7 +68,11 @@ macro_rules! autowrapper {
 
         fn $fn_name(gift: &str) -> $type_name<'_> {
             //~^ ERROR hidden lifetime parameters in types are deprecated
-            //~| HELP indicate the anonymous lifetime
+            //~| NOTE expected named lifetime parameter
+            //~| HELP consider using the `'_` lifetime
+            //~| ERROR hidden lifetime parameters in types are deprecated
+            //~| NOTE expected named lifetime parameter
+            //~| HELP consider using the `'_` lifetime
             $type_name { gift }
         }
     }
@@ -65,19 +82,34 @@ autowrapper!(Autowrapped, autowrap_gift, 'a);
 //~^ NOTE in this expansion of autowrapper!
 //~| NOTE in this expansion of autowrapper!
 
+// Verify that rustfix does not try to apply the fix twice.
+autowrapper!(AutowrappedAgain, autowrap_gift_again, 'a);
+//~^ NOTE in this expansion of autowrapper!
+//~| NOTE in this expansion of autowrapper!
+
 macro_rules! anytuple_ref_ty {
     ($($types:ty),*) => {
         Ref<'_, ($($types),*)>
         //~^ ERROR hidden lifetime parameters in types are deprecated
-        //~| HELP indicate the anonymous lifetime
+        //~| NOTE expected named lifetime parameter
+        //~| HELP consider using the `'_` lifetime
     }
 }
 
+#[allow(elided_lifetimes_in_paths)]
+mod blah {
+    struct Thing<'a>(&'a i32);
+    struct Bar<T>(T);
+
+    fn foo(b: Bar<Thing>) {}
+}
+
 fn main() {
     let honesty = RefCell::new((4, 'e'));
     let loyalty: Ref<'_, (u32, char)> = honesty.borrow();
     //~^ ERROR hidden lifetime parameters in types are deprecated
-    //~| HELP indicate the anonymous lifetime
+    //~| NOTE expected named lifetime parameter
+    //~| HELP consider using the `'_` lifetime
     let generosity = Ref::map(loyalty, |t| &t.0);
 
     let laughter = RefCell::new((true, "magic"));
index b729a15a29edd78d2e17d9df290d190f3f9d9e00..28323a22427b64c837644d183f7b2e90a65c2778 100644 (file)
@@ -5,23 +5,24 @@
 #![deny(elided_lifetimes_in_paths)]
 //~^ NOTE the lint level is defined here
 
-use std::cell::{RefCell, Ref};
+use std::cell::{Ref, RefCell};
 
-
-struct Foo<'a> { x: &'a u32 }
+struct Foo<'a> {
+    x: &'a u32,
+}
 
 fn foo(x: &Foo) {
     //~^ ERROR hidden lifetime parameters in types are deprecated
-    //~| HELP indicate the anonymous lifetime
+    //~| NOTE expected named lifetime parameter
+    //~| HELP consider using the `'_` lifetime
 }
 
 fn bar(x: &Foo<'_>) {}
 
-
 struct Wrapped<'a>(&'a str);
 
 struct WrappedWithBow<'a> {
-    gift: &'a str
+    gift: &'a str,
 }
 
 struct MatchedSet<'a, 'b> {
@@ -31,22 +32,34 @@ struct MatchedSet<'a, 'b> {
 
 fn wrap_gift(gift: &str) -> Wrapped {
     //~^ ERROR hidden lifetime parameters in types are deprecated
-    //~| HELP indicate the anonymous lifetime
+    //~| NOTE expected named lifetime parameter
+    //~| HELP consider using the `'_` lifetime
     Wrapped(gift)
 }
 
 fn wrap_gift_with_bow(gift: &str) -> WrappedWithBow {
     //~^ ERROR hidden lifetime parameters in types are deprecated
-    //~| HELP indicate the anonymous lifetime
+    //~| NOTE expected named lifetime parameter
+    //~| HELP consider using the `'_` lifetime
     WrappedWithBow { gift }
 }
 
 fn inspect_matched_set(set: MatchedSet) {
     //~^ ERROR hidden lifetime parameters in types are deprecated
-    //~| HELP indicate the anonymous lifetime
+    //~| NOTE expected 2 lifetime parameters
+    //~| HELP consider using the `'_` lifetime
     println!("{} {}", set.one, set.another);
 }
 
+// Verify that the lint does not fire, because the added `'_` wouldn't be resolved correctly.
+fn match_sets() -> MatchedSet {
+    //~^ ERROR missing lifetime specifiers
+    //~| NOTE expected 2 lifetime parameters
+    //~| HELP this function's return type contains a borrowed value
+    //~| HELP consider using the `'static` lifetime
+    MatchedSet { one: "one", another: "another" }
+}
+
 macro_rules! autowrapper {
     ($type_name:ident, $fn_name:ident, $lt:lifetime) => {
         struct $type_name<$lt> {
@@ -55,7 +68,11 @@ struct $type_name<$lt> {
 
         fn $fn_name(gift: &str) -> $type_name {
             //~^ ERROR hidden lifetime parameters in types are deprecated
-            //~| HELP indicate the anonymous lifetime
+            //~| NOTE expected named lifetime parameter
+            //~| HELP consider using the `'_` lifetime
+            //~| ERROR hidden lifetime parameters in types are deprecated
+            //~| NOTE expected named lifetime parameter
+            //~| HELP consider using the `'_` lifetime
             $type_name { gift }
         }
     }
@@ -65,19 +82,34 @@ fn $fn_name(gift: &str) -> $type_name {
 //~^ NOTE in this expansion of autowrapper!
 //~| NOTE in this expansion of autowrapper!
 
+// Verify that rustfix does not try to apply the fix twice.
+autowrapper!(AutowrappedAgain, autowrap_gift_again, 'a);
+//~^ NOTE in this expansion of autowrapper!
+//~| NOTE in this expansion of autowrapper!
+
 macro_rules! anytuple_ref_ty {
     ($($types:ty),*) => {
         Ref<($($types),*)>
         //~^ ERROR hidden lifetime parameters in types are deprecated
-        //~| HELP indicate the anonymous lifetime
+        //~| NOTE expected named lifetime parameter
+        //~| HELP consider using the `'_` lifetime
     }
 }
 
+#[allow(elided_lifetimes_in_paths)]
+mod blah {
+    struct Thing<'a>(&'a i32);
+    struct Bar<T>(T);
+
+    fn foo(b: Bar<Thing>) {}
+}
+
 fn main() {
     let honesty = RefCell::new((4, 'e'));
     let loyalty: Ref<(u32, char)> = honesty.borrow();
     //~^ ERROR hidden lifetime parameters in types are deprecated
-    //~| HELP indicate the anonymous lifetime
+    //~| NOTE expected named lifetime parameter
+    //~| HELP consider using the `'_` lifetime
     let generosity = Ref::map(loyalty, |t| &t.0);
 
     let laughter = RefCell::new((true, "magic"));
index 037ce401b3cc91306acbec1f661bec0768a82ce9..2e65461b321e989fc65ee61de24230228b9787bd 100644 (file)
 error: hidden lifetime parameters in types are deprecated
-  --> $DIR/elided-lifetimes.rs:13:12
+  --> $DIR/elided-lifetimes.rs:14:12
    |
 LL | fn foo(x: &Foo) {
-   |            ^^^- help: indicate the anonymous lifetime: `<'_>`
+   |            ^^^ expected named lifetime parameter
    |
 note: the lint level is defined here
   --> $DIR/elided-lifetimes.rs:5:9
    |
 LL | #![deny(elided_lifetimes_in_paths)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider using the `'_` lifetime
+   |
+LL | fn foo(x: &Foo<'_>) {
+   |            ~~~~~~~
 
 error: hidden lifetime parameters in types are deprecated
-  --> $DIR/elided-lifetimes.rs:32:29
+  --> $DIR/elided-lifetimes.rs:33:29
    |
 LL | fn wrap_gift(gift: &str) -> Wrapped {
-   |                             ^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
+   |                             ^^^^^^^ expected named lifetime parameter
+   |
+help: consider using the `'_` lifetime
+   |
+LL | fn wrap_gift(gift: &str) -> Wrapped<'_> {
+   |                             ~~~~~~~~~~~
 
 error: hidden lifetime parameters in types are deprecated
-  --> $DIR/elided-lifetimes.rs:38:38
+  --> $DIR/elided-lifetimes.rs:40:38
    |
 LL | fn wrap_gift_with_bow(gift: &str) -> WrappedWithBow {
-   |                                      ^^^^^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
+   |                                      ^^^^^^^^^^^^^^ expected named lifetime parameter
+   |
+help: consider using the `'_` lifetime
+   |
+LL | fn wrap_gift_with_bow(gift: &str) -> WrappedWithBow<'_> {
+   |                                      ~~~~~~~~~~~~~~~~~~
 
 error: hidden lifetime parameters in types are deprecated
-  --> $DIR/elided-lifetimes.rs:44:29
+  --> $DIR/elided-lifetimes.rs:47:29
    |
 LL | fn inspect_matched_set(set: MatchedSet) {
-   |                             ^^^^^^^^^^- help: indicate the anonymous lifetimes: `<'_, '_>`
+   |                             ^^^^^^^^^^ expected 2 lifetime parameters
+   |
+help: consider using the `'_` lifetime
+   |
+LL | fn inspect_matched_set(set: MatchedSet<'_, '_>) {
+   |                             ~~~~~~~~~~~~~~~~~~
+
+error[E0106]: missing lifetime specifiers
+  --> $DIR/elided-lifetimes.rs:55:20
+   |
+LL | fn match_sets() -> MatchedSet {
+   |                    ^^^^^^^^^^ expected 2 lifetime parameters
+   |
+   = 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 match_sets() -> MatchedSet<'static, 'static> {
+   |                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: hidden lifetime parameters in types are deprecated
-  --> $DIR/elided-lifetimes.rs:56:36
+  --> $DIR/elided-lifetimes.rs:69:36
    |
 LL |         fn $fn_name(gift: &str) -> $type_name {
-   |                                    ^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
+   |                                    ^^^^^^^^^^ expected named lifetime parameter
 ...
 LL | autowrapper!(Autowrapped, autowrap_gift, 'a);
    | -------------------------------------------- in this macro invocation
    |
    = note: this error originates in the macro `autowrapper` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider using the `'_` lifetime
+   |
+LL |         fn $fn_name(gift: &str) -> $type_name<'_> {
+   |                                    ~~~~~~~~~~~~~~
 
 error: hidden lifetime parameters in types are deprecated
-  --> $DIR/elided-lifetimes.rs:78:18
+  --> $DIR/elided-lifetimes.rs:69:36
+   |
+LL |         fn $fn_name(gift: &str) -> $type_name {
+   |                                    ^^^^^^^^^^ expected named lifetime parameter
+...
+LL | autowrapper!(AutowrappedAgain, autowrap_gift_again, 'a);
+   | ------------------------------------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `autowrapper` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider using the `'_` lifetime
+   |
+LL |         fn $fn_name(gift: &str) -> $type_name<'_> {
+   |                                    ~~~~~~~~~~~~~~
+
+error: hidden lifetime parameters in types are deprecated
+  --> $DIR/elided-lifetimes.rs:109:22
    |
 LL |     let loyalty: Ref<(u32, char)> = honesty.borrow();
-   |                  ^^^^^^^^^^^^^^^^ help: indicate the anonymous lifetime: `Ref<'_, (u32, char)>`
+   |                      ^ expected named lifetime parameter
+   |
+help: consider using the `'_` lifetime
+   |
+LL |     let loyalty: Ref<'_, (u32, char)> = honesty.borrow();
+   |                      +++
 
 error: hidden lifetime parameters in types are deprecated
-  --> $DIR/elided-lifetimes.rs:70:9
+  --> $DIR/elided-lifetimes.rs:92:13
    |
 LL |         Ref<($($types),*)>
-   |         ^^^^^^^^^^^^^^^^^^ help: indicate the anonymous lifetime: `Ref<'_, ($($types),*)>`
+   |             ^ expected named lifetime parameter
 ...
 LL |     let yellow: anytuple_ref_ty!(bool, &str) = laughter.borrow();
    |                 ---------------------------- in this macro invocation
    |
    = note: this error originates in the macro `anytuple_ref_ty` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider using the `'_` lifetime
+   |
+LL |         Ref<'_, ($($types),*)>
+   |             +++
 
-error: aborting due to 7 previous errors
+error: aborting due to 9 previous errors
 
+For more information about this error, try `rustc --explain E0106`.
index 5200b4a829db236f4298288cabf0f03bb13ea250..8d1621321e8e6ca0b2392181fbe55675601b3849 100644 (file)
@@ -1,6 +1,8 @@
 fn main() {
-    let mut x = 2;
+    let mut x //~ NOTE expected due to the type of this binding
+        =
+        2; //~ NOTE expected due to this value
     x = 5.0;
     //~^ ERROR mismatched types
-    //~| expected integer, found floating-point number
+    //~| NOTE expected integer, found floating-point number
 }
index b49bff1b0d84dc9e076ce9409e0c8a9e3ac8fb53..f77c265a2ada7512bf774ef7de204ce0ea6e6042 100644 (file)
@@ -1,6 +1,11 @@
 error[E0308]: mismatched types
-  --> $DIR/integral-variable-unification-error.rs:3:9
+  --> $DIR/integral-variable-unification-error.rs:5:9
    |
+LL |     let mut x
+   |         ----- expected due to the type of this binding
+LL |         =
+LL |         2;
+   |         - expected due to this value
 LL |     x = 5.0;
    |         ^^^ expected integer, found floating-point number
 
index bbcdd3e37a96ef141c6b7dc1800362396c1b0a53..bc4dc9ebf9e00b4c6569c43cecde89d654d5ce6a 100644 (file)
@@ -11,6 +11,7 @@ LL | fn test_ref(x: &u32) -> impl std::future::Future<Output = u32> + '_ {
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `u32` is not a future
    |
    = help: the trait `Future` is not implemented for `u32`
+   = note: u32 must be a future or must implement `IntoFuture` to be awaited
 
 error: aborting due to 2 previous errors
 
index fa53d55f5b3d7240b7dc9a97224ee00976c38c2c..7ea81ffb59e7eebf4d17239c6e9b577703484deb 100644 (file)
@@ -5,6 +5,5 @@ mod A {
 fn main() {
     A::C = 1;
     //~^ ERROR: invalid left-hand side of assignment
-    //~| ERROR: mismatched types
     //~| ERROR: struct `C` is private
 }
index 4df1813a710ff780063fb1ebcac69d5562efb638..54b6c640d9d79cdf23b997ca26431ac1382f0785 100644 (file)
@@ -18,13 +18,7 @@ LL |     A::C = 1;
    |     |
    |     cannot assign to this expression
 
-error[E0308]: mismatched types
-  --> $DIR/issue-13407.rs:6:12
-   |
-LL |     A::C = 1;
-   |            ^ expected struct `C`, found integer
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0070, E0308, E0603.
+Some errors have detailed explanations: E0070, E0603.
 For more information about an error, try `rustc --explain E0070`.
index d7e8c08bb01b245b95b651bc69f22e087c94e87a..5a276f27886d29830b85009b2ad518f162f24f5a 100644 (file)
@@ -1,27 +1,26 @@
 error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
-  --> $DIR/issue-16538.rs:14:27
+  --> $DIR/issue-16538.rs:15:23
    |
-LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: `*const usize` cannot be shared between threads safely
-  --> $DIR/issue-16538.rs:14:1
+error[E0133]: use of extern static is unsafe and requires unsafe function or block
+  --> $DIR/issue-16538.rs:15:30
    |
-LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const usize` cannot be shared between threads safely
+LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
+   |                              ^^^^ use of extern static
    |
-   = help: the trait `Sync` is not implemented for `*const usize`
-   = note: shared static variables must have a type that implements `Sync`
+   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
 
-error[E0133]: use of extern static is unsafe and requires unsafe function or block
-  --> $DIR/issue-16538.rs:14:34
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/issue-16538.rs:15:21
    |
-LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
-   |                                  ^^^^ use of extern static
+LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer
    |
-   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+   = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0015, E0133, E0277.
+Some errors have detailed explanations: E0015, E0133.
 For more information about an error, try `rustc --explain E0015`.
index 1e8ecf015c85a8aff0950b3c99fa60b29db9f3d3..b6891deb937da0af8a10319f2255d0b81c644dcd 100644 (file)
@@ -1,6 +1,7 @@
 // revisions: mir thir
 // [thir]compile-flags: -Z thir-unsafeck
 
+#![feature(const_raw_ptr_deref)]
 mod Y {
     pub type X = usize;
     extern "C" {
@@ -11,8 +12,8 @@ pub fn foo(value: *const X) -> *const X {
     }
 }
 
-static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
-//~^ ERROR `*const usize` cannot be shared between threads safely [E0277]
+static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
+//~^ ERROR dereference of raw pointer
 //~| ERROR E0015
 //~| ERROR use of extern static is unsafe and requires
 
index 435334c322808bbf92107c9a36a0cc378cf2a5c8..8365a1dbf6e5ebdb92e1a4fa9ae7c860629b8fb8 100644 (file)
@@ -1,27 +1,26 @@
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/issue-16538.rs:15:22
+   |
+LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer
+   |
+   = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
 error[E0133]: use of extern static is unsafe and requires unsafe function or block
-  --> $DIR/issue-16538.rs:14:34
+  --> $DIR/issue-16538.rs:15:30
    |
-LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
-   |                                  ^^^^ use of extern static
+LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
+   |                              ^^^^ 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[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
-  --> $DIR/issue-16538.rs:14:27
-   |
-LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: `*const usize` cannot be shared between threads safely
-  --> $DIR/issue-16538.rs:14:1
-   |
-LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const usize` cannot be shared between threads safely
+  --> $DIR/issue-16538.rs:15:23
    |
-   = help: the trait `Sync` is not implemented for `*const usize`
-   = note: shared static variables must have a type that implements `Sync`
+LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0015, E0133, E0277.
+Some errors have detailed explanations: E0015, E0133.
 For more information about an error, try `rustc --explain E0015`.
index 4cd85124c35074aa64fa27c052fe7536f3264d59..bc6e45e59258f370cda1ad3e9541d376c2ee2cd0 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: `Foo` cannot be shared between threads safely
-  --> $DIR/issue-17718-static-sync.rs:9:1
+  --> $DIR/issue-17718-static-sync.rs:9:13
    |
 LL | static BAR: Foo = Foo;
-   | ^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be shared between threads safely
+   |             ^^^ `Foo` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `Foo`
    = note: shared static variables must have a type that implements `Sync`
index ffd6dfabc2890a1cb7f905485e1812780b86b903..9ab952ade9cf4636ccddc39c1d88908ee51addf5 100644 (file)
@@ -1,6 +1,7 @@
 fn main() {
     static foo: dyn Fn() -> u32 = || -> u32 {
         //~^ ERROR the size for values of type
+        //~| ERROR cannot be shared between threads safely
         0
     };
 }
index 1674fa8af2845fc482750bde1dce2b2af537cc22..4afb87c48254901a651d09cb9f8d1fa82f612b6a 100644 (file)
@@ -6,6 +6,15 @@ LL |     static foo: dyn Fn() -> u32 = || -> u32 {
    |
    = help: the trait `Sized` is not implemented for `(dyn Fn() -> u32 + 'static)`
 
-error: aborting due to previous error
+error[E0277]: `(dyn Fn() -> u32 + 'static)` cannot be shared between threads safely
+  --> $DIR/issue-24446.rs:2:17
+   |
+LL |     static foo: dyn Fn() -> u32 = || -> u32 {
+   |                 ^^^^^^^^^^^^^^^ `(dyn Fn() -> u32 + 'static)` cannot be shared between threads safely
+   |
+   = help: the trait `Sync` is not implemented for `(dyn Fn() -> u32 + 'static)`
+   = note: shared static variables must have a type that implements `Sync`
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
index b966b339389170e4e942d1b0be057d58fd8a2dbc..538bbe2f50296989940775c9f91150737bb4cfa6 100644 (file)
@@ -6,6 +6,7 @@ LL | fn foo<T, U>(x: T, y: U) {
    |        |
    |        expected type parameter
 LL |     let mut xx = x;
+   |                  - expected due to this value
 LL |     xx = y;
    |          ^ expected type parameter `T`, found type parameter `U`
    |
index b45574f0c49af80d563b5a5404b2a12f6728939f..9ecae3e7a2b2437794896087d813dcafda6d3b3a 100644 (file)
@@ -4,6 +4,8 @@ error[E0463]: can't find crate for `std`
    = help: consider downloading the target with `rustup target add thumbv6m-none-eabi`
    = help: consider building the standard library from source with `cargo build -Zbuild-std`
 
-error: aborting due to previous error
+error: requires `sized` lang_item
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0463`.
index 61cf3f25d0d07390e1de49fefba1ef988ab34187..4a1debf37a079547bdbdaff4a3a64c71de359a22 100644 (file)
@@ -8,6 +8,8 @@ LL |     let mut s_copy = s;
 ...
 LL |     println!("{}", s);
    |                    ^ value borrowed here after move
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index eff1de3e01752c472e9b1e718574575058256c88..32e8588b3c0749dc3a9aeecd6ba43e2c54b11596 100644 (file)
@@ -12,6 +12,8 @@ LL |             println!("{:?}", heap);
 ...
 LL |     };
    |      - ... and the mutable borrow might be used here, when that temporary is dropped and runs the destructor for type `(Option<PeekMut<'_, i32>>, ())`
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index ddb070ddf9fae8838ac1df8fcdeeedb1a0877a4b..4e56cca33d6a9301febbb5b4ebbba23dbd2c531a 100644 (file)
@@ -1,4 +1,5 @@
-//~ ERROR 1:1: 1:1: can't find crate for `core` [E0463]
+//~ ERROR can't find crate for `core`
+//~^ ERROR can't find crate for `compiler_builtins`
 
 // compile-flags: --target thumbv7em-none-eabihf
 // needs-llvm-components: arm
@@ -7,3 +8,6 @@
 #![no_std]
 
 extern crate cortex_m;
+//~^ ERROR can't find crate for `cortex_m`
+
+fn main() {}
index d963c07ea91750ac12704dc65c4af389233d6d91..fcfa2bf119cff6f29c5410cdb34524ff1ab4972e 100644 (file)
@@ -4,6 +4,16 @@ error[E0463]: can't find crate for `core`
    = help: consider downloading the target with `rustup target add thumbv7em-none-eabihf`
    = help: consider building the standard library from source with `cargo build -Zbuild-std`
 
-error: aborting due to previous error
+error[E0463]: can't find crate for `compiler_builtins`
+
+error[E0463]: can't find crate for `cortex_m`
+  --> $DIR/compiler-builtins-error.rs:10:1
+   |
+LL | extern crate cortex_m;
+   | ^^^^^^^^^^^^^^^^^^^^^^ can't find crate
+
+error: requires `sized` lang_item
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0463`.
index 35b343edfbdbe870c23a63f1828936983106b212..4072a57cb10526aaccd0f12937c5328202db6608 100644 (file)
@@ -1,10 +1,10 @@
 fn f() { }
-struct S(Box<dyn FnMut()>);
+struct S(Box<dyn FnMut() + Sync>);
 pub static C: S = S(f); //~ ERROR mismatched types
 
 
 fn g() { }
-type T = Box<dyn FnMut()>;
+type T = Box<dyn FnMut() + Sync>;
 pub static D: T = g; //~ ERROR mismatched types
 
 fn main() {}
index 7a1f42adf65d48a07cd9ffaad1ea517301762264..29c95e4fb62b89f4206e0ccf144549423b43ec29 100644 (file)
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL | pub static C: S = S(f);
    |                     ^ expected struct `Box`, found fn item
    |
-   = note: expected struct `Box<(dyn FnMut() + 'static)>`
+   = note: expected struct `Box<(dyn FnMut() + Sync + 'static)>`
              found fn item `fn() {f}`
 
 error[E0308]: mismatched types
@@ -13,7 +13,7 @@ error[E0308]: mismatched types
 LL | pub static D: T = g;
    |                   ^ expected struct `Box`, found fn item
    |
-   = note: expected struct `Box<(dyn FnMut() + 'static)>`
+   = note: expected struct `Box<(dyn FnMut() + Sync + 'static)>`
              found fn item `fn() {g}`
 
 error: aborting due to 2 previous errors
index 65f4656b0226629ddddf7017d4c85c5a322a4436..d2f8c77c0ce1122fec3b49629098b1a010021956 100644 (file)
@@ -5,7 +5,7 @@ fn main() {
 
     v.into_iter().map(|s|s.to_owned()).collect::<Vec<_>>();
 
-    let mut a = String::new();
+    let mut a = String::new(); //~ NOTE expected due to this value
     for i in v {
         a = *i.to_string();
         //~^ ERROR mismatched types
index 8f500261243f19b977cd9872e62ee27ea12e8a4a..71d9f5b3dbbff615970a6eb724077ec3c207cf1e 100644 (file)
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/issue-53348.rs:10:13
    |
+LL |     let mut a = String::new();
+   |                 ------------- expected due to this value
+LL |     for i in v {
 LL |         a = *i.to_string();
    |             ^^^^^^^^^^^^^^ expected struct `String`, found `str`
 
index 06b8eb777c035198993ad7573cbf24b6f7ee7ddc..a53e28f7246e64fd8f2b7b4a82152bfa6a0ea478 100644 (file)
@@ -19,5 +19,5 @@ fn main() {
     let g = |(a, _)| a;
     let t7 = |env| |a| |b| t7p(f, g)(((env, a), b));
     let t8 = t8n(t7, t7p(f, g));
-    //~^ ERROR: expected a `Fn<(_,)>` closure, found `impl Fn<(((_, _), _),)>
+    //~^ ERROR: expected a `Fn<(_,)>` closure, found `impl Fn(((_, _), _))` [E0277]
 }
index 9b7fe1ef786f07721f557f1337f72e75b26348e2..a9284535e4dc4221a6c1faf198fc113706f2ec5c 100644 (file)
@@ -1,12 +1,12 @@
-error[E0277]: expected a `Fn<(_,)>` closure, found `impl Fn<(((_, _), _),)>`
+error[E0277]: expected a `Fn<(_,)>` closure, found `impl Fn(((_, _), _))`
   --> $DIR/issue-59494.rs:21:22
    |
 LL |     let t8 = t8n(t7, t7p(f, g));
-   |              ---     ^^^^^^^^^ expected an `Fn<(_,)>` closure, found `impl Fn<(((_, _), _),)>`
+   |              ---     ^^^^^^^^^ expected an `Fn<(_,)>` closure, found `impl Fn(((_, _), _))`
    |              |
    |              required by a bound introduced by this call
    |
-   = help: the trait `Fn<(_,)>` is not implemented for `impl Fn<(((_, _), _),)>`
+   = help: the trait `Fn<(_,)>` is not implemented for `impl Fn(((_, _), _))`
 note: required by a bound in `t8n`
   --> $DIR/issue-59494.rs:5:45
    |
index 29a1644673d4ec4ae652328f8be7b121251453bd..83c52d286a199c9ea1c2d9f71c22aafef4af4047 100644 (file)
@@ -4,7 +4,6 @@
 
 // Regression test for issue 7364
 static boxed: Box<RefCell<isize>> = box RefCell::new(0);
-//~^ ERROR allocations are not allowed in statics
-//~| ERROR `RefCell<isize>` cannot be shared between threads safely [E0277]
+//~^ ERROR `RefCell<isize>` cannot be shared between threads safely [E0277]
 
 fn main() { }
index 8ceb3be7ec913110853456edc191c7e75fcf42ad..f2e80f451695ac3a9c4fe235572cff1f146e1613 100644 (file)
@@ -1,21 +1,14 @@
-error[E0010]: allocations are not allowed in statics
-  --> $DIR/issue-7364.rs:6:37
-   |
-LL | static boxed: Box<RefCell<isize>> = box RefCell::new(0);
-   |                                     ^^^^^^^^^^^^^^^^^^^ allocation not allowed in statics
-
 error[E0277]: `RefCell<isize>` cannot be shared between threads safely
-  --> $DIR/issue-7364.rs:6:1
+  --> $DIR/issue-7364.rs:6:15
    |
 LL | static boxed: Box<RefCell<isize>> = box RefCell::new(0);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `RefCell<isize>` cannot be shared between threads safely
+   |               ^^^^^^^^^^^^^^^^^^^ `RefCell<isize>` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `RefCell<isize>`
    = note: required because of the requirements on the impl of `Sync` for `Unique<RefCell<isize>>`
    = note: required because it appears within the type `Box<RefCell<isize>>`
    = note: shared static variables must have a type that implements `Sync`
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0010, E0277.
-For more information about an error, try `rustc --explain E0010`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-77218.rs b/src/test/ui/issues/issue-77218.rs
deleted file mode 100644 (file)
index a6a2401..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-fn main() {
-    let value = [7u8];
-    while Some(0) = value.get(0) { //~ ERROR destructuring assignments are unstable
-        //~| ERROR invalid left-hand side of assignment
-        //~| ERROR mismatched types
-        //~| ERROR mismatched types
-
-        // FIXME The following diagnostic should also be emitted
-        // HELP you might have meant to use pattern matching
-    }
-}
diff --git a/src/test/ui/issues/issue-77218.stderr b/src/test/ui/issues/issue-77218.stderr
deleted file mode 100644 (file)
index ce70c01..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-error[E0658]: destructuring assignments are unstable
-  --> $DIR/issue-77218.rs:3:19
-   |
-LL |     while Some(0) = value.get(0) {
-   |           ------- ^
-   |           |
-   |           cannot assign to this expression
-   |
-   = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information
-   = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable
-
-error[E0070]: invalid left-hand side of assignment
-  --> $DIR/issue-77218.rs:3:19
-   |
-LL |     while Some(0) = value.get(0) {
-   |                -  ^
-   |                |
-   |                cannot assign to this expression
-
-error[E0308]: mismatched types
-  --> $DIR/issue-77218.rs:3:16
-   |
-LL |     while Some(0) = value.get(0) {
-   |                ^ expected integer, found `&u8`
-   |
-help: consider dereferencing the borrow
-   |
-LL |     while Some(*0) = value.get(0) {
-   |                +
-
-error[E0308]: mismatched types
-  --> $DIR/issue-77218.rs:3:11
-   |
-LL |     while Some(0) = value.get(0) {
-   |           ^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
-
-error: aborting due to 4 previous errors
-
-Some errors have detailed explanations: E0070, E0308, E0658.
-For more information about an error, try `rustc --explain E0070`.
diff --git a/src/test/ui/issues/issue-77218/issue-77218-2.fixed b/src/test/ui/issues/issue-77218/issue-77218-2.fixed
new file mode 100644 (file)
index 0000000..06487fe
--- /dev/null
@@ -0,0 +1,7 @@
+// run-rustfix
+#![feature(destructuring_assignment)]
+fn main() {
+    let value = [7u8];
+    while let Some(0) = value.get(0) { //~ ERROR invalid left-hand side of assignment
+    }
+}
diff --git a/src/test/ui/issues/issue-77218/issue-77218-2.rs b/src/test/ui/issues/issue-77218/issue-77218-2.rs
new file mode 100644 (file)
index 0000000..e19cec0
--- /dev/null
@@ -0,0 +1,7 @@
+// run-rustfix
+#![feature(destructuring_assignment)]
+fn main() {
+    let value = [7u8];
+    while Some(0) = value.get(0) { //~ ERROR invalid left-hand side of assignment
+    }
+}
diff --git a/src/test/ui/issues/issue-77218/issue-77218-2.stderr b/src/test/ui/issues/issue-77218/issue-77218-2.stderr
new file mode 100644 (file)
index 0000000..8d9eb22
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0070]: invalid left-hand side of assignment
+  --> $DIR/issue-77218-2.rs:5:19
+   |
+LL |     while Some(0) = value.get(0) {
+   |                -  ^
+   |                |
+   |                cannot assign to this expression
+   |
+help: you might have meant to use pattern destructuring
+   |
+LL |     while let Some(0) = value.get(0) {
+   |           +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0070`.
diff --git a/src/test/ui/issues/issue-77218/issue-77218.fixed b/src/test/ui/issues/issue-77218/issue-77218.fixed
new file mode 100644 (file)
index 0000000..4ea5110
--- /dev/null
@@ -0,0 +1,6 @@
+// run-rustfix
+fn main() {
+    let value = [7u8];
+    while let Some(0) = value.get(0) { //~ ERROR destructuring assignments are unstable
+    }
+}
diff --git a/src/test/ui/issues/issue-77218/issue-77218.rs b/src/test/ui/issues/issue-77218/issue-77218.rs
new file mode 100644 (file)
index 0000000..0f3c12f
--- /dev/null
@@ -0,0 +1,6 @@
+// run-rustfix
+fn main() {
+    let value = [7u8];
+    while Some(0) = value.get(0) { //~ ERROR destructuring assignments are unstable
+    }
+}
diff --git a/src/test/ui/issues/issue-77218/issue-77218.stderr b/src/test/ui/issues/issue-77218/issue-77218.stderr
new file mode 100644 (file)
index 0000000..54f4960
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0658]: destructuring assignments are unstable
+  --> $DIR/issue-77218.rs:4:19
+   |
+LL |     while Some(0) = value.get(0) {
+   |           ------- ^
+   |           |
+   |           cannot assign to this expression
+   |
+   = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information
+   = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable
+help: you might have meant to use pattern destructuring
+   |
+LL |     while let Some(0) = value.get(0) {
+   |           +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-88150.rs b/src/test/ui/issues/issue-88150.rs
new file mode 100644 (file)
index 0000000..555a386
--- /dev/null
@@ -0,0 +1,21 @@
+// run-pass
+// compile-flags:-C debuginfo=2
+// edition:2018
+
+use core::marker::PhantomData;
+
+pub struct Foo<T: ?Sized, A>(
+    PhantomData<(A, T)>,
+);
+
+enum Never {}
+
+impl<T: ?Sized> Foo<T, Never> {
+    fn new_foo() -> Foo<T, Never> {
+        Foo(PhantomData)
+    }
+}
+
+fn main() {
+    let _ = Foo::<[()], Never>::new_foo();
+}
diff --git a/src/test/ui/lexer/lex-bad-binary-literal.rs b/src/test/ui/lexer/lex-bad-binary-literal.rs
new file mode 100644 (file)
index 0000000..7df9807
--- /dev/null
@@ -0,0 +1,11 @@
+fn main() {
+    0b121; //~ ERROR invalid digit for a base 2 literal
+    0b10_10301; //~ ERROR invalid digit for a base 2 literal
+    0b30; //~ ERROR invalid digit for a base 2 literal
+    0b41; //~ ERROR invalid digit for a base 2 literal
+    0b5; //~ ERROR invalid digit for a base 2 literal
+    0b6; //~ ERROR invalid digit for a base 2 literal
+    0b7; //~ ERROR invalid digit for a base 2 literal
+    0b8; //~ ERROR invalid digit for a base 2 literal
+    0b9; //~ ERROR invalid digit for a base 2 literal
+}
diff --git a/src/test/ui/lexer/lex-bad-binary-literal.stderr b/src/test/ui/lexer/lex-bad-binary-literal.stderr
new file mode 100644 (file)
index 0000000..992b3d2
--- /dev/null
@@ -0,0 +1,56 @@
+error: invalid digit for a base 2 literal
+  --> $DIR/lex-bad-binary-literal.rs:2:8
+   |
+LL |     0b121;
+   |        ^
+
+error: invalid digit for a base 2 literal
+  --> $DIR/lex-bad-binary-literal.rs:3:12
+   |
+LL |     0b10_10301;
+   |            ^
+
+error: invalid digit for a base 2 literal
+  --> $DIR/lex-bad-binary-literal.rs:4:7
+   |
+LL |     0b30;
+   |       ^
+
+error: invalid digit for a base 2 literal
+  --> $DIR/lex-bad-binary-literal.rs:5:7
+   |
+LL |     0b41;
+   |       ^
+
+error: invalid digit for a base 2 literal
+  --> $DIR/lex-bad-binary-literal.rs:6:7
+   |
+LL |     0b5;
+   |       ^
+
+error: invalid digit for a base 2 literal
+  --> $DIR/lex-bad-binary-literal.rs:7:7
+   |
+LL |     0b6;
+   |       ^
+
+error: invalid digit for a base 2 literal
+  --> $DIR/lex-bad-binary-literal.rs:8:7
+   |
+LL |     0b7;
+   |       ^
+
+error: invalid digit for a base 2 literal
+  --> $DIR/lex-bad-binary-literal.rs:9:7
+   |
+LL |     0b8;
+   |       ^
+
+error: invalid digit for a base 2 literal
+  --> $DIR/lex-bad-binary-literal.rs:10:7
+   |
+LL |     0b9;
+   |       ^
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/lexer/lex-bad-char-literals-1.rs b/src/test/ui/lexer/lex-bad-char-literals-1.rs
new file mode 100644 (file)
index 0000000..e7951cf
--- /dev/null
@@ -0,0 +1,17 @@
+static c3: char =
+    '\x1' //~ ERROR: numeric character escape is too short
+;
+
+static s3: &'static str =
+    "\x1" //~ ERROR: numeric character escape is too short
+;
+
+static c: char =
+    '\●' //~ ERROR: unknown character escape
+;
+
+static s: &'static str =
+    "\●" //~ ERROR: unknown character escape
+;
+
+fn main() {}
diff --git a/src/test/ui/lexer/lex-bad-char-literals-1.stderr b/src/test/ui/lexer/lex-bad-char-literals-1.stderr
new file mode 100644 (file)
index 0000000..ed129a1
--- /dev/null
@@ -0,0 +1,30 @@
+error: numeric character escape is too short
+  --> $DIR/lex-bad-char-literals-1.rs:2:6
+   |
+LL |     '\x1'
+   |      ^^^
+
+error: numeric character escape is too short
+  --> $DIR/lex-bad-char-literals-1.rs:6:6
+   |
+LL |     "\x1"
+   |      ^^^
+
+error: unknown character escape: `\u{25cf}`
+  --> $DIR/lex-bad-char-literals-1.rs:10:7
+   |
+LL |     '\●'
+   |       ^ unknown character escape
+   |
+   = help: for more information, visit <https://static.rust-lang.org/doc/master/reference.html#literals>
+
+error: unknown character escape: `\u{25cf}`
+  --> $DIR/lex-bad-char-literals-1.rs:14:7
+   |
+LL |     "\●"
+   |       ^ unknown character escape
+   |
+   = help: for more information, visit <https://static.rust-lang.org/doc/master/reference.html#literals>
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/lexer/lex-bad-char-literals-2.rs b/src/test/ui/lexer/lex-bad-char-literals-2.rs
new file mode 100644 (file)
index 0000000..d35dafd
--- /dev/null
@@ -0,0 +1,6 @@
+// This test needs to the last one appearing in this file as it kills the parser
+static c: char =
+    'nope' //~ ERROR: character literal may only contain one codepoint
+;
+
+fn main() {}
diff --git a/src/test/ui/lexer/lex-bad-char-literals-2.stderr b/src/test/ui/lexer/lex-bad-char-literals-2.stderr
new file mode 100644 (file)
index 0000000..c2b19a7
--- /dev/null
@@ -0,0 +1,13 @@
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-2.rs:3:5
+   |
+LL |     'nope'
+   |     ^^^^^^
+   |
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL |     "nope"
+   |     ~~~~~~
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lexer/lex-bad-char-literals-3.rs b/src/test/ui/lexer/lex-bad-char-literals-3.rs
new file mode 100644 (file)
index 0000000..5194ff4
--- /dev/null
@@ -0,0 +1,7 @@
+static c: char = '●●';
+//~^ ERROR: character literal may only contain one codepoint
+
+fn main() {
+    let ch: &str = '●●';
+    //~^ ERROR: character literal may only contain one codepoint
+}
diff --git a/src/test/ui/lexer/lex-bad-char-literals-3.stderr b/src/test/ui/lexer/lex-bad-char-literals-3.stderr
new file mode 100644 (file)
index 0000000..62a5e42
--- /dev/null
@@ -0,0 +1,24 @@
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-3.rs:1:18
+   |
+LL | static c: char = '●●';
+   |                  ^^^^
+   |
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL | static c: char = "●●";
+   |                  ~~~~
+
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-3.rs:5:20
+   |
+LL |     let ch: &str = '●●';
+   |                    ^^^^
+   |
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL |     let ch: &str = "●●";
+   |                    ~~~~
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lexer/lex-bad-char-literals-4.rs b/src/test/ui/lexer/lex-bad-char-literals-4.rs
new file mode 100644 (file)
index 0000000..de0a19d
--- /dev/null
@@ -0,0 +1,5 @@
+//
+// This test needs to the last one appearing in this file as it kills the parser
+static c: char =
+    '●  //~ ERROR: unterminated character literal
+;
diff --git a/src/test/ui/lexer/lex-bad-char-literals-4.stderr b/src/test/ui/lexer/lex-bad-char-literals-4.stderr
new file mode 100644 (file)
index 0000000..fec4421
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0762]: unterminated character literal
+  --> $DIR/lex-bad-char-literals-4.rs:4:5
+   |
+LL |     '●
+   |     ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0762`.
diff --git a/src/test/ui/lexer/lex-bad-char-literals-5.rs b/src/test/ui/lexer/lex-bad-char-literals-5.rs
new file mode 100644 (file)
index 0000000..0c4339e
--- /dev/null
@@ -0,0 +1,7 @@
+static c: char = '\x10\x10';
+//~^ ERROR: character literal may only contain one codepoint
+
+fn main() {
+    let ch: &str = '\x10\x10';
+    //~^ ERROR: character literal may only contain one codepoint
+}
diff --git a/src/test/ui/lexer/lex-bad-char-literals-5.stderr b/src/test/ui/lexer/lex-bad-char-literals-5.stderr
new file mode 100644 (file)
index 0000000..184817a
--- /dev/null
@@ -0,0 +1,24 @@
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-5.rs:1:18
+   |
+LL | static c: char = '\x10\x10';
+   |                  ^^^^^^^^^^
+   |
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL | static c: char = "\x10\x10";
+   |                  ~~~~~~~~~~
+
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-5.rs:5:20
+   |
+LL |     let ch: &str = '\x10\x10';
+   |                    ^^^^^^^^^^
+   |
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL |     let ch: &str = "\x10\x10";
+   |                    ~~~~~~~~~~
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lexer/lex-bad-char-literals-6.rs b/src/test/ui/lexer/lex-bad-char-literals-6.rs
new file mode 100644 (file)
index 0000000..4379b4f
--- /dev/null
@@ -0,0 +1,17 @@
+fn main() {
+    let x: &str = 'ab';
+    //~^ ERROR: character literal may only contain one codepoint
+    let y: char = 'cd';
+    //~^ ERROR: character literal may only contain one codepoint
+    let z = 'ef';
+    //~^ ERROR: character literal may only contain one codepoint
+
+    if x == y {}
+    //~^ ERROR: can't compare `&str` with `char`
+    if y == z {}  // no error here
+    if x == z {}
+    //~^ ERROR: can't compare `&str` with `char`
+
+    let a: usize = "";
+    //~^ ERROR: mismatched types
+}
diff --git a/src/test/ui/lexer/lex-bad-char-literals-6.stderr b/src/test/ui/lexer/lex-bad-char-literals-6.stderr
new file mode 100644 (file)
index 0000000..4332bde
--- /dev/null
@@ -0,0 +1,61 @@
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-6.rs:2:19
+   |
+LL |     let x: &str = 'ab';
+   |                   ^^^^
+   |
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL |     let x: &str = "ab";
+   |                   ~~~~
+
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-6.rs:4:19
+   |
+LL |     let y: char = 'cd';
+   |                   ^^^^
+   |
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL |     let y: char = "cd";
+   |                   ~~~~
+
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-6.rs:6:13
+   |
+LL |     let z = 'ef';
+   |             ^^^^
+   |
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL |     let z = "ef";
+   |             ~~~~
+
+error[E0277]: can't compare `&str` with `char`
+  --> $DIR/lex-bad-char-literals-6.rs:9:10
+   |
+LL |     if x == y {}
+   |          ^^ no implementation for `&str == char`
+   |
+   = help: the trait `PartialEq<char>` is not implemented for `&str`
+
+error[E0308]: mismatched types
+  --> $DIR/lex-bad-char-literals-6.rs:15:20
+   |
+LL |     let a: usize = "";
+   |            -----   ^^ expected `usize`, found `&str`
+   |            |
+   |            expected due to this
+
+error[E0277]: can't compare `&str` with `char`
+  --> $DIR/lex-bad-char-literals-6.rs:12:10
+   |
+LL |     if x == z {}
+   |          ^^ no implementation for `&str == char`
+   |
+   = help: the trait `PartialEq<char>` is not implemented for `&str`
+
+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/lexer/lex-bad-char-literals-7.rs b/src/test/ui/lexer/lex-bad-char-literals-7.rs
new file mode 100644 (file)
index 0000000..c675df2
--- /dev/null
@@ -0,0 +1,13 @@
+fn main() {
+    let _: char = '';
+    //~^ ERROR: empty character literal
+    let _: char = '\u{}';
+    //~^ ERROR: empty unicode escape
+
+    // Next two are OK, but may befool error recovery
+    let _ = '/';
+    let _ = b'/';
+
+    let _ = ' hello // here's a comment
+    //~^ ERROR: unterminated character literal
+}
diff --git a/src/test/ui/lexer/lex-bad-char-literals-7.stderr b/src/test/ui/lexer/lex-bad-char-literals-7.stderr
new file mode 100644 (file)
index 0000000..255b9c6
--- /dev/null
@@ -0,0 +1,21 @@
+error: empty character literal
+  --> $DIR/lex-bad-char-literals-7.rs:2:20
+   |
+LL |     let _: char = '';
+   |                    ^ empty character literal
+
+error: empty unicode escape
+  --> $DIR/lex-bad-char-literals-7.rs:4:20
+   |
+LL |     let _: char = '\u{}';
+   |                    ^^^^ this escape must have at least 1 hex digit
+
+error[E0762]: unterminated character literal
+  --> $DIR/lex-bad-char-literals-7.rs:11:13
+   |
+LL |     let _ = ' hello // here's a comment
+   |             ^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0762`.
diff --git a/src/test/ui/lexer/lex-bad-numeric-literals.rs b/src/test/ui/lexer/lex-bad-numeric-literals.rs
new file mode 100644 (file)
index 0000000..cf8440c
--- /dev/null
@@ -0,0 +1,27 @@
+fn main() {
+    0o1.0; //~ ERROR: octal float literal is not supported
+    0o2f32; //~ ERROR: octal float literal is not supported
+    0o3.0f32; //~ ERROR: octal float literal is not supported
+    0o4e4; //~ ERROR: octal float literal is not supported
+    0o5.0e5; //~ ERROR: octal float literal is not supported
+    0o6e6f32; //~ ERROR: octal float literal is not supported
+    0o7.0e7f64; //~ ERROR: octal float literal is not supported
+    0x8.0e+9; //~ ERROR: hexadecimal float literal is not supported
+    0x9.0e-9; //~ ERROR: hexadecimal float literal is not supported
+    0o; //~ ERROR: no valid digits
+    1e+; //~ ERROR: expected at least one digit in exponent
+    0x539.0; //~ ERROR: hexadecimal float literal is not supported
+    9900000000000000000000000000999999999999999999999999999999;
+    //~^ ERROR: integer literal is too large
+    9900000000000000000000000000999999999999999999999999999999;
+    //~^ ERROR: integer literal is too large
+    0x; //~ ERROR: no valid digits
+    0xu32; //~ ERROR: no valid digits
+    0ou32; //~ ERROR: no valid digits
+    0bu32; //~ ERROR: no valid digits
+    0b; //~ ERROR: no valid digits
+    0o123f64; //~ ERROR: octal float literal is not supported
+    0o123.456; //~ ERROR: octal float literal is not supported
+    0b101f64; //~ ERROR: binary float literal is not supported
+    0b111.101; //~ ERROR: binary float literal is not supported
+}
diff --git a/src/test/ui/lexer/lex-bad-numeric-literals.stderr b/src/test/ui/lexer/lex-bad-numeric-literals.stderr
new file mode 100644 (file)
index 0000000..f05d616
--- /dev/null
@@ -0,0 +1,141 @@
+error: octal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:2:5
+   |
+LL |     0o1.0;
+   |     ^^^^^
+
+error: octal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:4:5
+   |
+LL |     0o3.0f32;
+   |     ^^^^^
+
+error: octal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:5:5
+   |
+LL |     0o4e4;
+   |     ^^^^^
+
+error: octal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:6:5
+   |
+LL |     0o5.0e5;
+   |     ^^^^^^^
+
+error: octal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:7:5
+   |
+LL |     0o6e6f32;
+   |     ^^^^^
+
+error: octal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:8:5
+   |
+LL |     0o7.0e7f64;
+   |     ^^^^^^^
+
+error: hexadecimal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:9:5
+   |
+LL |     0x8.0e+9;
+   |     ^^^^^^^^
+
+error: hexadecimal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:10:5
+   |
+LL |     0x9.0e-9;
+   |     ^^^^^^^^
+
+error[E0768]: no valid digits found for number
+  --> $DIR/lex-bad-numeric-literals.rs:11:5
+   |
+LL |     0o;
+   |     ^^
+
+error: expected at least one digit in exponent
+  --> $DIR/lex-bad-numeric-literals.rs:12:5
+   |
+LL |     1e+;
+   |     ^^^
+
+error: hexadecimal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:13:5
+   |
+LL |     0x539.0;
+   |     ^^^^^^^
+
+error[E0768]: no valid digits found for number
+  --> $DIR/lex-bad-numeric-literals.rs:18:5
+   |
+LL |     0x;
+   |     ^^
+
+error[E0768]: no valid digits found for number
+  --> $DIR/lex-bad-numeric-literals.rs:19:5
+   |
+LL |     0xu32;
+   |     ^^
+
+error[E0768]: no valid digits found for number
+  --> $DIR/lex-bad-numeric-literals.rs:20:5
+   |
+LL |     0ou32;
+   |     ^^
+
+error[E0768]: no valid digits found for number
+  --> $DIR/lex-bad-numeric-literals.rs:21:5
+   |
+LL |     0bu32;
+   |     ^^
+
+error[E0768]: no valid digits found for number
+  --> $DIR/lex-bad-numeric-literals.rs:22:5
+   |
+LL |     0b;
+   |     ^^
+
+error: octal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:24:5
+   |
+LL |     0o123.456;
+   |     ^^^^^^^^^
+
+error: binary float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:26:5
+   |
+LL |     0b111.101;
+   |     ^^^^^^^^^
+
+error: octal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:3:5
+   |
+LL |     0o2f32;
+   |     ^^^^^^ not supported
+
+error: integer literal is too large
+  --> $DIR/lex-bad-numeric-literals.rs:14:5
+   |
+LL |     9900000000000000000000000000999999999999999999999999999999;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: integer literal is too large
+  --> $DIR/lex-bad-numeric-literals.rs:16:5
+   |
+LL |     9900000000000000000000000000999999999999999999999999999999;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: octal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:23:5
+   |
+LL |     0o123f64;
+   |     ^^^^^^^^ not supported
+
+error: binary float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:25:5
+   |
+LL |     0b101f64;
+   |     ^^^^^^^^ not supported
+
+error: aborting due to 23 previous errors
+
+For more information about this error, try `rustc --explain E0768`.
diff --git a/src/test/ui/lexer/lex-bad-octal-literal.rs b/src/test/ui/lexer/lex-bad-octal-literal.rs
new file mode 100644 (file)
index 0000000..49631f1
--- /dev/null
@@ -0,0 +1,4 @@
+fn main() {
+    0o18; //~ ERROR invalid digit for a base 8 literal
+    0o1234_9_5670;  //~ ERROR invalid digit for a base 8 literal
+}
diff --git a/src/test/ui/lexer/lex-bad-octal-literal.stderr b/src/test/ui/lexer/lex-bad-octal-literal.stderr
new file mode 100644 (file)
index 0000000..2cb8ca5
--- /dev/null
@@ -0,0 +1,14 @@
+error: invalid digit for a base 8 literal
+  --> $DIR/lex-bad-octal-literal.rs:2:8
+   |
+LL |     0o18;
+   |        ^
+
+error: invalid digit for a base 8 literal
+  --> $DIR/lex-bad-octal-literal.rs:3:12
+   |
+LL |     0o1234_9_5670;
+   |            ^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lexer/lex-bad-token.rs b/src/test/ui/lexer/lex-bad-token.rs
new file mode 100644 (file)
index 0000000..9e48246
--- /dev/null
@@ -0,0 +1,3 @@
+● //~ ERROR: unknown start of token
+
+fn main() {}
diff --git a/src/test/ui/lexer/lex-bad-token.stderr b/src/test/ui/lexer/lex-bad-token.stderr
new file mode 100644 (file)
index 0000000..43c4372
--- /dev/null
@@ -0,0 +1,8 @@
+error: unknown start of token: \u{25cf}
+  --> $DIR/lex-bad-token.rs:1:1
+   |
+LL | ●
+   | ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lexer/lex-bare-cr-nondoc-comment.rs b/src/test/ui/lexer/lex-bare-cr-nondoc-comment.rs
new file mode 100644 (file)
index 0000000..5b528d6
--- /dev/null
@@ -0,0 +1,9 @@
+// run-pass
+// ignore-tidy-cr
+
+// nondoc comment with bare CR: '\r'
+//// nondoc comment with bare CR: '\r'
+/* block nondoc comment with bare CR: '\r' */
+
+fn main() {
+}
diff --git a/src/test/ui/lexer/lex-bare-cr-string-literal-doc-comment.rs b/src/test/ui/lexer/lex-bare-cr-string-literal-doc-comment.rs
new file mode 100644 (file)
index 0000000..b7752e1
--- /dev/null
@@ -0,0 +1,26 @@
+// ignore-tidy-cr
+
+/// doc comment with bare CR: '\r'
+pub fn foo() {}
+//~^^ ERROR: bare CR not allowed in doc-comment
+
+/** block doc comment with bare CR: '\r' */
+pub fn bar() {}
+//~^^ ERROR: bare CR not allowed in block doc-comment
+
+fn main() {
+    //! doc comment with bare CR: '\r'
+    //~^ ERROR: bare CR not allowed in doc-comment
+
+    /*! block doc comment with bare CR: '\r' */
+    //~^ ERROR: bare CR not allowed in block doc-comment
+
+    // the following string literal has a bare CR in it
+    let _s = "foo\rbar"; //~ ERROR: bare CR not allowed in string
+
+    // the following string literal has a bare CR in it
+    let _s = r"bar\rfoo"; //~ ERROR: bare CR not allowed in raw string
+
+    // the following string literal has a bare CR in it
+    let _s = "foo\\rbar"; //~ ERROR: unknown character escape: `\r`
+}
diff --git a/src/test/ui/lexer/lex-bare-cr-string-literal-doc-comment.stderr b/src/test/ui/lexer/lex-bare-cr-string-literal-doc-comment.stderr
new file mode 100644 (file)
index 0000000..1a21fed
--- /dev/null
@@ -0,0 +1,46 @@
+error: bare CR not allowed in doc-comment
+  --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:3:32
+   |
+LL | /// doc comment with bare CR: '\r'
+   |                                ^
+
+error: bare CR not allowed in block doc-comment
+  --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:7:38
+   |
+LL | /** block doc comment with bare CR: '\r' */
+   |                                      ^
+
+error: bare CR not allowed in doc-comment
+  --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:12:36
+   |
+LL |     //! doc comment with bare CR: '\r'
+   |                                    ^
+
+error: bare CR not allowed in block doc-comment
+  --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:15:42
+   |
+LL |     /*! block doc comment with bare CR: '\r' */
+   |                                          ^
+
+error: bare CR not allowed in string, use `\r` instead
+  --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:19:18
+   |
+LL |     let _s = "foo\rbar";
+   |                  ^ help: escape the character: `\r`
+
+error: bare CR not allowed in raw string
+  --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:22:19
+   |
+LL |     let _s = r"bar\rfoo";
+   |                   ^
+
+error: unknown character escape: `\r`
+  --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:25:19
+   |
+LL |     let _s = "foo\\rbar";
+   |                   ^ unknown character escape
+   |
+   = help: this is an isolated carriage return; consider checking your editor and version control settings
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/lexer/lex-stray-backslash.rs b/src/test/ui/lexer/lex-stray-backslash.rs
new file mode 100644 (file)
index 0000000..bb27f44
--- /dev/null
@@ -0,0 +1,3 @@
+\ //~ ERROR: unknown start of token: \
+
+fn main() {}
diff --git a/src/test/ui/lexer/lex-stray-backslash.stderr b/src/test/ui/lexer/lex-stray-backslash.stderr
new file mode 100644 (file)
index 0000000..06dc0f2
--- /dev/null
@@ -0,0 +1,8 @@
+error: unknown start of token: \
+  --> $DIR/lex-stray-backslash.rs:1:1
+   |
+LL | \
+   | ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lexer/lexer-crlf-line-endings-string-literal-doc-comment.rs b/src/test/ui/lexer/lexer-crlf-line-endings-string-literal-doc-comment.rs
new file mode 100644 (file)
index 0000000..802be7f
--- /dev/null
@@ -0,0 +1,38 @@
+// run-pass\r
+// ignore-tidy-cr\r
+// ignore-tidy-cr (repeated again because of tidy bug)\r
+// license is ignored because tidy can't handle the CRLF here properly.\r
+\r
+// N.B., this file needs CRLF line endings. The .gitattributes file in\r
+// this directory should enforce it.\r
+\r
+// ignore-pretty issue #37195\r
+\r
+/// Doc comment that ends in CRLF\r
+pub fn foo() {}\r
+\r
+/** Block doc comment that\r
+ *  contains CRLF characters\r
+ */\r
+pub fn bar() {}\r
+\r
+fn main() {\r
+    let s = "string\r
+literal";\r
+    assert_eq!(s, "string\nliteral");\r
+\r
+    let s = "literal with \\r
+             escaped newline";\r
+    assert_eq!(s, "literal with escaped newline");\r
+\r
+    let s = r"string\r
+literal";\r
+    assert_eq!(s, "string\nliteral");\r
+    let s = br"byte string\r
+literal";\r
+    assert_eq!(s, "byte string\nliteral".as_bytes());\r
+\r
+    // validate that our source file has CRLF endings\r
+    let source = include_str!("lexer-crlf-line-endings-string-literal-doc-comment.rs");\r
+    assert!(source.contains("string\r\nliteral"));\r
+}\r
diff --git a/src/test/ui/lifetimes/issue-76168-hr-outlives.rs b/src/test/ui/lifetimes/issue-76168-hr-outlives.rs
new file mode 100644 (file)
index 0000000..9366e94
--- /dev/null
@@ -0,0 +1,19 @@
+// edition:2018
+// check-pass
+
+#![feature(unboxed_closures)]
+use std::future::Future;
+
+async fn wrapper<F>(f: F)
+where for<'a> F: FnOnce<(&'a mut i32,)>,
+    for<'a> <F as FnOnce<(&'a mut i32,)>>::Output: Future<Output=()> + 'a
+{
+    let mut i = 41;
+    f(&mut i).await;
+}
+
+async fn add_one(i: &mut i32) {
+    *i = *i + 1;
+}
+
+fn main() {}
index a7e382479021aeb8767c6b46391f0ecb8476eb30..90411353f08250496680c6466b0f8b594167663b 100644 (file)
@@ -18,6 +18,7 @@ LL |     println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>());
    = note: `#[deny(const_err)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors
 
index baa47cbb10fd5a6529a5e29ae856e961553798b0..f5e8b41b1634e5e2b7046af4aab722a0f5c6fefd 100644 (file)
@@ -2,9 +2,13 @@ warning: hidden lifetime parameters in types are deprecated
   --> $DIR/allowed-by-default-lint.rs:9:12
    |
 LL | fn foo(x: &Foo) {}
-   |            ^^^- help: indicate the anonymous lifetime: `<'_>`
+   |            ^^^ expected named lifetime parameter
    |
    = note: requested on the command line with `--force-warn elided-lifetimes-in-paths`
+help: consider using the `'_` lifetime
+   |
+LL | fn foo(x: &Foo<'_>) {}
+   |            ~~~~~~~
 
 warning: 1 warning emitted
 
index 79effd054b083f0db31ef8c209c0e91cb15b0fc3..717ca4986f700e6e0fca62692bfb1790f8eb656f 100644 (file)
@@ -33,7 +33,7 @@ fn use_of_b() -> AliasB {
 }
 
 extern "C" {
-    pub fn lint_me() -> <AliasB as TraitB>::Assoc; //~ ERROR: uses type `impl TraitA`
+    pub fn lint_me() -> <AliasB as TraitB>::Assoc; //~ ERROR: uses type `impl TraitA<Assoc = u32>`
 }
 
 fn main() {}
index 94ee95d422e086f7cf7c7445f95ee9147d1869ef..d7e10db441ec23eb11ca485e468a1bb96785682b 100644 (file)
@@ -1,4 +1,4 @@
-error: `extern` block uses type `impl TraitA`, which is not FFI-safe
+error: `extern` block uses type `impl TraitA<Assoc = u32>`, which is not FFI-safe
   --> $DIR/lint-ctypes-73251-2.rs:36:25
    |
 LL |     pub fn lint_me() -> <AliasB as TraitB>::Assoc;
index fadb7471952f59e384375dbb7a193b82b8b7852f..3a62b6a21a56a6dc859d77adc2bece27ea285ebc 100644 (file)
@@ -9,7 +9,7 @@ pub fn ret_closure() -> A {
 
 extern "C" {
     pub fn a(_: A);
-    //~^ ERROR `extern` block uses type `impl Fn<()>`, which is not FFI-safe
+    //~^ ERROR `extern` block uses type `impl Fn()`, which is not FFI-safe [improper_ctypes]
 }
 
 fn main() {}
index 9d46f6d936e25273f97ebd28d286b65691e1662a..5afbef778b3e35d29b38472d517b0f48729794fd 100644 (file)
@@ -1,4 +1,4 @@
-error: `extern` block uses type `impl Fn<()>`, which is not FFI-safe
+error: `extern` block uses type `impl Fn()`, which is not FFI-safe
   --> $DIR/opaque-ty-ffi-unsafe.rs:11:17
    |
 LL |     pub fn a(_: A);
index 34cac4968a84fe508190f6ff7a9c0678644560a2..b1792e2e9cbf862a1b645cc78d83ebe9d377211a 100644 (file)
@@ -1,7 +1,6 @@
 // check-pass
 
 #![feature(lint_reasons)]
-
 #![warn(elided_lifetimes_in_paths,
         //~^ NOTE the lint level is defined here
         reason = "explicit anonymous lifetimes aid reasoning about ownership")]
@@ -20,8 +19,9 @@ pub struct CheaterDetectionMechanism {}
 impl fmt::Debug for CheaterDetectionMechanism {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         //~^ WARN hidden lifetime parameters in types are deprecated
+        //~| NOTE expected named lifetime parameter
         //~| NOTE explicit anonymous lifetimes aid
-        //~| HELP indicate the anonymous lifetime
+        //~| HELP consider using the `'_` lifetime
         fmt.debug_struct("CheaterDetectionMechanism").finish()
     }
 }
index 150237c6be2933bae4d1cbdc31c9f930134abe13..f797c89a0326994344b87cf92d752861fc593108 100644 (file)
@@ -1,15 +1,19 @@
 warning: hidden lifetime parameters in types are deprecated
-  --> $DIR/reasons.rs:21:29
+  --> $DIR/reasons.rs:20:29
    |
 LL |     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-   |                             ^^^^^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
+   |                             ^^^^^^^^^^^^^^ expected named lifetime parameter
    |
    = note: explicit anonymous lifetimes aid reasoning about ownership
 note: the lint level is defined here
-  --> $DIR/reasons.rs:5:9
+  --> $DIR/reasons.rs:4:9
    |
 LL | #![warn(elided_lifetimes_in_paths,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider using the `'_` lifetime
+   |
+LL |     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+   |                             ~~~~~~~~~~~~~~~~~~
 
 warning: variable `Social_exchange_psychology` should have a snake case name
   --> $DIR/reasons.rs:30:9
@@ -20,7 +24,7 @@ LL |     let Social_exchange_psychology = CheaterDetectionMechanism {};
    = note: people shouldn't have to change their usual style habits
            to contribute to our project
 note: the lint level is defined here
-  --> $DIR/reasons.rs:9:5
+  --> $DIR/reasons.rs:8:5
    |
 LL |     nonstandard_style,
    |     ^^^^^^^^^^^^^^^^^
index fd9baf8c6b9a28168e7433af05f1d3cd0ed15bb6..258f9e4831f9a3cddefc110f71cb43c55de0d763 100644 (file)
@@ -26,4 +26,7 @@ fn doc_comment_on_expr(num: u8) -> bool {
     num == 3
 }
 
+fn doc_comment_on_generic<#[doc = "x"] T>(val: T) {}
+//~^ ERROR: unused doc comment
+
 fn main() {}
index 403367017c6e6e35e4c9f2a8bfa6034b72d769ba..3ce1df71a2ed58b9c41004cc102416075dde40fc 100644 (file)
@@ -41,6 +41,14 @@ LL |     num == 3
    |
    = help: use `//` for a plain comment
 
+error: unused doc comment
+  --> $DIR/unused-doc-comments-edge-cases.rs:29:27
+   |
+LL | fn doc_comment_on_generic<#[doc = "x"] T>(val: T) {}
+   |                           ^^^^^^^^^^^^ - rustdoc does not generate documentation for generic parameters
+   |
+   = help: use `//` for a plain comment
+
 error[E0308]: mismatched types
   --> $DIR/unused-doc-comments-edge-cases.rs:14:9
    |
@@ -55,7 +63,7 @@ help: you might have meant to return this value
 LL |         return true;
    |         ++++++     +
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0308, E0658.
 For more information about an error, try `rustc --explain E0308`.
index 6a8f239bd09a8a073862e455e3e15d7631167d78..ff6c02f2110f647daf0c1ecf6b6f446cf16bf974 100644 (file)
@@ -28,6 +28,8 @@ LL |         println!("{}", y);
    |                        ^ value borrowed here after move
 LL |         while true { while true { while true { x = y; x.clone(); } } }
    |                                                    - value moved here, in previous iteration of loop
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error; 3 warnings emitted
 
index 292ce013dcc7622aaaa2cce9a285009cbe79b702..df54af9f0f2ce2e038bd2c420ea62fefce0920de 100644 (file)
@@ -8,6 +8,8 @@ LL |     let y = x;
 LL | 
 LL |     println!("{}", *x);
    |                    ^^ value borrowed here after move
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index 50ae98ca9bedcca7190a8d4a7d5c2d88b3b0cbb4..becede1ceb6b3edd0b0f3eadad2c6ca2f7a7fe5e 100644 (file)
@@ -7,6 +7,8 @@ LL |     send(ch, message);
    |              ------- value moved here
 LL |     println!("{}", message);
    |                    ^^^^^^^ value borrowed here after move
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index d55f9ff31e3ee7a43c343ab0da0a0ff49690ba64..20d5c66a3f20581c789238f26c733a54c859c8d5 100644 (file)
@@ -3,6 +3,8 @@ error[E0381]: borrow of possibly-uninitialized variable: `x`
    |
 LL |     println!("{:?}", x);
    |                      ^ use of possibly-uninitialized `x`
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index 922ec36e531de9d74541387cdf3360faab8a8a12..0098584dd261c8e729f0e379fd25507ec9ce8908 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-// compile-flags: -Z force-overflow-checks=off
+// compile-flags: -overflow-checks=off
 
 // Test that with MIR codegen, overflow checks can be
 // turned off, even when they're from core::ops::*.
index 0c27e17294131d334fa28053e54ca0dc221e6d0f..f8f2b1f0f57204c9120a693b43852f7e441d73f8 100644 (file)
@@ -7,6 +7,9 @@ LL |     length = { foo(&length) };
 error[E0308]: mismatched types
   --> $DIR/issue-84976.rs:17:14
    |
+LL |     let mut length = 0;
+   |                      - expected due to this value
+...
 LL |     length = foo(&length);
    |              ^^^^^^^^^^^^ expected `u32`, found `i32`
 
@@ -19,6 +22,9 @@ LL |     float_length = { bar(&float_length) };
 error[E0308]: mismatched types
   --> $DIR/issue-84976.rs:23:20
    |
+LL |     let mut float_length = 0.0;
+   |                            --- expected due to this value
+...
 LL |     float_length = bar(&float_length);
    |                    ^^^^^^^^^^^^^^^^^^ expected `f32`, found `f64`
 
index acb0932f6d6b9a98f242db9be125f5192fac26fe..ac921c18e07d577ace08f15b684ff4269e709750 100644 (file)
@@ -10,6 +10,8 @@ LL |         println!("{}", x);
 LL |     });
 LL |     println!("{}", x);
    |                    ^ value borrowed here after move
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index 10ec3f0c6624e73ce29211b01c16eaf721c2a626..9c6dff7e1a6ca151d5d08651d1e9a7a494f9d73d 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-// compile-flags: -Z force-overflow-checks=on
+// compile-flags: -overflow-checks=on
 // ignore-emscripten no threads support
 
 use std::thread;
diff --git a/src/test/ui/optimization-remark.rs b/src/test/ui/optimization-remark.rs
new file mode 100644 (file)
index 0000000..36549cb
--- /dev/null
@@ -0,0 +1,28 @@
+// build-pass
+// ignore-pass
+// no-system-llvm
+// revisions: all inline merge1 merge2
+// compile-flags: --crate-type=lib -Cdebuginfo=1 -Copt-level=2
+//
+// Check that remarks can be enabled individually or with "all":
+//
+// [all]    compile-flags: -Cremark=all
+// [inline] compile-flags: -Cremark=inline
+//
+// Check that values of -Cremark flag are accumulated:
+//
+// [merge1] compile-flags: -Cremark=all    -Cremark=giraffe
+// [merge2] compile-flags: -Cremark=inline -Cremark=giraffe
+//
+// error-pattern: inline: f not inlined into g
+// dont-check-compiler-stderr
+
+#[no_mangle]
+#[inline(never)]
+pub fn f() {
+}
+
+#[no_mangle]
+pub fn g() {
+    f();
+}
index 533bd87c9cccb2b6192787a5f5fbbb104e0d2594..4507a4df621e1c2fde27ad96a18cf3ce4791dee3 100644 (file)
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/output-type-mismatch.rs:5:31
    |
 LL | fn main() { let i: isize; i = f(); }
-   |                               ^^^ expected `isize`, found `()`
+   |                    -----      ^^^ expected `isize`, found `()`
+   |                    |
+   |                    expected due to this type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/const-param-decl-on-type-instead-of-impl.rs b/src/test/ui/parser/const-param-decl-on-type-instead-of-impl.rs
new file mode 100644 (file)
index 0000000..53e3c6f
--- /dev/null
@@ -0,0 +1,15 @@
+struct NInts<const N: usize>([u8; N]);
+impl NInts<const N: usize> {} //~ ERROR unexpected `const` parameter declaration
+
+fn main() {
+    let _: () = 42; //~ ERROR mismatched types
+}
+
+fn banana(a: <T<const N: usize>>::BAR) {}
+//~^ ERROR unexpected `const` parameter declaration
+//~| ERROR cannot find type `T` in this scope
+fn chaenomeles() {
+    path::path::Struct::<const N: usize>()
+    //~^ ERROR unexpected `const` parameter declaration
+    //~| ERROR failed to resolve: use of undeclared crate or module `path`
+}
diff --git a/src/test/ui/parser/const-param-decl-on-type-instead-of-impl.stderr b/src/test/ui/parser/const-param-decl-on-type-instead-of-impl.stderr
new file mode 100644 (file)
index 0000000..96885d1
--- /dev/null
@@ -0,0 +1,47 @@
+error: unexpected `const` parameter declaration
+  --> $DIR/const-param-decl-on-type-instead-of-impl.rs:2:12
+   |
+LL | impl NInts<const N: usize> {}
+   |            ^^^^^^^^^^^^^^ expected a `const` expression, not a parameter declaration
+   |
+help: `const` parameters must be declared for the `impl`
+   |
+LL | impl<const N: usize> NInts<N> {}
+   |     ++++++++++++++++       ~
+
+error: unexpected `const` parameter declaration
+  --> $DIR/const-param-decl-on-type-instead-of-impl.rs:8:17
+   |
+LL | fn banana(a: <T<const N: usize>>::BAR) {}
+   |                 ^^^^^^^^^^^^^^ expected a `const` expression, not a parameter declaration
+
+error: unexpected `const` parameter declaration
+  --> $DIR/const-param-decl-on-type-instead-of-impl.rs:12:26
+   |
+LL |     path::path::Struct::<const N: usize>()
+   |                          ^^^^^^^^^^^^^^ expected a `const` expression, not a parameter declaration
+
+error[E0433]: failed to resolve: use of undeclared crate or module `path`
+  --> $DIR/const-param-decl-on-type-instead-of-impl.rs:12:5
+   |
+LL |     path::path::Struct::<const N: usize>()
+   |     ^^^^ use of undeclared crate or module `path`
+
+error[E0412]: cannot find type `T` in this scope
+  --> $DIR/const-param-decl-on-type-instead-of-impl.rs:8:15
+   |
+LL | fn banana(a: <T<const N: usize>>::BAR) {}
+   |               ^ not found in this scope
+
+error[E0308]: mismatched types
+  --> $DIR/const-param-decl-on-type-instead-of-impl.rs:5:17
+   |
+LL |     let _: () = 42;
+   |            --   ^^ expected `()`, found integer
+   |            |
+   |            expected due to this
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0308, E0412, E0433.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/emoji-identifiers.rs b/src/test/ui/parser/emoji-identifiers.rs
new file mode 100644 (file)
index 0000000..ef18939
--- /dev/null
@@ -0,0 +1,16 @@
+struct ABig👩‍👩‍👧‍👧Family; //~ ERROR identifiers cannot contain emoji
+struct 👀; //~ ERROR identifiers cannot contain emoji
+impl 👀 {
+    fn full_of_✨() -> 👀 { //~ ERROR identifiers cannot contain emoji
+        👀
+    }
+}
+fn i_like_to_😅_a_lot() -> 👀 { //~ ERROR identifiers cannot contain emoji
+    👀::full_of✨() //~ ERROR no function or associated item named `full_of✨` found for struct `👀`
+    //~^ ERROR identifiers cannot contain emoji
+}
+fn main() {
+    let _ = i_like_to_😄_a_lot() ➖ 4; //~ ERROR cannot find function `i_like_to_😄_a_lot` in this scope
+    //~^ ERROR identifiers cannot contain emoji
+    //~| ERROR unknown start of token: \u{2796}
+}
diff --git a/src/test/ui/parser/emoji-identifiers.stderr b/src/test/ui/parser/emoji-identifiers.stderr
new file mode 100644 (file)
index 0000000..5f9263c
--- /dev/null
@@ -0,0 +1,83 @@
+error: unknown start of token: \u{2796}
+  --> $DIR/emoji-identifiers.rs:13:33
+   |
+LL |     let _ = i_like_to_😄_a_lot() ➖ 4;
+   |                                  ^^
+   |
+help: Unicode character '➖' (Heavy Minus Sign) looks like '-' (Minus/Hyphen), but it is not
+   |
+LL |     let _ = i_like_to_😄_a_lot() - 4;
+   |                                  ~
+
+error[E0425]: cannot find function `i_like_to_😄_a_lot` in this scope
+  --> $DIR/emoji-identifiers.rs:13:13
+   |
+LL | fn i_like_to_😅_a_lot() -> 👀 {
+   | ----------------------------- similarly named function `i_like_to_😅_a_lot` defined here
+...
+LL |     let _ = i_like_to_😄_a_lot() ➖ 4;
+   |             ^^^^^^^^^^^^^^^^^^ help: a function with a similar name exists: `i_like_to_😅_a_lot`
+
+error: identifiers cannot contain emoji: `ABig👩👩👧👧Family`
+  --> $DIR/emoji-identifiers.rs:1:8
+   |
+LL | struct ABig👩👩👧👧Family;
+   |        ^^^^^^^^^^^^^^^^^^
+
+error: identifiers cannot contain emoji: `👀`
+  --> $DIR/emoji-identifiers.rs:2:8
+   |
+LL | struct 👀;
+   |        ^^
+LL | impl 👀 {
+   |      ^^
+LL |     fn full_of_✨() -> 👀 {
+   |                        ^^
+LL |         👀
+   |         ^^
+...
+LL | fn i_like_to_😅_a_lot() -> 👀 {
+   |                            ^^
+LL |     👀::full_of✨()
+   |     ^^
+
+error: identifiers cannot contain emoji: `full_of_✨`
+  --> $DIR/emoji-identifiers.rs:4:8
+   |
+LL |     fn full_of_✨() -> 👀 {
+   |        ^^^^^^^^^^
+
+error: identifiers cannot contain emoji: `i_like_to_😅_a_lot`
+  --> $DIR/emoji-identifiers.rs:8:4
+   |
+LL | fn i_like_to_😅_a_lot() -> 👀 {
+   |    ^^^^^^^^^^^^^^^^^^
+
+error: identifiers cannot contain emoji: `full_of✨`
+  --> $DIR/emoji-identifiers.rs:9:8
+   |
+LL |     👀::full_of✨()
+   |         ^^^^^^^^^
+
+error: identifiers cannot contain emoji: `i_like_to_😄_a_lot`
+  --> $DIR/emoji-identifiers.rs:13:13
+   |
+LL |     let _ = i_like_to_😄_a_lot() ➖ 4;
+   |             ^^^^^^^^^^^^^^^^^^
+
+error[E0599]: no function or associated item named `full_of✨` found for struct `👀` in the current scope
+  --> $DIR/emoji-identifiers.rs:9:8
+   |
+LL | struct 👀;
+   | ---------- function or associated item `full_of✨` not found for this
+...
+LL |     👀::full_of✨()
+   |         ^^^^^^^^^
+   |         |
+   |         function or associated item not found in `👀`
+   |         help: there is an associated function with a similar name: `full_of_✨`
+
+error: aborting due to 9 previous errors
+
+Some errors have detailed explanations: E0425, E0599.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/parser/issue-91421.rs b/src/test/ui/parser/issue-91421.rs
new file mode 100644 (file)
index 0000000..9959df5
--- /dev/null
@@ -0,0 +1,10 @@
+// Regression test for issue #91421.
+
+fn main() {
+    let value = if true && {
+    //~^ ERROR: this `if` expression has a condition, but no block
+    //~| HELP: maybe you forgot the right operand of the condition?
+        3
+        //~^ ERROR: mismatched types [E0308]
+    } else { 4 };
+}
diff --git a/src/test/ui/parser/issue-91421.stderr b/src/test/ui/parser/issue-91421.stderr
new file mode 100644 (file)
index 0000000..04284d5
--- /dev/null
@@ -0,0 +1,21 @@
+error: this `if` expression has a condition, but no block
+  --> $DIR/issue-91421.rs:4:17
+   |
+LL |     let value = if true && {
+   |                 ^^
+   |
+help: maybe you forgot the right operand of the condition?
+  --> $DIR/issue-91421.rs:4:25
+   |
+LL |     let value = if true && {
+   |                         ^^
+
+error[E0308]: mismatched types
+  --> $DIR/issue-91421.rs:7:9
+   |
+LL |         3
+   |         ^ expected `bool`, found integer
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index 4ee0b2054ff772dcc3c92ca5bbc99a06dc5ffb04..0b7b67496d6f32df39107feb43e1c957a029ae21 100644 (file)
@@ -1,11 +1,15 @@
 // Tests that a suggestion is issued if the user wrote a colon instead of
 // a path separator in a match arm.
 
-enum Foo {
-    Bar,
-    Baz,
+mod qux {
+    pub enum Foo {
+        Bar,
+        Baz,
+    }
 }
 
+use qux::Foo;
+
 fn f() -> Foo { Foo::Bar }
 
 fn g1() {
@@ -16,24 +20,24 @@ fn g1() {
         _ => {}
     }
     match f() {
-        Foo::Bar:Baz => {}
+        qux::Foo:Bar => {}
         //~^ ERROR: expected one of
         //~| HELP: maybe write a path separator here
         _ => {}
     }
     match f() {
-        Foo:Bar::Baz => {}
+        qux:Foo::Baz => {}
         //~^ ERROR: expected one of
         //~| HELP: maybe write a path separator here
         _ => {}
     }
     match f() {
-        Foo: Bar::Baz if true => {}
+        qux: Foo::Baz if true => {}
         //~^ ERROR: expected one of
         //~| HELP: maybe write a path separator here
         _ => {}
     }
-    if let Bar:Baz = f() {
+    if let Foo:Bar = f() {
     //~^ ERROR: expected one of
     //~| HELP: maybe write a path separator here
     }
@@ -41,16 +45,18 @@ fn g1() {
 
 fn g1_neg() {
     match f() {
-        ref Foo: Bar::Baz => {}
+        ref qux: Foo::Baz => {}
         //~^ ERROR: expected one of
+        //~| HELP: maybe write a path separator here
         _ => {}
     }
 }
 
 fn g2_neg() {
     match f() {
-        mut Foo: Bar::Baz => {}
+        mut qux: Foo::Baz => {}
         //~^ ERROR: expected one of
+        //~| HELP: maybe write a path separator here
         _ => {}
     }
 }
@@ -62,5 +68,12 @@ fn main() {
         Foo:Bar::Baz => {}
         //~^ ERROR: expected one of
         //~| HELP: maybe write a path separator here
+        //~| ERROR: failed to resolve: `Bar` is a variant, not a module
+    }
+    match myfoo {
+        Foo::Bar => {}
+        Foo:Bar => {}
+        //~^ ERROR: expected one of
+        //~| HELP: maybe write a path separator here
     }
 }
index 8f93661a626467f7e85ef154140fbbbf292b15be..2050a16beb34983c63e96f847a82c1d23f3f16d5 100644 (file)
@@ -1,5 +1,5 @@
 error: expected one of `@` or `|`, found `:`
-  --> $DIR/issue-87086-colon-path-sep.rs:13:12
+  --> $DIR/issue-87086-colon-path-sep.rs:17:12
    |
 LL |         Foo:Bar => {}
    |            ^
@@ -8,55 +8,61 @@ LL |         Foo:Bar => {}
    |            help: maybe write a path separator here: `::`
 
 error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `{`, or `|`, found `:`
-  --> $DIR/issue-87086-colon-path-sep.rs:19:17
+  --> $DIR/issue-87086-colon-path-sep.rs:23:17
    |
-LL |         Foo::Bar:Baz => {}
+LL |         qux::Foo:Bar => {}
    |                 ^
    |                 |
    |                 expected one of 8 possible tokens
    |                 help: maybe write a path separator here: `::`
 
 error: expected one of `@` or `|`, found `:`
-  --> $DIR/issue-87086-colon-path-sep.rs:25:12
+  --> $DIR/issue-87086-colon-path-sep.rs:29:12
    |
-LL |         Foo:Bar::Baz => {}
+LL |         qux:Foo::Baz => {}
    |            ^
    |            |
    |            expected one of `@` or `|`
    |            help: maybe write a path separator here: `::`
 
 error: expected one of `@` or `|`, found `:`
-  --> $DIR/issue-87086-colon-path-sep.rs:31:12
+  --> $DIR/issue-87086-colon-path-sep.rs:35:12
    |
-LL |         Foo: Bar::Baz if true => {}
+LL |         qux: Foo::Baz if true => {}
    |            ^
    |            |
    |            expected one of `@` or `|`
    |            help: maybe write a path separator here: `::`
 
 error: expected one of `@` or `|`, found `:`
-  --> $DIR/issue-87086-colon-path-sep.rs:36:15
+  --> $DIR/issue-87086-colon-path-sep.rs:40:15
    |
-LL |     if let Bar:Baz = f() {
+LL |     if let Foo:Bar = f() {
    |               ^
    |               |
    |               expected one of `@` or `|`
    |               help: maybe write a path separator here: `::`
 
-error: expected one of `=>`, `@`, `if`, or `|`, found `:`
-  --> $DIR/issue-87086-colon-path-sep.rs:44:16
+error: expected one of `@` or `|`, found `:`
+  --> $DIR/issue-87086-colon-path-sep.rs:48:16
    |
-LL |         ref Foo: Bar::Baz => {}
-   |                ^ expected one of `=>`, `@`, `if`, or `|`
+LL |         ref qux: Foo::Baz => {}
+   |                ^
+   |                |
+   |                expected one of `@` or `|`
+   |                help: maybe write a path separator here: `::`
 
-error: expected one of `=>`, `@`, `if`, or `|`, found `:`
-  --> $DIR/issue-87086-colon-path-sep.rs:52:16
+error: expected one of `@` or `|`, found `:`
+  --> $DIR/issue-87086-colon-path-sep.rs:57:16
    |
-LL |         mut Foo: Bar::Baz => {}
-   |                ^ expected one of `=>`, `@`, `if`, or `|`
+LL |         mut qux: Foo::Baz => {}
+   |                ^
+   |                |
+   |                expected one of `@` or `|`
+   |                help: maybe write a path separator here: `::`
 
 error: expected one of `@` or `|`, found `:`
-  --> $DIR/issue-87086-colon-path-sep.rs:62:12
+  --> $DIR/issue-87086-colon-path-sep.rs:68:12
    |
 LL |         Foo:Bar::Baz => {}
    |            ^
@@ -64,5 +70,21 @@ LL |         Foo:Bar::Baz => {}
    |            expected one of `@` or `|`
    |            help: maybe write a path separator here: `::`
 
-error: aborting due to 8 previous errors
+error: expected one of `@` or `|`, found `:`
+  --> $DIR/issue-87086-colon-path-sep.rs:75:12
+   |
+LL |         Foo:Bar => {}
+   |            ^
+   |            |
+   |            expected one of `@` or `|`
+   |            help: maybe write a path separator here: `::`
+
+error[E0433]: failed to resolve: `Bar` is a variant, not a module
+  --> $DIR/issue-87086-colon-path-sep.rs:68:13
+   |
+LL |         Foo:Bar::Baz => {}
+   |             ^^^ `Bar` is a variant, not a module
+
+error: aborting due to 10 previous errors
 
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/parser/lex-bad-binary-literal.rs b/src/test/ui/parser/lex-bad-binary-literal.rs
deleted file mode 100644 (file)
index 7df9807..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-fn main() {
-    0b121; //~ ERROR invalid digit for a base 2 literal
-    0b10_10301; //~ ERROR invalid digit for a base 2 literal
-    0b30; //~ ERROR invalid digit for a base 2 literal
-    0b41; //~ ERROR invalid digit for a base 2 literal
-    0b5; //~ ERROR invalid digit for a base 2 literal
-    0b6; //~ ERROR invalid digit for a base 2 literal
-    0b7; //~ ERROR invalid digit for a base 2 literal
-    0b8; //~ ERROR invalid digit for a base 2 literal
-    0b9; //~ ERROR invalid digit for a base 2 literal
-}
diff --git a/src/test/ui/parser/lex-bad-binary-literal.stderr b/src/test/ui/parser/lex-bad-binary-literal.stderr
deleted file mode 100644 (file)
index 992b3d2..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-error: invalid digit for a base 2 literal
-  --> $DIR/lex-bad-binary-literal.rs:2:8
-   |
-LL |     0b121;
-   |        ^
-
-error: invalid digit for a base 2 literal
-  --> $DIR/lex-bad-binary-literal.rs:3:12
-   |
-LL |     0b10_10301;
-   |            ^
-
-error: invalid digit for a base 2 literal
-  --> $DIR/lex-bad-binary-literal.rs:4:7
-   |
-LL |     0b30;
-   |       ^
-
-error: invalid digit for a base 2 literal
-  --> $DIR/lex-bad-binary-literal.rs:5:7
-   |
-LL |     0b41;
-   |       ^
-
-error: invalid digit for a base 2 literal
-  --> $DIR/lex-bad-binary-literal.rs:6:7
-   |
-LL |     0b5;
-   |       ^
-
-error: invalid digit for a base 2 literal
-  --> $DIR/lex-bad-binary-literal.rs:7:7
-   |
-LL |     0b6;
-   |       ^
-
-error: invalid digit for a base 2 literal
-  --> $DIR/lex-bad-binary-literal.rs:8:7
-   |
-LL |     0b7;
-   |       ^
-
-error: invalid digit for a base 2 literal
-  --> $DIR/lex-bad-binary-literal.rs:9:7
-   |
-LL |     0b8;
-   |       ^
-
-error: invalid digit for a base 2 literal
-  --> $DIR/lex-bad-binary-literal.rs:10:7
-   |
-LL |     0b9;
-   |       ^
-
-error: aborting due to 9 previous errors
-
diff --git a/src/test/ui/parser/lex-bad-char-literals-1.rs b/src/test/ui/parser/lex-bad-char-literals-1.rs
deleted file mode 100644 (file)
index e7951cf..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-static c3: char =
-    '\x1' //~ ERROR: numeric character escape is too short
-;
-
-static s3: &'static str =
-    "\x1" //~ ERROR: numeric character escape is too short
-;
-
-static c: char =
-    '\●' //~ ERROR: unknown character escape
-;
-
-static s: &'static str =
-    "\●" //~ ERROR: unknown character escape
-;
-
-fn main() {}
diff --git a/src/test/ui/parser/lex-bad-char-literals-1.stderr b/src/test/ui/parser/lex-bad-char-literals-1.stderr
deleted file mode 100644 (file)
index ed129a1..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-error: numeric character escape is too short
-  --> $DIR/lex-bad-char-literals-1.rs:2:6
-   |
-LL |     '\x1'
-   |      ^^^
-
-error: numeric character escape is too short
-  --> $DIR/lex-bad-char-literals-1.rs:6:6
-   |
-LL |     "\x1"
-   |      ^^^
-
-error: unknown character escape: `\u{25cf}`
-  --> $DIR/lex-bad-char-literals-1.rs:10:7
-   |
-LL |     '\●'
-   |       ^ unknown character escape
-   |
-   = help: for more information, visit <https://static.rust-lang.org/doc/master/reference.html#literals>
-
-error: unknown character escape: `\u{25cf}`
-  --> $DIR/lex-bad-char-literals-1.rs:14:7
-   |
-LL |     "\●"
-   |       ^ unknown character escape
-   |
-   = help: for more information, visit <https://static.rust-lang.org/doc/master/reference.html#literals>
-
-error: aborting due to 4 previous errors
-
diff --git a/src/test/ui/parser/lex-bad-char-literals-2.rs b/src/test/ui/parser/lex-bad-char-literals-2.rs
deleted file mode 100644 (file)
index d35dafd..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// This test needs to the last one appearing in this file as it kills the parser
-static c: char =
-    'nope' //~ ERROR: character literal may only contain one codepoint
-;
-
-fn main() {}
diff --git a/src/test/ui/parser/lex-bad-char-literals-2.stderr b/src/test/ui/parser/lex-bad-char-literals-2.stderr
deleted file mode 100644 (file)
index c2b19a7..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error: character literal may only contain one codepoint
-  --> $DIR/lex-bad-char-literals-2.rs:3:5
-   |
-LL |     'nope'
-   |     ^^^^^^
-   |
-help: if you meant to write a `str` literal, use double quotes
-   |
-LL |     "nope"
-   |     ~~~~~~
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/parser/lex-bad-char-literals-3.rs b/src/test/ui/parser/lex-bad-char-literals-3.rs
deleted file mode 100644 (file)
index 5194ff4..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-static c: char = '●●';
-//~^ ERROR: character literal may only contain one codepoint
-
-fn main() {
-    let ch: &str = '●●';
-    //~^ ERROR: character literal may only contain one codepoint
-}
diff --git a/src/test/ui/parser/lex-bad-char-literals-3.stderr b/src/test/ui/parser/lex-bad-char-literals-3.stderr
deleted file mode 100644 (file)
index 62a5e42..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-error: character literal may only contain one codepoint
-  --> $DIR/lex-bad-char-literals-3.rs:1:18
-   |
-LL | static c: char = '●●';
-   |                  ^^^^
-   |
-help: if you meant to write a `str` literal, use double quotes
-   |
-LL | static c: char = "●●";
-   |                  ~~~~
-
-error: character literal may only contain one codepoint
-  --> $DIR/lex-bad-char-literals-3.rs:5:20
-   |
-LL |     let ch: &str = '●●';
-   |                    ^^^^
-   |
-help: if you meant to write a `str` literal, use double quotes
-   |
-LL |     let ch: &str = "●●";
-   |                    ~~~~
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/parser/lex-bad-char-literals-4.rs b/src/test/ui/parser/lex-bad-char-literals-4.rs
deleted file mode 100644 (file)
index de0a19d..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-//
-// This test needs to the last one appearing in this file as it kills the parser
-static c: char =
-    '●  //~ ERROR: unterminated character literal
-;
diff --git a/src/test/ui/parser/lex-bad-char-literals-4.stderr b/src/test/ui/parser/lex-bad-char-literals-4.stderr
deleted file mode 100644 (file)
index fec4421..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0762]: unterminated character literal
-  --> $DIR/lex-bad-char-literals-4.rs:4:5
-   |
-LL |     '●
-   |     ^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0762`.
diff --git a/src/test/ui/parser/lex-bad-char-literals-5.rs b/src/test/ui/parser/lex-bad-char-literals-5.rs
deleted file mode 100644 (file)
index 0c4339e..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-static c: char = '\x10\x10';
-//~^ ERROR: character literal may only contain one codepoint
-
-fn main() {
-    let ch: &str = '\x10\x10';
-    //~^ ERROR: character literal may only contain one codepoint
-}
diff --git a/src/test/ui/parser/lex-bad-char-literals-5.stderr b/src/test/ui/parser/lex-bad-char-literals-5.stderr
deleted file mode 100644 (file)
index 184817a..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-error: character literal may only contain one codepoint
-  --> $DIR/lex-bad-char-literals-5.rs:1:18
-   |
-LL | static c: char = '\x10\x10';
-   |                  ^^^^^^^^^^
-   |
-help: if you meant to write a `str` literal, use double quotes
-   |
-LL | static c: char = "\x10\x10";
-   |                  ~~~~~~~~~~
-
-error: character literal may only contain one codepoint
-  --> $DIR/lex-bad-char-literals-5.rs:5:20
-   |
-LL |     let ch: &str = '\x10\x10';
-   |                    ^^^^^^^^^^
-   |
-help: if you meant to write a `str` literal, use double quotes
-   |
-LL |     let ch: &str = "\x10\x10";
-   |                    ~~~~~~~~~~
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/parser/lex-bad-char-literals-6.rs b/src/test/ui/parser/lex-bad-char-literals-6.rs
deleted file mode 100644 (file)
index 4379b4f..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-fn main() {
-    let x: &str = 'ab';
-    //~^ ERROR: character literal may only contain one codepoint
-    let y: char = 'cd';
-    //~^ ERROR: character literal may only contain one codepoint
-    let z = 'ef';
-    //~^ ERROR: character literal may only contain one codepoint
-
-    if x == y {}
-    //~^ ERROR: can't compare `&str` with `char`
-    if y == z {}  // no error here
-    if x == z {}
-    //~^ ERROR: can't compare `&str` with `char`
-
-    let a: usize = "";
-    //~^ ERROR: mismatched types
-}
diff --git a/src/test/ui/parser/lex-bad-char-literals-6.stderr b/src/test/ui/parser/lex-bad-char-literals-6.stderr
deleted file mode 100644 (file)
index 4332bde..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-error: character literal may only contain one codepoint
-  --> $DIR/lex-bad-char-literals-6.rs:2:19
-   |
-LL |     let x: &str = 'ab';
-   |                   ^^^^
-   |
-help: if you meant to write a `str` literal, use double quotes
-   |
-LL |     let x: &str = "ab";
-   |                   ~~~~
-
-error: character literal may only contain one codepoint
-  --> $DIR/lex-bad-char-literals-6.rs:4:19
-   |
-LL |     let y: char = 'cd';
-   |                   ^^^^
-   |
-help: if you meant to write a `str` literal, use double quotes
-   |
-LL |     let y: char = "cd";
-   |                   ~~~~
-
-error: character literal may only contain one codepoint
-  --> $DIR/lex-bad-char-literals-6.rs:6:13
-   |
-LL |     let z = 'ef';
-   |             ^^^^
-   |
-help: if you meant to write a `str` literal, use double quotes
-   |
-LL |     let z = "ef";
-   |             ~~~~
-
-error[E0277]: can't compare `&str` with `char`
-  --> $DIR/lex-bad-char-literals-6.rs:9:10
-   |
-LL |     if x == y {}
-   |          ^^ no implementation for `&str == char`
-   |
-   = help: the trait `PartialEq<char>` is not implemented for `&str`
-
-error[E0308]: mismatched types
-  --> $DIR/lex-bad-char-literals-6.rs:15:20
-   |
-LL |     let a: usize = "";
-   |            -----   ^^ expected `usize`, found `&str`
-   |            |
-   |            expected due to this
-
-error[E0277]: can't compare `&str` with `char`
-  --> $DIR/lex-bad-char-literals-6.rs:12:10
-   |
-LL |     if x == z {}
-   |          ^^ no implementation for `&str == char`
-   |
-   = help: the trait `PartialEq<char>` is not implemented for `&str`
-
-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/parser/lex-bad-char-literals-7.rs b/src/test/ui/parser/lex-bad-char-literals-7.rs
deleted file mode 100644 (file)
index c675df2..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-fn main() {
-    let _: char = '';
-    //~^ ERROR: empty character literal
-    let _: char = '\u{}';
-    //~^ ERROR: empty unicode escape
-
-    // Next two are OK, but may befool error recovery
-    let _ = '/';
-    let _ = b'/';
-
-    let _ = ' hello // here's a comment
-    //~^ ERROR: unterminated character literal
-}
diff --git a/src/test/ui/parser/lex-bad-char-literals-7.stderr b/src/test/ui/parser/lex-bad-char-literals-7.stderr
deleted file mode 100644 (file)
index 255b9c6..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error: empty character literal
-  --> $DIR/lex-bad-char-literals-7.rs:2:20
-   |
-LL |     let _: char = '';
-   |                    ^ empty character literal
-
-error: empty unicode escape
-  --> $DIR/lex-bad-char-literals-7.rs:4:20
-   |
-LL |     let _: char = '\u{}';
-   |                    ^^^^ this escape must have at least 1 hex digit
-
-error[E0762]: unterminated character literal
-  --> $DIR/lex-bad-char-literals-7.rs:11:13
-   |
-LL |     let _ = ' hello // here's a comment
-   |             ^^^^^^^^
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0762`.
diff --git a/src/test/ui/parser/lex-bad-numeric-literals.rs b/src/test/ui/parser/lex-bad-numeric-literals.rs
deleted file mode 100644 (file)
index cf8440c..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-fn main() {
-    0o1.0; //~ ERROR: octal float literal is not supported
-    0o2f32; //~ ERROR: octal float literal is not supported
-    0o3.0f32; //~ ERROR: octal float literal is not supported
-    0o4e4; //~ ERROR: octal float literal is not supported
-    0o5.0e5; //~ ERROR: octal float literal is not supported
-    0o6e6f32; //~ ERROR: octal float literal is not supported
-    0o7.0e7f64; //~ ERROR: octal float literal is not supported
-    0x8.0e+9; //~ ERROR: hexadecimal float literal is not supported
-    0x9.0e-9; //~ ERROR: hexadecimal float literal is not supported
-    0o; //~ ERROR: no valid digits
-    1e+; //~ ERROR: expected at least one digit in exponent
-    0x539.0; //~ ERROR: hexadecimal float literal is not supported
-    9900000000000000000000000000999999999999999999999999999999;
-    //~^ ERROR: integer literal is too large
-    9900000000000000000000000000999999999999999999999999999999;
-    //~^ ERROR: integer literal is too large
-    0x; //~ ERROR: no valid digits
-    0xu32; //~ ERROR: no valid digits
-    0ou32; //~ ERROR: no valid digits
-    0bu32; //~ ERROR: no valid digits
-    0b; //~ ERROR: no valid digits
-    0o123f64; //~ ERROR: octal float literal is not supported
-    0o123.456; //~ ERROR: octal float literal is not supported
-    0b101f64; //~ ERROR: binary float literal is not supported
-    0b111.101; //~ ERROR: binary float literal is not supported
-}
diff --git a/src/test/ui/parser/lex-bad-numeric-literals.stderr b/src/test/ui/parser/lex-bad-numeric-literals.stderr
deleted file mode 100644 (file)
index f05d616..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:2:5
-   |
-LL |     0o1.0;
-   |     ^^^^^
-
-error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:4:5
-   |
-LL |     0o3.0f32;
-   |     ^^^^^
-
-error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:5:5
-   |
-LL |     0o4e4;
-   |     ^^^^^
-
-error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:6:5
-   |
-LL |     0o5.0e5;
-   |     ^^^^^^^
-
-error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:7:5
-   |
-LL |     0o6e6f32;
-   |     ^^^^^
-
-error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:8:5
-   |
-LL |     0o7.0e7f64;
-   |     ^^^^^^^
-
-error: hexadecimal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:9:5
-   |
-LL |     0x8.0e+9;
-   |     ^^^^^^^^
-
-error: hexadecimal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:10:5
-   |
-LL |     0x9.0e-9;
-   |     ^^^^^^^^
-
-error[E0768]: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:11:5
-   |
-LL |     0o;
-   |     ^^
-
-error: expected at least one digit in exponent
-  --> $DIR/lex-bad-numeric-literals.rs:12:5
-   |
-LL |     1e+;
-   |     ^^^
-
-error: hexadecimal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:13:5
-   |
-LL |     0x539.0;
-   |     ^^^^^^^
-
-error[E0768]: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:18:5
-   |
-LL |     0x;
-   |     ^^
-
-error[E0768]: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:19:5
-   |
-LL |     0xu32;
-   |     ^^
-
-error[E0768]: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:20:5
-   |
-LL |     0ou32;
-   |     ^^
-
-error[E0768]: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:21:5
-   |
-LL |     0bu32;
-   |     ^^
-
-error[E0768]: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:22:5
-   |
-LL |     0b;
-   |     ^^
-
-error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:24:5
-   |
-LL |     0o123.456;
-   |     ^^^^^^^^^
-
-error: binary float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:26:5
-   |
-LL |     0b111.101;
-   |     ^^^^^^^^^
-
-error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:3:5
-   |
-LL |     0o2f32;
-   |     ^^^^^^ not supported
-
-error: integer literal is too large
-  --> $DIR/lex-bad-numeric-literals.rs:14:5
-   |
-LL |     9900000000000000000000000000999999999999999999999999999999;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: integer literal is too large
-  --> $DIR/lex-bad-numeric-literals.rs:16:5
-   |
-LL |     9900000000000000000000000000999999999999999999999999999999;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:23:5
-   |
-LL |     0o123f64;
-   |     ^^^^^^^^ not supported
-
-error: binary float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:25:5
-   |
-LL |     0b101f64;
-   |     ^^^^^^^^ not supported
-
-error: aborting due to 23 previous errors
-
-For more information about this error, try `rustc --explain E0768`.
diff --git a/src/test/ui/parser/lex-bad-octal-literal.rs b/src/test/ui/parser/lex-bad-octal-literal.rs
deleted file mode 100644 (file)
index 49631f1..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-fn main() {
-    0o18; //~ ERROR invalid digit for a base 8 literal
-    0o1234_9_5670;  //~ ERROR invalid digit for a base 8 literal
-}
diff --git a/src/test/ui/parser/lex-bad-octal-literal.stderr b/src/test/ui/parser/lex-bad-octal-literal.stderr
deleted file mode 100644 (file)
index 2cb8ca5..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: invalid digit for a base 8 literal
-  --> $DIR/lex-bad-octal-literal.rs:2:8
-   |
-LL |     0o18;
-   |        ^
-
-error: invalid digit for a base 8 literal
-  --> $DIR/lex-bad-octal-literal.rs:3:12
-   |
-LL |     0o1234_9_5670;
-   |            ^
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/parser/lex-bad-token.rs b/src/test/ui/parser/lex-bad-token.rs
deleted file mode 100644 (file)
index 9e48246..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-● //~ ERROR: unknown start of token
-
-fn main() {}
diff --git a/src/test/ui/parser/lex-bad-token.stderr b/src/test/ui/parser/lex-bad-token.stderr
deleted file mode 100644 (file)
index 43c4372..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: unknown start of token: \u{25cf}
-  --> $DIR/lex-bad-token.rs:1:1
-   |
-LL | ●
-   | ^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/parser/lex-bare-cr-nondoc-comment.rs b/src/test/ui/parser/lex-bare-cr-nondoc-comment.rs
deleted file mode 100644 (file)
index 5b528d6..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// run-pass
-// ignore-tidy-cr
-
-// nondoc comment with bare CR: '\r'
-//// nondoc comment with bare CR: '\r'
-/* block nondoc comment with bare CR: '\r' */
-
-fn main() {
-}
diff --git a/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.rs b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.rs
deleted file mode 100644 (file)
index b7752e1..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// ignore-tidy-cr
-
-/// doc comment with bare CR: '\r'
-pub fn foo() {}
-//~^^ ERROR: bare CR not allowed in doc-comment
-
-/** block doc comment with bare CR: '\r' */
-pub fn bar() {}
-//~^^ ERROR: bare CR not allowed in block doc-comment
-
-fn main() {
-    //! doc comment with bare CR: '\r'
-    //~^ ERROR: bare CR not allowed in doc-comment
-
-    /*! block doc comment with bare CR: '\r' */
-    //~^ ERROR: bare CR not allowed in block doc-comment
-
-    // the following string literal has a bare CR in it
-    let _s = "foo\rbar"; //~ ERROR: bare CR not allowed in string
-
-    // the following string literal has a bare CR in it
-    let _s = r"bar\rfoo"; //~ ERROR: bare CR not allowed in raw string
-
-    // the following string literal has a bare CR in it
-    let _s = "foo\\rbar"; //~ ERROR: unknown character escape: `\r`
-}
diff --git a/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr
deleted file mode 100644 (file)
index 1a21fed..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-error: bare CR not allowed in doc-comment
-  --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:3:32
-   |
-LL | /// doc comment with bare CR: '\r'
-   |                                ^
-
-error: bare CR not allowed in block doc-comment
-  --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:7:38
-   |
-LL | /** block doc comment with bare CR: '\r' */
-   |                                      ^
-
-error: bare CR not allowed in doc-comment
-  --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:12:36
-   |
-LL |     //! doc comment with bare CR: '\r'
-   |                                    ^
-
-error: bare CR not allowed in block doc-comment
-  --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:15:42
-   |
-LL |     /*! block doc comment with bare CR: '\r' */
-   |                                          ^
-
-error: bare CR not allowed in string, use `\r` instead
-  --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:19:18
-   |
-LL |     let _s = "foo\rbar";
-   |                  ^ help: escape the character: `\r`
-
-error: bare CR not allowed in raw string
-  --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:22:19
-   |
-LL |     let _s = r"bar\rfoo";
-   |                   ^
-
-error: unknown character escape: `\r`
-  --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:25:19
-   |
-LL |     let _s = "foo\\rbar";
-   |                   ^ unknown character escape
-   |
-   = help: this is an isolated carriage return; consider checking your editor and version control settings
-
-error: aborting due to 7 previous errors
-
diff --git a/src/test/ui/parser/lex-stray-backslash.rs b/src/test/ui/parser/lex-stray-backslash.rs
deleted file mode 100644 (file)
index bb27f44..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-\ //~ ERROR: unknown start of token: \
-
-fn main() {}
diff --git a/src/test/ui/parser/lex-stray-backslash.stderr b/src/test/ui/parser/lex-stray-backslash.stderr
deleted file mode 100644 (file)
index 06dc0f2..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: unknown start of token: \
-  --> $DIR/lex-stray-backslash.rs:1:1
-   |
-LL | \
-   | ^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/parser/lexer-crlf-line-endings-string-literal-doc-comment.rs b/src/test/ui/parser/lexer-crlf-line-endings-string-literal-doc-comment.rs
deleted file mode 100644 (file)
index 802be7f..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-// run-pass\r
-// ignore-tidy-cr\r
-// ignore-tidy-cr (repeated again because of tidy bug)\r
-// license is ignored because tidy can't handle the CRLF here properly.\r
-\r
-// N.B., this file needs CRLF line endings. The .gitattributes file in\r
-// this directory should enforce it.\r
-\r
-// ignore-pretty issue #37195\r
-\r
-/// Doc comment that ends in CRLF\r
-pub fn foo() {}\r
-\r
-/** Block doc comment that\r
- *  contains CRLF characters\r
- */\r
-pub fn bar() {}\r
-\r
-fn main() {\r
-    let s = "string\r
-literal";\r
-    assert_eq!(s, "string\nliteral");\r
-\r
-    let s = "literal with \\r
-             escaped newline";\r
-    assert_eq!(s, "literal with escaped newline");\r
-\r
-    let s = r"string\r
-literal";\r
-    assert_eq!(s, "string\nliteral");\r
-    let s = br"byte string\r
-literal";\r
-    assert_eq!(s, "byte string\nliteral".as_bytes());\r
-\r
-    // validate that our source file has CRLF endings\r
-    let source = include_str!("lexer-crlf-line-endings-string-literal-doc-comment.rs");\r
-    assert!(source.contains("string\r\nliteral"));\r
-}\r
index 91fed81eaeff6927e99aada93a1603a4ade43b93..31168e29eb82fc583e800d035bd4e2d329c527ed 100644 (file)
@@ -4,7 +4,7 @@ error: `[closure@$DIR/non-structural-match-types.rs:9:17: 9:22]` cannot be used
 LL |         const { || {} } => {},
    |         ^^^^^^^^^^^^^^^
 
-error: `impl Future` cannot be used in patterns
+error: `impl Future<Output = [async output]>` cannot be used in patterns
   --> $DIR/non-structural-match-types.rs:12:9
    |
 LL |         const { async {} } => {},
diff --git a/src/test/ui/pattern/usefulness/issue-88747.rs b/src/test/ui/pattern/usefulness/issue-88747.rs
new file mode 100644 (file)
index 0000000..948c99f
--- /dev/null
@@ -0,0 +1,14 @@
+// check-pass: this used to be a stack overflow because of recursion in `usefulness.rs`
+
+macro_rules! long_tuple_arg {
+    ([$($t:tt)*]#$($h:tt)*) => {
+        long_tuple_arg!{[$($t)*$($t)*]$($h)*}
+    };
+    ([$([$t:tt $y:tt])*]) => {
+        pub fn _f(($($t,)*): ($($y,)*)) {}
+    }
+}
+
+long_tuple_arg!{[[_ u8]]########## ###}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/crate-attrs-multiple.rs b/src/test/ui/proc-macro/crate-attrs-multiple.rs
new file mode 100644 (file)
index 0000000..29a0eca
--- /dev/null
@@ -0,0 +1,14 @@
+// Multiple custom crate-level attributes, both inert and active.
+
+// check-pass
+// aux-crate:test_macros=test-macros.rs
+
+#![feature(custom_inner_attributes)]
+#![feature(prelude_import)]
+
+#![test_macros::identity_attr]
+#![rustfmt::skip]
+#![test_macros::identity_attr]
+#![rustfmt::skip]
+
+fn main() {}
index 039878af56eb651dfd3967bd4ffe8ae06d73b13f..a4161d4fc3dcc8625bf7788ecff9c2134ed6a72b 100644 (file)
@@ -1,7 +1,10 @@
-// edition:2018
-// aux-crate:issue_59191=issue-59191.rs
 // Test that using a macro to replace the entire crate tree with a non-'mod' item errors out nicely.
 // `issue_59191::no_main` replaces whatever's passed in with `fn main() {}`.
+
+// edition:2018
+// aux-crate:issue_59191=issue-59191.rs
+// error-pattern: requires `sized` lang_item
+
 #![feature(custom_inner_attributes)]
 #![issue_59191::no_main]
-//~^ ERROR expected crate top-level item to be a module after macro expansion, found a function
+#![issue_59191::no_main]
index 126c52db548f7db96dad562bd76a6b6bd8c964d9..f7516c7d377dab1ff50429237150044408aa9e26 100644 (file)
@@ -1,10 +1,4 @@
-error: expected crate top-level item to be a module after macro expansion, found a function
-  --> $DIR/issue-59191-replace-root-with-fn.rs:6:1
-   |
-LL | #![issue_59191::no_main]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: this error originates in the attribute macro `issue_59191::no_main` (in Nightly builds, run with -Z macro-backtrace for more info)
+error: requires `sized` lang_item
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.nll.stderr b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.nll.stderr
deleted file mode 100644 (file)
index 9bb385b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error: lifetime may not live long enough
-  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:39:12
-   |
-LL | fn with_assoc<'a,'b>() {
-   |               -- -- lifetime `'b` defined here
-   |               |
-   |               lifetime `'a` defined here
-...
-LL |     let _: &'a WithAssoc<TheType<'b>> = loop { };
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
-   |
-   = help: consider adding the following bound: `'b: 'a`
-
-error: aborting due to previous error
-
index 6ae70ec672ce1210b4371b7e3fd9f7e92cdd2c56..d9fd1aebf277d719cce674760eaa55991154a72d 100644 (file)
@@ -1,16 +1,16 @@
 error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
-  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:39:12
+  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:44:12
    |
 LL |     let _: &'a WithAssoc<TheType<'b>> = loop { };
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the pointer is valid for the lifetime `'a` as defined here
-  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:33:15
+  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:38:15
    |
 LL | fn with_assoc<'a,'b>() {
    |               ^^
 note: but the referenced data is only valid for the lifetime `'b` as defined here
-  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:33:18
+  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:38:18
    |
 LL | fn with_assoc<'a,'b>() {
    |                  ^^
index 9bb385b0dcdc8e0c0801f5b9003619c2450cad20..ba7572ebe31377ea9302d72836efb2fa9f337a47 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:39:12
+  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:44:12
    |
 LL | fn with_assoc<'a,'b>() {
    |               -- -- lifetime `'b` defined here
index 046d010002e6e7a9ad26f0fbb04e8ee53ab67fd8..08bc64926fac365247fa73e9b3a78064c3f1f009 100644 (file)
@@ -6,6 +6,11 @@
 // revisions: migrate nll
 //[nll]compile-flags: -Z borrowck=mir
 
+// Since we are testing nll (and migration) explicitly as a separate
+// revisions, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
 #![allow(dead_code)]
 
 pub trait TheTrait {
diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.migrate.nll.stderr b/src/test/ui/regions/regions-free-region-ordering-caller.migrate.nll.stderr
deleted file mode 100644 (file)
index 0d4694a..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-error: lifetime may not live long enough
-  --> $DIR/regions-free-region-ordering-caller.rs:11:12
-   |
-LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
-   |          --  -- lifetime `'b` defined here
-   |          |
-   |          lifetime `'a` defined here
-LL |     let z: Option<&'b &'a usize> = None;
-   |            ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
-   |
-   = help: consider adding the following bound: `'a: 'b`
-
-error: lifetime may not live long enough
-  --> $DIR/regions-free-region-ordering-caller.rs:17:12
-   |
-LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
-   |          --  -- lifetime `'b` defined here
-   |          |
-   |          lifetime `'a` defined here
-LL |     let y: Paramd<'a> = Paramd { x: a };
-LL |     let z: Option<&'b Paramd<'a>> = None;
-   |            ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
-   |
-   = help: consider adding the following bound: `'a: 'b`
-
-error: lifetime may not live long enough
-  --> $DIR/regions-free-region-ordering-caller.rs:22:12
-   |
-LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
-   |          --  -- lifetime `'b` defined here
-   |          |
-   |          lifetime `'a` defined here
-LL |     let z: Option<&'a &'b usize> = None;
-   |            ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
-   |
-   = help: consider adding the following bound: `'b: 'a`
-
-error: aborting due to 3 previous errors
-
index c0f3b24f68cfec2f6d55fa7223896f13b7b500cc..a27a010d7f302346ff76cb066406ac0f7197708e 100644 (file)
@@ -1,50 +1,50 @@
 error[E0491]: in type `&'b &'a usize`, reference has a longer lifetime than the data it references
-  --> $DIR/regions-free-region-ordering-caller.rs:11:12
+  --> $DIR/regions-free-region-ordering-caller.rs:16:12
    |
 LL |     let z: Option<&'b &'a usize> = None;
    |            ^^^^^^^^^^^^^^^^^^^^^
    |
 note: the pointer is valid for the lifetime `'b` as defined here
-  --> $DIR/regions-free-region-ordering-caller.rs:10:14
+  --> $DIR/regions-free-region-ordering-caller.rs:15:14
    |
 LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
    |              ^^
 note: but the referenced data is only valid for the lifetime `'a` as defined here
-  --> $DIR/regions-free-region-ordering-caller.rs:10:10
+  --> $DIR/regions-free-region-ordering-caller.rs:15:10
    |
 LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
    |          ^^
 
 error[E0491]: in type `&'b Paramd<'a>`, reference has a longer lifetime than the data it references
-  --> $DIR/regions-free-region-ordering-caller.rs:17:12
+  --> $DIR/regions-free-region-ordering-caller.rs:22:12
    |
 LL |     let z: Option<&'b Paramd<'a>> = None;
    |            ^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the pointer is valid for the lifetime `'b` as defined here
-  --> $DIR/regions-free-region-ordering-caller.rs:15:14
+  --> $DIR/regions-free-region-ordering-caller.rs:20:14
    |
 LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
    |              ^^
 note: but the referenced data is only valid for the lifetime `'a` as defined here
-  --> $DIR/regions-free-region-ordering-caller.rs:15:10
+  --> $DIR/regions-free-region-ordering-caller.rs:20:10
    |
 LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
    |          ^^
 
 error[E0491]: in type `&'a &'b usize`, reference has a longer lifetime than the data it references
-  --> $DIR/regions-free-region-ordering-caller.rs:22:12
+  --> $DIR/regions-free-region-ordering-caller.rs:27:12
    |
 LL |     let z: Option<&'a &'b usize> = None;
    |            ^^^^^^^^^^^^^^^^^^^^^
    |
 note: the pointer is valid for the lifetime `'a` as defined here
-  --> $DIR/regions-free-region-ordering-caller.rs:21:10
+  --> $DIR/regions-free-region-ordering-caller.rs:26:10
    |
 LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
    |          ^^
 note: but the referenced data is only valid for the lifetime `'b` as defined here
-  --> $DIR/regions-free-region-ordering-caller.rs:21:14
+  --> $DIR/regions-free-region-ordering-caller.rs:26:14
    |
 LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
    |              ^^
index 0d4694a64d087c7f7502b550ef7f043ba1bacd81..546eb93d8ecab9a7f45f018dcca3de8751a85b28 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/regions-free-region-ordering-caller.rs:11:12
+  --> $DIR/regions-free-region-ordering-caller.rs:16:12
    |
 LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
    |          --  -- lifetime `'b` defined here
@@ -11,7 +11,7 @@ LL |     let z: Option<&'b &'a usize> = None;
    = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
-  --> $DIR/regions-free-region-ordering-caller.rs:17:12
+  --> $DIR/regions-free-region-ordering-caller.rs:22:12
    |
 LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
    |          --  -- lifetime `'b` defined here
@@ -24,7 +24,7 @@ LL |     let z: Option<&'b Paramd<'a>> = None;
    = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
-  --> $DIR/regions-free-region-ordering-caller.rs:22:12
+  --> $DIR/regions-free-region-ordering-caller.rs:27:12
    |
 LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
    |          --  -- lifetime `'b` defined here
index 2bf4734cf73802137006e1cd64f2865447231f85..11997a5fb56a5c3659da35785af282d549d6e4f4 100644 (file)
@@ -5,6 +5,11 @@
 // revisions: migrate nll
 //[nll]compile-flags: -Z borrowck=mir
 
+// Since we are testing nll (and migration) explicitly as a separate
+// revisions, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
 struct Paramd<'a> { x: &'a usize }
 
 fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr
deleted file mode 100644 (file)
index 29e92f3..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-error: lifetime may not live long enough
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:30:12
-   |
-LL | fn with_assoc<'a,'b>() {
-   |               -- -- lifetime `'b` defined here
-   |               |
-   |               lifetime `'a` defined here
-...
-LL |     let _: &'a WithHrAssoc<TheType<'b>> = loop { };
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
-   |
-   = help: consider adding the following bound: `'b: 'a`
-
-error: lifetime may not live long enough
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:50:12
-   |
-LL | fn with_assoc_sub<'a,'b>() {
-   |                   -- -- lifetime `'b` defined here
-   |                   |
-   |                   lifetime `'a` defined here
-...
-LL |     let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
-   |
-   = help: consider adding the following bound: `'b: 'a`
-
-error: aborting due to 2 previous errors
-
index 60c115b3f5939e2c5b61f37586457d7953973f3b..f2308bb7c78b1e140b34eb2080484eb37a270256 100644 (file)
@@ -1,33 +1,33 @@
 error[E0491]: in type `&'a WithHrAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:30:12
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:35:12
    |
 LL |     let _: &'a WithHrAssoc<TheType<'b>> = loop { };
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the pointer is valid for the lifetime `'a` as defined here
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:27:15
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:32:15
    |
 LL | fn with_assoc<'a,'b>() {
    |               ^^
 note: but the referenced data is only valid for the lifetime `'b` as defined here
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:27:18
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:32:18
    |
 LL | fn with_assoc<'a,'b>() {
    |                  ^^
 
 error[E0491]: in type `&'a WithHrAssocSub<TheType<'b>>`, reference has a longer lifetime than the data it references
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:50:12
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:55:12
    |
 LL |     let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the pointer is valid for the lifetime `'a` as defined here
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:46:19
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:51:19
    |
 LL | fn with_assoc_sub<'a,'b>() {
    |                   ^^
 note: but the referenced data is only valid for the lifetime `'b` as defined here
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:46:22
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:51:22
    |
 LL | fn with_assoc_sub<'a,'b>() {
    |                      ^^
index 29e92f33ec9148a97bc12a522b49883726195c17..472323772c1a50a0e68adb29d06120b28aac045a 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:30:12
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:35:12
    |
 LL | fn with_assoc<'a,'b>() {
    |               -- -- lifetime `'b` defined here
@@ -12,7 +12,7 @@ LL |     let _: &'a WithHrAssoc<TheType<'b>> = loop { };
    = help: consider adding the following bound: `'b: 'a`
 
 error: lifetime may not live long enough
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:50:12
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:55:12
    |
 LL | fn with_assoc_sub<'a,'b>() {
    |                   -- -- lifetime `'b` defined here
index cee741184ca2ab68a0ddb8b35bf7864274b13533..695a81dca27c84925390f361575fc3ab1bd773e3 100644 (file)
@@ -4,6 +4,11 @@
 // revisions: migrate nll
 //[nll]compile-flags: -Z borrowck=mir
 
+// Since we are testing nll (and migration) explicitly as a separate
+// revisions, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
 #![allow(dead_code)]
 
 pub trait TheTrait<'b> {
diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr
deleted file mode 100644 (file)
index 7035144..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error: lifetime may not live long enough
-  --> $DIR/regions-outlives-projection-container-wc.rs:33:12
-   |
-LL | fn with_assoc<'a,'b>() {
-   |               -- -- lifetime `'b` defined here
-   |               |
-   |               lifetime `'a` defined here
-...
-LL |     let _: &'a WithAssoc<TheType<'b>> = loop { };
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
-   |
-   = help: consider adding the following bound: `'b: 'a`
-
-error: aborting due to previous error
-
index 8430b69f998326f36e2b9177f7aa5539329a2f98..bda2896fca4ac9b3bb831986f4e9494c630bd2b6 100644 (file)
@@ -1,16 +1,16 @@
 error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
-  --> $DIR/regions-outlives-projection-container-wc.rs:33:12
+  --> $DIR/regions-outlives-projection-container-wc.rs:38:12
    |
 LL |     let _: &'a WithAssoc<TheType<'b>> = loop { };
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the pointer is valid for the lifetime `'a` as defined here
-  --> $DIR/regions-outlives-projection-container-wc.rs:27:15
+  --> $DIR/regions-outlives-projection-container-wc.rs:32:15
    |
 LL | fn with_assoc<'a,'b>() {
    |               ^^
 note: but the referenced data is only valid for the lifetime `'b` as defined here
-  --> $DIR/regions-outlives-projection-container-wc.rs:27:18
+  --> $DIR/regions-outlives-projection-container-wc.rs:32:18
    |
 LL | fn with_assoc<'a,'b>() {
    |                  ^^
index 7035144302479f4a0578aa074b6d1d4607f78bca..fc32a72d508963db013d438d3df048b49ae6be1b 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/regions-outlives-projection-container-wc.rs:33:12
+  --> $DIR/regions-outlives-projection-container-wc.rs:38:12
    |
 LL | fn with_assoc<'a,'b>() {
    |               -- -- lifetime `'b` defined here
index 99965f333907bff77772640989900ecc090fc93d..c9b714cffb6e4528cc0bf1f8a7050fd61c98cd95 100644 (file)
@@ -6,6 +6,11 @@
 // revisions: migrate nll
 //[nll]compile-flags: -Z borrowck=mir
 
+// Since we are testing nll (and migration) explicitly as a separate
+// revisions, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
 #![allow(dead_code)]
 
 pub trait TheTrait {
index 0098f087d10f8dcf469d7d45683beb8683c871dd..cb2b585ab96a8cd7680b5b006228e1cee1936a09 100644 (file)
@@ -30,3 +30,15 @@ pub enum VariantNonExhaustive {
 pub enum NonExhaustiveSingleVariant {
     A(bool),
 }
+
+#[repr(u8)]
+pub enum FieldLessWithNonExhaustiveVariant {
+    A,
+    B,
+    #[non_exhaustive]
+    C,
+}
+
+impl Default for FieldLessWithNonExhaustiveVariant {
+    fn default() -> Self { Self::A }
+}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.rs b/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.rs
new file mode 100644 (file)
index 0000000..d9657ba
--- /dev/null
@@ -0,0 +1,17 @@
+// aux-build:enums.rs
+// run-pass
+
+extern crate enums;
+
+use enums::FieldLessWithNonExhaustiveVariant;
+
+fn main() {
+    let e = FieldLessWithNonExhaustiveVariant::default();
+    // FIXME: https://github.com/rust-lang/rust/issues/91161
+    // This `as` cast *should* be an error, since it would fail
+    // if the non-exhaustive variant got fields.  But today it
+    // doesn't.  The fix for that will update this test to
+    // show an error (and not be run-pass any more).
+    let d = e as u8;
+    assert_eq!(d, 0);
+}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs
new file mode 100644 (file)
index 0000000..83fa32b
--- /dev/null
@@ -0,0 +1,20 @@
+// check-pass
+
+#![feature(const_trait_impl)]
+#![feature(const_fn_trait_bound)]
+#![feature(const_precise_live_drops)]
+
+const fn foo<T, E>(res: Result<T, E>) -> Option<T> where E: ~const Drop {
+    match res {
+        Ok(t) => Some(t),
+        Err(_e) => None,
+    }
+}
+
+pub struct Foo<T>(T);
+
+const fn baz<T: ~const Drop, E: ~const Drop>(res: Result<Foo<T>, Foo<E>>) -> Option<Foo<T>> {
+    foo(res)
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs
new file mode 100644 (file)
index 0000000..cbfdf89
--- /dev/null
@@ -0,0 +1,51 @@
+// check-pass
+
+#![feature(staged_api)]
+#![feature(const_trait_impl)]
+#![feature(const_fn_trait_bound)]
+#![feature(const_t_try)]
+#![feature(const_try)]
+#![feature(try_trait_v2)]
+
+#![stable(feature = "foo", since = "1.0")]
+
+use std::ops::{ControlFlow, FromResidual, Try};
+
+#[stable(feature = "foo", since = "1.0")]
+pub struct T;
+
+#[stable(feature = "foo", since = "1.0")]
+#[rustc_const_unstable(feature = "const_t_try", issue = "none")]
+impl const Try for T {
+    type Output = T;
+    type Residual = T;
+
+    fn from_output(t: T) -> T {
+        t
+    }
+
+    fn branch(self) -> ControlFlow<T, T> {
+        ControlFlow::Continue(self)
+    }
+}
+
+#[stable(feature = "foo", since = "1.0")]
+#[rustc_const_unstable(feature = "const_t_try", issue = "none")]
+impl const FromResidual for T {
+    fn from_residual(t: T) -> T {
+        t
+    }
+}
+
+#[stable(feature = "foo", since = "1.0")]
+pub trait Tr {
+    #[default_method_body_is_const]
+    #[stable(feature = "foo", since = "1.0")]
+    fn bar() -> T {
+        T?
+        // Should be allowed.
+        // Must enable unstable features to call this trait fn in const contexts.
+    }
+}
+
+fn main() {}
index 7f15c1c1f57703473063f94fe6dfabd02498192f..86513b6064d2df50f0af1a961afea91cab6fb4bd 100644 (file)
@@ -1,26 +1,5 @@
-error[E0277]: `dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Foo<'b>` cannot be shared between threads safely
-  --> $DIR/rfc1623.rs:21:1
-   |
-LL | / static SOME_STRUCT: &SomeStruct = &SomeStruct {
-LL | |     foo: &Foo { bools: &[false, true] },
-LL | |     bar: &Bar { bools: &[true, true] },
-LL | |     f: &id,
-LL | |
-LL | | };
-   | |__^ `dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Foo<'b>` cannot be shared between threads safely
-   |
-   = help: within `&SomeStruct`, the trait `Sync` is not implemented for `dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Foo<'b>`
-   = note: required because it appears within the type `&dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Foo<'b>`
-note: required because it appears within the type `SomeStruct`
-  --> $DIR/rfc1623.rs:11:8
-   |
-LL | struct SomeStruct<'x, 'y, 'z: 'x> {
-   |        ^^^^^^^^^^
-   = note: required because it appears within the type `&SomeStruct`
-   = note: shared static variables must have a type that implements `Sync`
-
 error[E0308]: mismatched types
-  --> $DIR/rfc1623.rs:21:35
+  --> $DIR/rfc1623.rs:25:35
    |
 LL |   static SOME_STRUCT: &SomeStruct = &SomeStruct {
    |  ___________________________________^
@@ -35,7 +14,7 @@ LL | | };
               found type `Fn<(&Foo<'_>,)>`
 
 error[E0308]: mismatched types
-  --> $DIR/rfc1623.rs:21:35
+  --> $DIR/rfc1623.rs:25:35
    |
 LL |   static SOME_STRUCT: &SomeStruct = &SomeStruct {
    |  ___________________________________^
@@ -50,7 +29,7 @@ LL | | };
               found type `Fn<(&Foo<'_>,)>`
 
 error: implementation of `FnOnce` is not general enough
-  --> $DIR/rfc1623.rs:21:35
+  --> $DIR/rfc1623.rs:25:35
    |
 LL |   static SOME_STRUCT: &SomeStruct = &SomeStruct {
    |  ___________________________________^
@@ -65,7 +44,7 @@ LL | | };
    = note: ...but it actually implements `FnOnce<(&'2 Foo<'_>,)>`, for some specific lifetime `'2`
 
 error: implementation of `FnOnce` is not general enough
-  --> $DIR/rfc1623.rs:21:35
+  --> $DIR/rfc1623.rs:25:35
    |
 LL |   static SOME_STRUCT: &SomeStruct = &SomeStruct {
    |  ___________________________________^
@@ -79,7 +58,6 @@ LL | | };
    = note: `fn(&Foo<'2>) -> &Foo<'2> {id::<&Foo<'2>>}` must implement `FnOnce<(&'a Foo<'1>,)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&Foo<'2>,)>`, for some specific lifetime `'2`
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0277, E0308.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0308`.
index 9ff4813d11286e860c0daf2a9f35dcd2c6c78789..32e00f9cb76c301e5c3107c6e03a803979389d3b 100644 (file)
@@ -14,6 +14,10 @@ struct SomeStruct<'x, 'y, 'z: 'x> {
     f: &'y dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Foo<'b>,
 }
 
+// Without this, the wf-check will fail early so we'll never see the
+// error in SOME_STRUCT's body.
+unsafe impl<'x, 'y, 'z: 'x> Sync for SomeStruct<'x, 'y, 'z> {}
+
 fn id<T>(t: T) -> T {
     t
 }
index e95e68c8e6d26c92669d517b9e78f9d6d95ae2eb..16829b5caa0b6894304ddcae9ba8d5706acd515d 100644 (file)
@@ -1,5 +1,5 @@
 error: implementation of `FnOnce` is not general enough
-  --> $DIR/rfc1623.rs:24:8
+  --> $DIR/rfc1623.rs:28:8
    |
 LL |     f: &id,
    |        ^^^ implementation of `FnOnce` is not general enough
index 83ed70a0459a8dc211da08f86c0368966fde5797..2427bde6d18bcbe543e2f92d9101d7a85f3d1a07 100644 (file)
@@ -1,7 +1,8 @@
 // edition:2018
 // compile-flags:--extern foo --extern bar
 
+use bar::foo; //~ ERROR can't find crate for `bar`
 use foo::bar; //~ ERROR can't find crate for `foo`
-use bar::foo;
+//~^^ ERROR unresolved imports `bar::foo`, `foo::bar`
 
 fn main() {}
index 9336e90afb71d23b5497ac491ebc3d16ca4d62eb..8b9863948bd6cd9cd076df02214ec65b7bb906aa 100644 (file)
@@ -1,9 +1,24 @@
-error[E0463]: can't find crate for `foo`
+error[E0463]: can't find crate for `bar`
   --> $DIR/deadlock.rs:4:5
    |
+LL | use bar::foo;
+   |     ^^^ can't find crate
+
+error[E0463]: can't find crate for `foo`
+  --> $DIR/deadlock.rs:5:5
+   |
 LL | use foo::bar;
    |     ^^^ can't find crate
 
-error: aborting due to previous error
+error[E0432]: unresolved imports `bar::foo`, `foo::bar`
+  --> $DIR/deadlock.rs:4:5
+   |
+LL | use bar::foo;
+   |     ^^^^^^^^
+LL | use foo::bar;
+   |     ^^^^^^^^
+
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0463`.
+Some errors have detailed explanations: E0432, E0463.
+For more information about an error, try `rustc --explain E0432`.
index ddd98ff40798a53f3864ec826aed0f1b82ffb866..983e1026f91e9fb50952e4bca2cee9403cf51116 100644 (file)
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/static-mut-bad-types.rs:5:13
    |
+LL | static mut a: isize = 3;
+   |               ----- expected due to this type
+...
 LL |         a = true;
    |             ^^^^ expected `isize`, found `bool`
 
index 4759ebea0e9b700b388174f043deca50807296d3..766db2a8356e7b9330cc6e4cb61e4c426e4769f7 100644 (file)
@@ -10,6 +10,7 @@ LL |     bar(foo);
    |     required by a bound introduced by this call
    |
    = help: the trait `Future` is not implemented for `fn() -> impl Future<Output = ()> {foo}`
+   = note: fn() -> impl Future<Output = ()> {foo} must be a future or must implement `IntoFuture` to be awaited
 note: required by a bound in `bar`
   --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16
    |
@@ -31,6 +32,7 @@ LL |     bar(async_closure);
    |     required by a bound introduced by this call
    |
    = help: the trait `Future` is not implemented for `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]`
+   = note: [closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36] must be a future or must implement `IntoFuture` to be awaited
 note: required by a bound in `bar`
   --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16
    |
index 7ef4895249cec7218f08a5836b9dd9edc0d817c2..550ed4b03b03937d2fe73fbff637f155ea662c48 100644 (file)
@@ -81,7 +81,7 @@ LL |   pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
    |                                             ------------------------------- the found opaque type
    |
    = note:   expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>`
-           found opaque type `impl Future`
+           found opaque type `impl Future<Output = [async output]>`
 help: you need to pin and box this expression
    |
 LL ~     Box::pin(async {
index b111df49f6e5396c20e6d7ec2c2c49d09164a844..101e7aecc0226dc431b3a9175da281c6e1920d00 100644 (file)
@@ -1,11 +1,11 @@
-error[E0277]: the trait bound `fn() -> impl T {foo}: T` is not satisfied
+error[E0277]: the trait bound `fn() -> impl T<O = ()> {foo}: T` is not satisfied
   --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:17:9
    |
 LL | fn foo() -> impl T<O=()> { S }
    |    --- consider calling this function
 ...
 LL |     bar(foo);
-   |     --- ^^^ the trait `T` is not implemented for `fn() -> impl T {foo}`
+   |     --- ^^^ the trait `T` is not implemented for `fn() -> impl T<O = ()> {foo}`
    |     |
    |     required by a bound introduced by this call
    |
index 7f71cb485815fc75949fd94f3b29a27d591a7b04..058f42f2200644955c0b6da29a47a034a83d5e4a 100644 (file)
@@ -70,11 +70,6 @@ error[E0308]: mismatched types
    |
 LL |     if 3 = foo {}
    |        ^^^^^^^ expected `bool`, found `()`
-   |
-help: you might have meant to use pattern matching
-   |
-LL |     if let 3 = foo {}
-   |        +++
 
 error[E0070]: invalid left-hand side of assignment
   --> $DIR/if-let-typo.rs:10:16
index fd5677898e65658ea9a3693d782730f923e39e74..3bd98c7630780a5c9ee02b44418ee0196df4e496 100644 (file)
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/mut-ref-reassignment.rs:2:11
    |
+LL | fn suggestion(opt: &mut Option<String>) {
+   |                    ------------------- expected due to this parameter type
 LL |     opt = None;
    |           ^^^^ expected mutable reference, found enum `Option`
    |
@@ -14,6 +16,8 @@ LL |     *opt = None;
 error[E0308]: mismatched types
   --> $DIR/mut-ref-reassignment.rs:6:11
    |
+LL | fn no_suggestion(opt: &mut Result<String, ()>) {
+   |                       ----------------------- expected due to this parameter type
 LL |     opt = None
    |           ^^^^ expected mutable reference, found enum `Option`
    |
@@ -23,6 +27,8 @@ LL |     opt = None
 error[E0308]: mismatched types
   --> $DIR/mut-ref-reassignment.rs:10:11
    |
+LL | fn suggestion2(opt: &mut Option<String>) {
+   |                     ------------------- expected due to this parameter type
 LL |     opt = Some(String::new())
    |           ^^^^^^^^^^^^^^^^^^^ expected mutable reference, found enum `Option`
    |
@@ -36,6 +42,8 @@ LL |     *opt = Some(String::new())
 error[E0308]: mismatched types
   --> $DIR/mut-ref-reassignment.rs:14:11
    |
+LL | fn no_suggestion2(opt: &mut Option<String>) {
+   |                        ------------------- expected due to this parameter type
 LL |     opt = Some(42)
    |           ^^^^^^^^ expected mutable reference, found enum `Option`
    |
index 60c043bc43f8859213140d5eea17348af320f179..66298e06ed6279ae1ff967185770c5c7783edcef 100644 (file)
@@ -1,5 +1,3 @@
-// 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
index cc62a4d4d9d76f28dade05dc0403fa0d3378eea1..7244919e86d5d66200944d7a8c354257123348ae 100644 (file)
@@ -1,5 +1,5 @@
 error[E0460]: found possibly newer version of crate `a` which `b` depends on
-  --> $DIR/changing-crates.rs:10:1
+  --> $DIR/changing-crates.rs:8:1
    |
 LL | extern crate b;
    | ^^^^^^^^^^^^^^^
index 7d991cc99716e9bb008f00a6561ad1c5abc7d284..ea500711bb76933b0e5211b4e555fb4bb125701f 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-msvc FIXME #31306
-
 // note that these aux-build directives must be in this order
 // aux-build:svh-a-base.rs
 // aux-build:svh-b.rs
index bf51e31bfd66887a833d9fc6547059b64eba010d..1e97e9d0557d04f8890bfec1263b8a6c1076371d 100644 (file)
@@ -1,5 +1,5 @@
 error[E0460]: found possibly newer version of crate `a` which `b` depends on
-  --> $DIR/svh-change-lit.rs:10:1
+  --> $DIR/svh-change-lit.rs:8:1
    |
 LL | extern crate b;
    | ^^^^^^^^^^^^^^^
index 8cf0d9ccaf1e8856d8cc4f50aa0bc501615f80d6..ff919ea83d533c507188f20bcabb1aef8718ce9c 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-msvc FIXME #31306
-
 // note that these aux-build directives must be in this order
 // aux-build:svh-a-base.rs
 // aux-build:svh-b.rs
index c747464db753cb37506e2fe14016c44739937982..f04046f4c87bf423b4173b7f119a4984b18d9d94 100644 (file)
@@ -1,5 +1,5 @@
 error[E0460]: found possibly newer version of crate `a` which `b` depends on
-  --> $DIR/svh-change-significant-cfg.rs:10:1
+  --> $DIR/svh-change-significant-cfg.rs:8:1
    |
 LL | extern crate b;
    | ^^^^^^^^^^^^^^^
index ddd10ac068df32ef4840d7a75ffad248eb65bb90..a4ba06eaf2ee5c3baa83aee9154e13383e517547 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-msvc FIXME #31306
-
 // note that these aux-build directives must be in this order
 // aux-build:svh-a-base.rs
 // aux-build:svh-b.rs
index b144b3b70da0339979c9aefabdf4114cb107b948..a778c61806a500b36e7db4ea2b04c047fbf52fcb 100644 (file)
@@ -1,5 +1,5 @@
 error[E0460]: found possibly newer version of crate `a` which `b` depends on
-  --> $DIR/svh-change-trait-bound.rs:10:1
+  --> $DIR/svh-change-trait-bound.rs:8:1
    |
 LL | extern crate b;
    | ^^^^^^^^^^^^^^^
index f845ab5bc6a91875fb9dbf4026b51690f004023d..d1651814bf66d8b6f81062326bb4ef41ad3186c8 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-msvc FIXME #31306
-
 // note that these aux-build directives must be in this order
 // aux-build:svh-a-base.rs
 // aux-build:svh-b.rs
index 473e4000d2d9c715396cd1ed5b226a34eefbe673..f09babf93fd358903c165ee239615e627f21b936 100644 (file)
@@ -1,5 +1,5 @@
 error[E0460]: found possibly newer version of crate `a` which `b` depends on
-  --> $DIR/svh-change-type-arg.rs:10:1
+  --> $DIR/svh-change-type-arg.rs:8:1
    |
 LL | extern crate b;
    | ^^^^^^^^^^^^^^^
index fb3e996c5fd8cbce427402e482a05dcbb951b1a5..a4be50a643359c27e16e4fcb503697f72d1d1198 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-msvc FIXME #31306
-
 // note that these aux-build directives must be in this order
 // aux-build:svh-a-base.rs
 // aux-build:svh-b.rs
index ecb332fc5b5e9d493c4a56d23f303e0831111b75..0998cd4b5496e8303f6c04450ffd0e8233a084e5 100644 (file)
@@ -1,5 +1,5 @@
 error[E0460]: found possibly newer version of crate `a` which `b` depends on
-  --> $DIR/svh-change-type-ret.rs:10:1
+  --> $DIR/svh-change-type-ret.rs:8:1
    |
 LL | extern crate b;
    | ^^^^^^^^^^^^^^^
index 0dfcaa0003b6657533a84f76ca4a2f8d849e049b..c470761be1954275c058479da9921bc79443da20 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-msvc FIXME #31306
-
 // note that these aux-build directives must be in this order
 // aux-build:svh-a-base.rs
 // aux-build:svh-b.rs
index 33f7e3c485acd436fbaf13741224befe4338546d..9c48cbd30a508408f4976eff4c067275700fedf6 100644 (file)
@@ -1,5 +1,5 @@
 error[E0460]: found possibly newer version of crate `a` which `b` depends on
-  --> $DIR/svh-change-type-static.rs:10:1
+  --> $DIR/svh-change-type-static.rs:8:1
    |
 LL | extern crate b;
    | ^^^^^^^^^^^^^^^
index e5c427e096a724b72576ee8089658a611046dac9..e144fdffb522bb91fc575f5c217b082f775d447c 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-msvc FIXME #31306
-
 // note that these aux-build directives must be in this order
 // aux-build:svh-uta-base.rs
 // aux-build:svh-utb.rs
index 3230bb5c384578635ae4a62af7262fef06c68bd4..5780cfef357d612bf8a23787c44da57b56423ba3 100644 (file)
@@ -1,5 +1,5 @@
 error[E0460]: found possibly newer version of crate `uta` which `utb` depends on
-  --> $DIR/svh-use-trait.rs:15:1
+  --> $DIR/svh-use-trait.rs:13:1
    |
 LL | extern crate utb;
    | ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/traits/project-modulo-regions.rs b/src/test/ui/traits/project-modulo-regions.rs
new file mode 100644 (file)
index 0000000..f0c0dd3
--- /dev/null
@@ -0,0 +1,55 @@
+// revisions: with_clause without_clause
+// Tests that `EvaluatedToOkModuloRegions` from a projection sub-obligation
+// is correctly propagated
+
+#![feature(rustc_attrs)]
+
+trait MyTrait {
+    type Assoc;
+}
+
+struct MyStruct;
+
+impl MyTrait for MyStruct {
+    // Evaluating this projection will result in `EvaluatedToOkModuloRegions`
+    // (when `with_clause` is enabled)
+    type Assoc = <Bar as MyTrait>::Assoc;
+}
+
+struct Bar;
+
+// The `where` clause on this impl will cause us to produce `EvaluatedToOkModuloRegions`
+// when evaluating a projection involving this impl
+#[cfg(with_clause)]
+impl MyTrait for Bar where for<'b> &'b (): 'b {
+    type Assoc = bool;
+}
+
+// This impl tests that the `EvaluatedToOkModuoRegions` result that we get
+// is really due to the `where` clause on the `with_clause` impl
+#[cfg(without_clause)]
+impl MyTrait for Bar {
+    type Assoc = bool;
+}
+
+// The implementation of `#[rustc_evaluate_where_clauses]` doesn't perform
+// normalization, so we need to place the projection predicate behind a normal
+// trait predicate
+struct Helper {}
+trait HelperTrait {}
+impl HelperTrait for Helper where <MyStruct as MyTrait>::Assoc: Sized {}
+
+// Evaluating this 'where' clause will (recursively) end up evaluating
+// `for<'b> &'b (): 'b`, which will produce `EvaluatedToOkModuloRegions`
+#[rustc_evaluate_where_clauses]
+fn test(val: MyStruct) where Helper: HelperTrait  {
+    panic!()
+}
+
+fn foo(val: MyStruct) {
+    test(val);
+    //[with_clause]~^     ERROR evaluate(Binder(TraitPredicate(<Helper as HelperTrait>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions)
+    //[without_clause]~^^ ERROR evaluate(Binder(TraitPredicate(<Helper as HelperTrait>, polarity:Positive), [])) = Ok(EvaluatedToOk)
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/project-modulo-regions.with_clause.stderr b/src/test/ui/traits/project-modulo-regions.with_clause.stderr
new file mode 100644 (file)
index 0000000..2434c32
--- /dev/null
@@ -0,0 +1,11 @@
+error: evaluate(Binder(TraitPredicate(<Helper as HelperTrait>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions)
+  --> $DIR/project-modulo-regions.rs:50:5
+   |
+LL | fn test(val: MyStruct) where Helper: HelperTrait  {
+   |                                      ----------- predicate
+...
+LL |     test(val);
+   |     ^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/traits/project-modulo-regions.without_clause.stderr b/src/test/ui/traits/project-modulo-regions.without_clause.stderr
new file mode 100644 (file)
index 0000000..9d35690
--- /dev/null
@@ -0,0 +1,11 @@
+error: evaluate(Binder(TraitPredicate(<Helper as HelperTrait>, polarity:Positive), [])) = Ok(EvaluatedToOk)
+  --> $DIR/project-modulo-regions.rs:50:5
+   |
+LL | fn test(val: MyStruct) where Helper: HelperTrait  {
+   |                                      ----------- predicate
+...
+LL |     test(val);
+   |     ^^^^
+
+error: aborting due to previous error
+
index c092aa26946f6140d813be7289cc95263f6b0220..d6822d94ca8c96ec0529461bee12948d6bec2fb2 100644 (file)
@@ -21,6 +21,8 @@ LL |             ::std::mem::drop(x);
 LL |         };
 LL |         println!("{}", x);
    |                        ^ value borrowed here after move
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0506]: cannot assign to `i` because it is borrowed
   --> $DIR/try-block-maybe-bad-lifetime.rs:40:9
index 1cbf9c95d3148252a77363d7bfd6448081b73e90..a87e44a048b250c09704b31158b51aacf0c8a60c 100644 (file)
@@ -4,6 +4,8 @@ error[E0308]: mismatched types
 LL | type Foo = impl Debug;
    |            ---------- the expected opaque type
 ...
+LL | fn foo1(mut x: Foo) {
+   |                --- expected due to this parameter type
 LL |     x = 22_u32;
    |         ^^^^^^ expected opaque type, found `u32`
    |
index 2b6ce49e7e2d7bcc1efdfee652bac48a57488df3..5878b26fddbc78453ae0dde1501c75a310f9a9d3 100644 (file)
@@ -5,7 +5,7 @@
 use std::future::Future;
 
 type G<'a, T> = impl Future<Output = ()>;
-//~^ ERROR: type mismatch resolving `<impl Future as Future>::Output == ()`
+//~^ ERROR: type mismatch resolving `<impl Future<Output = [async output]> as Future>::Output == ()`
 //~| ERROR: the trait bound `T: Trait` is not satisfied
 
 trait Trait {
index accc84d30a7bde3a954866eb7e9c0432ae3337a1..19ed9a7476c1b872bded84d1f988665a2067bfca 100644 (file)
@@ -1,4 +1,4 @@
-error[E0271]: type mismatch resolving `<impl Future as Future>::Output == ()`
+error[E0271]: type mismatch resolving `<impl Future<Output = [async output]> as Future>::Output == ()`
   --> $DIR/issue-89686.rs:7:17
    |
 LL | type G<'a, T> = impl Future<Output = ()>;
@@ -13,8 +13,8 @@ LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
    |                                           ------------------------------- the found opaque type
    |
    = note:    expected unit type `()`
-           found associated type `<impl Future as Future>::Output`
-   = help: consider constraining the associated type `<impl Future as Future>::Output` to `()`
+           found associated type `<impl Future<Output = [async output]> as Future>::Output`
+   = help: consider constraining the associated type `<impl Future<Output = [async output]> as Future>::Output` to `()`
    = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 
 error[E0277]: the trait bound `T: Trait` is not satisfied
index f630d2783350306983396776befcecc2bb8d6f21..86b685022b20ec7dd71e5b9b757c57c01253285c 100644 (file)
@@ -5,12 +5,9 @@
 
 use std::fmt::Debug;
 
-type Foo = impl Debug;
-//~^ ERROR: could not find defining uses
+type Foo = impl Debug; //~ ERROR could not find defining uses
 
-static FOO1: Foo = 22_u32;
-//~^ ERROR: mismatched types [E0308]
-const FOO2: Foo = 22_u32;
-//~^ ERROR: mismatched types [E0308]
+static FOO1: Foo = 22_u32; //~ ERROR mismatched types
+const FOO2: Foo = 22_u32; //~ ERROR mismatched types
 
 fn main() {}
index 72083d014fe3a0006ad14af3949cbec9828b858a..6f4c2944f72851e4ec6b1c8084091b1d86d19b2f 100644 (file)
@@ -1,9 +1,9 @@
 error[E0308]: mismatched types
-  --> $DIR/static-const-types.rs:11:20
+  --> $DIR/static-const-types.rs:10:20
    |
 LL | type Foo = impl Debug;
    |            ---------- the expected opaque type
-...
+LL | 
 LL | static FOO1: Foo = 22_u32;
    |                    ^^^^^^ expected opaque type, found `u32`
    |
@@ -11,7 +11,7 @@ LL | static FOO1: Foo = 22_u32;
                      found type `u32`
 
 error[E0308]: mismatched types
-  --> $DIR/static-const-types.rs:13:19
+  --> $DIR/static-const-types.rs:11:19
    |
 LL | type Foo = impl Debug;
    |            ---------- the expected opaque type
diff --git a/src/test/ui/type/issue-91268.rs b/src/test/ui/type/issue-91268.rs
new file mode 100644 (file)
index 0000000..fd2733c
--- /dev/null
@@ -0,0 +1,9 @@
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: cannot find type `ţ` in this scope
+// error-pattern: parenthesized type parameters may only be used with a `Fn` trait
+// error-pattern: type arguments are not allowed for this type
+// error-pattern: mismatched types
+// ignore-tidy-trailing-newlines
+// `ţ` must be the last character in this file, it cannot be followed by a newline
+fn main() {
+    0: u8(ţ
\ No newline at end of file
diff --git a/src/test/ui/type/issue-91268.stderr b/src/test/ui/type/issue-91268.stderr
new file mode 100644 (file)
index 0000000..2fe6ba6
--- /dev/null
@@ -0,0 +1,50 @@
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-91268.rs:9:12
+   |
+LL | fn main() {
+   |           - unclosed delimiter
+LL |     0: u8(ţ
+   |          - ^
+   |          |
+   |          unclosed delimiter
+
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-91268.rs:9:12
+   |
+LL | fn main() {
+   |           - unclosed delimiter
+LL |     0: u8(ţ
+   |          - ^
+   |          |
+   |          unclosed delimiter
+
+error[E0412]: cannot find type `ţ` in this scope
+  --> $DIR/issue-91268.rs:9:11
+   |
+LL |     0: u8(ţ
+   |           ^ expecting a type here because of type ascription
+
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/issue-91268.rs:9:8
+   |
+LL |     0: u8(ţ
+   |        ^^^^ only `Fn` traits may use parentheses
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/issue-91268.rs:9:11
+   |
+LL |     0: u8(ţ
+   |           ^ type argument not allowed
+
+error[E0308]: mismatched types
+  --> $DIR/issue-91268.rs:9:5
+   |
+LL | fn main() {
+   |           - expected `()` because of default return type
+LL |     0: u8(ţ
+   |     ^^^^^^^ expected `()`, found `u8`
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0109, E0214, E0308, E0412.
+For more information about an error, try `rustc --explain E0109`.
index 862ac65bc24e436a984d804a64f1c227f5b5821c..e2b821f7b05e902abceaba706a4fd1f5494f3dd4 100644 (file)
@@ -48,10 +48,6 @@ error[E0308]: mismatched types
 LL |     if 0 = 0 {}
    |        ^^^^^ expected `bool`, found `()`
    |
-help: you might have meant to use pattern matching
-   |
-LL |     if let 0 = 0 {}
-   |        +++
 help: you might have meant to compare for equality
    |
 LL |     if 0 == 0 {}
index 710be9d6a0420da43f76a39940a52f22b61f89c9..f4ef44e2444ee9387d10551511d178323679d634 100644 (file)
@@ -37,10 +37,6 @@ error[E0308]: mismatched types
 LL |     if 3 = x {
    |        ^^^^^ expected `bool`, found `()`
    |
-help: you might have meant to use pattern matching
-   |
-LL |     if let 3 = x {
-   |        +++
 help: you might have meant to compare for equality
    |
 LL |     if 3 == x {
index 1e6ff3b5f9ee752ed72fc8dc2a7bdb11d1dc056c..c545a563b0d0ab1e0abdd8e348113939582e7fc1 100644 (file)
@@ -7,6 +7,9 @@ LL |     a = c + b * 5;
 error[E0308]: mismatched types
   --> $DIR/issue-81293.rs:6:9
    |
+LL |     let a: u16;
+   |            --- expected due to this type
+...
 LL |     a = c + b * 5;
    |         ^^^^^^^^^ expected `u16`, found `usize`
 
index fe10fa733d23808c9e6c18f77f3515fe2bb12678..56817ee2ca9f823f71b060b4cedf994edcb8e83e 100644 (file)
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/issue-87771-ice-assign-assign-to-bool.rs:3:9
    |
+LL |     let mut a;
+   |         ----- expected due to the type of this binding
 LL |     a = a = true;
    |         ^^^^^^^^ expected `bool`, found `()`
 
diff --git a/src/test/ui/typeck/issue-91210-ptr-method.fixed b/src/test/ui/typeck/issue-91210-ptr-method.fixed
new file mode 100644 (file)
index 0000000..94200cc
--- /dev/null
@@ -0,0 +1,15 @@
+// Regression test for issue #91210.
+
+// run-rustfix
+
+#![allow(unused)]
+
+struct Foo { read: i32 }
+
+unsafe fn blah(x: *mut Foo) {
+    (*x).read = 4;
+    //~^ ERROR: attempted to take value of method
+    //~| HELP: to access the field, dereference first
+}
+
+fn main() {}
diff --git a/src/test/ui/typeck/issue-91210-ptr-method.rs b/src/test/ui/typeck/issue-91210-ptr-method.rs
new file mode 100644 (file)
index 0000000..ed0ce6e
--- /dev/null
@@ -0,0 +1,15 @@
+// Regression test for issue #91210.
+
+// run-rustfix
+
+#![allow(unused)]
+
+struct Foo { read: i32 }
+
+unsafe fn blah(x: *mut Foo) {
+    x.read = 4;
+    //~^ ERROR: attempted to take value of method
+    //~| HELP: to access the field, dereference first
+}
+
+fn main() {}
diff --git a/src/test/ui/typeck/issue-91210-ptr-method.stderr b/src/test/ui/typeck/issue-91210-ptr-method.stderr
new file mode 100644 (file)
index 0000000..503a323
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0615]: attempted to take value of method `read` on type `*mut Foo`
+  --> $DIR/issue-91210-ptr-method.rs:10:7
+   |
+LL |     x.read = 4;
+   |     - ^^^^ method, not a field
+   |     |
+   |     help: to access the field, dereference first: `(*x)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0615`.
diff --git a/src/test/ui/union/issue-81199.rs b/src/test/ui/union/issue-81199.rs
new file mode 100644 (file)
index 0000000..628e7c6
--- /dev/null
@@ -0,0 +1,21 @@
+#[repr(C)]
+union PtrRepr<T: ?Sized> {
+    const_ptr: *const T,
+    mut_ptr: *mut T,
+    components: PtrComponents<T>,
+    //~^ ERROR the trait bound
+}
+
+#[repr(C)]
+struct PtrComponents<T: Pointee + ?Sized> {
+    data_address: *const (),
+    metadata: <T as Pointee>::Metadata,
+}
+
+
+
+pub trait Pointee {
+   type Metadata;
+}
+
+fn main() {}
diff --git a/src/test/ui/union/issue-81199.stderr b/src/test/ui/union/issue-81199.stderr
new file mode 100644 (file)
index 0000000..f26bfe3
--- /dev/null
@@ -0,0 +1,29 @@
+error[E0277]: the trait bound `T: Pointee` is not satisfied in `PtrComponents<T>`
+  --> $DIR/issue-81199.rs:5:17
+   |
+LL |     components: PtrComponents<T>,
+   |                 ^^^^^^^^^^^^^^^^ within `PtrComponents<T>`, the trait `Pointee` is not implemented for `T`
+   |
+note: required because it appears within the type `PtrComponents<T>`
+  --> $DIR/issue-81199.rs:10:8
+   |
+LL | struct PtrComponents<T: Pointee + ?Sized> {
+   |        ^^^^^^^^^^^^^
+   = note: no field of a union may have a dynamically sized type
+   = help: change the field's type to have a statically known size
+help: consider further restricting this bound
+   |
+LL | union PtrRepr<T: ?Sized + Pointee> {
+   |                         +++++++++
+help: borrowed types always have a statically known size
+   |
+LL |     components: &PtrComponents<T>,
+   |                 +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+   |
+LL |     components: Box<PtrComponents<T>>,
+   |                 ++++                +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index 11ce005bb457c861e50921de05d2be07185e9c82..361a6e2d8c2786658f49be72d2f1e800aed5cc39 100644 (file)
@@ -7,6 +7,8 @@ LL |     let _y = x;
    |              - value moved here
 LL |     println!("{}", x);
    |                    ^ value borrowed here after move
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index cda08b0f4e09cc6c1404a2389535e1b39f83c42e..377a8074458912c55e789f70828f813b7afa3e69 100644 (file)
@@ -13,6 +13,7 @@ note: this function takes ownership of the receiver `self`, which moves `start`
    |
 LL |     fn make_string_bar(mut self) -> Mine{
    |                            ^^^^
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index e1fb17631eb1b3665cdbe45b1c186111577ef512..294967c53f0c70d598fc54ca189313c86c576ea7 160000 (submodule)
@@ -1 +1 @@
-Subproject commit e1fb17631eb1b3665cdbe45b1c186111577ef512
+Subproject commit 294967c53f0c70d598fc54ca189313c86c576ea7
index 24ac5917dcb0521350e0072234bee02982e58f7a..94b35ad88af2d605243fb06db7379633d43bb15b 100644 (file)
@@ -3,7 +3,6 @@
 use clippy_utils::ty::{implements_trait, is_copy};
 use clippy_utils::{get_trait_def_id, is_automatically_derived, is_lint_allowed, match_def_path};
 use if_chain::if_chain;
-use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, NestedVisitorMap, Visitor};
 use rustc_hir::{
     BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, HirId, Impl, Item, ItemKind, TraitRef, UnsafeSource, Unsafety,
@@ -343,11 +342,6 @@ fn check_unsafe_derive_deserialize<'tcx>(
     trait_ref: &TraitRef<'_>,
     ty: Ty<'tcx>,
 ) {
-    fn item_from_def_id<'tcx>(cx: &LateContext<'tcx>, def_id: DefId) -> &'tcx Item<'tcx> {
-        let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-        cx.tcx.hir().expect_item(hir_id)
-    }
-
     fn has_unsafe<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>) -> bool {
         let mut visitor = UnsafeVisitor { cx, has_unsafe: false };
         walk_item(&mut visitor, item);
@@ -363,7 +357,7 @@ fn has_unsafe<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>) -> bool {
         if !is_lint_allowed(cx, UNSAFE_DERIVE_DESERIALIZE, adt_hir_id);
         if cx.tcx.inherent_impls(def.did)
             .iter()
-            .map(|imp_did| item_from_def_id(cx, *imp_did))
+            .map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local()))
             .any(|imp| has_unsafe(cx, imp));
         then {
             span_lint_and_help(
index 26c29fbb289cb7f8d11e1aa41ce5d22d46a07cb0..e46739fea34beb1b70e1f8c0d6a68d5d834bc592 100644 (file)
@@ -1939,7 +1939,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::Impl
             return;
         }
         let name = impl_item.ident.name.as_str();
-        let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
+        let parent = cx.tcx.hir().get_parent_did(impl_item.hir_id());
         let item = cx.tcx.hir().expect_item(parent);
         let self_ty = cx.tcx.type_of(item.def_id);
 
index 2a85a67fa099cac9355d26e61ca5bdada9387994..2ea97eb88f783558076b8655f62b0444723d4701 100644 (file)
@@ -279,8 +279,8 @@ fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx TraitIt
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) {
         if let ImplItemKind::Const(hir_ty, body_id) = &impl_item.kind {
-            let item_hir_id = cx.tcx.hir().get_parent_node(impl_item.hir_id());
-            let item = cx.tcx.hir().expect_item(item_hir_id);
+            let item_def_id = cx.tcx.hir().get_parent_did(impl_item.hir_id());
+            let item = cx.tcx.hir().expect_item(item_def_id);
 
             match &item.kind {
                 ItemKind::Impl(Impl {
index 4ba5e1a0f5357829f95fad45aec80029882e8b88..9390378d789cdddec8c5b27f5156843e7366169d 100644 (file)
@@ -50,7 +50,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<
             _ => return,
         }
 
-        let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
+        let parent = cx.tcx.hir().get_parent_did(impl_item.hir_id());
         let item = cx.tcx.hir().expect_item(parent);
         let self_ty = cx.tcx.type_of(item.def_id);
         let ret_ty = return_ty(cx, impl_item.hir_id());
index e7e249c79a2fad0f6f97e1a8110d62b41f763029..c961f995667952343e846eeee07c36b68cb214a5 100644 (file)
@@ -41,7 +41,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &ImplItem<'_>)
         if impl_item.span.from_expansion() {
             return;
         }
-        let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
+        let parent = cx.tcx.hir().get_parent_did(impl_item.hir_id());
         let parent_item = cx.tcx.hir().expect_item(parent);
         let assoc_item = cx.tcx.associated_item(impl_item.def_id);
         if_chain! {
index 439884b7d274aef2d3cd92637a0b8847e1bedbd8..0d7713aa9a2780794fcc118a02af3f50b18276ec 100644 (file)
@@ -24,6 +24,9 @@ LL | | }
 error[E0308]: mismatched types
   --> $DIR/ice-6250.rs:12:14
    |
+LL |     for reference in vec![1, 2, 3] {
+   |         --------- expected due to the type of this binding
+...
 LL |         Some(reference) = cache.data.get(key) {
    |              ^^^^^^^^^ expected integer, found `&i32`
    |
index d0ad4b80cdefe5602fa40a20a2bf76f34742f63f..4bf74c1508bd295882d648c39c8167ebd12987e1 100644 (file)
@@ -1452,6 +1452,8 @@ fn document(&self, out_dir: &Path) -> ProcRes {
             .arg(aux_dir)
             .arg("-o")
             .arg(out_dir)
+            .arg("--deny")
+            .arg("warnings")
             .arg(&self.testpaths.file)
             .args(&self.props.compile_flags);
 
index 76a3329f51439ff2cacda4d26d478a9dc1682a06..9983e0fc634e11717eb457a73fe84cfc9409ba8f 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 76a3329f51439ff2cacda4d26d478a9dc1682a06
+Subproject commit 9983e0fc634e11717eb457a73fe84cfc9409ba8f
index 183ef048f61ae36aa389d1d0345cde940fe788e9..d9b2291f546abc77d24499339a72a89127464b95 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 183ef048f61ae36aa389d1d0345cde940fe788e9
+Subproject commit d9b2291f546abc77d24499339a72a89127464b95
index 6eaae69c708056c56c0e6c8d44883fb8625f241b..db497941642122c107bb3335a7520bcd1761647d 100644 (file)
@@ -8,7 +8,9 @@ on:
 jobs:
   test:
     runs-on: ubuntu-latest
-    name: (${{ matrix.target }}, nightly)
+    name: (${{ matrix.target }}, ${{ matrix.cfg_release_channel }})
+    env:
+      CFG_RELEASE_CHANNEL: ${{ matrix.cfg_release_channel }}
     strategy:
       # https://help.github.com/en/actions/getting-started-with-github-actions/about-github-actions#usage-limits
       # There's a limit of 60 concurrent jobs across all repos in the rust-lang organization.
@@ -20,6 +22,7 @@ jobs:
         target: [
           x86_64-unknown-linux-gnu,
         ]
+        cfg_release_channel: [nightly, stable]
 
     steps:
     - name: checkout
index 79e4f69163e030b3a5eae659ab0165cb093790bf..55e1cc9539b8508db5234f9fde51191b40644c43 100644 (file)
@@ -10,13 +10,16 @@ jobs:
     # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners#supported-runners-and-hardware-resources
     # macOS Catalina 10.15
     runs-on: macos-latest
-    name: (${{ matrix.target }}, nightly)
+    name: (${{ matrix.target }}, ${{ matrix.cfg_release_channel }})
+    env:
+      CFG_RELEASE_CHANNEL: ${{ matrix.cfg_release_channel }}
     strategy:
       fail-fast: false
       matrix:
         target: [
           x86_64-apple-darwin,
         ]
+        cfg_release_channel: [nightly, stable]
 
     steps:
     - name: checkout
index c05e8d4896ac707d2c23b24d12eda006355a01be..dcb08b5412ea6c421c6ac3bf1971f4eb3d291f77 100644 (file)
@@ -8,7 +8,9 @@ on:
 jobs:
   test:
     runs-on: windows-latest
-    name: (${{ matrix.target }}, nightly)
+    name: (${{ matrix.target }}, ${{ matrix.cfg_release_channel }})
+    env:
+      CFG_RELEASE_CHANNEL: ${{ matrix.cfg_release_channel }}
     strategy:
       # https://help.github.com/en/actions/getting-started-with-github-actions/about-github-actions#usage-limits
       # There's a limit of 60 concurrent jobs across all repos in the rust-lang organization.
@@ -23,6 +25,7 @@ jobs:
           x86_64-pc-windows-gnu,
           x86_64-pc-windows-msvc,
         ]
+        cfg_release_channel: [nightly, stable]
 
     steps:
     # The Windows runners have autocrlf enabled by default
index 13826883d2f4bdf537df1df2a687be215adbaf97..a89fbe863e65283ce47ca0e36f87a0267058eb52 100644 (file)
@@ -47,7 +47,7 @@ Where to put a binary operator when a binary expression goes multiline.
 
 - **Default value**: `"Front"`
 - **Possible values**: `"Front"`, `"Back"`
-- **Stable**: No (tracking issue: #3368)
+- **Stable**: No (tracking issue: [#3368](https://github.com/rust-lang/rustfmt/issues/3368))
 
 #### `"Front"` (default):
 
@@ -88,7 +88,7 @@ them, additional blank lines are inserted.
 
 - **Default value**: `0`
 - **Possible values**: *unsigned integer*
-- **Stable**: No (tracking issue: #3382)
+- **Stable**: No (tracking issue: [#3382](https://github.com/rust-lang/rustfmt/issues/3382))
 
 ### Example
 Original Code (rustfmt will not change it with the default value of `0`):
@@ -128,7 +128,7 @@ lines are found, they are trimmed down to match this integer.
 
 - **Default value**: `1`
 - **Possible values**: any non-negative integer
-- **Stable**: No (tracking issue: #3381)
+- **Stable**: No (tracking issue: [#3381](https://github.com/rust-lang/rustfmt/issues/3381))
 
 ### Example
 Original Code:
@@ -186,7 +186,7 @@ Brace style for items
 
 - **Default value**: `"SameLineWhere"`
 - **Possible values**: `"AlwaysNextLine"`, `"PreferSameLine"`, `"SameLineWhere"`
-- **Stable**: No (tracking issue: #3376)
+- **Stable**: No (tracking issue: [#3376](https://github.com/rust-lang/rustfmt/issues/3376))
 
 ### Functions
 
@@ -313,7 +313,7 @@ Whether to use colored output or not.
 
 - **Default value**: `"Auto"`
 - **Possible values**: "Auto", "Always", "Never"
-- **Stable**: No (tracking issue: #3385)
+- **Stable**: No (tracking issue: [#3385](https://github.com/rust-lang/rustfmt/issues/3385))
 
 ## `combine_control_expr`
 
@@ -321,7 +321,7 @@ Combine control expressions with function calls.
 
 - **Default value**: `true`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3369)
+- **Stable**: No (tracking issue: [#3369](https://github.com/rust-lang/rustfmt/issues/3369))
 
 #### `true` (default):
 
@@ -429,7 +429,7 @@ Maximum length of comments. No effect unless`wrap_comments = true`.
 
 - **Default value**: `80`
 - **Possible values**: any positive integer
-- **Stable**: No (tracking issue: #3349)
+- **Stable**: No (tracking issue: [#3349](https://github.com/rust-lang/rustfmt/issues/3349))
 
 **Note:** A value of `0` results in [`wrap_comments`](#wrap_comments) being applied regardless of a line's width.
 
@@ -452,7 +452,7 @@ Replace strings of _ wildcards by a single .. in tuple patterns
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3384)
+- **Stable**: No (tracking issue: [#3384](https://github.com/rust-lang/rustfmt/issues/3384))
 
 #### `false` (default):
 
@@ -477,7 +477,7 @@ Brace style for control flow constructs
 
 - **Default value**: `"AlwaysSameLine"`
 - **Possible values**: `"AlwaysNextLine"`, `"AlwaysSameLine"`, `"ClosingNextLine"`
-- **Stable**: No (tracking issue: #3377)
+- **Stable**: No (tracking issue: [#3377](https://github.com/rust-lang/rustfmt/issues/3377))
 
 #### `"AlwaysSameLine"` (default):
 
@@ -551,7 +551,7 @@ Put empty-body functions and impls on a single line
 
 - **Default value**: `true`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3356)
+- **Stable**: No (tracking issue: [#3356](https://github.com/rust-lang/rustfmt/issues/3356))
 
 #### `true` (default):
 
@@ -584,7 +584,7 @@ doesn't get ignored when aligning.
 
 - **Default value** : 0
 - **Possible values**: any positive integer
-- **Stable**: No (tracking issue: #3372)
+- **Stable**: No (tracking issue: [#3372](https://github.com/rust-lang/rustfmt/issues/3372))
 
 #### `0` (default):
 
@@ -630,7 +630,7 @@ using a shorter name.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3391)
+- **Stable**: No (tracking issue: [#3391](https://github.com/rust-lang/rustfmt/issues/3391))
 
 See also [`max_width`](#max_width).
 
@@ -641,7 +641,7 @@ trailing whitespaces.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3392)
+- **Stable**: No (tracking issue: [#3392](https://github.com/rust-lang/rustfmt/issues/3392))
 
 ## `fn_args_layout`
 
@@ -771,7 +771,7 @@ Put single-expression functions on a single line
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3358)
+- **Stable**: No (tracking issue: [#3358](https://github.com/rust-lang/rustfmt/issues/3358))
 
 #### `false` (default):
 
@@ -832,7 +832,7 @@ Force multiline closure and match arm bodies to be wrapped in a block
 
 - **Default value**: `false`
 - **Possible values**: `false`, `true`
-- **Stable**: No (tracking issue: #3374)
+- **Stable**: No (tracking issue: [#3374](https://github.com/rust-lang/rustfmt/issues/3374))
 
 #### `false` (default):
 
@@ -881,7 +881,7 @@ Format code snippet included in doc comments.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3348)
+- **Stable**: No (tracking issue: [#3348](https://github.com/rust-lang/rustfmt/issues/3348))
 
 #### `false` (default):
 
@@ -933,7 +933,7 @@ if any of the first five lines contains `@generated` marker.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No
+- **Stable**: No (tracking issue: [#5080](https://github.com/rust-lang/rustfmt/issues/5080))
 
 ## `format_macro_matchers`
 
@@ -941,7 +941,7 @@ Format the metavariable matching patterns in macros.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3354)
+- **Stable**: No (tracking issue: [#3354](https://github.com/rust-lang/rustfmt/issues/3354))
 
 #### `false` (default):
 
@@ -978,7 +978,7 @@ Format the bodies of macros.
 
 - **Default value**: `true`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3355)
+- **Stable**: No (tracking issue: [#3355](https://github.com/rust-lang/rustfmt/issues/3355))
 
 #### `true` (default):
 
@@ -1011,7 +1011,7 @@ Format string literals where necessary
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3353)
+- **Stable**: No (tracking issue: [#3353](https://github.com/rust-lang/rustfmt/issues/3353))
 
 #### `false` (default):
 
@@ -1064,7 +1064,7 @@ Control the case of the letters in hexadecimal literal values
 
 - **Default value**: `Preserve`
 - **Possible values**: `Upper`, `Lower`
-- **Stable**: No
+- **Stable**: No (tracking issue: [#5081](https://github.com/rust-lang/rustfmt/issues/5081))
 
 ## `hide_parse_errors`
 
@@ -1072,7 +1072,7 @@ Do not show parse errors if the parser failed to parse files.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3390)
+- **Stable**: No (tracking issue: [#3390](https://github.com/rust-lang/rustfmt/issues/3390))
 
 ## `ignore`
 
@@ -1081,7 +1081,7 @@ The pattern format is the same as [.gitignore](https://git-scm.com/docs/gitignor
 
 - **Default value**: format every file
 - **Possible values**: See an example below
-- **Stable**: No (tracking issue: #3395)
+- **Stable**: No (tracking issue: [#3395](https://github.com/rust-lang/rustfmt/issues/3395))
 
 ### Example
 
@@ -1114,7 +1114,7 @@ Indent style of imports
 
 - **Default Value**: `"Block"`
 - **Possible values**: `"Block"`, `"Visual"`
-- **Stable**: No (tracking issue: #3360)
+- **Stable**: No (tracking issue: [#3360](https://github.com/rust-lang/rustfmt/issues/3360))
 
 #### `"Block"` (default):
 
@@ -1140,7 +1140,7 @@ Item layout inside a imports block
 
 - **Default value**: "Mixed"
 - **Possible values**: "Horizontal", "HorizontalVertical", "Mixed", "Vertical"
-- **Stable**: No (tracking issue: #3361)
+- **Stable**: No (tracking issue: [#3361](https://github.com/rust-lang/rustfmt/issues/3361))
 
 #### `"Mixed"` (default):
 
@@ -1203,7 +1203,7 @@ Indent on expressions or items.
 
 - **Default value**: `"Block"`
 - **Possible values**: `"Block"`, `"Visual"`
-- **Stable**: No (tracking issue: #3346)
+- **Stable**: No (tracking issue: [#3346](https://github.com/rust-lang/rustfmt/issues/3346))
 
 ### Array
 
@@ -1456,7 +1456,7 @@ Write an item and its attribute on the same line if their combined width is belo
 
 - **Default value**: 0
 - **Possible values**: any positive integer
-- **Stable**: No (tracking issue: #3343)
+- **Stable**: No (tracking issue: [#3343](https://github.com/rust-lang/rustfmt/issues/3343))
 
 ### Example
 
@@ -1477,7 +1477,7 @@ Check whether beginnings of files match a license template.
 
 - **Default value**: `""`
 - **Possible values**: path to a license template file
-- **Stable**: No (tracking issue: #3352)
+- **Stable**: No (tracking issue: [#3352](https://github.com/rust-lang/rustfmt/issues/3352))
 
 A license template is a plain text file which is matched literally against the
 beginning of each source file, except for `{}`-delimited blocks, which are
@@ -1499,7 +1499,7 @@ The Style Guide requires that bodies are block wrapped by default if a line brea
 
 - **Default value**: `true`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3373)
+- **Stable**: No (tracking issue: [#3373](https://github.com/rust-lang/rustfmt/issues/3373))
 
 #### `true` (default):
 
@@ -1701,7 +1701,7 @@ How imports should be grouped into `use` statements. Imports will be merged or s
 
 - **Default value**: `Preserve`
 - **Possible values**: `Preserve`, `Crate`, `Module`, `Item`, `One`
-- **Stable**: No
+- **Stable**: No (tracking issue: [#4991](https://github.com/rust-lang/rustfmt/issues/4991))
 
 #### `Preserve` (default):
 
@@ -1826,7 +1826,7 @@ Convert /* */ comments to // comments where possible
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3350)
+- **Stable**: No (tracking issue: [#3350](https://github.com/rust-lang/rustfmt/issues/3350))
 
 #### `false` (default):
 
@@ -1854,7 +1854,7 @@ Convert `#![doc]` and `#[doc]` attributes to `//!` and `///` doc comments.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3351)
+- **Stable**: No (tracking issue: [#3351](https://github.com/rust-lang/rustfmt/issues/3351))
 
 #### `false` (default):
 
@@ -1885,7 +1885,7 @@ instead of being indented on a new line.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3370)
+- **Stable**: No (tracking issue: [#3370](https://github.com/rust-lang/rustfmt/issues/3370))
 
 #### `false` (default):
 
@@ -1992,7 +1992,7 @@ Reorder impl items. `type` and `const` are put first, then macros and methods.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3363)
+- **Stable**: No (tracking issue: [#3363](https://github.com/rust-lang/rustfmt/issues/3363))
 
 #### `false` (default)
 
@@ -2063,7 +2063,7 @@ Controls the strategy for how imports are grouped together.
 
 - **Default value**: `Preserve`
 - **Possible values**: `Preserve`, `StdExternalCrate`, `One`
-- **Stable**: No
+- **Stable**: No (tracking issue: [#5083](https://github.com/rust-lang/rustfmt/issues/5083))
 
 #### `Preserve` (default):
 
@@ -2166,7 +2166,7 @@ Report `FIXME` items in comments.
 
 - **Default value**: `"Never"`
 - **Possible values**: `"Always"`, `"Unnumbered"`, `"Never"`
-- **Stable**: No (tracking issue: #3394)
+- **Stable**: No (tracking issue: [#3394](https://github.com/rust-lang/rustfmt/issues/3394))
 
 Warns about any comments containing `FIXME` in them when set to `"Always"`. If
 it contains a `#X` (with `X` being a number) in parentheses following the
@@ -2181,7 +2181,7 @@ Report `TODO` items in comments.
 
 - **Default value**: `"Never"`
 - **Possible values**: `"Always"`, `"Unnumbered"`, `"Never"`
-- **Stable**: No (tracking issue: #3393)
+- **Stable**: No (tracking issue: [#3393](https://github.com/rust-lang/rustfmt/issues/3393))
 
 Warns about any comments containing `TODO` in them when set to `"Always"`. If
 it contains a `#X` (with `X` being a number) in parentheses following the
@@ -2196,7 +2196,7 @@ specific version of rustfmt is used in your CI, use this option.
 
 - **Default value**: `CARGO_PKG_VERSION`
 - **Possible values**: any published version (e.g. `"0.3.8"`)
-- **Stable**: No (tracking issue: #3386)
+- **Stable**: No (tracking issue: [#3386](https://github.com/rust-lang/rustfmt/issues/3386))
 
 ## `skip_children`
 
@@ -2204,7 +2204,7 @@ Don't reformat out of line modules
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3389)
+- **Stable**: No (tracking issue: [#3389](https://github.com/rust-lang/rustfmt/issues/3386))
 
 ## `single_line_if_else_max_width`
 
@@ -2224,7 +2224,7 @@ Leave a space after the colon.
 
 - **Default value**: `true`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3366)
+- **Stable**: No (tracking issue: [#3366](https://github.com/rust-lang/rustfmt/issues/3366))
 
 #### `true` (default):
 
@@ -2256,7 +2256,7 @@ Leave a space before the colon.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3365)
+- **Stable**: No (tracking issue: [#3365](https://github.com/rust-lang/rustfmt/issues/3365))
 
 #### `false` (default):
 
@@ -2288,7 +2288,7 @@ Put spaces around the .., ..=, and ... range operators
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3367)
+- **Stable**: No (tracking issue: [#3367](https://github.com/rust-lang/rustfmt/issues/3367))
 
 #### `false` (default):
 
@@ -2344,7 +2344,7 @@ The maximum diff of width between struct fields to be aligned with each other.
 
 - **Default value** : 0
 - **Possible values**: any non-negative integer
-- **Stable**: No (tracking issue: #3371)
+- **Stable**: No (tracking issue: [#3371](https://github.com/rust-lang/rustfmt/issues/3371))
 
 #### `0` (default):
 
@@ -2372,7 +2372,7 @@ Put small struct literals on a single line
 
 - **Default value**: `true`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3357)
+- **Stable**: No (tracking issue: [#3357](https://github.com/rust-lang/rustfmt/issues/3357))
 
 #### `true` (default):
 
@@ -2460,7 +2460,7 @@ How to handle trailing commas for lists
 
 - **Default value**: `"Vertical"`
 - **Possible values**: `"Always"`, `"Never"`, `"Vertical"`
-- **Stable**: No (tracking issue: #3379)
+- **Stable**: No (tracking issue: [#3379](https://github.com/rust-lang/rustfmt/issues/3379))
 
 #### `"Vertical"` (default):
 
@@ -2518,7 +2518,7 @@ Add trailing semicolon after break, continue and return
 
 - **Default value**: `true`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3378)
+- **Stable**: No (tracking issue: [#3378](https://github.com/rust-lang/rustfmt/issues/3378))
 
 #### `true` (default):
 ```rust
@@ -2540,7 +2540,7 @@ Determines if `+` or `=` are wrapped in spaces in the punctuation of types
 
 - **Default value**: `"Wide"`
 - **Possible values**: `"Compressed"`, `"Wide"`
-- **Stable**: No (tracking issue: #3364)
+- **Stable**: No (tracking issue: [#3364](https://github.com/rust-lang/rustfmt/issues/3364))
 
 #### `"Wide"` (default):
 
@@ -2564,7 +2564,7 @@ Enable unstable features on the unstable channel.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3387)
+- **Stable**: No (tracking issue: [#3387](https://github.com/rust-lang/rustfmt/issues/3387))
 
 ## `use_field_init_shorthand`
 
@@ -2779,7 +2779,7 @@ version number.
 
 - **Default value**: `One`
 - **Possible values**: `One`, `Two`
-- **Stable**: No (tracking issue: #3383)
+- **Stable**: No (tracking issue: [#3383](https://github.com/rust-lang/rustfmt/issues/3383))
 
 ### Example
 
@@ -2793,7 +2793,7 @@ Forces the `where` clause to be laid out on a single line.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3359)
+- **Stable**: No (tracking issue: [#3359](https://github.com/rust-lang/rustfmt/issues/3359))
 
 #### `false` (default):
 
@@ -2825,7 +2825,7 @@ Break comments to fit on the line
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3347)
+- **Stable**: No (tracking issue: [#3347](https://github.com/rust-lang/rustfmt/issues/3347))
 
 #### `false` (default):
 
index b3d21e6fb87c79ffa3957b20a4cc405f2787f051..b3a968f0c043e30f10badc3853a3b5652e082eee 100644 (file)
@@ -48,12 +48,11 @@ cargo +nightly fmt
 ## Limitations
 
 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
-Rustfmt can't do or can't do well (and thus where formatting might change
-significantly, even post-1.0). We would like to reduce the list of limitations
-over time.
+doesn't even need to compile! In general, we are 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 Rustfmt can't
+do or can't do well (and thus where formatting might change significantly,
+even post-1.0). We would like to reduce the list of limitations over time.
 
 The following list enumerates areas where Rustfmt does not work or where the
 stability guarantees do not apply (we don't make a distinction between the two
index 78e7e098ed9e17cf1de271c9c637cf41fbb9158c..513018213192df3625b11f5b87fc88673c00e5cf 100644 (file)
@@ -8,6 +8,8 @@
 mod item_struct;
 mod utils;
 
+use std::str::FromStr;
+
 use proc_macro::TokenStream;
 use syn::parse_macro_input;
 
@@ -23,3 +25,43 @@ pub fn config_type(_args: TokenStream, input: TokenStream) -> TokenStream {
 
     TokenStream::from(output)
 }
+
+/// Used to conditionally output the TokenStream for tests that need to be run on nightly only.
+///
+/// ```rust
+/// #[nightly_only_test]
+/// #[test]
+/// fn test_needs_nightly_rustfmt() {
+///   assert!(true);
+/// }
+/// ```
+#[proc_macro_attribute]
+pub fn nightly_only_test(_args: TokenStream, input: TokenStream) -> TokenStream {
+    // if CFG_RELEASE_CHANNEL is not set we default to nightly, hence why the default is true
+    if option_env!("CFG_RELEASE_CHANNEL").map_or(true, |c| c == "nightly" || c == "dev") {
+        input
+    } else {
+        // output an empty token stream if CFG_RELEASE_CHANNEL is not set to "nightly" or "dev"
+        TokenStream::from_str("").unwrap()
+    }
+}
+
+/// Used to conditionally output the TokenStream for tests that need to be run on stable only.
+///
+/// ```rust
+/// #[stable_only_test]
+/// #[test]
+/// fn test_needs_stable_rustfmt() {
+///   assert!(true);
+/// }
+/// ```
+#[proc_macro_attribute]
+pub fn stable_only_test(_args: TokenStream, input: TokenStream) -> TokenStream {
+    // if CFG_RELEASE_CHANNEL is not set we default to nightly, hence why the default is false
+    if option_env!("CFG_RELEASE_CHANNEL").map_or(false, |c| c == "stable") {
+        input
+    } else {
+        // output an empty token stream if CFG_RELEASE_CHANNEL is not set or is not 'stable'
+        TokenStream::from_str("").unwrap()
+    }
+}
index 7b76c232937dc7cea63d7df07716777730cbeef2..0f850b9b2f2fba2b84be6e51101161fbf5773a2e 100644 (file)
@@ -3,6 +3,8 @@
 use std::{self, borrow::Cow, iter};
 
 use itertools::{multipeek, MultiPeek};
+use lazy_static::lazy_static;
+use regex::Regex;
 use rustc_span::Span;
 
 use crate::config::Config;
 };
 use crate::{ErrorKind, FormattingError};
 
+lazy_static! {
+    /// A regex matching reference doc links.
+    ///
+    /// ```markdown
+    /// /// An [example].
+    /// ///
+    /// /// [example]: this::is::a::link
+    /// ```
+    static ref REFERENCE_LINK_URL: Regex = Regex::new(r"^\[.+\]\s?:").unwrap();
+}
+
 fn is_custom_comment(comment: &str) -> bool {
     if !comment.starts_with("//") {
         false
@@ -506,6 +519,7 @@ struct CommentRewrite<'a> {
     opener: String,
     closer: String,
     line_start: String,
+    style: CommentStyle<'a>,
 }
 
 impl<'a> CommentRewrite<'a> {
@@ -515,10 +529,14 @@ fn new(
         shape: Shape,
         config: &'a Config,
     ) -> CommentRewrite<'a> {
-        let (opener, closer, line_start) = if block_style {
-            CommentStyle::SingleBullet.to_str_tuplet()
+        let ((opener, closer, line_start), style) = if block_style {
+            (
+                CommentStyle::SingleBullet.to_str_tuplet(),
+                CommentStyle::SingleBullet,
+            )
         } else {
-            comment_style(orig, config.normalize_comments()).to_str_tuplet()
+            let style = comment_style(orig, config.normalize_comments());
+            (style.to_str_tuplet(), style)
         };
 
         let max_width = shape
@@ -551,6 +569,7 @@ fn new(
             opener: opener.to_owned(),
             closer: closer.to_owned(),
             line_start: line_start.to_owned(),
+            style,
         };
         cr.result.push_str(opener);
         cr
@@ -570,6 +589,15 @@ fn join_block(s: &str, sep: &str) -> String {
         result
     }
 
+    /// Check if any characters were written to the result buffer after the start of the comment.
+    /// when calling [`CommentRewrite::new()`] the result buffer is initiazlied with the opening
+    /// characters for the comment.
+    fn buffer_contains_comment(&self) -> bool {
+        // if self.result.len() < self.opener.len() then an empty comment is in the buffer
+        // if self.result.len() > self.opener.len() then a non empty comment is in the buffer
+        self.result.len() != self.opener.len()
+    }
+
     fn finish(mut self) -> String {
         if !self.code_block_buffer.is_empty() {
             // There is a code block that is not properly enclosed by backticks.
@@ -585,7 +613,12 @@ fn finish(mut self) -> String {
             // the last few lines are part of an itemized block
             self.fmt.shape = Shape::legacy(self.max_width, self.fmt_indent);
             let item_fmt = ib.create_string_format(&self.fmt);
-            self.result.push_str(&self.comment_line_separator);
+
+            // only push a comment_line_separator for ItemizedBlocks if the comment is not empty
+            if self.buffer_contains_comment() {
+                self.result.push_str(&self.comment_line_separator);
+            }
+
             self.result.push_str(&ib.opener);
             match rewrite_string(
                 &ib.trimmed_block_as_string(),
@@ -619,7 +652,13 @@ fn handle_line(
         line: &'a str,
         has_leading_whitespace: bool,
     ) -> bool {
-        let is_last = i == count_newlines(orig);
+        let num_newlines = count_newlines(orig);
+        let is_last = i == num_newlines;
+        let needs_new_comment_line = if self.style.is_block_comment() {
+            num_newlines > 0 || self.buffer_contains_comment()
+        } else {
+            self.buffer_contains_comment()
+        };
 
         if let Some(ref mut ib) = self.item_block {
             if ib.add_line(line) {
@@ -628,7 +667,12 @@ fn handle_line(
             self.is_prev_line_multi_line = false;
             self.fmt.shape = Shape::legacy(self.max_width, self.fmt_indent);
             let item_fmt = ib.create_string_format(&self.fmt);
-            self.result.push_str(&self.comment_line_separator);
+
+            // only push a comment_line_separator if we need to start a new comment line
+            if needs_new_comment_line {
+                self.result.push_str(&self.comment_line_separator);
+            }
+
             self.result.push_str(&ib.opener);
             match rewrite_string(
                 &ib.trimmed_block_as_string(),
@@ -842,7 +886,11 @@ fn trim_custom_comment_prefix(s: &str) -> String {
 /// Returns `true` if the given string MAY include URLs or alike.
 fn has_url(s: &str) -> bool {
     // This function may return false positive, but should get its job done in most cases.
-    s.contains("https://") || s.contains("http://") || s.contains("ftp://") || s.contains("file://")
+    s.contains("https://")
+        || s.contains("http://")
+        || s.contains("ftp://")
+        || s.contains("file://")
+        || REFERENCE_LINK_URL.is_match(s)
 }
 
 /// Given the span, rewrite the missing comment inside it if available.
index c5419d860c94312952f19dcaf26130e7cf1bfa35..5dbe532ac388fee287d48ee200e7d2bed65e8206 100644 (file)
@@ -405,6 +405,8 @@ mod test {
     use super::*;
     use std::str;
 
+    use rustfmt_config_proc_macro::{nightly_only_test, stable_only_test};
+
     #[allow(dead_code)]
     mod mock {
         use super::super::*;
@@ -525,21 +527,17 @@ fn test_empty_string_license_template_path() {
         assert!(config.license_template.is_none());
     }
 
+    #[nightly_only_test]
     #[test]
     fn test_valid_license_template_path() {
-        if !crate::is_nightly_channel!() {
-            return;
-        }
         let toml = r#"license_template_path = "tests/license-template/lt.txt""#;
         let config = Config::from_toml(toml, Path::new("")).unwrap();
         assert!(config.license_template.is_some());
     }
 
+    #[nightly_only_test]
     #[test]
     fn test_override_existing_license_with_no_license() {
-        if !crate::is_nightly_channel!() {
-            return;
-        }
         let toml = r#"license_template_path = "tests/license-template/lt.txt""#;
         let mut config = Config::from_toml(toml, Path::new("")).unwrap();
         assert!(config.license_template.is_some());
@@ -634,48 +632,42 @@ fn test_dump_default_config() {
         assert_eq!(&toml, &default_config);
     }
 
-    // FIXME(#2183): these tests cannot be run in parallel because they use env vars.
-    // #[test]
-    // fn test_as_not_nightly_channel() {
-    //     let mut config = Config::default();
-    //     assert_eq!(config.was_set().unstable_features(), false);
-    //     config.set().unstable_features(true);
-    //     assert_eq!(config.was_set().unstable_features(), false);
-    // }
-
-    // #[test]
-    // fn test_as_nightly_channel() {
-    //     let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from(""));
-    //     ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly");
-    //     let mut config = Config::default();
-    //     config.set().unstable_features(true);
-    //     assert_eq!(config.was_set().unstable_features(), false);
-    //     config.set().unstable_features(true);
-    //     assert_eq!(config.unstable_features(), true);
-    //     ::std::env::set_var("CFG_RELEASE_CHANNEL", v);
-    // }
-
-    // #[test]
-    // fn test_unstable_from_toml() {
-    //     let mut config = Config::from_toml("unstable_features = true").unwrap();
-    //     assert_eq!(config.was_set().unstable_features(), false);
-    //     let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from(""));
-    //     ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly");
-    //     config = Config::from_toml("unstable_features = true").unwrap();
-    //     assert_eq!(config.was_set().unstable_features(), true);
-    //     assert_eq!(config.unstable_features(), true);
-    //     ::std::env::set_var("CFG_RELEASE_CHANNEL", v);
-    // }
+    #[stable_only_test]
+    #[test]
+    fn test_as_not_nightly_channel() {
+        let mut config = Config::default();
+        assert_eq!(config.was_set().unstable_features(), false);
+        config.set().unstable_features(true);
+        assert_eq!(config.was_set().unstable_features(), false);
+    }
+
+    #[nightly_only_test]
+    #[test]
+    fn test_as_nightly_channel() {
+        let mut config = Config::default();
+        config.set().unstable_features(true);
+        // When we don't set the config from toml or command line options it
+        // doesn't get marked as set by the user.
+        assert_eq!(config.was_set().unstable_features(), false);
+        config.set().unstable_features(true);
+        assert_eq!(config.unstable_features(), true);
+    }
+
+    #[nightly_only_test]
+    #[test]
+    fn test_unstable_from_toml() {
+        let config = Config::from_toml("unstable_features = true", Path::new("")).unwrap();
+        assert_eq!(config.was_set().unstable_features(), true);
+        assert_eq!(config.unstable_features(), true);
+    }
 
     #[cfg(test)]
     mod deprecated_option_merge_imports {
         use super::*;
 
+        #[nightly_only_test]
         #[test]
         fn test_old_option_set() {
-            if !crate::is_nightly_channel!() {
-                return;
-            }
             let toml = r#"
                 unstable_features = true
                 merge_imports = true
@@ -684,11 +676,9 @@ fn test_old_option_set() {
             assert_eq!(config.imports_granularity(), ImportGranularity::Crate);
         }
 
+        #[nightly_only_test]
         #[test]
         fn test_both_set() {
-            if !crate::is_nightly_channel!() {
-                return;
-            }
             let toml = r#"
                 unstable_features = true
                 merge_imports = true
@@ -698,11 +688,9 @@ fn test_both_set() {
             assert_eq!(config.imports_granularity(), ImportGranularity::Preserve);
         }
 
+        #[nightly_only_test]
         #[test]
         fn test_new_overridden() {
-            if !crate::is_nightly_channel!() {
-                return;
-            }
             let toml = r#"
                 unstable_features = true
                 merge_imports = true
@@ -712,11 +700,9 @@ fn test_new_overridden() {
             assert_eq!(config.imports_granularity(), ImportGranularity::Preserve);
         }
 
+        #[nightly_only_test]
         #[test]
         fn test_old_overridden() {
-            if !crate::is_nightly_channel!() {
-                return;
-            }
             let toml = r#"
                 unstable_features = true
                 imports_granularity = "Module"
index 58942e442de05ba39ef3472bbb6b51850711ebfc..5fd86c1a4eadd2172394a0d871da875ff71c8e34 100644 (file)
@@ -196,9 +196,10 @@ pub(crate) fn format_expr(
                 capture, is_async, movability, fn_decl, body, expr.span, context, shape,
             )
         }
-        ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::MethodCall(..) => {
-            rewrite_chain(expr, context, shape)
-        }
+        ast::ExprKind::Try(..)
+        | ast::ExprKind::Field(..)
+        | ast::ExprKind::MethodCall(..)
+        | ast::ExprKind::Await(_) => rewrite_chain(expr, context, shape),
         ast::ExprKind::MacCall(ref mac) => {
             rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| {
                 wrap_str(
@@ -377,7 +378,6 @@ fn needs_space_after_range(rhs: &ast::Expr) -> bool {
                 ))
             }
         }
-        ast::ExprKind::Await(_) => rewrite_chain(expr, context, shape),
         ast::ExprKind::Underscore => Some("_".to_owned()),
         ast::ExprKind::Err => None,
     };
@@ -829,6 +829,7 @@ fn rewrite_pat_expr(
                 &format!("{}{}{}", matcher, pat_string, self.connector),
                 expr,
                 cond_shape,
+                &RhsAssignKind::Expr(&expr.kind, expr.span),
                 RhsTactics::Default,
                 comments_span,
                 true,
@@ -1839,6 +1840,34 @@ fn rewrite_unary_op(
     rewrite_unary_prefix(context, ast::UnOp::to_string(op), expr, shape)
 }
 
+pub(crate) enum RhsAssignKind<'ast> {
+    Expr(&'ast ast::ExprKind, Span),
+    Bounds,
+    Ty,
+}
+
+impl<'ast> RhsAssignKind<'ast> {
+    // TODO(calebcartwright)
+    // Preemptive addition for handling RHS with chains, not yet utilized.
+    // It may make more sense to construct the chain first and then check
+    // whether there are actually chain elements.
+    #[allow(dead_code)]
+    fn is_chain(&self) -> bool {
+        match self {
+            RhsAssignKind::Expr(kind, _) => {
+                matches!(
+                    kind,
+                    ast::ExprKind::Try(..)
+                        | ast::ExprKind::Field(..)
+                        | ast::ExprKind::MethodCall(..)
+                        | ast::ExprKind::Await(_)
+                )
+            }
+            _ => false,
+        }
+    }
+}
+
 fn rewrite_assignment(
     context: &RewriteContext<'_>,
     lhs: &ast::Expr,
@@ -1855,7 +1884,13 @@ fn rewrite_assignment(
     let lhs_shape = shape.sub_width(operator_str.len() + 1)?;
     let lhs_str = format!("{} {}", lhs.rewrite(context, lhs_shape)?, operator_str);
 
-    rewrite_assign_rhs(context, lhs_str, rhs, shape)
+    rewrite_assign_rhs(
+        context,
+        lhs_str,
+        rhs,
+        &RhsAssignKind::Expr(&rhs.kind, rhs.span),
+        shape,
+    )
 }
 
 /// Controls where to put the rhs.
@@ -1876,9 +1911,10 @@ pub(crate) fn rewrite_assign_rhs<S: Into<String>, R: Rewrite>(
     context: &RewriteContext<'_>,
     lhs: S,
     ex: &R,
+    rhs_kind: &RhsAssignKind<'_>,
     shape: Shape,
 ) -> Option<String> {
-    rewrite_assign_rhs_with(context, lhs, ex, shape, RhsTactics::Default)
+    rewrite_assign_rhs_with(context, lhs, ex, shape, rhs_kind, RhsTactics::Default)
 }
 
 pub(crate) fn rewrite_assign_rhs_expr<R: Rewrite>(
@@ -1886,6 +1922,7 @@ pub(crate) fn rewrite_assign_rhs_expr<R: Rewrite>(
     lhs: &str,
     ex: &R,
     shape: Shape,
+    rhs_kind: &RhsAssignKind<'_>,
     rhs_tactics: RhsTactics,
 ) -> Option<String> {
     let last_line_width = last_line_width(lhs).saturating_sub(if lhs.contains('\n') {
@@ -1910,6 +1947,7 @@ pub(crate) fn rewrite_assign_rhs_expr<R: Rewrite>(
         ex,
         orig_shape,
         ex.rewrite(context, orig_shape),
+        rhs_kind,
         rhs_tactics,
         has_rhs_comment,
     )
@@ -1920,10 +1958,11 @@ pub(crate) fn rewrite_assign_rhs_with<S: Into<String>, R: Rewrite>(
     lhs: S,
     ex: &R,
     shape: Shape,
+    rhs_kind: &RhsAssignKind<'_>,
     rhs_tactics: RhsTactics,
 ) -> Option<String> {
     let lhs = lhs.into();
-    let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_tactics)?;
+    let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_kind, rhs_tactics)?;
     Some(lhs + &rhs)
 }
 
@@ -1932,6 +1971,7 @@ pub(crate) fn rewrite_assign_rhs_with_comments<S: Into<String>, R: Rewrite>(
     lhs: S,
     ex: &R,
     shape: Shape,
+    rhs_kind: &RhsAssignKind<'_>,
     rhs_tactics: RhsTactics,
     between_span: Span,
     allow_extend: bool,
@@ -1943,7 +1983,7 @@ pub(crate) fn rewrite_assign_rhs_with_comments<S: Into<String>, R: Rewrite>(
     } else {
         shape
     };
-    let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_tactics)?;
+    let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_kind, rhs_tactics)?;
 
     if contains_comment {
         let rhs = rhs.trim_start();
@@ -1958,6 +1998,7 @@ fn choose_rhs<R: Rewrite>(
     expr: &R,
     shape: Shape,
     orig_rhs: Option<String>,
+    _rhs_kind: &RhsAssignKind<'_>,
     rhs_tactics: RhsTactics,
     has_rhs_comment: bool,
 ) -> Option<String> {
index d8974e12b8f5f4fe07742214ec1f28f2e41ddae2..7738eee0a76049b769a2aa547ccdc908483c16fd 100644 (file)
@@ -37,21 +37,17 @@ mod test {
     use crate::config::{Config, FileName};
     use crate::ignore_path::IgnorePathSet;
 
+    use rustfmt_config_proc_macro::nightly_only_test;
+
+    #[nightly_only_test]
     #[test]
     fn test_ignore_path_set() {
-        match option_env!("CFG_RELEASE_CHANNEL") {
-            // this test requires nightly
-            None | Some("nightly") => {
-                let config =
-                    Config::from_toml(r#"ignore = ["foo.rs", "bar_dir/*"]"#, Path::new(""))
-                        .unwrap();
-                let ignore_path_set = IgnorePathSet::from_ignore_list(&config.ignore()).unwrap();
-
-                assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/foo.rs"))));
-                assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("bar_dir/baz.rs"))));
-                assert!(!ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/bar.rs"))));
-            }
-            _ => (),
-        };
+        let config =
+            Config::from_toml(r#"ignore = ["foo.rs", "bar_dir/*"]"#, Path::new("")).unwrap();
+        let ignore_path_set = IgnorePathSet::from_ignore_list(&config.ignore()).unwrap();
+
+        assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/foo.rs"))));
+        assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("bar_dir/baz.rs"))));
+        assert!(!ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/bar.rs"))));
     }
 }
index 50121a8b6b50e7d506d07e9a14ed645579e2d094..f36bdba26e98e91b8aecad2a4e4d433e7651596d 100644 (file)
@@ -18,7 +18,7 @@
 use crate::config::{BraceStyle, Config, IndentStyle, Version};
 use crate::expr::{
     is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with,
-    rewrite_assign_rhs_with_comments, RhsTactics,
+    rewrite_assign_rhs_with_comments, RhsAssignKind, RhsTactics,
 };
 use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator};
 use crate::macros::{rewrite_macro, MacroPosition};
@@ -28,6 +28,7 @@
 use crate::source_map::{LineRangeUtils, SpanUtils};
 use crate::spanned::Spanned;
 use crate::stmt::Stmt;
+use crate::types::opaque_ty;
 use crate::utils::*;
 use crate::vertical::rewrite_with_alignment;
 use crate::visitor::FmtVisitor;
@@ -115,7 +116,13 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
             // 1 = trailing semicolon;
             let nested_shape = shape.sub_width(1)?;
 
-            result = rewrite_assign_rhs(context, result, init, nested_shape)?;
+            result = rewrite_assign_rhs(
+                context,
+                result,
+                init,
+                &RhsAssignKind::Expr(&init.kind, init.span),
+                nested_shape,
+            )?;
             // todo else
         }
 
@@ -563,11 +570,13 @@ fn format_variant(
 
         let variant_body = if let Some(ref expr) = field.disr_expr {
             let lhs = format!("{:1$} =", variant_body, pad_discrim_ident_to);
+            let ex = &*expr.value;
             rewrite_assign_rhs_with(
                 &context,
                 lhs,
-                &*expr.value,
+                ex,
                 shape,
+                &RhsAssignKind::Expr(&ex.kind, ex.span),
                 RhsTactics::AllowOverflow,
             )?
         } else {
@@ -579,6 +588,22 @@ fn format_variant(
 
     fn visit_impl_items(&mut self, items: &[ptr::P<ast::AssocItem>]) {
         if self.get_context().config.reorder_impl_items() {
+            type TyOpt = Option<ptr::P<ast::Ty>>;
+            use crate::ast::AssocItemKind::*;
+            let is_type = |ty: &TyOpt| opaque_ty(ty).is_none();
+            let is_opaque = |ty: &TyOpt| opaque_ty(ty).is_some();
+            let both_type = |l: &TyOpt, r: &TyOpt| is_type(l) && is_type(r);
+            let both_opaque = |l: &TyOpt, r: &TyOpt| is_opaque(l) && is_opaque(r);
+            let need_empty_line = |a: &ast::AssocItemKind, b: &ast::AssocItemKind| match (a, b) {
+                (TyAlias(lty), TyAlias(rty))
+                    if both_type(&lty.ty, &rty.ty) || both_opaque(&lty.ty, &rty.ty) =>
+                {
+                    false
+                }
+                (Const(..), Const(..)) => false,
+                _ => true,
+            };
+
             // Create visitor for each items, then reorder them.
             let mut buffer = vec![];
             for item in items {
@@ -587,50 +612,6 @@ fn visit_impl_items(&mut self, items: &[ptr::P<ast::AssocItem>]) {
                 self.buffer.clear();
             }
 
-            fn is_type(ty: &Option<rustc_ast::ptr::P<ast::Ty>>) -> bool {
-                if let Some(lty) = ty {
-                    if let ast::TyKind::ImplTrait(..) = lty.kind {
-                        return false;
-                    }
-                }
-                true
-            }
-
-            fn is_opaque(ty: &Option<rustc_ast::ptr::P<ast::Ty>>) -> bool {
-                !is_type(ty)
-            }
-
-            fn both_type(
-                a: &Option<rustc_ast::ptr::P<ast::Ty>>,
-                b: &Option<rustc_ast::ptr::P<ast::Ty>>,
-            ) -> bool {
-                is_type(a) && is_type(b)
-            }
-
-            fn both_opaque(
-                a: &Option<rustc_ast::ptr::P<ast::Ty>>,
-                b: &Option<rustc_ast::ptr::P<ast::Ty>>,
-            ) -> bool {
-                is_opaque(a) && is_opaque(b)
-            }
-
-            // In rustc-ap-v638 the `OpaqueTy` AssocItemKind variant was removed but
-            // we still need to differentiate to maintain sorting order.
-
-            // type -> opaque -> const -> macro -> method
-            use crate::ast::AssocItemKind::*;
-            fn need_empty_line(a: &ast::AssocItemKind, b: &ast::AssocItemKind) -> bool {
-                match (a, b) {
-                    (TyAlias(lty), TyAlias(rty))
-                        if both_type(&lty.ty, &rty.ty) || both_opaque(&lty.ty, &rty.ty) =>
-                    {
-                        false
-                    }
-                    (Const(..), Const(..)) => false,
-                    _ => true,
-                }
-            }
-
             buffer.sort_by(|(_, a), (_, b)| match (&a.kind, &b.kind) {
                 (TyAlias(lty), TyAlias(rty))
                     if both_type(&lty.ty, &rty.ty) || both_opaque(&lty.ty, &rty.ty) =>
@@ -676,136 +657,133 @@ fn need_empty_line(a: &ast::AssocItemKind, b: &ast::AssocItemKind) -> bool {
 pub(crate) fn format_impl(
     context: &RewriteContext<'_>,
     item: &ast::Item,
+    iimpl: &ast::Impl,
     offset: Indent,
 ) -> Option<String> {
-    if let ast::ItemKind::Impl(impl_kind) = &item.kind {
-        let ast::Impl {
-            ref generics,
-            ref self_ty,
-            ref items,
-            ..
-        } = **impl_kind;
-        let mut result = String::with_capacity(128);
-        let ref_and_type = format_impl_ref_and_type(context, item, offset)?;
-        let sep = offset.to_string_with_newline(context.config);
-        result.push_str(&ref_and_type);
+    let ast::Impl {
+        generics,
+        self_ty,
+        items,
+        ..
+    } = iimpl;
+    let mut result = String::with_capacity(128);
+    let ref_and_type = format_impl_ref_and_type(context, item, iimpl, offset)?;
+    let sep = offset.to_string_with_newline(context.config);
+    result.push_str(&ref_and_type);
 
-        let where_budget = if result.contains('\n') {
-            context.config.max_width()
-        } else {
-            context.budget(last_line_width(&result))
-        };
+    let where_budget = if result.contains('\n') {
+        context.config.max_width()
+    } else {
+        context.budget(last_line_width(&result))
+    };
 
-        let mut option = WhereClauseOption::snuggled(&ref_and_type);
-        let snippet = context.snippet(item.span);
-        let open_pos = snippet.find_uncommented("{")? + 1;
-        if !contains_comment(&snippet[open_pos..])
-            && items.is_empty()
-            && generics.where_clause.predicates.len() == 1
-            && !result.contains('\n')
-        {
-            option.suppress_comma();
-            option.snuggle();
-            option.allow_single_line();
-        }
+    let mut option = WhereClauseOption::snuggled(&ref_and_type);
+    let snippet = context.snippet(item.span);
+    let open_pos = snippet.find_uncommented("{")? + 1;
+    if !contains_comment(&snippet[open_pos..])
+        && items.is_empty()
+        && generics.where_clause.predicates.len() == 1
+        && !result.contains('\n')
+    {
+        option.suppress_comma();
+        option.snuggle();
+        option.allow_single_line();
+    }
 
-        let missing_span = mk_sp(self_ty.span.hi(), item.span.hi());
-        let where_span_end = context.snippet_provider.opt_span_before(missing_span, "{");
-        let where_clause_str = rewrite_where_clause(
-            context,
-            &generics.where_clause,
-            context.config.brace_style(),
-            Shape::legacy(where_budget, offset.block_only()),
-            false,
-            "{",
-            where_span_end,
-            self_ty.span.hi(),
-            option,
-        )?;
+    let missing_span = mk_sp(self_ty.span.hi(), item.span.hi());
+    let where_span_end = context.snippet_provider.opt_span_before(missing_span, "{");
+    let where_clause_str = rewrite_where_clause(
+        context,
+        &generics.where_clause,
+        context.config.brace_style(),
+        Shape::legacy(where_budget, offset.block_only()),
+        false,
+        "{",
+        where_span_end,
+        self_ty.span.hi(),
+        option,
+    )?;
 
-        // If there is no where-clause, we may have missing comments between the trait name and
-        // the opening brace.
-        if generics.where_clause.predicates.is_empty() {
-            if let Some(hi) = where_span_end {
-                match recover_missing_comment_in_span(
-                    mk_sp(self_ty.span.hi(), hi),
-                    Shape::indented(offset, context.config),
-                    context,
-                    last_line_width(&result),
-                ) {
-                    Some(ref missing_comment) if !missing_comment.is_empty() => {
-                        result.push_str(missing_comment);
-                    }
-                    _ => (),
+    // If there is no where-clause, we may have missing comments between the trait name and
+    // the opening brace.
+    if generics.where_clause.predicates.is_empty() {
+        if let Some(hi) = where_span_end {
+            match recover_missing_comment_in_span(
+                mk_sp(self_ty.span.hi(), hi),
+                Shape::indented(offset, context.config),
+                context,
+                last_line_width(&result),
+            ) {
+                Some(ref missing_comment) if !missing_comment.is_empty() => {
+                    result.push_str(missing_comment);
                 }
+                _ => (),
             }
         }
+    }
 
-        if is_impl_single_line(context, items.as_slice(), &result, &where_clause_str, item)? {
-            result.push_str(&where_clause_str);
-            if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) {
-                // if the where_clause contains extra comments AND
-                // there is only one where-clause predicate
-                // recover the suppressed comma in single line where_clause formatting
-                if generics.where_clause.predicates.len() == 1 {
-                    result.push(',');
-                }
-                result.push_str(&format!("{}{{{}}}", sep, sep));
-            } else {
-                result.push_str(" {}");
+    if is_impl_single_line(context, items.as_slice(), &result, &where_clause_str, item)? {
+        result.push_str(&where_clause_str);
+        if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) {
+            // if the where_clause contains extra comments AND
+            // there is only one where-clause predicate
+            // recover the suppressed comma in single line where_clause formatting
+            if generics.where_clause.predicates.len() == 1 {
+                result.push(',');
             }
-            return Some(result);
+            result.push_str(&format!("{}{{{}}}", sep, sep));
+        } else {
+            result.push_str(" {}");
         }
+        return Some(result);
+    }
 
-        result.push_str(&where_clause_str);
+    result.push_str(&where_clause_str);
 
-        let need_newline = last_line_contains_single_line_comment(&result) || result.contains('\n');
-        match context.config.brace_style() {
-            _ if need_newline => result.push_str(&sep),
-            BraceStyle::AlwaysNextLine => result.push_str(&sep),
-            BraceStyle::PreferSameLine => result.push(' '),
-            BraceStyle::SameLineWhere => {
-                if !where_clause_str.is_empty() {
-                    result.push_str(&sep);
-                } else {
-                    result.push(' ');
-                }
+    let need_newline = last_line_contains_single_line_comment(&result) || result.contains('\n');
+    match context.config.brace_style() {
+        _ if need_newline => result.push_str(&sep),
+        BraceStyle::AlwaysNextLine => result.push_str(&sep),
+        BraceStyle::PreferSameLine => result.push(' '),
+        BraceStyle::SameLineWhere => {
+            if !where_clause_str.is_empty() {
+                result.push_str(&sep);
+            } else {
+                result.push(' ');
             }
         }
+    }
 
-        result.push('{');
-        // this is an impl body snippet(impl SampleImpl { /* here */ })
-        let lo = max(self_ty.span.hi(), generics.where_clause.span.hi());
-        let snippet = context.snippet(mk_sp(lo, item.span.hi()));
-        let open_pos = snippet.find_uncommented("{")? + 1;
+    result.push('{');
+    // this is an impl body snippet(impl SampleImpl { /* here */ })
+    let lo = max(self_ty.span.hi(), generics.where_clause.span.hi());
+    let snippet = context.snippet(mk_sp(lo, item.span.hi()));
+    let open_pos = snippet.find_uncommented("{")? + 1;
 
-        if !items.is_empty() || contains_comment(&snippet[open_pos..]) {
-            let mut visitor = FmtVisitor::from_context(context);
-            let item_indent = offset.block_only().block_indent(context.config);
-            visitor.block_indent = item_indent;
-            visitor.last_pos = lo + BytePos(open_pos as u32);
+    if !items.is_empty() || contains_comment(&snippet[open_pos..]) {
+        let mut visitor = FmtVisitor::from_context(context);
+        let item_indent = offset.block_only().block_indent(context.config);
+        visitor.block_indent = item_indent;
+        visitor.last_pos = lo + BytePos(open_pos as u32);
 
-            visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner);
-            visitor.visit_impl_items(items);
+        visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner);
+        visitor.visit_impl_items(items);
 
-            visitor.format_missing(item.span.hi() - BytePos(1));
+        visitor.format_missing(item.span.hi() - BytePos(1));
 
-            let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config);
-            let outer_indent_str = offset.block_only().to_string_with_newline(context.config);
+        let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config);
+        let outer_indent_str = offset.block_only().to_string_with_newline(context.config);
 
-            result.push_str(&inner_indent_str);
-            result.push_str(visitor.buffer.trim());
-            result.push_str(&outer_indent_str);
-        } else if need_newline || !context.config.empty_item_single_line() {
-            result.push_str(&sep);
-        }
+        result.push_str(&inner_indent_str);
+        result.push_str(visitor.buffer.trim());
+        result.push_str(&outer_indent_str);
+    } else if need_newline || !context.config.empty_item_single_line() {
+        result.push_str(&sep);
+    }
 
-        result.push('}');
+    result.push('}');
 
-        Some(result)
-    } else {
-        unreachable!();
-    }
+    Some(result)
 }
 
 fn is_impl_single_line(
@@ -830,111 +808,106 @@ fn is_impl_single_line(
 fn format_impl_ref_and_type(
     context: &RewriteContext<'_>,
     item: &ast::Item,
+    iimpl: &ast::Impl,
     offset: Indent,
 ) -> Option<String> {
-    if let ast::ItemKind::Impl(impl_kind) = &item.kind {
-        let ast::Impl {
-            unsafety,
-            polarity,
-            defaultness,
-            constness,
-            ref generics,
-            of_trait: ref trait_ref,
-            ref self_ty,
-            ..
-        } = **impl_kind;
-        let mut result = String::with_capacity(128);
+    let ast::Impl {
+        unsafety,
+        polarity,
+        defaultness,
+        constness,
+        ref generics,
+        of_trait: ref trait_ref,
+        ref self_ty,
+        ..
+    } = *iimpl;
+    let mut result = String::with_capacity(128);
 
-        result.push_str(&format_visibility(context, &item.vis));
-        result.push_str(format_defaultness(defaultness));
-        result.push_str(format_unsafety(unsafety));
+    result.push_str(&format_visibility(context, &item.vis));
+    result.push_str(format_defaultness(defaultness));
+    result.push_str(format_unsafety(unsafety));
 
-        let shape = if context.config.version() == Version::Two {
-            Shape::indented(offset + last_line_width(&result), context.config)
-        } else {
-            generics_shape_from_config(
-                context.config,
-                Shape::indented(offset + last_line_width(&result), context.config),
-                0,
-            )?
-        };
-        let generics_str = rewrite_generics(context, "impl", generics, shape)?;
-        result.push_str(&generics_str);
-        result.push_str(format_constness_right(constness));
+    let shape = if context.config.version() == Version::Two {
+        Shape::indented(offset + last_line_width(&result), context.config)
+    } else {
+        generics_shape_from_config(
+            context.config,
+            Shape::indented(offset + last_line_width(&result), context.config),
+            0,
+        )?
+    };
+    let generics_str = rewrite_generics(context, "impl", generics, shape)?;
+    result.push_str(&generics_str);
+    result.push_str(format_constness_right(constness));
 
-        let polarity_str = match polarity {
-            ast::ImplPolarity::Negative(_) => "!",
-            ast::ImplPolarity::Positive => "",
-        };
+    let polarity_str = match polarity {
+        ast::ImplPolarity::Negative(_) => "!",
+        ast::ImplPolarity::Positive => "",
+    };
 
-        let polarity_overhead;
-        let trait_ref_overhead;
-        if let Some(ref trait_ref) = *trait_ref {
-            let result_len = last_line_width(&result);
-            result.push_str(&rewrite_trait_ref(
-                context,
-                trait_ref,
-                offset,
-                polarity_str,
-                result_len,
-            )?);
-            polarity_overhead = 0; // already written
-            trait_ref_overhead = " for".len();
-        } else {
-            polarity_overhead = polarity_str.len();
-            trait_ref_overhead = 0;
-        }
+    let polarity_overhead;
+    let trait_ref_overhead;
+    if let Some(ref trait_ref) = *trait_ref {
+        let result_len = last_line_width(&result);
+        result.push_str(&rewrite_trait_ref(
+            context,
+            trait_ref,
+            offset,
+            polarity_str,
+            result_len,
+        )?);
+        polarity_overhead = 0; // already written
+        trait_ref_overhead = " for".len();
+    } else {
+        polarity_overhead = polarity_str.len();
+        trait_ref_overhead = 0;
+    }
 
-        // Try to put the self type in a single line.
-        let curly_brace_overhead = if generics.where_clause.predicates.is_empty() {
-            // If there is no where-clause adapt budget for type formatting to take space and curly
-            // brace into account.
-            match context.config.brace_style() {
-                BraceStyle::AlwaysNextLine => 0,
-                _ => 2,
-            }
-        } else {
-            0
-        };
-        let used_space = last_line_width(&result)
-            + polarity_overhead
-            + trait_ref_overhead
-            + curly_brace_overhead;
-        // 1 = space before the type.
-        let budget = context.budget(used_space + 1);
-        if let Some(self_ty_str) = self_ty.rewrite(context, Shape::legacy(budget, offset)) {
-            if !self_ty_str.contains('\n') {
-                if trait_ref.is_some() {
-                    result.push_str(" for ");
-                } else {
-                    result.push(' ');
-                    result.push_str(polarity_str);
-                }
-                result.push_str(&self_ty_str);
-                return Some(result);
+    // Try to put the self type in a single line.
+    let curly_brace_overhead = if generics.where_clause.predicates.is_empty() {
+        // If there is no where-clause adapt budget for type formatting to take space and curly
+        // brace into account.
+        match context.config.brace_style() {
+            BraceStyle::AlwaysNextLine => 0,
+            _ => 2,
+        }
+    } else {
+        0
+    };
+    let used_space =
+        last_line_width(&result) + polarity_overhead + trait_ref_overhead + curly_brace_overhead;
+    // 1 = space before the type.
+    let budget = context.budget(used_space + 1);
+    if let Some(self_ty_str) = self_ty.rewrite(context, Shape::legacy(budget, offset)) {
+        if !self_ty_str.contains('\n') {
+            if trait_ref.is_some() {
+                result.push_str(" for ");
+            } else {
+                result.push(' ');
+                result.push_str(polarity_str);
             }
+            result.push_str(&self_ty_str);
+            return Some(result);
         }
+    }
 
-        // Couldn't fit the self type on a single line, put it on a new line.
-        result.push('\n');
-        // Add indentation of one additional tab.
-        let new_line_offset = offset.block_indent(context.config);
-        result.push_str(&new_line_offset.to_string(context.config));
-        if trait_ref.is_some() {
-            result.push_str("for ");
-        } else {
-            result.push_str(polarity_str);
-        }
-        let budget = context.budget(last_line_width(&result) + polarity_overhead);
-        let type_offset = match context.config.indent_style() {
-            IndentStyle::Visual => new_line_offset + trait_ref_overhead,
-            IndentStyle::Block => new_line_offset,
-        };
-        result.push_str(&*self_ty.rewrite(context, Shape::legacy(budget, type_offset))?);
-        Some(result)
+    // Couldn't fit the self type on a single line, put it on a new line.
+    result.push('\n');
+    // Add indentation of one additional tab.
+    let new_line_offset = offset.block_indent(context.config);
+    result.push_str(&new_line_offset.to_string(context.config));
+    if trait_ref.is_some() {
+        result.push_str("for ");
     } else {
-        unreachable!();
+        result.push_str(polarity_str);
     }
+    let budget = context.budget(last_line_width(&result) + polarity_overhead);
+    let type_offset = match context.config.indent_style() {
+        IndentStyle::Visual => new_line_offset + trait_ref_overhead,
+        IndentStyle::Block => new_line_offset,
+    };
+    result.push_str(&*self_ty.rewrite(context, Shape::legacy(budget, type_offset))?);
+    Some(result)
 }
 
 fn rewrite_trait_ref(
@@ -1068,6 +1041,7 @@ pub(crate) fn format_trait(
                 result + ":",
                 bounds,
                 shape,
+                &RhsAssignKind::Bounds,
                 RhsTactics::ForceNextLineWithoutIndent,
             )?;
         }
@@ -1248,7 +1222,14 @@ pub(crate) fn format_trait_alias(
         generic_bounds,
         generics,
     };
-    rewrite_assign_rhs(context, lhs, &trait_alias_bounds, shape.sub_width(1)?).map(|s| s + ";")
+    rewrite_assign_rhs(
+        context,
+        lhs,
+        &trait_alias_bounds,
+        &RhsAssignKind::Bounds,
+        shape.sub_width(1)?,
+    )
+    .map(|s| s + ";")
 }
 
 fn format_unit_struct(
@@ -1541,43 +1522,38 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
         ref bounds,
         ref ty,
     } = *ty_alias_kind;
-    let ty_opt = ty.as_ref().map(|t| &**t);
+    let ty_opt = ty.as_ref();
     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);
-
+    let op_ty = opaque_ty(ty);
     // 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)
+    match (visitor_kind, &op_ty) {
+        (Item(_) | AssocTraitItem(_) | ForeignItem(_), Some(ref op_bounds)) => {
+            let op = OpaqueType { bounds: op_bounds };
+            rewrite_ty(rw_info, Some(bounds), Some(&op), vis)
+        }
+        (Item(_) | AssocTraitItem(_) | ForeignItem(_), None) => {
+            rewrite_ty(rw_info, Some(bounds), ty_opt, 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)
+            let result = if let Some(ref op_bounds) = op_ty {
+                let op = OpaqueType { bounds: op_bounds };
+                rewrite_ty(rw_info, Some(bounds), Some(&op), &DEFAULT_VISIBILITY)
             } else {
-                rewrite_ty(rw_info, None, ty.as_ref(), vis)
+                rewrite_ty(rw_info, Some(bounds), ty_opt, vis)
             }?;
             match defaultness {
                 ast::Defaultness::Default(..) => Some(format!("default {}", result)),
                 _ => Some(result),
             }
         }
-        (AssocTraitItem(_), _) | (ForeignItem(_), _) => {
-            rewrite_ty(rw_info, Some(bounds), ty.as_ref(), vis)
-        }
     }
 }
 
@@ -1670,7 +1646,7 @@ fn rewrite_ty<R: Rewrite>(
 
         // 1 = `;`
         let shape = Shape::indented(indent, context.config).sub_width(1)?;
-        rewrite_assign_rhs(context, lhs, &*ty, shape).map(|s| s + ";")
+        rewrite_assign_rhs(context, lhs, &*ty, &RhsAssignKind::Ty, shape).map(|s| s + ";")
     } else {
         Some(format!("{};", result))
     }
@@ -1760,7 +1736,7 @@ pub(crate) fn rewrite_struct_field(
 
     let is_prefix_empty = prefix.is_empty();
     // We must use multiline. We are going to put attributes and a field on different lines.
-    let field_str = rewrite_assign_rhs(context, prefix, &*field.ty, shape)?;
+    let field_str = rewrite_assign_rhs(context, prefix, &*field.ty, &RhsAssignKind::Ty, shape)?;
     // Remove a leading white-space from `rewrite_assign_rhs()` when rewriting a tuple struct.
     let field_str = if is_prefix_empty {
         field_str.trim_start()
@@ -1890,6 +1866,7 @@ fn rewrite_static(
             &lhs,
             &**expr,
             Shape::legacy(remaining_width, offset.block_only()),
+            &RhsAssignKind::Expr(&expr.kind, expr.span),
             RhsTactics::Default,
             comments_span,
             true,
@@ -1900,6 +1877,12 @@ fn rewrite_static(
         Some(format!("{}{};", prefix, ty_str))
     }
 }
+
+// FIXME(calebcartwright) - This is a hack around a bug in the handling of TyKind::ImplTrait.
+// This should be removed once that bug is resolved, with the type alias formatting using the
+// defined Ty for the RHS directly.
+// https://github.com/rust-lang/rustfmt/issues/4373
+// https://github.com/rust-lang/rustfmt/issues/5027
 struct OpaqueType<'a> {
     bounds: &'a ast::GenericBounds,
 }
@@ -2236,18 +2219,10 @@ fn rewrite_fn_base(
         result.push_str(&param_indent.to_string_with_newline(context.config));
     }
 
-    // Skip `pub(crate)`.
-    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
-        .params
-        .last()
-        .map_or(lo_after_visibility, |param| param.span().hi());
     let params_end = if fd.inputs.is_empty() {
         context
             .snippet_provider
-            .span_after(mk_sp(params_start, span.hi()), ")")
+            .span_after(mk_sp(fn_sig.generics.span.hi(), span.hi()), ")")
     } else {
         let last_span = mk_sp(fd.inputs[fd.inputs.len() - 1].span().hi(), span.hi());
         context.snippet_provider.span_after(last_span, ")")
@@ -2255,7 +2230,7 @@ fn rewrite_fn_base(
     let params_span = mk_sp(
         context
             .snippet_provider
-            .span_after(mk_sp(params_start, span.hi()), "("),
+            .span_after(mk_sp(fn_sig.generics.span.hi(), span.hi()), "("),
         params_end,
     );
     let param_str = rewrite_params(
@@ -3181,7 +3156,14 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                     rewrite_ident(context, self.ident)
                 );
                 // 1 = ;
-                rewrite_assign_rhs(context, prefix, &**ty, shape.sub_width(1)?).map(|s| s + ";")
+                rewrite_assign_rhs(
+                    context,
+                    prefix,
+                    &**ty,
+                    &RhsAssignKind::Ty,
+                    shape.sub_width(1)?,
+                )
+                .map(|s| s + ";")
             }
             ast::ForeignItemKind::TyAlias(ref ty_alias) => {
                 let (kind, span) = (&ItemVisitorKind::ForeignItem(&self), self.span);
index d341ec8e6b0e7d15f428cc3e91527635129f9687..3515dd172510c91e6bc109c7378ab8cccd82f0b2 100644 (file)
@@ -444,10 +444,15 @@ pub(crate) fn write_list<I, T>(items: I, formatting: &ListFormatting<'_>) -> Opt
                 let offset = formatting.shape.indent + overhead;
                 let comment_shape = Shape::legacy(width, offset);
 
-                // Use block-style only for the last item or multiline comments.
-                let block_style = !formatting.ends_with_newline && last
-                    || comment.trim().contains('\n')
-                    || comment.trim().len() > width;
+                let block_style = if !formatting.ends_with_newline && last {
+                    true
+                } else if starts_with_newline(comment) {
+                    false
+                } else if comment.trim().contains('\n') || comment.trim().len() > width {
+                    true
+                } else {
+                    false
+                };
 
                 rewrite_comment(
                     comment.trim_start(),
index ef747638e33ec83459e4b9f9fe02d052e41c4812..a52568be9eac44298a0f3cf40a1ef8b7e576081e 100644 (file)
@@ -27,7 +27,7 @@
     contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses,
 };
 use crate::config::lists::*;
-use crate::expr::rewrite_array;
+use crate::expr::{rewrite_array, rewrite_assign_rhs, RhsAssignKind};
 use crate::lists::{itemize_list, write_list, ListFormatting};
 use crate::overflow;
 use crate::rewrite::{Rewrite, RewriteContext};
@@ -1468,10 +1468,11 @@ macro_rules! parse_or {
             id,
             ty.rewrite(context, nested_shape)?
         ));
-        result.push_str(&crate::expr::rewrite_assign_rhs(
+        result.push_str(&rewrite_assign_rhs(
             context,
             stmt,
             &*expr,
+            &RhsAssignKind::Expr(&expr.kind, expr.span),
             nested_shape.sub_width(1)?,
         )?);
         result.push(';');
index cdb4893d443b9b381cde8e4c1d284aee5154ddd4..dd7c7352686e620eda97ad4411bc43da48aeac84 100644 (file)
@@ -286,10 +286,11 @@ fn lookup_line_range(&self, span: Span) -> LineRange {
 mod tests {
     use super::*;
 
+    use rustfmt_config_proc_macro::nightly_only_test;
+
     mod emitter {
         use super::*;
         use crate::config::IgnoreList;
-        use crate::is_nightly_channel;
         use crate::utils::mk_sp;
         use rustc_span::{FileName as SourceMapFileName, MultiSpan, RealFileName, DUMMY_SP};
         use std::path::PathBuf;
@@ -371,11 +372,9 @@ fn handles_fatal_parse_error_in_ignored_file() {
             assert_eq!(can_reset_errors.load(Ordering::Acquire), false);
         }
 
+        #[nightly_only_test]
         #[test]
         fn handles_recoverable_parse_error_in_ignored_file() {
-            if !is_nightly_channel!() {
-                return;
-            }
             let num_emitted_errors = Lrc::new(AtomicU32::new(0));
             let can_reset_errors = Lrc::new(AtomicBool::new(false));
             let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#);
@@ -398,11 +397,9 @@ fn handles_recoverable_parse_error_in_ignored_file() {
             assert_eq!(can_reset_errors.load(Ordering::Acquire), true);
         }
 
+        #[nightly_only_test]
         #[test]
         fn handles_recoverable_parse_error_in_non_ignored_file() {
-            if !is_nightly_channel!() {
-                return;
-            }
             let num_emitted_errors = Lrc::new(AtomicU32::new(0));
             let can_reset_errors = Lrc::new(AtomicBool::new(false));
             let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty()));
@@ -424,11 +421,9 @@ fn handles_recoverable_parse_error_in_non_ignored_file() {
             assert_eq!(can_reset_errors.load(Ordering::Acquire), false);
         }
 
+        #[nightly_only_test]
         #[test]
         fn handles_mix_of_recoverable_parse_error() {
-            if !is_nightly_channel!() {
-                return;
-            }
             let num_emitted_errors = Lrc::new(AtomicU32::new(0));
             let can_reset_errors = Lrc::new(AtomicBool::new(false));
             let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty()));
index e2620508c340bad91699e8ebd90b36f2a80f6049..cceb28dfea6d7e82e06d3051983cc0a377fca9a2 100644 (file)
@@ -15,6 +15,8 @@
 use crate::source_file;
 use crate::{is_nightly_channel, FormatReport, FormatReportFormatterBuilder, Input, Session};
 
+use rustfmt_config_proc_macro::nightly_only_test;
+
 mod configuration_snippet;
 mod mod_resolver;
 mod parser;
@@ -307,14 +309,11 @@ fn assert_output(source: &Path, expected_filename: &Path) {
 
 // Idempotence tests. Files in tests/target are checked to be unaltered by
 // rustfmt.
+#[nightly_only_test]
 #[test]
 fn idempotence_tests() {
     init_log();
     run_test_with(&TestSetting::default(), || {
-        // these tests require nightly
-        if !is_nightly_channel!() {
-            return;
-        }
         // Get all files in the tests/target directory.
         let files = get_test_files(Path::new("tests/target"), true);
         let (_reports, count, fails) = check_files(files, &None);
@@ -332,13 +331,11 @@ fn idempotence_tests() {
 
 // Run rustfmt on itself. This operation must be idempotent. We also check that
 // no warnings are emitted.
+// Issue-3443: these tests require nightly
+#[nightly_only_test]
 #[test]
 fn self_tests() {
     init_log();
-    // Issue-3443: these tests require nightly
-    if !is_nightly_channel!() {
-        return;
-    }
     let mut files = get_test_files(Path::new("tests"), false);
     let bin_directories = vec!["cargo-fmt", "git-rustfmt", "bin", "format-diff"];
     for dir in bin_directories {
index 9ea90c5e46dd87104522dd220558e7127ade7cdb..88f5dc432451010436694b49a355e68fb9f27b98 100644 (file)
@@ -2,6 +2,7 @@
 use std::ops::Deref;
 
 use rustc_ast::ast::{self, FnRetTy, Mutability};
+use rustc_ast::ptr;
 use rustc_span::{symbol::kw, BytePos, Pos, Span};
 
 use crate::comment::{combine_strs_with_missing_comments, contains_comment};
@@ -9,6 +10,7 @@
 use crate::config::{IndentStyle, TypeDensity, Version};
 use crate::expr::{
     format_expr, rewrite_assign_rhs, rewrite_call, rewrite_tuple, rewrite_unary_prefix, ExprType,
+    RhsAssignKind,
 };
 use crate::lists::{
     definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator,
@@ -429,7 +431,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                     format!("{}{}", type_str, colon)
                 };
 
-                rewrite_assign_rhs(context, lhs, bounds, shape)?
+                rewrite_assign_rhs(context, lhs, bounds, &RhsAssignKind::Bounds, shape)?
             }
             ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
                 ref lifetime,
@@ -442,7 +444,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                 ..
             }) => {
                 let lhs_ty_str = lhs_ty.rewrite(context, shape).map(|lhs| lhs + " =")?;
-                rewrite_assign_rhs(context, lhs_ty_str, &**rhs_ty, shape)?
+                rewrite_assign_rhs(context, lhs_ty_str, &**rhs_ty, &RhsAssignKind::Ty, shape)?
             }
         };
 
@@ -1031,6 +1033,13 @@ fn join_bounds_inner(
     }
 }
 
+pub(crate) fn opaque_ty(ty: &Option<ptr::P<ast::Ty>>) -> Option<&ast::GenericBounds> {
+    ty.as_ref().and_then(|t| match &t.kind {
+        ast::TyKind::ImplTrait(_, bounds) => Some(bounds),
+        _ => None,
+    })
+}
+
 pub(crate) fn can_be_overflowed_type(
     context: &RewriteContext<'_>,
     ty: &ast::Ty,
index 527042d098a1c61f7d6252438ea4b97ba741c5d7..e4a7be742abcbace1602fad9b5b45593b2dd71ad 100644 (file)
@@ -485,9 +485,9 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) {
         if should_visit_node_again {
             match item.kind {
                 ast::ItemKind::Use(ref tree) => self.format_import(item, tree),
-                ast::ItemKind::Impl { .. } => {
+                ast::ItemKind::Impl(ref iimpl) => {
                     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, iimpl, block_indent));
                     self.push_rewrite(item.span, rw);
                 }
                 ast::ItemKind::Trait(..) => {
diff --git a/src/tools/rustfmt/tests/source/comments-in-lists/wrap-comments-not-normalized.rs b/src/tools/rustfmt/tests/source/comments-in-lists/wrap-comments-not-normalized.rs
new file mode 100644 (file)
index 0000000..b96c028
--- /dev/null
@@ -0,0 +1,129 @@
+// rustfmt-wrap_comments: true
+
+// https://github.com/rust-lang/rustfmt/issues/4909
+pub enum E {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant1,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant2,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub enum E2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+pub enum E3 {
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    Variant1,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    Variant2,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+
+}
+
+pub struct S {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    some_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    last_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S3 {
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    some_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    last_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+}
+
+fn foo(
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    a: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    b: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn foo2(// Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn foo3(
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    a: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    b: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+
+) -> usize {
+    5
+}
+
+fn main() {
+    let v = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        1,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        2,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    let v2: Vec<i32> = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    let v3 = vec![
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+        1,
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+        2,
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    ];
+
+    // https://github.com/rust-lang/rustfmt/issues/4430
+    match a {
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        b => c,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        d => e,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    }
+
+    match a {
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+        b => c,
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+        d => e,
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    }
+}
diff --git a/src/tools/rustfmt/tests/source/comments-in-lists/wrap-comments-true.rs b/src/tools/rustfmt/tests/source/comments-in-lists/wrap-comments-true.rs
new file mode 100644 (file)
index 0000000..360b838
--- /dev/null
@@ -0,0 +1,130 @@
+// rustfmt-normalize_comments: true
+// rustfmt-wrap_comments: true
+
+// https://github.com/rust-lang/rustfmt/issues/4909
+pub enum E {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant1,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant2,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub enum E2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+pub enum E3 {
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    Variant1,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    Variant2,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+
+}
+
+pub struct S {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    some_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    last_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S3 {
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    some_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    last_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+}
+
+fn foo(
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    a: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    b: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn foo2(// Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn foo3(
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    a: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    b: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+
+) -> usize {
+    5
+}
+
+fn main() {
+    let v = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        1,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        2,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    let v2: Vec<i32> = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    let v3 = vec![
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+        1,
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+        2,
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    ];
+
+    // https://github.com/rust-lang/rustfmt/issues/4430
+    match a {
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        b => c,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        d => e,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    }
+
+    match a {
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+        b => c,
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+        d => e,
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    }
+}
diff --git a/src/tools/rustfmt/tests/source/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs b/src/tools/rustfmt/tests/source/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs
new file mode 100644 (file)
index 0000000..09f68ca
--- /dev/null
@@ -0,0 +1,33 @@
+// rustfmt-wrap_comments: true
+
+fn main() {
+    {
+        {
+            {
+                {
+                    {
+                        {
+                            {
+                                {
+                                    {
+                                        {
+                                            {
+                                                // - aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc
+
+                                                // * aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc
+
+                                                /* - aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc */
+
+                                                /* * aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc */
+                                            };
+                                        };
+                                    };
+                                };
+                            };
+                        };
+                    };
+                };
+            };
+        };
+    };
+}
diff --git a/src/tools/rustfmt/tests/source/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs b/src/tools/rustfmt/tests/source/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs
new file mode 100644 (file)
index 0000000..75f7480
--- /dev/null
@@ -0,0 +1,19 @@
+// rustfmt-wrap_comments: true
+
+//
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+
+//
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+
+/*
+ * - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+/*
+ * - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+
+/*
+ * * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+/*
+ * * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
diff --git a/src/tools/rustfmt/tests/source/issue-5088/very_long_comment_wrap_comments_true.rs b/src/tools/rustfmt/tests/source/issue-5088/very_long_comment_wrap_comments_true.rs
new file mode 100644 (file)
index 0000000..00437f0
--- /dev/null
@@ -0,0 +1,13 @@
+// rustfmt-wrap_comments: true
+
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+
+/* - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+/* - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+
+/* * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+/* * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
diff --git a/src/tools/rustfmt/tests/source/issue_4823.rs b/src/tools/rustfmt/tests/source/issue_4823.rs
new file mode 100644 (file)
index 0000000..a008dd3
--- /dev/null
@@ -0,0 +1,5 @@
+macro_rules! m {
+() => {
+type Type;
+};
+}
diff --git a/src/tools/rustfmt/tests/source/issue_5027.rs b/src/tools/rustfmt/tests/source/issue_5027.rs
new file mode 100644 (file)
index 0000000..67beeb2
--- /dev/null
@@ -0,0 +1,7 @@
+// rustfmt-version: Two
+
+pub type Iter<'a, D> =                 impl       DoubleEndedIterator<Item = (SomethingSomethingSomethingLongType<D>)>+ ExactSizeIterator+ 'a;
+
+trait FOo {pub type Iter<'a, D> = impl        DoubleEndedIterator<Item = (SomethingSomethingSomethingLongType<D>)>+ ExactSizeIterator+ 'a;}
+
+impl Bar {pub type Iter<'a, D> = impl             DoubleEndedIterator<Item = (SomethingSomethingSomethingLongType<D>)>+ ExactSizeIterator+ 'a;}
\ No newline at end of file
diff --git a/src/tools/rustfmt/tests/source/issue_5086.rs b/src/tools/rustfmt/tests/source/issue_5086.rs
new file mode 100644 (file)
index 0000000..1644c9d
--- /dev/null
@@ -0,0 +1,2 @@
+#[cfg(any())]
+    type   Type :   Bound ;
\ No newline at end of file
diff --git a/src/tools/rustfmt/tests/target/comments-in-lists/format-doc-comments.rs b/src/tools/rustfmt/tests/target/comments-in-lists/format-doc-comments.rs
new file mode 100644 (file)
index 0000000..be31bf0
--- /dev/null
@@ -0,0 +1,96 @@
+// rustfmt-format_code_in_doc_comments: true
+
+// https://github.com/rust-lang/rustfmt/issues/4420
+enum Minimal {
+    Example,
+    //[thisisremoved thatsleft
+    // canbeanything
+}
+
+struct Minimal2 {
+    Example: usize,
+    //[thisisremoved thatsleft
+    // canbeanything
+}
+
+pub enum E {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant1,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant2,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub enum E2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    some_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    last_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+fn foo(
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    a: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    b: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn foo2(// Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn main() {
+    let v = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        1,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        2,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    let v2: Vec<i32> = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    match a {
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        b => c,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        d => e,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    }
+}
diff --git a/src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-false.rs b/src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-false.rs
new file mode 100644 (file)
index 0000000..80aea59
--- /dev/null
@@ -0,0 +1,85 @@
+// rustfmt-normalize_comments: true
+
+// https://github.com/rust-lang/rustfmt/issues/4909
+pub enum E {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant1,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant2,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub enum E2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    some_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    last_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+fn foo(
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    a: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    b: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn foo2(// Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn main() {
+    let v = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        1,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        2,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    let v2: Vec<i32> = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    // https://github.com/rust-lang/rustfmt/issues/4430
+    match a {
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        b => c,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        d => e,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    }
+}
diff --git a/src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-not-normalized.rs b/src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-not-normalized.rs
new file mode 100644 (file)
index 0000000..52315f4
--- /dev/null
@@ -0,0 +1,142 @@
+// rustfmt-wrap_comments: true
+
+// https://github.com/rust-lang/rustfmt/issues/4909
+pub enum E {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant1,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant2,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub enum E2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+pub enum E3 {
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    Variant1,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    Variant2,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+}
+
+pub struct S {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    some_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    last_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S3 {
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    some_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    last_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+}
+
+fn foo(
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    a: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    b: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn foo2(// Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn foo3(
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    a: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    b: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn main() {
+    let v = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        1,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        2,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    let v2: Vec<i32> = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    let v3 = vec![
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+        1,
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+        2,
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+    ];
+
+    // https://github.com/rust-lang/rustfmt/issues/4430
+    match a {
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        b => c,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        d => e,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    }
+
+    match a {
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+        b => c,
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+        d => e,
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+    }
+}
diff --git a/src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-true.rs b/src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-true.rs
new file mode 100644 (file)
index 0000000..e0bfcf0
--- /dev/null
@@ -0,0 +1,143 @@
+// rustfmt-normalize_comments: true
+// rustfmt-wrap_comments: true
+
+// https://github.com/rust-lang/rustfmt/issues/4909
+pub enum E {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant1,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant2,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub enum E2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+pub enum E3 {
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    Variant1,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    Variant2,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+}
+
+pub struct S {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    some_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    last_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S3 {
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    some_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    last_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+}
+
+fn foo(
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    a: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    b: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn foo2(// Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn foo3(
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    a: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    b: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn main() {
+    let v = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        1,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        2,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    let v2: Vec<i32> = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    let v3 = vec![
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+        1,
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+        2,
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+    ];
+
+    // https://github.com/rust-lang/rustfmt/issues/4430
+    match a {
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        b => c,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        d => e,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    }
+
+    match a {
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+        b => c,
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+        d => e,
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+    }
+}
diff --git a/src/tools/rustfmt/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_false.rs
new file mode 100644 (file)
index 0000000..f4801de
--- /dev/null
@@ -0,0 +1,33 @@
+// rustfmt-wrap_comments: false
+
+fn main() {
+    {
+        {
+            {
+                {
+                    {
+                        {
+                            {
+                                {
+                                    {
+                                        {
+                                            {
+                                                // - aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc
+
+                                                // * aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc
+
+                                                /* - aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc */
+
+                                                /* * aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc */
+                                            };
+                                        };
+                                    };
+                                };
+                            };
+                        };
+                    };
+                };
+            };
+        };
+    };
+}
diff --git a/src/tools/rustfmt/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs
new file mode 100644 (file)
index 0000000..b289c9f
--- /dev/null
@@ -0,0 +1,49 @@
+// rustfmt-wrap_comments: true
+
+fn main() {
+    {
+        {
+            {
+                {
+                    {
+                        {
+                            {
+                                {
+                                    {
+                                        {
+                                            {
+                                                // - aaaa aaaaaaaaa aaaaaaaaa
+                                                //   aaaaaaaaa aaaaaaaaa
+                                                //   bbbbbbbbbb bbbbbbbbb
+                                                //   bbbbbbbbb ccc cccccccccc
+                                                //   ccccccc cccccccc
+
+                                                // * aaaa aaaaaaaaa aaaaaaaaa
+                                                //   aaaaaaaaa aaaaaaaaa
+                                                //   bbbbbbbbbb bbbbbbbbb
+                                                //   bbbbbbbbb ccc cccccccccc
+                                                //   ccccccc cccccccc
+
+                                                /* - aaaa aaaaaaaaa aaaaaaaaa
+                                                 *   aaaaaaaaa aaaaaaaaa
+                                                 *   bbbbbbbbbb bbbbbbbbb
+                                                 *   bbbbbbbbb ccc cccccccccc
+                                                 *   ccccccc cccccccc */
+
+                                                /* * aaaa aaaaaaaaa aaaaaaaaa
+                                                 *   aaaaaaaaa aaaaaaaaa
+                                                 *   bbbbbbbbbb bbbbbbbbb
+                                                 *   bbbbbbbbb ccc cccccccccc
+                                                 *   ccccccc cccccccc */
+                                            };
+                                        };
+                                    };
+                                };
+                            };
+                        };
+                    };
+                };
+            };
+        };
+    };
+}
diff --git a/src/tools/rustfmt/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_false.rs
new file mode 100644 (file)
index 0000000..60beed1
--- /dev/null
@@ -0,0 +1,17 @@
+// rustfmt-wrap_comments: false
+
+// - some itemized block 1
+// - some itemized block 2
+
+// * some itemized block 3
+// * some itemized block 4
+
+/*
+ * - some itemized block 5
+ * - some itemized block 6
+ */
+
+/*
+ * * some itemized block 7
+ * * some itemized block 8
+ */
diff --git a/src/tools/rustfmt/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_true.rs
new file mode 100644 (file)
index 0000000..84fba4b
--- /dev/null
@@ -0,0 +1,17 @@
+// rustfmt-wrap_comments: true
+
+// - some itemized block 1
+// - some itemized block 2
+
+// * some itemized block 3
+// * some itemized block 4
+
+/*
+ * - some itemized block 5
+ * - some itemized block 6
+ */
+
+/*
+ * * some itemized block 7
+ * * some itemized block 8
+ */
diff --git a/src/tools/rustfmt/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_false.rs
new file mode 100644 (file)
index 0000000..d1bf44f
--- /dev/null
@@ -0,0 +1,37 @@
+// rustfmt-wrap_comments: false
+
+// Some text
+// - some itemized block 1
+// - some itemized block 2
+// Some more text
+// - some itemized block 3
+// - some itemized block 4
+// Even more text
+
+// Some text
+// * some itemized block 5
+// * some itemized block 6
+// Some more text
+// * some itemized block 7
+// * some itemized block 8
+// Even more text
+
+/*
+ * Some text
+ * - some itemized block 9
+ * - some itemized block 10
+ * Some more text
+ * - some itemized block 11
+ * - some itemized block 12
+ * Even more text
+ */
+
+/*
+ * Some text
+ * * some itemized block 13
+ * * some itemized block 14
+ * Some more text
+ * * some itemized block 15
+ * * some itemized block 16
+ * Even more text
+ */
diff --git a/src/tools/rustfmt/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_true.rs
new file mode 100644 (file)
index 0000000..f767491
--- /dev/null
@@ -0,0 +1,37 @@
+// rustfmt-wrap_comments: true
+
+// Some text
+// - some itemized block 1
+// - some itemized block 2
+// Some more text
+// - some itemized block 3
+// - some itemized block 4
+// Even more text
+
+// Some text
+// * some itemized block 5
+// * some itemized block 6
+// Some more text
+// * some itemized block 7
+// * some itemized block 8
+// Even more text
+
+/*
+ * Some text
+ * - some itemized block 9
+ * - some itemized block 10
+ * Some more text
+ * - some itemized block 11
+ * - some itemized block 12
+ * Even more text
+ */
+
+/*
+ * Some text
+ * * some itemized block 13
+ * * some itemized block 14
+ * Some more text
+ * * some itemized block 15
+ * * some itemized block 16
+ * Even more text
+ */
diff --git a/src/tools/rustfmt/tests/target/issue-5088/single_line_itemized_block_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5088/single_line_itemized_block_wrap_comments_false.rs
new file mode 100644 (file)
index 0000000..2cd85c7
--- /dev/null
@@ -0,0 +1,9 @@
+// rustfmt-wrap_comments: false
+
+// - some itemized block 1
+
+// * some itemized block 2
+
+/* - some itemized block 3 */
+
+/* * some itemized block 4 */
diff --git a/src/tools/rustfmt/tests/target/issue-5088/single_line_itemized_block_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5088/single_line_itemized_block_wrap_comments_true.rs
new file mode 100644 (file)
index 0000000..e9f343d
--- /dev/null
@@ -0,0 +1,9 @@
+// rustfmt-wrap_comments: true
+
+// - some itemized block 1
+
+// * some itemized block 2
+
+/* - some itemized block 3 */
+
+/* * some itemized block 4 */
diff --git a/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_false.rs
new file mode 100644 (file)
index 0000000..97bb773
--- /dev/null
@@ -0,0 +1,19 @@
+// rustfmt-wrap_comments: false
+
+//
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+
+//
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+
+/*
+ * - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+/*
+ * - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+
+/*
+ * * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+/*
+ * * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
diff --git a/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs
new file mode 100644 (file)
index 0000000..c8af838
--- /dev/null
@@ -0,0 +1,27 @@
+// rustfmt-wrap_comments: true
+
+//
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+//   tempor incididunt ut labore et dolore magna aliqua.
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+//   tempor incididunt ut labore et dolore magna aliqua.
+
+//
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+//   tempor incididunt ut labore et dolore magna aliqua.
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+//   tempor incididunt ut labore et dolore magna aliqua.
+
+/*
+ * - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ *   tempor incididunt ut labore et dolore magna aliqua. */
+/*
+ * - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ *   tempor incididunt ut labore et dolore magna aliqua. */
+
+/*
+ * * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ *   tempor incididunt ut labore et dolore magna aliqua. */
+/*
+ * * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ *   tempor incididunt ut labore et dolore magna aliqua. */
diff --git a/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_wrap_comments_false.rs
new file mode 100644 (file)
index 0000000..75cc42c
--- /dev/null
@@ -0,0 +1,17 @@
+// rustfmt-wrap_comments: false
+
+//
+// - some itemized block 1
+// - some itemized block 2
+
+//
+// * some itemized block 3
+// * some itemized block 4
+
+/*
+ * - some itemized block 5
+ * - some itemized block 6 */
+
+/*
+ * * some itemized block 7
+ * * some itemized block 8 */
diff --git a/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_wrap_comments_true.rs
new file mode 100644 (file)
index 0000000..ef2c8f9
--- /dev/null
@@ -0,0 +1,17 @@
+// rustfmt-wrap_comments: true
+
+//
+// - some itemized block 1
+// - some itemized block 2
+
+//
+// * some itemized block 3
+// * some itemized block 4
+
+/*
+ * - some itemized block 5
+ * - some itemized block 6 */
+
+/*
+ * * some itemized block 7
+ * * some itemized block 8 */
diff --git a/src/tools/rustfmt/tests/target/issue-5088/very_long_comment_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5088/very_long_comment_wrap_comments_false.rs
new file mode 100644 (file)
index 0000000..c826cc5
--- /dev/null
@@ -0,0 +1,13 @@
+// rustfmt-wrap_comments: false
+
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+
+/* - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+/* - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+
+/* * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+/* * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
diff --git a/src/tools/rustfmt/tests/target/issue-5088/very_long_comment_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5088/very_long_comment_wrap_comments_true.rs
new file mode 100644 (file)
index 0000000..7f764db
--- /dev/null
@@ -0,0 +1,21 @@
+// rustfmt-wrap_comments: true
+
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+//   tempor incididunt ut labore et dolore magna aliqua.
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+//   tempor incididunt ut labore et dolore magna aliqua.
+
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+//   tempor incididunt ut labore et dolore magna aliqua.
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+//   tempor incididunt ut labore et dolore magna aliqua.
+
+/* - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ *   tempor incididunt ut labore et dolore magna aliqua. */
+/* - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ *   tempor incididunt ut labore et dolore magna aliqua. */
+
+/* * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ *   tempor incididunt ut labore et dolore magna aliqua. */
+/* * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ *   tempor incididunt ut labore et dolore magna aliqua. */
diff --git a/src/tools/rustfmt/tests/target/issue-5095.rs b/src/tools/rustfmt/tests/target/issue-5095.rs
new file mode 100644 (file)
index 0000000..6981a65
--- /dev/null
@@ -0,0 +1,27 @@
+// rustfmt-wrap_comments: true
+
+pub mod a_long_name {
+    pub mod b_long_name {
+        pub mod c_long_name {
+            pub mod d_long_name {
+                pub mod e_long_name {
+                    pub struct Bananas;
+                    impl Bananas {
+                        pub fn fantastic() {}
+                    }
+
+                    pub mod f_long_name {
+                        pub struct Apples;
+                    }
+                }
+            }
+        }
+    }
+}
+
+/// Check out [my other struct] ([`Bananas`]) and [the method it has].
+///
+/// [my other struct]: a_long_name::b_long_name::c_long_name::d_long_name::e_long_name::f_long_name::Apples
+/// [`Bananas`]: a_long_name::b_long_name::c_long_name::d_long_name::e_long_name::Bananas::fantastic()
+/// [the method it has]: a_long_name::b_long_name::c_long_name::d_long_name::e_long_name::Bananas::fantastic()
+pub struct A;
diff --git a/src/tools/rustfmt/tests/target/issue_4823.rs b/src/tools/rustfmt/tests/target/issue_4823.rs
new file mode 100644 (file)
index 0000000..de17467
--- /dev/null
@@ -0,0 +1,5 @@
+macro_rules! m {
+    () => {
+        type Type;
+    };
+}
diff --git a/src/tools/rustfmt/tests/target/issue_5027.rs b/src/tools/rustfmt/tests/target/issue_5027.rs
new file mode 100644 (file)
index 0000000..26d7717
--- /dev/null
@@ -0,0 +1,17 @@
+// rustfmt-version: Two
+
+pub type Iter<'a, D> = impl DoubleEndedIterator<Item = (SomethingSomethingSomethingLongType<D>)>
+    + ExactSizeIterator
+    + 'a;
+
+trait FOo {
+    pub type Iter<'a, D> = impl DoubleEndedIterator<Item = (SomethingSomethingSomethingLongType<D>)>
+        + ExactSizeIterator
+        + 'a;
+}
+
+impl Bar {
+    type Iter<'a, D> = impl DoubleEndedIterator<Item = (SomethingSomethingSomethingLongType<D>)>
+        + ExactSizeIterator
+        + 'a;
+}
diff --git a/src/tools/rustfmt/tests/target/issue_5086.rs b/src/tools/rustfmt/tests/target/issue_5086.rs
new file mode 100644 (file)
index 0000000..7a0be06
--- /dev/null
@@ -0,0 +1,2 @@
+#[cfg(any())]
+type Type: Bound;
index c1719a9ffe80c7530698b4ef7b70b78b07d3e8f1..bc33284f31e2e903b2c3342da6f835cb6ce7e1f7 100644 (file)
@@ -82,8 +82,8 @@
     "bitflags",
     "block-buffer",
     "block-padding",
-    "byteorder",
     "byte-tools",
+    "byteorder",
     "cc",
     "cfg-if",
     "chalk-derive",
     "memmap2",
     "memoffset",
     "miniz_oxide",
-    "num_cpus",
     "num-integer",
     "num-traits",
+    "num_cpus",
     "object",
     "odht",
     "once_cell",
     "serde_json",
     "sha-1",
     "sha2",
-    "smallvec",
     "sharded-slab",
+    "smallvec",
     "snap",
     "stable_deref_trait",
     "stacker",
     "tracing-subscriber",
     "tracing-tree",
     "typenum",
+    "unic-char-property",
+    "unic-char-range",
+    "unic-common",
+    "unic-emoji-char",
+    "unic-ucd-version",
     "unicode-normalization",
     "unicode-script",
     "unicode-security",
index 7fae9bf0f69b3df1d06c878b18135121d4689e26..203e33e8b1f38728d3398f19aa55a0d818c9a20d 100644 (file)
@@ -7,9 +7,8 @@
 
 const ENTRY_LIMIT: usize = 1000;
 // FIXME: The following limits should be reduced eventually.
-const ROOT_ENTRY_LIMIT: usize = 983;
+const ROOT_ENTRY_LIMIT: usize = 982;
 const ISSUES_ENTRY_LIMIT: usize = 2310;
-const PARSER_LIMIT: usize = 1012;
 
 fn check_entries(path: &Path, bad: &mut bool) {
     let dirs = walkdir::WalkDir::new(&path.join("test/ui"))
@@ -22,13 +21,10 @@ fn check_entries(path: &Path, bad: &mut bool) {
             // Use special values for these dirs.
             let is_root = path.join("test/ui") == dir_path;
             let is_issues_dir = path.join("test/ui/issues") == dir_path;
-            let is_parser = path.join("test/ui/parser") == dir_path;
             let limit = if is_root {
                 ROOT_ENTRY_LIMIT
             } else if is_issues_dir {
                 ISSUES_ENTRY_LIMIT
-            } else if is_parser {
-                PARSER_LIMIT
             } else {
                 ENTRY_LIMIT
             };
index 79f82f6b8e0ceb99fe26d976bae0285f53a07473..bb120e876c620345b6e6704bf5eb2578a2b044ed 100644 (file)
@@ -1 +1 @@
-1.58.0
+1.59.0